Can a DOM element attribute value be a JavaScript object? - javascript

Maybe this is a duplicate, but I could find the similar question.
For example we have <input data-student=""> and we have a var studentObj = {...}. Can I assign studentObj to input data-student attribute? Will it contradict the standards?

Attribute values are always strings, so no. You have several options:
Store the object in string form, such as JSON, in the attribute.
Store the object in a container somewhere and keep a key for it in the attribute.
If you mean on an element instance, it's possible to add your own properties to element instances, and those properties can have any value (search for "expando properties" for details), but be sure to use a name that will be really, really specific to your situation. (jQuery does this, for example, for the data it manages via the data function.)
And in fact, if you're using jQuery, you could use data to store the object, leaving the details to jQuery. :-)

Sure will! HTML doesn't accept a data type of object, it is in fact just plain text

What you are looking for is the dataset attribute. But it only stores strings, you can solve this with JSON.
el.dataset.student = JSON.stringify(studentObj);
studentObj = JSON.parse(el.dataset.student);
With jquery's data method (https://api.jquery.com/data/) you can store objects without any further problems.
Read more:
Dataset: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset -
JSON: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON

Actually your desire doesn't contradict the standards, you must stringify your object and put in your data attribute then in usage parse it, like below:
const q = document.querySelector.bind(document); // it's just for easiness
const input = q('input'); //select the input
const studentObj = { // make your student object
something: 'some-value'
};
input.dataset.student = JSON.stringify(studentObj);
// put the student object in your selected input data attribute
When you wanna use it you can parse it:
const input = q('input'); //select the input
const myDesireObject = JSON.parse(input.dataset.student);

Related

How do I access the 'str' value in my object?

I am trying to return the value under the key 'str' in an Object but I am having trouble accessing the value.
This is what is returned in the console:
Currently I am using a map function to go over the array and just return the _str value like so:
let idx = currentArray.map(function(x) {
return x._id._str;
});
However it is still returning the value as an object. How can I get just the value of the _str key?
Here is the full array without specifying the id field. This is what is returned if you jsut return 'x' in the map function.
You've clarified that the screenshot is of x._id. So to access _str, you'd use x._id[0]._str: The _str property is in the object referenced by the 0 property (the first entry in the array x._id refers to).
Note that in general, _-prefixed properties are meant not to be accessed by code outside the code responsible for the objects in question. You don't seem to be responsible for them, so accessing those properties is likely to make your code rely on undocumented properties that may change in the next "dot" release of whatever lib you're using. It's just convention, but it's a very common convention.
If you right click on the property, most browser consoles offer the ability to copy property path.
Based on this SO post and the docs, it appears that you can probably use x._id.str.
If I understand correctly, you are receiving the str value but it is an object instead of the string literal. In other words, you are getting _str: "598..." instead of "598....". A possible solution would be to use the mongo javascript function to convert the str value to a string.
In your case, I think something like return x._id.str; may work as _id is a MongoID.ObjectID.
I've also linked the documentation below for reference.
https://docs.mongodb.com/manual/reference/method/ObjectId/
Here's a relevant SO answer as well: Convert ObjectID (Mongodb) to String in JavaScript
I think you should write x[_id]._str because _id is one of the array objects.

Saving an element as a index in a object

I'd like to save a DOM element in a object. But not as a value, i want save it as a key of the object. But i think the core of javascript is not able to do that.
data={}
data[$('div#a')] = 'A';
data[$('div#b')] = 'B';
console.log(data[$('div#a')]); //return B
Do you know some way to save the element in a index object?
Imagine i have XXXXXX elements on my document. If i want to access to the element properties when some event happen on it i dont want to iterate XXXXXX elements to find it.
Why i don't use data of jquery for two reasons:
I want to do it on native javascript
I dont want another array to iterate separate data from the elementid
So the perfect way to do it was have only one object with the elements on the key to acces them easy. And if i want iterate them i only have to do for i in data
JavaScript objects will only accept strings as keys, and JS will use .toString() if you try to use anything else as a key, typically resulting in everything being stored under the (single) key "[object Object]".
Is there any reason you can't use $('#a').data() to store the data associated with that element directly on the element?
Failing that, assuming that every such element has an ID, just use the element ID as the object key.
NB: ES6 has a Map object which can use arbitrary keys, but that's only an experimental feature in current browsers. However even then you would have to use the actual element as the key rather than a jQuery wrapped $(element) object, since $('#a') !== $('#a') - you would have to use the exact same original jQuery object each time you access the map, not a newly constructed object.
Javascript objects only accept string as key.
So if you try to give key value other than string, javascript will internally call .toString() method of that object and use return value of it as key.
Object keys have to be stings.
You can use the data method to associate anything to the element:
$('div#a').data('name', 'A');
$('div#b').data('name', 'B');
console.log($('div#a').data('name')); //return B

Editing objects in jQuery

