Behaviour of event.stopPropagation(); in different browser - javascript

I want to use event.stopPropagation(); method of jquery to stop bubbling of events.
But i am not sure if it works for all browsers as it is. Can any one please help in making it work for all browsers
eg :Ie(7,8,9,10),firefox,chrome.

event.stopPropagation() is normalized across browsers, so it should work on all platforms and all browsers. As a general practice event.stopPropagation is used in combination with event.preventDefault and these two actions are equal with return false statement.
function() {
return false;
}
// IS EQUAL TO
function(e) {
e.preventDefault();
e.stopPropagation();
}

event.stopPropagation(); is a intelligent function, once you have included JQuery library which uses pure JavaScript , handles every browser.

Related

Overwriting tap event with preventDefault

I had a lot of:
$('#element').on('tap', function(){
// some code ..
})
I searched many questions about the tap event problem firing twice, and I solved my problem using e.preventDefault(), now I have a lot of:
$('#element').on('tap', function(e){
e.preventDefault();
// some code ..
})
Ok, but as I said, I have many of these calls and I don't like much to write every time e.preventDefault(), then I typed $.fn.tap on chrome's console and it showed me:
function (a){return a?this.bind(c,a):this.trigger(c)}
I tried to overwrite it this way:
$.fn.tap = function (a) {
a.preventDefault();
return a?this.bind(c,a):this.trigger(c)
}
But it didn't worked as it did in the previous e.preventDefault().
I'm not seeing anything obvious and I'm out of ideas for this.
Any help or idea is appreciated. Thanks in advance.
This is how you can create your $.fn.tap:-
$.fn.tap = function(f) {
$(this).on('tap', function(e) {
e.preventDefault();
f();
});
return this;
};
//usage
$('.selector').tap(function() {
alert('foo bar')
})
#Washington Guedes - overwrite the default tap-event to always use e.preventDefault()
rather than changing from $(element).on('tap', function(){}) to
$(element).tap(function(){})
You could add a delegate event to body for tap, without specifying a target. This will then fire for all tap events on the body, which you can then check if the target has its own tap event, so you can then e.preventDefault();.
NOTE: This will not work for delegated tap events as shown.
// global tap handler
$('body').on('tap', function(e) {
if ($._data(e.target, "events").tap)
e.preventDefault();
});
// tap event
$('a.tap').on('tap', function(e) {
$(this).css('color', 'red');
});
// delegated tap event
$('body').on('tap', 'a.delegate', function(e) {
$(this).css('color', 'green');
});
a {
display: block;
margin: 20px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js"></script>
<a class="tap" href="www.google.co.uk">tap event, prevented.</a>
<a class="delegate" href="www.google.co.uk">delegate tap event, not prevented.</a>
no tap event, not prevented
One of the cool features of jQuery (I usually don't use 'jQuery' and 'cool' in a single sentence) is that it lets you specify custom behaviour for events, using the $.event.special object.
There is very little documentation on the subject, so a little example would be in order.
A working fiddle using the click event (as this was more convenient for me to write on my laptop) can be found here
Translated to your request to have all tap events have e.preventDefault() invoked before the actual handler, would look like:
$.event.special.tap.add = function(options) {
var handler = options.handler;
options.handler = function(e) {
e.preventDefault();
return handler.apply(this, arguments);
}
}
What this code does (should do, as I haven't actually tested the tap version above) is telling jQuery that you want a special treatment for the tab event, more particularly you want to provide a 'wrapping handler' which does nothing more than call e.preventDefault() before calling the provided event handler.
UPDATE: prevented the default tap-settings from being overwritten, for future visitors
NOTE: Before you make any attempt on changing the default behaviour of things, you should ask yourself why the defaults don't work for you. Mostly because changing default (=expected) behaviour will upset your future self (or worse, another person) while maintaining your code and adding features.
In order to create a maintainable (and predictable) flow in your code the suggested solution to create a special case function ($.fn.tap) is in fact a very viable solution, as it does not interfere with the default (=expected) behaviour of things.
From the links I provided you should also be able to create your own event type (e.g. tapOnly) and make it more obvious there is some custom work involved. Then again, both of these solutions will require you to change your event bindings, which is what you are trying to prevent.
I knew can be a bad idea but I've just tested this in Chrome
$('*').on('tap',function(e){
e.preventDefault();
});
$('#element').on('tap', function(){
// some code ..
});
and if you don't need this for all elements:
$('*').not('#aCertainElement').on('tap',function(e){
e.preventDefault();
});
I had a similar problem, in which e.preventDefault() would work on some cases, but not on others. It showed no errors, and using try-catch was not displaying the catch alert. Adding e.stopImmediatePropagation() did the trick, in case it helps anyone

What causes preventDefault to let the original event through

I don't have an example at hand, but in some situations calling event.preventDefault() lets the original event through (navigating to page, submitting form etc) but returning false helps. What could cause this?
You don't have an example to hand? OK, let me invent one that may or may not be whatever it was you were thinking of.
Remember that return false; is the equivalent of calling both event.preventDefault(); and event.stopPropagation(). EDIT: This applies with jQuery, which explictly implements this behaviour and also normalises event.preventDefault() and event.stopPropagation() for use in all browsers. It doesn't work that way in all browsers with "plain" JS, in fact older IE versions don't support event.preventDefault() at all, they have their own equivalent event.returnValue = false;
If you have nested elements and you handle the same event in several levels then calling event.preventDefault() will not stop the outer elements' event handlers from running, but return false will because it stops propagation of the event.
An example that demonstrates it: http://jsfiddle.net/nnnnnn/KjLv3/
<span>Click me to see an alert</span>
// using jQuery for simplicity in the example:
$("a span").click(function(e){
e.preventDefault();
});
$("a").click(function() {
alert("Hello");
});
The alert will display. If you change the "a span" handler to return false the alert will not display.
event.preventDefault() prevents the browser from performing the default action ( if the event is cancelable ) without stopping further propagation of the event, whereas
return false prevents the event from propagating (or "bubbling up") the DOM, along with preventing the default action.
So,
function() {
return false;
}
// IS EQUAL TO
function(e) {
e.preventDefault();
e.stopPropagation();
}

Does JavaScript 'return false' works just inline together with HTML?

I know that JavaScript return false means prevent default event (like preventDefault() method).
#1
click
#2
<a id="a" href="http://stackoverflow.com">click</a>
<script>
document.getElementById('a').addEventListener('click', function(){ return false; }, false);
</script>
I wonder why just #1 prevent default event but not #2. Did I make some mistake?
Edit:
Sorry, I missed an id of anchor tag and third argument of code in #2. I added it but it's still not working.
There are two problems with your second example:
You're using document.getElementById but you're giving a tagname. You can probably use document.getElementsByTagName (which returns a NodeList you would then index into), or give the element an id attribute and use getElementById to look it up.
Your addEventListener call is missing the third argument, which is required. So:
document.getElementById('someId').addEventListener(
'click',
function(){ return false; },
false // <=== Third argument, you almost certainly want `false`
);
Regarding your question about return false: If you're using a browser that supports addEventListener and you're hooking up event handlers with it, no, you don't use return false to prevent the default action. Instead, you use event#preventDefault. (You can also use event#stopPropagation to stop the event bubbling, but DOM0's return false doesn't do that, so that's just an extra bonus.)
document.getElementById('someId').addEventListener(
'click',
function(e){
// Prevent the default action of the link
e.preventDefault();
// Stop the event propagating (bubbling) to the parent element
e.stopPropagation();
},
false
);
Also note that there are a lot of people using IE8 and earlier, which do not support addEventListener (instead, they support Microsoft's original attachEvent; but not all versions support preventDefault or stopPropagation).
Somewhat off-topic: As you can see, handling events in a cross-browser way is a hassle. It's one of the many hassles you can avoid by using a decent JavaScript library like jQuery, Prototype, YUI, Closure, or any of several others. They smooth over browser differences and provide lots of helpful utility functionality, so you can focus on what you're actually trying to build (rather than worrying about how IE7 and earlier have a broken version of getElementById).
Examples:
jQuery: jQuery provides a return false feature (although it's different from the DOM0 one you're talking about), and it also ensures that event#preventDefault and event#stopPropagation work regardless of how the underlying browser handles events. So either of these work with jQuery:
// Using return false (which prevents the default AND -- unlike DOM0 stuff -- stops propagation)
$('#someId').click(function() { return false; });
// Using the DOM standard event methods -- even on browsers that don't support them
$('#someId').click(function(e) {
e.preventDefault();
e.stopPropagation();
});
Prototype: Prototype provides the DOM standard event methods (even on browsers that don't support them) as well as event#stop which is just a combination of preventing the default and stopping propagation:
// Using `stop` (which prevents the default and stops propagation)
$('someId').observe('click', function(e) { e.stop(); });
// Using the DOM standard event methods -- even on browsers that don't support them
$('someId').observe('click', function(e) {
e.preventDefault();
e.stopPropagation();
});
Other libraries will offer similar functionality.
This will not work w/o a proper id (not tag name)
document.getElementById('a')
Try
<a id="example" href="http://stackoverflow.com">click</a>
...
document.getElementById('example')...
If you use getElementById(), you need an id on the element. As the name suggests, this function will find an element by searching for the id.
<a id="a" href="http://stackoverflow.com">click</a>
<script>
document.getElementById('a').addEventListener('click', function(){ return false; });
</script>
If you want to find it by tag name, you can use getElementsByTagName(). It will return an array (actually a NodeList) of those tags.
Using:
var x=document.getElementsByTagName('a')[0];
x will store a reference to the first link (a element) on the page.
you can't get the anchor-tag with document.getElementById(), because it is a TagName and not an Id.
Maybe u have to add "javascript:" before the "return false". Like so:
click
I hope that helps.

JavaScript suppress double click selection

i'm working on a slide gallery at the moment.
My problem is that when i click the navigation divs very fast, the browsers default behavior is fired (selection of content).
My question is: how can I suppress the default double click behavior?
navigationDiv.onclick = function () {
// do something
};
A jQuery solution would also be suitable since i'm using it.
Thanks in advance!
$("yourselector").dblclick(function(){
return false;
});
You can also use event.preventDefault()
$("yourselector").dblclick(function(event){
event.preventDefault();
});
Just FYI, in Firefox and Safari/Chrome, selection can be disabled through CSS, too:
.navigationDiv {
-moz-user-select: none;
-webkit-user-select: none;
}
I think this is more simple when your purpose is only to prevent selections from taking place on a certain element.
You could try disabling the onselectstart event of the target element.
navigationDiv.onselectstart=function(){return false}
Not sure if this is x-browser compatible. (I'll check it)
Edit
Turns out that this is a IE-only event. To accomplish the same in Mozilla, you would have to disable the -moz-user-select CSS style. In JavaScript that would be:
navigationDiv.style.MozUserSelect="none"
To be honest, I think you would be better off disabling the double-click event, as described in the other comments here.
Putting a return false; at the end of the event handler should be able to suppress the default selection behaviour.
Calling event.preventDefault() in dblclick handler will help only if it is called in the element BEING CLICKED, not in the parent's event handler.
In scenarios when there's a container with multiple children, default behaviour of double click will happen in a child and bubbled up to it's parent. In this case there're 2 options:
Clear selection in parent's event handler, e.g.:
window.getSelection().empty(). The issue with this approach is that you'll notice blinking of the selected text and in Opera there'll be a pop-up ('Copy', 'Search').
Traverse all children and call e.PreventDefault() in their dblclick.
You could try making the "dblclick" event return false?
$('.someStuff').bind('dblclick', function() { return false; });
Cancel the ondblclick event:
navigationDiv.ondblclick = function () {
return false; // cancel default
};
http://www.quirksmode.org/js/events_mouse.html
Quite Simple:
navigationDiv.ondblclick = function (event) {
// do something
if (!event) event = window.event;
if (event.preventDefault)
event.preventDefault();
else
event.returnValue = false;
};
This works on IE and Mozilla browsers.
Neither e.preventDefault() nor return false ensure in all cases, that double-click's default action (text selection) will not happen. But, having read this note and this answer I've composed a working solution for a similar problem of my own:
$(...your selector...)
.on('mousedown',function(e){ if (e.detail>1) return false }) // prevent dblclick default
.on('dblclick', ...your dblclick handler...);

keydown EventListener in IE7

I've written this code inside the HEAD tags of my HTML page. It works fine in Firefox, Chrome and Safari, but doesn't in IE7. I would like to know how to fix it.
<script type="text/javascript">
if ( window.addEventListener ) {
window.addEventListener("keydown", function(e) {
alert(e.keyCode);
}, true);
}
</script>
Microsoft has implemented their own way of doing this called attachEvent. You can read more about this over at quirksmode.org: http://www.quirksmode.org/js/events_advanced.html
You're screwed: you're using event capturing (passing true as the last parameter to addEventListener). IE has no such equivalent, in any version, including IE8 in IE8 mode.
Is there a reason you must use event capturing rather that event bubbling here? IOW, pass false as your last parameter? Then, you'd be able to port this (somewhat) to use IE's attachEvent proprietary method, or use a library (as others have suggested and added links for).
There is no window.addEventListener in IE, you need to use attachEvent. There's good documentation on events here, or you could switch to using a library that abstracts away browser differences.
Try:
window.attachEvent
More fully:
//set page event handlers
if (window.attachEvent) {
//IE and Opera
window.attachEvent("keydown", "");
} else if (window.addEventListener) {
// IE 6
window.addEventListener("keydown", "");
} else {
//FireFox
document.addEventListener("keydown", "");
}

Categories