js和css重寫Alert和Confirm提示窗口,支持服務器控件調用。
js自帶的Alert和Confirm窗口樣貌醜陋,且每個瀏覽器的實現方式都不一樣(彈出位置等),而且還不支持自己輸入樣式和自定義返回函數等。
在一次.NET的web開發過程中,爲用戶提供一個刪除功能時,在用戶刪除前彈出提示框,這做起來方法很多。
1. 可以前臺寫個按鈕(input,button)或者連接(a)標籤,又或者隨便一個標籤,然後加個click事件,在click事件中用ajax來調用服務器代碼,進行更新數據。如果你要改的代碼或者新寫的代碼是這樣的,那恭喜你,你造福了你自己和你的後來者。
2. 使用.net自帶的服務器控件來做。如果你是在改代碼,而且時間不允許你重新構建整個表格區域,又或者是你不想改前輩們的勞動成果,那麼你很有可能就直接添加了一個服務器控件,然後添加一個onClientClick事件,直接return confirm(“xxxx”)來簡單實現一個提示窗口。
但是作爲一個很有責任感的開發人員,作爲一個追求完美的開發者,在這前端越來越讓人眼花繚亂的前端開發世界裏,仍舊使用原生的Confirm實在是讓人心裏發麻,很不爽。所以花了點時間研究如何自定義新的彈窗來做替換。多說無益,真槍實彈纔是真,直接上代碼。
前臺HTML文件代碼和調用方法:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>模擬alert和confirm提示框</title>
<script src="../js/jquery-1.12.4.js"></script>
<script src="../js/confirm.js"></script>
</head>
<body>
<input id="add" type="button" value="添加" onclick="AlertDemo()"/>
<input id="update" type="button" value="修改" onclick="ConfirmDemo()" />
<script>
//非服務器控件調用Alert
function AlertDemo(){
PlusAlert("模擬Alert彈窗", "模擬Alert成功!");
}
//非服務器控件調用Confirm
function ConfirmDemo(){
PlusConfirm("模擬Confirm彈窗", "模擬Confirm成功!", 340, function (r) {
if (r) {
PlusAlert("模擬Alert彈窗", "你單擊了確定");
} else {
PlusAlert("模擬Alert彈窗", "你單擊了取消");
}
});
}
</script>
</body>
</html>
生成彈窗的js代碼:
$(function () {
//css樣式
var strStyle = "<style type='text/css'>";
strStyle += ".confirmPop a{text-decoration: none;}";
strStyle += ".confirmPop{width:350px; border:#64a64b solid 1px; position:absolute;background:#fff;z-index: 9999;left: 40%;top: 40%;font-family:Microsoft Yahei;}";
strStyle += ".confirmTitle{ background-color:#69ae4e; position:relative;}";
strStyle += ".confirmTitle span{line-height: 30px;margin-left: 5px;font-size: 15px;color: white;}";
strStyle += ".confirmText{ margin:20px 0;text-align: center;}.confirmText span{ font-size: 15px;}";
strStyle += ".confirmBtnBox{ text-align:center; margin:10px 0;}";
strStyle += ".confirmBtnBox .btn{ display:inline-block; padding:0 28px; height:30px; line-height:30px; color:#fff; background-color: #64a64b;margin: 0 10px;}";
strStyle += ".confirmBtnBox .btn:hover{ background-color:#509236;}";
strStyle += ".confirmGlobal{display: block; position: fixed; clear: both; z-index: 9999; left: 0px; top: 0px; bottom: 0px;border: 0px solid rgb(255, 255, 255); width: 100%; height: 100%; opacity: 0.5; background: rgb(255, 255, 255);}";
strStyle += "</style>";
$("head").append(strStyle)
//js事件
$.alerts = {
alert: function (title, message, width, callback) {
if (title == null) title = 'Alert';
$.alerts._show(title, message, width, 'alert', callback);
},
confirm: function (title, message, width, callback) {
if (title == null) { title = 'Confirm'; }
return $.alerts._show(title, message, width, 'confirm', callback);
},
_show: function (title, msg, width, type, callback) {
renderHtml(title, msg, width, type);
switch (type) {
case 'alert':
$("#confirmBtnSure").click(function () {
$.alerts._hide();
if (callback) {
callback(true);
}
});
$("#confirmBtnSure").focus().keypress(function (e) {
if (e.keyCode == 13 || e.keyCode == 27) {
$("#confirmBtnSure").trigger('click');
}
});
break;
case 'confirm':
$("#confirmBtnSure").click(function () {
$.alerts._hide();
if (callback) {
return callback(true);
}
});
$("#confirmBtnCancel").click(function () {
$.alerts._hide();
if (callback) {
return callback(false);
}
});
$("#confirmBtnCancel").focus();
$("#confirmBtnSure, #confirmBtnCancel").keypress(function (e) {
if (e.keyCode == 13) {//回車
$("#confirmBtnSure").trigger('click');
}
if (e.keyCode == 27) {//ESC
$("#confirmBtnCancel").trigger('click');
}
});
break;
}
},
_hide: function () {
$("#confirmId,#confirmGlobal").remove();
}
}
//修改Alert彈層提示框
//標題-title,提示信息-altInfo,確認按鈕函數-callback,寬度-width
PlusAlert = function (title, message, width, callback) {
$.alerts.alert(title, message, width, callback);
}
//修改Confirm彈層提示框
PlusConfirm = function (title, message, width, callback) {
$.alerts.confirm(title, message, width, callback);
};
})
//生成html並渲染樣式
function renderHtml(title, msg, width, type) {
if (width) {
strPrompt = "<div id='confirmId' style='width: " + width + "px'>";
} else {
strPrompt = "<div id='confirmId'>";
}
strPrompt += "<div id='confirmTitleDiv'><span id='confirmTitle'>" + title + "</span></div><div id='confirmTextDiv'><span id='confirmInfo'>";
strPrompt += msg + "</span></div><div id='confirmBtnBox'>";
strPrompt += "<a class='btn' href='javascript:void(0)' id='confirmBtnSure'>確認</a>";
if (type == "confirm") {
strPrompt += "<a class='btn' href='javascript:void(0)' id='confirmBtnCancel'>取消</a>";
}
strPrompt += "</div></div>";
$("body").append(strPrompt)
//遮罩層
$("#confirmId").before("<div id='confirmGlobal'></div>")
//手動渲染樣式
$("#confirmId").attr("class", "confirmPop");
$("#confirmTitleDiv").attr("class", "confirmTitle");
$("#confirmTextDiv").attr("class", "confirmText");
$("#confirmBtnBox").attr("class", "confirmBtnBox");
$("#confirmBtnSure").attr("class", "btn");
$("#confirmBtnCancel").attr("class", "btn");
$("#confirmGlobal").attr("class", "confirmGlobal");
}
彈窗的css樣式已經寫在了js文件中,這樣就不用再引用一次css文件,只需要引用一個js文件即可。當然將css寫到另外的文件,自己修改樣式時會更方便。
通過以上的代碼,對非服務器控件,你完全可以實現一個自定義的alert和confirm窗口,裏面的所有東西你都可以修改,樣式完全可以根據自己的需求自定義。
對於服務器控件,通過添加onclientclick事件,調用renturn PlusConfirm()來實現一個提示時,你會發現他的返回值永遠是true,還沒等你點擊確定或者取消,頁面已經被提交到後臺執行了。
實現一個自定義的提示窗口,然後自定義返回函數這些都簡單,半小時一小時就能實現,煩人的是對於服務器控件,在調用了自定義窗口完成後,並不會阻塞程序,等待用戶的下一步操作指示再進行是否提交到後臺執行。
我嘗試用了while循環,結果失敗,因爲while執行的過程中你無法操作;用Timeout來做,還是失敗,延時0微妙,你還是不能操作界面,大於0秒,程序會還沒等你跑Timeout方法就已經提交到後臺執行;那就只能阻塞js的進程咯,然後找半天的結果和上面兩種差不多的結果。
經過不懈的努力,我想到了實現方法。其實上面的while和Timeout的嘗試中我已經無限接近這個答案了。
服務器控件調用自定義提示窗口的代碼:
//後臺控件調用自定義confirm窗口時,需要單擊控件後先返回false,當點擊確定時,再次模擬點擊控件。
var IsOk = false;
function bgControlConfirm() {
if (IsOk) {
return true;
}
PlusConfirm("模擬Confirm彈窗", "模擬服務器控件調用Confirm彈窗", 340, function (r) {
if (r) {
IsOk = true;
document.getElementById('SignInGrid_ctl02_btnDelete').click();
} else {
IsOk = false;
}
});
return false;
}