jQuery.trigger('click') results in "change" Event in IE8 - javascript

$('#myRadioButton').change(function(event) {
var eventType = event.type;
$(this).trigger('click'); // In IE8 only, this results in endless loop
});
The code snippet above results in a change event being fired in IE8 and hence an endless loop is started when my radio button is selected. This is not the expected behaviour, as a 'click' event certainly is not a 'change' event. In other browsers and IE9+ the code works as expected (i.e., not an endless loop).
The variable eventType equals "change" in IE8, both for initial, user triggered 'change' event, but also for the subsequent calls to itself.
What is the reason for this behavior and how to stop IE8 from being a jerk and act like a normal browser?
Best regards!

Reason - no idea sorry.
'Work Around' :-
function radioChange() {
$(this).off('change', radioChange);
$(this).trigger('click');
$(this).on('change', radioChange);
}
$('#myRadioButton').change(radioChange);
trigger is synchronous, so removing the change, then triggering the click, then re-attach the change should work.

Related

stopPropagation in Chrome and IE

I've been having trouble getting stopPropagation to work for my dataview. Basically the issue is as follows;
Select node in the dataview, this fires the select, selectionchange events
Selected node has an image with an onClick event, this creates a report in a pop up window.
When image is clicked I call stopPropagation to prevent the event being bubbled up to the dataview which would cause the deselect, selectionchange events to be fired.
stopPropagation only seems to work in Firefox for me. Chrome and IE it seems to have no effect as the node is deselected and the unwanted events fired.
I've tried the following function on the onClick event
handleBubbleEvent: function(e) {
if (!e) {
var e = window.event;
}
e.cancelBubble = true;
e.returnValue = false;
if (e.stopPropagation) {
e.stopPropagation();
}
}
Have also seen stopImmediatePropagation, preventDefault, stopEvent but these also has had no effect
I am doing all this inside an Ext XTemplate
I'm wondering if this is an ExtJS 5 issue and the same code is working for an older version of ExtJS. I just can't seem to stop the click event bubbling back up to the dataview which then fires the deselect and selectionchange events.
Could it be that it is a timing/order issue. I use ExtJS's selectionchange event on the dataview whereas in the XTemplate I am using my own listener function? I see stuff online referencing capturing/bubbling of events and as I'm not a web developer I'm struggling on this.
UPDATE:
I'm now looking at events and capturing/bubbling, it seems the capturing is going up to the parent and calling the deselect, selectionchange then going down into the actual click handler at which point I then call stopPropagation but it is too late at this stage. Looking at creating my own listener for selectionchange with either target/delegate set so that it is only called when class != 'some class' and then a listener on 'some class' click to handle what I want and stopPropagation, if that makes any sense!
Try using a setTimeout on any dom manipulation triggered by the event.target element's event handler so that the event bubbling completes before any of the dom manipulation occurs.
I had the same issue with Chrome, and (like with you) Firefox worked. I discovered that Chrome seems to get confused if you modify the dom before the event bubbling completes.
In my case, I was adding two elements to the document.body (a canvas and a fieldset) and by the time chrome bubbled the event, the event.target was incorrect (it thought "BODY" was the event.target.tagName -- WRONG!). I wrapped the DOM manipulation portion in a setTimeout like this:
setTimeout(()=>
{
document.body.appendChild(canvas);
document.body.appendChild(fieldSet);
},0);
After this, chrome started reporting the correct element.target on the bubbled body click event. Maybe this same technique will help you get e.stopPropagation() to do its thing before the dom manipulation occurs.

Trigger event from inside event hander has different behavior in IE10

I want to trigger a blur within a keypress. IE10 works differently from Chrome/FF. It appears that IE will finish the keydown handler before calling the blur handler, whereas Chrome and FF will trigger the blur handler right when the blur occurs and then go back to finish the keypress handler.
I'm wondering if this is a bug and if there is a good workaround in IE to work like Chrome and FF.
See the code below.
$(document).ready(function () {
document.getElementById("txtInput").addEventListener('blur',
function (event) {
console.log('blur');
});
document.getElementById("txtInput").addEventListener('keydown',
function (event) {
console.log('down 1');
document.getElementById("txtInput").blur();
console.log('down 2');
}
);
});
http://jsfiddle.net/244raf1u/
Output from Chrome:
down 1
blur
down 2
Output from IE
down 1
down 2
blur
Try this:
$(document).ready(function () {
$("#txtInput").blur(function (event) {
event.preventDefault();
console.log('blur');
});
$("#txtInput").keypress(function (event) {
console.log('down 1');
$(this).blur();
console.log('down 2');
});
});
Check out the changes I made in this updated fiddler here.
I had to change the way you were calling the blur() trigger, and then added a simple event.preventDefault() in the blur() handler to prevent a second firing in IE. It seems like IE was trying to move focus off of that input after running the keypress handler.
Also by using this notation: ($("#txtInput")[0]) you are actually referring to the original element object and not the jQuery object, which may be causing issues in IE where the other two are catching the error.
Hopefully this will help!
I found a couple solutions. First is to use the focusout instead of blur. Blur doesn't bubble, focusout does. Not sure why that matters, but the events are probably implemented differently. Unfortunately, that's not an option for me.
The other solution was to have two keydown handlers. The first triggers the blur and anything I want to happen before the blur. The 2nd handler does the processing after the blur, but I have to set a 50ms timeout because all keydown handling occurs before the blur handling.

