web-dev-qa-db-ja.com

jQuery UIのソート可能なスクロールヘルパー要素によるFirefoxの問題のオフセット

Firefox 3.6のjQuery UI 1.7.2ソート可能リストに問題があります。IE7-8は正常に動作します。少し下にスクロールすると、ヘルパー要素には、マウスポインターから下にスクロールしたのと同じ高さのオフセットがあるように見えるため、最初にドラッグを開始したアイテムを確認できません。これを修正する方法、または問題を回避するにはどうすればよいですか?修正がない場合、本当に優れた代替のドラッグ可能なプラグインは何ですか?

ソート可能の初期化パラメーターは次のとおりです。

$("#sortable").sortable( {placeholder: 'ui-state-highlight'  } );
$("#sortable").disableSelection();
55
James

私はこの問題を見ていましたが、ページに含まれるdivの1つからCSSルールposition:relativeを削除することで解決できました。参照: http://forum.jquery.com/topic/sortable-offset-when-element-is-dragged-and-page-scrolled-down-ff

23
craig

ブラウザのスニッフィングを防ぎたい場合、CSSのみの解決策は、ulまたはコンテナスタイルをoverflow: autoに設定することです。 firebugを介してソースを見ると、jQueryが example で行う方法です。

126
munch

overflow: auto;を使用することは私にとって選択肢ではありませんでした。このsortイベントハンドラでこの問題を回避できました。

$(...).sortable({
    ...
    sort: function(event, ui) {
        var $target = $(event.target);
        if (!/html|body/i.test($target.offsetParent()[0].tagName)) {
            var top = event.pageY - $target.offsetParent().offset().top - (ui.helper.outerHeight(true) / 2);
            ui.helper.css({'top' : top + 'px'});
        }
    },
    ...
});

完全ではありませんが、ブラウザのスニッフィングは必要ありません。 IE8でテスト済み、ChromeおよびFirefox。

編集:これはjQuery 1.10.0とjQuery UI 1.10.3を使用しています。

43
rtcherry

私もこの問題を抱えており、次のコードで修正しました。

var wscrolltop = 0;
$sortable_elements.sortable({ 
    start: function(event, ui) {
        wscrolltop = $(window).scrollTop();
    },
    sort: function(event, ui) {                   
        ui.helper.css({'top' : ui.position.top + wscrolltop + 'px'});
    }
});

ソート可能な要素でスクロールすると、まだ問題があることを発見しました。たぶん誰かがこれに対する解決策を持っていますか?

更新:修正は次のとおりです。

$sortable_elements.sortable({ 
    connectWith: '#personal-favs ul.fitems',
    sort: function(event, ui) {  
        ui.helper.css({'top' : ui.position.top + $(window).scrollTop() + 'px'});
    }
});

それでも、リストから離れると、ソートイベントは停止するようです。

20
Theodor

また、これはfirefoxに固有であるという事実を考慮する必要があります。ここに私が使用しているスニペットがあります-Harrisのソリューションから正しい方法で指示されました。ソート可能オブジェクトが比較的配置されたコンテナにある場合、ヘルパーを使用しないとこの問題が発生しました。

  var options = { 
   handle: '.mover', 
   update:updateSorting 
 };
  var userAgent = navigator.userAgent.toLowerCase();
  if(userAgent.match(/firefox/)) {
    options["start"] = function (event, ui) { ui.item.css('margin-top', $(window).scrollTop() ); };
    options["beforeStop"] = function (event, ui) { ui.item.css('margin-top', 0 ); };
  }
  $("#" + list_id+"").sortable(options);
  $("#" + list_id+"").disableSelection();

サーバーでこのチェックを実行してから、ブラウザーに応じて2つの異なる呼び出しを行うこともできます。

9
Russell

私はこれに対する修正を見つけ出すことができました:

$( "items" ).sortable({
start: function (event, ui) {
 if( ui.helper !== undefined )
  ui.helper.css('position','absolute').css('margin-top', $(window).scrollTop() );
},
beforeStop: function (event, ui) {
 if( ui.offset !== undefined )
  ui.helper.css('margin-top', 0);
},
placeholder: 'placeholder-class'
});

基本的に、ブラウザの現在のscrollTop()値をヘルパーの位置に追加するには、ソート可能の「開始」イベントをリッスンする必要があります。その後、ソート可能の「beforeStop」イベントをリッスンして、アイテムが正式にリリースされる前にそのオフセットを削除する必要がありますリストの新しい位置に戻されます。

それが誰かに役立つことを願っています!

7
Jonathan Harris

私は自分のサイトでスクロールバーを強制しているので、このスクロール可能なオフセットの問題は、html { overflow-y: scroll }私のCSS。

スクロール可能のオンとオフを切り替えると、次の方法で回避できます。 IE8、FF12、Chromeでのみテストしました...

  turnSortingOnOff:function(e) {
    e.preventDefault();

    if (stopOrdering()) {
      // get rid of the hacky css on the html element
      $('html').css({ 'overflow-y': '' });
      $('html').css({ 'margin-right': '' });

      elmt.sortable('disable');
    }
    else if (startOrdering()) {
      // if the body is smaller than the window
      // then there aren't any scrollbars
      // in which case, add a right hand margin of 16px
      // to the html to prevent the site wobbling
      if ($('body').outerHeight() <= $(window).height()) {
        $('html').css({ 'margin-right': 16 });
      }

      // then override the { overflow-y: scroll }
      // in the css by setting it to a Nice, safe inherit
      $('html').css({ 'overflow-y': 'inherit' });

      elmt.sortable('enable');
    }
  }

