jQuery event handlers not firing in IE - javascript

I have a list of items on a page with a set of controls to MoveUp, MoveDown and Delete.
The controls sit at the top of list hidden by default. As you mouseover an item row, I select the controls with jquery
//doc ready function:
..
var tools = $('#tools');
$('#moveup').click(MoveUp);
$('#movedn').click(MoveDn);
$('#delete').click(Delete);
..
$('li.item').mouseover(function(){
$(this).prepend(tools);
});
This works great in Firefox .. the tools move into the current row, and the click events call the ajax functions. However, in IE6 and IE7 .. no click occurs. I tried unbinding on mouseout and rebinding on each mouseover .. to no avail.
I also looked into various reasons outside of javascript (e.g. transparent png conflicts, z-index, position:absolute) .. also no solution found.
I eventually needed to add a tools row to each item and show/hide on mouse over/out. Works just as well -- the only downer is that I have much more 'tools' markup on my page.
Does anyone know why IE ignores/drops/kills the mouse events once the objects are moved (using prepend)? And why rebinding the event afterwards also has no effect? Kept me annoyed for almost 2 hours before I gave up.

IE will lose events depending on how you are adding things to the DOM.
var ele = $("#itemtocopy");
$("#someotheritem").append( ele ); // Will not work and will lose events
$("#someotheritem").append( ele.clone(true) );
I would also recommend using .live() on the click events to simplify your code a little. Mouseover/out is not supported by live yet. http://docs.jquery.com/Events/live

I just spent the whole day troubleshooting events not triggering on items appended to the DOM, (IE7, jQuery 1.4.1) and it wasn't because I needed to use live() (though, good to know, Chad), nor was it because I needed to clone the items.
It was because I was selecting anchor tags that had a "#" in them like so:
var myitem = $('a[href=#top]');
My solution was to use the "Attribute Contains Selector" like so:
var myitem = $('a[href*=top]');
Fortunately I have enough control over everything that it won't likely break in the future. This isn't technically related to appended objects, but hopefully it saves someone some time.

i had a similar problem. trying to use .ready to load a div on the initial page load.
works well in FF , but not ie7.
i have found a hack that seems to get around this.
I have load call a callback, divLoaded().
In divLoaded i check the $('#targetdiv').innerText.length < 50 or whatever you think will indicate that it didnt load. If I detect that case, i simply call the function taht loads that div again.
Oddly enough, i also add a '.' to the innerText before i recall the ajax function. It seems taht sometimes we go through 3 or 4 loops before the ajax load finally takes.
This leads me to think that document.ready works pretty flawlessly in IE7, which seems to dispel a bit of a myth that it is unreliable. What really 'seems' to be happening is that .load is a little bit flakey and doesnt work well when the page is just loaded.
I am still a bit green w/ all the jQuery stuff, so take this w/ a grain of salt. Interested to hear anyone's take on my little hypothesis.
cheers
greg

Related

Is "document ready" supposed to work like this on IE?

