0

我想创建一个jQuery UI 范围滑块,其中可以设置上限的值集不同于可以设置下限的值集。本质上我想要一个滑块,其中可能值的范围是 [a, b] 但两个句柄“跨越式”交替值,因此下句柄只能设置为第 1、第 3、第 5 等值范围,上手柄只能设置为2号、4号、6号等。

最简单的例子是:是否可以创建一个值为 1-10 的范围滑块,其中下手柄只能设置为奇数,上手柄只能设置为偶数?

用例是我有一个滑块,用于选择以年为单位的时间范围。下限应表示一年的开始,上限应表示一年的结束。因此,如果您将下限设置为 2012 年,上限也设置为 2012 年,这应该意味着“从 2012 年初到 2012 年底”。

我可以制作一个范围加倍的滑块并做一些数学运算来计算基础范围(即,选择 2012 表示“2012 年初”,选择 2012.5 表示“2012 年底”,但对用户隐藏),但问题是然后用户可以将结束设置为“2012 年初”,这是我不想要的。问题是我实际上希望视觉 UI 防止两个句柄占据相同的位置,以防止有人选择对我的目的而言在语义上无效的范围。

在将初始上限/下限设置为交错值时,我试图变得聪明并使用“步骤”选项,但这不起作用。似乎步数不是相对于当前值计算的,而是在每次移动时将该值“捕捉”到可用的步数位置。因此,如果您有一个 1-10 的滑块,其中步长为 2,但上限设置为 10,则将其向下移动一个会将其变为 9,而不是 8。这正是我不想要的,因为我想要两个句柄具有不同的交错可用值。

如果这更容易的话,我愿意接受使用除 jQuery UI 之外的一些小部件集的解决方案,尽管我更喜欢基于一些有信誉的小部件集的解决方案。(也就是说,我宁愿拥有基于现有范围滑块的东西,而不是从头开始实现具有此特定功能的滑块。)

4

2 回答 2

4

您可以通过取消slide活动return false;
请参阅jsfiddle 上的此链接

function setValues(stepIncrease) {
  return function (event, ui) {
    var slider = $("#" + this.id);
    var currentValues = slider.slider("values");
    var step = slider.slider("option")["step"];
    if ((Math.abs(ui.values[0] - currentValues[0]) % (stepIncrease * step) != 0 || Math.abs(ui.values[1] - currentValues[1]) % (stepIncrease * step) != 0)){
        return false;
    };
    slider.slider("values", ui.values);
    var currentValues = slider.slider("values");
    $("#" + this.id + "-values").html(currentValues[0] + ' ' + currentValues[1]);
  };
};

在滑块中:

$(function() {
  $( "#slider-range-1-2" ).slider({
    range: true,
    min: 1,
    max: 10,
    step: 1,
    values: [1, 10],
    slide: setValues(2),
    create: function(event, ui) {
        var slider = $("#" + this.id);
        var currentValues = slider.slider("values");
        $("#" + this.id + "-values").html(currentValues[0] + ' ' + currentValues[1]);
    }
  });
});

UPD
这是处理keydown事件 的函数

function eventHandlerKeydown(slider, stepIncrease) {
return function(event) {
    var step, curVal, min, max, newVal, index = $( event.target ).data( "ui-slider-handle-index" );
    switch (event.keyCode) {
        case $.ui.keyCode.UP:
        case $.ui.keyCode.RIGHT:
        case $.ui.keyCode.DOWN:
        case $.ui.keyCode.LEFT:
            event.preventDefault();
            if ( !slider.keySliding ) {
                slider.keySliding = true;
                $(event.target).addClass( "ui-state-active" );
            }
            break;
    }
    step = slider.slider("option")["step"];
    max = slider.slider("option")["max"];
    min = slider.slider("option")["min"];
    curVal = slider.slider("values")[index];
    switch ( event.keyCode ) {
        case $.ui.keyCode.UP:
        case $.ui.keyCode.RIGHT:
            newVal = curVal + step * stepIncrease;
            if ( newVal > max ) {
                return;
            }
            slider.slider("values", index, newVal );
            break;
        case $.ui.keyCode.DOWN:
        case $.ui.keyCode.LEFT:
            newVal = curVal - step * stepIncrease;
            if ( newVal < min ) {
                return;
            }
            slider.slider("values", index, newVal );
            break;
    }
}
}

在滑块中:

$(function() {
var slider = $( "#slider-range" ).slider({
    ...
});
var handlers = slider.children("a");
$.each(handlers, function(index, handler) {
    $(handler).off('keydown');
    $(handler).on({keydown: eventHandlerKeydown(slider, 1)});
});
});

以及示例的链接

PS我仍然认为有一个简单的解决方案。

如果您只想选择年份的开始或结束,我认为@user568109 是正确的

function showValues(event, ui) {
var values;
if (!ui.values) {
    values = $("#" + event.target.id).slider("values");
} else {
    values = ui.values;
}
if (values[0] == values[1]) {
    return false;
} else {
    var periodFrom;
    values[0] % 1 == 0 ? periodFrom = 'beginnig of the year' : periodFrom = 'year-end';
    var periodTo;
    values[1] % 1 == 0 ? periodTo = 'beginnig of the year' : periodTo = 'year-end';
    $("#" + event.target.id + "-values").html('From ' + periodFrom + ' ' + parseInt(values[0]) + '<br />to ' + periodTo + ' ' + parseInt(values[1]));
}
}
$(function() {
$( "#slider" ).slider({
    range: true,
    min: 2010,
    max: 2013.5,
    step: 0.5,
    values: [2010, 2013.5],
    slide: showValues,
    create: showValues,
    change: showValues
});
});

那里的例子

于 2013-07-19T13:36:07.897 回答
-1

我不认为上下滑块的范围不同的想法是完全明智的。您将实数与日期时间范围混淆了。

数字 2012 可能意味着一年的开始/结束,但仅限于用户。在代码中应该清楚它是开始还是结束。通常是一年的开始。

所以 2012 - 2013 的实际数字将转换为 2012 年初到 2013 年初。或者您可以简单地将最后一项更改为 x 的开头到 x-1 的结尾。

这里唯一的问题是您不希望滑块重叠。所以只需检查值。

if (ui.values[ 1 ] === ui.values[ 0 ])
            return false;

请参阅jsfiddle

于 2013-07-20T08:04:53.477 回答