當前我們可以通過瀏覽器自帶的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;
}