Many of us non-jquery javaScript developers, have been using domElement.setAttribute, and its sister functions, to hack our way around countless dom elements, for all of internet eternity.
Be it, css, dom classNames, storing/retrieval of variable data, etc...
var b = document.getElementById("someDiv");
b.setAttribute("align", "center");
So what's the purpose / practical use of its domElement.setAttributeNS variant? This question is in regards to web browser display / uses. And not in the context of XML. In which setAttributeNS has lots of uses.
var d = document.getElementById("someDiv");
d.setAttributeNS("http://www.mozilla.org/ns/specialspace", "align", "center");
In HTML Documents (i.e. Document objects create by the text/html parser) there really aren't many uses for setAttributeNS.
But if look at what the HTML5 parser is required to do when parsing foreign content (i.e. SVG abd MathML) we find this table: adjust foreign attributes.
So it automatically moves and renames some attributes into the XLink, XML and XMLNS namespaces. When you are manipulating the DOM via functions like setAttribute and setAttributeNS, that automatic moving and renaming won't happen, so to get the attributes into their correct namespaces, you need to use setAttributeNS to create and modify them.
xlink:href is possibly the most common of these to be set via setAttributeNS()
That's domElement not htmlElement.
It is useful when you are working with a DOM constructed from XML that uses elements from multiple namespaces.
(And if you want to know why namespaces are useful, then see this question)
Related
JavaScript lets you add arbitrary properties and methods to any object, including DOM nodes. Assuming the property was well namespaced (something like _myLib_propertyName) so that it would be unlikely to create a conflict, are there any good reasons not to stash data in DOM nodes?
Are there any good use cases for doing so?
I imagine doing this frequently could contribute to a sloppy coding style or code that is confusing or counter-intuitive, but it seems like there would also be times when tucking "custom" properties into DOM nodes would be an effective and expedient technique.
No, it is usually a bad idea to store your own properties on DOM nodes.
DOM nodes are host objects and host objects can do what they like. Specifically, there is no requirement in the ECMAScript spec for host objects to allow this kind of extension, so browsers are not obliged to allow it. In particular, new browsers may choose not to, and existing code relying on it will break.
Not all host objects in existing browsers allow it. For example, text nodes and all ActiveX objects (such as XMLHttpRequest and XMLDOM objects, used for parsing XML) in IE do not, and failure behaviour varies from throwing errors to silent failure.
In IE, the ability to add properties can be switched off for a whole document, including all nodes within the document, with the line document.expando = false;. Thus if any of the code in your page includes this line, all code relying on adding properties to DOM nodes will fail.
I think more than anything, the best reason not to store data in the DOM is because the DOM is meant to represent content structure and styling for an HTML page. While you could surely add data to the nodes in a well-namespaced manner as to avoid conflicts, you're introducing data state into the visual representation.
I'm trying to find an example for or against storing data in the DOM, and scratching my head to find a convincing case. In the past, I've found that the separation of the data state from the visual state has saved headache during re-designs of sites I've worked on.
If you look at HTML 5 there is the data attribute for fields that will allow you to store information for the field.
Don't be surprised to run into trouble with IE 6 & 7. They are very inconsistent with setAttribute vs set as a property.
And if you're not careful you could set circular references and give yourself a memory leak.
http://www.ibm.com/developerworks/web/library/wa-memleak/
I always set node properties as a last resort, and when I do I'm extra careful with my code and test more heavily than usual.
For what it's worth, the D3.js library makes extensive use of custom properties on DOM nodes. In particular for the following packages that introduce interaction behaviors:
https://github.com/d3/d3-zoom - the __zoom property
https://github.com/d3/d3-brush - the __brush property
D3 also provides a mechanism for putting your own custom properties on DOM elements called d3.local. The point of that utility is to generate property names that are guaranteed not to conflict with the DOM API.
The primary risk I can see associated with custom properties on DOM nodes is accidentally picking a name that already has some meaning in the DOM API. If you use d3.local or maybe prefix everything with __, that should avoid conflicts.
I have a question about the following piece of Javascript code, it is very basic.
var elNote = document.getElementById('note');
elNote.TextContent = 'Hello';
I am new to Javascript and would like to know what is going on here. My book will most likely explain it later, but I would like to learn now.
It is my understanding that elNote gets assigned the html element named note.
My question is if html elements have built in properties, since we select the Property TextConent from the element note. It is also my understanding that elements such as note, are NODES. Does Javascript create and "inject" properties into elements so that they can be modified. I don't know, I'm really trying to think what is going on. thanks.
Yes you can use for example:
elNote.textContent = 'Hello world'; // For raw text content
elNote.innerHTML = '<h1>Hello</h1> world'; // For raw text content
elNote.value = 123; // Tipically for <input> and <button> tags value
Javascript is a loosely typed language, it assigns properties and related methods to the nodes when DOM is defined and its properties vary browser to browser and tier versions.
as far as TextContent is concerned it is described here
These properties are specific to the type of nodes like
document it self is also a node but it is a top level node and it does not contains properties like innerText etc.
For more deep understanding of Document Object Model please refer this wiki
Summing up:
The W3C DOM and WHATWG DOM standards form the basis of the DOM implemented in most modern browsers. Many browsers offer extensions beyond the standard, so care must be exercised when using them on the web where documents may be accessed by various browsers with different DOMs. Copied from this source It looks like DOM is defined by Browsers in the form of javascript readable / accessible objects and their properties vary browser to browser.
For the past few years I have always used a client-side hidden <input> field to store a server-side value and use it in Javascript land.
For example, let's say I need an Ajax timeout value from my app configuration.
I'd probably store it like this in my JSP:
<input type="hidden" id="ajaxTimeout" value="${serverValue}" />
and then use it like this where my AJAX call lived in an external file:
$("#ajaxTimeout").val()
I was having a discussion about this today and it was suggested that it is best practice to store values which are only going to be used by Javascript within HTML <meta> tags.
Does this matter? Is there a preferred way to obtain server-side information which is solely to be used in Javascript?
My understanding is that if the hidden input field is not part of a form then it is safe enough to use to store value as it won't be attached to any requests. Having said that, I've always thought this was indeed a bit of a hack.
Thoughts?
::EDIT::
Two fantastic answers:
Use objects literals for general in-page data that is not tied to any particular DOM element.
Use data attributes to store custom data tied to DOM elements: http://www.w3.org/TR/2010/WD-html5-20101019/elements.html#attr-data
In addition to the plain old object literal method given in other answers, if the value you want to pass to the client is about a specific DOM element (or there is a DOM element that represents the logical object that the value is about), you can put the value in a data attribute:
<div id="videoplayer" data-startplayingat="1:02">HTML Content</div>
This is accessible as an entire attribute, data-startplayingat, or in modern browsers there is the dataset attribute. jQuery syntax is $('#videoplayer').data('startplayingat').
The official W3C spec on data attributes explains all this.
Here are a few interesting highlights:
The name must not use upper case letters, and must be XML compatible.
The dataset attribute converts dashes, such that a name like start-playing will become startPlaying.
One potential drawback for the object literal method (which I like and have used myself) is that if you want the object in a .js file, then normally static javascript files have to be run through your dynamic parser--which will cause a potentially small (but still present) performance loss. Putting the object declaration into a <script> tag in an HTML file works around this, but then you can have script load order issues to deal with.
We personally do something like this:
var options = {
selector: '#divId',
serverSideVariableHere: <%=AspNetProperty %>,
anotherServerSideVariableHere: <%=AspNetPropertyTwo %>
}
var viewModel = new KnockoutViewModel(options);
ko.applyBindings(viewModel, $(options.selector)[0]);
This is simply an example using KnockOut JS, but this idea can be expanded to any JavaScript library you choose to use (or not ;))
We then pass these options to whatever use them, such as Knockout ViewModels, or whatever. That way our JavaScript remains testable and we can pass in whatever values we want to our tests.
Using meta tag for something other than browser meta-"instructions" is no less of a hack IMO.
I would consider storing JavaScript data where it belongs - in JavaScript, using JavaScript object literals.
I strongly prefer JSON snippets in data- attributes. This lets you scope them to the related HTML element, and you don't pollute your Javascript global namespace, or have to generate additional code to handle namespacing otherwise. Coupled with a JSON serialiser on the server side this minimises having to manually escape anything in your values.
(Also I have a Thing™ against <script> tags with content in general. View and logic separation and all that.)
I am building a tree (for SOAP) using DOM. I would like read the following info at a certain node:
Is an XML namespace already "imported" into the document (with xmlns:blah="http://...) - knowing the http://... part.
What moniker (in the above example blah) used.
Is there any way other than the manual: to walk chain of ancestors and iterate on attribute nodes, find any starting with xmlns: checking the value and if match return the rest of the attribute name?
Aside the usual methods such as document.getElementsByTagName, DOM offers their namespaced versions: document.getElementsByTagNameNS
Such methods take the namespace URL as their first argument.
document.getElementsByTagNameNS('http://...', 'abc');
By the way, using the regular methods, the elements might be available as…
document.getElementsByTagName('xmlns\\:abc');
This works for me in case of a HTML DOM even without "importing" any namespace.
Update:
The method OP was looking for is document.lookupPrefix('http://...')
I've been looking for a straight answer for this (I can think of lots of possiblities, but I'd like to know the true reason):
jQuery provides a .data() method for associating data with DOM Element objects. What makes this necessary? Is there a problem adding properties (or methods) directly to DOM Element Objects? What is it?
Is there a problem adding properties (or methods) directly to DOM Element Objects?
Potentially.
There is no web standard that says you can add arbitrary properties to DOM nodes. They are ‘host objects’ with browser-specific implementations, not ‘native JavaScript objects’ which according to ECMA-262 you can do what you like with. Other host objects will not allow you to add arbitrary properties.
In reality since the earliest browsers did allow you to do it, it's a de facto standard that you can anyway... unless you deliberately tell IE to disallow it by setting document.expando= false. You probably wouldn't do that yourself, but if you're writing a script to be deployed elsewhere it might concern you.
There is a practical problem with arbitrary-properties in that you don't really know that the arbitrary name you have chosen doesn't have an existing meaning in some browser you haven't tested yet, or in a future version of a browser or standard that doesn't exist yet. Add a property element.sausage= true, and you can't be sure that no browser anywhere in space and time will use that as a signal to engage the exciting DOM Sausage Make The Browser Crash feature. So if you do add an arbitrary property, make sure to give it an unlikely name, for example element._mylibraryname_sausage= true. This also helps prevent namespace conflicts with other script components that might add arbitrary properties.
There is a further problem in IE in that properties you add are incorrectly treated as attributes. If you serialise the element with innerHTML you'll get an unexpected attribute in the output, eg. <p _mylibraryname_sausage="true">. Should you then assign that HTML string to another element, you'll get a property in the new element, potentially confusing your script.
(Note this only happens for properties whose values are simple types; Objects, Arrays and Functions do not show up in serialised HTML. I wish jQuery knew about this, because the way it works around it to implement the data method is absolutely terrible, results in bugs, and slows down many simple DOM operations.)
I think you can add all the properties you want, as long as you only have to use them yourself and the property is not a method or some object containing methods. What's wrong with that is that methods can create memory leaks in browsers. Especially when you use closures in such methods, the browser may not be able to complete garbage cleaning which causing scattered peaces of memory to stay occupied.
This link explains it nicely.
here you'll find a description of several common memory leak patterns
It has to do with the fact that DOM in IE is not managed by JScript, which makes it completely different environment to access. This leads to the memory leaks http://www.crockford.com/javascript/memory/leak.html. Another reason is that, when people use innerHTML to copy nodes, all those added properties are not transfered.