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");
&lt;input id="myEmail" type="email" placeholder="Email"&gt;

还有一个完整的示例,您还可以在其中更改占位符值

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);
&lt;input type="search" placeholder="Search..."/&gt;

或者,如果您将其用作内联 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);
&lt;input type="search" placeholder="Search..." oninput="onSearch(this)"/&gt;

【讨论】:

以上是关于IE 10, 11. 如何防止使用占位符的文本输入触发焦点输入事件?的主要内容,如果未能解决你的问题,请参考以下文章

在 Edge 浏览器上,如何使用 CSS 更改输入占位符文本颜色?

输入占位符css在IE9中不起作用[重复]

IE10+ 上的 AngularJS,带有占位符的文本区域导致“无效参数”。

在 IE 中更改占位符文本的字体大小和边距

如何更改输入标签占位符的语言?

如何在资源管理器的文本区域中设置占位符的样式?