www.webdeveloper.com
Results 1 to 15 of 15

Thread: questions about <input> tags and DOM

  1. #1
    Join Date
    Mar 2006
    Location
    Sacramento
    Posts
    73

    questions about <input> tags and DOM

    Hey guys,
    I put together a cool lil utility that modifies the DOM on the fly. The only problem with it is that for some reason it will not work with <input> tags, won't create them. This could have been an IE6 thing, as I haven't tried it in a while.

    Does anyone have any insight into this?

    (BTW... I've been using the utility below for a while now. It has slowly evolved over time, but it's solid. Feel free to use it. )

    Code:
    ChangeDOM = new ChangeDOM();
     
    //custom utility to change the DOM
    function ChangeDOM(){
    		//adds children to given node 
    		//"keys" format  - {"['elType'] or [element attribute] or ['text']":"[element type] or [attribute property] or [actual text],"":""...}
    		this.addChildren = function(keys,parentNodeObject){
    			var elName=document.createElement(keys["elType"]);
    			parentNodeObject.appendChild(elName);
    			for(var key in keys){
    				if(key != "elType"){
    					if(key == "text"){
    						var txt=document.createTextNode(keys[key]);
    						elName.appendChild(txt);
    					}
    					else elName.setAttribute(key,keys[key]);
    				}
    			}
    			return;
    		}
    		//clears all children from given node
    		this.clearChildren = function(parentNodeObject){
    			if(parentNodeObject.childNodes){
    				var nodechildren = new Array();
    				nodechildren = parentNodeObject.childNodes;
    				if(nodechildren.length>0)for(i=0;nodechildren.length;i++)parentNodeObject.removeChild(parentNodeObject.lastChild);
    			}
    			return;
    		}
    		//updates text for a given node
    		this.updateText = function(newText,parentNodeObject){
    			this.clearChildren(parentNodeObject);
    			this.addChildren({'text':newText},parentNodeObject);
    		}
    	}

  2. #2
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Quote Originally Posted by jnoster View Post
    The only problem with it is that for some reason it will not work with <input> tags, won't create them. This could have been an IE6 thing, as I haven't tried it in a while.
    Not very clear. It fails only in IE or in all the browsers?

    On the other hand I doubt it will work in IE in case of setting the name attribute. IE has a bug, it can not handle properly the name attribute with DOM methods. IE needs a workaround like:
    Code:
    var isIE=/*@cc_on!@*/false;//IE detector
    var newInput;
    if(isIE){//IE workaround
    newInput=document.createElement('<input name="newname">');
    }
    else{//other browsers
    newInput=document.createElement('input');
    newInput.setAttribute('name','newname');
    }
    ...

  3. #3
    Join Date
    Apr 2003
    Location
    Netherlands
    Posts
    21,654
    Not forgetting that the attributes class and style can't be set using setAttribute in IE

  4. #4
    Join Date
    Mar 2006
    Location
    Sacramento
    Posts
    73
    Interesting...

    Kor
    Like I said, it's been a long time since I tried it with an input tag of any kind. Maybe it's time to try it again.

    Thanks for the insight! I'll try and plug that in to the code.

    Fang
    You're right of course

  5. #5
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Moreover: IE needs another trick for DOM methods. In case of the HTML compounded attributes (maxlength, colspan, readonly ... and so on...) IE (not sure about IE8, but in IE6&7 for sure) needs them to be written in so called "camel case" - maxLength, colSpan, readOnly. Quite stupid I guess, but this is IE . Well, the good news is that will not affect the other browsers. These are able to handle the HTML attributes in "ignore case"

    There is no need to modify the code for that, but make sure you pass that kind of attributes in camelcase to your constructor.
    Last edited by Kor; 01-08-2010 at 03:28 PM.

  6. #6
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Quote Originally Posted by Fang View Post
    Not forgetting that the attributes class and style can't be set using setAttribute in IE
    Yeap. The simpler way is to use the old DOM0 trusty syntax:
    Code:
    element.className="classname";
    element.style.cssAttribute='whicevervalue';
    And even so, there are some cases when IE needs a special treatment.

    Don't mention about the events. IE does not consider them as attributes, thus ... well, if you need further advice about creating events or adding new functions to be called on a certain event, let us know

    Welcome in the crossbrowser weird world!
    Last edited by Kor; 01-08-2010 at 02:27 PM.

  7. #7
    Join Date
    Mar 2006
    Location
    Sacramento
    Posts
    73
    Thanks guys...

    Usually what I use it for is to just get some peice of text up on the browser, change some existing text, put up an image, etc.

    After an element is up there then it's easy to code afterward to add onclick, onmouseover, apply styles, etc.

    After working with PHP I wanted a nice and easy way to present HTML on the fly and this is what I came up with. Nope, it doesn't work with all attributes but it doesn't take much JS undersanding to know what to do with it. And so far, the only tag it won't work with is <input>

    It just really bugged me why it wouldn't work with <input>. And it seemed to me that it was across all browsers, but I don't remember. I was begining to think it was a security thing... but even that didn't made sense.

    So I appreciate the info on that bug... All hail IE!! {NOT}

  8. #8
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Quote Originally Posted by jnoster View Post
    It just really bugged me why it wouldn't work with <input>. And it seemed to me that it was across all browsers, but I don't remember.
    Compare carefully the codes. Maybe there is a typo somewhere, when you might have copyed/pasted them . Small things (but SO important!) like that. Does your document have a Doctype? Which one? If XHTML, has your embedded code a CDATA escape? Is you full document valid (see W3C validation site)? Sometimes an HTML error (like a tag which is not properly closed) might bring a JavaScript error as well. Do you have a debugger (as Firebug in FF)? What does it say?... Things like that
    Last edited by Kor; 01-08-2010 at 03:36 PM.

  9. #9
    Join Date
    Mar 2006
    Location
    Sacramento
    Posts
    73
    OK... I built a test case. Probably should have done this much earlier.

    <input> by itself works to create a default simple input box...

    ...but...

    won't work in (at least in IE7) for a radio or checkbox...

    test code...

    HTML Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
    <script type="text/javascript">
    function ChangeDOM(){
    		//adds children to given node 
    		//"keys" format  - {"['elType'] or [element attribute] or ['text']":"[element type] or [attribute property] or [actual text],"":""...}
    		this.addChildren = function(keys,parentNodeObject){
    			var elName=document.createElement(keys["elType"]);
    			parentNodeObject.appendChild(elName);
    			for(var key in keys){
    				if(key != "elType"){
    					if(key == "text"){
    						var txt=document.createTextNode(keys[key]);
    						elName.appendChild(txt);
    					}
    					else elName.setAttribute(key,keys[key]);
    				}
    			}
    			return;
    		}
    		//clears all children from given node
    		this.clearChildren = function(parentNodeObject){
    			if(parentNodeObject.childNodes){
    				var nodechildren = new Array();
    				nodechildren = parentNodeObject.childNodes;
    				if(nodechildren.length>0)for(i=0;nodechildren.length;i++)parentNodeObject.removeChild(parentNodeObject.lastChild);
    			}
    			return;
    		}
    		//updates text for a given node
    		this.updateText = function(newText,parentNodeObject){
    			this.clearChildren(parentNodeObject);
    			this.addChildren({'text':newText},parentNodeObject);
    		}
    	}
    </script>
    </head>
    
    <body>
    <div id="test">
    </div>
    <script type="text/javascript">
    ChangeDOM = new ChangeDOM();
    ChangeDOM.addChildren({'elType':'input','type':'checkbox','value':'someValue'},document.getElementById('test'));
    </script>
    </body>
    </html>
    Last edited by jnoster; 01-08-2010 at 03:55 PM.

  10. #10
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Error here:
    Code:
    if(key == "text"){
    						var txt=document.createTextNode(keys[key]);
    						elName.appendChild(txt);
    					}
    What textNode do you expect to append to an input? An input is a non empty tag, it has no inner space (like <input>inner space</input>) where you can append a textNode.

  11. #11
    Join Date
    Mar 2006
    Location
    Sacramento
    Posts
    73
    Yep, caught that... and fixed it in my reply above.

    Issue still applies.

  12. #12
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Try nesting the embedded javascript code within a CDATA island. That will prevent the interpretation of some special characters as XML tokens (<, >, &...)
    Code:
    <script type="text/javascript">
    /*<![CDATA[*/
    //code here
    /*]]>*/
    </script>
    IE is sensitive about that.

    Or use an external js file

  13. #13
    Join Date
    Mar 2006
    Location
    Sacramento
    Posts
    73
    Thanks but that has no affect.

    Note that I only put the script inline in the header here for simplicity. My test case on my server is using a .js file in the header.

    And since this is a transitional xhtml, I'm thinking CDATA is not needed anyway.

    AND

    If you replace ...
    ChangeDOM.addChildren({'elType':'input','type':'checkbox','value':'someValue'},document.getElementBy Id('test'));
    ... with ...
    ChangeDOM.addChildren({'elType':'p','text':'Yo baby yo baby yo!'},document.getElementById('test'));
    It produces a <p> with text just as expected without the CDATA. And it's not much of a stretch to expect anything different with the former array.

    Another test did provide a clue, however. I'm thinking now that because <input> is created before the attribute is added in the script above, this is where it is failing.

    I just ran a test where I had created in the HTML the following...
    HTML Code:
    <input id="testInput" value="yo" />
    Then in my JS I added the line...
    Code:
    document.getElementById('testInput').setAttribute('type','radio');
    Now that I've done this I think I realize the issue. Once an <input> tag is created as a default text input type element, it's not going to change it to a "radio" on the fly.

    Thoughts??

    This now makes perfect sense to me...

    Unless I've fallen off my rocker and bumped my head!

  14. #14
    Join Date
    Dec 2003
    Location
    Bucharest, ROMANIA
    Posts
    15,428
    Yeap. Your code works as expected in Mozilla, but not in IE, as IE has another bug: it can not change the type of an input tag. You must modify your code in order to set all the needed attributes before appending the element to its parent.

  15. #15
    Join Date
    Apr 2003
    Location
    Netherlands
    Posts
    21,654
    If I remember correctly <map> and <area> have a similar problem with changing attributes

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles