large dataset with custom binding using jQuery event handler

HTML

<script src="http://knockoutjs.com/downloads/knockout-3.1.0.js"></script>
Load and DOM manipulation time: ~<span data-bind='text: finishTime() - startTime'></span> ms

<div data-bind="myDataTable:{columns:ColumnName, data:gridData, click:gridNameClick}"></div>

CSS

.nameHeader {
    cursor: pointer; 
    text-decoration: underline;
}

JavaScript

ko.bindingHandlers.myDataTable = {
    init: function () {
        return { controlsDescendantBindings: true };
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var output = [],
            value = valueAccessor(),
            columns = ko.unwrap(value.columns),
            column1 = columns[0],
            column2 = columns[1],
            column3 = columns[2],
            data = ko.unwrap(value.data),
            dataLength = data.length,
            clickFunction = value.click;
        output.push('<table><tbody class="ngTBody">');
        for (var i = 0; i < dataLength; ++i) {
            output.push('<tr class="ngdatarow"><td><span class="nameHeader" data-index="');
            output.push(i + '">');
            output.push(data[i][column1]);
            output.push('</span></td><td><span class="displayBlock">');
            output.push(data[i][column2]);
            output.push('</span></td><td><span class="displayBlock">');
            output.push(data[i][column3]);
            output.push('</span></td></tr>');
        }
        output.push('</tbody></table>');
        element.innerHTML = output.join('');
        $(element).on('click', 'span.nameHeader', function (event) {
            var index = event.target.getAttribute('data-index');
            if (index) {
                clickFunction(data[index], event);
            }
        });
    }
};

function ViewModel() {
    var self = this;
    self.ColumnName = ko.observableArray();
    self.gridData = ko.observableArray();
    self.totalRowCount = ko.observable();
    self.selectedItems = ko.observableArray();
    self.selectedRowCount = ko.observable();

    self.updateGrid = function (gridDataSource, groupGridOptions) {
        self.ColumnName(groupGridOptions.ColumnNameList);
        self.gridData(gridDataSource);
        self.totalRowCount(self.gridData().length);
        self.selectedItems.removeAll();
        self.selectedRowCount(0);
    };
   ...