Solved

Problem writing Javascript to the DOM in IE only

Posted on 2009-04-08
9
701 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Before we dive into the marketing strategies involved with creating an effective homepage, it’s crucial that EE members know what a homepage is. In essence, a homepage is the introductory, or default page, of a website that typically highlights the …
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
This Micro Tutorial will demonstrate how nuggets on the Web are formatted by using Chrome Developer Tools. These tools would not only view the site's CSS but it can also modify it and save the CSS to use on your own site.

939 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

2 Experts available now in Live!

Get 1:1 Help Now