Solved

Problem writing Javascript to the DOM in IE only

Posted on 2009-04-08
9
700 Views
Last Modified: 2013-12-08
I've got a bit of a confusing one here regarding writing to the DOM on the fly. I've included a stripped down version of my page in the code section below to highlight the problem that can be reproduced locally.

If you run the page in Firefox and the IE7 it should be pretty obvious what the problem is, but I'll explain: I start my page with 2 select fields in static HTML - the options/values of the second are written dynamically depending on what is selected in the first select field, so they work as a pair. The first is a category, the second essentially is a product. This bit is working fine, when i change category the options change in the product drop down.

I now have a button to add further pairs of these select fields to create further category/product inputs, and when this button is clicked there's a fair amount of script which creates notes and inserts them into the DOM in the appropriate place, giving new names to the fields based on a random number. This bit actually works fine too, and even a button to remove the parent paragraph tag which the new select pairs are in works fine in both browsers.

What Im having trouble with is setting the attribute of 'onChange' in the first select to call the javascript function. The function requires two parameters - the selectedIndex and the name of the field to update, and this is done in line 73 - the variable "passFunctionInSetAttr" is set and ontains the complete function call. This is then added to the node 3 lines later (after being alerted to the screen so I can see what is going on and that it is fine - it is).

And in firefox it works perfectly - I get an alert to say that its reached the updateproducts  function as expected and the newly created select list updates with the products list, but in IE (Im in version 7) - despite that I'm echoing the string back in the alert to see it's working - and it seems to be - it fails silently without an error message or anything and it doesnt reach the function to update the products - I can tell as the alert doesnt come up. I've been pulling this apart today in Visual Web Developer 2008 to try and get some debugging messages and theres no error message or anything, yet it doesn't work and fails in total silence.

I've added a 'Print Dom' button to this too, so I can print out the structure of the document that's been written on the fly and take a look - and it does look a little odd - the paragraph id isn't quoted for example (how can I change this I wonder..) but it seems to look vaguely ok.

Weirdly though, if i then paste the dom that is dumped out into the text area into its own document, and run it locally in a browser (just need to add the Doctype and HTML tags around the core code), it then gets as far as the function in IE and flashes up the alert which it didn't before. It still fails to update the second select..  but this is supposed to be exactly the same script, just one is written on the fly and the other has been run from a static HTML document - and its behaving differently.

Not sure if I've done something stupid here or hit a Javascript bug, but many thanks in advance for any help anyone can give me on this!

Matt


<!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>

<title>Select DOM Test</title>

<script type="text/javascript">

    function node_delete(whichPara) {

        if (confirm("Are you sure you want to delete this product?")) {

            document.getElementById('allparas').removeChild(document.getElementById(whichPara));

       }

    }
 

    function printDom() {

        allHTML = document.getElementsByTagName("html")[0].innerHTML;

        document.forms['update_table'].elements['dom'].value = allHTML;
 

    }

    var products_matrix = new Array();

    products_matrix[0] = "";

    products_matrix[1] = new Array("550|X1|product 1|10");

    products_matrix[2] = new Array("551|Y1|Product in section 2|10", "552|Y2|Another Product in Section 2|10");

    products_matrix[3] = new Array("640|B-682|Product in 3|1", "641|B-682-int|Another in 3|1", "642|CD-682|Product|1", "643|CD-6821|Another Product|1", "644|CD-C|And Another Product|1");

    products_matrix[4] = new Array("611|E-API682sd|Item in section 4|15", "612|B-AP|Another item in section 4|15", "613|S2wed|item name here|20", "614|B-Chem|Another items|15", "615|B-Chem|and another|15", "616|B-C|Aargh|15", "624|B-Oi|Final test product|15");
 

    var categories_names_array = new Array("Section 1", "Section 2", "Section 3", "Section 4");

    var categories_ids_array = new Array("6", "7", "12", "9");
 

    function updateproducts(selectedcategory, fieldtoupdate) {

        alert("reached update products function");

        

        var categorieslist = document.update_table.category1

        var productslist = eval("document.forms['update_table'].elements['" + fieldtoupdate + "']")
 

        productslist.options.length = 0

        if (selectedcategory > 0) {

            for (i = 0; i < products_matrix[selectedcategory].length; i++)

                productslist.options[productslist.options.length] = new Option(products_matrix[selectedcategory][i].split("|")[1] + "  -  " + products_matrix[selectedcategory][i].split("|")[2], products_matrix[selectedcategory][i].split("|")[0]);

        }

    }
 

    //-->

