【问题标题】:onChange event for HTML5 rangeHTML5 范围的 onChange 事件
【发布时间】:2011-07-07 03:21:01
【问题描述】:

目前,我的范围输入上的 onChange 事件在每一步都会触发。

有没有办法阻止此事件触发,直到用户放开滑块?

我正在使用范围来创建搜索查询。我希望能够在每次更改表单时运行搜索,但在滑块移动的每一步发出搜索请求太多了。


代码如下:

HTML:

<div id="page">
    <p>Currently viewing page <span>1</span>.</p>
    <input class="slider" type="range" min="1" max="100" step="1" value="1" name="page" />
</div>

JavaScript:

$(".slider").change(function() {
    $("#query").text($("form").serialize());
});

这有帮助吗?

【问题讨论】:

  • 这是 WebKit 和 IE 实现中的一个错误,因为 HTML 规范中存在歧义。此后,规范已经澄清,在释放旋钮之前不应触发“更改”事件。要在用户滑动旋钮时获取值,应使用“输入”事件。但是,WebKit 和 IE 尚未修复此实现错误。 HTML 规范修订:html5.org/tools/web-apps-tracker?from=7786&to=7787

标签: html forms range onchange


【解决方案1】:

用于最终选择的值:

 $(".slider").on("change", function(){console.log(this.value)});

用于获取增量值作为滑动:

$(".slider").on("input", function(){console.log(this.value)});

【讨论】:

  • 这在 Firefox 和 Chrome 中可以正常工作,但在 Safari 上不行。 Safari 在您滑动时触发更改事件。至少在他们开始根据修订后的标准实施修复之前。
  • 酷,谢谢 - 不知道“输入”事件。但我一直在寻找! (y)
【解决方案2】:

有点晚了,但前几天我遇到了同样的问题。这是我使用 jQuery 绑定/触发器的解决方案:

