javascript object reference by shortcuts - javascript

I have very very valuable , so i tried to make shortcuts like this :
LIVE example : http://jsfiddle.net/nqeUN/
var d = "document" ,
t = "getElementByTagName" ,
d = "div" ,
oc = "onclick";
d[t](d)[0].oc = function(){
alert("1");
}
but it's not working , what is the reason? i can see in Google plus api that all the objects are defined like this , as strings , how do they make it work?

There are a couple of problems you need to address
You have two values bound to d: "document" and "div".
It's getElementsByTagName
The getElementsByTagName function needs a DOM entry point not a string. Switch the first d to document
When using dot notation for .oc it will bound to the property oc in stead of the value of the variable oc. Use [] notation instead
Code:
var d = document ,
t = "getElementsByTagName" ,
div = "div" ,
oc = "onclick";
d[t](div)[0][oc] = function(){
alert("1");
}
Working Fiddle: http://jsfiddle.net/nqeUN/1/

Strings will work for properties, but not variable names. You also define d twice, and have the wrong method name. You would be able to do this:
var d = 'document', t = 'getElementsByTagName', div = 'div', oc = 'onclick';
window[d][t](div)[0][oc] = function() { ... }
But this really reduces readability and isn't necessary. You could run your code through a minimizer to get this automatically and still maintain readable dev code.

d is a string, not document.
You should write var d = document to get the actual document object.
However, you should not do this yourself; it makes utterly unreadable code.
Instead, you should develop normal, readable Javascript, then use a minifier (such as Microsoft AjaxMin or Google Closure Compiler) to automatically shrink your code as much as possible in production.

if you replace the values in your example, you'll see:
"document".getElementsByTagName("document").onclick = function() {};
1.) d should be set to the global document reference, not the string 'document'
var d = window.document;
2.) getElementsByTagName returns nodes that match the given tag name that are contained within the given DOM node, so passing 'document' as a string would look for HTML elements named 'document'. you need to find the divs, for example:
d.getElementsByTagName("div"); // All the 'div' elements in the document
3.) For method names to be used as strings, they need to be in brackets
document[ t ]; // document.t won't work, t is not a member
4.) Once you've accessed the nodes you care about, you need to loop through them to add event handlers to each element
var d = document.getElementsByTagName("div"),
i = 0,
len = d.length;
for ( ; i < len; i++ ) {
(function() {
// do something with d[i], the current element in the loop
})(i)
}
hope that helps! cheers.

Because the variable d is a string; and the String object does not have a getElementByTagName method.
Furthermore, your d variable is being redeclared as the string div; so you need to assign that to a different name:
var d = "document" ,
t = "getElementByTagName" ,
e = "div" ,
oc = "onclick";
Then, you need to access the window object, and retrieve the document attribute of it:
window[d]
to retrieve the Document element, and then retrieve the getElementsByTagName method from it (read getElements not getElement)
window[d][t]
You then invoke it and pass it the name of the element, retrieve the first value of the returned array, and assign a function to its onclick attribute:
window[d][t](e)[0][oc] = function () {
alert("1");
};

var d = "document",
t = "getElementsByTagName" ,
div = "div" ,
oc = "onclick";
window[d][t](div)[0][oc] = function(){
alert("1");
}
) document is not a string
) document['getElementByTagName'].call(this, 'div')
) . accessor changed to bracket because oc is a string not a property
) you used to var d twice
) it's getElementsByTagName, plural Elements

Full string madness http://jsfiddle.net/nqeUN/8/
"document"["gg"]()["getElementsByTagName"]("div")["0"]["onclick"] = function(){alert(1);};

Related

Get class attribute list [duplicate]

I know you can SET multiple css properties like so:
$('#element').css({property: value, property: value});
But how do I GET multiple properties with CSS?
Is there any solution at all?
jquery's css method (as of 1.9) says you can pass an array of property strings and it will return an object with key/value pairs.
eg:
$( elem ).css([ 'property1', 'property2', 'property3' ]);
http://api.jquery.com/css/
Easiest way? Drop the jQuery.
var e = document.getElementById('element');
var css = e.currentStyle || getComputedStyle(e);
// now access things like css.color, css.backgroundImage, etc.
You can create your own jQuery function to do this:
​
//create a jQuery function named `cssGet`
$.fn.cssGet = function (propertyArray) {
//create an output variable and limit this function to finding info for only the first element passed into the function
var output = {},
self = this.eq(0);
//iterate through the properties passed into the function and add them to the output variable
for (var i = 0, len = propertyArray.length; i < len; i++) {
output[propertyArray[i]] = this.css(propertyArray[i]);
}
return output;
};
Here is a demo: http://jsfiddle.net/6qfQx/1/ (check your console log to see the output)
This function requires an array to be passed in containing the CSS properties to look-up. Usage for this would be something like:
var elementProperties = $('#my-element').cssGet(['color', 'paddingTop', 'paddingLeft']);
console.log(elementProperties.color);//this will output the `color` CSS property for the selected element

