將網頁輸入欄位設為唯讀的做法
7 |
恰巧與同事討論到將網頁輸入欄位設為唯讀的做法,就順便整理分享一下我嘗試過的幾種方式: readonly, disabled及blockUI。
我把三種做法整理在一個範例中,設了四個checkbox來啟動不同的唯讀效果進行測試: (四個checkbox有加上radio互斥點選的效果,請參照這篇文章)
唯讀1是readonly法、唯讀2是disabled、唯讀3則是blockUI法。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>blockUI.block()</title>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.4.4.js"
type="text/javascript"></script>
<script src="https://github.com/malsup/blockui/raw/master/jquery.blockUI.js?v2.31"
type="text/javascript"></script>
<style type="text/css">
.ro { background-color: #cccccc; color: #444444; }
</style>
<script type="text/javascript">
$(function () {
//設計t1, t2連動,t1 blur()時清掉t2的值
$("#t1").blur(function () { $("#t2").val(""); });
var $ctrlGrp = $(".controller input");
$ctrlGrp.click(function () {
//先找出目前checked者
var $chked = $ctrlGrp.filter(":checked").not(this);
//取消已選取者的唯讀設定
if ($chked.length == 1)
clearReadOnly($chked[0].id);
//清除其他選取者,形成互斥
$ctrlGrp.not(this).removeAttr("checked");
//點選一律為checked,並設定唯讀
this.checked = true;
setReadOnly(this.id);
});
//示範三種設定唯讀的方式
function setReadOnly(t) {
switch (t) {
case "ro1":
//設定readonly屬性,缺點是事件仍有作用
$("#t1,#t2").addClass("ro").attr("readonly", true);
break;
case "ro2":
//設定disabled的,但欄位外觀較異常,且Submit前不還原
//欄位將被忽略不Postback回後端
$("#t1,#t2").addClass("ro").attr("disabled", true);
break;
case "ro3":
//利用blockUI block()形成遮罩,阻止使用者對欄位進行操作
$("#t1,#t2").addClass("ro");
$("#dvEditor").block({
message: null,
overlayCSS: {
backgroundColor: "#cccccc",
opacity: 0.2,
cursor: "default"
}
});
break;
}
}
//清除唯讀設定
function clearReadOnly(t) {
switch (t) {
case "ro1":
$("#t1,#t2").removeClass("ro").removeAttr("readonly");
break;
case "ro2":
$("#t1,#t2").removeClass("ro").removeAttr("disabled");
break;
case "ro3":
$("#t1,#t2").removeClass("ro")
$("#dvEditor").unblock();
break;
}
}
});
</script>
</head>
<body>
<fieldset>
<legend class="controller">
正常 <input type="checkbox" id="ro0" />
唯讀1 <input type="checkbox" id="ro1" />
唯讀2 <input type="checkbox" id="ro2" />
唯讀3 <input type="checkbox" id="ro3" />
</legend>
<div id="dvEditor">
<input type="text" id="t1" value="" />
<input type="text" id="t2" value="" />
</div>
</fieldset>
</body>
</html>
來談談三種做法的優缺點:
- readonly:
最直覺簡單,但我故意加上的t1, t2連動突顯它的問題。即使設為readonly,點選t1再移開焦點照樣會觸發blur()事件! 若要避免,則在設定唯讀時得一併停用事件;若唯讀狀態允許動態取消,則又要再加上重新啟用事件的邏輯,挺麻煩的。readonly的另一個缺點是<select>不支援,沒法用統一的做法處理各式輸入欄位。 - disabled:
設定disabled屬性將欄位停用後,使用者就無法對欄位進行任何操作,一方面等同唯讀,也不用擔心事件會被觸發,並且<input>, <select>, <textarea>通通適用,算是很乾脆的選擇。
不過,停用欄位長相跟一般正常欄位不太一樣(可參考上圖唯讀2的呈現結果,不同瀏覽器差異幅度也各異),或許會影響視覺上的一致性。另外要注意,被disabled的欄位在Postback回Server端時會被忽略,若我們的目的只是唯讀並非無視欄位內容,則記得在送出表單前要偷偷將disabled拿掉,這要花些額外的工。 - blockUI:
blockUI的block()可以在特定元素上放一層遮罩,阻絕使用者的操作,無法輸入也不會觸發事件;而overlayCSS參數允許我們設定它的顏色透明度等,可配合我們的需求調整外觀。
由於是用遮的,只要在包含輸入欄位的容器元素(如<div>, <span>)上啟動.block(),便可一次大範圍地將各式輸入欄位(<input> <select> <textarea>)變成唯讀。
由以上分析,blockUI可以一次處理多個欄位,又不需處理事件停用、disabled還原等議題,看起來會是較簡便的選擇。
Comments
# by walk
特定元素上放一層遮罩... 用遮的...感覺不錯 謝謝大大分享
# by ' 0r 1=1;--
用遮的也適用於 <select> 這個難搞的控制項嗎?
# by Jeffrey
to OR 1=1, <select>難搞應是指IE6的下拉選單會浮在所有元素的圖層上方吧? BlockUI有加了iframe特別克服這個問題,應可安心服用。
# by qoo
請問block()在ie6用會讓ie整個當掉,但ie8則不會,ie6是不是就不能用了?
# by qoo
block()在ie6下拉選單會不見,請問如何解決?
# by Jeffrey
to qoo, 依我之前的經驗,blockUI在IE6上也可正常運作,看你是否能提供會讓IE6當掉的範例讓大家幫你看看問題所在。(只是這年頭大部分的開發者都已經無視IE6了,包含微軟在內)
# by Wing
分析的淺顯易懂 對新手我太有幫助了 天呀 這裡好棒~!