How to read raw content of data-* attribute using jQuery? - javascript

Maybe I am missing something, but I use data-* attribute, namely data-content with such entries like "apple", "cow", etc. Suddenly I was hit when I set my data-content with string "null" (I checked using Chromium HTML is:
<p class="text" data-content="null">null</p>
But when I read data-content using jQuery:
text_elem.data('content')
I get null value, not "null" string.
So my question is, how to read it in raw form, so I could get "null" string exactly as it is in HTML?

If you want to read it in the raw form you would need to use .attr instead of .data. Because that is what data api does it parses the content of the data attribute (ex JSON --> object, numeric string value to number etc...).
text_elem.attr('data-content');
Or you could use dataset (Not supported in older browsers) with the DOM element.
text_elem[0].dataset.content; //this will return a string

You get null instead of "null" because jQuery has for some reason decided to parse data- attributes as JSON when fetching using .data().
To get the raw data, use .attr() instead. This will be faster, and it doesn't make a copy of the value into jQuery.cache, which is very often unnecessary.
Basically, only use .data() for data- attributes if you need the data stored in jQuery.cache and if you're alright with it being parsed as JSON.

The .find() method could be use to search an XML document for the element name specified. For the HTML document, if you want to access the attribute you must use the .attr() method.

Related

Select an object property within an attribute of the DOM

I looked at this thread but it didn't help: Find an element in DOM based on an attribute value
I need a Vanilla JS solution to select a username that is in a custom attribute of an <a> tag in the DOM. I used const users = document.querySelectorAll('a[metadata]') which returns a NodeList of all the <a> tags with all their attributes. If I type console.log(users[0]), I get:
<a href="#" class="btn-normal" metadata="
{
'username':'johnny134',
'category':'shoes',
'summary':'Just a guy called Johnny',
'userId':1223432432
}"
</a>
To access the username, I have tried const usernames = document.querySelectorAll('a[metadata="username"]'); but just get back undefined. I think my issue is that username is in an object and I can't figure out how to select it.
Thanks in advance
First, note that document.querySelectorAll returns a list of elements that match the given query, not a list of the values of attributes of those elements that you specify in the query.
From const users = document.querySelectorAll('a[metadata]'), you can get the metadata attribute of, say, the first element, like so:
const metadata0 = users[0].getAttribute("metadata");
And then, since it's a JSON string, you parse it:
const user0 = JSON.parse(metadata0);
Now you can use user0 like a regular JavaScript object:
user0.username
// johnny134
P.S. The JSON in the metadata attribute is not valid, and you may get an error when you try to parse it. Use double quotes in JSON, not single quotes.

Get Data Attribute Value Without CamelCasing

Is it possible to pull out a data attribute value without grabbing the data attribute via camel case?
Example: Take this button:
<button id="my-button" type="button" data-some-url=<%=some_dynamic_path%>>Lookup</button>
When this button is clicked I want to do some ajax stuff. Currently I only know how to grab the data attribute value by camel casing:
$("#my-button").on("click", function(){
url = $(this).data("someUrl");
});
Instead I would prefer to grab the data attribute value like so, but of course it doesn't work:
url = $(this).data("some-url");
Question: Is there some way I can grab the data attribute value by keeping the hyphens in there?
Update:
I made a simple typo. The second version does in fact work:
url = $(this).data("some-url");
That will successfully get you the data attribute value.
Just pass the name as a string to the data method.
$('#my-button').data('some-url')
You could ignore it's data-semantics and treat it like any other attribute:
url = $(this).attr( 'data-some-url' );

Identity selectors in jQuery returning arrays

Suppose I have a div tag like this:
<div id="group-dialog" class="modal-dialog">
Now I want to grab it as a jQuery object (in this case so I can run .dialog()).
When I try this:
var gDialog = $('#group-dialog');
I get an array back (!!).
Why am I getting an array? Isn't the point of having an ID attribute that there's only one? I can see getting multiple p's or .my-css-thing back ...
Next question:
I have this array with 1 object in it that I now want to access as a jQuery object.
When I do this:
$(gDialog[0])
And pull it up in F12, I still have an array!! I thought I de-referenced the array already by picking the first element.
This doesn't seem to help either:
var gDialog = $('#group-dialog:first');
This is basic, but I run into this problem a lot. It seems like it used to be a lot simpler!
What is the best way to access this DOM element as a jQuery object?
Answer 1
jQuery selectors always return arrays.
Selection with id attribute is a particular use case and ideally the result should be unique. However, there is nothing preventing you from having duplicated ids in a HTML document (although this is bad practice).
Answer 2
The following code will get you the first element as a DOM object:
var gDialog = $('#group-dialog')[0];
Note: you may want to check the size of the return array first.
As far as I know, there is no way to transform this DOM element back to a jQuery object. The standard use case would be to directly used $('#group-dialog') and asume that it is found and unique.
Try using .get(). Though I'm not sure it will work with dialog()
Retrieve the DOM elements matched by the jQuery object.
var gDialog = $('#group-dialog').get();
If you're trying to grab it to use it on a dialog, you can just put
$(document).ready(function(){
$('#group-dialog').dialog({put options here})
});

jQuery .data() is not actual after adding new values

I've got div like
<div data-a="aa"> </div>
Then I'm getting its data with:
var data = $("div").data();
And its working fine. Then I'm adding new data like this via data- attribute:
$("div").attr("data-b", "bb");
Then I'm getting data again like
var updatedData = $("div").data();
However, the new value ( data-b attr with bb value ) is not there. Why is that? (I want to manage data via data- attributes)
Fiddle playground
Using attributes is suitable in my case, so I dont want to use .data("key", "val"). data- attributes are valid anyway
Interesting thing is that when I add data- attribute before first call of .data() - it works ok. Is there a way to ignore or 'rebuild' cache of data then? example here
Use .data("key","value") to set the value
$("div").data("b", "bb");
Also use .data("key") to get the value
var data = $("div").data("b");
When you use the data() api, jquery uses an internal private data structure to store the data so the attribute value is not updated.
When you use the data api, there is no need to use the data- prefix.
So once you use the data api to read the values the attribute values are copied to the internal data structure thereafter any changes done to the attribute will not be reflected in the data api.
Demo: Fiddle
There are two ways to add data to an element either you can use data() function by jQuery or you can manually add the 'data-attribute'
The issue you're facing is you can always GET as well as SET the data-attribute's value with data() function. But the attribute SET by this function won't be visible in HTML file.
In the below, 'data-c' won't be visible in the HTML file.
<div class='bar' data-a='avalue' data-b='bvalue'></div>
<script>
console.log($( "div" ).data());
$( "div" ).data('c','cvalue');
console.log($( "div" ).data());
</script>
Try using dataset
var article = document.querySelector('#div1'),
updatedData = article.dataset;
Demo
Reference JavaScript Access

get attribute from selectNodes in JavaScript and XML?

I am trying to get an attribute from an XML node from JavaScript.
item.selectNodes("enclosure[#url]")
That is not working like I thought it would :(
Any hints ?
thanks!
[#url]
is a predicate, which does not select the attribute but filters the "enclosure" nodes that do have a url attribute.
In XPath,
enclosure/#url
would select the attribute.
This:
item.selectNodes("enclosure[#url]")
will give you a collection of enclosure nodes that have a url attribute.
To get a collection of url attribute nodes that are on enclosure nodes, do this:
item.selectNodes("enclosure/#url")
Which you must then loop over to get the values of each one. Remember this gives you attribute nodes, not attribute values. You can use attributeNode.nodeValue to get the value from the node.
If you are expecting just one such node, then use selectSingleNode instead of selectNodes. This will give you the first matching node, instead of a collection of all matching nodes.

Categories