明らかにそれは防弾ではありません-ソート中にドキュメントのサイズが変更された場合、他のことを行う必要があります。しかし、私の経験では、そのような状況ではそれほど奇妙に見えません。

4
DaveJenni

新しいjQuery/jQuery UIバージョンを使用してこれを「修正」しました。

  • jQuery 1.8.0
  • jQuery UI 1.8.23
1
Jorge Morante

将来の読者のために、bootstrap=ダイアログのスクロールされたdiv内でドラッグするとヘルパー要素にオフセットがあるという同様の問題に遭遇しました。ドラッグされたオブジェクトを解放すると、アニメーションはページのスクロール部分を考慮しない新しい位置であり、ユーザーに混乱を招くフィードバックを与えます。

ダイアログコンテナでposition:relativeとoverflow-y:autoを使用して作業を続けるために、私の解決策は

1-スクロール開始イベントのヘルパーオブジェクトのマージン上部にscrollTop()オフセットを追加します。

2- beforeStopイベントのマージン上部を削除します

これにより、ドラッグ後にアニメーションがオフになるのを修正しましたが、ページのスクロール部分をドラッグしている間、ヘルパーオブジェクトはカーソルの下にプッシュされます。最後の修正は

3-ポインターとコンテナーオフセットを基準にして(並べ替えイベントを使用して)ドラッグ中にヘルパーオブジェクトのtopプロパティを計算して設定します。

$(...).sortable({
...
start: function (event, ui) {  
    ui.helper.css('margin-top', $("#mybootstrap-dialog").scrollTop()); 
},
beforeStop: function (event, ui){ 
    ui.helper.css('margin-top',0); 
},
sort: function(event, ui) {
    var top = event.clientY - $('#my-sortable-ul').offset().top  -  $("#mybootstrap-dialog").scrollTop();
    ui.helper.css({'top' : top + 'px'});
    }
},
...

});

これが役立ちます

この問題を抱えている将来の読者のために。 jqueryui 1.8から1.10.3にアップグレードしたところ、CSSを修正することなく問題は解決しました。

http://jqueryui.com/

また、jquery 1.8から1.10.2にアップグレードしました

http://jquery.com/

0

設定overflow: autoは、Firefoxがポインターの下にある要素でドラッグを開始するようにしますが、自動スクロールが適切に機能しないようにします。スクロールが必要なほどウィンドウを小さくした場合、jQuery Sortableの例でそのことがわかります。

私はoverflow: scroll htmlタグで、ただし、それを削除しても(と思う)すべての関連要素を含む要素は完全に問題を解決しませんでした(ドラッグが正しく開始され、自動スクロールが機能することを意味します)。私は_findRelativeOffsetへのmozilla-sniffingパッチも試してみました(それがそうだったと思います)が、助けにはなりませんでした。

私のユースケースで助けになったのは、クローンをドラッグするだけでした(helper: 'clone'ドラッグ可能なコンストラクター内)。クローンが存在しないように見せるために、可視性を非表示に設定してから元に戻す開始メソッドと停止メソッドを追加しました。

私は上記でコメントしたでしょうが、私はまだポイントを持っていません。

0
Dan Chadwick

あなたの努力を要約し、完成したソリューションを提供します。以下は、Chrome 40+およびFirefox 30+で動作するようです

var isFirefox = /firefox/.test(navigator.userAgent.toLowerCase());
$('#target').sortable({
    connectWith: '#target-holder .elements',
    handle: ".element-header",
    start: function(ev, ui) {
        if( isFirefox ) {
            ui.item.css('margin-top', $(window).scrollTop() );
        }
    },
    sort: function(ev, ui) {
        if( isFirefox) {
            ui.helper.css({'top' : ui.position.top - $(window).scrollTop() + 'px'});
        } else {
            ui.helper.css({'top' : ui.position.top + $(window).scrollTop() + 'px'});
        }
    },
    beforeStop: function (ev, ui) {
        if( isFirefox ) {
            ui.item.css('margin-top', 0 );
        }
    }
});
0
Lorenz Lo Sauer

同じ問題がありました。私の場合、「overflow:auto」修正を使用することはできませんでした。これが私がしたことです。

var pos_fixed = 1;        // switch variable (the fix should only be fired ones)
$('.drag').draggable({
 start: function(event, ui){
  pos_fixed = 0;            // we're about to start, set to not fixed yet
 },
 drag: function(event, ui){
  if(pos_fixed == 0){       // check if the fix hasn't been fired for this instance yet
   var help_pos = $(ui.helper).offset().top, // get helpers offset
   targ_pos = $(event.target).offset().top,  // get targets(the dragged elements) offset
   marg = targ_pos-help_pos; // calculate the margin the helper has to have to put it on the same y-position as our target
   $(ui.helper).css('margin-top', marg); // put our helper on the same y-position as the target
   pos_fixed = 1;            // we've fixed it, we don't want it to fire again
  }
 }
});

修正プログラムは、使用しているブラウザを気にしません。ドラッグの開始時に、ヘルパーがターゲットと同じyオフセットを持っていることを常に確認します。

0
tappad