jquery object inside an object literal - javascript

i am trying not to repeat the selector and get to its children via a the same objects parentElment declared variable.
I tried:
testimonialsBelt={
parentElment:$(".testimonialsCntnr ul"),
childrenElem:this.parentElment.children().length
}
I also tried:
testimonialsBelt={
parentElment:$(".testimonialsCntnr ul"),
childrenElem:$("testimonialsBelt.parentElment").children().length
}
but i keep on getting a undefined when calling alert(testimonialsBelt.childrenElem).
is there anyway to get the jquery object with object literals?
What is the rule? when can i use this and when must i have the full path? (in this case testimonialsBelt.parentElment).
i am trying to have all these variables in one object called testimonialsBelt. i know i can do this with loose javaScript.
Thanks

In object literals, you can only use this to refer to the object that you're declaring inside of a function. Try the following:
var testimonialsBelt = {
parentElment: $(".testimonialsCntnr ul"),
childrenElem: function() {
return this.parentElment.children().length;
}
};
The difference in calling childrenElem is that instead of using alert(testimonialsBelt.childrenElem), you would instead have alert(testimonialsBelt.childrenElem()).
Otherwise, this refers to the current scope that you are in (typically window if you are declaring the object literal as a global).
Addressing your edit: I'm not sure what you mean by "loose javascript," but I assume you mean as simple as possible. In which case, you can try the following, although I'm not a big fan of the method. It's more verbose, but is easy to understand.
var testimonialsBelt = {
parentElment: $(".testimonialsCntnr ul")
};
testimonialsBelt.childrenElem = parentElment.children().length;
This gives you an object where childrenElem is static (it doesn't change) and avoids calling $(".testimonialsCntnr ul") twice. However, if you expect $(".testimonialsCntnr ul").children() to change, then you will need to use my first example.

In JavaScript (not ECMAScript) you can use this:
testimonialsBelt={
parentElment:#1=$(".testimonialsCntnr ul"),
childrenElem:#1#.children().length
}

Related

Use passed variable name as part of another variable name

blah('A');
function blah(letter){
arrayA.push('something');
}
I want to push something to an array where the name of the array is 'array' plus a letter being passed to it.
I can console out 'arrayA' fine:
console.log('array'+${letter})
But if I try to build the array name, the same logic doesn't work:
array${letter}.push('something')
In the browser (where the global objects, functions, and variables become members of the window object) you can create and access dynamically named objects using the bracket notation.
Were you looking for something like this?
function blah(letter){
window['array' + letter] = [];
window['array' + letter].push('something');
}
blah('A');
After this you can access and use the newly created array (arrayA) as usual.
arrayA.push('something else');
In node you can probably achieve this using global instead of window.
Try it and forget it (or replace the 3 occurrences of window with global for testing with node.js):
function test(name,value){
if(!window["array"+name])
window["array"+name]=[];
window["array"+name].push(value);
}
try{console.log(arrayA);}catch(e){console.log("arrayA missing: "+e);}
test("A",10);
try{console.log(arrayA);}catch(e){console.log("arrayA missing: "+e);}
test("A",20);
try{console.log(arrayA);}catch(e){console.log("arrayA missing: "+e);}
window is the global scope in a browser, and generally you should not rely on global variables without a good reason. They lack context (that is why they are 'global'), making it hard to tell where they belong, what they are and where they come from. That is something what most programming paradigms advise against.
The thing also works with node.js, just it has global as global context, you can paste this snippet into https://www.tutorialspoint.com/execute_nodejs_online.php as a test, replace the 3 window-s, and it will work (you can of course wrap it into a proper module too, just that is more work). What is written above against the usage of global variables stays true for node.js too. Do not use the global context especially if you are developing modules.
However, instead of window, the syntax works with any object too, and that would be considered okay:
var obj={};
console.log(obj.something);
obj['some'+'thing']=10;
console.log(obj.something);
So you can freely have your own 'context' object (if you write the var obj={}; line in the top-level of a module, it will be available everywhere in that module, and it will not interfere with the outside world), and create/access its members using this array-like syntax (obj['something']), constructing the names on the fly when necessary.

How does the length property work?

I'm writing code that needs to reference this inside a prototype, but it cannot be a function. Javascript won't let me do this, but it seems like the length property of arrays and strings does this. I know that length is built-in, and my code is not, but if I can, how do I implement this?
I tried:
String.prototype.prototypeName = (function(aThing){
//Do whatever I need to do here
})(this);
But that references to the global object, because this is called outside of the function.
String.prototype.prototypeName = function(aThing){
//Do whatever I need to do here referencing this
};
However, that is a function, and I can't have that.
I can't have a function because the user can call the function and use typeof on it, and the prototype is supposed to return a string.
For example:
String.prototype.reverse = "Put something that is the reversed string (or this)";
console.log("Stuff"); //"ffutS"
console.log("Anything"); //gnihtynA
You can use a Javascript getter to access a computed property without calling a prototype function. Note this is IE9+ only.

call jQuery lib function identified with variable

I build recurring html with jQuery functions.
I'd like to give my functions more flexibility with $.append(), $.before(), and $.after(), etc.
Currently, I do something like
$.fn.appendRecurringHTML = function(domInsertMethod, domInsertID, htmlToInsert) {
if(domInsertMethod == 'append'){
$(domInsertID).append(htmlToInsert);
}
else if(domInsertMethod == 'before'){
$(domInsertID).before( ...
}
but I'd prefer (pseudo)
$.fn.appendRecurringHTML = function(domInsertMethod, domInsertID, htmlToInsert) {
$(domInsertID).window[domInsertMethod](htmlToInsert);
}
but that doesn't work for me.
Is this possible? If so, how?
Just use
$(domInsertID)[domInsertMethod](htmlToInsert);
DEMO: http://jsfiddle.net/UZKLY/
This works because the result of $(domInsertID) (or any $()) is a jQuery object, so it has properties and methods you want to call. Normally, you use dot notation to access them, but bracket notation is just as valid to use. Bracket notation is the only way to dynamically get a property/method (and allows for invalid identifier characters).
But be careful, because technically any method name could be provided, and therefore called. So it's up to you if you want to allow it or not.
As it stands, it doesn't make sense to add to $.fn, because you're not actually using the selected elements from the selector. It makes more sense to me to use this setup:
$.appendRecurringHTML = function(domInsertMethod, domInsertID, htmlToInsert) {
$(domInsertID)[domInsertMethod](htmlToInsert);
};
And you would call it like:
$.appendRecurringHTML("after", "#id", "html");
But if you wanted to use the selected element(s) as the target(s), you could use:
$.fn.appendRecurringHTML = function(domInsertMethod, htmlToInsert) {
return this.each(function () {
$(this)[domInsertMethod](htmlToInsert);
});
};
And call it like:
$("selector").appendRecurringHTML("after", "html");
DEMO: http://jsfiddle.net/UZKLY/1/
It preserves chaining, and will be applied to all matched elements.
Try this:
$(domInsertID)[domInsertMethod](htmlToInsert);
This approach creates jQuery object with your domInsertID first. Than selects domInsertMethod from that object's prototype chain and executes the method using htmlToInsert.

Accessing Object's Data Via Another Variable Name

It's super late and my mind is blanking right now, but let's say I have variable filename and it's storing the name of another variable marker. The variable marker is an array and contains the object & property position: new google.maps.LatLng(42.2550,-114.3221).
I've been stupidly trying to access it via filename.position which of course returns undefined, since it's searching the literal filename for a 'position' property that does not exist.
But how could I pull marker.position by using filename? Is there some nifty jQuery trick for, uh, 'resolving' a variable to its contents? I'm brain fried. I know I've done this before.
If it's possible in your script, you can store the data not just in variable, but in a property of some object (usually it's more convenient to use global one).
For example
var myObj = {};
myObj.marker = new google.maps.LatLng(42.2550,-114.3221); // or anything else
Then you will be able to get this property using a variable like this:
myObj[filename].position
In this case i would also recomment to check for myObj[filename] existance using typeof structure, just to make sure such property exists in myObj.
if (typeof myObj[filename] !== "undefined") {
// do something
}
As apsillers noted, you could use global window object for this as well. But if your marker variable was defined inside some other function (i.e. not global), you won't be able to access it with window.marker or window[filename] as it will be out of scope.
Second way is to use eval() function which i'd strongly recommend to avoid.
Try this :
window[filename].position;

Object has no method 'apply'

I am creating a few DOM elements dynamically like,
var anchorElement = jQuery('<a />',{text:property.text});
var liElement = jQuery('<li />',{"class":"navlink_"+i,id:"navlink_"+i});
anchorElement.on('click',property.fnctn);
liElement.append(anchorElement);
parentID.append(liElement);
Where property is a JSON object.
property.text is the text that I want to put into anchor element. (Works fine)
I want to attach a click event handler to that anchor element.
The function that needs to be bound to that element is specified in JSON and we can access it like
property.fnctn
The following line should bind the event handler to the anchor element.
anchorElement.on('click',property.fnctn);
This was not working so I tried converting it into string like,
anchorElement.on('click',property.fnctn.toString());
No Success...
When I click on this link, the error is logged in the console
The object has no method 'apply'.
What is the reason...???
I am able to get it working with a slight work around like
anchorElement.attr('onclick',property.fnctn+"()");
Above statement works, but I want to know why .on() API is not working.
Thanks :)
AÐitya.
Update:
Youve said that property.actfn is a string, "paySomeoneClick". It's best not to use strings for event handlers, use functions instead. If you want the function paySomeoneClick, defined in the string, to be called, and if that function is global, you can do this:
anchorElement.on('click',function(event) {
return window[property.fnctn](event);
});
That works because global functions are properties of the global object, which is available via window on browsers, and because of the bracketed notation described below.
If the function is on an object you have a reference to, then:
anchorElement.on('click',function(event) {
return theObject[property.fnctn](event);
});
That works because in JavaScript, you can access properties of objects in two ways: Dotted notation with a literal property name (foo.bar accesses the bar propety on foo) and bracketed notation with a string property name (foo["bar"]). They're equivalent, except of course in the bracketed notation, the string can be the result of an expression, including coming from a property value like property.fnctn.
But I would recommend stepping back and refactoring a bit so you're not passing function names around in strings. Sometimes it's the right answer, but in my experience, not often. :-)
Original answer:
(This assumed that property.fnctn was a function, not a string. But may be of some use to someone...)
The code
anchorElement.on('click',property.fnctn);
will attach the function to the event, but during the call to the function, this will refer to the DOM element, not to your property object.
To get around that, use jQuery's $.proxy:
anchorElement.on('click',$.proxy(property.fnctn, property));
...or ES5's Function#bind:
anchorElement.on('click',property.fnctn.bind(property));
...or a closure:
anchorElement.on('click',function(event) {
return property.fnctn(event);
});
More reading (on my blog):
Mythical methods
You must remember this
Closures are not complicated

Categories

Resources