我的任务是构建一个模态提示,到目前为止,当它归结为 DOM 操作时,描述它的方法(例如“显示”、“隐藏”)很简单。
现在对我来说困难来了......假设我们有一个页面,其中有多个立即调用来在一个页面上构建和显示多个模式
//on page load:
$("browser-deprecated-modal").modal();
$("change-your-city-modal").modal();
$("promotion-modal").modal();
默认情况下,我的模态(以及我尝试过的其他库)一次构造所有这些模态,并以相反的顺序显示它们彼此重叠 - 即 $(promotion-modal) 位于顶部,而 $("browser-deprecated-modal") 将位于所有这些的下方。这不是我想要的,更不用说重叠了。
我需要每个模态仅在前一个模态(如果有)关闭时才显示。因此,首先我们应该看到“browser-deprecated-modal”(下面没有其他模态),关闭它后必须弹出第二个模态,依此类推。
我一直在尝试解决这个问题:
$.fn.modal = function(options) {
return this.each(function() {
if (Modal.running) {
Modal.toInstantiateLater.push({this,options});
} else {
var md = new Modal(this, options);
}
});
}
destroy :function () {
....
if (Modal.toInstantiateLater.length)
new Modal (Modal.toInstantiateLater[0][0],Modal.toInstantiateLater[0][1]);
}
跟踪在数组中构造 Modal 的所有调用,并在“destroy”方法中检查该数组是否为空。 但我认为这似乎很尴尬而且有问题。 我需要一个强大而清晰的解决方案。我一直在考虑 $.Callbacks 或 $.Deferred, 有点设置回调队列
if (Modal.running) { //if one Modal is already running
var cb = $.Callbacks();
cb.add(function(){
new Modal(this, options);
});
} else { //the road is clear
var md = new Modal(this, options);
}
并在 destroy 方法中触发 cb 触发,但我对这个东西很陌生,卡住了并且无法进展,无论它是否正确,或者其他方法更合适。 此外,我读到回调会立即触发所有函数(如果队列中有多个额外的模态),这是不对的,因为我需要一一触发模态创建并一一清除回调队列。
请帮助我解决这个问题。
我的代码jsfiddle
最佳答案
我去掉了计数器变量,因为您可以使用toInstantiateLater
来跟踪您所在的位置,并且只需进行一些更改。尝试一下...
JavaScript
function Modal(el, opts){
this.el = $(el);
this.opts = opts;
this.overlay = $("<div class='overlay' id='overlay"+Modal.counter+"'></div>");
this.wrap = $("<div class='wrap' id='wrap"+Modal.counter+"'></div>");
this.replace = $("<div class='replace' id='replace"+Modal.counter+"'></div>");
this.close = $("<span class='close' id='close"+Modal.counter+"'></span>")
if (Modal.running) {
Modal.toInstantiateLater.push(this);
}
else {
Modal.running = true;
this.show();
}
}
Modal.destroyAll = function() {
Modal.prototype.destroyAll();
};
Modal.prototype = {
show: function() {
var s = this;
s.wrap.append(s.close);
s.el.before(s.replace).appendTo(s.wrap).show();
$('body').append(s.overlay).append(s.wrap);
s.bindEvents();
Modal.currentModal = s;
},
bindEvents: function() {
var s = this;
s.close.on("click.modal",function(e){
s.destroy.call(s,e);
});
},
destroy: function(e) {
var s = this;
s.replace.replaceWith(s.el.hide());
s.wrap.remove();
s.overlay.remove();
if (Modal.toInstantiateLater.length > 0) {
Modal.toInstantiateLater.shift().show();
}
else {
Modal.running = false;
}
},
destroyAll: function(e) {
Modal.toInstantiateLater = [];
Modal.currentModal.destroy();
}
}
Modal.running = false;
Modal.toInstantiateLater = [];
Modal.currentModal = {};
$.fn.modal = function(options) {
return this.each(function() {
var md = new Modal(this, options);
});
}
$("document").ready(function(){
$("#browser-deprecated-modal").modal();
$("#change-your-city-modal").modal();
$("#promotion-modal").modal();
$("#destroy-all").on("click", function() {
Modal.destroyAll();
});
});
jsfiddle 示例
关于javascript - 如何实现 jQuery 模式的对象实例队列,确保每次只有一个实例打开?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26929021/