Site Navigation

Showing posts with label DOM. Show all posts
Showing posts with label DOM. Show all posts

Wednesday, October 17, 2007

bug 256 - DOM nodeType constants are not in IE and Opera

Issue: #256
Affects: IE5, IE5.5 IE6, IE7, IE8 Beta 1, Opera 8.2, Opera 9.2
Fixed in: Opera 9.50 alpha 1 build 9500
MSIE Feedback ID: 339307

The ECMAScript specification for the DOM provides a set list of element types or nodeTypes... Text Elements, Node Elements, Comments, etc. They are numbered integers, with a Constant defined for easy to read comparison purposes. The only problem is, that they are not Constants at all, in IE or Opera.

NodeTypes:

interface Node {
// NodeType
const unsigned short ELEMENT_NODE = 1;
const unsigned short ATTRIBUTE_NODE = 2;
const unsigned short TEXT_NODE = 3;
const unsigned short CDATA_SECTION_NODE = 4;
const unsigned short ENTITY_REFERENCE_NODE = 5;
const unsigned short ENTITY_NODE = 6;
const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
const unsigned short COMMENT_NODE = 8;
const unsigned short DOCUMENT_NODE = 9;
const unsigned short DOCUMENT_TYPE_NODE = 10;
const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
const unsigned short NOTATION_NODE = 12;
//...
}


Example:

<script type="text/javascript">
var obj = document.getElementById('someID');
var textContent [];
for(var i=0;i<obj.childNodes.length;i++){
if(obj.childNodes.item(i).nodeType == TEXT_NODE){
textContent.push( obj.childNodes.item(i) );
}
}
alert('The inner text without HTML tags is: ' + textContent.join(', '));
</script>


In a spec compliant browser, the code should be able to test against the TEXT_NODE constant.


Known Workarounds: One. It is extra processing, but each element type can be defined as globals at the begining of every page.

Example Workaround Code:

<script type="text/javascript">
(function(){
var NodeTypes = ['ELEMENT', 'ATTRIBUTE', 'TEXT', 'CDATA_SECTION',
'ENTITY_REFERENCE', 'ENTITY', 'PROCESSING_INSTRUCTION',
'COMMENT', 'DOCUMENT', 'DOCUMENT_TYPE',
'DOCUMENT_FRAGMENT', 'NOTATION'];
for(var i=0i<NodeTypes.length;i++){
window[NodeTypes[i] + '_NODE'] = (i + 1);
}
})();
</script>



Related Issues: None.

Tuesday, October 16, 2007

bug 124 - setting innerHTML problem no.1 in IE

Issue: #124
Affects: IE6, IE7

Setting the .innerHTML in IE can fail in the following scenario.
If you add multiple lines of content (e.g. with line beaks) to an empty element with the overflow set to auto.

Example:

<div id="test" style="border:1px solid #ff0000;height:200px;overflow:auto;">before</div>
<script type="text/javascript">
var divObj = document.getElementById('test');
divObj.innerHTML = 'first<br/>second<br/>third';
</script>


You would expect to see the div content update to display:

first
second
third


However IE will update the DOM, but not the content on screen. IE doesn't update the visible height of the DIV, resulting in the "second, and third" not showing.


Known Workarounds: None.


Related Issues: None.

Saturday, August 4, 2007

DOM Method Support - What dreams are made of...

In the ideal world, each and every browser would support these properly, and development would be a breeze... but alas, that is not the case.

For each method listed below, I'll link to the various bugs in terms of their implementation.

getElementById( id )

What seems like the most simplistic method available, yet also one of the most powerful, is unfortunately broken. (bug 152) describes how Internet Explorer, will return an element, if it matches by the id attribute as designed, but will also return a match based on the name attribute. It will also disregard your case-sensitive searches and return elements with IDs with non-matching case (bug 154).

createElement( type )

Another super simple, but super useful method, is again plagued with issues. The correct syntax is:


var myDiv = document.createElement( 'div' );
//or
var myHeader = document.createElement( 'h2' );
//or
var myTextBox = document.createElement( 'input' );


Well, lets say you are building up some form elements on-the-fly (very common in today's Web 2.0 world). Say you want to add a hidden field named "showOption" that you will pre-populate with the value "messages", just before the form is submitted to take the user directly to a certain screen.

The code would look something like this:
development would be a breeze... but alas, that is not the case.


var hiddenOption = document.createElement( 'input' );
hiddenOption.setAttribute('name', 'showOption');
hiddenOption.setAttribute('value', 'messages');
hiddenOption.setAttribute('type', 'hidden');
var myForm = document.forms[0];
document.appendChild(hiddenOption, myForm);
myForm.submit();


So as long as you have a form, this should work! Well, not in Internet Explorer!

As it turns out, in (bug 235) Internet Explorer, you can't set the name attribute on an Element... any Element! To overcome this, there is a hack, which explains why the createElement method is broken (bug 124) in IE. To make the above code snippet work in IE, you need to do this:


var hiddenOption = document.createElement( '<input name="showOption">' );
hiddenOption.setAttribute('type', 'hidden');
hiddenOption.setAttribute('value', 'messages');
var myForm = document.forms[0];
document.appendChild(hiddenOption, myForm);
myForm.submit();


Did you spot the changes?

Change#1.) The Element we create is a string that is the HTML tag, with the name attribute. This is not only quite ugly (mixing tags in strings), but also completely against the spec! document.createElement Spec Reference.

Change#2.) We moved the "type" attribute up to be the first attribute set. The reason for this, is that in IE you can't change the type attribute (bug 237) after the node is added to the DOM, and the default type is always "text". In this code snippet, it didn't matter, but if we had added this to the DOM, before setting the type, we would have been stuck.