javascript 文本框水印/占位符(watermark/placeholder)实现方法


Posted in Javascript onJanuary 15, 2012

Firefox/Chrome/Opera从某一版本开始已经支持这一特性,但ie系列即使是ie9也还不支持,所以需要通过javascript来兼容这些不支持placeholder特性的浏览器。

普遍的做法
现在普遍使用的做法是通过表单元素的onfocus/onblur事件来改变value值,如下:

<input type="text" id="text1" /> 
<script> 
var el = document.getElementById("text1"); 
if (el.value == "") 
el.value = "提示信息"; el.onfocus = function() { 
if (this.value == "提示信息") 
this.value = ""; 
}; 
el.onblur = function() { 
if (this.value == "") 
this.value = "提示信息"; 
} 
</script>

jQuery的各个watermark插件(http://archive.plugins.jquery.com/plugin-tags/watermark)大都是采用这种做法,可能还会有设置一些样式等操作。

这种做法直接操作表单元素,方便快捷,比较实用。

但它也有弊端:

有些操作同样需要通过监听表单元素的value值来实现功能,比如:autocomplete、验证等
表单提交时需要清空它的值
当然可能还有其他弊端,这里不再列举。

更好的做法
为了避免引起不必要的麻烦,就要避免去改变表单元素的value值。

首先,假如有如下一个文本框:

<input type="text" />

既然不能改变文本框的值,那么只能通过添加一个span或其他元素,并通过绝对定位放置到文本框之上,并在外框加一个position:relative的容器来包装它们以保证提示信息不会产生偏移,如:

<span style="position:relative;"> 
<span style="position:absolute;">提示信息</span> 
<input type="text" /> 
</span>

无意中发现淘宝的登录页面并不需要额外加一层position:relative的容器来包装也不会产生偏移,所以仅需要把提示信息的标记放在文本框之前即可,如下:

<span style="position:absolute;">提示信息</span> 
<input type="text" />

这样子产生的标记更加简洁。
相应的样式
既然最终呈现的标记已经确定,那么现在就需要定义相应的样式,来使它看起来更美观,如下:
/* 标记的主要样式 style */ 
.w-label { 
position: absolute; 
padding: 0 0 0 6px; 
margin: 0; 
font-size: .8em; 
color: #999; 
opacity: 1; 
} 
/* 隐藏标记 */ 
.w-hide { 
visibility: hidden; 
opacity: 0; 
} 
/* 表单元素获得焦点时,标记的颜色 */ 
.w-active { 
color: #ddd; 
}

那么html就相应的变成:
<span class="w-label">提示信息</span> 
<input type="text" />

相关的脚本
虽然不需要去改变表单元素的value值来实现效果,但还是需要通过onfocus/onblur事件来控制提示信息的标记,全部实现如下:
/* 事件绑定 */ 
var addEvent = document.addEventListener ? 
function(element, type, fn) { 
element.addEventListener(type, fn, false); 
} : 
function(element, type, fn) { 
element.attachEvent("on" + type, fn); 
}, 
/* 事件解除绑定 */ 
removeEvent = document.removeEventListener ? 
function(element, type, fn) { 
element.removeEventListener(type, fn, false); 
} : 
function(element, type, fn) { 
element.detachEvent("on" + type, fn); 
}, 
/* 文本框水印/占位符 */ 
watermark = function(element, text) { 
if (!(this instanceof watermark)) 
return new watermark(element, text); 
var place = document.createElement("span");//提示信息标记 
element.parentNode.insertBefore(place, element);//插入到表单元素之前的位置 
place.className = "w-label"; 
place.innerHTML = text; 
place.style.height = place.style.lineHeight = element.offsetHeight + "px";//设置高度、行高以居中 
element.place = this; 
function hideIfHasValue() { 
if (element.value && place.className.indexOf("w-hide") == -1) 
place.className += " w-hide"; 
} 
function onFocus() { 
hideIfHasValue() 
if (!element.value && place.className.indexOf("w-active") == -1) 
place.className += " w-active"; 
} 
function onBlur() { 
if (!element.value) { 
place.className = place.className.replace(" w-active", ""); 
place.className = place.className.replace(" w-hide", ""); 
} 
} 
function onClick() { 
hideIfHasValue(); 
try { 
element.focus && element.focus(); 
} catch (ex) {} 
} 
// 注册各个事件 
hideIfHasValue(); 
addEvent(element, "focus", onFocus); 
addEvent(element, "blur", onBlur); 
addEvent(element, "keyup", hideIfHasValue); 
addEvent(place, "click", onClick); 
// 取消watermark 
this.unload = function() { 
removeEvent(element, "focus", onFocus); 
removeEvent(element, "blur", onBlur); 
removeEvent(element, "keyup", hideIfHasValue); 
removeEvent(place, "click", onClick); 
element.parentNode.removeChild(place); 
element.place = null; 
}; 
};

以上代码分别通过表单元素的focus/blur/keyup事件来控制提示信息标记的显示、隐藏及样式;另外还通过提示信息标记的click事件来隐藏它及为表单元素获得焦点。
最后提供一个unload方法来取消watermark。
具体使用
有了以上的js及css,那么就可以直接使用它们来实现watermark功能了,如下演示应用及取消watermark:
<input id="text1" type="text" /> 
<input type="button" id="button1" value="取消watermark" /> 
<script> 
var m1 = watermark(document.getElementById("text1"), "提示信息"); 
addEvent(document.getElementById("button1"), "click", function() { 
m1.unload(); 
}); 
</script>

html5 placeholder兼容
既然有了以上的实现,那么兼容不支持html5 placeholder的浏览器也很简单,首先,需要判断浏览器是否支持placeholder:
var html5support = "placeholder" in document.createElement("input");

接着,对不支持html5 placeholder的浏览器,提取表单元素的placeholder内容,实现如下:
placeHolderForm = function(form) { 
var ph, elems = form.elements, 
html5support = "placeholder" in document.createElement("input"); 
if (!html5support) { 
for (var i = 0, l = elems.length; i < l; i++) { 
ph = elems[i].getAttribute("placeholder"); 
if (ph) elems[i].ph = watermark(elems[i], ph); 
} 
} 
}

演示代码如下:
<form id="form2"> 
<fieldset> 
<legend><strong>对不支持html5 placeholder的表单元素应用watermark</strong></legend> 
<ul> 
<li> 
文本框: 
<input type="text" placeholder="文本框文本框" /> 
</li> 
<li> 
密码框: 
<input type="password" placeholder="密码框密码框" /> 
</li> 
<li> 
多行文本: 
<textarea placeholder="多行文本多行文本"></textarea> 
</li> 
</ul> 
</fieldset> 
</form> 
<script> 
placeHolderForm(document.getElementById("form2")); 
</script>

结尾
至此,功能全部完成,放上全部代码:点击下载,如有额外需要可自行修改。
作者:?逶
出处:http://lwme.cnblogs.com/
Javascript 相关文章推荐
jquery实现的让超出显示范围外的导航自动固定屏幕最顶上
Sep 22 Javascript
JS版元素周期表实现方法
Aug 05 Javascript
JS遍历数组和对象的区别及递归遍历对象、数组、属性的方法详解
Jun 14 Javascript
聊一聊JS中this的指向问题
Jun 17 Javascript
jQuery 实现ajax传入参数含有特殊字符的方法总结
Oct 17 Javascript
基于JavaScript实现多级菜单效果
Jul 25 Javascript
重新认识vue之事件阻止冒泡的实现
Aug 02 Javascript
angularjs通过过滤器返回超链接的方法
Oct 26 Javascript
详解vue-cli 3.0 build包太大导致首屏过长的解决方案
Nov 10 Javascript
vue生命周期的探索
Apr 03 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
Jun 19 jQuery
Vue中Object.assign清空数据报错的解决方案
Mar 03 Vue.js
jQuery-Easyui 1.2 实现多层菜单效果的代码
Jan 13 #Javascript
20个最新的jQuery插件
Jan 13 #Javascript
JSON 数据格式介绍
Jan 13 #Javascript
ASP.NET jQuery 实例6 (实现CheckBoxList成员全选或全取消)
Jan 13 #Javascript
ASP.NET jQuery 实例5 (显示CheckBoxList成员选中的内容)
Jan 13 #Javascript
ASP.NET jQuery 实例4(复制TextBox的文本到本地剪贴板上)
Jan 13 #Javascript
ASP.NET jQuery 实例3 (在TextBox里面阻止复制、剪切和粘贴事件)
Jan 13 #Javascript
You might like
php中ltrim()、rtrim()与trim()删除字符空格实例
2014/11/25 PHP
[原创]PHP正则匹配中英文、数字及下划线的方法【用户名验证】
2017/08/01 PHP
thinkPHP框架乐观锁和悲观锁实例分析
2019/10/30 PHP
飞鱼(shqlsl) javascript作品集
2006/12/16 Javascript
js onpropertychange输入框 事件获取属性
2009/03/26 Javascript
使用jQuery.Validate进行客户端验证(初级篇) 不使用微软验证控件的理由
2010/06/28 Javascript
JavaScript将当前时间转换成UTC标准时间的方法
2015/04/06 Javascript
Nodejs中session的简单使用及通过session实现身份验证的方法
2016/02/04 NodeJs
JavaScript代码生成PDF文件的方法
2016/02/26 Javascript
JS实现兼容各种浏览器的高级拖动方法完整实例【测试可用】
2016/06/21 Javascript
完美实现八种js焦点轮播图(下篇)
2020/04/20 Javascript
怎样判断jQuery当前元素是隐藏还是显示
2016/11/23 Javascript
Node.js dgram模块实现UDP通信示例代码
2017/09/26 Javascript
高性能的javascript之加载顺序与执行原理篇
2018/01/14 Javascript
vue如何自动化打包测试环境和正式环境的dist/test文件
2019/06/06 Javascript
原生js实现弹窗消息动画
2020/11/20 Javascript
Python爬取Coursera课程资源的详细过程
2014/11/04 Python
python字典键值对的添加和遍历方法
2016/09/11 Python
详解Python with/as使用说明
2018/12/13 Python
pyinstaller打包多个py文件和去除cmd黑框的方法
2019/06/21 Python
解析Python3中的Import
2019/10/13 Python
基于TensorFlow常量、序列以及随机值生成实例
2020/01/04 Python
Django 设置admin后台表和App(应用)为中文名的操作方法
2020/05/10 Python
通过Python扫描代码关键字并进行预警的实现方法
2020/05/24 Python
通过代码实例了解Python3编程技巧
2020/10/13 Python
python os.listdir()乱码解决方案
2021/01/31 Python
美国最大的网上冲印店:Shutterfly
2017/01/01 全球购物
春秋航空官方网站:Spring Airlines
2017/09/27 全球购物
EJB的激活机制
2013/10/25 面试题
小学美术教学反思
2014/02/01 职场文书
计算机软件专业求职信
2014/06/10 职场文书
大学生毕业评语
2014/12/31 职场文书
幼儿园教师个人工作总结2015
2015/05/12 职场文书
入党积极分子党支部意见
2015/06/02 职场文书
创业计划书之美容店
2019/09/16 职场文书
golang三种设计模式之简单工厂、方法工厂和抽象工厂
2022/04/10 Golang