取消后如何继续事件传播?
当用户点击某个链接时,我想给他们一个确认对话框。 如果他们点击“是”,我想继续原来的导航。 一个catch:我的确认对话框是通过返回一个jQuery.Deferred对象来实现的,只有当用户点击Yesbutton时才parsing。 所以基本上确认对话框是asynchronous的。
所以基本上我想要这样的东西:
$('a.my-link').click(function(e) { e.preventDefault(); e.stopPropogation(); MyApp.confirm("Are you sure you want to navigate away?") .done(function() { //continue propogation of e }) })
当然,我可以设置一个标志,并重新触发点击,但这是混乱的。 任何自然的方式呢?
以下是Chrome 13中实际工作的代码,令我惊讶的是。
function handler (evt ) { var t = evt.target; ... setTimeout( function() { t.dispatchEvent( evt ) }, 1000); return false; }
这是不是很跨浏览器,也许将来会被修复,因为它感觉像安全风险,恕我直言。
如果您取消事件传播,我不知道会发生什么。
如果我正确地理解了这个问题,我认为你可以把事件更新成你在那里closures的原始事件。 所以只需在.done函数中设置e = e.originalEvent。
https://jsfiddle.net/oyetxu54/
MyApp.confirm("confirmation?") .done(function(){ e = e.originalEvent;})
这里是一个不同的例子(保持控制台打开,所以你可以看到消息)的小提琴:这对我在铬和Firefox
我通过这种方式在我的一个项目上解决了问题。 这个例子适用于一些基本的事件处理,比如点击等等。Handler的确认必须是第一个处理程序绑定的。
// 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 :)
我解决了这个问题:
- 将事件监听器放在父元素上
- 只有在用户确认时才从链接中删除课程
- 在我删除课程后重新点击链接。
function async() { var dfd = $.Deferred(); // simulate async setTimeout(function () { if (confirm('Stackoverflow FTW')) { dfd.resolve(); } else { dfd.reject(); } }, 0); return dfd.promise(); }; $('.container').on('click', '.another-page', function (e) { e.stopPropagation(); e.preventDefault(); async().done(function () { $(e.currentTarget).removeClass('another-page').click(); }); }); $('body').on('click', function (e) { alert('navigating somewhere else woot!') });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="container"> <a href="#" class="another-page">Somewhere else</a> </div>
我们在项目中有类似的要求,这对我有用。 在Chrome和IE11testing。
$('a.my-link').click(function(e) { e.preventDefault(); if (do_something === true) { e.stopPropogation(); MyApp.confirm("Are you sure you want to navigate away?") .done(function() { do_something = false; // this allows user to navigate $(e.target).click(); }) } })
这是未经testing,但可能作为您的解决方法
$('a.my-link').click(function(e) { e.preventDefault(); e.stopPropogation(); MyApp.confirm("Are you sure you want to navigate away?") .done(function() { //continue propogation of e $(this).unbind('click').click() }) })