当用户点击某个链接时,我想通过确认对话框显示它们。如果他们点击“是”,我想继续原始导航。一个问题:我的确认对话框是通过返回一个jQuery.Deferred对象实现的,该对象仅在用户单击Yes按钮时解析。所以基本上确认对话框是异步的。
基本上我想要这样的东西:
$('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
})
})
当然,我可以设置一个标志并重新触发点击,但这很麻烦。这样做的任何自然方式?
答案 0 :(得分:11)
以下是Chrome 13中实际工作的代码中的一些内容,令我惊讶。
function handler (evt ) {
var t = evt.target;
...
setTimeout( function() {
t.dispatchEvent( evt )
}, 1000);
return false;
}
这不是非常跨浏览器,也许将来会修复,因为它感觉像安全风险,imho。
如果您取消事件传播,我不知道会发生什么。
答案 1 :(得分:3)
我通过这种方式在我的一个项目上解决了问题。此示例适用于某些基本事件处理(如点击等)。用于确认的处理程序必须是第一个处理程序绑定。
// 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 :)
答案 2 :(得分:3)
如果我正确理解了问题,我认为您可以将事件更新为您在那里的闭包中的原始事件。所以只需在.done函数中设置e = e.originalEvent。
https://jsfiddle.net/oyetxu54/
MyApp.confirm("confirmation?")
.done(function(){ e = e.originalEvent;})
这里有一个不同的例子(保持控制台打开,以便您可以看到消息): 这在chrome和firefox中对我有用
答案 3 :(得分:2)
我认为这可能有风险(!),但至少在撰写本文时似乎可行。
这是ES6和React,我已经测试并发现它适用于以下浏览器。一个好处是,如果有异常(在进行此操作的过程中有几个异常),它会像普通的<a>
链接一样进入该链接,但是从那时起它就不会是SPA。
台式机:
手机/平板电脑:
。
import 'mdn-polyfills/MouseEvent'; // for IE11
import 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>
}
}
答案 4 :(得分:0)
我通过以下方式解决了这个问题:
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>
我将事件监听器添加到父级而不是链接本身的原因是因为jQuery的on
事件将绑定到该元素,除非另有说明。因此,即使元素没有类another-page
,它仍然附加了事件监听器,因此您必须利用event delegation
来解决此问题。
GOTCHAS 这是非常基于状态的。即如果您需要询问用户他们每次点击链接,您必须添加第二个听众,以便将another-page
课程重新读回链接。即:
$('body').on('click', function (e) {
$(e.currentTarget).addClass('another-page');
});
旁注如果用户接受,您还可以删除container
上的事件侦听器,如果这样做,请确保使用namespace
事件,因为可能还有其他侦听器在容器上,你可能会无意中删除。有关详细信息,请参阅https://api.jquery.com/event.namespace/。
答案 5 :(得分:0)
我们的项目有类似的要求,这对我有用。在chrome和IE11中测试过。
$('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();
})
}
})
答案 6 :(得分:0)
我编辑了您的代码。我添加的新功能:
代码:
$('a.my-link').on("click.myEvent", function(e) {
var $that = $(this);
$that.off("click.myEvent");
e.preventDefault();
e.stopImmediatePropagation();
MyApp.confirm("Are you sure you want to navigate away?")
.done(function() {
//continue propogation of e
$that.trigger("click");
});
});
答案 7 :(得分:-2)
这是未经测试的,但可能会为您提供解决方法
$('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()
})
})