JQuery插件開發之如何實時顯示被隱藏的輸入框密碼

原文連接:http://www.gbtags.com/gb/share/5827.htmjavascript

咱們前面曾經介紹過如何提升用戶界面表單性能,同時咱們也介紹過如何避免使用密碼框來避免隱藏輸入的密碼,也討論過隱藏密碼顯示對於用戶體驗將有多麼糟糕。css

基本上對於密碼輸入處理咱們有以下倆個可選方式:html

  1. 繼續使用密碼框控件,不考慮用戶的操做體驗
  2. 使用通常的輸入框,不考慮用戶密碼的安全性

這就是爲何咱們這裏須要開發一個鼠標懸浮可顯示密碼的控件做爲第三選擇的緣由,既能夠提升安全,同時也能夠大大知足用戶體驗java

今天將講解如何使用jQuery插件來完成上述功能,同時讓你們瞭解更多jQuery插件開發,動態內容顯示,及其代碼開發的最佳實踐。node

這裏咱們將仿效一些移動設備的界面設計方式,咱們將能看到最後一個輸入的字符。廢話不說,咱們如今開始!jquery

用戶體驗背景

在咱們正式開發代碼前,咱們最好先了解爲何咱們開發這些功能。這個功能徹底是爲了用戶體驗而設計的,而且是爲了讓用戶體驗能達到極致。web

最初開始討論屏蔽用戶密碼問題的人是Jakob Nielsen,在初在他的"中止使用密碼屏蔽"文章中,他表達了對於密碼屏蔽的觀點。 有時候咱們可能在一些可疑的人周圍,他們正尋找一切可能的機會來獲取咱們的密碼。可是有時候,咱們則不須要應付這樣糟糕的狀況。ajax

理想狀況下咱們須要可以同時應付最好的和最壞的場景。無論使用IE6仍是chrome14.0.803.2Beta等瀏覽器。咱們都但願能作的最好。chrome

以上就是爲何咱們不想讓密碼缺省就被設置爲屏蔽的主要緣由。實際上咱們應該提供給咱們用戶一個更好的選擇。api

代碼開發

咱們須要作的是獲得一個通常的密碼控件,而後把它轉化成文字,再在其上建立一個覆蓋層,這個在你輸入過程當中會自動覆蓋。使用這個方法你能夠屏蔽任何內容而不用影響自己的輸入內容。如下圖片很好的解釋了這一切:

如今咱們開始正式編寫代碼。

咱們首先開始一個基本的表單標籤。很簡單隻有2個控件,一個有缺省的數值,另一個是空白的,用來顯示你須要的東西。

  1. <div id="container">  
  1. <h1>Sign Up!</h1> 
  1. <form action="#" method="get">
  1. <label> 
  1. <span class="title">Old Password</span> 
  1. <span class="desc">This is our awesome password field with default value. Try it out!</span>
  1. <input type="text" name="oldpassword" id="oldpassword" value="tHis1$myP4swrd." />
  1. </label> 
  1. <label> 
  1. <span class="title">Password</span> 
  1. <span class="desc">This is our awesome blank password field. Try it out!</span>
  1. <input type="password" name="password" id="password" />
  1. </label>
  1. </form> </div>

 

而後咱們調用jQuery和插件文件,以下:

  1. <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"> 
  1. // call jQuery from google! 
  1. </script> 
  1. <script type="text/javascript" src="jquery.hp.js"> 
  1. // call plugin </script>

 

如下咱們建立咱們基本的插件文件。你能夠參考咱們的jQuery Smooth Table of Contents Plugin,這裏咱們使用一個很是簡單的結構:

  1. (function($) { 
  1. $.fn.hoverpass = function(options) { 
  1. //Our default options
  1. var defaults = {
  1. bullet: "&bull;", 
  1. //which should be the "masking" character
  1. font: "'Lucida Console', monospace", 
  1. //please just use MONOSPACE fonts 
  1. bg: "#fff", 
  1. // background style for bullets
  1. free: "", 
  1. // add your own additional styling here 
  1. freeBul: "float: left; overflow: hidden;", 
  1. // add your own additional styling for bullets here 
  1. delay: 500, //how long it takes to create the bullet over the last character, in milliseconds 
  1. delayHover: 3000, //how long it takes to hide again a hovered character
  1. animation: 500, //how long it takes the animation itself 
  1. maxSize: 10 // maximum number of characters, to prevent bullets exploding input's size 
  1. };
  1. //let's extend our plugin with default or user options when defined
  1. var options = $.extend(defaults, options);
  1. return this.each(function() {
  1. //our action goes here 
  1. });
  1. }; 
  1. })
  1. (jQuery); 

 

