Is there a best practice, or industry-wide standard for JavaScript naming convention for DOM element?
Take the following example:
var tarzan = document.getElementById('foobar');
What would be the most acceptable name to use so that a DOM element could be differentiated from another type of var? Should it be...
DOM_tarzan
DOMtarzan
elementTarzan
.... so on and so forth?
I want to be able to tell the difference by just looking at the variable. For example, if I see:
DOM_tarzan.remove();
... I know straightaway that "DOM_tarzan" is a DOM element, and that it is employing the standard JavaScript remove() method.
There is no mistaking or guesswork that "DOM_tarzan" is a custom object that has a user-defined "remove()" method.
Thanks.
For indicating that a JS object variable references a DOM element object, I append El (or Elem) as a suffix to the variable name, as in
var tarzanElem = document.getElementById('foobar');
Whether I include jQuery in my projects or not, i like my naming convention of variables to be $variable. Then I can easily see if the variable is a DOM element.
Related
I need to associate some data with an HTML Element, hopefully avoiding any memory leaks. Obviously a simple solution would be to throw some kind of identifier on the element, and then create a dictionary mapping that identifier to the data I need. However, this is in a javascript library that users will add to their page, thus I don't have control over when elements are added or removed.
What I'm looking to do is associate data with an HTML element while it's on the page, while allowing for that data to be GC'd when/if the element is removed. Is there a way to do this that doesn't involve writing my own periodic GC to clean up orphaned data? Is it safe to add properties to HTML elements?
Attribute approach
You can store data in elements using custom data-* attributes.
This has the limitation that you can only store strings, but you can use JSON to store plain objects or arrays (not by reference).
To avoid conflicts with other code, it would be a good idea to include the name of your library in the attribute.
They can be set directly in the HTML:
<div data-mylibrary-foo="bar"></div>
And they can be read or written with JavaScript:
element.getAttribute('data-mylibrary-foo'); // read (old way)
element.setAttribute('data-mylibrary-foo', 'bar'); // write (old way)
element.dataset.mylibraryFoo; // read (new way)
element.dataset.mylibraryFoo = 'bar'; // write (new way)
They can also be read by CSS, using some attribute selector.
Property approach
This is much more flexible than the attribute approach, allowing to store arbitrary data in your element.
To avoid conflicts with other code, better wrap all properties in an object with the name of your library:
element.mylibrary = {};
element.mylibrary.foo = 'bar';
The problem is that a future HTML standard could define mylibrary as a native property, so there could be problems.
Symbol approach
ECMAScript 6 introduces symbols, which can be used as properties. The advantage is that each symbol has an unique identity, so you don't need to worry about some other library or a future standard using the same properties as your code.
var foo = Symbol("foo");
element[foo] = 'bar';
WeakMap approach
ECMAScript 6 introduces WeakMaps, which allow you to associate data with objects in a way that, if the objects are no longer referenced anywhere else, they will be garbage collected.
Like the property approach, they allow you to store arbitrary data.
Since the data is not stored in the elements themselves, there is no risk of conflicts.
var allData = new WeakMap();
var data1 = allData.get(element1) || {}; // read
data1.foo = "bar";
allData.set(element1, data1); // write
An HTML element in JavaScript is just a JavaScript object, so you can certainly add arbitrary properties to it. JavaScript will handle the garbage collection just fine.
The data- attribute is another option and might be a better choice if your properties are strings; their values will be visible in the DOM (which might be a good thing for debugging). If your properties are themselves objects, then you'd have to stringify them (and reverse the process to retrieve their values).
I've noticed that when I am trying to check for a variable within the window object, javascript will return the DOM node of an id matching the variable name. Consider the following code:
<html>
<body>
<div id='hello'>
</div>
<script>console.log(window.hello);</script>
</body>
</html>
In this example, the console will output the DOM object representation of <div id='hello'> and any of its descendants. I've also observed that overwriting window.hello doesn't affect the DOM and subsequent operations show the new assignment.
Is there a way to type check specifically for a DOM object? Alternatively, is there a way to avoid this behavior? Although not difficult, having to be conscious of page ID's when choosing namespaces seems like it could become very counter intuitive.
Some browsers will create a global variable for each id value in the document. In general, you should use:
document.getElementById("hello")
to retrieve DOM elements by id.
This is yet another reason why you should generally avoid using the global namespace any more than required as it is significantly polluted by this browser practice.
If you really want to test whether something is DOM object, you can see how that is done here: JavaScript isDOM -- How do you check if a JavaScript Object is a DOM Object?, but you should, in general, not need to do this for regular DOM programming purposes.
This is actually the HTML5 standard:
http://www.whatwg.org/specs/web-apps/current-work/#named-access-on-the-window-object
A way to be safe about this is to make all your javascript objects and functions within a "namespace":
var objs = {
someObject: document.getElementById( "someThing" ),
someFunction: function() {},
hello: {
...
}
};
//Now you can access it without interfering with the DOM "hello"
console.log( window.objs.hello );
I read somewhere that objects were basically hash tables, and you could assign values to them willy nilly. Well, I am hoping to take advantage of this, but I want to know if it is even possible, if it is considered "correct", and, if there are any unwanted situations.
My situation:
I have a serious of objects (the kind which CANNOT be stored in the DOM!) which I want to assign to DOM objects. My plan is to:
FInd a dom object (A div, or area of some form), and then assign that to the variable myVar
I will then call: myVar.customVal = value
customVal of course is not defined in the DOM specification. Will that even work, though? Will it show up in the DOM, or stay a virtual variable? Is there any way to assign custom values to members of the DOM for access later?
You can do it:
var foo = document.getElementById('sidebar');
foo.party = 3;
console.dir(foo);
But no, it's not considered good practice. Rather, consider using HTML5's custom data attributes, or better yet, jQuery's abstraction of them.
What's the jQuery equivalent for each():
$(".element").each(function(){
// do stuff
});
when attaching a function to a single element, like #element ?
You can always reference the jQuery object in a variable:
var $el = $('#element');
...then manipulate it.
$el.doSomething(); // call some jQuery methods from the cached object
$el.doSomethingElse();
If the reason you wanted .each() was to reference the DOM element as this, you don't really need the this keyword to do it, you can simply grab the DOM element out of the jQuery object.
var element = $('#element')[0]; // both of these give you the DOM element
var element = $('#element').get(0); // at index 0
The two of these are equivalent, and will retrieve the DOM element that would be referenced as this in the .each().
alert( element.tagName ); // alert the tagName property of the DOM element
alert( element.id ); // alert the ID property of the DOM element
I'd note that it isn't necessarily bad to use each to iterate over a single element.
The benefits are that you have easy access to the DOM element, and you can do so in a new scope so you don't clutter the surrounding namespace with variables.
There are other ways to accomplish this as well. Take this example:
(function( $ ) {
// Inside here, "this" will refer to the DOM element,
// and the "$" parameter, will reference the jQuery library.
alert( this.tagName );
// Any variables you create inside will not pollute the surrounding
// namespace.
var someVariable = 'somevalue'; // is local to this function
}).call( $('#element')[0], jQuery );
To directly answer your question, .each() operates normally on element sets of any size including 1.
You can also omit the .each() call completely and just call jQuery methods on $('#element'). Remember that you can chain most if not all jQuery method calls as they return the jQuery object. This even works on multiple elements for the matter, depending on what the methods do.
$('#element').doSomething().doSomethingElse();
If you need to reference the object multiple times, make a variable:
var $elm = $('#element');
$elm.doSomething();
doSomethingElse($elm);
Use first().
each() matches all elements, while first() matches only the first.
There are other selectors too. When you use the id in the selector, you will only get one element. This is the main difference between .element and #element. The first is a class that can be assigned to many elements, while the second is an id that belongs to only (at most) one element.
You can still use each if only one (or 0) element is returned. Also, you can skip each altogether if you want to link an event. You use each when you want to execute a specific function for each element in the list of elements.
If there is only 1 element, you can access it normally using the selector.
$('#your_element').your_event(function() {
});
Behind the scenes, each is just a for loop that iterates through each element in the map returned by jQuery.
It is essentially† the same as:
var i, map = $('...selector...');
for (i = 0; i < map.length; i++)
{
someFunction(i, map[i]);
}
† There's more to it than this, involving calling the function in the context of the map element etc.
It's implementation is to provide a convenient way to call a function on each element in the selection.
Do you mean like $('#element').children().each()
supposing you have something like a ul with an id and you want the li each inside it?
If the intention is to call a (non-jQuery) function in a new scope I think using "each" still is a valid (and probably the most elegant) way and it stays true to the jQuery syntax although I agree to Alex, it feels wrong since it might have some overhead.
If you can change the syntax use $('#element')[0] as replacement for this (as already mentioned in the accepted answer).
Btw could someone with enough reputation please correct the comment of "zzzzBov" about the accepted answer?
$('#element')[0] and $('#element').get(0) ARE! the same, if you want the jQuery object use $('#element').first() or $('#element').eq(0)
Is there a way to get JavaScript this from jQuery this?
this == this, whatever this is.
this is a not jquery it is a special, somewhat convoluted, javascript keyword that describes the current scope of execution.
your challenge may be determining or controlling what this is.
There is:
$('a').click(function(){
var jqueryobject = $(this);
var domelement = this;
});
Within such a closure, this always represent the native DOM element which must/can be wrapped into a jQuery object.
If you already got a jQuery object and need to get the DOM element either use
var DOMelement = $(this)[0];
or
var DOMelement = $(this).get(0);
Since jQuery objects are array like objects you can always grab them with standard array access [] notation. The jQuery method .get() will actually do the same. With both ways, you'll receive the DOM element at that array position.
General - what is this ?
this contains a reference to the object of invocation
this allows a method to know what object it is concerned with
this allows a single function object to service many functions
So this is the most important part of all protoypal inheritance things
I don't really understand what you're asking for here, but I'll give it a shot. Firstly, remember that jQuery is just a series of functions written in Javascript. The this keyword is literally the same in "both" contexts.
Perhaps you want to get the actual DOM element instead of the jQuery object? You can use .get():
// let's say there's a single paragraph element
var obj = $('p'); // obj is a jQuery object
var dom = obj.get(0); // dom is a DOM element
Try to access this (DOM element) instead of $(this) (jquery object).