原文链接:http://www.gbtags.com/gb/share/5827.htm
我们前面曾经介绍过如何提高用户界面表单性能,同时我们也介绍过如何避免使用密码框来避免隐藏输入的密码,也讨论过隐藏密码显示对于用户体验将有多么糟糕。
基本上对于密码输入处理我们有如下俩个可选方式:
- 继续使用密码框控件,不考虑用户的操作体验
- 使用一般的输入框,不考虑用户密码的安全性
这就是为什么我们这里需要开发一个鼠标悬浮可显示密码的控件作为第三选择的原因,既可以提高安全,同时也可以大大满足用户体验
今天将讲解如何使用jQuery插件来完成上述功能,同时让大家了解更多jQuery插件开发,动态内容显示,及其代码开发的最佳实践。
这里我们将仿效一些移动设备的界面设计方式,我们将能看到最后一个输入的字符。废话不说,我们现在开始!
用户体验背景
在我们正式开发代码前,我们最好先了解为什么我们开发这些功能。这个功能完全是为了用户体验而设计的,并且是为了让用户体验能达到极致。
最初开始讨论屏蔽用户密码问题的人是Jakob Nielsen,在初在他的"停止使用密码屏蔽"文章中,他表达了对于密码屏蔽的观点。 有时候我们可能在一些可疑的人周围,他们正寻找一切可能的机会来获取我们的密码。但是有时候,我们则不需要应付这样糟糕的情况。
理想情况下我们需要能够同时应付最好的和最坏的场景。不管使用IE6还是chrome14.0.803.2Beta等浏览器。我们都希望能做的最好。
以上就是为什么我们不想让密码缺省就被设置为屏蔽的主要原因。实际上我们应该提供给我们用户一个更好的选择。
代码开发
我们需要做的是得到一个一般的密码控件,然后把它转化成文字,再在其上创建一个覆盖层,这个在你输入过程中会自动覆盖。使用这个方法你可以屏蔽任何内容而不用影响本身的输入内容。以下图片很好的解释了这一切:
现在我们开始正式编写代码。
我们首先开始一个基本的表单标签。很简单只有2个控件,一个有缺省的数值,另外一个是空白的,用来显示你需要的东西。
- <div id="container">
- <h1>Sign Up!</h1>
- <form action="#" method="get">
- <label>
- <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." />
- </label>
- <label>
- <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" />
- </label>
- </form> </div>
然后我们调用jQuery和插件文件,如下:
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
- // call jQuery from google!
- </script>
- <script type="text/javascript" src="jquery.hp.js">
- // call plugin </script>
以下我们创建我们基本的插件文件。你可以参考我们的jQuery Smooth Table of Contents Plugin,这里我们使用一个非常简单的结构:
- (function($) {
- $.fn.hoverpass = function(options) {
- //Our default options
- var defaults = {
- bullet: "•",
- //which should be the "masking" character
- font: "‘Lucida Console‘, monospace",
- //please just use MONOSPACE fonts
- bg: "#fff",
- // background style for bullets
- free: "",
- // 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() {
- //our action goes here
- });
- };
- })
- (jQuery);
以上我们定义了缺省的参数,接下来我解释一下:
- 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,
- font = options.font,
- bg = options.bg,
- free = options.free,
- freeBul = options.freeBul,
- delay = options.delay,
- delayHover = options.delayHover,
- animation = options.animation,
- lastBul = "";
- //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++){
- attr = attrs.item(i)
- if (attr.nodeName != "type" && attr.nodeName != "style") {
- //well, we defined our type as text and font-style!
- input.attr( attr.nodeName, attr.nodeValue );
- }
- }
- oldElement.remove();
- // 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(){
- $(this).show(); } );
- //start timer to show
- lastBul
- lastBul.delay(delay).fadeIn(animation);
- countBullet++; }
目前为止你可以又看到一个文本框,但如果你有一个value属性定义,你将看到很多bullets并且最后一个一妙后淡出。但是如果你输入,没有任何效果。
开始编写键盘输入
我们需要每次在密码框输入过程中添加bullets,并且在使用delete或者backspace键时删除一个bullet.
这里我们使用keypress, keyup和keydown来实现。
我们需要考虑一下使用keydown和keypress(因为它们很相似)我们绑定"按下按键",使用keyup绑定"释放按键。再仔细一点,你会发现在这个例子里,keydown/keypress将会在我们在字段内容有任何变化之前被调用,而keyup将会在任何变化发生后被调用。
这就是为什么我们使用keyup。我们必须查看控件内容并且看是否内容改变了大小,以此判断是否添加和删除bullets。这里因为我们需要照料到用户选择某一部分密码,或者在密码起始处按删除键,以及其它比较困难绑定行为的操作。
- //let‘s bind all keydown and create
- / remove our bullets ;
- we need do use keydown in order to detect special characters in non-gecko browsers input.keyup(
- function(event) {
- //check if something was really typed
- if (input[0].value.length > countBullet) {
- addBullet();
- } else { //ooops, delete or backspace?
- //then we check if something was really deleted
- while (input[0].value.length < countBullet) {
- maskContainer.find(":last-child").remove();
- countBullet--;
- }
- }
- } );
最后,鼠标悬浮显示密码
现在我们需要在用户鼠标悬浮时隐藏我们的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‘,
- function(){
- var item = $(this);
- if ( item.hasClass("hpHiddenBullet") != true ) {
- hideBullets( $(".hpHiddenBullet") );
- item.stop().addClass("hpHiddenBullet").animate( { opacity: 0.01},
- animation, function() { item.css({ "height": "1px"}); } );
- setTimeout( function() {
- if ( item.hasClass("hpHiddenBullet") == true ) {
- hideBullets( item );
- }
- }, delayHover);
- }
- }
- );
希望大家能喜欢这个效果,如果你有更好的实现,请和GBTAG分享。谢谢!
原文链接:http://www.gbtags.com/gb/share/5827.htm