最近一直在學習.net core的用法。想法是通過寫一個新聞系統來熟悉一下這個最新的技術。其實,我以前一直對.net技術都是淺嘗輒止,最主要原因是沒有動力。平時寫企業站因為時間原因,不是使用php的框架就是用N年以前自己用asp寫的系統直接上了。最近一直沒什么活,決定試試。但在使用前端驗證時有個問題一直很不喜歡。驗證信息的顯示方式太占用頁面的空間。如果 顯示在輸入控件后面,就要為其留出足夠的空間,這樣看起來很不好看。如果顯示在下面,會讓界面一會兒高一會兒低的。就想解決一下。至於效果嗎,有兩種想法,一是泡泡提示效果,另一種是圖標提示,兩種都可以。於是去網上找各種資料,找到了幾篇,大部分都是關於jquery-validation的,而且基本上都是修改原碼來實現。這個不是我想要的。因為修改原碼會很麻煩,一來,以后原碼就無法升級了。二是如果想換一個效果就又要修改原代碼。這個不符合切片精神。
於是想如果能象mvc中加過濾器一樣,在錯誤信息顯示過程中加入自定義的代碼不就可以了嗎?但查了很久資料,都沒有找到這方面的內容。后來想,能不能來監聽css的class的變動來實現呢。這個資料也沒能找到中文的,后來在英文網站中找到一篇關於如何監聽class改變的。http://forum.jquery.com/topic/firing-an-event-on-addclass,這里面提供了一思路,就是我們可以通過修改jquery的事件處理來實現監聽任意事件。
這樣,我們就可以不用修改原碼而實現我們的想法。
先看一下運行結果:
驗證錯誤信息不出現在頁面上,而是當鼠標指上去時才會顯示。當然,根據本文的方法,原則上可以實現任何顯示效果。比如說氣泡提示。
1、網頁代碼
網頁是從mvc渲染后的頁面中直接拷貝出來的。因為是實驗性質的,所以css文件都沒有帶。有點難看。其中<img class='validImg' style="display:none;" src="images/validatebox_warning.png" title='' >是加在每一個需要前端驗證的控件上,用來代替原來的那個<span>的。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>JsDemo</title> <script type="text/javascript" src="jquery.js"></script> <script src="jquery.validate.js"></script> <script src="jquery.validate.unobtrusive.js"></script> <script src="my.js"></script> <style> .control-label{float:left;} </style> </head> <body> <form action="/Admin/Home/Login" onsubmit="return false;" method="post"> <div class="form-horizontal"> <div class="text-danger"></div> <div class="form-group"> <label class="col-md-2 control-label" for="LoginName">登录名称</label> <div class="col-md-10"> <input class="form-control" type="text" data-val="true" data-val-required="登錄名稱必輸。" id="LoginName" name="LoginName" value="" /> <img class='validImg' style="display:none;" src="images/validatebox_warning.png" title='' > <span id="validSpanForLoginName" class="text-danger field-validation-valid" data-valmsg-for="LoginName" data-valmsg-replace="true"></span> </div> </div> <div class="form-group"> <label class="col-md-2 control-label" for="LoginPass">登录密码</label> <div class="cold-md-10"> <input class="form-control" type="password" data-val="true" data-val-length="登录密码长度必须小于50个字符。" data-val-length-max="50" data-val-required="登录密码必须输入。" id="LoginPass" name="LoginPass" /> <img class='validImg' style="display:none;" src="images/validatebox_warning.png" title='' > <span class="text-danger field-validation-valid" data-valmsg-for="LoginPass" data-valmsg-replace="true"></span> </div> </div> <div class="form-group"> <label class="col-md-2 control-label" for="CheckCode">验证码</label> <input class="form-control" type="text" data-val="true" data-val-required="验证码必须输入。" id="CheckCode" name="CheckCode" value="" /> <img class='validImg' style="display:none;" src="images/validatebox_warning.png" title='' > <span class="text-danger field-validation-valid" data-valmsg-for="CheckCode" data-valmsg-replace="true"></span> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10" style="padding-left:65px;"> <input type="submit" value="登錄" class="btn btn-default" /> <!--<div class="poptip" > <span class="poptip-arrow poptip-arrow-bottom"> <em>◆</em> <i>◆</i> </span> 這是氣泡提示,純CSS[◆字符]寫的哦 </div>--> </div> </div> </div> </form> </body> </html>
2、js代碼
從上面提到的那篇 文章中我們知道,在jquery中可以通過將原方法進行替換的方法對一個方法進行添加功能,這很象mvc中的過濾器。其實真的很簡單,就幾行代碼。
(function($){ $.each(["attr","css"],function(i,methodname){ var oldmethod = $.fn[methodname]; $.fn[methodname] = function(){ oldmethod.apply( this, arguments ); this.trigger(methodname+"change"); return this; } }); })(jQuery);
可能你會覺得$.each([], function(){});這個就是一個對數組進行遍歷呀。為什么?
再往下看兩行就明白了,就是使用$.fn['methodname']來取出要進行過濾的方法,然后對其進行添加代碼處理,在這里只是簡單地觸發一個自定義事件,事件名稱就是xxx+change。
這樣,在頁面中你只要去監聽這個自定義事件就可以了。就象下面的代碼一樣,我只是簡單地監聽了所有前端驗證顯示控件對錯誤信息處理時要用到的兩個事件(appendTo和removeData),因為不管如何處理,要想顯示信息就要將內容加到頁面上的控件中去,一定會使用appendTo或insert或insertBefore等方法來實現 。而當驗證通過時也應該會使用相對應的方法將添加的信息去掉。當然,到底如何做,這個要看原碼才行。
下面是jquery.validate.unobtrusive.js原碼中關於如何顯示驗證錯誤信息的兩部分原碼:為什么是jquery.validate.unobtrusive.js?噢,忘了說,這是.net mvc,而不是直接使用jquery.validation.js,不過原理一樣,如果你使用的是jquery.validation.js只要找到關鍵的顯示錯誤信息的方法就行了。
有關錯誤信息顯示的最重要的兩個方法:
onError方法用來顯示錯誤信息:
function onError(error, inputElement) { // 'this' is the form element var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), replaceAttrValue = container.attr("data-valmsg-replace"), replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; container.removeClass("field-validation-valid").addClass("field-validation-error"); error.data("unobtrusiveContainer", container); if (replace) { container.empty(); error.removeClass("input-validation-error").appendTo(container); } else { error.hide(); } }
onSuccess用來去掉錯誤信息,因為通過驗證了。
function onSuccess(error) { // 'this' is the form element var container = error.data("unobtrusiveContainer"); if (container) { var replaceAttrValue = container.attr("data-valmsg-replace"), replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; container.addClass("field-validation-valid").removeClass("field-validation-error"); error.removeData("unobtrusiveContainer"); if (replace) { container.empty(); } } }
從上面的兩段代碼我們可以看出,在顯示錯誤信息時一定會調用appendTo方法,而通過驗證時一定會調用removeData方法,所以在下面的代碼中監聽了這兩個方法。
(function($){ $.each(["appendTo","removeData"],function(i,methodname){ var oldmethod = $.fn[methodname]; $.fn[methodname] = function(){ oldmethod.apply( this, arguments ); this.trigger(methodname+"change"); return this; } }); })(jQuery); $(document).ready(function(e){ //監聽jquery中的appendTo事件而引發的自定義事件 $(".field-validation-valid").on('appendTochange', function(e){ var errText = $(this).children().eq(0).text(); if(errText.length>0) { $(this).parent().children('.validImg').attr('title', errText).show(); //將錯誤提示信息span隱藏起來 $(this).hide(); } //此時應該添加上去了一個子元素 }); // $(".field-validation-valid").on('removeDatachange', function(e){ //此時已經驗證通過了 $(this).parent().children('.validImg').hide(); }); });