HTML5范围的onChange事件


70

当前,我的范围输入上的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());
});

有帮助吗?


7
由于HTML规范含糊不清,这是WebKit和IE在实现中的错误。此后,规范已经阐明,释放旋钮之前,不应触发“ change”事件。为了在用户滑动旋钮时获取值,应使用“输入”事件。但是,WebKit和IE尚未修复此实现错误。HTML规范修订版:html5.org/tools/web-apps-tracker?from=7786&to=7787
JeremiahLee

Answers:


66

用于最终选择的值:

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

用于获取增量值的滑动值:

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

2
这在Firefox和Chrome浏览器中工作正常,但在Safari上却不能。滑动时,Safari会触发change事件。至少要等到他们围绕修订后的标准实施修补程序为止。
baohouse

酷,谢谢-不知道“输入”事件。但是我一直在寻找!(y)
KS

14

有点晚了,但是前几天我遇到了同样的问题。这是我使用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);

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


2
这是一个不错的解决方法,但缺点是每次只有一个改变时,所有对选择器“ .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);
示例

9

呸!

使用onmouseup事件,而不是onChange


4
我已经考虑了这一点,但由于以下两个原因而决定拒绝这样做:处理未更改的滑块值(次要)很笨拙,并且我不能假设人们会使用鼠标来编辑表单(主要)。我对这个问题仍然没有适当的答案,但是我对不将任何答案标记为正确的感到难过。它们是正确的(例如,它们可以工作),但是它们并不能真正回答问题。
WilliamMayor

2
您还需要添加事件:(onkeyup如果使用键盘)和ontouchend(如果使用触摸屏)。
iRon

6

一个问题是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);
}

2

gravediggin但如果您需要,请检查js节流阀反跳功能

用法:

//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);
        }
    };
};

1

这是我用来捕获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());
});

如果要在单击(甚至拖动)时返回其值,也可以将“ click”事件绑定到范围滑块。将其视为“ mouseup”事件。(我确实尝试过,但是单击滑块后滑块并未停止。)

JavaScript:

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

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

希望这可以帮助。


1

我在同一页面中使用以下设置来使用多个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);
    }
}

0

另一个建议:

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

这段代码似乎与jQuery 1.9.1冲突,因为它不断抛出错误。我发现下面的Arwyn答案有效。
朱利安·多蒙

0

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

您还可以尝试将和事件组合在一起blur,以捕获不同的情况:当用户使用键盘箭头和击键进行选择时,当用户使用键盘进行选择并始终专注于滑块时,以及使用鼠标时。甚至可能只组合和。onkeyuponmouseupblur<Tab>onkeyuponmouseuponkeyuponmouseup

仍然需要对值是否已更改进行简单检查,并且仅在发生更改后才运行必要的代码。


0

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/


0

让我们为集合添加一个简单的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)}/>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.