How to continue event propagation after cancelling?
Below are the bits from the code that actually worked in Chrome 13, to my surprise.
function handler (evt ) { var t = evt.target; ... setTimeout( function() { t.dispatchEvent( evt ) }, 1000); return false;}
This is not very cross-browser, and maybe will be fixed in future, because it feels like security risk, imho.
And i don't know what happens, if you cancel event propagation.
It could be risky but seems to work at the time of writing at least, we're using it in production.
This is ES6 and React, I have tested and found it working for the below browsers. One bonus is if there is an exception (had a couple during the way making this), it goes to the link like a normal <a>
link, but it won't be SPA then ofc.
Desktop:
- Chrome v.76.0.3809.132
- Safari v.12.1.2
- Firefox Quantum v.69.0.1
- Edge 18
- Edge 17
- IE11
Mobile/Tablet:
- Android v.8 Samsung Internet
- Android v.8 Chrome
- Android v.9 Chrome
- iOs11.4 Safari
- iOs12.1 Safari
.
import 'mdn-polyfills/MouseEvent'; // for IE11import React, { Component } from 'react';import { Link } from 'react-router-dom';class ProductListLink extends Component { constructor(props) { super(props); this.realClick = true; this.onProductClick = this.onProductClick.bind(this); } onProductClick = (e) => { const { target, nativeEvent } = e; const clonedNativeEvent = new MouseEvent('click', nativeEvent); if (!this.realClick) { this.realClick = true; return; } e.preventDefault(); e.stopPropagation(); // @todo what you want before the link is acted on here this.realClick = false; target.dispatchEvent(clonedNativeEvent); }; render() { <Link onClick={(e => this.onProductClick(e))} > Lorem </Link> }}
I solved problem by this way on one of my projects. This example works with some basic event handling like clicks etc. Handler for confirmation must be first handler bound.
// This example assumes clickFunction is first event handled. // // you have to preserve called function handler to ignore it // when you continue calling. // // store it in object to preserve function reference var ignoredHandler = { fn: false }; // function which will continues processing var go = function(e, el){ // process href var href = $(el).attr('href'); if (href) { window.location = href; } // process events var events = $(el).data('events'); for (prop in events) { if (events.hasOwnProperty(prop)) { var event = events[prop]; $.each(event, function(idx, handler){ // do not run for clickFunction if (ignoredHandler.fn != handler.handler) { handler.handler.call(el, e); } }); } } } // click handler var clickFunction = function(e){ e.preventDefault(); e.stopImmediatePropagation(); MyApp.confirm("Are you sure you want to navigate away?") .done(go.apply(this, e)); }; // preserve ignored handler ignoredHandler.fn = clickFunction; $('.confirmable').click(clickFunction); // a little bit longer but it works :)