Node null error

Dear guys,

I have buil a webshop system in JavaScript(school project)and if I run it , it refuses to work in chrome or internet explorer . In Firefox it works but I get node is null errors on line 343 . But I don’t know why

any help would be much appreciated.

my code :


// inladen 
window.addEventListener("load",start,false);

function start()
{
insert_basket_contents(status);

}




/////////////////////////////////////////////////////////////////////////////
//
// cookie stuff
//

function save_cookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString()
	}
	else expires = "";
	document.cookie = name+"="+value+expires+"; path=/"
}

function read_cookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i<ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length)
	}
	return null
}

function delete_cookie(name) {
	save_cookie(name, "", -1);
}

/////////////////////////////////////////////////////////////////////////////
//
// product stuff
//

var g_currency = '€';
var g_decimal = ',';
var g_thousand = '.';
var g_cookiedays = 365;
var g_havebasket = 0;
var g_products = new Array();

function add_product(guid, name, price){
	var item = new Array(guid, name, price);
	g_products[g_products.length] = item;
}

function get_qty(guid){
	var cookie = read_cookie(guid+'_qty');
	if ((cookie != null) && (cookie != '')){
		return parseInt(cookie);
	}else{
		return 0;
	}
}

function set_qty(guid, qty){
	if (qty < 0) qty = 0;
	if (!qty){
		delete_cookie(guid+'_qty');
	}else{
		save_cookie(guid+'_qty', parseInt(qty), g_cookiedays);
	}
}

function add_item(guid, qty){
	set_qty(guid, get_qty(guid) + parseInt(qty));
	update_basket();
}

function remove_item(guid){
	set_qty(guid, 0);
	update_basket();
}

function empty_basket(){
	for(var i=0; i<g_products.length; i++){
		var product = g_products[i];
		var guid = product[0];
		remove_item(guid);
	}
}

/////////////////////////////////////////////////////////////////////////////
//
// basket stuff
//

function build_basket(container_id, checkout_url){
	var cell, row;
	var elm_parent = document.getElementById(container_id);

	var elm_table = create_element(elm_parent, 'TABLE');
	elm_table.setAttribute('border', '2');
	elm_table.setAttribute('cellPadding', '4');
	elm_table.setAttribute('cellSpacing', '0');

	// we have to have a tbody for some reason
	var elm_tbody = create_element(elm_table, 'TBODY');

	// add header row
	row = create_element(elm_tbody, 'TR');
	cell = create_element_filled(row, 'TH', 'Product');
	cell = create_element_filled(row, 'TH', 'Prijs');
	cell = create_element_filled(row, 'TH', 'Aantal');
	cell = create_element_filled(row, 'TH', 'BTW');
	cell = create_element_filled(row, 'TH', 'Totaal');
	cell = create_element_filled(row, 'TH', 'Verwijderen');


	var sub_total = 0;

	// add product rows
	for(var i=0; i<g_products.length; i++){
		var product = g_products[i];

		var guid = product[0];
		var name = product[1];
		var price = product[2];
	
		var qty = get_qty(guid);

		var total = price*qty;
		 sub_total += total;
		var btw= total*0.21;
		sub_total += btw;

		row = create_element(elm_tbody, 'TR');
		row.style.display = 'none';
		row.id = 'basket_row_'+guid;

		cell = create_element_filled(row, 'TD', name);

		cell = create_element_filled(row, 'TD', format_price(price));
		cell.setAttribute('align', 'right');
		
		
		cell = create_element_filled(row, 'TD', 'QTY');
		cell.setAttribute('align', 'right');

		var input = document.createElement('INPUT');
		input.setAttribute('disabled', true); 
		input.id = 'basket_input_'+guid;
		input.value = qty;
		input.size = 10;
		input.style.textAlign = 'right';
		input.onblur = update_qty;
		replace_contents(cell, input);
		
		cell = create_element_filled(row, 'TD', format_price(btw));
		cell.setAttribute('align', 'right');
		
			
		cell = create_element_filled(row, 'TD', 'Totaal');
		cell.setAttribute('align', 'right');
		cell = create_element(row, 'TD');
		
		var link = create_element_filled(cell, 'A', 'Verwijderen');
		link.href = "Javascript:remove_item('"+guid+"');";
		
		
	}

	// add "empty" row
	row = create_element(elm_tbody, 'TR');
	row.style.display = 'none';
	row.id = 'basket_empty_row';
	cell = create_element(row, 'TD');
	cell.setAttribute('colSpan', '5');
	cell.setAttribute('align', 'center');
	create_element_filled(cell, 'I', 'Je winkelmandje is leeg !');

	// show totals
	row = create_element(elm_tbody, 'TR');

	cell = create_element_filled(row, 'TH', 'Totaal:');
	cell.setAttribute('colSpan', '4');
	cell.setAttribute('align', 'left');

	cell = create_element_filled(row, 'TD', format_price(sub_total));
	cell.setAttribute('align', 'right');
	cell.id = 'basket_subtotal';

	// checkout button
	row = create_element(elm_tbody, 'TR');
	row.id = 'basket_checkout';
	row.style.display = 'none';

	cell = create_element(row, 'TD');
	cell.setAttribute('colSpan', '5');
	cell.setAttribute('align', 'right');

	link = create_element_filled(cell, 'A', 'Afrekenen »');
	link.href = checkout_url;

	g_havebasket = 1;
	update_basket();
}

