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);
}
}
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');
}
...
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.
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
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}
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
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>
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.
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>
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...
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!
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.
Bookmarks