Alternative to using eval()

I've heard a lot of rumblings about how "evil" or even "misunderstood" the eval function is, so I've decided to remove it from my code. The problem is I don't know what to replace it with.
Here's a quick rundown of my current code. I have a series of arrays (just 2 for the example below) declared at the beginning, and then based on a button click one of them gets loaded into a variable that is passed into a function.
Here's some basic HTML
<div class="button" data-name="button1">Button1</div>
<div class="button" data-name="button2">Button2</div>
and the JS (with jQuery)
var butName = null;
var eArray = null;
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = eval(butName + "Logo");
});
Doing it this way assigns the array to the variable and not just a string that says "butnameLogo" which is why I used eval. But I'm looking to get away from that.
I know I can add a new attribute to the html and just retrieve that for the variable but I don't want to add more html when I can possibly do it with JS.
I've also tried making an object with strings loaded into it as seen in this answer: https://stackoverflow.com/a/16038097/1621380 but that resulted in just a string again, and not assigning a variable.
Wondering if you smart people have any better suggestions!
Replace
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
with an object, where the keys are your button names:
var buttonLogos = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
Then instead of the eval you can simply do
eArray = buttonLogos[butName]
(or buttonLogos[butName + "Logo"] if you want to call the keys button1Logo and button2Logo, but I can't really see the point now that they are nicely contained within a buttonLogos object)
Use an object:
var butName = null;
var buttonsLogos = {
button1: ["..path/to/pic1.png", "..path/to/pic2.png"],
button2: ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = buttonsLogos[butName];
});
Consider making the data available as properties of an object, then you can control access to the object through scope and only need one (global?) variable for all such data.
If global scope is needed, then:
var dataObj = {
button1Logo: ["..path/to/pic1.png","..path/to/pic2.png"],
button2Logo: ["..path/to/pic3.png","..path/to/pic4.png"]
}
and later:
var eArray = dataObj[this.data-name + 'Logo'];
You may want to call the data object something more meaningful than dataObj though.
The best option is to define an object which holds all our button paths:
var buttons = {
"1": ["..path/to/pic1.png", "..path/to/pic2.png"],
"2": ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/* give a butName */
var butName = $(this).attr("data-name");
/* give the array from the button */
var eArray = buttons[butName];
});
If your variables reside in the global scope, you could use the bracket notation to access them:
eArray = window[butName + "Logo"];
Note that this solution is not recommended. The first code sample is much cleaner and more maintainable.
Imagine a situation where you would have to move all the code into a 'deeper' context (!= global context). Nothing would work anymore.
You can do this very nicely with arrays and array indexes. You needn't find and use variable names at all. Even your data- attributes are unnecessary.
var eArray;
var buttonLogos = [
["..path/to/pic1.png","..path/to/pic2.png"],
["..path/to/pic3.png","..path/to/pic4.png"]
];
var buttons = $(".button").mouseup(function(){
var idx = buttons.index(this);
eArray = buttonLogos[idx];
});
The key line in this is buttons.index(this). This method call gets the position of the current element among all the elements matched by $(".button"). We then use this index to select the relevant element from the buttonLogos array.
You're taking a very circuitous route by using eval here.
You'd be much better off doing something like this:
var paths = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give the array from the button*/
eArray = paths[$(this).attr("data-name")];
});
eval should only be used if you need to execute code (usually from a 3rd party source), and even that is rare. If you ever find yourself saying "i should use eval here", there's almost definitely a better alternative, and you should try and find it.

How to get the variable passed through the function JavaScript/jQuery

Here is the function
function addCategory(category) {
$('#category_choice').append($('#!the variable "category" has to go in here!'));
$('#feed_submit_categories').hide();
}
The "category" variable sends the id of the element that has to be appended. How can I insert the "category" var into the function? In PHP it is much easier having $var_name tags... But here, I have no idea as to how to include it.
function addCategory(category) {
$('#category_choice').append($('#'+category));
$('#feed_submit_categories').hide();
}
Simple example of concatenation ( variables, string ):
var h = "Hello";
var w = "World!";
alert( h+w ); // HelloWorld!
alert( h+' '+w); // Hello World!
alert( h+' my dear '+w); // Hello my dear World!
jQuery selector can use string to represent literally an element ID selector:
$('#element')
that means you keep as string what you need and you concatenate a variable to it:
var elName = "element"; // string variable
$('#'+ elName) // same as: $('#element')
If you need to append every time a new fresh element do like:
$('#category_choice').append('<div id="'+category+'" />');
just make sure not to duplicate your elements ID for ID has to be unique per page element.
Use
function addCategory(category) {
$('#category_choice').append( $('#'+category) );
$('#feed_submit_categories').hide();
}
$('#category_choice').append($('#'+category));
jQuery selectors are just strings that are evaluated, you can generate a string following basic Javascript rules.
For example :
var iAmString = "#"+category;
$(iAmString) //<-- using string var as a selector

putting source of all images into an array

What is the cleanest way to put the source attribute string of all images within a div into an array?
I was hoping this would work -
var imageSourceArray = $("#leDiv img").attr('src');
alert(imageSourceArray[3]); //not alerting the source, boo hoo.
Do I need to loop through $("#leDiv img") and add each src string to an array individually? Or is there a more elegant way to do this?
You can use jQuery's map function which is described as:
Pass each element in the current matched set through a function, producing a new jQuery object containing the return values.
For your example:
var mySources = $('#leDiv img').map(function() {
return $(this).attr('src');
}).get();
Edit: Far more elegant solution, there's obviously still some looping involved internally:
var img_sources = $('#leDiv img').map(function(){ return $(this).attr('src') });
You will in fact need to loop over the collection and add sources individually.
var img_sources = [];
$('#leDiv img').each(function(i,e){
img_sources.push($(e).attr('src'))
})
Some background: jQuery.fn.attr() maps to jQuery.access() internally, the key part of which looks like this:
function( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// setter functions omitted here …
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
}
Note the elems[0] part – only the first item in the collection is fed to the subsequent callback function (jQuery.attr() in fact) responsible for extracting the information.
var imageSourceArray = [];
$('#leDiv img').each(function(){
var src = $(this).attr("src");
imageSourceArray.push(src);
});
alert(imageSourceArray[3]);
you already have the src in a collection when you fetch the the images. It may be more efficient to not store the src attributes in another array:
$('#leDiv img').each(function(i,e){
var dosomethingwith = $(e).attr('src');
})
or you could do:
var ImageCol = $('#leDiv img');
alert(ImageCol[3].attr('src'));

Global var in JavaScript

This is annoying me.
I'm setting an array in beginning of the doc:
var idPartner;
var myar = new Array();
myar[0] = "http://example.com/"+idPartner;
And I'm getting a number over the address, which is the id of partner. Great. But I'm trying to set it without success:
$.address.change(function(event) {
idPartner = 3;
alert(idPartner);
}
Ok. The alert is giving me the right number, but isn't setting it.
What's wrong?
Changing the value of the variable does not re-set the values within the array. That is just something javascript can't do automatically. You would have to re-generate the array for it to have the new id. Could you add the id to the value where you use the array instead of pre-setting the values in the array containing the id?
Edit: For example, you would do:
var myArray = [];
var myId = 0;
myArray[0] = "http://foo.com/id/";
and when you need to use a value from the array, you would do this:
var theVal = myArray[0] + myId;
Try this:
var myvar = ["http://site.com/"];
$.address.change(function(event) {
myvar[1] = 3;
}
then use myvar.join () where you need the full url.
The problem here is that at the line
myar[0] = "http://site.com/"+idPartner;
..you perform a string concatenation, meaning you copy the resulting string into the array at index position 0.
Hence, when later setting idPartnerit won't have any effect on the previously copied string. To avoid such effect you can either always construct the string again when the idPartnervariable updates or you create an object and you evaluate it when you need it like...
var MyObject = function(){
this.idPartner = 0; //default value
};
MyObject.prototype.getUrl = function(){
return "http://site.com/" + this.idPartner;
};
In this way you could use it like
var myGlblUrlObj = new MyObject();
$.address.change(function(event){
myGlblUrlObj.idPartner = ... /setting it here
});
at some later point you can then always get the correct url using
myGlblUrlObj.getUrl();
Now obviously it depends on the complexity of your situation. Maybe the suggested array solution might work as well, although I prefer having it encapsulated somewhere in an object for better reusability.
myar[0] = "http://site.com/" + idPartner;
After this line, myar[0] = "http://site.com/undefined" and it has nothing to do with the variable idPartner no more.
So, after that changing the value of idPartner will affect the value of myar[0].
You need to change the value of myar[0] itself.

Categories