function update_basket(){
	if (!g_havebasket) return;

	var sub_total = 0;

	// update product rows
	for(var i=0; i<g_products.length; i++){
		var product = g_products[i];

		var guid = product[0];
		var price = product[2];
		var qty = get_qty(guid);

		var total = price*qty;
		sub_total += total;
		var btw=0.21*total;
		sub_total+=btw;

		var row = document.getElementById('basket_row_'+guid);
		row.style.display = (qty > 0)?'':'none';

		// update qty
		var input = document.getElementById('basket_input_'+guid);
		input.value = qty;		

		// update total
		replace_contents(row.childNodes[4], document.createTextNode(format_price(total+btw)));

	}

	 row = document.getElementById('basket_empty_row');
	row.style.display = (sub_total > 0)?'none':'';

	var cell = document.getElementById('basket_subtotal');
	replace_contents(cell, document.createTextNode(format_price(sub_total)));

	 row = document.getElementById('basket_checkout');
	row.style.display = (sub_total > 0)?'':'none';
}

function update_qty(){
	if (!g_havebasket) return;

	for(var i=0; i<g_products.length; i++){
		var product = g_products[i];

		var guid = product[0];

		var row = document.getElementById('basket_row_'+guid);
		var cell = row.childNodes[2];
		var input = cell.childNodes[0];

		set_qty(guid, input.value);
	}

	update_basket();
}

function insert_basket_contents(node_name){
	var qty = 0;
	var node = document.getElementById("node_name");
		var s;   


	for(var i=0; i<g_products.length; i++){
		var product = g_products[i];
		var guid = product[0];
		qty += get_qty(guid);
	}

	if (qty){
		if (qty == 1){
			s = "Je mandje bevat 1 Artikel.";
		}else{
			s = "Je mandje bevat"+qty+" Artikels.";
		}
	}else{
		s = "Je winkelmandje is leeg !";
	}

	replace_contents(node, document.createTextNode(s));
}

function get_order_copy(){

	var sub_total = 0;
	var items = 0;
	var buffer = '';

	// update product rows
	for(var i=0; i<g_products.length; i++){
		var product = g_products[i];

		var guid = product[0];
		var name = product[1];
		var price = product[2];
		var qty = get_qty(guid);
		items += qty;

		var total = price*qty;
		sub_total += total;

		if (qty > 0){
			buffer += name+" ("+guid+") x"+qty+" @ "+format_price(price)+" = "+format_price(total)+"\
";
		}
	}
	buffer += "\
Totaal: ("+items+" items) "+format_price(sub_total)+"\
";

	return buffer;
}

/////////////////////////////////////////////////////////////////////////////
//
// DOM helper stuff
//

function create_element(parent, type){
	var elm = document.createElement(type);
	parent.appendChild(elm);
	return elm;
}

function create_element_filled(parent, type, contents){
	var elm = document.createElement(type);
	parent.appendChild(elm);
	elm.appendChild(document.createTextNode(contents));
	return elm;
}

function replace_contents(node, newnode){
	if (node.childNodes.length > 0){
		node.replaceChild(newnode, node.childNodes[0]);
	}else{
		node.appendChild(newnode);
	}
}

/////////////////////////////////////////////////////////////////////////////
//
// format stuff
//

