KnockoutJS & jQuery Datatable NEW custom binding (Bootstrap)

a custom knockout binding

by litespeedtdf

HTML

<script src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
<script src="//code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css">
<script src="https://rawgit.com/zachpainter77/zach-knockout.js/master/zach-knockout.debug.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/plug-ins/1.10.7/integration/bootstrap/3/dataTables.bootstrap.js"></script>
<button data-bind="click: add">ADD</button>&nbsp;&nbsp;Toggle Editing Mode <span data-bind="text: getEditMode"></span>

<input type="checkbox" data-bind="checked: inline" />
<br />
<br/>
<button data-bind="click: removeAll">Remove All</button>
<button data-bind="click: addAll">Add All</button>
<br />
<br />
<div id="wrapper">
    <table id="example" style="width:100%" class="table table-striped table-bordered dataTable">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Age</th>
                <th>Remove</th>
                <th>Edit</th>
            </tr>
        </thead>
        <tbody data-bind="DataTablesForEach: {data: people, options: { 
                          scrollY: 250, paging: true, dom: 'rtip', columns:[{width: '30px'},{width: '100px'},{width: '100px'},{width: '100px'},{width:'100px'}] }}">
            <tr style="height:50px;">
                <td><span data-bind="text: id" />
                </td>
                <td style="width:50px;"> <span data-bind="text: first, visible:!isEdit()"></span>

                    <input class="form-control input-sm" data-bind="textInput: first, visible: isEdit()" style="width:95%" />
                </td>
         ...

CSS

.table {
    margin-bottom: 0px;
}
#wrapper {
    padding:10px;
}

JavaScript

ko.bindingHandlers.DataTablesForEach = {
        page: 0,
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            valueAccessor().data.subscribe(function (changes) {
                var table = $(element).closest('table').DataTable();
                ko.bindingHandlers.DataTablesForEach.page = table.page();
                table.destroy();
            }, null, 'arrayChange');
            var nodes = Array.prototype.slice.call(element.childNodes, 0);
            ko.utils.arrayForEach(nodes, function (node) {
                if (node && node.nodeType !== 1) {
                    node.parentNode.removeChild(node);
                }
            });
            return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var value = ko.unwrap(valueAccessor()),
                key = 'DataTablesForEach_Initialized';
            var newValue = function () {
                return {
                    data: value.data || value,
                    afterRenderAll: function () {
                        var table = $(element).closest('table').DataTable(value.options);
                        if (value.options.paging) {
                            if (table.page.info().pages - ko.bindingHandlers.DataTablesForEach.page === 0) {
                                table.page(--ko.bindingHandlers.DataTablesForEach.page).draw(false);
                            } else {
                                table.page(ko.bindingHandlers.DataTablesForEach.page).draw(false);
                            }
                        }
                    }
                };
            };

            ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext);

            //if we have not previously marked this as initialized...