9

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

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

这样做的问题是,当您尝试将单个可见手柄拖动到右侧时,它会失败,因为 jQuery UI 总是将最小手柄放在顶部。这显然很糟糕,原因有很多。

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

4

7 回答 7

6

啊,我喜欢吃完 11k 个库,你不是吗?:)

注意:以下是 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. 如果用户现在更改了值,我们会使我们的起始位置无效,以便手柄之间不再有切换

为了您的高兴,这里有一个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

于 2010-11-22T19:36:54.943 回答
4

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

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

  1. 拼接一个附加变量以跟踪原始值
  2. 当满足条件时,(两个句柄,相同的值,新值大于当前值),翻转一个内部变量(_handleIndex),导致最大句柄用于内部_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在调用之前插入函数,_slide最后一部分插入_mouseDrag函数,也在调用之前_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

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

于 2010-11-23T10:14:44.273 回答
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] );
}

看起来票 #3736仍然开放,并提到了您所看到的具体问题。

于 2010-11-22T18:25:50.087 回答
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 中运行良好。

于 2013-07-01T13:30:27.040 回答
2

我用 1.8.12 尝试了 Yijiang的解决方案,它在一个单手柄的滑块上坏了,但在我改变后完美运行

this._originalVal = this.values();

this._originalVal = this.options.values === null ? this.value() : this.values();
于 2011-05-05T16:37:14.037 回答
1

这是 jQuery UI 1.10.2 的新版本

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

完整文件: http: //pastebin.com/ibSpAAX1

于 2013-04-17T09:39:26.533 回答
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] );
                }
            }
      });
于 2011-10-09T21:32:40.947 回答