可排序的jquery交换排序

时间:2011-11-20 00:17:00

标签: javascript jquery jquery-ui-sortable swap nodes

好的,我正在研究一个问题,但这个问题消失了,所以我只是在努力创造一些东西。仅供参考,这不是首要任务,所以不要觉得有义务。

无论哪种方式,我都需要一些建议来解决这个问题,因为我无法让它正常工作。我有节点交换,但无法让它正确交换回来。我认为我没有正确处理这些元素。

第一步是与正在移动的元素进行交换,基本上是:

1 2 3 4 5

如果1超过2则(x保持单元格为1):

2 X 3 4 5

如果1超过3,那么:

3 2 X 4 5

这是我到目前为止所拥有的。在“可排序”($)

_NodeHold_pos: false,

// return what n1 get's replaced with
nodeSwap: function( n1, n2) {
    // not null and not same node and both have parents
    //  hmm, !n1.isSameNode(n2) doesn't work here for some reason
    if ( n1 && n2 && n1 != n2 && n1.parentNode && n2.parentNode ) {
        // if they don't have same parent, we need to make sure they don't contain each other (untested)
        if ( !n1.parentNode.isSameNode(n2.parentNode) ) {
            prnt = n1.parentNode;
            while ( prnt ) {
                if ( prnt.isSameNode(n2) ) return;
            }
            prnt = n2.parentNode;
            while ( prnt ) {
                if ( prnt.isSameNode(n1) ) return;
            }
        }
        n1h = n1.cloneNode(true);
        n1.parentNode.replaceChild(n1h,n1);
        n2.parentNode.replaceChild(n1,n2);
        n1h.parentNode.replaceChild(n2,n1h);
        //sn2.parentNode.removeChild(n1h);
        return n2;
    }
    return n1;
},

_rearrange2: function(event, i) {
    var n1 = this.placeholder[0];
    var n2 = (this.direction == 'down' || !i.item[0].nextSibling? i.item[0] : i.item[0].nextSibling);

    if ( n2 && !this._NodeHold_pos) {
        this._NodeHold_pos = this.nodeSwap(n1,n2);
    } else if ( n2 ) {
        var hold = n1;
        this.nodeSwap(n1,this._NodeHold_pos);
        this._NodeHold_pos = this.nodeSwap(n1,n2);
    }

    //Various things done here to improve the performance:
    // 1. we create a setTimeout, that calls refreshPositions
    // 2. on the instance, we have a counter variable, that get's higher after every append
    // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
    // 4. this lets only the last addition to the timeout stack through
    this.counter = this.counter ? ++this.counter : 1;
    var self = this, counter = this.counter;

    window.setTimeout(function() {
        if(counter == self.counter) self.refreshPositions(true); //Precompute after each DOM insertion, NOT on mousemove
    },0);
},

在函数“_mouseDrag”中,替换为“_rearrange”调用将切换为添加“_rearrange2”

                //* <-- add '/' in front for this or remove for next
                this._rearrange(event, item);
                /*/
                this._rearrange2(event,item);
                //*/

在函数“_mouseStop”中,将“_NodeHold_pos”设置为false

我认为这就是我所做的一切。无论哪种方式,测试掉交换并且似乎工作,但是当我尝试交换回来时,我不断发送空节点并且它们因此而一直卡住。我认为这也导致了奇怪的行为,所以不确定该去哪里。

哦,html(这是来自演示):

<html>
<head>
<script src="../jquery-1.7.min.js" type="text/javascript"></script>
<script src="../jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="../jquery-ui-1.8.16.custom.css"></link>
<script src="../jquery/development-bundle/ui/jquery.ui.sortable.js" type="text/javascript"></script>
</head>
<body>
<meta charset="utf-8">
    <style>
    #sortable2 { list-style-type: none; margin: 0; padding: 0; zoom: 1; }
    #sortable2 li { margin: 0 5px 5px 5px; padding: 3px; width: 90%; }
    </style>
<script>
    $(function() {
        $( "#sortable2" ).sortable({ tolerance: 'pointer',
            //items: "li:not(.ui-state-disabled)",
            cancel: ".ui-state-disabled",
        });
        $( "#sortable2 li" ).disableSelection();
    });
</script>
<div class="demo">
<h3 class="docs">Cancel sorting (but keep as drop targets):</h3>

