简体   繁体   English

jQuery Nested Sortable-无法移动嵌套的LI元素

[英]jQuery Nested Sortable - Can't move nested LI elements

I am stumped. 我感到难过。 I have been trying to solve this for 2 days and looked all over online including this site. 我已经尝试解决了2天,并在整个网上(包括此站点)进行了查找。 This is very frustrating, and I will be very impressed if you can solve it. 这非常令人沮丧,如果您能解决的话,我将印象深刻。

I am using Interspire shopping cart, which uses the jQuery plugin nestedsortables (http://code.google.com/p/nestedsortables/wiki/NestedSortableDocumentation) to arrange the order of your pages in the admin panel by dragging and dropping. 我正在使用Interspire购物车,该购物车使用jQuery插件nestedsortables(http://code.google.com/p/nestedsortables/wiki/NestedSortableDocumentation)通过拖放操作在管理面板中排列页面的顺序。 Here is a demo of a DIFFERENT script that does the same thing: http://mjsarfatti.com/sandbox/nestedSortable/ 这是一个执行相同操作的不同脚本的演示: http : //mjsarfatti.com/sandbox/nestedSortable/

The problem is the parent pages (in the list, not an actual page) are able to be dragged into any order, including into a nested child position and back out (until refresh, and then it is stuck in the child position). 问题是父页面(在列表中,而不是实际页面)能够被拖动到任何顺序,包括到嵌套的子位置并回退(直到刷新,然后卡在子位置)。 The child pages cannot be dragged/moved, and the cursor changes to a 4-way arrow just like the parent pages. 子页面无法拖动/移动,并且光标将变为与父页面相同的4向箭头。

I have gone over the HTML so many times I lose count. 我已经遍历了HTML太多次了,我数不清了。 The HTML looks almost identical for parent and children, that I can figure out why one would work, and one wouldn't. 对于父母和孩子来说,HTML看起来几乎是相同的,我可以弄清楚为什么一个可以起作用,一个不能起作用。 I think maybe it has something to do with either a ul or li tag, but I just don't see the problem. 我认为也许与ul或li标签有关,但我只是没有看到问题。

I have compared my code to that of the Interspire demo (http://shoppingcart.interspire-demo.com/demos) and I don't see any difference. 我已经将我的代码与Interspire演示的代码(http://shoppingcart.interspire-demo.com/demos)进行了比较,但没有发现任何不同。 Their admin panel works, mine doesn't. 他们的管理面板有效,我的无效。 I tried re-uploading the 2 JavaScript files that control this feature, but the problem persists. 我尝试重新上传2个控制此功能的JavaScript文件,但问题仍然存在。

Here is a HTML snippet: 这是一个HTML代码段:

<table class="GridPanel SortablePanel" cellspacing="0" cellpadding="0" border="0" style="width: 100%; margin-top: 10px;">
<tbody>
<tr class="Heading3">
<td width="1" style="padding-left: 5px;">
<input type="checkbox" style="vertical-align: middle;" onclick="ToggleDeleteBoxes(this.checked)">
</td>
<td> Page Name &nbsp; </td>
<td width="120"> Page Type &nbsp; </td>
<td width="80" align="center"> Visible &nbsp; </td>
<td width="80"> Action </td>
</tr>
</tbody>
</table>
<ul id="PageList" class="SortableList">
<li id="ele-5" class="SortableRow"></li> << **collapsed**
<li id="ele-3" class="SortableRow"></li> << **collapsed**
<li id="ele-11" class="SortableRow">
<table class="GridPanel" cellspacing="0" cellpadding="0" border="0" style="width: 100%;">
<tbody>
<tr class="GridRow" onmouseout="this.className='GridRow'" onmouseover="this.className='GridRowOver'">
<td width="1">
<input type="checkbox" value="11" name="page[]">
</td>
<td width="150" style="display: none;"> </td>
<td class="DragMouseDown sort-handle " style="-moz-user-select: none;"> PARENT </td>
<td class="HideOnDrag " width="120">Normal Page</td>
<td class="HideOnDrag " width="80" align="center">
<a href="index.php?ToDo=editPageVisibility&pageId=11&visible=1" title="Click here to make this page visible on your web site">
<img border="0" src="images/cross.gif">
</a>
</td>
<td class="HideOnDrag" width="80">
<a href="javascript:PreviewPage(11)" title="Preview Page">Preview</a>
<a href="index.php?ToDo=editPage&pageId=11" title="Edit this page">Edit</a>
</td>
</tr>
</tbody>
</table>
<ul class="SortableList" style="padding-left: 30px; padding-right: 0px;">
<li id="ele-12" class="SortableRow">
<table class="GridPanel" cellspacing="0" cellpadding="0" border="0" style="width: 100%;">
<tbody>
<tr class="GridRow" onmouseout="this.className='GridRow'" onmouseover="this.className='GridRowOver'">
<td width="1">
<input type="checkbox" value="12" name="page[]">
</td>
<td width="150" style="display: none;"> </td>
<td class="DragMouseDown sort-handle " style="-moz-user-select: none;"> CHILD ONE </td>
<td class="HideOnDrag " width="120">Normal Page</td>
<td class="HideOnDrag " width="80" align="center">
<a href="index.php?ToDo=editPageVisibility&pageId=12&visible=1" title="Click here to make this page visible on your web site">
<img border="0" src="images/cross.gif">
</a>
</td>
<td class="HideOnDrag" width="80">
<a href="javascript:PreviewPage(12)" title="Preview Page">Preview</a>
<a href="index.php?ToDo=editPage&pageId=12" title="Edit this page">Edit</a>
</td>
</tr>
</tbody>
</table>
</li>
<li id="ele-13" class="SortableRow">
<table class="GridPanel" cellspacing="0" cellpadding="0" border="0" style="width: 100%;">
<tbody>
<tr class="GridRow" onmouseout="this.className='GridRow'" onmouseover="this.className='GridRowOver'">
<td width="1">
<input type="checkbox" value="13" name="page[]">
</td>
<td width="150" style="display: none;"> </td>
<td class="DragMouseDown sort-handle " style="-moz-user-select: none;"> CHILD TWO </td>
<td class="HideOnDrag " width="120">Normal Page</td>
<td class="HideOnDrag " width="80" align="center">
<a href="index.php?ToDo=editPageVisibility&pageId=13&visible=1" title="Click here to make this page visible on your web site">
<img border="0" src="images/cross.gif">
</a>
</td>
<td class="HideOnDrag" width="80">
<a href="javascript:PreviewPage(13)" title="Preview Page">Preview</a>
<a href="index.php?ToDo=editPage&pageId=13" title="Edit this page">Edit</a>
</td>
</tr>
</tbody>
</table>
</li>
</ul>
</li>
</ul>
</div>
<div id="div1" style="display: none;">
</div>
</td>
</tr>
</tbody>
</table>

I named the pages PARENT, CHILD ONE, and CHILD TWO. 我将页面命名为PARENT,CHILD ONE和CHILD TWO。 The 2 child pages are nested in the parent. 2个子页面嵌套在父页面中。 Parent is draggable, but the 2 nested pages are not. 父级是可拖动的,但2个嵌套页面则不能。

Below is the NestedSortable jQuery Plugin code for your reference: 以下是NestedSortable jQuery插件代码供您参考:

jQuery.iNestedSortable = {
    checkHover: function (e, o) {
        if (e.isNestedSortable) {
            jQuery.iNestedSortable.scroll(e);
            return jQuery.iNestedSortable.newCheckHover(e)
        } else {
            return jQuery.iNestedSortable.oldCheckHover(e, o)
        }
    },
    oldCheckHover: jQuery.iSort.checkhover,
    newCheckHover: function (e) {
        if (!jQuery.iDrag.dragged) {
            return
        }
        if (!(e.dropCfg.el.size() > 0)) {
            return
        }
        if (!e.nestedSortCfg.remeasured) {
            jQuery.iSort.measure(e);
            e.nestedSortCfg.remeasured = true
        }
        var a = jQuery.iNestedSortable.findPrecedingItem(e);
        var b = jQuery.iNestedSortable.shouldNestItem(e, a);
        var c = (!a) ? jQuery.iNestedSortable.isTouchingFirstItem(e) : false;
        var d = false;
        if (a) {
            if (e.nestedSortCfg.lastPrecedingItem === a && e.nestedSortCfg.lastShouldNest === b) {
                d = true
            }
        } else if (e.nestedSortCfg.lastPrecedingItem === a && e.nestedSortCfg.lastTouchingFirst === c) {
            d = true
        }
        e.nestedSortCfg.lastPrecedingItem = a;
        e.nestedSortCfg.lastShouldNest = b;
        e.nestedSortCfg.lastTouchingFirst = c;
        if (d) {
            return
        }
        if (a !== null) {
            if (b) {
                jQuery.iNestedSortable.nestItem(e, a)
            } else {
                jQuery.iNestedSortable.appendItem(e, a)
            }
        } else if (c) {
            jQuery.iNestedSortable.insertOnTop(e)
        }
    },
    scroll: function (e) {
        if (!e.nestedSortCfg.autoScroll) {
            return false
        }
        var a = e.nestedSortCfg.scrollSensitivity;
        var b = e.nestedSortCfg.scrollSpeed;
        var c = jQuery.iDrag.dragged.dragCfg.currentPointer;
        var d = jQuery.iUtil.getScroll();
        if ((c.y - d.ih) - d.t > -a) {
            window.scrollBy(0, b)
        }
        if (c.y - d.t < a) {
            window.scrollBy(0, -b)
        }
    },
    check: function (a) {
        jQuery.iNestedSortable.newCheck(a);
        return jQuery.iNestedSortable.oldCheck(a)
    },
    oldCheck: jQuery.iSort.check,
    newCheck: function (a) {
        if (jQuery.iNestedSortable.latestNestingClass && jQuery.iNestedSortable.currentNesting) {
            jQuery.iNestedSortable.currentNesting.removeClass(jQuery.iNestedSortable.latestNestingClass);
            jQuery.iNestedSortable.currentNesting = null;
            jQuery.iNestedSortable.latestNestingClass = ""
        }
        if (jQuery.iDrop.overzone.isNestedSortable) {
            jQuery.iDrop.overzone.nestedSortCfg.remeasured = false
        }
    },
    serialize: function (s) {
        if (jQuery('#' + s).get(0).isNestedSortable) {
            return jQuery.iNestedSortable.newSerialize(s)
        } else {
            return jQuery.iNestedSortable.oldSerialize(s)
        }
    },
    oldSerialize: jQuery.iSort.serialize,
    newSerialize: function (s) {
        var i;
        var h = '';
        var j = '';
        var o = {};
        var e;
        var k = function (f) {
                var g = [];
                thisChildren = jQuery(f).children('.' + jQuery.iSort.collected[s]);
                thisChildren.each(function (i) {
                    var a = jQuery.attr(this, 'id');
                    if (a && a.match) {
                        a = a.match(e.nestedSortCfg.serializeRegExp)[0]
                    }
                    if (h.length > 0) {
                        h += '&'
                    }
                    h += s + j + '[' + i + '][id]=' + a;
                    g[i] = {
                        id: a
                    };
                    var b = jQuery(this).children(e.nestedSortCfg.nestingTag + "." + e.nestedSortCfg.nestingTagClass.split(" ").join(".")).get(0);
                    var c = j;
                    j += '[' + i + '][children]';
                    var d = k(b);
                    if (d.length > 0) {
                        g[i].children = d
                    }
                    j = c
                });
                return g
            };
        if (s) {
            if (jQuery.iSort.collected[s]) {
                e = jQuery('#' + s).get(0);
                o[s] = k(e)
            } else {
                for (a in s) {
                    if (jQuery.iSort.collected[s[a]]) {
                        e = jQuery('#' + s[a]).get(0);
                        o[s[a]] = k(e)
                    }
                }
            }
        } else {
            for (i in jQuery.iSort.collected) {
                e = jQuery('#' + i).get(0);
                o[i] = k(e)
            }
        }
        return {
            hash: h,
            o: o
        }
    },
    findPrecedingItem: function (e) {
        var d = 0;
        var f = jQuery.grep(e.dropCfg.el, function (i) {
            var a = (i.pos.y < jQuery.iDrag.dragged.dragCfg.ny) && (i.pos.y > d);
            if (!a) {
                return false
            }
            var b;
            if (e.nestedSortCfg.rightToLeft) {
                b = (i.pos.x + i.pos.wb + e.nestedSortCfg.snapTolerance > jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.wb)
            } else {
                b = (i.pos.x - e.nestedSortCfg.snapTolerance < jQuery.iDrag.dragged.dragCfg.nx)
            }
            if (!b) {
                return false
            }
            var c = jQuery.iNestedSortable.isBeingDragged(e, i);
            if (c) {
                return false
            }
            d = i.pos.y;
            return true
        });
        if (f.length > 0) {
            return f[(f.length - 1)]
        } else {
            return null
        }
    },
    isTouchingFirstItem: function (e) {
        var c;
        var d = jQuery.grep(e.dropCfg.el, function (i) {
            var a = (c === undefined || i.pos.y < c);
            if (!a) {
                return false
            }
            var b = jQuery.iNestedSortable.isBeingDragged(e, i);
            if (b) {
                return false
            }
            c = i.pos.y;
            return true
        });
        if (d.length > 0) {
            d = d[(d.length - 1)];
            return d.pos.y < jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.hb && d.pos.y > jQuery.iDrag.dragged.dragCfg.ny
        } else {
            return false
        }
    },
    isBeingDragged: function (e, a) {
        var b = jQuery.iDrag.dragged;
        if (!b) {
            return false
        }
        if (a == b) {
            return true
        }
        if (jQuery(a).parents("." + e.sortCfg.accept.split(" ").join(".")).filter(function () {
            return this == b
        }).length !== 0) {
            return true
        } else {
            return false
        }
    },
    shouldNestItem: function (e, a) {
        if (!a) {
            return false
        }
        if (e.nestedSortCfg.noNestingClass && jQuery(a).filter("." + e.nestedSortCfg.noNestingClass).get(0) === a) {
            return false
        }
        if (e.nestedSortCfg.rightToLeft) {
            return a.pos.x + a.pos.wb - (e.nestedSortCfg.nestingPxSpace - e.nestedSortCfg.snapTolerance) > jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.wb
        } else {
            return a.pos.x + (e.nestedSortCfg.nestingPxSpace - e.nestedSortCfg.snapTolerance) < jQuery.iDrag.dragged.dragCfg.nx
        }
    },
    nestItem: function (e, a) {
        var b = jQuery(a).children(e.nestedSortCfg.nestingTag + "." + e.nestedSortCfg.nestingTagClass.split(" ").join("."));
        var c = jQuery.iSort.helper;
        styleHelper = c.get(0).style;
        styleHelper.width = 'auto';
        if (!b.size()) {
            var d = "<" + e.nestedSortCfg.nestingTag + " class='" + e.nestedSortCfg.nestingTagClass + "'></" + e.nestedSortCfg.nestingTag + ">";
            b = jQuery(a).append(d).children(e.nestedSortCfg.nestingTag).css(e.nestedSortCfg.styleToAttach)
        }
        jQuery.iNestedSortable.updateCurrentNestingClass(e, b);
        jQuery.iNestedSortable.beforeHelperRemove(e);
        b.prepend(c.get(0));
        jQuery.iNestedSortable.afterHelperInsert(e)
    },
    appendItem: function (e, a) {
        jQuery.iNestedSortable.updateCurrentNestingClass(e, jQuery(a).parent());
        jQuery.iNestedSortable.beforeHelperRemove(e);
        jQuery(a).after(jQuery.iSort.helper.get(0));
        jQuery.iNestedSortable.afterHelperInsert(e)
    },
    insertOnTop: function (e) {
        jQuery.iNestedSortable.updateCurrentNestingClass(e, e);
        jQuery.iNestedSortable.beforeHelperRemove(e);
        jQuery(e).prepend(jQuery.iSort.helper.get(0));
        jQuery.iNestedSortable.afterHelperInsert(e)
    },
    beforeHelperRemove: function (e) {
        var a = jQuery.iSort.helper.parent(e.nestedSortCfg.nestingTag + "." + e.nestedSortCfg.nestingTagClass.split(" ").join("."));
        var b = a.children("." + e.sortCfg.accept.split(" ").join(".") + ":visible").size();
        if (b === 0 && a.get(0) !== e) {
            a.hide()
        }
    },
    afterHelperInsert: function (e) {
        var a = jQuery.iSort.helper.parent();
        if (a.get(0) !== e) {
            a.show()
        }
        e.nestedSortCfg.remeasured = false
    },
    updateCurrentNestingClass: function (e, a) {
        var b = jQuery(a);
        if ((e.nestedSortCfg.currentNestingClass) && (!jQuery.iNestedSortable.currentNesting || b.get(0) != jQuery.iNestedSortable.currentNesting.get(0))) {
            if (jQuery.iNestedSortable.currentNesting) {
                jQuery.iNestedSortable.currentNesting.removeClass(e.nestedSortCfg.currentNestingClass)
            }
            if (b.get(0) != e) {
                jQuery.iNestedSortable.currentNesting = b;
                b.addClass(e.nestedSortCfg.currentNestingClass);
                jQuery.iNestedSortable.latestNestingClass = e.nestedSortCfg.currentNestingClass
            } else {
                jQuery.iNestedSortable.currentNesting = null;
                jQuery.iNestedSortable.latestNestingClass = ""
            }
        }
    },
    destroy: function () {
        return this.each(function () {
            if (this.isNestedSortable) {
                this.nestedSortCfg = null;
                this.isNestedSortable = null;
                jQuery(this).SortableDestroy()
            }
        })
    },
    build: function (a) {
        if (a.accept && jQuery.iUtil && jQuery.iDrag && jQuery.iDrop && jQuery.iSort) {
            this.each(function () {
                this.isNestedSortable = true;
                this.nestedSortCfg = {
                    noNestingClass: a.noNestingClass ? a.noNestingClass : false,
                    rightToLeft: a.rightToLeft ? true : false,
                    nestingPxSpace: parseInt(a.nestingPxSpace, 10) || 30,
                    currentNestingClass: a.currentNestingClass ? a.currentNestingClass : "",
                    nestingLimit: a.nestingLimit ? a.nestingLimit : false,
                    autoScroll: a.autoScroll !== undefined ? a.autoScroll == true : true,
                    scrollSensitivity: a.scrollSensitivity ? a.scrollSensitivity : 20,
                    scrollSpeed: a.scrollSpeed ? a.scrollSpeed : 20,
                    serializeRegExp: a.serializeRegExp ? a.serializeRegExp : /[^\-]*$/
                };
                this.nestedSortCfg.snapTolerance = parseInt(this.nestedSortCfg.nestingPxSpace * 0.4, 10);
                this.nestedSortCfg.nestingTag = this.tagName;
                this.nestedSortCfg.nestingTagClass = this.className;
                this.nestedSortCfg.styleToAttach = (this.nestedSortCfg.rightToLeft) ? {
                    "padding-left": 0,
                    "padding-right": this.nestedSortCfg.nestingPxSpace + 'px'
                } : {
                    "padding-left": this.nestedSortCfg.nestingPxSpace + 'px',
                    "padding-right": 0
                };
                jQuery(this.nestedSortCfg.nestingTag, this).css(this.nestedSortCfg.styleToAttach)
            });
            jQuery.iSort.checkhover = jQuery.iNestedSortable.checkHover;
            jQuery.iSort.check = jQuery.iNestedSortable.check;
            jQuery.iSort.serialize = jQuery.iNestedSortable.serialize
        }
        return this.Sortable(a)
    }
};
jQuery.fn.extend({
    NestedSortable: jQuery.iNestedSortable.build,
    NestedSortableDestroy: jQuery.iNestedSortable.destroy
});
jQuery.iUtil.getScroll = function (e) {
    var t, l, w, h, iw, ih;
    if (e && e.nodeName.toLowerCase() != 'body') {
        t = e.scrollTop;
        l = e.scrollLeft;
        w = e.scrollWidth;
        h = e.scrollHeight;
        iw = 0;
        ih = 0
    } else {
        if (document.documentElement && document.documentElement.scrollTop) {
            t = document.documentElement.scrollTop;
            l = document.documentElement.scrollLeft;
            w = document.documentElement.scrollWidth;
            h = document.documentElement.scrollHeight
        } else if (document.body) {
            t = document.body.scrollTop;
            l = document.body.scrollLeft;
            w = document.body.scrollWidth;
            h = document.body.scrollHeight
        }
        iw = self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0;
        ih = self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0
    }
    return {
        t: t,
        l: l,
        w: w,
        h: h,
        iw: iw,
        ih: ih
    }

Please help me out. 请帮帮我。 I am sure other Interspire and NestedSortable users would find this useful as well. 我确信其他Interspire和NestedSortable用户也会发现它也很有用。 Thanks for looking, and I do greatly appreciate anyone trying to solve this whether you succeed or not. 感谢您的关注,无论您是否成功,我都非常感谢任何尝试解决此问题的人。 }; };

After spending 3 and half days trying to debug this without success, I decided to try the jQuery plug-in from mjsarfatti.com instead of the one from code.google.com . 在花了三天半的时间尝试调试成功之后,我决定尝试使用mjsarfatti.com的jQuery插件,而不是code.google.com的jQuery插件。

Using the plug-in from Misarfatti didn't work right out of the box, because he does have settings you must configure in order for it to work correctly otherwise it will freeze your browser. 使用Misarfatti插件无法立即使用,因为他确实具有必须进行设置才能正确运行的设置,否则它将冻结您的浏览器。 I figure this was worth a try before spending hours taking all the code from a private admin panel and setting it up to work in jsfiddle. 我认为在花几个小时从私人管理面板中获取所有代码并将其设置为在jsfiddle中工作之前,值得尝试一下。 Even if I did that, this question seems to have little to no interest here, and would probably never get solved. 即使我这样做了,这个问题似乎也没有引起人们的兴趣,并且可能永远也无法解决。

This was the biggest coding nightmare I have had in over a year, so I figured I would post the solution here in case someone else ran into the same problem. 这是我一年多以来最大的编码梦night,所以我认为我将在这里发布解决方案,以防其他人遇到相同的问题。 I would hate for someone to go through what I did with it. 我不希望有人经历我所做的事情。 I can post the full code if requested, although it was pretty straight-forward. 我可以按要求发布完整的代码,尽管这很简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM