JSFiddle - React, Tailwind, and code Playground

by rniemeyer

HTML

<script src="https://github.com/jquery/jquery-tmpl/raw/master/jquery.tmpl.js"></script>
<script src="https://github.com/SteveSanderson/knockout/raw/master/build/output/knockout-latest.debug.js"></script>
<script src="http://hoponster-soc.googlecode.com/hg-history/ba975cabf64a107c69c6f0a507847bae4c6a3827/app/jquery.min/jquery-editable-1.3.3.js"></script>
<table id="table1" cellspacing="0" cellpadding="0" border="0">
    <tr>
        <th style="width:150px">Product</th>
        <th>Price ($)</th>
        <th>Quantity</th>
        <th>Amount ($)</th>
    </tr>

    <tbody data-bind='template: {name: "orderTemplate", foreach: orders}'></tbody>
</table>

<script type="text/html" id="orderTemplate">
    <tr>
        <td data-bind="text: product"></td>
        <td class="editable number" data-bind="dataCell: price"></td>
        <td class="editable number"data-bind="dataCell: quantity"></td>
        <td class="number" data-bind="text: amount"></td>
    </tr>
</script>

CSS

table 
    {
        border: solid 1px #e8eef4;
        border-collapse: collapse;
    }
    
    table th
    {
        padding: 6px 5px;
        background-color: #e8eef4; 
        border: solid 1px #e8eef4;   
    }

    table td 
    {
        padding:0 3px 0 3px;
        margin: 0px;
        height: 20px;
        border: solid 1px #e8eef4;
    }

    td.number
    {
        width: 100px;
        text-align:right;
    }
    
    td.editable
    {
        background-color:#fff;
    }
    
    td.editable input
    {
        font-family: Verdana, Helvetica, Sans-Serif;
        text-align: right;
        width: 100%;
        height: 100%;
        border: 0;
    }
    
    td.editing
    {
        border: 2px solid Blue;
    }

JavaScript

$(function () {
    ko.bindingHandlers.dataCell = {

        init: function (element, valueAccessor) {
            ko.utils.registerEventHandler(element, "change", function () {
                var value = valueAccessor();
                setTimeout(function() { value($(element).text()); }, 0);
            });
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                existing = $(element).text();
            
            if (value != existing) {
                $(element).text(value);    
            }
        }

    };

    var order = function (product, price, quantity) {
        this.product = product;
        this.price = ko.observable(price);
        this.quantity = ko.observable(quantity);
        this.amount = ko.dependentObservable(function () {
            return this.price() * this.quantity();
        }, this);
    }

    var ordersModel = function () {
        this.orders = ko.observableArray([]);
    }


    var viewModel = new ordersModel();
    viewModel.orders = ko.observableArray([
            new order("Gala Apple", 0.79, 150),
            new order("Naval Orange", 0.29, 500)
        ]);

    ko.applyBindings(viewModel);

    $('.editable').editable({ onEdit: edit, onSubmit: submit, onCancel: cancel });
    
    $(".editable").change();
});

function edit(content) {
    $(this).addClass("editing");
    $(this).children('input').get(0).select();
}

function submit(content) {
    $(this).removeClass("editing");
    $(this).change();
}

function cancel(content) {
    $(this).removeClass("editing");
}