最近在修改一個MVC項目的頁面時要實現輸入為空時禁用提交按扭的功能,這其實是個很簡單的功能,這里只是寫點自己的分享出來,順便總結經驗以后查用。資深專家勿噴 。
在制作表單時,我們經常會遇到需要對表單內容進行驗證,數據非法時不允許用戶提交。對用戶的輸入進行驗證又有兩種選擇:服務器端的驗證和客戶端的驗證。由於后者會重大服務器的負擔,不利於服務器處理更為核心的業務,一般我們都選擇用JavaScript在客戶端進行驗證。這樣會保證數據在送達服務器時已經是正確的,減輕了服務器開銷,更重要的是,客戶端的驗證是即時的,不會存在與服務器進行通信的時間開銷。
如果你在開發中使用的是第三方控件,你可能不必考慮驗證了,控件大都自帶了數據驗證功能,你只需調用相關功能即可。但很多時候其實還是需要我們親自動手進行驗證的。
輸入為空禁用提交按扭
當輸入框中沒有值時,無聊的用戶還是會猛擊提交按扭的,這時需要將提交禁用掉。即使是這樣一個灰常之簡單的功能,在初次嘗試時也不是一下就達到了我想要的效果的,尋求理想的解決方案是個過程。這里我將用jQuery來實現。
首先構造一個非常簡單的頁面,只是用來演示,上面放一個輸入框,一個提交按扭。
下面打開VS2010新建一個網站項目(當然,本文中的一切操作你完全可以在記事本中完成,我只是想用VS的代碼提示及排版方便些)
圖1
然后右擊項目名選擇添加新項,往項目中添加一個HTML 頁面。
往上面放面放一個輸入框和一個提交按扭。<body>部分代碼如下:
1 <body> 2 <input type="text" id="name"/> 3 <input type="submit" id="submit"/> 4 </body>
出來的頁面應該是這樣的
圖2
為了使用jQuery,需要將jQuery引用到這個頁面中,在新建網站項目時VS已經把jQuery放在了Scripts文件夾中,我們只需在頁面的<head>部分添加對jQuery的引用。
1 <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
現在點擊提交還沒有任何反應,現在我們為提交按扭添加一個方法,好在點擊提交之后執行些什么。我們讓頁面彈出個消息框,對輸入框中輸入的名字問好。
還是在<head>部分,我們添加如下代碼:
1 <script> 2 3 $(document).ready(function() { 4 5 $("#submit").click(function() { 6 7 alert("Hello," + $("#name").val()); 8 9 }); 10 11 }); 12 13 </script>
如果不熟悉jQuery,你可能需要簡單學習一下,不過上手很快。Ready()表示頁面元素加載完成之后,再執行ready里面的function()。現在我們點擊提交會彈出一個消息框,如果我們輸入了值的話,消息框中的Hello會加上我們的輸入。
圖3
圖4
上面看到,即使沒有輸入,提交也會成功,現在來增加對輸入是否為空的驗證。
考慮到頁面第一次加載后,輸入框中並沒有輸入,所以一開始我們就需要把提交禁用掉。所以我的基本思路是取到輸入框中的值,如果有輸入,這個值的長度肯定大於0,把提交按扭的disable屬性去掉,讓用戶可以提交,如果沒有輸入,這個值的長度等於0,則什么也不做。
所以我們在$(document).ready()增加一個方法,代碼如下:
1 <script> 2 3 $(document).ready(function () { 4 5 $("#submit").attr("disabled", "disabled"); 6 7 $("#name").change(function () { 8 9 if ($(this).val().length > 0) { 10 11 $("#submit").removeAttr("disabled"); 12 13 } 14 15 }); 16 17 $("#submit").click(function () { 18 19 alert("Hello," + $("#name").val()); 20 21 }); 22 23 }); 24 25 </script>
打開頁面后,第5行的代碼將提交按扭禁止。然后第7行的change方法監聽輸入框中值的變化,如果變化,則進行長度判斷,大於0說明有輸入,移除掉提交按扭的disable屬性使其能用。否則表示沒有輸入,什么也不做。
圖5
我們輸入東西進去然后單擊頁面空白部分使焦點離開輸入框這時提交按扭可用,彈出了圖4一樣的消息框,工作正常。
但如果我們把剛才的輸入擦掉,再點擊,還是可以彈出消息框,說明程序不完善。這是因為第一次輸入之后,程序判斷有值,那么就把提交按扭激活了,到第二次清空輸入后再點擊提交時,按扭依然是激活的,所以出現這種情況。
於是我們$("#submit").click()方法進行一下修改,在提交時進行判斷,如果有輸入,則正常彈出消息框,如果沒有輸入,則不彈出,並且我們讓輸入框獲得焦點,提示用戶進行輸入。
1 $("#submit").click(function () { 2 3 if ($("#name").val().length > 0) { 4 5 alert("Hello," + $("#name").val()); 6 7 } else { 8 9 $("#name").focus(); 10 11 } 12 13 });
再次運行,輸入之后,單擊頁面其他空白處激活按扭,再將輸入清空,這時再點擊提交,不會彈出消息框了。到這里,不管完不完美,想要的輸入為空禁用提交功能是實現了。
上面為了激活提交按扭,我們輸入之后還需單擊頁面其他部分讓焦點從輸入框離開,這確實有點不爽。這里激活提交是調用的change方法,而輸入框的change方法只有在輸入框失去焦點后才會觸發,這就是為什么總需要點擊頁面其他地方讓光標離開輸入框。
完美的情況應該是我們一旦輸入了東西,按扭就自動激活,而不需要我們再去點其他地方。這時你可能會想到用keydown(),keyup(),或者keypress()這樣的方法來代替change(),這些方法確實可以。但仍會有些小問題。這里我們試一下用keydown()來代替change()。現在變成只要輸入框中有鍵按下,就會判斷到有值輸入從而激活提交按扭。
1 $(document).ready(function () { 2 3 $("#submit").attr("disabled", "disabled"); 4 5 $("#name").keydown(function () { 6 7 if ($(this).val().length > 0) { 8 9 $("#submit").removeAttr("disabled"); 10 11 } 12 13 }); 14 15 $("#submit").click(function () { 16 17 if ($("#name").val().length > 0) { 18 19 alert("Hello," + $("#name").val()); 20 21 } else { 22 23 $("#name").focus(); 24 25 } 26 27 }); 28 29 });
程序運行后,我們發現,在按下第一個字母后,提交按扭還是不可用,在按下第二個字母后,它才變得可用。這是不是黑奇怪!?
對丫,我也覺得黑奇怪。特么神奇了。
圖6 圖7
仔細分析就會發現問題。keydown是在鍵被按下的時候觸發事件,而剛按下時,鍵值還沒有被輸入到框中,所以此刻的輸入框中長度確實為0,激活按扭的語句沒有沒有被執行到;而當我們按第二個鍵時,因為前面已經輸入了一個字符,所以這回同樣是在按下的瞬間,檢測到框中有值長度為1,所以if語句判斷通過,將提交按扭的disable去掉從而激活。另外,keypress()也有同樣的問題,原因也是一樣的,事件觸發時值還沒有被輸入。還好,最后發現keyup()是可以的。keyup之所以可以是因為它是在按完鍵彈起后才觸發事件,鍵都彈起了,值肯定已經被輸入到框里面去了嘛,所以此刻觸發if語句進行判斷時,就會得到長度為1。下面是使用keyup()代替change()時的截圖,注意,在輸入第一個字母后,光標還在輸入框中,但按扭已經激活,沒有出現上面keydown()和keypress()一樣的問題了。
圖8
說明keyup()能滿足我們的需求,但再仔細一想,用戶輸入難道必需要按鍵么,完全可以通過鼠標右擊然后粘貼,這在填表單時是經常發生的事。這里我試驗了一下,通過鼠標右鍵粘貼了東西到輸入框后,這個看似能解決問題的keyup()也掛掉了,提交還是沒有自動激活,需要我們點擊其他地方來移除焦點。
圖9
后來我研究了一下,還是找到了一個完美的解決辦法,那就是用bind()來將我們要做的操作綁定到這個輸入框。
最后修改的代碼如下:
1 <script type="text/javascript" language="javascript"> 2 3 $(document).ready(function () { 4 5 $("#submit").attr("disabled", "disabled"); 6 7 $("#name").bind("input", function () { 8 9 if ($("#name").val().length > 0) { 10 11 $("#submit").removeAttr("disabled"); 12 13 } 14 15 }); 16 17 $("#submit").click(function () { 18 19 if ($("#name").val().length > 0) { 20 21 alert("Hello," + $("#name").val()); 22 23 } else { 24 25 $("#name").focus(); 26 27 } 28 29 }); 30 31 }); 32 33 </script>
現在,不管你是手動輸入,還是Ctrl+V或者鼠標右鍵的粘貼,提交按扭都能在第一時間被激活。
錯誤提示---增加用戶友好度
為了更人性化,當用戶在沒有輸入任何東西試圖提交時,我們應該給點提示信息告訴用戶要輸入,上面僅僅把焦點轉回輸入框還是不足不夠直觀的。
我們在頁面上加一個<p>標簽來放提示信息:
1 <body> 2 3 <input type="text" id="name" /> 4 5 <input type="submit" id="submit" /> 6 7 <br /> 8 9 <p id="error_msg" style="color: red"> 10 11 u kidding me? input something first!</p> 12 13 </body>
平時讓它處於隱藏狀態,只有當用戶沒有輸入而試圖提交時,才將它顯示出來。並且在用戶輸入之后,提示信息應該立即消失。修改后的js代碼如下:
1 <script type="text/javascript" language="javascript"> 2 3 $(document).ready(function () { 4 5 $("#error_msg").hide(); 6 7 $("#submit").attr("disabled", "disabled"); 8 9 $("#name").bind("input", function () { 10 11 if ($("#name").val().length > 0 ) { 12 13 $("#error_msg").hide(); 14 15 $("#submit").removeAttr("disabled"); 16 17 } 18 19 }); 20 21 $("#submit").click(function () { 22 23 if ($("#name").val().length > 0) { 24 25 alert("Hello," + $("#name").val()); 26 27 } else { 28 29 $("#name").focus(); 30 31 $("#error_msg").show(); 32 33 } 34 35 }); 36 37 }); 38 39 </script>
運行效果:
圖10
Ctrl+Enter組合鍵—錦上添花
在輸入完登陸的用戶名及密碼后,你是否試過不去點擊“登陸”而直接按ctrl+enter鍵優雅而便捷地完成登陸,這個組合鍵也經常用在提交評論。我是覺得這樣的用戶體驗是非常棒的,因為你在完成輸入或者帖子的評論后,要把手移開鍵盤去用鼠標然后再移到相應的按扭上操作,這是很不爽的事。而直接按ctrl+enter提交會便捷得多,至少如果在提供了這樣的功能的網站上,我不會用鼠標去提交。
而且一般大企業的網站這方面的細節做得比較好,都有這樣的功能。比如你在QQ空間評論好友的說說,可以按ctrl+enter提交。並且這個功能不是很難,只是幾句代碼的事,我簡直找不到理由不去實現它。
只需要再加一個ctrl+enter組合鍵的監聽即可,如果監聽到了用戶輸入同時按下ctrl和enter,則執行提交,這與鼠標點擊“提交”的效果是一樣的。
這里需要用到jQuery提供的bind()方法。Bind()方法允許你將多個事件綁定到同一個頁面元素上,這里我們的綁定目標是輸入框。這也是在上面的討論中什么最后選擇了bind()的原因,不僅解決了上面遇到的那些問題,也是為了向輸入框再綁定一個事件,一舉兩得。
原先綁定的”input”部分需要作一下小小的調整,修改后的代碼如下:
1 <script type="text/javascript" language="javascript"> 2 3 $(document).ready(function () { 4 5 $("#error_msg").hide(); 6 7 $("#submit").attr("disabled", "disabled"); 8 9 $("#name").bind({ 10 11 input: function () { 12 13 if ($("#name").val().length > 0) { 14 15 $("#error_msg").hide(); 16 17 $("#submit").removeAttr("disabled"); 18 19 } 20 21 }, 22 23 keydown: function (e) { 24 25 if (e.ctrlKey && e.keyCode == 13) { 26 27 $("#submit").click(); 28 29 } 30 31 } 32 33 }); 34 35 $("#submit").click(function () { 36 37 if ($("#name").val().length > 0) { 38 39 alert("Hello," + $("#name").val()); 40 41 } else { 42 43 $("#name").focus(); 44 45 $("#error_msg").show(); 46 47 } 48 49 }); 50 51 }); 52 53 </script>
鍵盤上每個按鍵都對應着一個數字編碼,代碼中的e.keyCode == 13指的正是enter鍵。關於按鍵編碼可以參考這里。
給提交按扭變個樣
現在的提交按扭還只是系統提供的默認樣式,為了美觀,我們可以通過定義CSS 樣式來進行簡單美化一下。至少做到按扭換個好看點的,並且在鼠標放上去時可以變個顏色。
同樣在<head>部分,我們定義一下style。其中按扭要用到的圖片可以在網上找,也可以下載文章末尾的源碼,里面包含了圖片。
更改后的代碼如下:
1 <style type="text/css"> 2 3 #submit 4 5 { 6 7 width: 85px; 8 9 height: 30px; 10 11 line-height: 30px; 12 13 background: url(btn.gif) top center no-repeat; 14 15 border: 0; 16 17 font-family: "Titillium800" , "Trebuchet MS" , Arial, sans-serif; 18 19 font-size: 14px; 20 21 font-weight: normal; 22 23 text-transform: uppercase; 24 25 color: white; 26 27 text-shadow: 1px 1px 0 #0A5482; 28 29 cursor: pointer; 30 31 margin-right: 10px; 32 33 vertical-align: middle; 34 35 } 36 37 #submit:hover 38 39 { 40 41 background: url(hover.gif) top center no-repeat; 42 43 text-shadow: 1px 1px 0 #b55f10; 44 45 } 46 47 48 49 #name 50 51 { 52 53 height: 25px; 54 55 } 56 57 </style>
現在可以看到,我們的頁面是這樣的了。
圖11 圖12
只接受特定類型的輸入
進行到這里,仔細思考會覺得,我為什么允許用戶能夠輸入非法值,然后再煞費苦心地去驗證,完了再輸出友情提示:親,你的輸入是非法的,這樣不好~我們完全可以將輸入框設置為只能輸入我們想要的數據類型,這就是最小用戶假設。我們不願去承擔處理非法輸入的開銷,我們假設用戶只輸入我們指定的類型,比如在一個前面指名了年齡的輸入框中,按常識用戶當然知道這里需要輸入的是數字而且必需是正整數!所以在這樣的輸入框里我們只接受數字,確切地說是正整數,如果用戶試圖輸入字母或者狂砸鍵盤,只有數字才會被輸入到輸入框中。
這里,因為是名字輸入框,應該設置為不接受數字類型及其他特殊符號的輸入,即只接受a-z,A-Z以前中文字符。
這個時候,就是正則表達式強大功能得到體現的時候了。如果你不熟悉正則表達式,你可能需要簡單的學習下,上手同樣很快。
首先在HTML標簽中為輸入框添加onkeypress事件,並指定事件觸發后的處理器。如下:
1 <input type="text" id="name" onkeypress='validate(event)'/>
然后我們在<javascript>部分來實現這個validate(event)方法,它帶有一個參數,即事件的發送者。緊接着$(document).ready(),我們添加對validate的實現:
1 function validate(evt) { 2 3 var theEvent = evt || window.event; 4 5 var key = theEvent.keyCode || theEvent.which; 6 7 key = String.fromCharCode(key); 8 9 var regex = /[a-zA-Z]|\./; 10 11 if (!regex.test(key)) { 12 13 theEvent.returnValue = false; 14 15 if (theEvent.preventDefault) theEvent.preventDefault(); 16 17 } 18 19 }
最后,我們運行程序測試一下效果。當我們試圖輸入數字時,數字不會上屏,輸入框中沒有任何變化,我們換字母或者漢字時,才能正常輸入。
但測試還發現,換成中文輸入法時,好多符號也能輸入。說明這里的正則表達式還是有缺陷的,但至少我們屏蔽掉了數字的輸入。
如果你有更好的方法來實現這一部分,請指教,請跟進,共同學習。
后記:看似簡單的一個提交功能,我覺得要做好還是需要花一些時間來掌握的。這里好多地方也都還有不足,比如文章最后一部分“只接受特定類型的輸入”,可能面臨很多不兩只的需求,這里可能只需要金錢類型的格式,另外一個地方要求只能輸入喵星語汪星語,所以不同情況,這里的實現會有不同,但正則表達式會是一個很好很強大的選擇。
可以參考的文章
1.關於jQuery.bind()方法
2.ctrl+enter combo key
http://stackoverflow.com/questions/1684196/ctrlenter-jquery-in-textarea
3.Binding Multiple Event Handlers
http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3
4.Numeric input
http://stackoverflow.com/questions/469357/html-text-input-allow-only-numeric-input
5.keycode
http://www.expandinghead.net/keycode.html