Get all elements with data = value - javascript

I have this problem in my JavaScript class:
//===== i set this data record
jQuery(element).data("types", "row");
console.log(jQuery(element).data("types")); // writes "row" (the element is a div)
//==== into other method
//==== i want find all element with data-types = row
console.log(jQuery("[data-types='row']").length); // writes 0
jQuery("div").each(function(i,e){
console.log(i, jQuery(e).data(), jQuery(e).attr("id")); // writes object{type:row}
});
why with this jQuery("[data-types='row']") i can't find elements ???

When you assign data to an element using jQuery.data() it does not update the data-* attribute of the element; you therefore cannot use attribute selectors to select the element.
The data- attributes are pulled in the first time the data property is
accessed and then are no longer accessed or mutated (all data values
are then stored internally in jQuery).
In order to select these elements you can use the filter() function with custom function:
jQuery("div").filter(function() {
return $(this).data("types") === "row";
});
Note: If you are also using jQuery UI you would find the :data(key) selector useful.

The data() method only uses the DOM when initially reading from an element. When you use it to add or change the data of an element, it puts the data in its internal memory, it doesn't modify the DOM. So DOM selectors won't find it. From the documentation:
The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery).
To find all the elements, you can use .filter():
jQuery("div").filter(function() {
return $(this).data("types") == "row";
});

Related

jQuery data function returning the first value

I have a one span tag with data attribute, data-kr-id. On clicks of different items of the list, I update this span's data-kr-id attributes and it gets updated.
When for the first time I retrieve this(data-kr-id) value using jQuery's data method, I get the correct value. But from the subsequent time, I always get the same value as of the first time. But on using jQuery's attr function, I get the correct value. Can't figure out why.
CODE: Where I set the data-kr-id value:
$_applozicWtLauncherBtn.attr('data-kr-id', seller.UserId);
CODE: Where I retrieve the values:
var topicId = $applozic(this).data("kr-id");
topicId = $applozic(this).attr("data-kr-id");
In the above code where I retrieve values, using data method gives me old value(the value of the first item I retrieved), but using attr method gives me correct value.
UPDATE :
As informed by everyone, I was setting the data attributes with attr method and retrieving the value with data method. After using data method for setting the attribute, When I was retrieving the values, I was getting a getting empty string. After digging a bit deeper, I realized there are two different versions of the jQuery are being used here.
Sorry for the incomplete information and late update.
You set value only using attr, Second time when you set data-kr-id value using attr then data value remains same, so need to set value with data also
// With Attr
$_applozicWtLauncherBtn.attr('data-kr-id', seller.UserId);
// With Data
$_applozicWtLauncherBtn.data('kr-id', seller.UserId);
Actually jquery's .data() fetches value from the property (same as .prop()) not from attributes. Main difference is .attr() fetches data from HTML tag which you can see it will reflect on your HTML when you update it with .attr(). But when you use .prop() or .data() it will not reflect in HTML tag but it will update value in it's property for that HTML tag as per the DOM tree.
You'll find out more about difference property and attribute from here.
Initially this property will set when your element is created. So for the first time your .data() and .attr() will work fine. When you update value from .attr() it will manipulate DOM but property will be remain same.

Associate an element with a unique number

I'm looking for a way to associate a DOM element with a unique number, such that no other element in the DOM will be associated with that number. Obviously, I can't use an Id attribute because not all elements have an Id.
The most obvious way to do this is to (somehow) acquire a number that will give the element's position within the DOM, but I'm not sure if this is feasible. Ultimately, given an arbitrary element from the DOM, I'd like to have a way of mapping that element to a number.
Everyone is asking why I need to do this -- given a DOM element, I need to use that element as a key in a JS Object. JS Objects must be strings. So, technically, I do not need a unique number, per se, but I need a unique value that can be turned into a "short string" and used as the key in a JS object.
Technically, I do not need a unique number, per se, but I need a unique value that can be turned into a "short string" and used as the key in a JS object.
I see that you have jQuery tagged. This might be a possible solution to your problem. jQuery has a way to associate an element to an object:
var ele = /* your element */
$(ele).data({name: "Paul"});
// later you can use the element as a key
$(ele).data(); //returns {name: "Paul"}
This will avoid the whole "assigning unique id" mess and just let jQuery does all the hard work for you (creating a map data structure).
Edit by Roamer-1888
Basically, I need to "tag" an element uniquely so that if I encounter the same element in the future, I will know I've seen it before. The "tag" value will be the key in my JS object. I will associate various values in the tagged element. I don't want to use Map or WeakMap because they might not be supported on all browsers.
To meet this requirement, you would typically use jQuery's .data() as follows :
//...
var elementData = $(ele).data('myApplication');
if(!elementData) { // this element was not previously encountered
elementData = {
prop_A: ...,
prop_B: ...,
prop_C: ...
};
$(ele).data('myApplication', elementData);
}
// Here `elementData` is guaranteed to exist and its properties can be read/written.
//...
This technique is particularly useful for preseving state in jQuery plugins. Here is an example
Multiple applications/modules can do this without interfering with each other.
I'm guessing that there might be a better way to solve your problem if we understood what the real problem was. But, at any point in time, you can find what position an element is at (if it is currently inserted in the document) with something like this:
var items = document.getElementsByTagName("*");
If you needed to then get a unique index for a DOM element (at this particular point in time), you can do so by just searching for it in that HTMLCollection. It's position in the collection is guaranteed to be a unique index.
But, of course as the DOM is modified, this HTMLCollection will change as will the index.
If you wanted to assign a non-changing unique index, you could just assign a property to each DOM element based on a monotomically increasing counter.
var idCntr = 1;
function assignIds() {
var items = document.getElementsByTagName("*");
for (var i = 0; i < items.length; i++) {
if (!items[i]._uniqueId) {
items[i]._uniqueId = idCntr++;
}
}
}
You can call this function as many times as you want and it will assign new unique IDs to any DOM elements that don't yet have an id, but will leave ids that were already assigned the same (so they will never change).
If you just want to be able to generate a unique ID for any given DOM node such that you can always have the same ID for that DOM node, then you can just again use a monotomically increasing counter.
var idCntr = 1;
function assignId(elem) {
if (!elem._uniqueId) {
elem._uniqueId = idCntr++;
}
return elem._uniqueId;
}
You can then call this on any DOM element that you want to assign a unique ID to and it will both assign the id to the element and return the id that it assigned. If you pass it an element that already has an id, it will leave that id in place and just return it.
Based on your latest edit, it appears you're just trying to generate an id string that you can use as a key in a JS object. You can certainly use the above assignId() function for that.
In a modern browser, you can also use a Map or a
WeakMap object which will accept the DOM object itself as the key - you don't need to manufacture your own string key. You can then look it up directly with the DOM element too (since it's the key).

