Utility functions in KnockoutJS

http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js"></script>

JavaScript

function Item(name, catid, category, price) {
    this.name = ko.observable(name);
    this.catid = ko.observable(catid);
    this.category = ko.observable(category);
    this.price = ko.observable(price);
    this.priceWithTax = ko.dependentObservable(function() {
        return (this.price() * 1.05).toFixed(2);
    }, this);
}

var viewModel = {
    categories: ["Bread", "Dairy", "Fruits", "Vegetables"],
    items: ko.observableArray([]),
    filter: ko.observable(""),
    search: ko.observable(""),
    addItem: function() {
        this.items.push(new Item("New", "", 1));
    },
    removeItem: function(item) {
        this.items.remove(item);
    }
};

//ko.utils.arrayFilter - filter the items using the filter text
viewModel.filteredItems = ko.dependentObservable(function() {
    var filter = this.filter().toLowerCase();
    if (!filter) {
        return this.items();
    } else {
        return ko.utils.arrayFilter(this.items(), function(item) {
            return ko.utils.stringStartsWith(item.name().toLowerCase(), filter);
        });
    }
}, viewModel);


//ko.utils.arrayForEach - return a total by adding all prices
viewModel.total = ko.dependentObservable(function() {
    var total = 0;
    ko.utils.arrayForEach(this.filteredItems(), function(item) {
        var value = parseFloat(item.priceWithTax());
        if (!isNaN(value)) {
            total += value;
        }
    });
    return total.toFixed(2);
}, viewModel);


//ko.utils.arrayFirst - identify the first matching item by name
viewModel.firstMatch = ko.dependentObservable(function() {
    var search = this.search().toLowerCase();
    if (!search) {
        return null;
    } else {
        return ko.utils.arrayFirst(this.filteredItems(), function(item) {
            return ko.utils.stringStartsWith(item.name().toLowerCase(), search);
        });
    }
}, viewModel);

//ko.utils.arrayMap - get a list of used categories
viewModel.justCategories = ko.dependentObservable(function() {
    var...