以上咱們定義了缺省的參數,接下來我解釋一下:

  • bullet - 是咱們用來屏蔽密碼的符號。你可使用任何符號或者HTML的符號定義來屏蔽密碼 
  • font - 這個很是重要,這個插件實現只能實如今monspaced字體上。由於其它類型字體,每個字符都有它本身的長度,咱們沒法屏蔽。
  • bg - 若是你使用其餘的輸入框背景,那麼你須要針對的在屏蔽層上也實現。由於屏蔽層會居於輸入框之上。
  • free - 這裏你添加margin用來處理你輸入的padding問題。並且你能夠用戶來設置輸入字體大小
  • maxsize - 這個對於密碼框很是短的時候也很是重要。若是你不修改的話,你會獲得多餘的bullets而把輸入內容擠開。

到這裏你會有個基本插件,經過調用$(elem).hoverpass(),由第二行$.fn.hoverpass = function(){}定義。

修改輸入類型到文本

我不確認你是否之前嘗試過,可是這裏我得告訴你們,你是不能夠修改inputs的類型。這裏多是由於安全緣由。看起來只有IE對此有擔心。無論怎樣,咱們要做的就是建立一個沒有type屬性的輸入框克隆。這裏有幾個方法,我這裏使用這個:

  1. return this.each(function()
  1. {
  1. //let's declare some variables, many as a "shortcut" for options 
  1. var bullet = options.bullet,
  1. font = options.font,
  1. bg = options.bg, 
  1. free = options.free,
  1. freeBul = options.freeBul,
  1. delay = options.delay, 
  1. delayHover = options.delayHover, 
  1. animation = options.animation, 
  1. lastBul = ""; 
  1. //since we just can't change a field's type, we'll remove it and append a brand new text input on it's place 
  1. var oldElement = $(this); 
  1. // caching element, much better performance 
  1. var inputHTML = '<input type="text" style="font-family: '+ font +'; " />'; 
  1. //this is our basic input text, with our monopace font 
  1. var input = oldElement.after(inputHTML).next(); 
  1. //appending our simple text field with our styling (font-family) AND caching it as var "input" 
  1. /**** we are saying here: define the following variables: attr , i (zero), attrs (array with all oldElement attributes), l (size of attrs) while our counter (i) is smaller than attributes lenght (l) increase our counter and run this code */ for ( var attr, i=0 , attrs = oldElement[0].attributes , l =attrs.length ; i < l ; i++){
  1. attr = attrs.item(i)
  1. if (attr.nodeName != "type" && attr.nodeName != "style") {
  1. //well, we defined our type as text and font-style!
  1. input.attr( attr.nodeName, attr.nodeValue );
  1. }
  1. } 
  1. oldElement.remove(); 
  1. // bye, bye input type="password"! 
  1. });

 

建立屏蔽和Bullets

到這裏,當你定義$(elem).hoverpass()時候,它會變成一個monospaced的文本輸入框。很是酷吧?可是咱們須要的不只僅是這些。

如今咱們將建立咱們本身的Bullets容器。這倆行惟一有意思的地方是jQuery元素的再次緩存。你應該使用這個小技巧:

  1. // let the game begin var maskHTML = '<div class="hpMask" style="position: 
  1. absolute; cursor: text; height: 1px; font-family: ' + font + ' ; ' + free + ' " />'; 
  1. //our container with his styling var maskContainer = input.before(maskHTML).prev(); 
  1. // appending our container for bullets with styling (font-family, free)

 

