css - sortable - selectable jquery ui




如何修復錯誤定位的可連接排序的可拖動助手(部分由浮動/相對定位父元素引起的)? (2)

前言

我遇到了一個問題,那就是當可拖動的輔助對像被放置在浮動的,相對定位的父元素中時,可拖動的輔助對像被錯誤地偏移。 浮動父元素是Bootstrap列,其中多個可排序列表放置在一列中,而可拖動列表放置在另一列中。

這是一個工作示例片段

$('.sortable').sortable({
  connectWith: '.sortable',
  revert: 600,
  forcePlaceholderSize: true,
  placeholder: 'ui-sortable-placeholder',
  tolerance: 'pointer'
}).disableSelection();

$('.draggable').draggable({
  connectToSortable: '.sortable',
  helper: 'clone',
  revert: true
}).disableSelection();
.sortable-container {
  display: inline-block;
  width: 100px;
  vertical-align: top;
}
.sortable {
  cursor: move;
  margin: 0;
  padding: 0;
  list-style-type: none;
  vertical-align: top;
  border: 1px solid #000;
}
.ui-sortable-placeholder {
  background: #ff0000;
}
#draggables {
  margin: 0;
  padding: 0;
  list-style-type: none;
}
.draggable {
  margin: 4px;
  cursor: move;
  color: #fff;
  background: #5dd1ff;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>

<div class='container-fluid'>
  <div class="row">
    <div class="col-xs-3">
      <p>foo</p>
      <p>bar</p>
    </div>
    <div class="col-xs-3">
      <p>foo</p>
      <p>bar</p>
    </div>
    <div class="col-xs-6">
      <p>foo</p>
      <p>bar</p>
    </div>
  </div>
  <div class='row'>
    <div class='col-xs-6'>
      <div id='sortables'>
        <div class='sortable-container'>
          <ul class='sortable'>
            <li>sortable 1</li>
            <li>sortable 2</li>
            <li>sortable 3</li>
            <li>sortable 4</li>
            <li>sortable 5</li>
            <li>sortable 6</li>
          </ul>
        </div>
        <div class='sortable-container'>
          <ul class='sortable'>
            <li>sortable 1</li>
            <li>sortable 2</li>
            <li>sortable 3</li>
            <li>sortable 4</li>
            <li>sortable 5</li>
            <li>sortable 6</li>
          </ul>
        </div>
        <div class='sortable-container'>
          <ul class='sortable'>
            <li>sortable 1</li>
            <li>sortable 2</li>
            <li>sortable 3</li>
            <li>sortable 4</li>
            <li>sortable 5</li>
            <li>sortable 6</li>
          </ul>
        </div>
      </div>
    </div>

    <div class='col-xs-6'>
      <ul id='draggables'>
        <li class='draggable'>draggable 1</li>
        <li class='draggable'>draggable 2</li>
        <li class='draggable'>draggable 3</li>
      </ul>
    </div>
  </div>
</div>

更新2015年11月16日我已經修改了代碼示例,以更好地反映我的實際使用上下文,其中有更多的行上方有持有draggables / sortables。

屏幕錄像 ,以及顯示發生情況的靜止圖像

進一步解釋

當從右側列拖動其中一個可拖動列在左邊的一個可排序列表上,並且不拖放它,但將其拖到可排序列表邊界框外時,該幫助器被錯誤地定位,向左幾百個像素,就好像它不正確地合併某種偏移(看起來可能是原始的可拖動位置)。

有趣的是,當可拖放元素與可排序元素放置在同一父元素中時,不會發生這種情況,至少它不會水平移動,而是垂直向上/向下或向左/向右移動/移出可排序列表。

水平移位與浮動/相對定位父元素有某種關係,禁用浮動或相對定位修復它。 但是,我想保持原樣,並找到另一個修復/解決方法。 在不涉及浮動/相對定位時也會發生垂直移位,所以我想這個問題還有一點。

201511月15日更新 - jQuery UI更改

看起來jQuery UI 1.11.4稍微改變了行為,現在當你離開可排序的邊界框時,它不會立即水平移動,但是你必須首先在兩個或多個可排序列表之間移動。 除此之外,越野車的行為似乎沒有改變。

201511月16日更新 - appendTo選項

最初,我試圖使用appendTo一個解決方法,這樣的幫助器將被保留在列表之外,雖然這是真實的我的原始示例代碼,它不會與更新的示例代碼工作,其中更多的行放在那些包含可拖動/可排序的元素之上,導致幫助者垂直移動。

有誰知道有問題的水平偏移源於哪裡,以及如何解決它,同時繼續使用浮動/相對位置的父元素?

那麼垂直偏移呢,看到這發生在jQuery UI演示中 ,這讓我覺得這是一個與父元素的樣式無關的錯誤?

201511月15日更新 - 找到垂直偏移問題

垂直偏移量似乎與拖動器上應用的邊距有關,但似乎沒有問題。

我已經報告這兩個錯誤,但我仍然在尋找修復/解決方法,我可以申請自己,直到這可能會或可能不會固定在圖書館。

http://bugs.jqueryui.com/ticket/14822
http://bugs.jqueryui.com/ticket/14806


https://jsfiddle.net/tsLcjw9c/1/

我把一個固定的寬度放在拖拽列表(100px)上,這樣可拖拽的助手和列表項目具有相同的寬度,這就防止了初始的水平偏移。

拖拽可排序容器時得到的大水平偏移值確實看起來是jQuery UI中的一個錯誤,但它似乎也完全是可排序容器寬度的100%,這就是為什麼我添加了以下css:

.sortable .ui-draggable-dragging:not(.ui-sortable-helper){
    margin-left:100%;
}

進入和離開可排序列表後,你得到的垂直偏移量似乎是由我刪除的可拖動項目4px的邊距造成的。 您可以通過透明的邊框和框的大小達到相同的效果:border-box; 或者添加填充並將背景剪輯設置為填充框。

最後,在我的瀏覽器(Chrome)中以一種奇怪的方式發生的,你想要發生的600毫秒的動畫,它發生在兩個不同的位置,最終動畫到正確的地方。 這就是為什麼我現在禁用動畫。 您可以嘗試重寫可排序jQuery中的放置事件,以便您可以手動對正確的位置執行動畫處理。

這裡的jsfiddle代碼:

HTML

<div class='container-fluid'>
  <div class='row'>
    <div class='col-xs-6'>
      <div id='sortables'>
        <div class='sortable-container'>
          <ul class='sortable'>
            <li>sortable 1</li>
            <li>sortable 2</li>
            <li>sortable 3</li>
            <li>sortable 4</li>
            <li>sortable 5</li>
            <li>sortable 6</li>
          </ul>
        </div>
        <div class='sortable-container'>
          <ul class='sortable'>
            <li>sortable 1</li>
            <li>sortable 2</li>
            <li>sortable 3</li>
            <li>sortable 4</li>
            <li>sortable 5</li>
            <li>sortable 6</li>
          </ul>
        </div>
        <div class='sortable-container'>
          <ul class='sortable'>
            <li>sortable 1</li>
            <li>sortable 2</li>
            <li>sortable 3</li>
            <li>sortable 4</li>
            <li>sortable 5</li>
            <li>sortable 6</li>
          </ul>
        </div>
      </div>
    </div>

    <div class='col-xs-6'>
      <ul id='draggables'>
        <li class='draggable'>draggable 1</li>
        <li class='draggable'>draggable 2</li>
        <li class='draggable'>draggable 3</li>
      </ul>
    </div>
  </div>
</div>

jQuery的

$('.sortable').sortable({
  connectWith: '.sortable',
  revert: 0,
  forcePlaceholderSize: true,
  placeholder: 'ui-sortable-placeholder',
  tolerance: 'pointer'
}).disableSelection();

$('.draggable').draggable({
  connectToSortable: '.sortable',
  helper: 'clone',
  revert: false
}).disableSelection();

CSS

.sortable-container {
  display: inline-block;
  width: 100px;
  vertical-align: top;
}
.sortable {
  cursor: move;
  margin: 0;
  padding: 0;
  list-style-type: none;
  vertical-align: top;
  border: 1px solid #000;
}
.ui-sortable-placeholder {
  background: #ff0000;
}
#draggables {
  margin: 0;
  padding: 0;
  list-style-type: none;
}
.draggable {
  cursor: move;
  color: #fff;
  background: #5dd1ff;
    width:100px;
    max-width:100%;
}
.sortable .ui-draggable-dragging:not(.ui-sortable-helper){
    margin-left:100%;
}

