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

  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/