Why does not self focus work in JavaScript?

Whenever a blur event is triggered from any input element, I want to set focus to one particular element.
This issue arises when I am trying to focus to the same element triggering the blur event.
Why does this only works, when the element I am trying to focus on to, is not the one triggering the event?
[Issue Illustration]
and explanation as per the fiddle:
The element I am trying to focus to is col0
Unless the element to trigger the blur event is not col0 it works perfect
But when blur is triggered from col0 itself, then $("#col0").focus() does not work.
Q: Why? & What is the workaround/solution?
P.S: I am just trying to know the cause of the behavior and ways to overcome it. Concerns about the usability, is NOT THE QUESTION.
This works in FF for me...
$('input').on('blur', function() {
setTimeout(function () { $("#col0").focus(); }, 0);
});
it is just to postpone a UI action a bit (after processing the blur event is finished).
Warning: in jsfiddle FF won't let you edit the code after you try it, once you get to the input you are stuck there until refresh
Update: The explanation is tricky, as it is a matter of implementation in FF (as Chrome and IE behave as you expected), my guess is that FF prevents firing related events when you are in the event handler for the same element (a thing that may potentially lead to infinite cycle), using setTimeout you are firing the event soon after you leave the handler (and even UI has a chance to redraw itself)
It looks like you're trying to keep focus on everything except the control you're on. Try this:
$('input:not(#idofcontrol)').blur(function() {
$('#idofcontrol').focus();
});

What's the cross-browser way to capture all single clicks on a button?

What's the best way to execute a function exactly once every time a button is clicked, regardless of click speed and browser?
Simply binding a "click" handler works perfectly in all browsers except IE.
In IE, when the user clicks too fast, only "dblclick" fires, so the "click" handler is never executed. Other browsers trigger both events so it's not a problem for them.
The obvious solution/hack (to me at least) is to attach a dblclick handler in IE that triggers my click handler twice. Another idea is to track clicks myself with mousedown/mouseup, which seems pretty primitive and probably belongs in a framework rather than my application.
So, what's the best/usual/right way of handling this? (pure Javascript or jQuery preferred)
Depending on your situation you can use different approaches, but I would suggest using namespaced event handlers with jQuery like this:
function eventHandler(event) {
// your handler code here
doSomeMagic();
}
var element = $('#element');
element.one('click.someNameSpace', function(event){
// first we unbind all other event handlers with this namespace
element.unbind('.someNameSpace');
// then we execute our eventHandler
eventHandler();
}).one('dblclick.someNameSpace', function(event){
// If this fires first, we also unbind all event handlers
element.unbind('.someNameSpace');
// and then execute our eventHandler
eventHandler();
});
I'm not sure this will work the way you want it, but it's a start, I guess.
Mousedown and mouseup works just like the click functions, unfortunately so much that when IE omits a click because of a doubleclick it will also omit the mousedown and mouseup. In any case, you can add both click and dblclick to the same object and feed the clicks through a function that sort out any click happening too close to the last.
<div onclick="clk()" ondblclick="clk()"></div>
lastclicktime=0
function clk(){
var time=new Date().getTime()
if(time>lastclicktime+50){
lastclicktime=time
//Handle click
}
}
I by the way just found out that, at least in Firefox the dblclick event is not given an event time, therefore I had to resolve to the Date method.

jQuery live('click') firing for right-click

I've noticed a strange behaviour of the live() function in jQuery:
normal
live
$('#normal').click(clickHandler);
$('#live').live('click', clickHandler);
function clickHandler() {
alert("Clicked");
return false;
}
That's fine and dandy until you right-click on the "live" link and it fires the handler, and then doesn't show the context menu. The event handler doesn't fire at all (as expected) on the "normal" link.
I've been able to work around it by changing the handler to this:
function clickHandler(e) {
if (e.button != 0) return true;
// normal handler code here
return false;
}
But that's really annoying to have to add that to all the event handlers. Is there any better way to have the event handlers only fire like regular click handlers?
It's a known issue:
It seems like Firefox does not fire a
click event for the element on a
right-click, although it fires a
mousedown and mouseup. However, it
does fire a click event on document! Since .live catches
events at the document level, it sees
the click event for the element even
though the element itself does not. If
you use an event like mouseup, both
the p element and the document
will see the event.
Your workaround is the best you can do for now. It appears to only affect Firefox (I believe it's actually a bug in Firefox, not jQuery per se).
See also this question asked yesterday.
I've found a solution - "fix" the the live() code itself.
In the unminified source of jQuery 1.3.2 around line 2989 there is a function called liveHandler(). Modify the code to add one line:
2989: function liveHandler(event) {
2990: if (event.type == 'click' && event.button != 0) return true;
This will stop the click events from firing on anything but the left-mouse button. If you particularly wanted, you could quite easy modify the code to allow for "rightclick" events too, but this works for me so it's staying at that.
You can actually rewrite it as:
function reattachEvents(){
$(element).unbind('click').click(function(){
//do something
});
}
and call it when you add a new dom element, it should have the expected result (no firing on the right click event).
This is an unfortunate consequence of how live is implemented. It's actually uses event bubbling so you're not binding to the anchor element's click event, you're binding to the document's click event.
I solved this by using mousedown events. In my situation the distinction between mousedown and click didn't matter.

Categories

Resources