
Help! I've solved a problem without successfully understanding what caused it. I'm posting this because maybe it will help somebody else, and perhaps somebody can tell me why it happens in the first place.
PROBLEM: Using innerHtml to add a textbox to an array of textboxes causes the contents of textboxes to be blanked out. It also means I cannot queue scriptaculous effects for displaying the textboxes, instead the effects execute in parallel. Here is the Javascript:
function newTextBox() {
count+=1;
new_companies.innerHTML+="<div id=new_company"+count+" class=new_company style={display:none} ><input type=text id=company["+count+"] name=company["+count+"] size=30 />";
new Effect.SlideDown("new_company"+count, { queue:'end'});
}
SOLUTION: By replacing that function with the following, everything works as expected. Adding textboxes doesn't affect the textboxes already on the screen, and my scriptaculous effects queue properly instead of executing in parallel. Here is the new Javascript:
function addTextBox() {
count+=1;
var all_companies = document.getElementById('new_companies');
var newdiv = document.createElement('div');
var divIdName = "new_company"+count;
newdiv.setAttribute('id',divIdName);
newdiv.setAttribute('class',"new_company");
newdiv.setAttribute('style',"{display:none}");
newdiv.innerHTML = "<input type=text id=company["+count+"] name=company["+count+"] size=30 />"
all_companies.appendChild(newdiv);
new Effect.SlideDown("new_company"+count, { queue:'end'});
}
5 comments:
Hey Josh,
I bumped up against this problem the other day as well. I was scratching my head for quite a while trying to figure out what was causing the problem for the first bit of code, but never found an answer…I used the same solution you detailed here… Let me know if anyone provides you an answer to your quandary…I’d be interested to know what the deal is.
By the way, be careful with setAttribute()…it doesn’t behave in IE7, IE6, etc. Instead, do:
newdiv.id = divIdName;
newdiv.className = “new_company”; // note the use of className, not class
newdiv.style.cssText = ‘display:none;’;
See this discussion for more info: http://www.quirksmode.org/bugreports/archives/2005/03/setAttribute_does_not_work_in_IE_when_used_with_th.html
boredandblogging
Doesn’t innerHTML completely overwrite the contents of the element?
So lets say you do this first:
foo.innerHTML = “”;
then you do this:
bar.innerHTML += “”;
When the bar.innerHTML is drawn, the foo div that is drawn is not the same one as foo.innerHTML. Its a brand new one.
WIth appendChild, it actually is appending to the end, not rewriting like innerHTML.
At least this is what I was told and thats why I try not to use innerHTML.
Ed Chang
Josh,
Using innerHTML simply adds/replaces a string of text within a DOM object and will break DOM object references.
For the case of the disappearing text within input fields:
String concatenation will get the innerHTML value of the newdiv variable and add some more text. As a result, you lose what the user typed into the input field. If that’s the route you want to go, you would need to add an event handler to store the value of what was typed and then add it to the output string as it’s built.
I assume the effects execute in parallel because all the concatenated DIVs are created at once. Not certain if timestamps play a role in this. See http://dev.rubyonrails.org/browser/spinoffs/scriptaculous/src/effects.js#L178 for references to timestamps when adding effects to a global queue.
In contrast, appending DOM objects will preserve what text the user has typed into an input field. The DIV objects are referenceable within the DOM and probably play nice with the effects queue since they’re created and appended one at a time.
Hope that helped,
Ed
Farhan Khan
By using innerHTML, you are actually adding a string of text (HTML code) to already existing text (HTML). Once the page has been rendered and some values have been filled in, these values are not present in the HTML code itself rather it’s being held by the DOM. So appending some thing in the DOM structure would retain those values.
It turns out that innerHTML has always been the first choice for most programmers but this is one of the disadvantages of using it.
shouldn't you use .value instead of .innerHTML for input fields?
Post a Comment