9

この単純なjQueryUIスライダーのセットアップには、範囲と2つのデフォルト値が重複しています。全体(いくつかのベルとホイッスルを含む)は、このjsfiddleにあります:http://jsfiddle.net/yijiang/XeyGS/

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

これに伴う問題は、表示されている単一のハンドルを右にドラッグしようとすると失敗することです。これは、jQueryUIが常に最小のハンドルを上に配置するためです。いくつかの理由から、これは明らかに悪いことです。

ユーザーがドラッグを開始する方向に応じて、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よりもシンプルですが、2つのポイントリリースの違いが原因である可能性があります。解決策は次のとおりです。

  1. 元の値を追跡するために追加の変数をスプライスします
  2. 条件が満たされた場合(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;
>       }

最初の部分は変数が宣言されている初期化領域に挿入され、2番目の部分は関数_mouseCaptureの呼び出しの直前に挿入され_slide、最後の部分は_mouseDrag関数の呼び出しの直前に挿入され_slideます。

パッチを使用した実際の例を次に示します。http ://www.jsfiddle.net/HcGXZ/

パッチが適用されたjQueryUI1.8.6スライダーファイルのコピーは、次の場所にあります: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

1.8.12 でYi Jiang のソリューションを試してみたところ、ハンドルが 1 つのスライダーで壊れましたが、変更後は完全に機能しました

this._originalVal = this.values();

this._originalVal = this.options.values === null ? this.value() : this.values();
于 2011-05-05T16:37:14.037 に答える
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 に答える
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 に答える