javascript - 动态行创建挖空js

标签 javascript arrays knockout.js foreach

我正在尝试使用 knockout js 创建一个包含 4 行和 4 列的表格。下面是我的数组,其中包含 16 个元素,需要将这些元素放入表格中。

    /*----------------------------------------------------------------------*/
/* View Model                                                           */
/*----------------------------------------------------------------------*/
function ViewModel() {
    var self = this;
    self.items = ko.observableArray(["1.jpg", 
                                      "2.jpg", 
                                      "3.jpg", 
                                      "4.jpg",
                                      "5.jpg",
                                      "6.jpg"
                                      ]);
    self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
        var rows = [];
        var count = 0;
        var items = self.items(); //get the item array
        var current = [];
        for(var i in items)
        {
            var item = items[i];
            current.push(item);
            count++;

            if (count == 4)
            {
                count = 0;
                rows.push(current);
                current = []; //next array
            }
        }

        if (current.length > 0)
        {
            rows.push(current);
        }

        return rows;
    });

    self.bindSort = function() {

        var startIndex = -1;         
        var sortableSetup = {        
         start: function (event, ui)
         {         
          startIndex = ui.item.index();
         },


         stop: function (event, ui) 
         {      
          var newIndex = ui.item.index();        
          if (startIndex > -1) 
          {
              self.from = ko.observable(startIndex);
              self.to = ko.observable(newIndex);
              var iTo = parseInt(self.to());
          var iFrom = parseInt(self.from());
          var from = self.items()[iFrom];
              var to = self.items()[iTo];
              self.items()[iTo] = from;
                  self.items()[iFrom] = to;
                  //alert('before');
                  // alert(from);
                  // alert(to);
                  var fromA = self.items()[iFrom];
              var toA = self.items()[iTo]; 
              //alert('after');
          //alert(fromA);
                  // alert(toA);
              self.items.remove(from);               
              self.items.splice(newIndex, 0, toA);
               self.items.remove(to); 
                self.items.splice(startIndex, 0, fromA);
                          //ui.item.remove();
               self.items.valueHasMutated();

          }

         }
        };


        $(".fruitList").sortable( sortableSetup );                           

    };

}   

/*----------------------------------------------------------------------*/
/* KO HTML Binding                                                      */
/*----------------------------------------------------------------------*/   
$(document).ready(function() {

    // create the view model
    var model = new ViewModel();

    // call the bind method for jquery UI setup
    model.bindSort();

    // binds ko attributes with the html
    ko.applyBindings(model);

});

并尝试在 html 中执行此操作,

<table data-bind="foreach: itemRows">
              <tr class="fruitList" data-bind="foreach: $data">
                  <td><img data-bind="attr: { src: $data }" /></td>
              </tr>
        </table>

我无法获取数组的长度,也无法在第一行创建 4 个 tds 并创建第二行后如何打破循环。有什么建议吗???

更新:

当我使用 sortable 时,下面的代码似乎不起作用,

    start: function (event, ui)
     {         
      startIndex = ui.item.index();
     },


     stop: function (event, ui) 
     {      
      var newIndex = ui.item.index();  

最佳答案

更新:移动到可排序版本的底部

不可排序版本

在您编辑和提到排序之前,我创建了一个似乎满足您要求的 jsfiddle:http://jsfiddle.net/fENSD/4/

我所做的是创建一个计算的可观察对象,它观察您的可观察项目并返回一个嵌套数组,其形状是您想要用于表格渲染的。这不是最有效的函数,但通过一些工作,您可能会减少分配的数组数量(目前,每次更新时都会为 4x4 网格创建 5 个左右):

self.items = ko.observableArray(["images/1.jpg", "images/2.jpg", "images/3.jpg", "images/4.jpg", "images/5.jpg", "images/6.jpg"]);

self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
    var rows = [];
    var count = 0;
    var items = self.items(); //get the item array
    var current = [];
    for(var i in items)
    {
        var item = items[i];
        current.push(item);
        count++;

        if (count == 4)
        {
            count = 0;
            rows.push(current);
            current = []; //next array
        }
    }

    if (current.length > 0)
    {
        rows.push(current);
    }

    return rows;
});

