【问题标题】:Knockout nested sortable lists淘汰嵌套的可排序列表
【发布时间】:2014-02-01 20:56:25
【问题描述】:

我需要构建一个包含两个可以交换的列表的网页。列表中的项目也可以从一个列表交换或移动到另一个列表。

我使用了 knockoutjs 和 knockoutjs-sortable 来实现这个。

HTML

<ul class="Tasks" data-bind="sortable: TaskLists">
    <li class="taskList"> 
        <span data-bind="text: Title" style='background: lightgray;'></span>
        <ul data-bind="sortable: Tasks">
           <li class="item"> 
              <span class="taskName" href="#" data-bind="text: name"></span>
            </li>
        </ul>
    </li>
</ul>

JS

var Task = function (name) {
    this.name = ko.observable(name);
}

var ViewModel = function () {
    var self = this;
    self.tasks1 = ko.observableArray([]);
    self.tasks2 = ko.observableArray([]);
    for (var i = 0; i < 5; i++) {
        self.tasks1.push(new Task("This task belongs to list one"));
        self.tasks2.push(new Task("This task belongs to list two"));
    }
    self.TaskList1 = {
        Tasks: self.tasks1,
        Title: 'List One'
    };
    self.TaskList2 = {
        Tasks: self.tasks2,
        Title: 'List Two'
    };
    self.TaskLists = ko.observableArray([]);
    self.TaskLists.push(self.TaskList1);
    self.TaskLists.push(self.TaskList2);
};

ko.bindingHandlers.sortable.options = {
    placeholder: 'ui-state-highlight',
    start: function (e, ui) {
        var dragElements = $('.ui-state-highlight');
        dragElements.css("height", ui.helper.outerHeight());
    }
};
ko.applyBindings(new ViewModel());

CSS

.frame {
    padding: 10px;
    overflow:auto;
}
.item {
    border: black 1px solid;
    width: 100px;
    background-color: #DDD;
    cursor: move;
    text-align: center;
    margin-top: 2px;
    margin-bottom: 2px;
}
.taskList {
    width: 110px;
    float:left;
    background: lightgreen;
}
.Tasks {
    width:400px;
    border: 1px #eee solid;
    height: 100%;
}
.taskName {
    word-wrap: break-word;
}
.ui-state-highlight {
    background: grey;
    border:1px dashed grey;
}

这是我目前得到的(fiddle)。

除了移动列表外,一切都按预期工作。 移动列表时,我希望拖动山墙占位符看起来像:

但我得到的是:

我做错了什么?我怎样才能实现这些预期结果?

【问题讨论】:

    标签: javascript jquery knockout.js knockout-sortable


    【解决方案1】:

    我在睡个好觉后发现了这个问题。 我上面的设计有几个陷阱:

    • 嵌套列表没有connectClass,这将有助于敲除排序找出可以拖动元素的位置。如果不指定此项,则其中一个列表接受要拖入其中的项目或完整列表。
    • 可拖动的占位符具有与列表本身不同的样式。这就是为什么可拖动占位符未正确呈现的原因(参考我上面问题中的结果截图)
    • 只定义了一个占位符,既适用于拖动的项目又适用于拖动的列表,这是不好的。

    这是一个fiddle,显示了完整的工作解决方案。

    HTML

    <div class="frame">
        <ul class="Tasks" data-bind="sortable: {data: TaskLists, connectClass: 'columns', options: { placeholder: 'list-highlight'}}">
          <li class="taskList">
            <span data-bind="text: Title" style='background: lightgray;'></span>
            <ul data-bind="sortable: {data: Tasks, connectClass: 'columnItems', options : { placeholder: 'ui-state-highlight'}}">
                <li class="item">
                  <span class="taskName" href="#" data-bind="text: name"></span>
                </li>
            </ul>
           </li>
        </ul>
    </div>
    

    JS

    var Task = function(name) {
        this.name = ko.observable(name);
    }
    
    var ViewModel = function() {
        var self = this;
        self.tasks1 = ko.observableArray([]);
        self.tasks2 = ko.observableArray([]);
        for (var i=0;i<5;i++){ 
            self.tasks1.push(new Task("This task belongs to list one"));
            self.tasks2.push(new Task("This task belongs to list two"));
        }
        self.TaskList1 = {Tasks: self.tasks1, Title:'List One'};
        self.TaskList2 = {Tasks: self.tasks2, Title:'List Two'};
        self.TaskLists = ko.observableArray([]);
        self.TaskLists.push(self.TaskList1);
        self.TaskLists.push(self.TaskList2);
    };
    
    ko.bindingHandlers.sortable.options = {
            //placeholder: 'ui-state-highlight',
            start: function (e, ui) {
                var dragItems = $('.ui-state-highlight');
                var dragLists = $('.list-highlight');
                var elementClass = ui.helper[0].className;
                if(elementClass === "item")
                      dragItems.css("height",ui.helper.outerHeight());
                if(elementClass === "taskList")
                      dragLists.css("height",ui.helper.outerHeight());
            }
        };
    ko.applyBindings(new ViewModel());
    

    CSS

        .frame{
            padding: 10px;
            overflow:auto;
        }
    
        .item {
           border: black 1px solid;
           width: 100px;
           background-color: #DDD;
           cursor: move;
           text-align: center;
           margin-top: 2px;
           margin-bottom: 2px;
        }
    
        .list-highlight{
            width: 100px;
            float:left;
            background: gray;
        }
    
        .taskList{
            width: 110px;
            float:left;
            background: lightgreen;
        }
    
        .Tasks{
            width:400px;
            border: 1px #eee solid;
            height: 100%;
        }
    
        .taskName{
            word-wrap: break-word;
        }
    
        .ui-state-highlight{
            background: grey;
            border:1px dashed grey;
    }
    

    【讨论】:

    • connectClass 名称/值 'columns' 和 'columnItems' 与您的 ViewModel 或 CSS 之间有什么关系(如果有)?我有(非常)类似的小提琴示例jsfiddle.net/patware/3VS6s,但不能让它像你的小提琴一样工作。
    • connectClass 是拖放插件在文档中拖放 html 元素时将查找的类。我也使用相同的类来格式化我的对象。
    • 我在您的 html 或 css 中找不到“columns”或“columnItems”。我期待您的 html 为 class="columns" 或类似的东西。
    • 哦,对不起,你是对的!这些类在 html 中不存在。它们实际上是由 jQuery 在运行时添加的 :)
    猜你喜欢
    • 1970-01-01
    • 2016-04-26
    • 2012-11-26
    • 2012-08-29
    • 2016-05-02
    • 2015-07-03
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    相关资源
    最近更新 更多