如今咱們準備咱們的bullets HTML,由於它將被使用幾回,而且當咱們有一個"數值"定義時添加一些bullets。

  1. var bulletHTML = "<span class='hpBullet' style='background: " + bg +
  1. "; " + freeBul + " '>"+ bullet + " </span> "; // our bullets HTML 
  1. with styling (bg, freeBull)
  2. var countBullet = 0; 
  1. // this is our counter, it is important to prevent 
  1. our mask to get bigger / smaller than our input or its maximum size 
  1. //since we use it from different places, it's better to add it via function
  2. function addBullet() {
  1. // add our last bullet, but hidden, 
  1. and show anything that isn't last bullet 
  1. lastBul = maskContainer.append(bulletHTML).find(":last-child").hide();
  1. maskContainer.find(":not(:last-child)").each( function(){
  1. $(this).show(); } );
  1. //start timer to show 
  1. lastBul 
  1. lastBul.delay(delay).fadeIn(animation);
  1. countBullet++; }

 

目前爲止你能夠又看到一個文本框,但若是你有一個value屬性定義,你將看到不少bullets而且最後一個一妙後淡出。可是若是你輸入,沒有任何效果。

開始編寫鍵盤輸入

咱們須要每次在密碼框輸入過程當中添加bullets,而且在使用delete或者backspace鍵時刪除一個bullet.

這裏咱們使用keypress, keyup和keydown來實現。

咱們須要考慮一下使用keydown和keypress(由於它們很類似)咱們綁定"按下按鍵",使用keyup綁定"釋放按鍵。再仔細一點,你會發如今這個例子裏,keydown/keypress將會在咱們在字段內容有任何變化以前被調用,而keyup將會在任何變化發生後被調用。

這就是爲何咱們使用keyup。咱們必須查看控件內容而且看是否內容改變了大小,以此判斷是否添加和刪除bullets。這裏由於咱們須要照料到用戶選擇某一部分密碼,或者在密碼起始處按刪除鍵,以及其它比較困難綁定行爲的操做。

  1. //let's bind all keydown and create
  1. / remove our bullets ; 
  1. we need do use keydown in order to detect special characters in non-gecko browsers input.keyup(
  1. function(event) { 
  1. //check if something was really typed
  1. if (input[0].value.length > countBullet) { 
  1. addBullet();
  1. } else { //ooops, delete or backspace? 
  1. //then we check if something was really deleted 
  1. while (input[0].value.length < countBullet) {
  1. maskContainer.find(":last-child").remove(); 
  1. countBullet--;
  1. }
  1. }
  1. } );

 

最後,鼠標懸浮顯示密碼

如今咱們須要在用戶鼠標懸浮時隱藏咱們的bullet。看起來挺簡單的?其實否則。

由於咱們必須隱藏咱們的bullet,可是咱們不能丟失寬度,由於咱們若是丟了,咱們用戶將看到僅僅密碼最後一個字符(不是中間字符)。咱們能作到的是將它淡出到一個不明顯的透明(大概10%)而後將高度改成1px,這樣咱們還有寬度。

如今咱們只須要使用elem.hover()就能夠了吧?答案是否認的。由於咱們有動態產生的內容,咱們須要使用live()或者delegate()來綁定。我測試結果是delegate的效果更好,所以咱們能夠這樣:

  1. //hide bullets based on a jquery object 
  1. function hideBullets(object) {
  1. object.stop().css({ "height": 
  1. "auto"}).animate({ opacity: 1 }, 
  1. animation).removeClass("hpHiddenBullet");
  1. }
  1. //hover function for our bullets
  1. maskContainer.delegate(".hpBullet", 'hover',
  1. function(){ 
  1. var item = $(this);
  1. if  ( item.hasClass("hpHiddenBullet") != true ) {
  1. hideBullets( $(".hpHiddenBullet") ); 
  1. item.stop().addClass("hpHiddenBullet").animate( { opacity: 0.01},
  1. animation, function() { item.css({ "height": "1px"}); } );
  1. setTimeout( function() {
  1. if ( item.hasClass("hpHiddenBullet") == true ) {
  1. hideBullets( item ); 
  1. }
  1. }, delayHover); 
  1. } 
  1. }
 
  1. );

 

但願你們能喜歡這個效果,若是你有更好的實現,請和GBTAG分享。謝謝!

原文連接:http://www.gbtags.com/gb/share/5827.htm

相關文章
相關標籤/搜索