Search code examples
javascripthtmlfocusinternet-explorer-11placeholder

IE 10, 11. How to prevent the triggering of input events on focus from text input with placeholder?


In IE 11 if I have an empty email input with a placeholder, then on clicking (focusing) it, the input event is being triggered.

Does anyone know why and is there a solution to this, since the input value hasn't really changed?

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


Solution

  • I came very late to the party, but I had the same problem, and I came to a workaround to fix this behavior on IE. In fact, there's two different bugs (or rather, only one bug but with two behavior depending on whether the target is an input or a textarea).

    • For input : the event is triggered each time the visual content of the field change, including keyboard inputting (naturally), but also when a placeholder appears/disappears (blur when no content), or when a visible placeholder is changed programmatically.
    • For textarea: it's basically the same, exepts that the event don't trigger when the placeholder disapears.

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

    And there's a full-working example, where you can also change placeholders value

    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