I'm not sure if this is the best place for this post, but it really must be said. I've been working in this industry for a long time, and have dealt with my fair share of cross-browser issues. I usually don't even complain about the complexities and constant confusion of what is supported by which browser, usually I'm the guy on the side of the ANSI standards giving the disapproving look to the fellows at Microsoft. I'm not your typical web developer, I prefer better performing browsers over ease of development, in most cases, which is why I recommend FireFox to almost anyone who asks me which browser is best.
While working on our latest release of Navigator, it became extremely important to provide the ability to modify the resulting document after the client receives the output from the server, to formalize the look and feel of the menu elements. Instead of using some of the new concepts of shooting XML formatting down to the browser for Javascript to handle, a method which is by no means Search Engine friendly, we provide a more universally accepted HTML format which is automatically modified to set class and display attributes. This requires a recursive method of re-rendering, starting with a call to our rendering routine for the Root element of the menu, and progressing through each contained child element.
Now, I reach the point of this post. Because I was modifying the Style attribute specifically within each of the nodes, and setting the className - both of which are provided by the ANSI standards, I needed to work directly with each of the HTMLElement objects. This method works great for setting the display information for a parent element, then setting the display attributes for each sub element, like the menu text, or any images which are contained within the menu. Hence, in IE you would normally work with the HTMLElement.children[] array. I was fully aware this was not supported by FireFox, and chose to use the HTMLElement.getElementsByTagName function for working with that browser. All seemed perfect in my world until I began to notice that the root menu items, and the sub menu items resulted in the same className assignment when viewed with FireFox.
After doing some thinking, I realized that the getElementsByTagName functionality returns all the elements from the requesting element - recursively. Meaning, the root node returns all the Root elements, and sub-elements, even though they are not at the same level of the node hierarchy. Due to this, many developers were recommending that I use the inferior childNodes property of my element to get access to the nodes which are immediate children of this element.
While, it is possible to use the childNodes property, it was nearly impossible to do what I was attempt with any level of convenience, because I had no access to the standard HTMLElement properties when working with the DOM nodes. I could add and remove attributes to my hearts content, but what I really needed was the simple ability to set the display of the style, and the className, and of course, recurse through the child element.
The headache began to pound as I struggled for a good 30 minutes to figure out how to progress forward, without taking a blade to my code to make it work with Nodes instead of HTMLElements. Searching through the web was fruitless, and I usually can find the information I need, or a sample of the functionality, but I must have been missing the best words, and Google was a complete waste of more time.
Finally, I came up with a simple solution, which, although it is not the most efficient in performance, it suited my needs correctly, using a combination of fetching of tag elements and utilization of the parentNode property.
In the end - for any of you who have had similar problems, or possibly, will stumble across the same issues as I. Lost in a realm which is half way between supported standards, and unsupported logical convenience, I bestow this small contribution. In the provided sample, assume “thisElement” is the node of which I want to retrieve all the children. The “children” variable will be the resulting Array.
-- CODE SNIPPET --
//ASSUMING WE WANT TO POPULATE THIS children ARRAY, WITH //THE CHILDREN OF THE HTMLElement IN QUESTION: thisElement. var children = []
//THIS WORKS IN IE if (thisElement.children) { children = thisElement.children; } //THIS WORKS FOR FIREFOX else { //GET ALL THE TAGS WHICH ARE WITHIN THIS TAG var allChildren = thisElement.getElementsByTagName('*');
//LOOP THROUGH THE TAGS for (var i = 0; i < allChildren.length; x++) { //ADD ONLY TAGS WHICH ARE DIRECT CHILDREN OF //THIS HTMLElement if (allChildren.item(i).parentNode == thisElement) children.push(allChildren.item(i)); } }
-- / CODE SNIPPET –
Anyone lost in the jungle of confusion of cross-browser Javascript manipulation, I feel for you. Even the pro's sometimes have their moments of utter frustration when it comes to these trivialities.
Happy Nuking!
|