.text update issue in IE - javascript

Having a bit of an issue in IE (aren't we all).
I've tracked down an problem I'm having to a recursive script that updates a tweets timestamp.
The script works fine, discovering all the date/time stamps to be updated, converts them fine but when it comes to updating the 'time' div it fails. IE doesn't have an issue with $('#id').text('value') but I'm obviously doing somehthing wrong.
Any ideas?
function parseTwitterDate() {
var timeToAdjust
$('a[data-scribe="element:full_timestamp"]').each(function() {
timeToAdjust = $(this).find('time')
var b = timeToAdjust.attr('datetime').split(/[-t:+]/ig);
//funky stuff here to generate strTime
timeToAdjust.text(strTime)
});
}
This works fine in every other browser however in at least IE8 (and 6 but not worried about that) it gets to timeToAdjust.text(strTime) and fails.
Note, doesn't have an issue grabbing the 'datetime' attribute timeToAdjust.attr('datetime').
Have tried .html() and $(this).find('time').text(strTime)
Many thanks for taking a look hopfully someone can point me in the right direction.
Justin

IE8 and earlier require special steps to ensure that they properly understand that the new HTML5 element types are actually elements. There are tiny scripts out there (like this one) which do that work for you.
Without doing that work, lots of aspects of those elements won't work even as just normal elements in IE8 and earlier.
This JSBin of your code (jsFiddle doesn't work with IE8) fails, but this one with a shim works.

Related

jQuery misbehaving in Safari

I'm having a problem where certain bit of code is working perfectly across all browsers until I come to Safari where it's giving me issues. I inherited this code, and I'm not a jQuery expert so needless to say I'm a bit baffled:
var xt_begin=$('#begin')[0];
xt_begin.currentTime = 0;
xt_begin.play();
"#begin" is an audio element that was set in the HTML that's using this code and the .play() function is in a jQuery plugin that's being used (Link to plugin).
In all browsers except for Safari, play is being defined as if xt_begin were an object of that timer class. In safari, however, it remains undefined and the code stops working. I have no idea how this happens or how to fix it. I can post more code if need be, any help would be appreciated.
**Update
Upon further investigation it turns out it is a DOM element, and I'm a bit thick. However, Safari seems to have a problem recognizing audio elements for some reason. It's identifying it as an "object HTMLelement" whereas Firefox shows it as "object HTMLAudioElement". I'm still stumped on this one.
**SOLVED
Apparently Safari needs quicktime installed on your desktop for it to use audio elements. That's gonna make this app I'm fixing completely useless, but at least I know now. Thanks for the help folks.
Really just a comment. The statement:
var xt_begin = $('#begin')[0];
is effectively the same as:
var xt_begin = document.getElementById('begin');
so xt_begin is either a DOM element or undefined (jQuery) or null (plain JS). Which is it?
In any case, you should probably follow with:
if (xt_begin) {
/* do stuff with xt_begin */
}
to avoid errors.
Try:
var xt_begin = document.getElementById('begin');
Instead of the jQuery line. That works across all browsers and will at least tell you if you have a jQuery problem or a Safari/web page problem.

svg animation does not start when loaded with settimeout

I'm loading 2 embedded svg-lets in a page. One animated one not. They're loaded in sequence with a setTimeout.
When I load the animated first all goes well, the animation starts as expected and the second static svg is correctly displayed afterwards. When I first load the second, and afterwards the animated one, the animation does not start.
Code is here: jsfiddle switch #svg1, and #svg2 in the javascript.
Upon browser checking I found out this is probably a webkit bug as chrome and safari both show this behavior FF 12 and Opera are well.
Can this be fixed with JS code or should I file a bug with webkit?
== Added
I think the question should be rephrased why the animation does not start after the svg is loaded with a settimeout.
As Jared investigated below it works when the element is present in the DOM and is reordered via dom manipulation into the focus element, Chrome and webkit need a kick with a beginElement() call to the animate element. This still doesn't work out for elements constructed from plain text. As I only do have a mac and I still consider this a hobby project I leave MS IE completely out of the loop.
Well, it took quite a bit longer than I anticipated, but I got it worked out. Basically, the method you were using with the semi-SVG and the regex on the markup, etc., was to say the least not quite the way to get it done.
The answer is to use svg DOM animation methods and attributes, especially to start/stop the animation when you want it to run. Apparently, Firefox was just fine with reinitializing the element and the animation just by manipulating the inner HTML/markup. Chrome (Webkit?), however, actually needs you to programmatically access and control the element. I have not checked in IE, Opera or Safari.
I redid the example, leaving out the arrow altogether, as it is unrelated to the problem. I instead concentrated on creating and testing the animation functionality. The critical points you were missing before were:
var $lasso = $('#lasso'),
animater = $lasso.find('animate')[0],
...
animater.beginElement();
...
animater.endElement();
Here is the demo I made, which is significantly different that what you have in your question:
http://jsfiddle.net/9hBfs/
What I call the "lasso" effect is still there, though.
I would reference the Mozilla Developer Network (MDN) site, as they have a lot of great information and are a highly trusted authority:
https://developer.mozilla.org/en/SVG
https://developer.mozilla.org/en/SVG/Element/animate
http://www.w3.org/TR/SVG11/animate.html#animation-mod
http://www.w3.org/TR/SVG11/animate.html#InterfaceElementTimeControl
http://www.w3.org/TR/SVG11/animate.html#RestartAttribute

Jquery Error in ie8 and ie9 with Wordpress theme. (Object doesnt support this property or method)

I recently launched a website for a client http://www.bridgechurch.us/ only to recieve complaints of it not displaying correctly on ie8 or ie9. I have confirmed this to be true. IE is pointing to this line of Javascript:
jQuery(function () {
jQuery(".scrollable").scrollable({circular: true}).navigator().autoscroll({interval: 7000});
[...]
Can anyone help me figure out what is wrong with this line of code?
Thank you
UPDATE - FIXED
I figured out that there was a comment before the Doctype Declaration that forced IE into quirks mode.
You have a lot of 404's on that page, mainly related to ie-specific css and border images, which is probably why the page doesn't look like it should. Files like /images/internet_explorer/borderBottomRight.png and /wp-content/themes/Moses/styles/default.css aren't loading.
That being said, looking at the scrollable documentation, there is no .navigator() function off of the return value of scrollable(); and I'm getting the same error in Chrome.
Well, visually, the site doesn't appear to work well at all in IE9 (compared to Chrome). But just looking at the code that adds scrollable() to jQuery, you can see that that function doesn't always return the original element. In your code, if you split the call into two, you might be ok:
jQuery(".scrollable").scrollable({circular: true});
jQuery(".scrollable").navigator().autoscroll({interval: 7000});
I blame the plug-in on this one: functions that extend jQuery are supposed to always return the original elements found by the selector.

Stupefyingly weird IE 9 Javascript bug: Altering doc title makes subsequent code execute

I don't understand this at all. Here is some Javascript code that works in every browser but IE 9. It is called from a Flash movie using ExternalInterface, and is meant to dynamically resize the movie in the DOM if the size of the movie changes internally
function vResizeFlash(swfId, ht) {
document.getElementById(swfId).height = "100%";
document.getElementById('flashContainer').style.height = ht + "px";
}
But it works fine if I alter the document.title:
function vResizeFlash(swfId, ht) {
// IE 9 won't run the rest of this function unless
// we go through the charade of changing the document title.
if (navigator.appName.indexOf("Microsoft") != -1) {
var docTitle = document.title.replace(/^(.+?)\s*$/,"$1");
document.title = docTitle + " ";
}
// Well-coded browsers begin here
document.getElementById(swfId).height = "100%";
document.getElementById('flashContainer').style.height = ht + "px";
}
Here I simply trim any white-space from the right side of the document.title, then add a single white-space character to it. Suddenly the following lines get executed. Note: there are other ExternalInterface calls on the page, and all of them work fine, even in IE 9, so it's not a Flash/IE 9 problem.
I stumbled on the fix because I was altering the title to show the function arguments (as a quick debugging test), just to make sure the function was getting run. And suddenly the code worked. Take it out? Doesn't work. 100% reproducible.
Anybody know why this absolutely stupefying behavior takes place?
UPDATE
#c69 has posed the question: "Maybe its IE9's dead code remover?"
I didn't know about this, so I went and Googled and found this article on the topic, as well as some discussion of it elsewhere. I don't know enough about it to evaluate how this would affect a two-line Javascript function, however, especially since one of the lines does have a referent on the page (although it is late-loading through the SwfObject code). Still, it would be a pretty bad bug for a code "optimizer" to remove lines of code it deemed unnecessary because it doesn't understand how they are called. And if it did fail to understand how the lines are called, how does inserting a line making a bogus change to the document.title render that code suddenly "necessary"?
UPDATE 2
Another piece of the puzzle This may have something to do with IE 9's compatibility mode. The page starts out in IE 9's standards mode.
Now, if I turn on IE's compatibility mode,
the problem goes away without using the above hack. Turn it off, and the problem returns (if no hack present).
But when I tried to make a simple test using the exact same HTML (minus a couple of JSP tags) and a stripped down SWF that only contains the resize code and the tools to test, everything works fine. In that case, however, no compatibility icon is displayed at all.
We're using Tomcat 6.0.32. I'm not aware that we are using any special headers, and there are no meta tags regarding IE compatibility mode (in either the main app or in my test app).
like InvertedSpear mentions, check your doc type out, i've had problems with IE9 recently and most of it boiled down to the Doc type tags triggering a compatability mode i didn't need, the same can be true of the meta tags so it might boil down to your Meta tags.
You can always impose a working compatibility mode using the links below too.
from: http://evolpin.wordpress.com/2011/02/25/ie9-compatibility-and-the-meta-tag/
I’ve discovered that this is indeed documented by Microsoft…
http://msdn.microsoft.com/en-us/library/cc288325(VS.85).aspx
“The X-UA-Compatible header is not case sensitive; however, it must appear in the header of the webpage (the HEAD section) before all other elements except for the title element and other meta elements.”
Whenever I see something like this happen in any language it's because there is other code that has a bug. As you pointed out your simple case doesn't produce the problem. Try removing other code a few lines at a time until the problem disappears - the last removed code should contain the problem.
Cheers

How can I control IE6+jQuery+jQuery-ui memory leaks?

Here's a sample page with a couple datepickers. Here's the Drip result for that:
alt text http://www.picvault.info/images/537090308_omoya.png
This page leaks indefinitely in IE6sp1 when I click the Refresh button repeatedly (IE6sp3+, Opera 9, Chrome2, and FF3+ seem to be good). The memory goes up and never goes down until I actually close the browser completely.
I've also tried using the latest nightly of jquery (r6414) and the latest stable UI (1.7.2) but it didn't make any difference. I've tried various things with no success (CollectGarbage, AntiLeak, others).
I'm looking for a solution other than "use a different browser!!1" as I don't have any control over that. Any help will be greatly appreciated!
Update 1: I added that button event to a loop and this is what happens (the sudden drop off is when I terminate IE):
Update 2: I filed a bug report (fingers crossed).
Update 3: This is also on the mailing list.
Update 4: This (as reported on the mailing list) doesn't work, and in fact makes things worse:
$(window).bind("unload", function() {
$('.hasDatepicker').datepicker('destroy');
$(window).unbind();
});
It's not enough to just call destroy. I'm still stranded with this one and getting very close to ripping jquery out of the project. I love it (I really do!) but if it's broken, I can't use it.
Update 5: Starting the bounty, another 550 points to one helpful individual!
Update 6: Some more testing has shown that this leak exists in IE6 and IE6sp1, but has been fixed in IE6sp2+. Now, about the answers I have so far...
So far all answers have been any one of these:
Abandon IE6sp0/sp1 users or ignore
them
Debug jquery and fix the problem myself
I can't repro the problem.
I know beggars can't be choosers, but those simply are not answers to my problem.
I cannot abandon my users. They make up 25% of the userbase. This is a custom app written for a customer, designed to work on IE6. It is not an option to abandon IE6sp0/sp1. It's not an option to tell my customers to just deal with it. It leaks so fast that after five minutes, some of the weaker machines are unusable.
Further, while I'd love to become a JS ninja so I can hunt down obscure memory leaks in jquery code (granted this is MS's fault, not jquery's), I don't see that happening either.
Finally, multiple people have reproduced the problem here and on the mailing list. If you can't repro it, you might have IE6SP2+, or you might not be refreshing enough.
Obviously this issue is very important to me (hence the 6 revisions, bounty, etc.) so I'm open to new ideas, but please keep in mind that none of those three suggestions will work for me.
Thanks to all for your consideration and insights. Please keep them coming!
Update 7: The bounty has ended and Keith's answer was auto-accepted by SO. I'm sorry that only half the points were awarded (since I didn't select the answer myself), but I'm still really stuck so I think half is fair.
I am hopeful that the jquery/jquery-ui team can fix this problem but I'm afraid that I'll have to write this off as "impossible (for now)" and stop using some or all of jquery. Thanks to everyone for your help and consideration. If someone comes along with a real solution to my problem, please post and I'll figure out some way to reward you.
I hate to say this, your approach is correct and professional, but I'd be tempted to just leave it.
The consequences of not fixing this is that IE6 users will notice their machine getting slower and slower and ultimately either crashing completely or more likely crashing IE6.
So what?
Really - why is this your problem?
Yours definitely won't be the only site they visit with this leak, and they will see IE6 crash regularly regardless of what you do, because that's what it does.
It's unlikely that anyone still on IE6 could even point out your application as one that leaks.
Finally when IE6 does crash it reports IE6 as the culprit - you can legitimately point out that this is a bug in IE6 that Microsoft have fixed in a new release.
Your expensive time is better spent on improving the application for the users not trapped in legacy hell - your app should basically work for IE6 users, but this sort of issue can suck away all of your time and not fix their problem. IE6 is still going to be an unsupported, crash ridden, security hole of a browser.
I suspect the jQuery devs take a similar view to me. Also you have to do some really ugly stuff to get round this bug in IE6, including hacky DOM work that stops the leak but is actually much slower.
Update
Ok, this isn't an easy problem to fix - MS describe the IE6 bug (and provide advice on how to fix it) here: http://msdn.microsoft.com/en-us/library/bb250448(VS.85).aspx
Basically this isn't a problem with javascript or jQuery - the actual issue is with the IE6 DOM - when HTML elements are added to the page (by javascript, rather than being in the page when it loads) IE can't garbage collect them unless they are created in a very specific way.
This is back to front from how jQuery UI builds elements (see DOM insertion order bug in the link above) and so this isn't something that either the jQuery devs or you can easily fix.
So how do you fix the issue? Well, you can stick with the legacy pop-up calendar for IE6 or you can write your own one.
I would recommend the former, but if you really want to built the latter there are some basic rules to follow:
Always add elements top-down - for instance if you want to built a table add the <table> element into the page's DOM, then add <tr> then <td> and so on. This is back to front as it's much quicker to build the entire table and then add it to the DOM - unfortunately that's where IE6 loses track of it.
Only use CSS and HTML 3.2 attributes - sounds dumb, but IE6 creates extra objects to store the extra attributes (or 'expando' properties) and these also leak.
Kinda related to (2), but as #gradbot mentions IE6 has problems garbage collecting javascript variables - if they reference a DOM element inside an event fired from that element you can get problems. This is also compounded by javascript references to DOM elements that have 'expando' properties.
If you have a look around online there may already be a drop-down DHTML calendar that sticks to these rules - it won't be as pretty, quick or configurable as the jQuery UI one, but I'm sure I've seen it done without leaking in IE6.
I think the best bet is to keep as much static as possible - for instance you could load the calendar grid (week numbers and day column headings) with the page and then dynamically load in the numbers (and nothing else). Create the day numbers as links, with javascript in the href - not best practice normally but far less likely to leak in IE6.
It's obvious that the problems you've been describing stem from a flaw in IE6 that you can't subvert with a software fix (be it a jQuery update, a manual call to CollectGarbage, or some other JavaScript/DOM hack).
There are 3 options, in my mind, that would fix this problem.
I would imagine that your customers/users are using IE6 SP0 because of some company standard or regulation, or even because some older web-app they still use doesn't support newer browsers. If it's not an option to upgrade to IE7 (or therefore IE8), you could get in contact with your customers' IT department and politely point out that updating IE6 with the latest service packs would not only fix a problem with an application that they are paying for, but also patch many security and performance flaws that undoubtedly exist in IE6 SP0. Admittedly, that might not be a comfortable situation, but it might solve the problems you are encountering, while still allowing them to work with a browser that require for whatever reason.
If you can convince your customers' IT department that IE6 is antiquated, they may be willing to allow your users to upgrade to a newer browser. It's not a stretch to say that someone running an IT department would be more willing to force employees to upgrade a piece of software if they knew it was either a) riddled with flaws and security holes or b) approaching its end of support date (as IE6 SP0 is). IE6 SP0 on XP Pro SP2 is supported until July 13, 2010 - so it still has some time, but pointing that out, along with other flaws/limitations you could find might make them think seriously about upgrading sooner rather than later.
If you can't convince anyone to upgrade their browsers either to IE6 SPX, or to IE7/8, then I don't know if you have a choice but to remove the offending control from your page, and pursue a different option until the user's browser permits it. There are assuredly many implementations of a date picker control available online which would suit your needs. It might not be as snazzy as the jQuery version, but you don't have many other options at this point.
I hope you find a solution!
try deleting these objects after destroying the datepicker object:
$.datepicker = null;
$.fn.datepicker = null;
This problem is either in a IE6-only part of jQuery, or in a general part of jQuery that is lacking IE6 especific code (as noted in the comments). Either way, it's still a bug in jQuery that needs addressing.
about:blank
You'll either have to dig yourself into jQuery or file a bug ticket. If you manage to fix it, don't forget to attach a diff to the bugtracker, so the project gets a little bit better. ;)
If I get some spare time, I'll try to help you with this.
Edit
Ok, so the problem seems unsurmountable.
The leak you are facing is an IE 6 SP 0 only problem, a leak caused by IE's approach to DOM. Doesn't matter what JS framework you use, it refuses to work correctly.
So, your current options are:
Die trying to get your users to upgrade IE 6 to a newer version/Service Pack,
Die (as in leak) in IE (loosing customers) or
Die trying to work on IE.
But that doesn't necesarily means you can't work this out. What about just trying to side pass the wole thing?
Show every non IE 6 SP 0 user the jQuery datepicker, and only IE 6 SP 0 another more resilient (and probably basic) datepicker with IE's conditional comments. This way you can keep the eye candy/functionality in your software, and allow IE 6 users to have the same basic functionality.
It might not be such a clean option, but you'd still be able to use what you want, and IE6 will still be able to work without leaking.
The only problem will be that you'll have a bigger burden, by having to degug two distinct datepickers. But you'll have to debug IE 6 anyway so, it may be your best bet at the moment.
The problem with IE 6 is that it has two garbage collectors. One for JavaScript and one for the DOM. So for example if you attach a function to a DOM event and then delete the DOM element the function will still exist in memory.
Check out this slide show. It's a bit tongue in cheek but it's good information.
They fixed this issue in IE 7. I tried your page in IE8 in windows 7 and I'm not seeing a memory leak.
The problem here lies a bit deeper than 'just' jquery. Jquery along with many other browsers "leak" circular references between DOM objects and object listeners. Say you have an input field that has attached to it a listener, then you remove the element from the dom and do not have any reference to the listener in your code. Now any modern browser (>=ie7, ff, chrome, safari, opera) will live with that and garbage collect it, while IE6 will think that because there is a listener attached to a dom element it should not garbage collect the dom and the listener itself.
To get around that some folks use very complicated design patterns as highlighted for example in events code in Google Doctype. To fix the problem for IE6 you would really need to rewrite a portion of jquery to work around IE6 issue and/or switch to using a different library and/or not attach any event listeners in your application to DOM events.
Can you try this demo here. It uses the same method as dojo implements to remove elements from the dom. Some quick testing it seems to ease the leaks, not fully but much better.
UPDATE After spending a little time on this I am convinced it is nothing to do with the datepicker itself.
My tests show that by just reloading a dummy page every 1 second sees ie leaking memory.
If you then include jquery on this page the leaks increase slightly (overhead of parsing the script) If you then add jquery-ui into the mix then again there is another slight increase in memory leakage.
To prove this if you avoid reloading the page and instead have a button that just adds an input, creates the datepicker on it then removes it, you see very little if any leaks.
Take a look at this snippet that cleans up DOM nodes. You may find it useful. https://stackoverflow.com/a/9519996/139667
The best debugger available for IE6 is Visual Studio. (Even the free edition will work.) As Janie mentions, if your problem is only happening on IE6 you'll want to debug on IE6, paying special attention to code that only runs there.

Categories

Resources