原文连接:http://www.gbtags.com/gb/share/5827.htmjavascript
咱们前面曾经介绍过如何提升用户界面表单性能,同时咱们也介绍过如何避免使用密码框来避免隐藏输入的密码,也讨论过隐藏密码显示对于用户体验将有多么糟糕。css
基本上对于密码输入处理咱们有以下俩个可选方式:html
- 继续使用密码框控件,不考虑用户的操做体验
- 使用通常的输入框,不考虑用户密码的安全性
这就是为何咱们这里须要开发一个鼠标悬浮可显示密码的控件做为第三选择的缘由,既能够提升安全,同时也能够大大知足用户体验java
今天将讲解如何使用jQuery插件来完成上述功能,同时让你们了解更多jQuery插件开发,动态内容显示,及其代码开发的最佳实践。node
这里咱们将仿效一些移动设备的界面设计方式,咱们将能看到最后一个输入的字符。废话不说,咱们如今开始!jquery
用户体验背景
在咱们正式开发代码前,咱们最好先了解为何咱们开发这些功能。这个功能彻底是为了用户体验而设计的,而且是为了让用户体验能达到极致。web
最初开始讨论屏蔽用户密码问题的人是Jakob Nielsen,在初在他的"中止使用密码屏蔽"文章中,他表达了对于密码屏蔽的观点。 有时候咱们可能在一些可疑的人周围,他们正寻找一切可能的机会来获取咱们的密码。可是有时候,咱们则不须要应付这样糟糕的状况。ajax
理想状况下咱们须要可以同时应付最好的和最坏的场景。无论使用IE6仍是chrome14.0.803.2Beta等浏览器。咱们都但愿能作的最好。chrome
以上就是为何咱们不想让密码缺省就被设置为屏蔽的主要缘由。实际上咱们应该提供给咱们用户一个更好的选择。api
代码开发
咱们须要作的是获得一个通常的密码控件,而后把它转化成文字,再在其上建立一个覆盖层,这个在你输入过程当中会自动覆盖。使用这个方法你能够屏蔽任何内容而不用影响自己的输入内容。如下图片很好的解释了这一切:

