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

发布于 2024-10-03 06:35:36 字数 421 浏览 3 评论 0原文

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

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

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

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

I have this simple jQuery UI Slider setup with a range and a two default values that overlap. The entire thing (with a few bells and whistles) can be found in this jsfiddle: http://jsfiddle.net/yijiang/XeyGS/

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

The problem with this is that when you attempt the drag the single visible handle to the right, it fails, because jQuery UI always places the minimum handle on top. This is obviously bad, for a number of reasons.

Is there a way to allow jQuery UI to choose which handle to drag depending on which direction the user starts dragging?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

拍不死你 2024-10-10 06:35:36

啊,我喜欢吃掉 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. 最后,如果所有这些都是 true,我们切换手柄
  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

Ah, I like it to eat through 11k libs, don't you too? :)

Note: The following is for jQuery UI 1.8.5

Anyways, here's a pretty clean solution:

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

And that's all there is to it, oh how it works, of course:

  1. Save the starting mouse offset as well as the value of the initially select handle
  2. When dragging compare the old value to the current value of the active handle and also check whether the start position is valid
  3. In case there's no difference we check whether there would be a difference if the active handle could be dragged further
  4. If that's the case we check whether both handles have the same value, that means they're on top of each other
  5. Now we check if the the currently selected handle hasn't been dragged yet
  6. And finally if all that is true, we switch the handles
  7. In case the user now changes the value we invalidate our start position so that there's no more switching between the handles

And for your pleasure here's a 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;

Save it to ui.diff then do patch -i ui.diff jquery-ui.js.

伴我老 2024-10-10 06:35:36

向 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

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

With apologies to Ivo there, whose excellent answer there I'm sure took a lot of effort to create. The problem is that I couldn't apply that solution, because I'm already on 1.8.6, I can't find the 1.8.5 sources anywhere to apply it to, and somehow I just couldn't get the patch to work for 1.8.6, even when I tried adding in the lines manually.

The following is my solution to the problem. It is simpler than Ivo's, but that might be because of differences between the two point releases. The solution is as follows:

  1. Splice in an additional variable to keep track of the original values
  2. When the conditions are met, (two handles, same value, new value larger than current), to flip an internal variable (_handleIndex) around, causing the maximum handle to be used for reference for the internal _slide function instead of the first.

The diff is as follows:

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

The first part should be inserted into the initialising area, where the variables are declared, the second into the _mouseCapture function right before the call to _slide, and the last part into the _mouseDrag function, also right before the call to _slide.

Here's a working example with the patch: http://www.jsfiddle.net/HcGXZ/

A copy of the patched jQuery UI 1.8.6 Slider file can be found here: http://dl.dropbox.com/u/1722364/jQuery%20UI%20Slider%20Patch/jquery.ui.slider.patched.js

As always, this patch has not been extensively tested and is not guaranteed to work for all scenarios.

傲世九天 2024-10-10 06:35:36

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

// 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 仍然开放,其中提到了您遇到的具体问题。

I'd say this is a bug, doubly so because there's already logic preventing a ‘deadlock’ from happening when both slider handles are at the minimum / far left position:

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

It looks like ticket #3736 is still open, with mentioning of the specific problem you're seeing.

韶华倾负 2024-10-10 06:35:36

我尝试了易江的解决方案 使用 1.8.12 时,它在带有单个手柄的滑块上破裂,但在我更改

this._originalVal = this.values();

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

I tried Yi Jiang's solution with 1.8.12 and it broke on a slider with a single handle, but worked perfectly after I changed

this._originalVal = this.values();

to

this._originalVal = this.options.values === null ? this.value() : this.values();
执手闯天涯 2024-10-10 06:35:36

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

this._originalVal;

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

this._originalVal = this.values();

并将其放入_mouseDrag code> 函数,也在调用 _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 中工作正常
左右按钮处理程序。

Put this into the initialising area, where the variables are declared:

this._originalVal;

Put this into the _mouseCapture function right before the call to _slide:

this._originalVal = this.values();

And this into the _mouseDrag function, also right before the call to _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;
}

I just added an else if to the above code; it's working fine in jQuery 1.8.14 for
both left and right button handlers.

撕心裂肺的伤痛 2024-10-10 06:35:36

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

 $("#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] );
                }
            }
      });

Another solution:
Test for both values and if they are the same, return to the last step.

 $("#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] );
                }
            }
      });
金橙橙 2024-10-10 06:35:36

的新版本

这是 jQuery UI 1.10.2补丁文件

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

Here's a new version for jQuery UI 1.10.2

Patch file: http://pastebin.com/Dsxw8NYR

Complete file: http://pastebin.com/ibSpAAX1

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文