</script>

</head>

<body>
 

<form name="update_table" method="post" action="" enctype="multipart/form-data" style="padding:0px; margin:0px">

<p style="font-size:12px">Select Category:<br />

<select name="category1" onChange="updateproducts(this.selectedIndex,'product1')" />

<option value="">Select a category:</option>

<script language="Javascript">

    for (p=0;p<categories_names_array.length;p++){

	document.write("<option value=\"" + categories_ids_array[p] + "\">" + categories_names_array[p] + "</option>\n");

    }

</script></select>

</p>
 

<p style="font-size:12px">Product Name: <select name="product1" style="font-size:13px">

<option value="" style="font-family:tahoma,arial,verdana,helvetica"> Please select a category first </option>

</select>

</p>
 

<div id="allparas">

<span class="order_button" style="margin-top:30px"><a style="font-weight:bold; clear:both; padding-top:10px; margin-top:10px;" href="#" onclick="

if( !document.createElement || !document.childNodes ) {

	window.alert('Your browser is not DOM compliant');

} else {

	// set up paragraph and select

	randomNumber = Math.floor(Math.random()*9999999999999999) 

	var theNewParagraph = document.createElement('p');

	var lineBreak = document.createElement('br');

	var divName = 'div_' + randomNumber;

	var theTopCategorySelect = document.createElement('select');

	var theSelect = document.createElement('select');

	newSelectName= 'select_' + document.getElementsByTagName('p').length;

	newCatSelectName= 'select_category_' + randomNumber

    myRandomNumber = Math.floor(Math.random()*9999999999999999);

	newSelectName = newSelectName + myRandomNumber;

    theSelect.setAttribute('name',newSelectName);

    theSelect.setAttribute('style','font-size:13px;');

	theTopCategorySelect.setAttribute('name',newCatSelectName);

	theTopCategorySelect.setAttribute('style','font-size:13px');

    

	passFunctionInSetAttr='updateproducts(this.selectedIndex,\'' + newSelectName + '\')';

	alert(passFunctionInSetAttr);

	

	theTopCategorySelect.setAttribute('onChange',passFunctionInSetAttr);
 

	// set up options for select

	firstOption = document.createElement('option');

	firstOption.setAttribute('value','');

	firstOption.setAttribute('style','font-weight:bold; font-size:12px');

	firstText = document.createTextNode(' - ');

	theSelect.appendChild(firstOption);

	firstOption.appendChild(firstText);

	arrayOptions=Array();

	arrayText=Array();

   

	// set up options for category select

	catFirstOption = document.createElement('option');

	catFirstOption,setAttribute('value','');

	catFirstOption.setAttribute('style','font-weight:bold; font-size:12px');

	catFirstText = document.createTextNode('Select A Category:');

	theTopCategorySelect.appendChild(catFirstOption);

	catFirstOption.appendChild(catFirstText);

	arrayOptions=Array();

	arrayText=Array();

    for (p=0;p<categories_ids_array.length;p++){

		arrayOptions[p] = document.createElement('option');

		arrayOptions[p].setAttribute('value',categories_ids_array[p]);

		arrayOptions[p].setAttribute('style','font-size:13px; ');

		arrayText[p] = document.createTextNode(categories_names_array[p]);

		theTopCategorySelect.appendChild(arrayOptions[p]);

		arrayOptions[p].appendChild(arrayText[p]);

	}

 

	var theDeleteImage = document.createElement('img');

	

	//set up theNewParagraph

	newParaName= 'para_' + document.getElementsByTagName('p').length;

	newParaName += randomNumber; 

	theNewParagraph.setAttribute('id',newParaName);

	theNewParagraph.setAttribute('style','padding-top:10px; font-size:12px; clear:both;');
 

    // delete image 

	theDeleteImage.setAttribute('src','http://www.dmlmarketing.net/demo/cancel.png');

	deleteImageName = 'delete_' + document.getElementsByTagName('p').length;

	deleteImageName += randomNumber; 

	theDeleteImage.setAttribute('id',deleteImageName);

	theDeleteImage.setAttribute('hspace','20');

	theDeleteImage.setAttribute('vspace','3');
 

    // div

	theDiv = document.createElement('div');

	theDiv.setAttribute('id',divName); 

	theDiv.setAttribute('style','display:inline; float:left;'); 
 

 	//prepare the text nodes

	var theText1 = document.createTextNode('Product Name:');

    theCategoryText = document.createTextNode('Select Category:');

       

    

	//put together the whole paragraph

	theNewParagraph.appendChild(theCategoryText);

	theNewParagraph.appendChild(lineBreak);

	theNewParagraph.appendChild(theTopCategorySelect);

	theNewParagraph.appendChild(lineBreak);

	theNewParagraph.appendChild(theText1);

	theNewParagraph.appendChild(theSelect);

	theNewParagraph.appendChild(theDiv);

	theDiv.appendChild(theDeleteImage);

	

	//insert it into the document somewhere

	this.parentNode.parentNode.insertBefore(theNewParagraph,this.parentNode);

	//make the paragraph delete itself when the delete image is clicked

	document.getElementById(deleteImageName).onclick = function () { node_delete(this.parentNode.parentNode.id); };

}