然后表格呈现如下:

<table data-bind="foreach: itemRows">
    <tr data-bind="foreach: $data">
        <td><img data-bind="attr: { src: $data }" /></td>
    </tr>
</table>

JSFiddle 包含一个示例,该示例将一个项目添加到 items observable 中,并更新表以反射(reflect)这一点,如果您希望看到它的实际效果。 JSFiddle 中还有一个示例,说明您可以通过一种方式获取项目数组的长度 (data-bind="text: items().length")。

排序版本

这是一个很大的变化,但我也设法让排序工作正常。以 jquery ui 网站为例,我得到以下内容:

http://jsfiddle.net/fENSD/11/

很难对表进行排序,因此 jquery ui 示例实际上使用了一个列表,该列表具有定义的宽度,每个元素占据一定的宽度。这有效地创建了一个表。我假设由于您使用的是图像,所以您可以使它们的大小完全相同。

为此,我有一些像这样的 CSS:

#items { list-style-type: none; margin: 0; padding: 0; width: 200px; }
#items li { width: 48px; margin: 0px; padding: 0px; float: left; text-align: center; height: 48px; }

然后我像这样创建了一个合适的绑定(bind)处理程序:

ko.bindingHandlers['sortable'] = {
    init: function (element, valueAccessor) {
        var $element = $(element);
        var observable = valueAccessor();
        var value = ko.utils.unwrapObservable(observable);
        $element.sortable({
            stop: function(event, ui) {
                var prev = ui.item.prev();
                var data = ko.dataFor(ui.item[0]);
                var index = 0;
                if (prev.length > 0) {
                    //not the first item
                    var prevData = ko.dataFor(prev[0]);
                    var index = value.indexOf(prevData) + 1;
                }
                var oldIndex = value.indexOf(data);
                value.splice(oldIndex, 1);
                value.splice(index, 0, data);
                observable.valueHasMutated();
            }
        });
    }
};

每当 sortable 更新时,它都会修改传递给绑定(bind)的可观察数组。 注意:这是非常不稳健的,需要检查以确保传递的值实际上是可观察的,然后再告诉它它的值已经发生变化。

View 模型如下所示:

function ViewModel() {
    var self = this;

    self.items = ko.observableArray(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"]);

    self.items.subscribe(function (value) {
        console.log(value); //this is so you can see that the array is indeed being re-sorted
    });

    self.add = function () {
        self.items.push("another thing");
    };
}

并渲染:

<ul id="items" data-bind="sortable: items, foreach: items">
    <li><img data-bind="attr: { src: $data }" /></li>
</ul>

此方法的局限性在于,如果您的项目大小不同,则 sortable 的顺序看起来与内存中实际表示的顺序略有不同。但是,只要所有元素的大小都相同,它应该可以正常工作。另一个问题是这不适用于重复项。然而,要解决这个问题,只需让每个元素成为包含一个值(甚至可能是一个可观察值)的对象,而不是一个普通的旧字符串。

关于javascript - 动态行创建挖空js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15105737/

相关文章:

javascript - 使用 radio 输入和 knockoutjs 选择客户地址

php - 在 firebug 或 chrome 开发人员中更改客户端的 javascript 变量

java - 复制数组并使用 printall() 方法将其大小加 1 以返回新数组中的所有 int

javascript - 迭代函数数组

arrays - 计算反转?

javascript - 如果从浏览器控制台提交,Knockoutjs 不会保存数据

php - 如何使 HTML 表单输入变灰?

javascript - 格式化 HTML 代码时单选按钮中的 Jquery <br/> 问题

javascript - 如何使用angularjs获取html元素内的文本?

javascript - 根据单选按钮的可见性执行验证