IE 11文本输入,占位符触发焦点

时间:2018-01-07 15:53:45

标签: javascript html focus internet-explorer-11 placeholder

在IE 11中,如果我有一个带占位符的空电子邮件输入,则在点击(聚焦)它时,会触发'input'事件。 有谁知道为什么并且有解决方案,因为输入值没有真正改变?

var el = document.getElementById('myEmail');
el.addEventListener("input", myFunction, true);
function myFunction() {
  alert("changed");
}
<input id="myEmail" type="email" placeholder="Email">
    

3 个答案:

答案 0 :(得分:4)

我参加聚会很晚,但是我遇到了同样的问题,因此我想出一种解决方法来解决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

答案 1 :(得分:1)

这似乎是一个错误。 {1}}已得到支持,因为IE9只应在值更改时触发。另一种方法是使用oninput

https://developer.mozilla.org/en-US/docs/Web/Events/input

如果你想处理输入和验证,你可以添加第二个eventlistener(假设你的html与上面相同)。

onkeyup

答案 2 :(得分:0)

解决方案很短!

首先,我们不需要那么多的代码,我们可以在公认的答案中看到这些内容。第二步,您必须了解为什么会发生这种情况:

  1. placeholder事件仅在具有焦点的placeholder value输入时触发,并且仅在输入值为空时才触发。发生这种情况是因为IE的不良开发人员曾认为输入值从value变为实际的input,但这是来自IE的不良开发人员的误解。
  2. 没有占位符的placeholder不会出现此问题。

第一个解决方案非常简单:如果您确实不需要title,请不要使用它。在大多数情况下,您可以向元素添加placeholder而不是placeholder。您还可以在input之前,之下或之上写下placeholder文本。

如果您必须使用value

第二种解决方案也非常简单且简短:将先前的input保存在value对象上,并将其与新的return进行比较–如果未更改,则{{1 }},然后在代码前使用该功能。

生活例子

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)"/>