Accessing data attributes with JavaScript - javascript

I have been using:
var data = element.getAttribute('data-name');
But it seems easier to use 'dataset'
var data = element.dataset.name
But my question is: Is there anyway I can use element.dataset with a var? For example I can't get this to work:
var dataName = 'test';
var data = element.dataset.dataName;

Consider what the code you wrote actually does.
var data = element.dataset.name is the code which works and you're familiar with – it looks for a property called name inside element.dataset. In this case, name is not an identifier which refers to a variable.
In exactly the same way, the code element.dataset.dataName looks for a property dataName inside element.dataset. dataName is not seen as an identifier.
What you want to do is look for a property called test, the content of your variable dataName.
To do that, you need to use bracket notation:
var dataName = 'test';
var data = element.dataset[dataName];
Here is a working code snippet which demonstrates this method:
var element = document.getElementsByTagName('div')[0];
var dataName = 'test';
var data = element.dataset[dataName];
console.log(data);
<div data-test="success"></div>
You could also look into variable variables, although many people would recommend against using them in javascript when it is not necessary.

Related

Iterate string array error, runs for first item's letters

I have a simple array loop, runs perfect in jsFiddle showing all items, see https://jsfiddle.net/8odoros/b27ocs4d/1/
What's strange is that putting the same script here as a snippet runs by letter, showing the first string letter by letter. I feel stupid, am I missing something? Check it out:
var name = ['Helen','Jim','Thomas','Luke','Theodore'];
var div = document.getElementById('cards');
for(var i=0;i<5;i++){
var newHtml = name[i]+' '+i+'</br>';
div.innerHTML = div.innerHTML + newHtml;
}
<div id="cards"></div>
Word name is a reserved word (as #prasad answered) in javascript that why your code was not working as expected.
See below code, after changing name with names. Its seems working as was working in jsfiddle.
var names = ['Helen','Jim','Thomas','Luke','Theodore'];
var div = document.getElementById('cards');
for(var i=0;i<5;i++){
var newHtml = names[i]+' '+i+'</br>';
div.innerHTML = div.innerHTML + newHtml;
}
<div id="cards"></div>
Note: name can only be used as local variable inside a function or iife and can not used as global varibale.
Try any one of the function its working. name is reserved word of javascript.But applied with in function .Its not act as a reserved word.This is one of the way preventing the action.
(function () {
var name = ["Helen","Jim","Thomas","Luke","Theodore"];
var div = document.getElementById('cards');
for(var i=0;i<5;i++){
var newHtml = name[i]+' '+i+'</br>';
div.innerHTML = div.innerHTML + newHtml;
}
})()
<div id="cards"></div>
Apparently name is a property of window and it has a setter which converts the input value to a string. Your code is trying to assign an array to that property which is magically converted to a string:
var name = ["foo", "bar"];
console.log(name); // array converted to "foo,bar"
So why does it work on jsFiddle? The answer is that, by default, jsFiddle wraps your code inside a function, something like this:
<script>
window.onload = function() {
var name = ["foo", "bar"];
console.log(name); // ["foo", "bar"]
}
</script>
This creates a closure where var name creates a new variable instead of referring to window.name. If you change your jsFiddle settings (JavaScript tab > Load type > No wrap - in body) then you get the same result as the StackSnippet like this:
<script>
var name = ["foo", "bar"];
console.log(name); // "foo,bar"
</script>
The solution is not to pollute the global namespace in the first place. That way you do not have to lookup the list of "words not to use as JavaScript variables".
name AKA window.name
Well name is most definitely not a reserved word in javascript.
name AKA window.name is the name of the window. Its value is set by a setter function and as the window name should be a string. So when you set it with name=["foo","bar"] it is converted to a string.
It is unfortunate that Javascript must share the global name space with every man and his dog and this illustrates another reason to avoid the global scope whenever possible.

jQuery objects as elements

I see this syntax in some advanced jQuery:
$container
as in:
$input = $container.find('.fn_this_timeline')
EDIT: based on some of the comments below, just to clarify the first instance of '$container' that I can see is created right at the beginning:
init: function($container){
var myThing = this,
$input = $container.find('.fn_do_some_calc'),
$submit = $container.find('.fn_do_some_other_calc'),
defaultValue = parseInt($input.val(), 10);
myThing.$container = $container;
The line above confuses me even more :/
I'm used to using jQuery selectors like this: $('#mySelector').method('etc');
Can someone let me know what the difference is and when it's appropriate or applicable to use the 'shorthand' style?
This isn't some shorthand, this is just the use of Javascript variables. For example, the $container variable was probably declared like this:
var $container = $("#container");
Because it's stored, the element (jQuery object) is "cached" and can be reused without having jQuery go out and re-traverse the DOM to find it again (because it has to every time $("select") is used).
The use of $ at the beginning of the variable name is sometimes helpful for the developer to remember that it holds a jQuery object and not a Javascript element (like what's returned from document.getElementById("container");.
Depending on where your question's init method is, the line myThing.$container = $container; is just setting an object's property "$container" as the value of the $container variable. So the object is probably like:
var myObject = {
init: function () {
// blah blah blah
},
$container: undefined
};
And after running the init method, it will set the "$container" property to something.
This is just to make clear, that the $container variable is already a wrapped jQuery object, instead of e.g. a native DOM node.
For Example you can write:
var container = document.getElementById('item');
var $container = jQuery(container); // or:
var $container = jQuery('#item');
Got the point?
Basically, yes it is shorthand.
For the function you noted:
init: function($container){
var myThing = this,
$input = $container.find('.fn_do_some_calc'),
$submit = $container.find('.fn_do_some_other_calc'),
defaultValue = parseInt($input.val(), 10);
The $ is included so you know to pass a jQuery object into the function. So When you call it, you may do something like this:
init($('#theid'));
As far as the line below:
myThing.$container = $container;
That is just storing your jQuery object as part of your myThing object. One other note, you could do something like $var = 1 and that would be perfectly valid. However usually it is done as a reminder to store a jQuery object.
There is no shortcut method for using jQuery.
It is Standard Method to declare variable in jQuery.
i.e $container = $("#container");
$container is a jquery object.
Understanding: $ indicate that it is jquery object so apply operation on it as appropriate.

Changing variable name with javascript and jQuery

How to shift between variable names in jQuery and change them?
//predefined variables
var s1='';
var d2='';
//trying to change variables by .attr() parameter but no luck
$('body').on('click','span', function() {
var $(this).parent().attr('data-scan')=$(this).attr('id');
});
HTML
<div data-scan="s1"><span id="banana">Banana</span><span id="apple">Apple</span></div>
<div data-scan="d2"><span id="orange">Orange</span><span id="apple">Apple</span></div>
How can I change specific variables? I do't care about changing attr papameter, all I need is changing predefined global var parameters!
You are using wrong syntax of attr()
Syntax: attr( attributeName , value)
Change
var $(this).parent().attr('data-scan')=$(this).attr('id');
To
$(this).closest('div').attr('data-scan',$(this).attr('id'));
You code would be
Live Demo
$('body').on('click','span', function() {
debugger
$(this).closest('div').attr('data-scan',$(this).attr('id'));
s1=$(this).closest('div').attr('data-scan');
alert(s1);
});​
Firstly, your html for the data-scan attributes is wrong, you have no closing quotes.
Secondly, you can the data() jquery function to access data attributes.
Thirdly, you cannot set values by using the = operator.
You want something like this:
$(this).parent().data('scan', $(this).attr('id'));
or, without the data() function:
$(this).parent().attr('data-scan', $(this).attr('id'));
Here is a working example
To get the value you can do one of the following:
var dataScan = $(this).parent().data('scan');
or
var dataScan = $(this).parent().attr('data-scan');
Your exact requirements for setting a variable based on the data-scan value
Based on your comments and code, I think it has not been clear what you were trying to do. I think I have worked it out though and you want to use the data-scan value to determine which global variable should be set...
//predefined variables
var s1='';
var d2='';
$('body').on('click','span', function() {
var variableType = $(this).parent().data('scan');
var valueToSet = $(this).attr('id');
if(variableType == "s1"){
s1 = valueToSet;
}
else if(variableType == "d2"){
d2 = valueToSet;
}
});
Here is an example of what I think you are trying to do.
However, if you have lots of variables then it is not ideal to use so many if/else statements. So you could use the javascript eval() function.
var variableType = $(this).parent().data('scan');
var valueToSet = $(this).attr('id');
eval("" + variableType + " = '" + valueToSet + "';");
See here for an example
But be careful the your eval code is subjected to user injected values (not that javascript is safe from users anyway)
You're pretty close!
// set
$('#item').attr('data-scan', 'set new value');
// get
var dataScan = $('#item').attr('data-scan');
console.log(dataScan); //=> set new value
Probably best if you use .prop() rather than .attr()
$(this).parent().prop('data-scan', $(this).attr('id') );
As the jQuery api documentation states
As of jQuery 1.6, the .attr() method returns undefined for attributes
that have not been set. In addition, .attr() should not be used on
plain objects, arrays, the window, or the document. To retrieve and
change DOM properties, use the .prop() method.

Object arrays in JavaScript

If I do this,
var element = {};
alert(element);
element[name] = "stephen";
alert(element.name);
Why doesn't element.name work?
When using bracket notation, (unless it's a variable) it needs to be in qoutes, like this:
var element = {};
alert(element);
element["name"] = "stephen";
alert(element.name);
You cant test it out here. To explain what I mean by "unless it's a variable", this would also work:
var myVariable = "name";
element[myVariable] = "stephen";
Because name should be in quotes.
This works:
var element = {};
alert(element);
element['name'] = "stephen";
alert(element.name);
Try it.
This is the reason why you may want to get an object's property dynamically. For example:
You have a variable, but you can't be sure of its value. The server send you the variable value so you should write like this.
obj[name].age // Here the name is a variable, and it can be changed in every page refresh, for example.
But if you want to set obj['name'] = 'Lorenzo' you have to use quotes.
Think like obj[name] is used for set, obj['name'] is used for get.

Executing a function by name, passing an object as a parameter

Here's the problem - I know function by name (and that function has already been loaded form an external script), but I don't have an actual function object avail for me to call. Normally I would call eval(function_name + "(arg1, arg2)"), but in my case I need to pass an object to it, not a string.
Simple example:
var div = document.getElementById('myDiv')
var func = "function_name" -- this function expects a DOM element passed, not id
How do I execute this function?
Thanks!
Andrey
Never use eval, it´s evil (see only one letter difference)
You can simply do:
var div = document.getElementById('myDiv');
var result = window[function_name](div);
This is possible because functions are first class objects in javascript, so you can acces them as you could with anyother variable. Note that this will also work for functions that want strings or anything as paramter:
var result = window[another_function_name]("string1", [1, "an array"]);
You should be able to get the function object from the top-level window. E.g.
var name = "function_name";
var func = window[name];
func( blah );

Categories