jQuery UI Sliders - 根据拖动方向选择重叠滑块

时间:2010-11-21 18:23:34

标签: javascript jquery jquery-ui jquery-ui-slider

我有这个简单的jQuery UI Slider设置,其中包含一个范围和两个重叠的默认值。整个事物(有一些花里胡哨)可以在这个jsfiddle中找到:http://jsfiddle.net/yijiang/XeyGS/

$('#slider').slider({
    min: 1,
    max: 11,
    range: true,
    values: [4, 4]
});

这个问题是当你尝试向右拖动单个可见句柄时,它会失败,因为jQuery UI总是将最小句柄置于顶部。出于多种原因,这显然是不好的。

有没有办法允许jQuery UI根据用户开始拖动的方向选择要拖动的句柄?

7 个答案:

答案 0 :(得分:6)

啊,我喜欢通过11k libs吃东西,不是吗? :)

注意:以下内容适用于jQuery UI 1.8.5

无论如何,这是一个非常干净的解决方案:

// add some stuff to the slider instance
this._handleIndex = null;
this._handleStartValue = -1; 

// remember the starting values in _mouseCapture
this._handleStartValue = this.values( this._handleIndex ); 
this._mouseDownOffset = this._normValueFromMouse( { x: event.pageX, y: event.pageY } );


// modify _mouseDrag
oldValue = this.values( this._handleIndex ),
curValue;

curValue = this.values(this._handleIndex);
if ( curValue === oldValue && this._handleStartValue !== -1 ) {
    if ( normValue - this._mouseDownOffset > 0
         && ( curValue === this.values( ( this._handleIndex + 1 ) % 2 ) )
         && oldValue === this._handleStartValue) {

        this._handleIndex = (this._handleIndex + 1) % 2;
    }

} else {
    this._handleStartValue = - 1
}

// reset everything in _mouseStop
this._handleIndex = null;
this._handleStartValue = -1; 

这就是它的全部,哦当然如何运作:

  1. 保存起始鼠标偏移量以及初始选择句柄的值
  2. 拖动时将旧值与活动句柄的当前值进行比较,并检查起始位置是否有效
  3. 如果没有区别我们会检查是否可以进一步拖动活动句柄
  4. 如果是这种情况,我们检查两个句柄是否具有相同的值,这意味着它们是彼此重叠的
  5. 现在我们检查当前选择的句柄是否尚未拖动
  6. 最后,如果一切正确,我们会切换句柄
  7. 如果用户现在更改了值,我们会使我们的起始位置无效,以便句柄之间不再切换
  8. 为了您的荣幸,这是一个diff

    9960c9960,9962
    < 
    ---
    >       
    >       this._handleIndex = null;
    >       this._handleStartValue = -1; 
    10215a10218,10219
    >         this._handleStartValue = this.values( this._handleIndex ); 
    >       this._mouseDownOffset = this._normValueFromMouse( { x: event.pageX, y: event.pageY } );
    10243c10247,10249
    <           normValue = this._normValueFromMouse( position );
    ---
    >           normValue = this._normValueFromMouse( position ),
    >           oldValue = this.values( this._handleIndex ),
    >           curValue;
    10246c10252,10263
    < 
    ---
    >       curValue = this.values(this._handleIndex);
    >       if ( curValue === oldValue && this._handleStartValue !== -1 ) {
    >           if ( normValue - this._mouseDownOffset > 0
    >                && ( curValue === this.values( ( this._handleIndex + 1 ) % 2 ) )
    >                && oldValue === this._handleStartValue) {
    >             
    >               this._handleIndex = (this._handleIndex + 1) % 2;
    >           }
    >         
    >       } else {
    >           this._handleStartValue = - 1
    >       }
    10257a10275,10276
    >       this._handleStartValue = -1; 
    >       this._handleIndex = null;
    

    将其保存到ui.diff,然后执行patch -i ui.diff jquery-ui.js

答案 1 :(得分:4)

向Ivo道歉,excellent answer在那里我确信需要付出很多努力来创造。问题是我无法应用该解决方案,因为我已经在1.8.6上,我无法在任何地方找到1.8.5源应用它,并且不知何故我无法使补丁工作对于1.8.6,即使我尝试手动添加行。

以下是我解决问题的方法。它比Ivo更简单,但这可能是因为两点发布之间存在差异。解决方案如下:

  1. 在另一个变量中拼接以跟踪原始值
  2. 满足条件时,(两个句柄,相同的值,大于当前的新值),翻转内部变量(_handleIndex),导致最大句柄用于内部{的参考{1}}功能而不是第一个。
  3. _slide如下:

    diff

    第一部分应插入初始化区域,其中变量被声明,第二部分插入46a47,48 > > this._originalVal; 310a313,314 > > this._originalVal = this.values(); 323a328,331 > > if(this._originalVal[0] === this._originalVal[1] && normValue > this._originalVal[0]){ > this._handleIndex = 1; > } 函数,恰好在调用_mouseCapture之前,最后一部分插入{{1}函数,也就在调用_slide之前。

    以下是补丁的工作示例:http://www.jsfiddle.net/HcGXZ/

    可以在此处找到修补的jQuery UI 1.8.6 Slider文件的副本:http://dl.dropbox.com/u/1722364/jQuery%20UI%20Slider%20Patch/jquery.ui.slider.patched.js

    与往常一样,此补丁尚未经过广泛测试,并不能保证适用于所有情况。

答案 2 :(得分:2)

我会说这是一个错误,加倍是因为当滑块手柄处于最小/最左侧位置时,已经有逻辑阻止“死锁”发生:

// workaround for bug #3736 (if both handles of a range are at 0,
// the first is always used as the one with least distance,
// and moving it is obviously prevented by preventing negative ranges)
if( o.range === true && this.values(1) === o.min ) {
  index += 1;
  closestHandle = $( this.handles[index] );
}

看起来ticket #3736仍处于开放状态,并提及您所看到的具体问题。

答案 3 :(得分:2)

我用1.8.12尝试Yi Jiang's solution并且它在一个带有单个手柄的滑块上打破了,但在我改变之后工作得很好

this._originalVal = this.values();

this._originalVal = this.options.values === null ? this.value() : this.values();

答案 4 :(得分:2)

将其放入初始化区域,声明变量:

this._originalVal;

在调用_mouseCapture之前将其放入_slide函数:

this._originalVal = this.values();

然后进入_mouseDrag函数,也就在调用_slide

之前
if (this._originalVal[0] === this._originalVal[1]
      && normValue > this._originalVal[0]) {
    this._handleIndex = 1;
} else if (this._originalVal[0] === this._originalVal[1]
             && normValue < this._originalVal[0]) {
    this._handleIndex = 0;
}

我刚刚在上面的代码中添加了else if;它在jQuery 1.8.14中运行良好 左右按钮处理程序。

答案 5 :(得分:1)

另一个解决方案: 测试两个值,如果它们相同,则返回上一步。

 $("#slider").slider({ 
            range:true, 
            min:0, 
            max:250,
            step: 25,
            slide: function( event, ui ) {
                if (ui.values[0] == ui.values[1]){
                    return false;
                }else{
                    $( "#amount" ).html( "&euro;" + ui.values[0] + " - &euro;" + ui.values[1] );
                }
            }
      });

答案 6 :(得分:1)

这是jQuery UI 1.10.2的新版本

补丁文件:http://pastebin.com/Dsxw8NYR

完整档案:http://pastebin.com/ibSpAAX1