当前我们可以通过浏览器自带的alert,prompt弹框来提示用户或取得用户输入信息。
此二种方式具有的缺陷:
1. 阻塞:即JS执行至alert, prompt方法时待用户操作后再进行下一个语句的执行。即同步操作
2. 样式单一: 针对同一种浏览器,其弹框样式固定,不够美观。
下面我们通过自定义一个弹框库(js),来解决上面二个问题。
目标:
1. 用户只需使用定义好的js库即可使用弹框。
2. 弹框具有“确定”或“取消”功能,并可回调用户注册的函数(即单击确定或取消后回调的函数)
3. 用户如果想修改样式可自定义css
思路:
1. 弹框以普通html元素来实现, 弹框具有背景(overlay)以遮盖其余部分,防止用户操作弹框以外的页面部分。
2. 框体部分由头部,体部,尾部三大部分。头部展示title, 体部承载提示信息,尾部定义按钮。其中头部与尾部为可选部分
3. 不论用户单击确定还是取消按钮,弹框都要消失。(当用户注册的“确定”按钮回调函数如果返回false,则不关闭弹框)
4. 用户可设置title,body,以及确定按钮的文字,取消按钮的文字。当title为空时,无header部分,确定与取消按钮哪一个定义了文字就显示哪一个按钮。
下面是参考实现代码:
/**
* window alert, prompt, and so on
* @author DavidWang
* @date 2015-11-13 11:14:30
* */
;(function($){
'use strict';
/**
* 对话框
*/
function Dialog(title){
if(!(this instanceof Dialog)) return new Dialog(title);
this.title = title;
this.dones = [];
this.fails = [];
this.alwayses = [];
return this;
}
Dialog.prototype.title = function(title){
this.title = title;
return this;
};
Dialog.prototype.sureBtn = function(txt1){
this.btn1 = txt1;
return this;
};
Dialog.prototype.cancelBtn = function(txt2){
this.btn2 = txt2;
return this;
};
/**
* body有可能是字符串,也有可能是doc element,或者是jQuery包装过的元素
* @param body
* @returns {Dialog}
*/
Dialog.prototype.body = function(body){
this.body = body;
return this;
};
/**positive button*/
Dialog.prototype.done = function(func){
this.dones.push(func);
return this;
};
/**negative button*/
Dialog.prototype.fail = function(func){
this.fails.push(func);
return this;
};
/**always*/
Dialog.prototype.always = function(func){
this.alwayses.push(func);
return this;
};
/**build the dialog*/
Dialog.prototype.build = function(){
var overlay = $('<div>').addClass('dialog-overlay');
var win = $('<div>').addClass('dialog-window');
overlay.append(win);
var me = this;
//title
this.title && ((function(){
var header = $('<div>').addClass('dialog-header');
if(me.title.jquery){
header.append(me.title);
}else{
header.append($('<h3>',{text: me.title}));
}
win.append(header);
})());
//body
var body = $('<div>').addClass('dialog-body');
body.append(this.body.jquery ? this.body : $('<p>',{text: this.body}));
win.append(body);
//footer
(this.btn1 || this.btn2) && (function(){
var footer = $('<div>').addClass('dialog-footer');
me.btn1 && footer.append($('<a>',{text: me.btn1,href:'javascript:void(0)'}).addClass('dialog-btn').click(function(evt){
me.dones.some(function(fn){
return fn.call(me) === false;
}) || me._always();
}))
me.btn2 && footer.append($('<a>',{text: me.btn2,href:'javascript:void(0)'}).addClass('dialog-btn').click(function(evt){
me.fails.some(function(fn){
return fn.call(me) === false;
}) || me._always();
}))
win.append(footer);
}());
overlay.appendTo(document.body);
this.overlay = overlay;
this.alwayses.push(function(){
overlay.remove();
});
return this;
};
Dialog.prototype._always = function(){
var me = this;
this.alwayses.forEach(function(fn){
fn.call(me);
});
return this;
};
Dialog.prototype.go = function(){
this.overlay.remove();
return this;
};
Dialog.alert = function(msg,cb){
return Dialog().body(msg).sureBtn('确定').done(cb || $.noop).build();
}
window.Dialog = Dialog;
})(window.jQuery);
可以看到上面代码中也定义了一个alert方法,是为了单纯弹一个没有header和footer的框,可通过调用go方法移除弹框。
使用方法可参考下述代码 :
Dialog().title('My Title').body('Really?')
.sureBtn('Yes').cancelBtn('No')
.done(function(){
//单击了Yes
})
.fail(function(){
//单击了No
})
.always(function(){
//弹框关闭,即总会回调的方法
});
其中的body除了像上面直接写字符串,也可以传入jQuery生成的元素对象,如$('<div>',{text: 'Body'})等
此弹框的样式可参考以下代码
@CHARSET "UTF-8";
/**edit by davidwang 2015-11-13 11:37:30 自定义弹框 使用方法参见dialog.js**/
.dialog-overlay{
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
}
.dialog-window{
position:absolute;
font-family: "Microsoft Yahei",sans-serif;
top:100px;
left:50%;
width:300px;
margin-left: -150px;
color:#333;
border: 1px solid #768995;
border-radius: 3px 3px 0 0;
}
.dialog-header{
background-color:#829aa8;
color:#fff;
padding:10px;
}
.dialog-header h3{
font: 14px bold "Microsoft Yahei",sans-serif;
}
.dialog-body{
background-color:#fff;
padding:15px;
font-size:12px;
border-bottom: 1px solid #d8dee2;
text-align:center;
}
.dialog-footer{
background-color:#fff;
padding:5px;
text-align:center;
}
.dialog-footer a.dialog-btn{
margin: 0 10px 0 10px;
cursor:pointer;
text-decoration: none;
font-weight: bold;
}