<ul id="sortable2">
    <li class="ui-state-default">Item 1</li>
    <li class="ui-state-default">Item 2</li>
    <li class="ui-state-default">Item 3</li>
    <li class="ui-state-default ui-state-disabled">(I'm not sortable)</li>
    <li class="ui-state-default ui-state-disabled">(I'm not sortable)</li>
    <li class="ui-state-default">Item 4</li>
</ul>

</div>
</body>
</html>

编辑:如果您在重新排列2中注释掉一部分(并调用它)并且只是调用swap:

    this.nodeSwap(n1,n2);
    /*
    if ( n2 && !this._NodeHold_pos) {
        this._NodeHold_pos = this.nodeSwap(n1,n2);
    } else if ( n2 ) {
        var hold = n1;
        this.nodeSwap(n1,this._NodeHold_pos);
        this._NodeHold_pos = this.nodeSwap(n1,n2);
    }
    */

你可以看到交换类型的工作。也许我应该首先解决这个问题。它有时挂起,有时只是推动一切,但大部分都有效。在测试时,即使我可以看到它们,节点有时也会被定义。我是否必须刷新DOM或其​​他东西?

1 个答案:

答案 0 :(得分:2)

嗯,有一段时间没有碰过,因为没有人回答。好的,我使交换功能工作。最大的问题是重新排列是从我没看到的几个地方调用的(这就是为什么我删除了传递给函数的两个变量)并且n2被设置为不同类型的排序。此外,交换不需要从JQuery的设置中检查父母。

要设置它,这是我用于测试的html:

<html>
<head>
<script src="jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="jquery-ui-1.8.16.custom.css"></link>
<!-- this is from the development bundle so that it can be seen easier -->
<script src="jquery.ui.sortable.js" type="text/javascript"></script>
<meta charset="utf-8">
<style>
#sortable1, #sortable2 { list-style-type: none; margin: 0; padding: 0; zoom: 1; }
#sortable1 li { margin: 0 5px 5px 5px; padding: 3px; width: 40%; }
#sortable2 li { margin: 0 5px 5px 5px; padding: 3px; width: 30%; }
</style>
<script>
    $(function() {
        $( ".sortable" ).sortable({ tolerance: 'pointer',cancel: ".ui-state-disabled",});
        $( ".sortable li" ).disableSelection();
    });
</script>
</head>
<body>
<ul class="sortable" id="sortable1">
    <li class="ui-state-default">Item 1</li>
    <li class="ui-state-default">Item 2</li>
    <li class="ui-state-default">Item 3</li>
    <li class="ui-state-default ui-state-disabled">(I'm not sortable 1)</li>
    <li class="ui-state-default ui-state-disabled">(I'm not sortable 2)</li>
    <li class="ui-state-default">Item 4</li>
    <ul class="sortable" id="sortable2">
        <li class="ui-state-default">sub 2</li>
        <li class="ui-state-default">sub 3</li>
    </ul>
</ul>
</body>
</html>

我还使用了一些子节点来测试其他一些东西。

在我收录的文件jquery.ui.sortable.js中,我做了以下更改。

对于函数_rearrange,我替换为以下内容:

_NodeHold_pos: false,

// return what n1 get's swapped with
nodeSwap: function( n1, n2 ) {
    if ( n1 && n2 && n1 !== n2 ) {
        var n1h = n1.cloneNode(false);
        n1.parentNode.replaceChild(n1h,n1);
        n2.parentNode.replaceChild(n1,n2);
        n1h.parentNode.replaceChild(n2,n1h);
        return n2;
    }
    return n1;
},

// _rearrange rework for specific sort
_rearrange: function(event, i, a, hardRefresh) {

    if ( a ) {
        a[0].appendChild(this.placeholder[0]);
        return;
    }

    var n1 = this.placeholder[0];
    var n2 = i.item[0];
    /*
    // swap in place, from where you were last (during mouseovers)
    this.nodeSwap(n1,n2);
    /*/
    // swap from original position (before picking up node)
    if ( this._NodeHold_pos === false ) {
        this._NodeHold_pos = this.nodeSwap(n1,n2);
    } else if ( n2 === this._NodeHold_pos ) {
        this.nodeSwap(n1,n2);
        this._NodeHold_pos = false;
    } else if ( n1 !== this._NodeHold_pos ) {
        this.nodeSwap(n1,this._NodeHold_pos);
        this._NodeHold_pos = this.nodeSwap(n1,n2);
    } else {
        alert("here");
        this._NodeHold_pos = false; // shouldn't really reach this
    }
    //*/
    this.counter = this.counter ? ++this.counter : 1;
    var self = this, counter = this.counter;

    window.setTimeout(function(){
        if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
    },0);
},

我将此行添加到_mousestop:

this._NodeHold_pos = false;

现在工作正常。我使用了两个不同的交换(因为我不知道什么是bug),但两者看起来都是一样的,所以只选择了代码较少的那个。

我没有真正回答我刚开始的原始问题,但这是有效的,所以这个问题得到了回答。