jQuery实现的一个自定义Placeholder属性插件


Posted in Javascript onAugust 11, 2014

HTML5中文本框的新属性placeholder是个非常好用的属性,但是IE系列直至IE9都不支持这一属性,这就让大家在用这一属性的时候有些犹豫不决。自己曾经写过很多类似共的小控件,但是都不是很通用,这里分享一个渐进增强的自定义placeholder的jQuery插件。有点是使用简单,大家也可以根据自己的需要进行改进。平常写jQuery插件比较少,考虑到用jQuery的同学比较多,这里就用jQuery插件的形式编写了。

在这里简单的介绍一下实现思路。

1.表现与html5原生的placeholder尽量类似
2.渐进增强对于支持placeholder的浏览器不做处理

一、首先是几个工具方法:

1.supportProperty(nodeType, property),获取浏览器是否支持某一控件的某一属性
2.getPositionInDoc(target, parent),获取对象在文档中的位置
3.$c,一个快速创建Dom对象的方法

这几个工具方法都是一些比较常见通用的方法,如果你有自己的或者更合适的可以自行替换。

二、主体,CustomPlaceholder对象。这个对象主要是维护每一个文本框的信息,包括其位置,应该显示的提示信息等等,另外它还包含创建提示信息以及定位等方法以及对象的相应事件。

事件主要是在initEvents函数中进行的处理,这里特别要注意的是对提示信息事件的处理,当提示信息被点击时焦点应该被重新定位到文本框。而文本框要处理的则是focus和blur事件。

$(self.hint).bind( 'click', function(e){

 self.input.focus();

});
$(self.input).bind( 'focus', function(e){

 self.hint.style.display = 'none';

});
$(self.input).bind( 'blur', function(e){

 if(this.value == ''){

  self.hint.style.display = 'inline';

 }

});

CustomPlacehodler对象的两个主要方法是createHintLabel(text, position)和position()。createHintLabel是用于创建提示信息的DOM对象并对其进行定位,并返回这个对象。position方法用于强制对提示消息进行重新定位。主要用于页面大小改变的情况。这两个方法的功能和实现都比较简单。

三、插件的功能实现部分。jQuery插件实现方式就不多说了。这里首先进行了能力检测,如果原生支持placeholder则直接返回。

if(supportProperty('input', 'placeholder')){

 return;

}

接下来是根据选择的input对象,生成相应的CustomPlaceholder对象,保存在数组中,并获取每个对象的提示信息的DOM对象,添加到容器中,最后将容器附加到body对象中。

var customPlaceholders = [];

if(this.length > 0){

 var box = $c('div', 'dk_placeholderfixed_box');

 for(var i = 0, len = this.length; i < len; i++){

  var input = this[i];

  customPlaceholders.push(new CustomPlaceholder(box, input, option));

 }
 document.body.appendChild(box);

}

最后还有一件比较重要的事情,为window对象绑定resize事件,当window对象触发resize事件时对所有的customPlacehoder对象进行重新定位。

$(window).bind( 'resize', function(e){

 for(var i = 0, len = customPlaceholders.length; i < len; i++){

  var customPlaceholder = customPlaceholders[i];

  customPlaceholder.position();

 }
});

这个简单的小插件到这里就写完了。

插件源码:

(function($){

var eles = {
	div: document.createElement('div'),
	ul: document.createElement('ul'),
	li: document.createElement('li'),
	span: document.createElement('span'),
	p: document.createElement('p'),
	a: document.createElement('a'),
	fragment: document.createDocumentFragment(),
	input: document.createElement('input')
}
	
var supportProperty = function(nodeType, property){
	switch(arguments.length){
		case 0:
			return false;
		case 1:
			var property = nodeType, nodeType = 'div';
			property = property.split('.');
			
			if(property.length == 1){
				return typeof eles[nodeType][property[0]] !== 'undefined';
			}else if(property.length == 2){
				return typeof eles[nodeType][property[0]][property[1]] !== 'undefined';
			}
		case 2:
			property = property.split('.');
			
			if(property.length == 1){
				return typeof eles[nodeType][property[0]] !== 'undefined';
			}else if(property.length == 2){
				return typeof eles[nodeType][property[0]][property[1]] !== 'undefined';
			}
			
			return false;
			
			
		default:
			return false;
	}
};

var getPositionInDoc = function(target, parent) {
	if (!target) {
		return null;
	}
	var left = 0,
		top = 0;
	do {
		left += target.offsetLeft || 0;
		top += target.offsetTop || 0;
		target = target.offsetParent;
		if(parent && target == parent){
			break;
		}
	} while (target);
	return {
		left: left,
		top: top
	};
}

var $c = function(tagName, id, className){
	var ele = null;
	if(!eles[tagName]){
		ele = eles[tagName] = document.createElement(tagName);
	}else{
		ele = eles[tagName].cloneNode(true);
	}
	if(id){
		ele.id = id;
	}
	if(className){
		ele.className = className;
	}
	return ele;
};
	
var CustomPlaceholder = function(box, input, option){
	var self = this;
	var position = getPositionInDoc(input);
	self.input = input;
	
	self.option = {xOffset:0, yOffset:0};
	for(var item in option){
		self.option[item] = option[item];
	}
	self.hint = self.createHintLabel(input.getAttribute('placeholder'), position);
	box.appendChild(self.hint);
	
	self.initEvents = function(){
		$(self.hint).bind( 'click', function(e){
			self.input.focus();
		});
		
		$(self.input).bind( 'focus', function(e){
			self.hint.style.display = 'none';
		});
		
		$(self.input).bind( 'blur', function(e){
			if(this.value == ''){
				self.hint.style.display = 'inline';
			}
		});
	};
	
	self.initEvents();
};

CustomPlaceholder.prototype = {
	createHintLabel: function(text, position){
		var hint = $c('label');
		hint.style.cusor = 'text';
		hint.style.position = 'absolute';
		hint.style.left = position.left + this.option.xOffset + 'px';
		hint.style.top = position.top + this.option.yOffset + 'px';
		hint.innerHTML = text;
		hint.style.zIndex = '9999';
		return hint;
	},
	position: function(){
		var position = getPositionInDoc(this.input);
		this.hint.style.left = position.left + this.option.xOffset + 'px';
		this.hint.style.top = position.top + this.option.yOffset + 'px';
	}
};

$.fn.placeholder = function(option){
	if(supportProperty('input', 'placeholder')){
		return;
	}
	var customPlaceholders = [];
	if(this.length > 0){
		var box = $c('div', 'dk_placeholderfixed_box');
		for(var i = 0, len = this.length; i < len; i++){
			var input = this[i];
			if($(input).is(':visible')){
				customPlaceholders.push(new CustomPlaceholder(box, input, option));
			}
		}
		
		document.body.appendChild(box);
	}
	
	$(window).bind( 'resize', function(e){
		for(var i = 0, len = customPlaceholders.length; i < len; i++){
			var customPlaceholder = customPlaceholders[i];
			customPlaceholder.position();
		}
		
	});
};

})(jQuery);
Javascript 相关文章推荐
javascript demo 基本技巧
Dec 18 Javascript
jquery的键盘事件修改代码
Feb 24 Javascript
JS完整获取IE浏览器信息包括类型、版本、语言等等
May 22 Javascript
jQuery中大家不太了解的几个方法
Mar 04 Javascript
详解Jquery实现ready和bind事件
Apr 14 Javascript
D3.js实现散点图和气泡图的方法详解
Sep 21 Javascript
Vue实现动态显示textarea剩余字数
May 22 Javascript
Angular4如何自定义首屏的加载动画详解
Jul 26 Javascript
vue学习教程之带你一步步详细解析vue-cli
Dec 26 Javascript
基于vue,vue-router, vuex及addRoutes进行权限控制问题
May 02 Javascript
Vue 幸运大转盘实现思路详解
May 06 Javascript
Ant design vue table 单击行选中 勾选checkbox教程
Oct 24 Javascript
javascript中解析四则运算表达式的算法和示例
Aug 11 #Javascript
javascript实现的平方米、亩、公顷单位换算小程序
Aug 11 #Javascript
jquery访问ashx文件示例代码
Aug 11 #Javascript
jQuery实现的一个tab切换效果内部还嵌有切换
Aug 10 #Javascript
JavaScript动态改变HTML页面元素例如添加或删除
Aug 10 #Javascript
网页运行时提示对象不支持abigimage属性或方法
Aug 10 #Javascript
js中直接声明一个对象的方法
Aug 10 #Javascript
You might like
PHP中的加密功能
2006/10/09 PHP
php数组函数序列之in_array() 查找数组值是否存在
2011/10/29 PHP
浅谈php扩展imagick
2014/06/02 PHP
php解决抢购秒杀抽奖等大流量并发入库导致的库存负数的问题
2014/06/19 PHP
PHP中变量引用与变量销毁机制分析
2014/11/15 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
PHP匿名函数(闭包函数)详解
2019/03/22 PHP
php生成微信红包数组的方法
2019/09/05 PHP
用js的for循环获取radio选中的值
2013/10/21 Javascript
js获取对象、数组的实际长度,元素实际个数的实现代码
2016/06/08 Javascript
BootStrap Progressbar 实现大文件上传的进度条的实例代码
2016/06/27 Javascript
JavaScript实现拖拽元素对齐到网格(每次移动固定距离)
2016/11/30 Javascript
javascript数组去重方法分析
2016/12/15 Javascript
微信小程序 下拉列表的实现实例代码
2017/03/08 Javascript
nodejs实现OAuth2.0授权服务认证
2017/12/27 NodeJs
简单分析js中的this的原理
2019/08/31 Javascript
JS实现盒子拖拽效果
2020/02/06 Javascript
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
2020/10/31 Javascript
在Python中使用列表生成式的教程
2015/04/27 Python
Ruby使用eventmachine为HTTP服务器添加文件下载功能
2016/04/20 Python
在Python中分别打印列表中的每一个元素方法
2018/11/07 Python
浅析Django中关于session的使用
2019/12/30 Python
关于Keras Dense层整理
2020/05/21 Python
Python中的特殊方法以及应用详解
2020/09/20 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
Python修改DBF文件指定列
2020/12/19 Python
CSS3教程:新增加的结构伪类
2009/04/02 HTML / CSS
会计自荐书
2013/12/02 职场文书
初中音乐教学反思
2014/01/12 职场文书
信访稳定工作汇报
2014/10/27 职场文书
小学同学聚会感言
2015/07/30 职场文书
严以用权学习心得体会
2016/01/12 职场文书
创业分两种人:那么哪些适合创业?,哪些适合不适合创业呢?
2019/08/23 职场文书
如何将numpy二维数组中的np.nan值替换为指定的值
2021/05/14 Python
CSS三大特性继承性、层叠性和优先级详解
2022/01/18 HTML / CSS