function format_price(price){
	var s = new String(Math.round(price*100));
	var eurocent = s.substr(s.length-2);
	var euro = s.substr(0, s.length-2);
	euro = commaify(euro);

	if (eurocent.length == 0) eurocent = '00';
	if (eurocent.length == 1) eurocent = '0'+eurocent;
	if (euro.length == 0) euro = '0';

	return g_currency + euro + g_decimal + eurocent;
}

function commaify(s){
	if (s.length <= 3) return s;
	var out = s.substr(s.length-3);
	s = s.substr(0, s.length-3);
	while(s.length > 0){
		out = s.substr(s.length-3) + g_thousand + out;
		if (s.length > 3){
			s = s.substr(0, s.length-3);
		}else{
			s = '';
		}
	}
	return out;
}



It’s trying to tell you that a node in the following line is null

node.replaceChild(newnode, node.childNodes[0]);

But which one is null? Is it node, is it newNode? It’s unlikely to be the childNodes one due to the if condition before getting there.

If you check beforehand if those nodes are defined, you can work out which one is causing the problem.
Perhaps with something like this:


function replace_contents(node, newnode){
    if (!node) {
        throw 'node argument is null!';
    } else if (!newnode) {
        throw 'newnode argument is null!';
    }
}

One you know which one is the problem, you can trace it back to what’s causing it.

The replace_contents function is called from several different places:


replace_contents(cell, input);
...
replace_contents(row.childNodes[4], document.createTextNode(format_price(total+btw)));
...
replace_contents(cell, document.createTextNode(format_price(sub_total)));
...
replace_contents(node, document.createTextNode(s));

Any one of those might be the cause of the problem, so once you’ve worked out which one is the null node, you can check for that node being null before calling each of those functions, and track the cause back even further.

That’'s about all the help I can give you though, without a link to a test page that demonstrates the problem.

it’s this one taht gives the null error :

var node = document.getElementById(“node_name”);
replace_contents(node, document.createTextNode(s));

but i’m not sure why it does that

Which variable is not defined? Is it node or s?

the node is not defined

Okay, is the script running before the “node_name” element exists on the page?

no the node_name elements is a html based span tag with an id .Are you sugesting I should use the createlement function instead ?

Nope, I’m suggesting that the script is running on the page before the “node_name” element even exists yet on the page.

The solution to which is to run the script after such page elements exist, preferably by placing the script at the end of the body, just before the </body> tag.

but I use an external js file and it is placed in the head of my html file . our teacher told us to do it that way . That also the reason why I use the eventlister “load”. I will post my html code also later so that you can take a better look .

Is er any way to solve this error with the script load in the head of the html file

Things have been learned about JavaScript over the past 5 years or so that might surprise you.

It’s preferable to have scripts in external files. Where they are loaded from though has many performance implications.

Best practices for speeding up your web site have ben advising for a while that you should not put your scripts in the head for performance reasons. They block all downloading of the page until the script has been downloaded and the script has completely finished executing.

The advice for performance reasons is to put scripts at bottom

Also, due to the load event being slow (it has to wait for the entire page to finish), scripts at the bottom of the page load long before the load event. There is a dom-ready event that fires shortly after the scripts at the bottom, but that dom-ready event is only supported on some web browsers.

That’s also why putting scripts at the bottom is advised.

The only useful reason to not put scripts at the bottom is if you need to support ancient web browsers like IE4.

Yes there is, we can help you with that. Just know that there are other alternatives available to you in terms of performance, expressiveness, and loading speed.

yes, could be but i’m affraid that I have to do it like I said before , by putting the javasript file in the head of my html page . So what do I need to change to solve this error . And to let it work in my other browers

If you head along to microjs there is a list of JavaScript loaders that are designed to solve that problem for you. They all specialize in slightly different ways, but you’ll find one there that does the job for you.

ah I see , any suggestion because I’m not used to work with those loader and we haven’t discussed them in class so I don’t know wich one is most usefull for this situation .

Well, you could start simple and go with the smallest ones, such as $script or LazyLoad

but I do have a loader not the window.addEventListener(“load”,start,false);
so in fact there should not be any differnce between that and putting the javascript at the end of my html page ??

Doesn’t addEventListener only work on W3C web browsers, and not on IE web browsers?

I never had problems with it so should be strange.
There must be an other problem .

Here are some investigative details about it.
Advanced event registration models