return false;">Add New</a></span>

<hr />

<span style="disaply:block; clear:both;"><textarea name="dom" rows=10 cols=70></textarea><br /><a href="Javascript:printDom()">Print Dom</a></span>

</form>

</body>

</html>

Open in new window

0
Comment
Question by:MatthewP
  • 4
  • 3
9 Comments
 
LVL 41

Expert Comment

by:HonorGod
ID: 24099909
I'm pretty sure that the problem is with this line of code:

document.getElementById(deleteImageName).onclick = function () { node_delete(this.parentNode.parentNode.id);

I've had problems before trying to change the onclick in IE.
What I had to end up doing was checking for an attachEvent function associated with the object (element), and using it, instead of the
assignment like you have, or setAttribute.

Something like:
var ele = document.getElementById( 'deleteImageName' )

if ( ele.attachEvent ) {

  ele.attachEvent( 'onfocus', function() { doSomething(this.event.srcElement); } )

} else {

  ele.setAttribute( 'onclick', 'doSomething(this);' );

}

Open in new window

0
 
LVL 41

Expert Comment

by:HonorGod
ID: 24099916
sorry, the attachEvent should have been
ele.attachEvent( 'onclick', function() { doSomething(this.event.srcElement); } )

Open in new window

0
 
LVL 6

Author Comment

by:MatthewP
ID: 24100111
Hi,

Thanks for taking a look. did you try running the code locally? The delete is working perfectly for me in both browsers, its the onChange when written to the DOM that is failing.

Thanks,
Matt
0
 
LVL 41

Expert Comment

by:HonorGod
ID: 24100212
Haven't had a chance yet... Trying to do way too many things at once. :-)
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 6

Author Comment

by:MatthewP
ID: 24100282
Tell me about it :) I've been on this 2 days and not got anywhere, I need to forget about it for a bit. If you're up for taking a look though the script i sent should demonstrate it pretty succinctly. I've either done something very stupid.. or its an IE bug.. i *think*.

Cheers,
matt

0
 
LVL 6

Author Comment

by:MatthewP
ID: 24926770
Bit of a curious one this, I got it fixed but not by what I was trying to do but by adding another line similar to:

document.getElementById(deleteImageName).onclick = function () { node_delete(this.parentNode.parentNode.id); };

it all worked correctly - it seems that the event wouldnt attach directly to the element but would if I attached it later. Not figured out why but there you go.
0
 
LVL 41

Expert Comment

by:HonorGod
ID: 24927095
Wow, somehow, I lost track of this, and never returned.

Please forgive me.

I'm glad that you were able to get the issue resolved though.
0
 

Accepted Solution

by:
ee_auto earned 0 total points
ID: 25621634
Question PAQ'd, 500 points refunded, and stored in the solution database.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

I recently found myself in a Corporate Situation where the client had requested blocking access to any and all websites except his own Domain? Easy? I am sure this would be your answer but their requirement was, this has to be done without using…
This article demonstrates how to create a simple responsive confirmation dialog with Ok and Cancel buttons using HTML, CSS, jQuery and Promises
Google currently has a new report that is in beta and coming soon to Webmaster Tool accounts. This Micro Tutorial will highlight new features for Google Webmaster Tools.
This Micro Tutorial will demonstrate how to add subdomains to your content reports. This can be very importing in having a site with multiple subdomains.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now