Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

IE DOM weirdness - document fragment

Status
Not open for further replies.

rravenn

Programmer
Jul 6, 2004
40
US
I have the following problem. I had some code that I wrote before, it got XML data from XMLHttPrequest and populated the table with rows. It worked like it should.

However, browser was lagging when the table was populated with large quantity of rows so i decided to rewrite it using document fragment.

I understand the function is not ideal, in fact xml is not passed as a parameter, and the items are fetched from it without any problems, I just rearranged it a bit to avoid the code that is not relevant to the problem at hand.

I also understand that I omit var in many places hwere I shouldn't, didnt get around to fixing this yet.

Problem is... the rows are filled. Images show up, input values, button text, everything is ok (the app is IE only).
However
1) I cannot set style attribute for tags. I can set any other attribute, but when i set style and alert tbl.innerHTML, it's not there.
2) class attribute doesn't work. titlecell class has some styling, but it doesn't show up.
3) javascript handlers don't work. As you see I add onclick attribute to button, so, when I click button, nothing happens even though when i alert tbl.innrHTML it's in place and everything looks good.

To get around this i tried extrancting innerHTML to a string and reassigning it it innerHTML - I get "Unknown error" popping up.

Here's the code
Code:
function buildResourceList(myxml)
{

	var tbl = document.getElementById('newTable');

	while (tbl.rows.length)
	{
		tbl.deleteRow(tbl.rows.length - 1);
	}
	
	var docFragment = document.createDocumentFragment();

	var items = myxml.getElementsByTagName("ResResource");
	
	for (var i = 0; i < items.length; i++) 
	{
		attrTimed = items[i].getAttribute("Timed").toString();

		id = items[i].getAttribute("resourceID").toString();
		vname = items[i].getAttribute("Name").toString();
		vname = vname.replace(/[']/g,'"').replace(/(\S[\/-])(\S)\w{10,}/g,'$1 $2');				
		var row = docFragment.getElementById('NewRow'+id);
		
		if (!row)
		{
			row = docFragment.createElement('tr');
			row.setAttribute('id','NewRow'+id);

			var cellTitle = docFragment.createElement('td');
			cellTitle.setAttribute('width','100%');
			cellTitle.setAttribute('class','titlecell');
			if (attrTimed == '1')
			{
				var img = docFragment.createElement('img');
				img.setAttribute('src','img/period_small.gif');
				cellTitle.appendChild(img);
			}
			cellTitle.appendChild(docFragment.createTextNode(' '+vname));


			var cellRight = docFragment.createElement('td');
			cellRight.setAttribute('width', '50');
			input = docFragment.createElement('input');
			input.setAttribute('name','txNewCount'+id);
			input.setAttribute('type','text');
			input.setAttribute('value','1');
			input.setAttribute('maxlength','3');
			hidden = docFragment.createElement('input');
			hidden.setAttribute('name','hdTimed'+id);
			hidden.setAttribute('id','hdTimed'+id);
			hidden.setAttribute('type','hidden');
			hidden.setAttribute('value',attrTimed);
			cellRight.appendChild(input);
			cellRight.appendChild(hidden);
			

			var cellButton = docFragment.createElement('td');
			cellButton.setAttribute('width', '20');
			var button = docFragment.createElement('button');
			button.setAttribute('onclick','javascript:addres('+id+',\''+vname+'\');');
			button.setAttribute('style','width:100%');
			button.appendChild(docFragment.createTextNode('+'));
			cellButton.appendChild(button);
			
			
			
			row.appendChild(cellTitle);
			row.appendChild(cellRight);
			row.appendChild(cellButton);

			docFragment.appendChild(row);
			
		}
	}
	

	tbl.getElementsByTagName('tbody')[0].appendChild(docFragment);
}
 
Style and event handler are set with slightly involved twist. I try to illustrate on specific lines.

[1] setAttribute on style
[1.a] ie
[tt] var cellButton = docFragment.createElement('td');
cellButton[red].style[/red].setAttribute([red]'cssText','width:20px'[/red]); //unit may not be what you want[/tt]
[1.b] ff/nn
[tt] var cellButton = docFragment.createElement('td');
cellButton.setAttribute([red]'style','width:20px'[/red]); //unit may not be what you want[/tt]

[2] event handlers
[2.a] ie
[tt] var button = docFragment.createElement('button');
button.[red]attachEvent[/red]([red]'onclick'[/red],'javascript:addres('+id+',\''+vname+'\');');[/tt]
[2.b] ff/nn
[tt] var button = docFragment.createElement('button');
button.[red]addEventListener[/red]([red]'click'[/red],'javascript:addres('+id+',\''+vname+'\');',[red]false[/red]);[/tt]

Edit in realtime, detail may need refinement. But, that's more or less the general approach.
 
Thanks a lot, haven't yet tried that but the idea is clear.
Two minor problems I found before leaving work today, name attributes aren't set either, and default values (input type="text") disappear too.
The last one seems to be a minor glitch, the first is more important, but maybe irrelevant in IE only app cause afair it submits form data wiithout names by id (I could be mistaken tho), are there any special ways to get around this too?
 
Well, here's the most fundamental problem.
I tried ataching event to button bariable itself, and i tried it this way after the row is added to fragment.
Code:
var pointer = function() { eval('addres('+id+',\''+vname+'\');'); }
docFragment.getElementById('addButton'+id).attachEvent('onclick',pointer);
Problem is, all the buttons in table call the same ufnction - the one from the last row (well with params for the last row).


I tried writing function in pointer without eval, nulling pointer after attachevent, removing var to make it a global variable...

I tried saving it to globalPointer, and when I compare new pointer to the previous one, they are not equal.
What's up with that?
 
It can be done this way, can it not?
[tt]
docFragment.getElementById('addButton'+id).attachEvent('onclick',function() {director(id);});
[/tt]
with the function say director(id) sending it out to id-dependent eventual handler.

- tsuji
 
A proof of principle can be done simply like this.
[tt]
function director(s) {
alert(s);
}
[/tt]
and it will pick up id as s.

- tsuji
 
right. It pops up the same last id every time in my case :(
I ended up with adding non-w3c xml attributes to button, calling fucntion without parameters and retrieving them from srcElement/target.
 
Then, use window.event.srcElement.id (ie only in this form) to discover the id of the element which trigger the event.
 
I was thoroughly disgust of the negative feedback so I did not read all your message. So come up with the same genetic solution (w3c will comply one-day). But, I have tested the solution I proposed up to, and cannot confirm your observation. I won't persist.
- tsuji
 
Huh? What negative feedback? Sorry if I misunderstood, English is not my native tongue in fact I have voted for you as valuable help provider ;)
I can send you full code if you want, I will have it at work tomorrow... I ended up with attributes solution but is surely is not perfect.
 
>Huh? What negative feedback?
negative=your reporting the scheme does not work
That's all.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top