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

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

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

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

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

啊,我喜欢通过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. 如果用户现在更改了值,我们将起始位置无效,这样就不再需要在句柄之间切换

为了您的愉快,这里是一个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

在那里向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; > } 

第一部分应该插入初始化区域,其中变量被声明,第二部分插入_mouseDrag函数,在调用_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

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

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

 // 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看起来仍然是开放的,提到你所看到的具体问题。

我用1.8.12尝试了Yi Jiang的解决方案 ,它打破了一个带有单个手柄的滑块,但在我改变之后工作得很好

 this._originalVal = this.values(); 

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

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

 this._originalVal; 

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

 this._originalVal = this.values(); 

并且这也是在调用_slide之前的_mouseDrag函数

 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中运行良好。

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

  $("#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( "€" + ui.values[0] + " - €" + ui.values[1] ); } } }); 

这是jQuery UI 1.10.2的新版本

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

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