On a website I'm designing a user searches for hotels in a city, and results are returned as xml then formatted through ajax/javascript/jquery.
The results are displayed almost immediately in Chrome or FF, but in Internet Explorer (I've tried ie6 and ie9) the results take almost a minute to be displayed.
Running the developer tools in IE states that 99% of execution time is spent in function "getElementsByTagName" which is called almost 200,000 times, however I'm unaware of how to fix this if it is the issue.
The page in question is beta.hotelsweep.com and the function being called on search is:
//summarized version of the function
$.get(url, function (xmlResponse) {
$('#results').empty();
var exception = $("Exception", xmlResponse);
if (exception.size() > 0) {
var error = "<h2>We were unable to complete your request</h2>";
$('#results').html(error);
} else {
$('#numResults').html($("resultsNumber", xmlResponse).text() + " hotels found <br>");
var resultsHtml = "<div id='results_list'>";
//set googlem map to center
map.setCenter(new GLatLng($("avgLat", xmlResponse).text(), $("avgLong", xmlResponse).text()), 9);
// Loop through response, creating <li> for each hotel
$("Hotel", xmlResponse).each(function () {
var bookLink = $('affiliateLink', this).text();
var address = $('fulladdress', this).text();
var stars = $('stars', this).text();
resultsHtml += 'Hotel Stars: ' + stars;
});
//put html into results div
$('#results').html(resultsHtml);
}
});
You can't really fix this issue. getElementsByTagName isn't indexed in older versions of IE. You can use element id lookups instead (avoid $("Exception"), $("avgLat"), etc).
If that's not feasible, you can add a script on the server to render the results to HTML.
It turns out the issue was something to do with the document mode. In quirk mode, the javascrit wasn't even fully executing.
Adding this to the top:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
or
<meta http-equiv="X-UA-Compatible" content="IE=9" />
Made Internet Explorer execute as expected. I don't fully understand what is happening, but if you find your javascript executing incorrectly only in IE it could be to do with the document mode.
Related
When I execute the below test HTML page in Chrome, I see the following in the debug console:
Has parent? true
Has parent? false
Am I right in assuming that this a Chrome bug (it doesn't happen in other browsers), or is Chrome within its right to do this for some reason? It resulted in a bug in one of my web apps and I finally isolated this snippet to repro the core issue.
Here is the test page:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body class="">
<script>
function testDoodle() {
var testParentEl = document.createElement('div');
var testChildEl = testParentEl.appendChild(document.createElement('div'));
document.body.innerHTML+=('Has parent? ' + !!testChildEl.parentNode+'<br>');
console.log('Has parent? ' + !!testChildEl.parentNode);
setTimeout(function() {
document.body.innerHTML+=('Has parent? ' + !!testChildEl.parentNode+'<br>');
console.log('Has parent? ' + !!testChildEl.parentNode);
},
2000);
return;
}
testDoodle();
</script>
</body>
</html>
EDIT: I should have mentioned that I'm testing on Windows 7 with Chrome 49.0.2623.87 m (64-bit). Was also able to repro on OSX 10.11.2 with Chrome 49.
Also, I should mention that sometimes it displays true/true and sometimes true/false. You might have to reload the page a few times to witness the issue. I'm not sure, but it's possible that the debug tools (console) need to be open as well.
Thanks much.
My guess is that testChildEl.parentNode does not reference testParentEl strongly, so it's garbage collected.
Both referencing testParentEl inside the timeout and adding a strong reference to testParentEl on testChildEl fix the problem for me:
(function testDoodle() {
var testParentEl = document.createElement('div');
var testChildEl = testParentEl.appendChild(document.createElement('div'));
setTimeout(function() {
testParentEl; // Prevents it from being garbage collected
document.write('Has parent? ' + !!testChildEl.parentNode);
}, 100);
})();
(function testDoodle() {
var testParentEl = document.createElement('div');
var testChildEl = testParentEl.appendChild(document.createElement('div'));
testChildEl.strongParent = testParentEl; // Prevents garbage collection
setTimeout(function() {
document.write('Has parent? ' + !!testChildEl.parentNode);
}, 100);
})();
I believe that this is finally fixed by Chrome v50 (or at least I haven't been able to repro since updating).
When I open Chrome developer tools, open this web page, and take a snapshot, the size is 2.1MB.
When I click on one of the buttons, all of them and their div are removed. If I then take another snapshot, the size is 1.6MB.
So is it the case that when using Chrome developer tools and taking snapshots, there will always be some memory consumed by the web page, that you need to account for when taking snapshots and looking for memory leaks?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript">
var onLoadFunc = function() {
for(var x=0;x<30000;x++) {
var button = document.createElement("input");
button.type = "button";
button.value = "Destroy Content";
button.onclick = destroyFunc;
document.getElementById('mainDiv').appendChild(button);
}
};
var destroyFunc = function() {
var el = document.getElementById( 'mainDiv' );
el.parentNode.removeChild(el);
};
</script>
</head>
<body onLoad="onLoadFunc()">
<div id="mainDiv"/>
</body>
</html>
You see in the snapshot everything that javascript engine keeps in the heap.
The javascript engine (v8) actually uses heap for almost everything include the generated code for your page, internal v8 scripts, objects, maps etc.
It may confuse you because you can't control the lifetime of these objects but it would be bigger problem if we hide that internal things in the snapshot. In that case you would ask why this object still alive when all the references to it from my objects were removed. Or why the empty page uses 1.6mb of js heap and heap snapshot shows nothing. etc.
What you're seeing in that 1.6 MB includes the objects which have been destroyed but remain in memory because they have yet to be garbage collected.
The destruction of an object does not guarantee when it will be garbage collected.
Hi I have a custom js autocomplete component using AJAX that uses a div containing a table to show matching values.
When using it in IE9 with DOCTYPE declaration the div does not appear.
The strange think is that if I have another instance of the component in tha page everything works fine (I have those components in a table and add new rows dinamically; if the table is empty at the beginning I have the problem, otherwise I can add new rows containing new instances of the component and everything works fine).
The code work fine in firefox and chrome.
It works fine in ie9 too if I specify
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="X-UA-Compatible" content="IE=8" />
I have debugged and the javascript setting the div visible is executed to no avil:
this.resultTable.innerHTML=responseText;
this.resultTable.style.top=getY(this.editField)+22;
this.resultTable.style.left=getX(this.editField);
this.resultTable.style.zIndex="1";
this.resultTable.style.visibility='visible';
If I resize the windows the div magically appears.
Thanks in advance for you reply.
EDIT:
I have found a solution (thank to epascarello hint).
I have added
window.resizeBy(1,1);
window.resizeBy(-1,-1);
this solved almost because my page is in an iframe 100% w/h; the only remaining issue was that maximizing and restoring browser windows resulted in unecessary srollbars appearing in the iframe; I solved it adding
getFrameForDocument(document).style.width='100%';
getFrameForDocument(document).style.height='100%';
where getFrameForDocument was found at Getting a reference to the parent IFRAME and is
function getFrameForDocument(document) {
var w= document.defaultView || document.parentWindow;
var frames= w.parent.document.getElementsByTagName('iframe');
for (var i= frames.length; i-->0;) {
var frame= frames[i];
try {
var d= frame.contentDocument || frame.contentWindow.document;
if (d===document)
return frame;
} catch(e) {}
}
}
At the bottom of this Magento product page you can see three tabs (Additional Info, Description and Tags) but it is impossible to switch between them in Internet Explorer 9 (even if I add the site to the trusted site group). The IE Javascript console (via F12) doesn't show one single error or warning.
What is going on?
I had this on a site I did last year - this isn't a new site, right? Some used to use the technique of forcing IE9 into IE8 mode using;
<meta http-equiv="X-UA-Compatible" content="IE=8" />
but I fixed my issue using this thread;
http://www.magentocommerce.com/boards/viewthread/219259/#t328876
Reposted here for link rot, in template/catalog/product/view/tabs.phtml
you remove the ordered list (ol);
showContent: function(a) {
var li = $(a.parentNode), ul = $(li.parentNode);
ul.select('li', 'ol').each(function(el){
Would become;
showContent: function(a) {
var li = $(a.parentNode), ul = $(li.parentNode);
ul.select('li').each(function(el){
(I've not copied the full function out, it's only that last line that changes).
Hope that helps you too.
EDIT - Yes I checked - the file and directory structure for the collateral info like this has since gone, but for CE 1.5 there was a tabs.phtml file in product/view/
I need to access a XML document I created with JavaScript via XPath. If I load an XML file from a server (via XMLHttpRequest) it works fine, but if I use the XML document reference from the local created XML document Chrome didn't show anything, while Firefox did what I expected.
Here a bit of example code:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<script type="text/javascript">
var xml = document.implementation.createDocument("", "", null);
var root = xml.createElement("root");
var level1 = xml.createElement("L1");
var level2 = xml.createElement("L2");
L2txt = xml.createTextNode("here is L2");
level2.appendChild(L2txt);
level1.appendChild(level2);
var level2 = xml.createElement("L2");
level2.setAttribute("id", "myId");
L2txt = xml.createTextNode("here is L2 with id");
level2.appendChild(L2txt);
level1.appendChild(level2);
root.appendChild(level1);
path="//L2[#id='myId']";
var nodes=xml.evaluate(path, root, null, XPathResult.ANY_TYPE, null);
var result=nodes.iterateNext();
while (result) {
document.write(result.textContent);
document.write("<br />");
result=nodes.iterateNext();
}
</script>
</body>
</html>
the Code should output "here is L2 with id".
I use FF 9.0.1 and Chrome 16.0.912.75 m the development tools don't show any error or hint.
Now I don't realy know, is it a bug in Chrome or an 'extra' feature in Firefox. And - most importent - how could I bring Chrome round to act like Firefox. Or do you have another idea how to use XPath on local created XML documents?!
Thanks in advance
I see you have a small problem in your example code.
The root element is never added to the XML document (the xml variable).
Therefore the XPath search cannot work since the xml document object has no root element and therefore no content to search. Try adding :
xml.appendChild(root);
After this:
var root = xml.createElement("root");
That fixes the issue for me in Chrome.