如何使用Isotope为Knockout observableArray中的项目布置HTML元素?

时间:2013-02-12 16:34:15

标签: javascript jquery knockout.js jquery-isotope

给定一个Knockout observableArray,可以添加和删除哪些项目,如何使用Isotope布置相应的HTML元素?例如考虑下面的HTML,它声明了一个div #container,它应该用Knockout填充子div:

<div id="container" data-bind="foreach: items, click: addItem">
<div class="item show" data-bind="text: text, click: $parent.removeItem, clickBubble: false"></div>

随附的JavaScript使用几个项目预先填充容器,并允许用户单击项目以删除它们并单击容器以添加新项目(通过Knockout):

function ItemModel(parent) {
    var value, self = this,
        found;
    for (value = 0; value < parent.items().length; ++value) {
        found = false;
        for (i in parent.items()) {
            var item = parent.items()[i];
            if (item.value() == value) {
                found = true;
                break;
            }
        }
        if (!found) {
            break;
        }
    }
    this.value = ko.observable(value);

    this.text = ko.computed(function () {
        return "Item " + self.value();
    });
}

var ViewModel = function () {
    var self = this;
    self.items = ko.observableArray()
    self.items.push(new ItemModel(self));
    self.items.push(new ItemModel(self));

    this.removeItem = function (item) {
        self.items.remove(item);
        return false;
    };

    this.addItem = function () {
        self.items.push(new ItemModel(self));
    };
};

ko.applyBindings(new ViewModel("Test"));

当与Isotope正确配合时,物品应由Isotope自动布局,包括物品被移除,添加和移动时。

请参阅this fiddle了解该概念的演示。

2 个答案:

答案 0 :(得分:0)

我已经能够通过编写一个名为Knockout-Isotope的特殊Knockout绑定将Knockout与Isotope集成。这有助于大大整合这两种技术,并确保Isotope与Knockout视图模型保持同步。请参阅下面的代码,了解如何将此绑定与Knockout observableArray一起使用,或尝试实时fiddle

请注意,此绑定依赖于Knockout的分支以便工作。

代码

Demo fiddle

<强> HTML:

<h1>Knockout Isotope Binding Demo</h1>
<p>This is a demonstration of the 
 <a href="https://github.com/aknuds1/knockout-isotope">Knockout-Isotope</a>
 binding for <a href="http://knockoutjs.com/">Knockout</a>, which visualizes
 Knockout observableArrays through
 <a href="http://isotope.metafizzy.co/index.html">Isotope</a>.
</p>

<p>Click on an item to remove it or click in the item container to add a new item</p>
<div id="container" data-bind="isotope: { data: items, isotopeOptions: getOptions }, click: addItem">
  <div data-bind="text: text, click: $parent.removeItem, clickBubble: false"></div>
</div>

<强> JavaScript的:

function ItemModel(parent) {
    var value, self = this,
        found, i;
    for (value = 0; value < parent.items().length; ++value) {
        found = false;
        for (i in parent.items()) {
            var item = parent.items()[i];
            if (item.value() == value) {
                found = true;
                break;
            }
        }
        if (!found) {
            break;
        }
    }
    this.value = ko.observable(value);

    this.text = ko.computed(function () {
        return "Item " + self.value();
    });
}

var ViewModel = function () {
    var self = this;
    self.items = ko.observableArray();
    self.items.push(new ItemModel(self));
    self.items.push(new ItemModel(self));

    this.removeItem = function (item) {
        self.items.remove(item);
    };

    this.addItem = function () {
        self.items.push(new ItemModel(self));
    };

    // Knockout callback for getting Isotope options
    this.getOptions = function () {
        return {
            masonry: {
                columnWidth: 210
            }
        };
    };
};

ko.applyBindings(new ViewModel("Test"));

答案 1 :(得分:0)

这可能是一种解决方案......或者是一种开始的方式

 <div id="Items" data-bind=" foreach: Items">

    <div class="item" data-bind="masonry: { container: '#Items'  }"> 
    </div>  
 </div>
  

ko.bindingHandlers.masonry = {       init:function(element,valueAccessor,allBindingsAccessor,viewModel,bindingContext){

},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

    var $el = $(element);
    var value = ko.utils.unwrapObservable(valueAccessor());


    var container = document.querySelector(value.container);
    var msnry = Masonry.data(container);


    if (!msnry) {
        var msnry = new Masonry(container);
    }
    msnry.addItems($el)
    msnry.layout();
    msnry.bindResize();
},
     

};