Fetching only specified list of attributes for elements selected through element selector

I need to fetch first 10 <p>elements in a document which I can easily do using $('p').slice(0,10). But going further I want to get only few attributes for each of the element returned by above call. For eg. when I execute $('p') in my script, I get each element with attributes such as childnodes, classname, firstchild, innerText, innerHTML etc.. I am interested in only the innertext and few others. Is there a way I can specify the list of attributes which I want to fetch for each of the elements selected?
The objects returned by jQuery selections are wrappers of DOM Node objects, which will always have those properties. You can't retrieve just the properties that you need directly from selecting elements.
If you need to create transport objects containing only specific properties, you will need to create them separately using the properties you want from the Node objects:
var elements = [];
$('p').slice(0, 10).each(function() {
elements.push({
tagName: this.tagName,
innerText: this.innerText,
className: this.className
});
});

Setting jQuery plugin options from data attributes

Im having a problem setting options to an array value in a jQuery plugin using data attributes.
If I reference the data attribute using a class selector
$('.tm-input').tagsManager(
{
prefilled: $('.tm-input').data('load')
})
It works but all the elements get the same values.
If I reference using "this" it sets the correct values but it comes across as a string not an array.
$('.tm-input').tagsManager(
{
prefilled: $(this).data('load')
})
I've tried using JSON.parse() but I get an error about an unexpected character. Any help would be appreciated!
Have you tried each
$('.tm-input').each (function () {
$(this).tagsManager( { prefilled: $(this).data('load') });
});
Explanation:
When a selector has more than 1 element, applying a method to it will typically affect all of the elements, but retrieving a property will typically only return that property from the 1st element.
So when you use .tagsManager on your $('.tm-input') selector, you are applying .tagsManger to all of the elements. But when you set prefilled:$('.tm-input').data('load'), the data method is only grabbing the data from the first element in the list, every single time.
When you use each, it applies the logic inside of the each block to each element individually, rather than all of them at once, so when you use $(this).data('load'), it grabs the load attribute from each individual element as well.

How To Access Dynamically Created Page Elements with jQuery (not events, ELEMENTS!)

I have several dynamically created elements on a page that I would like to POST the contents using jQuery to another page. The problem is, the elements created cannot be accessed via jQuery (only elements that existed on the page can be accessed using the $(#myElementID).
I've seen hundreds of posts using the live() and on() functions for accessing EVENTS, but no way to access any properties, values, innerHTML, etc, of the dynamically created ELEMENTS.
Is this simply not possible to do with jQuery?
$('#btnParseTable').click(function () {
var tblCustomPattern = $("#tblCustomPattern").innerHTML;
//This test alert yields "" because tblCustomPattern is undefined - yet FireBug clearly shows the table exists!
alert(tblCustomPattern);
var postData = { "method": "ParseTable", "tbl": tblCustomPattern };
$.post("tiler.aspx", postData, function (data) {
$("#test").html(data); //for testing
});
});
If not supported by jQuery, can this be done in JavaScript or is it not possible to post back information that is NOT an "INPUT" element?
This test alert yields "" because tblCustomPattern is undefined -
yet FireBug clearly shows the table exists!
You can assess dynamically created element after they being added to DOM. tblCustomPattern is undefined because jQuery object does not have attribute innerHTML You need DOM element to use innerHTML but the selector will return you jQuery object. You can use indexer [] or [get()][1] to get html element from jQuery object. It is zero-based index and you will get first element at zero index.
var tblCustomPattern = $("#tblCustomPattern")[0].innerHTML;
OR, using .get()
var tblCustomPattern = $("#tblCustomPattern").get(0).innerHTML;
OR using html()
var tblCustomPattern = $("#tblCustomPattern").html();
In this part of your code, you have a problem:
$("#tblCustomPattern").innerHTML;
The issue is that $("#tblCustomPattern") is a jQuery object. It is not a DOM object. The jQuery object does not have a property .innerHTML.
So, to fix your issue, you have several choices:
You can get the DOM element out of the jQuery object and then use the .innerHTML property on the DOM object directly.
You can use the jQuery method for this same functionality by called the jQuery .html() method.
You don't even really need jQuery for this at all, so you can just use plain JS.
So, any of these will work:
// get the first DOM object from the jQuery object
// two different methods for doing that
var tblCustomPattern = $("#tblCustomPattern")[0].innerHTML;
var tblCustomPattern = $("#tblCustomPattern").get(0).innerHTML;
// use the jQuery method to get the HTML
var tblCustomPattern = $("#tblCustomPattern").html();
// use plain JS - fastest option
var tblCustomPattern = document.getElementById("tblCustomPattern").innerHTML;

Categories