I'm making a small javascript framework, for a variety of reasons, including learning.
Hence, I wanted to implement "document ready" functionality, and so I went to check how jQuery fakes DOMContentLoaded on IE < 9.
Problem is, it doesn't seem to be working the way it should. Check this fiddle in IE8 and a good browser.
The logic is: apply css to make a div start red, then on "ready" make it blue, and on load make it green. Additionally, there are three img tags with fake URLs just so there is a synthetic lag between ready and load.
What should happen:
The div shouldn't be shown red for more than a split second, if at all. Ideally, the first thing seen should be blue. Then, when the browser times out on the invalid images, green.
What happens on IE8:
The div remains red until all images "load" (in this synthetic example, timeout), then goes green.
Again, I'm not exactly asking for a fix, I'm asking if it is the right thing for a framework to behave like this on IE8 (I don't care about IE 6-7 anymore), or if this is happening due to me misusing jQuery in some way.
P.S.: I know how to bind an event manually, I'm asking more about if this is expected/acceptable/a bug/my mistake.
I'm going to go with working as intended.
jQuery is using the document.readyState for browsers that don't support DOMContentLoaded. document.readyState only equals complete when the page's resources are done loading.
https://developer.mozilla.org/en-US/docs/DOM/document.readyState
There's probably a good reason why they aren't doing it on "interactive", but I'm not positive on that.
Edit: Here's your updated fiddle with a event on document.readyState == interactive
http://jsfiddle.net/PFWmS/7/
It works in both IE7 and IE8
Edit
The reason that jQuery doesn't use "interactive" is because that fires too early in IE9.
http://bugs.jquery.com/ticket/12282#comment:25
I'm thinking there may be a better way of handling that which results in IE7 and 8 proper ready timing while still working properly in IE9

How to debug DOM manipulation by jQuery?

I'm working on an website with some dynamic jQuery content.
If the user pushed a button ("show menu") on the page, an javascript function runs. Let this function call loadMenu().
The loadMenu() function loads a menu (web conent) from server using ajax. Part of this loaded code is javascript/jquery. 2 functions of this code make some elements on the page draggable, 2 other functions make some elements on the webpage droppable. These functions are all started at $.ready-Time (if the DOM is ready).
All this works fine.
Now i added an "MenuAlwaysVisible" feature. This means: if the web-page is loading and finished (ready) the user doesn't need to press the button "show menu", because the javascript loadMenu() now fires automatically, if the page is ready
The problem now is, it looks like, the draggable handler are attached and worked as defined, but droppable does not work.
I'm not sure, but probably the droppable function runs on a time, where the DOM elements doesn't like to be droppable? Ore maybe some other jQuery codes overrides this? (but there are no other droppable elements on the page)?
So the question is: how to analyze that problem: how to debug DOM manipulation, using Windows and Firefox/Firebug or Safari, Chrome .. whatever...
Thank you!
One debugging trick I have found endlessly useful for dealing with JQuery is the insert obvious code trick. Slap in a .hide() command on some obvious, identifiable part of the page, and see if the code ever runs. Lets you track which code pieces are not behaving as intended, and which are simply never being used in the first place.
To answer my own question: i did not found any alternatives way than using firebug and console.info() or console.warn() to debug the code.
Thanks # all for the comments

oninput/onkeyup/onkeydow/onpropertychange doesn't work in IE8

As you might have noticed from the title I'm trying to make an event work properly and IE is giving me a hard time. I have tried all possible combinations, none of them seems to work.
I'm trying to mimic the Google suggestions list. A visitor should be able to come down in the list using the arrow keys, which is a Jquery keydown event. This event however also renders the request for the suggestion list at the same time in IE8 so the therefore the arrow keys function comes to an end (because of the request that is being maid.)
I know there must be a simple solution to this, but I can't see it.Help is appreciated. This is a demo: at jsbin
It works in all browsers but not in IE.
You are attaching the events before the elements exist.
Always work with elements only inside $(document).ready() method to be sure they exist and loaded in the document.
In your specific case, just move all the code:
el("inp").oninput=function(){
addScript("http://www.google.nl/complete/search?callback=suggest&q="+this.value);
}
$('#inp').keydown(
function (e){
var curr = $('#test').find('.current');
//......
}
//.....
To be inside the $(document).ready( you already have.
Live test case that works for me in IE as well: http://jsfiddle.net/n7qAD/12/
(Your original code really didn't work in IE)

Why is this jQuery animation so SLOW on Firefox 4/5?

EDIT by Phrogz: This appears to be a problem with the framerate of jQuery animation when this particular complex CSS is applied. See the video at the bottom for an example of the problem.
I think is hard to copy and paste the whole code here. So I've create a fiddle for this.
To be honest, CSS is not so important on this (I putted it for have a decent grid). I also removed many functions from my original version, in fact they aren't so important.
The only one that works is by clicking on the buttons + Tracks (which call addTrack()) that adds a new track/line in the grid. Tested on Chrome, IE, and Firefox < 4 version. There isn't much problem. It's really rapid and fluid.
The problem is on Firefox 4 or 5. It's really slow to add the new track/line. It's fast like a turtle.
What the function done is to clone (copy with handler) an element trackOn, which is already written in a hidden field (tracklistOff) and add it (insertAfter) applying a fade effect. (thats means a new line in the grid).
Why this behaviour on Firefox? Too many elements to browse on the DOM I suppose. I need to get rid about this slow attitude... so what can I do?
EDIT
You can hear the difference about Chrome and Firefox (5, last version) on this video. Try to hear/see the difference between clicking on mouse and add new line (with the effect). It's too frozen (also when I try to add more tracks quicly).
Still a problem for me, any suggestion will be appreciate :)
This is not very slow for me. On my computer running Firefox 5 I can add many tracks in less than a second. What performance are you seeing? ("Fast like a turtle" is not a very quantitative measurement. :)
When you have trouble with JavaScript speed, profile it, using the Developer tools for Chrome/Safari/IE or Firebug for Firefox. Here's what I see when I run the profiler on your JSFiddle and click on the +Track button twice:
From this we can see that most of the time is spent in some set function from a mootools library. Since I don't see this library included in your code, I'm assuming the profile is tainted by JSFiddle.
So, we create a standalone test case without the unnecessary CSS and profile that. Now we see this (for several presses of the +Track button):
Almost all of your time is spent in the clone() function.
So what can you do about it? You could try pre-creating the HTML string (in JS) for a template row, and instead of using 'clone' try creating that with:
$(templateString).hide().insertAfter(...).fadeIn(600);
would it be ok if you get just the last element?
something like:
$('.tracklistOff div:last-of-type')
.clone()
.hide()
.insertAfter(($(param).parents('.trackOn')))
.fadeIn(600);
or you could addClass(last) to the last element to get only one
I just tested your fiddle on the following browsers and they all worked well: FireFox 5, Opera, Google Chrome, Safari & IE9.
There were no speed issues but each browser handled the fade slightly differently however everything else seemed to work fine. Not sure what the problem is here. It could be your computer speed but as you're on this site I presume it's decent.

Problem with qTip - Tips not showing because elements load after the script

I'm not very experienced with javascript, jQuery or it's plugins but usually I manage. Anyways, my client is building a site and one of its purposes is to pick up news articles from different sites and show the titles in unordered html lists. I don't have access to his code, the news articles load up rather slow(much after the site has loaded).
I'm using qTIP and the idea is that once you hover over a news title, it will generate a tooltip. This works fine in my dev environment, because I have dummy title's that are not generated from anywhere.
The problem is that once the client sets the site up in his test environment, the scripts that load the news titles into the lists are so slow, that the qTIP-script loads before there are any elements in the lists. Hence it's not aware of any <li>'s to pick up and generate tooltips from.
Is there a way make sure that ALL of the news articles are loaded before the tooltip-script
loads? I think that a simple delay in loading the script is not very smart because some of the titles seem to take longer to load than others, so the delay would have to be rather long.
See my update at the bottom
I've been working on this problem as well, and came up with a solution similar to that provided by #Gaby. The problem with #Gaby's solution is that it doesn't create the qTip until the mouseover event has happened. This means that you won't see the qTip the first time you mouseover, but will the second time. Also, it will recreate the qTip every time you mouseover, which isn't exactly optimal.
The solution I went with is this:
$("li").live('mouseover', function() {
var target = $(this);
if (target.data('qtip')) { return false; }
target.qtip(...);
target.trigger('mouseover');
});
Here's what it does:
Sets target to the li element
Returns if that li element already has a qtip
If no qtip on li, then applies qtip to it
Sends mouseover trigger again so that qtip is activated
I know this is a bit hacky, but it seems to work. Also note that the 2.0 version of qTip should support live() as an option. As far as I can tell, the current 2.0 development branch doesn't yet support it.
UPDATE:
Here's the proper way to do this, direct from the qtip developer himself on the forums:
$('selector').live('mouseover', function() {
$(this).qtip({
overwrite: false, // Make sure another tooltip can't overwrite this one without it being explicitly destroyed
content: 'I\'m a live qTip', // comma was missing here
show: {
ready: true // Needed to make it show on first mouseover event
}
});
})
So it first makes sure that you don't recreate new qtips every mouseover with "overwrite: false". Then it makes the qtip show on the first mouseover with "show: {ready: true}".
You should use the Live Events of the jQuery framework.
Binds a handler to an event (like click) for all current - and future - matched element. Can also bind custom events.
so for example you could do something like
$("li").live( 'mouseover', function(){
$(this).qTip(...);
});
ref: http://docs.jquery.com/Events/live
Not for nothing, but I just added the show:{ready:true} in my onmouseover event. That got it working in Chrome & FF.
Yeah I came up with something similar. I think someone posted a similar one on their forums as well. I changed the mouseover-event to mousemove so that the qtip activates on the first mouseover.
$('li').live('mousemove', function() {
if( !$(this).data('qtip') ) {
$(this).qtip(...)
I also agree that this is a very hacky solution, however I couldn't come up with a better one. Maybe checking and applying the qtip in the callback function that fills the li's would be better but I don't really have access to that code.

Categories