Is it a bad practice to reference Javascript objects from DOM elements? - javascript

As a "best practice" for front-end developers, is it bad to use the "control" property to reference back to the Javascript object?
Here's a link to the property in question:
https://developer.mozilla.org/en/XUL/Property/control
I've seen a lot of Javascript functions that reference DOM elements using selectors and then perform DOM manipulation that way. But what if we started by traversing through the DOM tree and we have the DOM element first?
EDIT 1
Okay, it seems like there are some interest here but no contributions for some reason. This started as a conversation between me and my co-worker. He was concerned about circular references and possible cases of losing references... does that apply here? I thought as long as we don't call delete <javascript object> then we're fine.
EDIT 2 I found this: JQuery methods and DOM properties
In my world right now, I'm using the Microsoft AJAX Library where we created multiple ScriptControls and put them on various pages; which in turn, (the ScriptControls) get "modified" by page's events and sometimes events of other ScriptControls. When pages need to do something with the DOM element, the Javascript would use the respective Javascript Object's methods.
However, it seems in JQuery (based on the other question), it's common to get the DOM element then use .get(0) to grab the JQuery object out of it (if it exists).
So I guess this is a witch hunt so far and there's still no right answer to my question :(
I know I'm still lacking an example but I'm not sure how to approach this.

I am not too sure what exactly you're referring to. Could you provide a simple code example? Otherwise, your question is a bit vague IMHO. I'll give it a shot anyways:
I do not understand why there would be any lost or circular references. The control attribute is just the id (string) of the "controlling" DOM Element, not a reference to the actual DOM Element. If you delete label.control it will no longer be associated with the other DOM Element.

Related

JavaScript variable equals jQuery selector creates open and closing tags. Why?