如今咱们开始正式编写代码。
咱们首先开始一个基本的表单标签。很简单只有2个控件,一个有缺省的数值,另一个是空白的,用来显示你须要的东西。
- <form action="#" method="get">
- <span class="title">Old Password</span>
- <span class="desc">This is our awesome password field with default value. Try it out!</span>
- <input type="text" name="oldpassword" id="oldpassword" value="tHis1$myP4swrd." />
- <span class="title">Password</span>
- <span class="desc">This is our awesome blank password field. Try it out!</span>
- <input type="password" name="password" id="password" />
而后咱们调用jQuery和插件文件,以下:
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
- // call jQuery from google!
- <script type="text/javascript" src="jquery.hp.js">
如下咱们建立咱们基本的插件文件。你能够参考咱们的jQuery Smooth Table of Contents Plugin,这里咱们使用一个很是简单的结构:
- $.fn.hoverpass = function(options) {
- //which should be the "masking" character
- font: "'Lucida Console', monospace",
- //please just use MONOSPACE fonts
- // background style for bullets
- // add your own additional styling here
- freeBul: "float: left; overflow: hidden;",
- // add your own additional styling for bullets here
- delay: 500, //how long it takes to create the bullet over the last character, in milliseconds
- delayHover: 3000, //how long it takes to hide again a hovered character
- animation: 500, //how long it takes the animation itself
- maxSize: 10 // maximum number of characters, to prevent bullets exploding input's size
- //let's extend our plugin with default or user options when defined
- var options = $.extend(defaults, options);
- return this.each(function() {
以上咱们定义了缺省的参数,接下来我解释一下:
- bullet - 是咱们用来屏蔽密码的符号。你可使用任何符号或者HTML的符号定义来屏蔽密码
- font - 这个很是重要,这个插件实现只能实如今monspaced字体上。由于其它类型字体,每个字符都有它本身的长度,咱们没法屏蔽。
- bg - 若是你使用其余的输入框背景,那么你须要针对的在屏蔽层上也实现。由于屏蔽层会居于输入框之上。
- free - 这里你添加margin用来处理你输入的padding问题。并且你能够用户来设置输入字体大小
- maxsize - 这个对于密码框很是短的时候也很是重要。若是你不修改的话,你会获得多余的bullets而把输入内容挤开。
到这里你会有个基本插件,经过调用$(elem).hoverpass(),由第二行$.fn.hoverpass = function(){}定义。
修改输入类型到文本
我不确认你是否之前尝试过,可是这里我得告诉你们,你是不能够修改inputs的类型。这里多是由于安全缘由。看起来只有IE对此有担心。无论怎样,咱们要做的就是建立一个没有type属性的输入框克隆。这里有几个方法,我这里使用这个:
- return this.each(function()
- //let's declare some variables, many as a "shortcut" for options
- var bullet = options.bullet,
- freeBul = options.freeBul,
- delayHover = options.delayHover,
- animation = options.animation,
- //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
- var oldElement = $(this);
- // caching element, much better performance
- var inputHTML = '<input type="text" style="font-family: '+ font +'; " />';
- //this is our basic input text, with our monopace font
- var input = oldElement.after(inputHTML).next();
- //appending our simple text field with our styling (font-family) AND caching it as var "input"
- /**** 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++){
- if (attr.nodeName != "type" && attr.nodeName != "style") {
- //well, we defined our type as text and font-style!
- input.attr( attr.nodeName, attr.nodeValue );
- // bye, bye input type="password"!
建立屏蔽和Bullets
到这里,当你定义$(elem).hoverpass()时候,它会变成一个monospaced的文本输入框。很是酷吧?可是咱们须要的不只仅是这些。
如今咱们将建立咱们本身的Bullets容器。这俩行惟一有意思的地方是jQuery元素的再次缓存。你应该使用这个小技巧:
- // let the game begin var maskHTML = '<div class="hpMask" style="position:
- absolute; cursor: text; height: 1px; font-family: ' + font + ' ; ' + free + ' " />';
- //our container with his styling var maskContainer = input.before(maskHTML).prev();
- // appending our container for bullets with styling (font-family, free)
如今咱们准备咱们的bullets HTML,由于它将被使用几回,而且当咱们有一个"数值"定义时添加一些bullets。
- var bulletHTML = "<span class='hpBullet' style='background: " + bg +
- "; " + freeBul + " '>"+ bullet + " </span> "; // our bullets HTML
- with styling (bg, freeBull)
- var countBullet = 0;
- // this is our counter, it is important to prevent
- our mask to get bigger / smaller than our input or its maximum size
- //since we use it from different places, it's better to add it via function
- function addBullet() {
- // add our last bullet, but hidden,
- and show anything that isn't last bullet
- lastBul = maskContainer.append(bulletHTML).find(":last-child").hide();
- maskContainer.find(":not(:last-child)").each( function(){
- lastBul.delay(delay).fadeIn(animation);
目前为止你能够又看到一个文本框,但若是你有一个value属性定义,你将看到不少bullets而且最后一个一妙后淡出。可是若是你输入,没有任何效果。
开始编写键盘输入
咱们须要每次在密码框输入过程当中添加bullets,而且在使用delete或者backspace键时删除一个bullet.
这里咱们使用keypress, keyup和keydown来实现。
咱们须要考虑一下使用keydown和keypress(由于它们很类似)咱们绑定"按下按键",使用keyup绑定"释放按键。再仔细一点,你会发如今这个例子里,keydown/keypress将会在咱们在字段内容有任何变化以前被调用,而keyup将会在任何变化发生后被调用。
这就是为何咱们使用keyup。咱们必须查看控件内容而且看是否内容改变了大小,以此判断是否添加和删除bullets。这里由于咱们须要照料到用户选择某一部分密码,或者在密码起始处按删除键,以及其它比较困难绑定行为的操做。
- //let's bind all keydown and create
- we need do use keydown in order to detect special characters in non-gecko browsers input.keyup(
- //check if something was really typed
- if (input[0].value.length > countBullet) {
- } else { //ooops, delete or backspace?
- //then we check if something was really deleted
- while (input[0].value.length < countBullet) {
- maskContainer.find(":last-child").remove();
最后,鼠标悬浮显示密码
如今咱们须要在用户鼠标悬浮时隐藏咱们的bullet。看起来挺简单的?其实否则。
由于咱们必须隐藏咱们的bullet,可是咱们不能丢失宽度,由于咱们若是丢了,咱们用户将看到仅仅密码最后一个字符(不是中间字符)。咱们能作到的是将它淡出到一个不明显的透明(大概10%)而后将高度改成1px,这样咱们还有宽度。
如今咱们只须要使用elem.hover()就能够了吧?答案是否认的。由于咱们有动态产生的内容,咱们须要使用live()或者delegate()来绑定。我测试结果是delegate的效果更好,所以咱们能够这样:
- //hide bullets based on a jquery object
- function hideBullets(object) {
- object.stop().css({ "height":
- "auto"}).animate({ opacity: 1 },
- animation).removeClass("hpHiddenBullet");
- //hover function for our bullets
- maskContainer.delegate(".hpBullet", 'hover',
- if ( item.hasClass("hpHiddenBullet") != true ) {
- hideBullets( $(".hpHiddenBullet") );
- item.stop().addClass("hpHiddenBullet").animate( { opacity: 0.01},
- animation, function() { item.css({ "height": "1px"}); } );
- if ( item.hasClass("hpHiddenBullet") == true ) {
但愿你们能喜欢这个效果,若是你有更好的实现,请和GBTAG分享。谢谢!
原文连接:http://www.gbtags.com/gb/share/5827.htm