How to use event capturing concept in jQuery this._on(); - javascript

I am using jQuery this._on() function for binding mouse event and I would like to use event capturing concept in this._on().
this._on($("#myId"), "mousedown", callMouseDown);
callMouseDown: function (e) {
//Mouse down event
},
Anyone can help me, here how to apply event capturing concept (parent to child).
Thanks,
Bharathi.

Use this to access your method.
this._on($("#myId"), "mousedown", this.callMouseDown);
callMouseDown: function (e) {
//Mouse down event
},
UPDATE:
jQuery events does not support event capturing. But it supports event bubbling.
Please check the following link for more information
Why does jQuery event model does not support event Capture and just supports event bubbling

Related

Manually click a child link (and navigate) when clicking parent [duplicate]

Recently I found jQuery cannot trigger the native click event on an anchor tag when I'm clicking on other elements, the example below won't work:
html
<a class="js-a1" href="new.html" target="_blank">this is a link</a>
<a class="js-a2" href="another.html" target="_blank">this is another link</a>
javascript
$('.js-a1').click(function () {
$('.js-a2').click();
return false;
});
And here is the jsfiddle - 1. Click on the first link won't trigger native click on the second one.
After some searches, I found a solution and an explanation.
Solution
Use the native DOM element.
$('.js-a1').click(function () {
$('.js-a2').get(0).click();
return false;
});
And here is the jsfiddle - 2.
Explanation
I found a post on Learn jQuery: Triggering Event Handlers. It told me:
The .trigger() function cannot be used to mimic native browser events, such as clicking on a file input box or an anchor tag. This is because, there is no event handler attached using jQuery's event system that corresponds to these events.
Question
So here comes my question:
How to understand 'there is no event handler attached using jQuery's event system that corresponds to these events'?
Why is there not such corresponding event handler?
EDIT
I update my jsfiddles, it seems there's and error on the class name.
there is no event handler attached using jQuery's event system that corresponds to these events
This means, at this point of the learning material, no jQuery event handlers has been attached to these elements using .click(function() {} or .bind('click', function () {}), etc.
The no-argument .click() is used to trigger (.trigger('click')) a "click" event from jQuery's perspective, which will execute all "click" event handlers registered by jQuery using .click, .bind, .on, etc. This pseudo event won't be sent to the browser.
.trigger()
Execute all handlers and behaviors attached to the matched elements for the given event type.
Check the updated jsFiddle example, click on the two links to see the difference. Hope it helps.
First of all you need to prevent the default behaviour of link
$('.js-a1').click(function (e) {
e.preventDefault();
$('.js-a2').get(0).click();
return false;
});
And to trigger the click event you can also use .trigger('click') better way
And the event handler is used like this:
$(document).on('click', '.js-a1',function(){//code in here});
// here now .js-a1 is event handler
i think you forgot to read documentation.
Document says :
// Triggering a native browser event using the simulate plugin
$( ".js-a2" ).simulate( "click" );
Old question, but here's a nifty and simple solution:
You can basically "register" a native JS event with jQuery by assigning the DOM element's onEvent handler to be the native event. Ideally, we would check first to ensure the onEvent handler has not already been set.
For example, 'register' the native JS click event so it will be triggered by jQuery:
$('.js-a1').click(function (e) {
$('.js-a2').click();
e.preventDefault();
});
var trigger_element = $('.js-a2')[0]; // native DOM element
if (!trigger_element.onclick) {
trigger_element.onclick = trigger_element.click;
}
Here is a fiddle: http://jsfiddle.net/f9vkd/162/
You have to use $("selector").trigger('click')

Event reverse order

I wonder how do I change the order of events.
Because I have to check when I took a focusOut with a click, if the click was inside the parent div, I can not let it happen the focusOut.
The problem, which is called first event focusOut the click event.
Is it possible to reverse the order of events? (Click - focusOut)?
http://jsfiddle.net/eL19p27L/5/
$(document).ready(function(){
$(".clean").click(function(){
$(".alert").html("");
});
$(document).on({
click: function(e){
$(".alert").append("<p>click</p>");
},
focusin: function(e){
$(".alert").append("<p>focusin</p>");
},
focusout: function(e){
$(".alert").append("<p>focusout</p>");
}
})
});
It would be even better. If I could detect what the event might turn out to generate the fucusout. Hence check if it happened within the parent div, if not a focusIn, it leaves not give a focusOut.
ATT
No, the way you have your event handler set up on a common parent, you can't change the order of the events.
But, you can attach your event handlers to the specific objects you want to watch and then you can see events for that object only.
Or, you can look at the target of the event and see which object is which and you will see that the focusOut event is on a different object than the click event.
You can see the source of the event with e.target.
Example of looking at the object that is the source of the event: http://jsfiddle.net/jfriend00/u5tLhes7/

ReactJS SyntheticEvent stopPropagation() only works with React events?

I'm trying to use event.stopPropagation() within a ReactJS component to stop a click event from bubbling up and triggering a click event that was attached with JQuery in legacy code, but it seems like React's stopPropagation() only stops propagation to events also attached in React, and JQuery's stopPropagation() doesn't stop propagation to events attached with React.
Is there any way to make stopPropagation() work across these events? I wrote a simple JSFiddle to demonstrate these behaviors:
/** #jsx React.DOM */
var Propagation = React.createClass({
alert: function(){
alert('React Alert');
},
stopPropagation: function(e){
e.stopPropagation();
},
render: function(){
return (
<div>
<div onClick={this.alert}>
<a href="#" onClick={this.stopPropagation}>React Stop Propagation on React Event</a>
</div>
<div className="alert">
<a href="#" onClick={this.stopPropagation}>React Stop Propagation on JQuery Event</a>
</div>
<div onClick={this.alert}>
JQuery Stop Propagation on React Event
</div>
<div className="alert">
JQuery Stop Propagation on JQuery Event
</div>
</div>
);
}
});
React.renderComponent(<Propagation />, document.body);
$(function(){
$(document).on('click', '.alert', function(e){
alert('Jquery Alert');
});
$(document).on('click', '.stop-propagation', function(e){
e.stopPropagation();
});
});
React uses event delegation with a single event listener on document for events that bubble, like 'click' in this example, which means stopping propagation is not possible; the real event has already propagated by the time you interact with it in React. stopPropagation on React's synthetic event is possible because React handles propagation of synthetic events internally.
Working JSFiddle with the fixes from below.
React Stop Propagation on jQuery Event
Use Event.stopImmediatePropagation to prevent your other (jQuery in this case) listeners on the root from being called. It is supported in IE9+ and modern browsers.
stopPropagation: function(e){
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
},
Caveat: Listeners are called in the order in which they are bound. React must be initialized before other code (jQuery here) for this to work.
jQuery Stop Propagation on React Event
Your jQuery code uses event delegation as well, which means calling stopPropagation in the handler is not stopping anything; the event has already propagated to document, and React's listener will be triggered.
// Listener bound to `document`, event delegation
$(document).on('click', '.stop-propagation', function(e){
e.stopPropagation();
});
To prevent propagation beyond the element, the listener must be bound to the element itself:
// Listener bound to `.stop-propagation`, no delegation
$('.stop-propagation').on('click', function(e){
e.stopPropagation();
});
Edit (2016/01/14): Clarified that delegation is necessarily only used for events that bubble. For more details on event handling, React's source has descriptive comments: ReactBrowserEventEmitter.js.
It is still one intersting moment:
ev.preventDefault()
ev.stopPropagation();
ev.nativeEvent.stopImmediatePropagation();
Use this construction, if your function is wrapped by tag
Worth noting (from this issue) that if you're attaching events to document, e.stopPropagation() isn't going to help. As a workaround, you can use window.addEventListener() instead of document.addEventListener, then event.stopPropagation() will stop event from propagating to the window.
From the React documentation:
The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture. (emphasis added)
If you have a click event listener in your React code and you don't want it to bubble up, I think what you want to do is use onClickCapture instead of onClick. Then you would pass the event to the handler and do event.nativeEvent.stopPropagation() to keep the native event from bubbling up to a vanilla JS event listener (or anything that's not react).
I was able to resolve this by adding the following to my component:
componentDidMount() {
ReactDOM.findDOMNode(this).addEventListener('click', (event) => {
event.stopPropagation();
}, false);
}
React 17 delegates events to root instead of document, which might solve the problem.
More details here.
You can also refer to my blog.
I ran into this problem yesterday, so I created a React-friendly solution.
Check out react-native-listener. It's working very well so far. Feedback appreciated.
A quick workaround is using window.addEventListener instead of document.addEventListener.
Update: You can now <Elem onClick={ proxy => proxy.stopPropagation() } />
The way i've solved this is by adding an if statement at the callback that check the event.target and if its diferent to the element i expect, then return from the function
// Callback from my own app
function exitResultsScreen(event){
// Check element by ID
if (event.target.className !== sass.div__search_screen){return}
// Executed only when the right elements calls
setShowResults(false)
}
In my case e.stopPropagation() didn't work because child had onChange event, parent onClick. Got insight from another StackOverflow answer
The change and click events are different events.
Meagning:
e.stopPropagation() calling inside onChange won't prevent firing onClick.
Solution to have both onChange or onClick.

Keydown event not being picked up by event handler

I am trying to figure out why the following doesn't work.
I am setting a keydown event handler, and then triggering the event. But the handler doesn't detect it.
If anyone can enlighten me!
function onKeyDown(event)
{
alert('keydown');
}
document.addEventListener('keydown', onKeyDown, false);
var keydown = jQuery.Event('keydown', {which:38, keyCode:38});
$(document).keydown();
$(document).trigger(keydown);
jsfiddle: http://jsfiddle.net/4bf3z/
From http://api.jquery.com/trigger/, emphasis added:
Any event handlers attached with .on() or one of its shortcut methods
are triggered when the corresponding event occurs. They can be fired
manually, however, with the .trigger() method. A call to .trigger()
executes the handlers in the same order they would be if the event
were triggered naturally by the user.
So, it works as expected if you attach the handler with jQuery instead of pure javascript:
function onKeyDown(event)
{
alert('keydown');
}
$(document).on('keydown', onKeyDown); // <----
var keydown = jQuery.Event('keydown', {which:38, keyCode:38});
$(document).keydown();
$(document).trigger(keydown);
jQuery’s trigger only triggers jQuery-attached events. Triggering actual DOM events is trickier, and the keyboard events module is still a working draft:
var e = document.createEvent('KeyboardEvents');
e.initKeyboardEvent('keydown');
document.dispatchEvent(e);
The arguments to initKeyboardEvent are on MSDN. Firefox uses initKeyEvent.
Updated jsFiddle

Direct vs delegation and bubbling vs capturing in jQuery

HTML
<div>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
jQuery
$('div span').on('click', function(){
//direct - 1st method
});
$('div').on('click','span', function(){
//delegation - 2nd method
});
I have used both above method in my code. I know second method is better due to it has only got single handler. My problems are:
Is first method (direct) refers to the concept called event capturing? Is it an example for event capturing?
Is second method (delegation) refers to the concept called event bubbling? Is it an example for event bubbling?
It appears as though All jQuery event methods use Event Bubbling, not Event Capturing.
Therefore, both of your examples will use Event Bubbling.
There is an edge case with focus and blur events not bubbling in some browsers. In the affected browsers, Event Capturing is used for focus and blur events.
For reference, you can simply view the source. http://code.jquery.com/jquery.js
$('div span').on('click', function(){
//direct - 1st method
});
This event only attached the event handler to the spans inside Div that are currently present in the DOM.. i.e; if a new span element is added to the div , that span will not have a click event associated with it..
The first and second one are example's of Event Bubbling
There comes the concept of Event delegation where in the ancestor is given the event handler and it is delegated to the children..
The second example is an example of event delegation .
Wherein event is attached to the parent element..So all the span element's inside the div class are attached to the event handler ..
So if a new span element is added to the div , becoz the event is associated with the span's ancestor the event will fire in this case
This helps in cases
$('div').on('click','span', function(){
//delegation - 2nd method
});
I have no idea where event capturing is used in the jQuery library
Answers to your questions:
This isn't bubbling, capturing, or delegating. It's just adding an event listener directly to an element.
Yep, this is delegation that under the hood relies on clicks bubbling up.
Event bubbling and capturing are different implementations of the same concept, brought to you by Microsoft and Netscape, respectively. Both listening for events on parent elements. Note that they occur in a different order: capturing happens from the parent down to descendent, whereas bubbling happens the other way around.
More details and its history on PPK's website: http://www.quirksmode.org/js/events_order.html
Modern browsers support both capture and bubbling (bubbling is the default now), and you can specify which one you want to use when you use the native addEventListener:
element.addEventListener('click', function(){}, false); // bubble
element.addEventListener('click', function(){}, true); // capture
However, some events, such as focus, blur, scroll, mouseover, etc only are supported through capture phase events, so you MUST specify "true" when you use addEventListener.
Unfortunately, it looks like jQuery doesn't support delegation for all capture phase events, only focus and blur (see https://github.com/jquery/jquery/blob/ad032d3c7df04827989a4187117614c29bf3a4ad/src/event.js#L728).
The short answer: for delegation of capture-phase events other than focus and blur, you need to use the native addEventListener, not jQuery.

Categories