如何避免使用jQuery手风琴ko.bindingHandlers的Ghost克隆

时间:2014-12-21 21:04:44

标签: jquery jquery-ui knockout.js

我有两个与ko.observableArrays绑定的手风琴,想要在它们之间移动物品。 observableArrays正确更新,但不知何故,我移动的元素在被目标手风琴接收时会重复。

这是bindingHandlers:

(function () {
ko.bindingHandlers.jqAccordion = {
    init: function (element, valueAccessor) {
        var options = valueAccessor();
        $(element).accordion(options);
        $(element).bind("valueChanged", function () {
            ko.bindingHandlers.jqAccordion.update(element, valueAccessor);
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).accordion("destroy");
        });
    },
    update: function (element, valueAccessor) {
        var options = valueAccessor();

        $(element).accordion("destroy").accordion({
            header: ".accordion-header",
            collapsible: true,
            navigation: true,
            heightStyle: "content",
            active: false
        })
        .sortable({
            axis: "x,y",
            handle: ".accordion-header",
            placeholder: "ui-state-highlight",
            connectWith: "div",
            start: function (event, ui) {
                sorting = true;
                //find what tab is open, false if none
                active = $(this).accordion("option", "active");
                //possibly change animation here (to make the animation instant if you like)
                $(element).accordion("option", "animate", {
                    easing: 'swing',
                    duration: 0
                });
                //close tab
                $(element).accordion({
                    active: false
                });
            },
            over: function (event, ui) {
                $(element).accordion({
                    active: false
                });
            },
            stop: function (event, ui) {
                //1st: Handle the visible impression during sorting...
                // IE doesn't register the blur when sorting so trigger focusout handlers to remove .ui-state-focus
                ui.item.children("h3").triggerHandler("focusout");
                $(element).accordion("option", "animate", {});
                active = false;
                $(element).accordion("option", "active", active);
                sorting = false;
                //2nd: Create sequence listing of items for later saving
                var items = [], itemSeqNos = [];
                ui.item.siblings().andSelf().each(function () {
                    if ($(this).data('index') != $(this).index()) {
                        items.push(this.id);
                        itemSeqNos.push(this.id.replace("scene", ""));
                    }
                });
                ui.item.parent().trigger('stop');
            },
            receive: function (event, ui) {
                var source = ui.sender.context.id;
                var draggedId = ui.item[0].id.replace("scene", "");
                var target = this.id;
                if (target !== source) { // unless dropped on it self.
                    var context = ko.contextFor(this);
                    if (context) {
                        context.$root.rearrangeArrays(draggedId, target, source);
                    }
                }
            }
        })
        .on({
            stop: function () {
                $(this).siblings().andSelf().each(function (i) {
                    $(this).data('index', i);
                });
            }
        })
        .trigger('stop')
        .draggable({
            handle: ".accordion-header",
            helper: 'original',
            revert: true,
            revertDuration: 0,
            cursor: 'default',
            connectWith: options.target
        }).disableSelection();
    }
};
})();

observableArrays的更新是在我执行的rearrangeArrays-function中完成的 将“draggedId”-item推送到“目标”并将其从“源”中删除。

即使可拖动助手设置为“原始”(而不是“克隆”),已删除/已接收的项目也会重复。

小提琴:http://jsfiddle.net/AsleG/cnLftvhe/

2 个答案:

答案 0 :(得分:1)

这是由于敲除读取模板与使用的模板引擎相结合的方式存在问题 - 但它有一个简单的解决方法。您只需要从顶级模板节点外部删除空格:

<script type="text/html" id="scene-template"><div data-bind="attr: {'id': 'scene' + sceneID}" class="ui-widget-content"> 
        <div class="accordion-header ui-widget-header" > 
            <span data-bind="text:sceneID"></span>
            <span data-bind="text:title"></span>
        </div>
        <div class="ui-widget-content">
            <span data-bind="text:text"></span>
        </div >                    
    </div></script>

div现在开始和结束于script开始和结束标记旁边。显示警报时仍会显示副本,但一旦执行可以继续,则可以正确清理挖出并使您只使用一个渲染模板。

Updated fiddle

答案 1 :(得分:0)

我发现作为我项目框架的Dotnetnuke打破了顶级节点,作为James Thorpe建议的解决方案。詹姆斯的建议在小提琴中运作良好,jQuery.load-suggestion也是一种创造性的方法。坏Dnn没有为此而堕落。 ;)

最后,我对Ryan Niemeyers knockout-sortable.js采取了接近的方法,并提出了一个有效的解决方案。它可以在这里找到:http //jsfiddle.net/AsleG/7zyfs5nt/

Thanx获得所有帮助和Merry Xmas!