ko grouped options

groupComboBox

by onuralp

HTML

<script src="http://knockoutjs.com/downloads/knockout-1.2.1.js"></script>
<select data-bind="groupedOptions: availableAppActions, optionsText: 'label', optionsValue: 'value', optionsGroup: 'group', selectedOptions: Selected"></select>

JavaScript

(function () {
  ko.bindingHandlers["groupedOptions"] = {
    update: function (element, valueAccessor, allBindingsAccessor) {
        if (element.tagName != "SELECT")
            throw new Error("groupedOptions binding applies only to SELECT elements");

        var previousSelectedValues = [];
        for (var i = 0; i < element.childNodes.length; i++) {
            var node = element.childNodes[i];
            if (node.tagName == "OPTGROUP") {
                if (node.childNodes != undefined) {
                    for (var k = 0; k < node.childNodes.length; k++) {
                        var childNode = node.childNodes[k];
                        if (childNode.tagName && childNode.tagName && childNode.tagName == "OPTION" && childNode.selected) {
                            previousSelectedValues.push(ko.selectExtensions.readValue(childNode));
                        }
                    }
                }
            } else if (node.tagName && node.tagName == "OPTION" && node.selected) {
                previousSelectedValues.push(ko.selectExtensions.readValue(node));
            }
        }

        var previousScrollTop = element.scrollTop;

        var value = ko.utils.unwrapObservable(valueAccessor());

        // Clear existing elements
        element.innerHTML = "";

        if (value) {
            var allBindings = allBindingsAccessor();
            if (typeof value.length != "number")
                value = [value];
            if (allBindings['optionsCaption']) {
                var option = document.createElement("OPTION");
                option.innerHTML = allBindings['optionsCaption'];
                ko.selectExtensions.writeValue(option, undefined);
                element.appendChild(option);
            }

            var optionsGroupNamesValue = allBindings['optionsGroupNames'];

            // Group values into optgroups
            var groupedOptions = [];
            var optionsGroupValue = allBindings['optionsGroup']; // undefined if...