最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Range slider input event not firing in IE 10 - Stack Overflow

programmeradmin1浏览0评论

I have a range slider and I want to listen to its change and input events. This works fine in most browsers, but in IE 10, there is no input event firing and change fires over and over like input is supposed to. Here is the code:

html:

<input id="slider" type="range" />

js:

window.addEventListener('load', function() {

  var input = document.getElementById('slider');

  input.addEventListener('input', function(e) {
    console.log('input');
  });

  input.addEventListener('change', function(e) {
    console.log('change');
  });

});

And here it is on codepen:

I'm wondering if there is a workaround for this - a polyfill or some simple trick.

I have a range slider and I want to listen to its change and input events. This works fine in most browsers, but in IE 10, there is no input event firing and change fires over and over like input is supposed to. Here is the code:

html:

<input id="slider" type="range" />

js:

window.addEventListener('load', function() {

  var input = document.getElementById('slider');

  input.addEventListener('input', function(e) {
    console.log('input');
  });

  input.addEventListener('change', function(e) {
    console.log('change');
  });

});

And here it is on codepen: http://codepen.io/ZevanRosser/pen/YPQVzJ

I'm wondering if there is a workaround for this - a polyfill or some simple trick.

Share Improve this question edited Jan 23, 2015 at 21:33 Zevan asked Jan 23, 2015 at 21:13 ZevanZevan 10.2k3 gold badges34 silver badges48 bronze badges 7
  • I am having no issue with IE10 Range slider. Do verify that you are in IE 10 / 11 by hitting F12 and viewing the version – Cayce K Commented Jan 23, 2015 at 21:22
  • @CayceK yeah I'm in IE 10 - are you seeing 'input' logged in your console? – Zevan Commented Jan 23, 2015 at 21:34
  • As a workaround, I’d probably try with a timeout on the change event – assuming that when the “constant” firing of change will stop for a certain amount of time, that means the user is done moving the slider, and this can therefor be considered the time to (manually) trigger the input event. (Similar to what Resig suggests here, ejohn/blog/learning-from-twitter) – C3roe Commented Jan 23, 2015 at 21:48
  • Is the element registering the event being fired? Console log is your best friend for debugging – EasyBB Commented Jan 23, 2015 at 21:52
  • cool - thanks @CBroe that may be what I have to end up doing... – Zevan Commented Jan 23, 2015 at 22:05
 |  Show 2 more ments

3 Answers 3

Reset to default 5

So I figured this out a few days ago and figured I'd post my solution. Basically the trick is to check if you're in IE (using your sniffing method of choice). Then hijack the change event for range inputs and fire an input instead. Then, fire a change on mouseup. This seems to work great so far:

(here's a pen http://codepen.io/ZevanRosser/pen/pvWzej)

window.addEventListener('load', function() {

  var input = document.getElementById('slider');

  input.addEventListener('input', function(e) {
    console.log('input');
  });

  input.addEventListener('change', function(e) {
    console.log('change');
  });

  var fixInputAndChangeEvents = function() {
    var currentSlider;
    var fireChange = function(e) {
      var changeEvent = document.createEvent('Event');
      changeEvent.initEvent('change', true, true);

      changeEvent.forceChange = true;
      currentSlider.dispatchEvent(changeEvent);
    };

    document.addEventListener('change', function(e) {
      var inputEvent;
      if (!e.forceChange && e.target.getAttribute('type') === 'range') {
        e.stopPropagation();
        inputEvent = document.createEvent('Event');
        inputEvent.initEvent('input', true, true);

        e.target.dispatchEvent(inputEvent);

        currentSlider = e.target;
        document.removeEventListener('mouseup', fireChange);
        document.addEventListener('mouseup', fireChange);
      }

    }, true); // make sure we're in the capture phase
  };

  var isIE = function() {
    var userAgent = navigator.userAgent;
    return userAgent.indexOf('MSIE') !== -1 ||  
      userAgent.indexOf('Trident') !== -1;
  };

  if (isIE()) {
    fixInputAndChangeEvents();
  }

});

There are a few things I changed in the actual version I used on the project I'm working on.

  1. The project uses lodash so at the request of another developer I partialized the fireChange event and passed the current range input as the first argument rather than just using the currentSlider variable. This is basically to avoid collisions - pretty sure a collision isn't possible since you can only slide one slider at a time, but we figured better be safe than sorry.

  2. The project already had IE sniffing, so I used what was already there over what you see here.

It would be nice to somehow figure out if this event behavior exists rather than sniffing for IE, but I couldn't quite figure out how to determine if the event flaw was present.

Anyway, hope that helps if someone else encounters this problem. I think there is still some room for improvement but this works good enough for now.

EDIT:

As mentionned in ment by Justin Smith, IE10 not support conditionnal ment anymore.

Conditional ments are no longer supported

So the code below is correct under IE10 (I will remove bad ment), and this post not respond to the original answer.

ORIGINAL:

With this code, you will be able to do what you want with your ie version:

If your browser is not one of IE version, no ie class will be found on html tag. Also, an ie class will be found and also an ieX version.

<!DOCTYPE html>
<!--[if IE 6]><html lang="fr" class="ie ie9"><![endif]-->
<!--[if IE 7]><html lang="fr" class="ie ie10"><![endif]-->
<!--[if IE 8]><html lang="fr" class="ie ie11"><![endif]-->
<!--[if gt IE 9]><!--><html lang="fr"><!--<![endif]-->

and below you have:

<input id="slider" type="range" />

After that, into your code, just do that:

  • Fire input for all browser.
  • Fire change for all ie.

So

var html = document.getElementsByTagName("html")[0];
    slider = document.getElementById("slider"),
    input = (html.classList.contains("ie")) "change" : "input";

slider.addEventListener(input, function () {
    // Do something;
});

I found a solution which I consider to be better than anything I've seen so far on this topic because it doesn't require you to check what browser you're in.

Basically instead of checking for input, you check for mousedown, set an interval, then on mouseup you clear the interval.

var dragInterval = function dragInterval() {
        console.log(event);
    }, 10);
};

rangeInput.addEventListener('mousedown', function () {
    dragInterval();
});
rangeInput.addEventListener('mouseup', function () {
    clearInterval(dragInterval);
});
发布评论

评论列表(0)

  1. 暂无评论