Please be nice. My first question here. I'm learning JavaScript and jQuery. Google isn't much help because I don't know how to ask the right question. Need human intervention please. I'm trying to figure out what is going on with this simple bit of code:
var myVar = $("<p>");
This creates an opening and closing <p> tag and I don't understand why.
Next, I'll add this paragraph to an existing element #myDiv. For example:
$("myDiv").html(myVar); results in the following:
<div id="myDiv"><p></p></div>
Continuing...
$("myDiv").html(myVar.text("A string for the paragraph"));
Results in:
<div id="myDiv"><p>A string for the paragraph</p></div>
Why does that first snippet create an opening and closing <p> tag? What is this called?
It's simply a more concise method of this in pure JavaScript:
var myVar = document.createElement("p");
And that goes to jQuery like this:
var myVar = $("<p></p>");
And because it's jQuery, and it gets more and more concise, it eventually becomes:
var myVar = $("<p>");
This is the right kind of question to be asking while you learn, so good for you! That being said, one SO post won’t be able to completely answer it, at least in the way that I think you're asking it, but I (we) will give you what I can.
To begin, the way that JavaScript interacts with HTML is through the Document Object Model (DOM). This is like taking an entire HTML document and cutting it up into the individual elements, tags, attributes, etc., and then constructing a representation of that document in "plain" JavaScript as a (very large) Object. The variable name assigned to this Object is document. This special Object has all sorts of magical properties and methods (functions) that can be used to read and update any piece of the DOM (which ultimately translates into the HTML you see in your browser).
What I've described so far has nothing to do with jQuery, and all of that manipulation can be done with plain JavaScript (like Jack Bashford's answer, for example). However, due to the way that browsers and other web technologies have evolved over the years, many "gotchas" exist (or used to exist) when it comes to doing any of this stuff in "plain" JavaScript. jQuery is an incredibly important tool, historically speaking, because it provided a "standard" way to write very direct code to do all of this DOM reading or manipulation, and the jQuery library would make sure that all of the "gotchas" were avoided.
So, what is jQuery (in code, that is)? Well, there could be many technical answers to that, and one important technical answer is that it is an Object, because in JavaScript, (almost) EVERYTHING is an Object. However, let's focus on the question at hand, and the code you provided:
$("<p>");
Here, the dollar sign IS jQuery (or a variable pointing to the jQuery Object). The parentheses that follow indicate that the jQuery Object is being called as a function. It is like saying, in code, "do the jQuery thing with this string of characters: '<p>'." Taking a step back, the full statement
var myVar = $("<p>");
is saying "this variable 'myVar' is now pointing to the results of whatever doing the jQuery thing with '<p>' will give us."
The "magical" thing about writing in jQuery is that the syntax almost always feels the same (and gives it an intuitive feel).
Grab the jQuery Object. This is usually the variable $, but jQuery will also work.
Call the function ($()). There are cases where you don't, like ajax requests, but that's a separate topic and use case.
Supply it with any kind of selector ($('#myDiv')), which is a way of referring to specific HTML elements based on their properties and location in the document (here we are looking up a specific element based on it's id).
Work with the result ($('#myDiv').html(...etc))
I'll point out at this point that the jQuery documentation should be handy so you know what you're getting as a result of any specific function call, but in almost all cases, this function will return another jQuery Object that holds references to whatever elements you selected or manipulated during that function call.
In the latter example, we will receive a reference to the #myDiv element, on which we then call another function (.html()) that will either read or update the contents of that html element.
In the case of the line you specifically asked about, the syntax used to "select" a 'p' tag will be interpreted by jQuery not to look up all 'p' elements in the document (that syntax would be $("p")), but rather to create a single new 'p' element and store it in memory as a jQuery Object that points to this newly created element. Read more about that syntax and its possibilities here.
Well, I hope that was helpful. I sure enjoyed writing it, and even learned a few things along the way myself.

Is there a program method to find javascript code fragment that sets "display:none" to element?

I have a big working project with massive frontend javascript code. If I add elements with class "icon" to one of templates, this elements get display:none at once. Obviously it comes from javascript, but I can't find it by file searching with ".icon" and related.
Is there a program way to find where this setting comes from? "Where" means anything helpful - function name, file name or something.
Your problem is one of the reasons I somewhat disagreed with the Unobtrusive JavaScript mantra from a few years back, which decreed that you should always target elements via selector hierarchy instead of attributes like "onload" on the element themselves. It becomes a nightmare to track down why a given element is affected. It could be because of a class, or because the element has ANY class at all, or if its class starts with "ic", etc etc etc.
Since you mention that it only happens when you apply the "icon" class, its definitely still most likely steaming up from that. Keep searching through all the JS methods that fire at pageload and look for "display: none" or "hide()" methods. Some of jquery's animation methods might be the culprit too, if they are running fast enough.

performance issue : storing a reference to DOM element vs using selectors

So in my app, the user can create some content inside certain div tags, and each content, or as I call them "elements" has its own object. Currently I use a function to calculate the original div tag that the element has been placed inside using jquery selectors, but I was wondering in terms of performance, wouldn't it be better to just store a reference to the div tag once the element has been created, instead of calculating it later ?
so right now I use something like this :
$('.div[value='+divID+']')
but instead I can just store the reference inside the element, when im creating the element. Would that be better for performance ?
If you have lots of these bindings it would be a good idea to store references to them. As mentioned in the comments, variable lookups are much much faster than looking things up in the DOM - especially with your current approach. jQuery selectors are slower than the pure DOM alternatives, and that particular selector will be very slow.
Here is a test based on the one by epascarello showing the difference between jQuery, DOM2 methods, and references: http://jsperf.com/test-reference-vs-lookup/2. The variable assignment is super fast as expected. Also, the DOM methods beat jQuery by an equally large margin. Note, that this is with Yahoo's home page as an example.
Another consideration is the size and complexity of the DOM. As this increases, the reference caching method becomes more favourable still.
A local variable will be super fast compared to looking it up each time. Test to prove it.
jQuery is a function that builds and returns an object. That part isn't super expensive but actual DOM lookups do involve a fair bit of work. Overhead isn't that high for a simple query that matches an existing DOM method like getElementById or getElementsByClassName (doesn't in exist in IE8 so it's really slow there) but yes the difference is between work (building an object that wraps a DOM access method) and almost no work (referencing an existing object). Always cache your selector results if you plan on reusing them.
Also, the xpath stuff that you're using can be really expensive in some browsers so yes, I would definitely cache that.
Stuff to watch out for:
Long series of JQ params without IDs
Selector with only a class in IE8 or less (add the tag name e.g. 'div.someClass') for a drastic improvement - IE8 and below has to hit every piece of HTML at the interpreter level rather than using a speedy native method when you only use the class
xpath-style queries (a lot of newer browsers probably handle these okay)
When writing selectors consider how much markup has to be looked at to get to it. If you know you only want divs of a certain class inside a certain ID, do one of these $('#theID div.someClass') rather than just $('div.someClass');
But regardless, just on the principle of work avoidance, cache the value if you're going to use it twice or more. And avoid haranguing the DOM with repeated requests as much as you can.
looking up an element by ID is super fast. i am not 100% sure i understand your other approach, but i doubt it would be any better than a simple lookup of an element by its id, browsers know how to this task best. from what you've explained I can't see how your approach would be any faster.

Storing custom data in dom elements

Is this wrong? If so why?
var elm = document.getElementById("myElm");
elm.customValue = {attr1 : "test", attr2 : "test"};
I understand how to use the data attributes, but I don't want to muddy up my dom with all those attributes.
This introduces a memory leak in some browsers because you bind a native C object (the DOM element) and a JS object together and some garbage collection algorithms cannot deal with this. IE is one of them.
Here is an MSDN article about IE memory leaks: http://msdn.microsoft.com/en-us/library/ie/bb250448(v=vs.85).aspx
Bottom line, why wouldn't you use the proper tools available? You have no idea if in the future, near or far, whatever custom property name you are using will be added to the w3c specifications for that particular element. Now, suddenly your code is broken.
Never mind that adding custom properties to elements which already have defined properties makes your code a maintenance nightmare. Whether it's you or someone else maintaining it in the future, there's going to be a "wtf" moment where the developer is trying to igure out if a) a custom property was added to the element or b) the element itself is in fact a custom object.
Finally, what if that element is replaced in the dom via Ajax or dynamic HTML? Now the property is gone and your code is broken.
You should consider HTML5 data-attributes.
From the man himself: http://ejohn.org/blog/html-5-data-attributes/

