-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfocusin,focusout event proxy watch value.html
187 lines (181 loc) · 6.83 KB
/
focusin,focusout event proxy watch value.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>用focusin,focusout事件代理的实时捕捉</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 id="emailwrap"><input class="input" type="email" id="email" value="" style="width:200px;" placeholder="email" /><span id="sametxt"></span><input class="input" type="text" value="" style="width:100px;" 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>
/*var el = document.getElementById('btn');
var focusHandler = function (event) {
var e = event || window.event;
console.log(e, e.type, e.target, e.srcElement.nodeName);
};
var blurHandler = function (event) {
var e = event || window.event;
console.log(e, e.type, e.target, e.srcElement.nodeName);
};
if (document.addEventListener) { //如果是W3C的方式,就用捕获的机制(从父元素到目标元素),来实现冒泡的机制(从目标元素到父元素),这样父元素就能获得目标元素的focus和blur事件了
document.addEventListener('focus', focusHandler, true);
document.addEventListener('blur', blurHandler, true);
} else {
document.onfocusin = focusHandler; //IE不支持捕获阶段,但是支持focusin和focusout这两个事件,这两个事件本身就是冒泡的。因此父元素能获得目标元素的focus和blur事件
document.onfocusout = blurHandler;
}*/
</script>
<script>
/**********************************************
@function 用户实时输入捕捉的直接和代理实现
fixed oncontextmenu delete or cut and backspace
@param id: 必选参数,元素的id或dom对象
@param simpselector: 可选参数,id对应dom下的子元素简单选择器.class,将simpselector替换为fn回调函数就实现了重载,直接给元素添加添加捕捉实时输入事件
@param fn: 实时响应的回调函数
@return 通过id获取的元素
@note 原理说明:IE6-9通过focusein和focusout在输入框聚焦时绑定selectionchange、onpropertychange事件实现实时捕捉,更高级浏览器用事件捕获阶段绑定input事件
@inadequate 不足:IE9同一时刻可能会有双重事件执行,因为有可能propertychange与selectionchange事件一同发生
************************************************/
function watchVal(id, simpselector, fn){
var fn = fn || function(e){},
obj = /INPUT|TEXTAREA/i.test(id.nodeName) ? id : id.nodeName ? id : document.getElementById(id),
IE69 = !('placeholder' in document.createElement('INPUT')),
IE9 = IE69 && window.addEventListener,
simpselector = typeof simpselector === 'string' && simpselector.replace('.',''),
clazzReg = new RegExp('(\\s|^)' + simpselector +'(\\s|$)'),
testTarget = function(t){
return /INPUT|TEXTAREA/i.test(t.tagName) && clazzReg.test(t.className);
};
if(typeof simpselector === 'function'){
//实时输入的直接实现
fn = simpselector;
if(IE69){
var IEwatchChange = function(e){
var e = window.event;
if(e.type == 'selectionchange' || e.propertyName == "value"){
fn.call(obj, e);
}
}
obj.attachEvent("onfocus", function(e){
obj.attachEvent("onpropertychange", IEwatchChange);
});
obj.attachEvent("onblur", function(e){
obj.detachEvent("onpropertychange", IEwatchChange);
});
obj.detachEvent("onselectionchange", IEwatchChange);
}else{
obj.addEventListener("input", fn, false);
obj.addEventListener("drop", fn, false);
}
}else{
//实时输入的代理实现
if(IE69){
var IEwatchChange = function(){
var e = window.event, _this = null;
if(e.propertyName && e.propertyName == "value"){
_this = e.srcElement;
}else if(e.type == 'selectionchange'){
_this = document.activeElement;
}
//事件修复
e.target = _this;
fn.call(_this, e);
}
obj.attachEvent("onfocusin", function(e){
var e = window.event, t = e.srcElement;
if(testTarget(t)){
t.attachEvent("onpropertychange", IEwatchChange);
}
});
obj.attachEvent("onfocusout", function(e){
var e = window.event, t = e.srcElement;
if(testTarget(t)){
t.detachEvent("onpropertychange", IEwatchChange);
}
});
document.attachEvent("onselectionchange", function(){
var t = document.activeElement, e = window.event;
if(testTarget(t)){
e.target = t;
fn.call(t, e);
}
});
}else{
obj.addEventListener("focus", function(e){
var t = e.target;
if(testTarget(t)){
t.addEventListener("input", fn, false);
}
}, true);
obj.addEventListener("blur", function(e){
var t = e.target;
if(testTarget(t)){
t.removeEventListener("input", fn, false);
}
}, true);
document.addEventListener("drop", function(e){
var t = e.target;
if(testTarget(t)){
e.target = t;
fn.call(t, e);
}
}, false);
}
}
return obj;
}
//测试用例demo,所有浏览器都兼容
//纯数字输入框
watchVal('input', function(e){
var oldVal = this.value;
if(/\D/g.test(oldVal)){
console.dir(this);
this.value = oldVal.replace(/\D/g, '');
}
});
var sametxt = document.getElementById("sametxt");
/*watchVal(document.getElementById('emailwrap'), '.input', function(e){
console.dir(this);
var oldVal = this.value || this.defaultValue;
if(/\D/g.test(oldVal)){
this.value = oldVal.replace(/\D/g, '');
sametxt.innerHTML = this.value;
}
});*/
//实时响应用户输入,提示用户还能输入多少字符
var maxlen = document.getElementById('maxlen');
/*bind(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');
bind(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;
});
*/
//密码框测试
//bind('pass');
//低版本不支持type=email,number等类型的输入框测试
//bind('email');
</script>
</body>
</html>