(function(el, timeout) {
    var timer, trig=function() { el.trigger("changed"); };
    el.bind("change", function() {
        if(timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(trig, timeout);
    });
})($(".slider"), 500);

现在只需将您的函数绑定到“更改”事件即可。

【讨论】:

  • 这是一个很好的解决方法,但缺点是每次响应选择器“.slider”的所有元素都触发“更改”,而每次只有一个元素实际更改时。我修改了你的例子:(function($el, timeout) { var timer; $el.bind("change", function() { var $me = $(this); if (timer) { clearTimeout(timer); } timer = setTimeout(function() { $me.trigger("changed"); }, timeout); }); })($(.slider), 500);
【解决方案3】:

呸!

使用onmouseup 事件而不是onChange

【讨论】:

  • 我曾考虑过,但出于两个原因决定不这样做:处理未更改(次要)的滑块值很笨拙,我不能假设人们会使用鼠标进行编辑形式(主要)。我对这个问题仍然没有正确的答案,但我对没有将任何答案标记为正确感到难过;它们是正确的(例如,它们有效),但它们并没有真正回答问题。
  • 您还需要添加事件:onkeyup(如果使用键盘)和ontouchend(如果使用触摸屏)。
【解决方案4】:

一个问题是 AFAIK HTML5 没有定义何时应该触发 onchange 事件,因此它很可能因浏览器而异。而且您还必须考虑,浏览器实际上不必将input type=range 呈现为滑块。

您唯一的选择是您必须建立一种机制来确保您的搜索不会被太频繁地触发,例如,检查搜索当前是否正在运行并中止,或者确保搜索是最多每 x 秒触发一次。

后者的快速示例(只是一个快速破解,未经测试)。

var doSearch = false;

function runSearch() {
   // execute your search here 
}

setInterval(function() {
  if (doSearch) {
     doSearch = false;
     runSearch();
  }
}, 2000); // 2000ms between each search.

yourRangeInputElement.onchange = function() { doSearch = true; }

【讨论】:

    【解决方案5】:

    这里是纯 JS:

    myInput.oninput = function(){
        console.log(this.value);
    }
    

    myInput.onchange = function(){
        console.log(this.value);
    }
    

    【讨论】:

      【解决方案6】:

      gravediggin,但如果需要,请检查 js throttledebounce 函数

      用法:

      //resize events gets processed 500ms after the last Event
      addEventListener("resize", _debounce(function(){ foo;}, 500));
      
      //resize events get processed every 500ms
      addEventListener("resize", _throttle(function(){ foo;}, 500));
      

      代码:

      /*waits 'delay' time after the last event to fire */
      _debounce = function(fn, delay) {
          var timer = null;
          return function() {
              var context = this,
                  args = arguments;
              clearTimeout(timer);
              timer = setTimeout(function() {
                  fn.apply(context, args);
              }, delay);
          };
      };
      
      
      /* triggers every 'treshhold' ms, */
      _throttle = function(fn, threshhold, scope) {
          threshhold = threshhold || 250;
          var last,
              deferTimer;
          return function() {
              var context = scope || this;
      
              var now = +new Date(),
                  args = arguments;
              if (last && now < last + threshhold) {
                  // hold on to it
                  clearTimeout(deferTimer);
                  deferTimer = setTimeout(function() {
                      last = now;
                      fn.apply(context, args);
                  }, threshhold);
              } else {
                  last = now;
                  fn.apply(context, args);
              }
          };
      };
      

      【讨论】:

        【解决方案7】:

        这是我用于捕获 html5 范围滑块的“更改事件”的内容:

        HTML:

        <form oninput="output1.value=slider1.value">
            <input type="range" name="slider1" value="50"/>
            <output name="output1" for="slider1">50</output>
        </form>
        

        JavaScript:

        var $slider = $('input[name="slider1"]');
        
        $slider.bind('change', function(e) {
            e.preventDefault();
            console.log($(this).val());
        });
        

        如果您想在单击(甚至拖动)时返回其值,也可以将“单击”事件绑定到范围滑块。把它想象成一个“mouseup”事件。 (我确实尝试过,但单击滑块后滑块并没有停止。)

        JavaScript:

        $slider.bind('click', function(e) {
            e.preventDefault();
            console.log($this).val());
        }
        

        附带说明,这会返回一个字符串,因此请确保在适当的时候使用 'parseInt($(this).value())'。

        希望这会有所帮助。

        【讨论】:

          【解决方案8】:

          我在同一页面中使用了几个 HTML5 默认滑块,设置如下:

          • 使用oninput 事件移动滑块时,页面中的输出标记会更改值
          • change 事件在发布时触发一次

          使用最新的 Chrome 进行测试,并在带有 Node 和 Socket.io 的 Raspberry 上很好地编译。

          <output id="APIDConKpVal"></output>&nbsp; <input type="range"
                       class="PIDControlSlider"
                       min="0"
                       max="1500"
                       step="1"
                       id="APIDConKp"
                       oninput="APIDConKpVal.value=value"/>
          
          <output id="APIDConKiVal"></output>&nbsp; <input type="range"
                       class="PIDControlSlider"
                       min="0"
                       max="2000"
                       step="1"
                       id="APIDConKi"
                       oninput="APIDConKiVal.value=value"/>
          

          一个简单的 Javascript 代码创建侦听器。您可能需要尝试不同的事件,而不是最后一行中的“更改”,以查看适合您的内容。

          window.onload=function()
          {
           var classname = document.getElementsByClassName("PIDControlSlider");
          
              var myFunction = function() {
                  var attribute = this.getAttribute("id");
          //Your code goes here
                  socket.emit('SCMD', this.getAttribute("id")+' '+ this.value);
              };
          
              for(var i=0;i<classname.length;i++){
                  classname[i].addEventListener('change', myFunction, false);
              }
          }
          

          【讨论】:

            【解决方案9】:

            另一个建议:

            $(".slider").change(function(){    
              if (this.sliderTimeour) clearTimeout(this.sliderTimeour);
              this.sliderTimeour = setTimeout(function(){
                //your code here
              },delayTimeHere);
            });
            

            【讨论】:

            • 此代码似乎与 jQuery 1.9.1 冲突,因为它不断抛出错误。但是,我在下面发现 Arwyn 的答案是可行的。
            【解决方案10】:

            您可以尝试使用blur 事件。当然它也有它的局限性,但这只是另一个建议:)

            您还可以尝试结合bluronkeyuponmouseup 事件来尝试捕捉不同的情况:blur 当用户使用键盘箭头进行选择并点击&lt;Tab&gt;onkeyup当用户使用键盘进行选择并保持专注于滑块时,onmouseup 当他使用鼠标时。甚至可以只组合onkeyuponmouseup

            您仍然必须简单检查值是否已更改,并仅在发生更改后运行必要的代码。

            【讨论】:

              【解决方案11】:

              onchange 工作得很好,但我需要在滑动时更新值。

              var interval;
              $("#rangeinput").mousedown(function(event){
                  interval = setInterval(function(){
                      $("#output").html($("#rangeinput").val());
                      console.log("running");
                  },150);
              });
              
              $("#rangeinput").mouseup(function(event){
                  clearInterval(interval);
              });
              

              http://jsbin.com/vibuc/1/

              【讨论】:

                【解决方案12】:

                让我们为集合添加一个简单的 ES6 替代方案:

                let timer;
                
                const debounceChange = (value, callback) => {
                    clearTimeout(timer);
                    timer = setTimeout(() => callback(value), 500);
                };
                

                当在 JSX 中使用时,它看起来像这样:

                <input type="range" onChange={e => debounceChange(e.target.value, props.onChange)}/>
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2019-10-01
                  • 2017-04-07
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-09-29
                  • 2012-10-26
                  • 2014-12-26
                  • 2013-11-01
                  相关资源
                  最近更新 更多