DOM properties/methods that aren't available in jQuery?

Following up on my question about jQuery.get() I was wondering if there is a list of DOM properties and methods that aren't available in jQuery that can only be accessible if you were working with the raw DOM object (i.e. $("#someID").get().scrollHeight; )
I haven't encountered a list but if one existed it would probably be quite lengthy. In addition to browser-specific (proprietary) properties there's a bunch of other less useful properties and methods not currently abstracted by jQuery. But then, I don't really see this as a problem, or even a valid point of discussion because jQuery IS JavaScript; if you need access to something beyond what jQuery provides then you can use get() or access a specified element within one of your "jQuery collections" like an array:
jQuery(elem)[0].someDOMProperty;
Plus jQuery provides absolutely no support for non-element nodes within the DOM. If, for whatever reason, you need direct access to comment nodes, text nodes etc. then you'll need to use the "raw" DOM.
I don't know of a compiled list of DOM operations/properties that are NOT available in jQuery (and a quick google search didn't turn anything up), but if you go to http://api.jquery.com/ you can see the entire API, and even download it as an Adobe AIR app in case you don't have internet when you need it.
No. JQuery is just JavaScript. If you can do it in JavaScript, you can do it in jQuery. Some properties and methods are overwritten in the context of a jQuery object and that's where you would want to us the get() method--to 'get' (i.e. access) the standard property/method.
That's really as complicated as it is.
Every attribute of every element is accessible through the attr() function. If you could do a document.getElementById() on that element and then access a property, you can also do it using the attr() function. However, some properties are accessed more easily in other ways when using jquery. For example, to see if an element is hidden or visible, you could do:
var isVisible=$("#el").is(":visible");
instead of using the attr() method. Similarly, you can find the selectedIndex of dropdowns and the text of the selected option, in easier ways than using the attr() method. This pdf outlines some of these easier approaches.
To access a css property, you are better off doing:
var fontWeight=$("#el").css("fontWeight");
rather than using get() or attr(). You can also set the css properties in this way, e.g:
$("#el").css("fontWeight","bold");
I could be wrong, but I think you can access any properties via the attr method.

Categories