奇怪的是,它似乎更好地使用jQuery 10.4 。 不同的是,在10.4中, 可拖拽的助手保持原來的div,並被克隆到可排序的對像中,但是隱藏起來。 所以計算更容易。

在11.4中, 助手被附加到可拖動的排序上,這使得精確的偏移計算難以遵循。 你必須不斷地改變父母的偏移量,並跟踪它的排序順序,排序順序,排序位置等等。 顯然那裡有一個錯誤。

一個簡單的解決方案是從10.4獲得connectToSortable插件。 你必須檢查不需要的副作用,但很快它似乎工作。 您可以使用不同的名稱,以便保留原件。 喜歡這個:

$.ui.plugin.add("draggable", "connectToSortable104", {
    // You take the whole connectToSortable plugin from  
    // here: https://code.jquery.com/ui/1.10.4/jquery-ui.js  
    // In 11.4 you'll need to add draggable parameter 
    // for example: to the event methods,
    // start: function(event, ui, draggable)
    ...

http://jsfiddle.net/gsnojkbc/2/

編輯:

我不認為額外的div是什麼原因造成的問題,這是一個真正的問題, connectToSortable在jquery 11.4中的工作方式導致了這個問題。 為了允許移動幫助器在可排序內容中並且仍然跟踪正確的偏移量,每次輔助程序更改div時都需要重新調整一些數據。 這樣做有兩個缺陷:

第一個是有一個refreshOffsets方法, 這個方法對於可拖動的其他事件是通用的。 例如,當你點擊一個可拖動的。 所以它會嘗試通過點擊來計算偏移量。 但是,當從可排序事件中調用refreshOffset時,會攪亂點擊偏移量。 這可以通過更改refreshOffsets方法來解決,以免考慮event.pageX和Y.像這樣:

$.ui.draggable.prototype._refreshOffsetsSortable = function(event, draggable){

        this.offset = {
                top: this.positionAbs.top - this.margins.top,
                left: this.positionAbs.left - this.margins.left,
                scroll: false,
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset()
            };

            this.offset.click = draggable.offset.click;
    }

另一個問題是因為你有很多排序 。 基本上需要做的其他操作是改變父偏移量。 現在完成的方式是保存以前的父母。 通常情況下,它可以工作,但是如果移動得太快,序列就會使保存的父項是可排序的,而不是原始的父項。 你可以通過拖拽開始保存父母來解決這個問題,這在任何情況下都使得它更有意義。 喜歡這個:

$.ui.plugin.add( "draggable", "connectToSortableFixed", {
    start: function( event, ui, draggable ) {
        var uiSortable = $.extend( {}, ui, {
            item: draggable.element
        });
        draggable._parent = this.parent();
...

看到這裡: http : //jsfiddle.net/24a8q49j/1/





jquery-ui-sortable