IE throws JavaScript TypeError but not on chrome
DESCRIPTION In our Magento Cart, when a user clicks the "Add to Cart" button on the Product Details page in any of the Internet Explorer browsers, they receive a popup in the browser with the following error message:
Exception: TypeError: Cannot get property tagName undefined or null reference
At first I, although this error was caused by an AJAX call, but after further investigation in the browser debugger, I see that it is caused by JavaScript trying to change DOM nodes / HTML tags and their attributes.
I have set breakpoints for all subtree and attribute changes in #mdl_ajax_confirm
div
the call stack:
ajax_cart.js:87
ajax_cart.js:89
ajax_cart.js:91
ajax_cart.js:97
ajax_cart.js:99
ajax_cart.js:104
ajax_cart.js:110
ajax_cart.js:112
ajax_cart.js:113
In IE, it breaks into ajax_cart.js:104
and goes to prototype:1617
to handle the exception.
So the offending piece of code looks like ajax_cart.js: 104 , which:
$$('.block-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
In Chrome it returns HTML, but in IE it returns the same error in the console as the popup: Cannot get property "tagName" from undefined or null reference
Question
I checked the IE console and it mini_cart_txt
var
exists before the ajax_cart.js: 104 is executed, the problem is what I assume it came from el
? I'm not sure how to fix this or what exactly is going on with this block of code?
Below is the rest of the code, thanks in advance :)
CODE
ajax_cart.js
var inCart = false;
if (window.location.toString().search('/product_compare/') != -1){
var win = window.opener;
}
else{
var win = window;
}
if (window.location.toString().search('/checkout/cart/') != -1){
inCart = true;
}
function setLocation(url){
if(!inCart && (/*(url.search('/add') != -1 ) || (url.search('/remove') != -1 ) ||*/ url.search('checkout/cart/add') != -1) ){
sendcart(url, 'url');
}else if((url.search('catalog/product_compare') != -1) ){
sendcompare(url, 'url');
}
else{
window.location.href = url;
}
}
function sendcompare(url, type){
//alert('test');
showLoading();
url = url.replace("catalog/product_compare/add","bestseller/index/compare");
url += 'isAjax/1/';
//jQuery('#ajax_loading'+id).show();
jQuery.ajax( {
url : url,
dataType : 'json',
success : function(data) {
// jQuery('#ajax_loading'+id).hide();
if(data.status == 'ERROR'){
alert(data.message);
}
else if(data.already!='')
{
$('mdl-temp-div').innerHTML = data.already;
var return_message = data.already;
$('mdl_ajax_confirm').innerHTML = '<div id="mdl_ajax_confirm_wrapper"><div class="f-block"><ul class="messages"><li class="notice-msg">'+return_message + '</li></ul></div></div>';
showConfirm();
}
else{
$('mdl-temp-div').innerHTML = data.message;
var return_message = data.message;
$('mdl_ajax_confirm').innerHTML = '<div id="mdl_ajax_confirm_wrapper"><div class="f-block"><ul class="messages"><li class="success-msg">'+return_message + '</li></ul></div></div>';
showConfirm();
if(jQuery('.header-compare').length){
jQuery('.header-compare').replaceWith(data.sidebar);
// Clear All
}else{
if(jQuery('.col-right').length){
jQuery('.col-right').prepend(data.sidebar);
}
}
}
}
});
}
function sendcart(url, type){
showLoading();
if (type == 'form'){
url = ($('product_addtocart_form').action).replace('checkout', 'mdlajaxcheckout/index/cart');
//url = ($('product_addtocart_form').action);
var myAjax = new Ajax.Request(
url,
{
method: 'post',
postBody: $('product_addtocart_form').serialize(),
parameters : Form.serialize("product_addtocart_form"),
onException: function (xhr, e)
{
alert('Exception : ' + e);
},
onComplete: function (xhr)
{
$('mdl-temp-div').innerHTML = xhr.responseText;
var return_message = $('mdl-temp-div').down('.mdl_ajax_message').innerHTML;
var middle_text = '<div class="mdl-cart-bts">'+$('mdl-temp-div').down('.back-ajax-add').innerHTML+'</div>';
$('mdl_ajax_confirm').innerHTML = '<div id="mdl_ajax_confirm_wrapper">'+return_message + middle_text + '</div>';
var link_cart_txt = $('mdl-temp-div').down('.cart_content').innerHTML;
$$('.top-link-cart').each(function (el){
el.innerHTML = link_cart_txt;
});
var mini_cart_txt = $('mdl-temp-div').down('.cart_side_ajax').innerHTML;
$$('.mini-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
$$('.block-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
replaceDelUrls();
if (ajax_cart_show_popup){
showConfirm();
} else {
hideMdlOverlay();
}
}
});
} else if (type == 'url'){
url = url.replace('checkout', 'mdlajaxcheckout/index/cart');
//alert(url);
var myAjax = new Ajax.Request(
url,
{
method: 'post',
postBody: '',
onException: function (xhr, e)
{
alert('Exception : ' + e);
},
onComplete: function (xhr)
{
$('mdl-temp-div').innerHTML = xhr.responseText;
var return_message = $('mdl-temp-div').down('.mdl_ajax_message').innerHTML;
var middle_text = '<div class="mdl-cart-bts">'+$('mdl-temp-div').down('.back-ajax-add').innerHTML+'</div>';
var content_ajax = return_message + middle_text;
$('mdl_ajax_confirm').innerHTML = '<div id="mdl_ajax_confirm_wrapper">'+content_ajax + '</div>';
var link_cart_txt = $('mdl-temp-div').down('.cart_content').innerHTML;
$$('.top-link-cart').each(function (el){
el.innerHTML = link_cart_txt;
});
var mini_cart_txt = $('mdl-temp-div').down('.cart_side_ajax').innerHTML;
//alert(mini_cart_txt);
$$('.mini-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
$$('.block-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
replaceDelUrls();
if (ajax_cart_show_popup){
showConfirm();
} else {
hideMdlOverlay();
}
}
});
}
}
function replaceDelUrls(){
//if (!inCart){
$$('a').each(function(el){
if(el.href.search('checkout/cart/delete') != -1 && el.href.search('javascript:cartdelete') == -1){
el.href = 'javascript:cartdelete(\'' + el.href +'\')';
}
});
//}
}
function replaceAddUrls(){
$$('a').each(function(link){
if(link.href.search('checkout/cart/add') != -1){
link.href = 'javascript:setLocation(\''+link.href+'\'); void(0);';
}
});
}
function cartdelete(url){
showLoading();
url = url.replace('checkout', 'mdlajaxcheckout/index/cartdelete');
var myAjax = new Ajax.Request(
url,
{
method: 'post',
postBody: '',
onException: function (xhr, e)
{
alert('Exception : ' + e);
},
onComplete: function (xhr)
{
$('mdl-temp-div').innerHTML = xhr.responseText;
//$('mdl-temp-div').insert(xhr.responseText);
var cart_content = $('mdl-temp-div').down('.cart_content').innerHTML;
//alert(cart_content);
$$('.top-link-cart').each(function (el){
el.innerHTML = cart_content;
});
var process_reload_cart = false;
var full_cart_content = $('mdl-temp-div').down('.mdl_full_cart_content').innerHTML;
$$('.cart').each(function (el){
el.replace(full_cart_content);
process_reload_cart = true;
});
if (!process_reload_cart){
$$('.checkout-cart-index .col-main').each(function (el){
el.replace(full_cart_content);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
}
var cart_side = '';
if ($('mdl-temp-div').down('.cart_side_ajax')){
cart_side = $('mdl-temp-div').down('.cart_side_ajax').innerHTML;
}
$$('.mini-cart').each(function (el){
el.replace(cart_side);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
$$('.block-cart').each(function (el){
el.replace(cart_side);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
replaceDelUrls();
//$('mdl_ajax_progress').hide();
hideMdlOverlay();
}
});
}
function showMdlOverlay(){
new Effect.Appear($('mdl-overlay'), { duration: 0.5, to: 0.8 });
}
function hideMdlOverlay(){
$('mdl-overlay').hide();
$('mdl_ajax_progress').hide();
$('mdl_ajax_confirm').hide();
}
function mdlCenterWindow(element) {
if($(element) != null) {
// retrieve required dimensions
var el = $(element);
var elDims = el.getDimensions();
var browserName=navigator.appName;
if(browserName==="Microsoft Internet Explorer") {
if(document.documentElement.clientWidth==0) {
//IE8 Quirks
//alert('In Quirks Mode!');
var y=(document.viewport.getScrollOffsets().top + (document.body.clientHeight - elDims.height) / 2);
var x=(document.viewport.getScrollOffsets().left + (document.body.clientWidth - elDims.width) / 2);
}
else {
var y=(document.viewport.getScrollOffsets().top + (document.documentElement.clientHeight - elDims.height) / 2);
var x=(document.viewport.getScrollOffsets().left + (document.documentElement.clientWidth - elDims.width) / 2);
}
}
else {
// calculate the center of the page using the browser andelement dimensions
var y = Math.round(document.viewport.getScrollOffsets().top + ((window.innerHeight - $(element).getHeight()))/2);
var x = Math.round(document.viewport.getScrollOffsets().left + ((window.innerWidth - $(element).getWidth()))/2);
}
// set the style of the element so it is centered
var styles = {
position: 'absolute',
top: y + 'px',
left : x + 'px'
};
el.setStyle(styles);
}
}
function showLoading(){
showMdlOverlay();
var progress_box = $('mdl_ajax_progress');
progress_box.show();
progress_box.style.width = loadingW + 'px';
progress_box.style.height = loadingH + 'px';
$('mdl_ajax_progress').innerHTML = $('mdl-loading-data').innerHTML;
progress_box.style.position = 'absolute';
mdlCenterWindow(progress_box);
}
function showConfirm(){
showMdlOverlay();
$('mdl_ajax_progress').hide();
var confirm_box = $('mdl_ajax_confirm');
confirm_box.show();
confirm_box.style.width = confirmW + 'px';
confirm_box.style.height = confirmH + 'px';
//mdl_ajax_confirm_wrapper
if ($('mdl_ajax_confirm_wrapper') && $('mdl-upsell-product-table')){
//alert($('mdl_ajax_confirm_wrapper').getHeight());
confirm_box.style.height = $('mdl_ajax_confirm_wrapper').getHeight() + 'px';
decorateTable('mdl-upsell-product-table');
}
$('mdl_ajax_confirm_wrapper').replace('<div id="mdl_ajax_confirm_wrapper">'+$('mdl_ajax_confirm_wrapper').innerHTML);
confirm_box.style.position = 'absolute';
mdlCenterWindow(confirm_box);
}
document.observe("dom:loaded", function() {
replaceDelUrls();
replaceAddUrls();
Event.observe($('mdl-overlay'), 'click', hideMdlOverlay);
var cartInt = setInterval(function(){
if (typeof productAddToCartForm != 'undefined'){
if ($('mdl-overlay')){
Event.observe($('mdl-overlay'), 'click', hideMdlOverlay);
}
productAddToCartForm.submit = function(url){
if(this.validator && this.validator.validate()){
sendcart('', 'form');
clearInterval(cartInt);
}
return false;
}
} else {
clearInterval(cartInt);
}
},500);
});
When I go through every line of code in the call stack up to ajax_cart.js: 104, both browsers react the same way.
87: $('mdl_ajax_confirm').innerHTML = '<div id="mdl_ajax_confirm_wrapper">'+return_message + middle_text + '</div>';
RETURN HTML IN ALL VIEWS
89: var link_cart_txt = $('mdl-temp-div').down('.cart_content').innerHTML;
UNDEFINED ON ALL
91:$$('.top-link-cart').each(function (el){el.innerHTML = link_cart_txt; });
RETURNS [object Array] [] ON ALL
97: var mini_cart_txt = $('mdl-temp-div').down('.cart_side_ajax').innerHTML;
UNDEFINED ON ALL
99: $$('.mini-cart').each(function (el){ el.replace(mini_cart_txt); //new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });});
RETURNS [object Array] [] ON ALL
104: $$('.block-cart').each(function (el){ el.replace(mini_cart_txt); //new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 }); });
Cannot get property "tagName" from undefined or null reference on IE RETURNS HTML ON ALL CHROME
source to share
Ok, so after quite a lot of trial and error I found out what the problem was and was able to solve it.
In the code, line 104 of ajax_cart.js was broken, which had this block of code:
$$('.block-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
This prototype.js snippet was looking for the DOM for a .block-cart
div to replace with a set of HTML in it variable mini_cart_txt
. It uses the Prototype $$ () Method to find the DOM and returns all elements with class .block-car
t, then iterates over each of them and replaces their contents with a variable mini_cart_txt
.
The problem was that our HTML theme was changed to include two divs with a .block-cart
div.
<div class="f-right block-cart span5">
<div class="f-left block-cart header_cart margin-left20">[OMITTED CODE FOR BREVITY]</div>
<div class="f-right checkout-button">[OMITTED CODE FOR BREVITY]</div>
</div>
Also the HTML variable in mini_cart_txt
naturally also had two classes .block_cart
, whereas in the original theme there was only one div with a class .block-cart
.
<div class="f-right block-cart span5">
<div class="f-left block-cart header_cart margin-left20">[CODE WITH SUB_TREE CHANGES OMMITED]</div>
<div class="f-right checkout-button"></div>
</div>
<script type="text/javascript">[OMITTED CODE FOR BREVITY]</script>
This is what was throwing the exception in IE, but not in Chrome. I'm not sure why Chrome missed this exception. Perhaps Chrome replaced the first .block-cart
div and then didn't replace the second div .block-cart
that was a child of the first, whereas IE was running like a loop that threw an exception.
Anyway, I managed to fix the problem by removing the class name block-cart
from the child div of the first basket div.
<div class="f-right block-cart span5">
<div class="f-left header_cart margin-left20">[OMITTED CODE FOR BREVITY]</div>
<div class="f-right checkout-button">[OMITTED CODE FOR BREVITY]</div>
</div>
source to share
OK, this is what your code is doing and why you might get the error and how to prevent it.
first, the block of code that throws the error
//$$ is the Prototype CSS selector, it returns an array of DOM elements that match the
//CSS selector
//.each() loops through those DOM elements, el is each DOM element
$$('.block-cart').each(function (el){
//el.replace attempts to replace the original element with the HTML of mini_cart_text
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
If the mini_cart_txt
HTML does not exist, or is possibly invalid HTML, the browser may have a problem replacing elements that match the class block-cart
with mini_cart_txt
. Based on the results from line 97 above, it looks like undefined
, so there might be a problem.
Try to wrap your replacement loop in an if statement
if(mini_cart_txt != undefined)
{
$$('.block-cart').each(function (el){
el.replace(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
}
This might fix the problem, but disable some of the code, so another troubleshooting option is
$$('.block-cart').each(function (el){
//change the replace method with
//el.replace(mini_cart_txt);
//the update method which replaces the content of the element, instead of replacing the element
el.update(mini_cart_txt);
//new Effect.Opacity(el, { from: 0, to: 1, duration: 1.5 });
});
it may reveal more about the problem and may lead you to a solution
source to share