-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplaceholder与textarea的maxlength.html
169 lines (159 loc) · 6.62 KB
/
placeholder与textarea的maxlength.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>兼容input、textarea的占位符+maxlength及实时捕获用户输入</title>
<style>
*{margin:0;padding:0;}
p span{color:#f00;}
div{height:100px;}
input{border:1px solid #ccc;}
textarea{border:1px solid #ccc;}
#bigdiv{height:800px;}
#input{ime-mode:disabled;}
</style>
</head>
<body>
<div><input type="text" id="input" value="" placeholder="我这里只能输入数字" /></div>
<div><input type="email" id="email" value="" style="width:200px;" placeholder="email" /></div>
<div><input type="password" id="pass" value="" style="width:200px" placeholder="密码框" /></div>
<div><textarea id="tarea" placeholder="文本域" maxlength="10"></textarea></div>
<p>您还可以输入<span id="maxlen">10</span>个字符</p>
<script>
/**********************************************
@function IE6-9 placeholder与textarea的maxlength修复,并提供值改变时的回调函数供实时捕捉用户输入
fixed oncontextmenu delete or cut and backspace
@param id: 必选参数,元素的id
@param fn: 可选参数,实时响应的回调函数
@return 通过id获取的元素
@note 原理说明:IE6-9动态生成另一个一样的背景透明的输入框叠加到本输入框下层,通过selectionchange、onpropertychange事件与keyup等事件实现实时捕捉,现代谷歌火狐内核的浏览器直接支持placeholder与maxlength,这里用input事件实现了实时输入捕捉;
注意点:布局时应在要应用的表单元素父节点上进行相对定位
@inadequate 不足:影响了页面结构,未实现事件代理,动态元素必须先插入文档之后再执行此函数实现动态添加的元素placeholder与maxlength修复;IE6-9 onpropertychange也能捕捉到js设置输入框值改变的事件,但现代谷歌火狐内核的浏览器捕捉不到
*/
function iChange(id, fn){
//var obj = id.nodeType == 1 ? id : id.jQuery ? id[0] : document.getElementById(id),
var obj = id.nodeType == 1 ? id : document.getElementById(id);
var doc = obj.document || obj.ownerDocument || document,
win = doc.defaultView || doc.parentWindow || window,
inputClone = doc.createElement(obj.nodeName == 'INPUT' ? 'INPUT' : 'TEXTAREA'),
advancedBrowser = 'placeholder' in inputClone,
oldValAttr = 'oldvalue' + (+new Date());
if(advancedBrowser){
obj.addEventListener("input",function(e){
fn && fn.call(this, e);
},false);
}else{
//IE6-9
var docElem = doc.documentElement,
inpCloneStyle = inputClone.style,
placeholder = obj.getAttributeNode('placeholder'),
curstyle = obj.currentStyle,
objstyle = obj.style;
placeholder = placeholder ? placeholder.nodeValue : '';
if(placeholder){
//初始化inputClone
inpCloneStyle.cssText = objstyle.cssText + ';position:absolute;color:graytext;background-color:transparent;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent;';
inputClone.className = obj.className;
inputClone.disabled = true;
if(obj.value === '' || obj.defaultValue === ''){
inputClone.value = placeholder;
}
if(curstyle.position == 'static'){
objstyle.position = 'relative';
}else{
if(typeof curstyle.zIndex == 'number' && curstyle.zIndex > 0){
inpCloneStyle.zIndex = --curstyle.zIndex;
}else{
inpCloneStyle.zIndex = 0;
}
}
inpCloneStyle.left = obj.offsetLeft+'px';
inpCloneStyle.top = obj.offsetTop+'px';
obj[oldValAttr] = obj.value;
}
var IEwatchChange = function(e){
var e = win.event || e,
maxLen = obj.getAttributeNode('maxlength'),
maxLen = maxLen && parseInt(maxLen.nodeValue);
if(e.type == 'selectionchange' || e.propertyName == "value"){
var objVal = obj.value;
if(obj[oldValAttr] !== objVal){
if(placeholder){
if(objVal === '') inputClone.value = placeholder;
else inputClone.value = '';
}
//input的maxlength所有浏览器都支持,只有TEXTAREA不支持
if(maxLen && obj.nodeName == 'TEXTAREA' && objVal.length > maxLen){
obj.value = objVal.substring(0, maxLen);
}
obj[oldValAttr] = obj.value;
//两次直接改值会造成光标到开头位置的bug,方法一:延迟后调用回调;方法二:回调中使用正则匹配一遍后再执行赋值
fn && fn.call(obj, e);
/*setTimeout(function(){
fn && fn.call(obj, e);
}, 0);*/
}
}
};
if(!win.XMLHttpRequest){
//IE6无法聚焦修复
obj.attachEvent('onclick',function(){
obj.focus();
});
inputClone.attachEvent('onclick',function(){
obj.focus();
});
}
//现代型事件绑定
obj.attachEvent("onfocus", function(){
//主要解决IE9中oncontextmenu delete or cut and backspace事件在onpropertychange时不响应
document.attachEvent("onselectionchange", IEwatchChange);
});
obj.attachEvent("onpropertychange", IEwatchChange);
obj.attachEvent("onblur", function(){
document.detachEvent("onselectionchange", IEwatchChange);
});
//事件全部绑定后再插入,尽量减少对dom重复渲染
if(placeholder){
objstyle.backgroundColor = 'transparent';
//IE6,8,9 input在将输入框背景设成透明时无法聚焦bug修复
objstyle.backgroundImage = 'url(about:blank)';
obj.parentNode.insertBefore(inputClone, obj);
}
}
return obj;
}
//测试用例demo,所有浏览器都兼容
//纯数字输入框
iChange('input', function(e){
var oldVal = this.value;
this.value = oldVal.replace(/\D/g, '');
/*if(/\D/g.test(oldVal)){
this.value = oldVal.replace(/\D/g, '');
}*/
});
//实时响应用户输入,提示用户还能输入多少字符
var maxlen = document.getElementById('maxlen');
iChange(document.getElementById('tarea'), function(e){
maxlen.innerHTML = parseInt(this.getAttributeNode('maxlength').nodeValue) - this.value.length;
});
/*
//中文字符限制版:中文在谷歌和opera浏览器下会把输入的字符码直接输入到输入框,导致上面实时响应有负值的情况
var maxlenObj = document.getElementById('tarea'), maxLen = parseInt(maxlenObj.getAttributeNode("maxlength").nodeValue), counter = document.getElementById('maxlen');
iChange(maxlenObj, function(e){
var text = this.value || this.defaultValue || '', len = text.length,
overplus = maxLen - len;
if( overplus < 0 ){
this.value = text.slice(0, maxLen);
overplus = 0;
}
counter.innerHTML = overplus;
});
*/
//密码框测试
iChange('pass');
//低版本不支持type=email,number等类型的输入框测试
iChange('email');
</script>
</body>
</html>