$(function(){
var z = document.body.children[0];
var x=$("li", z);
x.name="Johnny";
alert(x.prop(name));
});
x should be an object containing all the elements within the first ul in the body.
Regardless of what the object contains, I would like to add a property with a value, and then use the prop() method to show it - but that doesn't seem to work. Why is that?
I saw a script containing the following: var $x = $("div"); - Do I have to add $ to the variable name if it's a jQuery object?
To select the first ul element inside a page you can do:
$("ul:first li")
This way you are going to select all lines inside the first list in the page.
To store arbitrary data in an element you can use the method data, like this:
$("element").data('key', 'value');
and to retrieve the data:
$("element").data('key');
More info, for the data method.
If you really want to add an attribute you can use the attr method, it works the same way as the data method, but it would reflect in the DOM.
If you want all li elements in the first ul element, then this should do the trick:
var elements = $("ul:eq(0) li");
Here is a very simple example of this in action.
In regards to setting a property, you can do element.name = "test" and it will work ok. But what you need to understand is that this is setting a name property on the jquery collection object and NOT on any of the actual elements.
What you can do however, is set the property like so:
elements.prop("name", "test");
and the access it like so:
var name = elements.prop("name");//name will be "test"
Here is a working example
As I mentioned in my comment, you don't need to prefix the variable with $. But this can be helpful to easily see which variables are JQuery objects.
Number 1. x is a jQuery object, you added to that instance a name property, then you're using name though it wasn't defined.
If you want to change a property of the element you got with jQuery the ways are:
$('selector').prop('property', 'value');
$('selector').attr('attribute', 'value');
$('selector').get(index).property = "value";
Number 2. no you don't have to, $ prefix is simply a convention to make the code more readable.
Is there any specific reason behind using $ with variable in jQuery
Using the selector from #musefan answer, you can take the collection returned, and use the attr() method to add an attribute and value to each item selected. However, I've modified his selector slightly to actually grab "all" elements in there, (just in case future visitors wonder)
var elements = $("ul:eq(0)").children();
elements.attr("attrName", value);
So if you wanted to set the title:
var elements = $("ul:eq(0)").children();
elements.attr("title", "Johnny");
You probably don't want to alert these values, browsers may ask you to stop allowing alerts on the page... but if you really did, then you could throw in an .each() after that.
var elements = $("ul:eq(0)").children();
elements.attr("title", "Johnny").each(function(){
alert($(this).attr("title");
});

Can a DOM element have an attribute whose value is an arbitrary object (not a string)?

I'd like to do something like this:
var elem = document.createElement("input");
elem.setAttribute("my-attribute", myObject);
document.getElementById("parent").appendChild(elem);
Later I will need to fetch myObject when performing some actions on this (and similar) element(s).
Note: I need this as an attribute (and not, for example, as a member of the element object, as in elem.myAttribute = myObject), as for some elements the value is a string which is hard-coded into the HTML of the page. What I need is the ability to set this attribute programmatically for other elements, and to use values which are not always plain strings.
I tried this and it worked in my browser (Firefox 14), but I need to know if this works cross-browser, and also if I'll be able to fetch the values of such attributes using jQuery if I decide to use jQuery in my page later on.
No - attributes by definition store string values. The obvious approach is to store the object as a property but you say that's not suitable.
Either:
1) Use jQuery's data API (since it does not literally log the data on the element, so you can store whatever you want, not only strings)
2) Stringify the object and append that to the element as an HTML5 data attribute.
var elem = document.querySelector('p'),
obj = {foo: 'bar'};
elem.setAttribute('data-myObj', JSON.stringify(obj));
/* ...then, later... */
var data = JSON.parse(elem.getAttribute('data-myObj'));
Note, though, that, because we're dealing with JSON, you will not be able to store methods as part of this object. They will be stripped out by JSON.stringify().
Finally, using attributes means you'll muddy your HTML since they show up in any HTML dumps (unlike properties) but this is purely a cosmetic weakness.
You can use the data attribute in jquery to do this (http://api.jquery.com/data/)
You can use html 5 data attributes:
http://ejohn.org/blog/html-5-data-attributes/
And these can be retrieved using the jquery data api.
These will have to be stringifed however
"As of jQuery 1.4.3 HTML 5 data- attributes will be automatically pulled in to jQuery's data object"

Creating a constant time data structure for DOM element references

Relevant discussion.
I understand I can build an array of references to elements/nodes. I realize also that I could use the neat trick of treating an array like a heap (index 2n and 2n+1 for children) to build a (potentially wasteful) binary search tree using it.
But all that's still not enough for the premature optimizer in me. Besides, implementing a BST is going to be bug prone.
Here's my question. Can I somehow use an element reference as index into javascript's hashes (which are objects, or vice versa?). If not, can I conjure up a unique string from an element reference, which I can then use as my hash key? If not, how the hell does jQuery do it?
The easiest option is to just use your own attribute on the DOM object:
var element = document.getElementById("test");
element.myData = "whatever";
Here's the general idea behind how jQuery's .data() function works that you could use in your own plain javascript. It uses one custom attribute on the object and then stores everything else in a data structure indexed by the value of that custom attribute.
var idCntr = 0; // global cntr
var data = {};
var element = document.getElementById("test");
var id = element.uniqueID;
if (!id) {
id = idCntr++ + "";
element.uniqueID = id;
}
data[id] = "whatever";
// then some time later, you can do this
var element = document.getElementById("test");
console.log(data[element.uniqueID]); // whatever
It is a bit more involved to store multiple attributes for a given object in the data object, but this is the general idea.
And, if you can use jQuery, it's trivial:
$("#test").data("myData", "whatever"); // sets the data
console.log($("#test").data("myData")); // retrieves the data
If you want to really see how jQuery's .data() works, you can step through the first call to set data and then retrieve it when using the unminified jQuery. It's easy to see what it does.

Categories