IE 10, 11. 如何防止使用占位符的文本输入触发焦点输入事件?
Posted
技术标签:
【中文标题】IE 10, 11. 如何防止使用占位符的文本输入触发焦点输入事件?【英文标题】:IE 10, 11. How to prevent the triggering of input events on focus from text input with placeholder? 【发布时间】:2018-06-16 18:10:19 【问题描述】:在 IE 11 中,如果我有一封带有 placeholder
的空电子邮件 input
,然后单击(聚焦)它,就会触发 input
事件。
由于input
的值并没有真正改变,有人知道原因吗?是否有解决方案?
var el = document.getElementById('myEmail');
el.addEventListener("input", myFunction, true);
function myFunction()
alert("changed");
<input id="myEmail" type="email" placeholder="Email">
【问题讨论】:
请参阅 my explanation with very short solution 并将我的答案设置为已接受 - 所以所有用户都可以从我的正确答案中受益。 【参考方案1】:这似乎是一个错误。 oninput
已被支持,因为 IE9 仅应在值更改时触发。另一种方法是使用onkeyup
https://developer.mozilla.org/en-US/docs/Web/Events/input
如果您想处理输入和验证,您只需添加第二个事件监听器(假设您的 html 与上面相同)。
var el = document.getElementById('myEmail');
function myFunction()
console.log("changed");
el.addEventListener("keyup", myFunction, true);
function validation()
console.log("validated");
el.addEventListener("keyup", validation, true);
【讨论】:
嗯。不能采用这种方法,因为我正在使用依赖于输入事件的验证库。验证应该发生在输入事件上,但在 IE 11 中它发生在焦点上 onchange 事件怎么样? onchange 仅在聚焦后触发。我需要“输入”事件,因为在您键入时需要进行验证 为什么不在keyup上添加多个事件监听器。我会更新我的答案。【参考方案2】:我参加聚会很晚,但我遇到了同样的问题,我想出了一个解决方法来解决 IE 上的这种行为。 事实上,有两个不同的错误(或者更确切地说,只有一个错误但有两种行为,具体取决于目标是输入还是文本区域)。
对于input
:每次字段的可视内容发生变化时都会触发该事件,包括键盘输入(自然)、占位符出现/消失(无内容时模糊)或可见占位符时以编程方式更改。
对于textarea
:基本相同,只是占位符消失时不触发事件。
function onInputWraper(cb)
if (!window.navigator.userAgent.match(/MSIE|Trident/)) return cb;
return function (e)
var t = e.target,
active = (t == document.activeElement);
if (!active || (t.placeholder && t.composition_started !== true))
t.composition_started = active;
if ((!active && t.tagName == 'TEXTAREA') || t.tagName == 'INPUT')
e.stopPropagation();
e.preventDefault();
return false;
cb(e);
;
var el = document.getElementById('myEmail');
el.addEventListener("input", onInputWraper(myFunction), true);
function myFunction()
alert("changed");
<input id="myEmail" type="email" placeholder="Email">
还有一个完整的示例,您还可以在其中更改占位符值
function onInputWraper(cb)
if (!window.navigator.userAgent.match(/MSIE|Trident/)) return cb;
return function (e)
var t = e.target,
active = (t == document.activeElement);
if (!active || (t.placeholder && t.composition_started !== true))
t.composition_started = active;
if ((!active && t.tagName == 'TEXTAREA') || t.tagName == 'INPUT')
e.stopPropagation();
e.preventDefault();
return false;
cb(e);
;
function handle(event)
console.log('EVENT', event);
document.getElementById('output')
.insertAdjacentHTML('afterbegin', "<p>" + event.type + " triggered on " + event.target.tagName +
'</p>');
var input = document.getElementById('input'),
textarea = document.getElementById('textarea');
input.addEventListener('input', onInputWraper(handle));
textarea.addEventListener('input', onInputWraper(handle));
// input.addEventListener('input', handle);
// textarea.addEventListener('input', handle);
// Example's settings
function removeListeners(elem)
var value = elem.value,
clone = elem.cloneNode(true);
elem.parentNode.replaceChild(clone, elem);
clone.value = value;
return clone;
document.querySelector('#settings input[type="checkbox"]').addEventListener('change', function (event)
if (event.target.checked)
document.getElementById('output').insertAdjacentHTML('afterbegin', '<p>Filter enabled !</p>');
//input = removeListeners(input);
console.log(input.value.length, (input == document.activeElement));
input = removeListeners(input);
input.addEventListener('input', onInputWraper(handle));
input.composing = input.value.length > 0 || (input == document.activeElement);
textarea = removeListeners(textarea);
textarea.addEventListener('input', onInputWraper(handle));
textarea.composing = textarea.value.length > 0 || (textarea == document.activeElement);
else
document.getElementById('output').insertAdjacentHTML('afterbegin', '<p>Filter disabled !</p>');
input = removeListeners(input);
input.addEventListener('input', handle);
input.composing = void 0;
textarea = removeListeners(textarea);
textarea.addEventListener('input', handle);
textarea.composing = void 0;
);
document.getElementById('input_cfg').addEventListener('click', function ()
document.getElementById('input').setAttribute('placeholder', document.getElementById(
'input_placeholder').value);
);
document.getElementById('textarea_cfg').addEventListener('click', function ()
document.getElementById('textarea').setAttribute('placeholder', document.getElementById(
'textarea_placeholder').value);
);
*
font: 15px arial, sans-serif;
dd
background: FloralWhite;
margin: 0;
dt
padding: 15px;
font-size: 1.2em;
background: steelblue;
color: AntiqueWhite;
p
margin: 0;
button,
label
width: 300px;
margin: 5px;
padding: 5px;
float: left;
color: DarkSlateGray;
#settings label
width: 100%;
margin: 15px;
#forms input,
#forms textarea,
#settings input:not([type])
display: block;
width: calc(100% - 340px);
padding: 7px;
margin: 0;
margin-left: 320px;
min-height: 25px;
border: 1px solid gray;
background: white;
cursor: text;
::placeholder
/* Chrome, Firefox, Opera, Safari 10.1+ */
color: LightBlue;
opacity: 1;
/* Firefox */
::-ms-input-placeholder
/* Microsoft Edge */
color: LightBlue;
:-ms-input-placeholder
/* Internet Explorer 10-11 */
color: LightBlue;
<dl>
<dt>Forms</dt>
<dd id="forms">
<label for="input">Input: </label>
<input id="input" name="input" class="testing" placeholder="Type some text" />
<label for="texarea">Textarea: </label>
<textarea id="textarea" name="textarea" placeholder="Type some text"></textarea>
</dd>
<dt>Settings</dt>
<dd id="settings">
<p>
<label><input type="checkbox" checked>Enable filtering script</label>
<button id="input_cfg">Change input's placeholder to</button><input id="input_placeholder" />
</p>
<p>
<button id="textarea_cfg">Change textarea's placeholder to</button>
<input id="textarea_placeholder" />
</p>
</dd>
<dt>Output</dt>
<dd id="output"></dd>
</dl>
or on jsfiddle
【讨论】:
这行得通。感谢您的解决方案和解释【参考方案3】:解决方案很短!
起初,我们不需要在接受的答案中看到的那么多代码。其次,您必须了解它发生的原因:
-
假
oninput
事件仅在具有placeholder
获得焦点的输入上且仅当输入值为空时才会触发。这是因为IE的坏开发者认为输入值从placeholder value
变为真正的value
,但这是来自IE的坏开发者的误解。
没有占位符的input
不会有这个问题。
第一个解决方案非常简单:如果您真的不需要它,请不要使用placeholder
。在大多数情况下,您可以将title
添加到元素而不是placeholder
。您也可以在input
之前、下方或上方写下您的placeholder
文本。
如果你必须使用placeholder
第二个解决方案也非常简单和简短:将之前的value
保存在input
对象上,并将其与新的value
进行比较——如果没有更改,则在代码之前的函数中return
.
生活实例
var input = document.querySelector('input[type=search]');
input.addEventListener('input', function(e)
if(this.prevVal == this.value /* if the value was not changed */
|| !this.prevVal && '' == this.value) //only for the first time because we do not know the previous value
return; //the function returns "undefined" as value in this case
this.prevVal = this.value;
//YOUR CODE PLACE
console.log('log: ' + this.value)
, false);
<input type="search" placeholder="Search..."/>
或者,如果您将其用作内联 JavaScript:
function onSearch(trg)
if(trg.prevVal == trg.value /* if the value was not changed */
|| !trg.prevVal && '' == trg.value) //only for the first time because we do not know the previous value
return; //the function returns "undefined" as value in this case
trg.prevVal = trg.value; // save the previous value on input object
//YOUR CODE PLACE
console.log('log: ' + trg.value);
<input type="search" placeholder="Search..." oninput="onSearch(this)"/>
【讨论】:
以上是关于IE 10, 11. 如何防止使用占位符的文本输入触发焦点输入事件?的主要内容,如果未能解决你的问题,请参考以下文章
在 Edge 浏览器上,如何使用 CSS 更改输入占位符文本颜色?