Can't read property of undefined, but it's clearly not undefined - templates

This code
div
each dum in dummy
div !{JSON.stringify(dum)}
outputs, as seen below, an object {"prop":3} So obviously, prop should be accessible via
div !{dum.prop}
div !{dum['prop']}
but it suddenly becomes undefined.
The dummy is passed by node
var dummy = [];
dummy[10] = {prop:3};
res.render('dummy.jade', {
dummy: dummy
});
What am I doing wrong?
PS: Converting the object to Javascript even works

I found out that the problem is that *sparse array*s don't work with Jade.
So
dummy[10] = {prop:3};
doesn't work but
dummy[0] = {prop:3};
does.
https://github.com/visionmedia/jade/issues/1445

Related

How do I get a custom element definition without instantiating it?

After looking at the custom element spec, it's not immediately obvious how I get a reference to a custom element definition without first instantiating it (which can be problematic). Is there a way to directly reference a custom element's prototype?
More concretely, if I have:
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() { // some heavy operation };
document.registerElement('x-foo', {prototype: proto});
At some point later, I would love to reference the prototype with something like:
// wish
var XFoo = document.getElementDefinition('x-foo');
But instead the only way I've come up with is:
// reality
var XFoo = document.createElement('x-foo').__proto__;
This is especially problematic when trying to write tests against heavy components - as there's no way to stub out the heavy behavior (with something like XFoo.createdCallback = // stub; before the original method is actually called.
If you have reference to the constructor of the custom element, you can use it to access the prototype.
var XFoo = document.registerElement('x-foo', {prototype: proto});
XFoo.prototype // this will give u access to the prototype object.
there's no way to stub out the heavy behavior
Use a function reference rather than an anonymous function:
proto.createdCallback = model.foo;
define it:
var model = {};
model.foo = function(){/*some heavy operation*/};
then stub it by redefining it:
var XModel = {};
XModel.foo = function(){/*stub*/};
and reference it in the test:
XFoo.createdCallback = XModel.foo;
References
AOP Aspect of JavaScript
AJAX Interception
Intro to Aspect Oriented Programming

Should I duplicate test data and assert data?

The question is probably best asked with a simple example:
var myObj = { name: 'John' };
var copiedObj = ObjectCopier.copy(myObj);
copiedObj.name.should.equal('John'); // Hard code 'John' twice
copiedObj.name.should.equal(myObj.name); // Reference the original value
Is one method preferred over the other? Assuming the value passed in is what I expect to be returned, is there any harm in the 2nd assert? Does it even matter?
In more complex cases you won't be able to duplicate an object completely - and you wouldn't want to. it would be better written this way:
var OBJ_NAME = 'John'
var myObj = { name: OBJ_NAME };
var copiedObj = ObjectCopier.copy(myObj);
copiedObj.name.should.equal(OBJ_NAME);
this way you're not duplicating any code/defines, and you can also make tests such as:
myObj.name.should.equal(OBJ_NAME);
to test for the object copier not changing the original object either (which either of your lines won't test for).

Issue with __nextSuper

Moving from Ember 1.5.1 to 1.6.0, I've run into an issue with __nextSuper (which has been changing in the last few versions). You can see the offending code here.
And here's the relevant Ember code:
function wrap(func, superFunc) {
function superWrapper() {
var ret, sup = this.__nextSuper; // THIS LINE
this.__nextSuper = superFunc;
ret = apply(this, func, arguments);
this.__nextSuper = sup;
return ret;
}
superWrapper.wrappedFunction = func;
superWrapper.wrappedFunction.__ember_arity__ = func.length;
superWrapper.__ember_observes__ = func.__ember_observes__;
superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
superWrapper.__ember_listens__ = func.__ember_listens__;
return superWrapper;
};
What happens is, at some point, the superWrapper function gets called with window as the this value. So when I reach the line marked above, this.__nextSuper comes out to be undefined. But rather than sup simply being undefined, it throws the following error:
TypeError: Cannot read property '__nextSuper' of undefined
The thing is, when I pause in the debugger, this is defined (it's the window object). And when I paste var ret, sup = this.__nextSuper; into the console, it works as expected. And, if I go up the stack frame and check the this value, it's exactly what I expect. So I have no idea why superWrapper suddenly has a bad this value.
Finally, the most interesting part, this only happens in the browser; it works fine in PhantomJS. The changelog didn't seem to list anything to do with __nextSuper as a breaking bugfix, but obviously something has changed. How can I solve this issue?
Ember 1.6 looks to have a requirement on super method being called from the scope of the object hosting the super method (probably a bug, but I'm not positive). In your case you'd want to keep track of the scope, then call the super method using it:
(scope is the object that houses isEqual)
var scope = meta.isEqual ? meta : this.get('store').attributeTypeFor(meta.type);
if (scope.isEqual(server, value)) { ...
instead of (scope is window and explodes in 1.6+)
var isEqual = meta.isEqual || this.get('store').attributeTypeFor(meta.type).isEqual;
if (isEqual(server, value)) { ...
Here's a super simple example showing the problem (1.6+): http://emberjs.jsbin.com/yelesahe/1/edit
And working in 1.5.1: http://emberjs.jsbin.com/zedevudo/1/edit
Issue: https://github.com/emberjs/ember.js/issues/5198

Array of tuples in Swift

I have a function:
func parseJSON3(inputData: NSData) -> NSArray {
var tempDict: (id:Int, ccomments:Int, post_date:String, post_title:String, url:String) = (id: 0, ccomments: 0, post_date: "null", post_title: "null", url: "null")
var resultArray: (id:Int, ccomments:Int, post_date:String, post_title:String, url:String)[] = []
var error: NSError?
var jsonDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
var firstArray = jsonDictionary.objectForKey("locations") as NSArray
for dict in firstArray {
tempDict.id = dict.valueForKey("ID") as Int
tempDict.ccomments = dict.valueForKey("ccomments") as Int
tempDict.post_date = dict.valueForKey("post_date") as String
tempDict.post_title = dict.valueForKey("post_title") as String
tempDict.url = dict.valueForKey("url") as String
resultArray.append(tempDict)
}
return resultArray
}
In line
resultArray.append(tempDict)
I have an error:
Missing argument for parameter 'ccomments' in call
Why? Help please....
It looks to me like resultArray.append() is treating the tuple a little bit like a variadic parameter, and trying to expand the tuple to match its own arguments. It's complaining about your second parameter because it's only expecting one. I haven't seen this behavior for Array.append() documented anywhere, so I would say it's a bug in Swift.
Using the appending operator += doesn't seem to have that issue:
resultArray += tempDict
So this is pretty wild - not sure if I would qualify it as a bug or as undocumented behavior, but it's definitely something that should be on the radar for a fix / clarification!
The situation is that append is treating your argument tempDict (which we would expect to be the only argument to an Array method that takes a single member and adds it to the collection) as the first argument in a signature where it is looking for 5 arguments (!), one for each member of the Tuple type that the Array holds.
See the following for some interesting behavior (including assigning a label to the single member of a 1-member 'Tuple' ??) ->
var arrayOne: Array<String> = []
arrayOne.append("hi")
println(arrayOne[0]) // hi
var arrayTwo: Array<(String)> = [] // where (String) is a single-member Tuple
arrayTwo.append("hi")
println(arrayTwo[0]) // hi
println(arrayTwo[0].0) // hi -> using .0 subscript to access the first member of the Tuple
// wanna see something crazy? remember arrayOne, that holds members of type String?
println(arrayOne[0].0) // hi -> this Array does not hold Tuples, but it looks like we can still treat its members like "single-member Tuples"?
var arrayThree: Array<(str: String)> = [] // members of the Array are single-member Tuples with the label 'str' for their member
arrayThree.append(str: "hi") // now we can't use append without providing the label 'str', acting as what looks like an argument label?
var byeString = "bye"
var byeTuple = ("bye")
arrayThree += byeString // += doesn't care about the label, and will take either a String or a single-member Tuple holding a String
arrayThree += byeTuple
println(arrayThree[0]) // hi
println(arrayThree[0].0) // hi
println(arrayThree[0].str) // hi -> accessing the single member of the Tuple by its label
...so in your case, where you are seeing the error with append what it wants you to do is (using the labels you used to declare the Tuple as something that looks like argument labels):
var resultArray: (id:Int, ccomments:Int, post_date:String, post_title:String, url:String)[] = []
...
resultArray.append(id: someIntValue, ccomments: someOtherIntValue, post_date: someStringValue, post_title: someOtherStringValue, url: someAnotherStringValue)
...and of course, as discussed, you can avoid doing that by just using += instead
Crazy stuff! could be by design to serve some purpose, could be a consequence of protocol inheritance that wasn't meant to have this effect... would be interesting to know the answer!
resultArray.append() seems to be taking tempDict as the first tuple element (id).
Changing it to :
resultArray += tempDict
seems to compile and work.
I'm not sure why append() doesn't behave the same way, maybe you can file a bug!

How to alter Bootstrap's typeahead selected value?

I retrieve the selected typeahead value by using this method:
$('ul.typeahead li.active').data('value');
I then set this equal to a variable, like so,
var foo = $('ul.typeahead li.active').data('value');
However, if I try and do something like this:
var foo = $('ul.typeahead li.active').data('value').replace( /\([^\)]+\)$/, '' );
it won't seem to update the value of foo even though when I console.log(foo) it actually is showing the right value for foo.
Can you please tell me what I could do to resolve this?
Data returns an object and not a String
Try :
var foo = $('ul.typeahead li.active').data('value').first.replace( /\([^\)]+\)$/, '' );