JSFiddle - React, Tailwind, and code Playground

by corinnekm

HTML

<body>
    	<h1>Contacts</h1>

    <table id="contacts-table">
        <tr id="contacts-head">
            <th>ID</th>
            <th>First name</th>
            <th>Last name</th>
            <th>Email</th>
            <th>Actions</th>
        </tr>
    </table>
    <form id="contacts-form">
        <div class="item text">
            <label>First name:</label>
            <div class="field">
                <input type="text" name="first_name" />
            </div>
        </div>
        <div class="item text">
            <label>Last name:</label>
            <div class="field">
                <input type="text" name="last_name" />
            </div>
        </div>
        <div class="item text">
            <label>Email:</label>
            <div class="field">
                <input type="text" name="email" />
            </div>
        </div>
        <div class="button-wrapper">
            <div class="item button">
                <div class="field">
                    <input type="button" id="contacts-op-discard" value="Discard" />
                </div>
            </div>
            <div class="item button button-default">
                <div class="field">
                    <input type="submit" id="contacts-op-save" value="Save" />
                </div>
            </div>
        </div>
        <input type="hidden" name="id_entry" value="0" />
    </form>
</body>

CSS

a {
    color: #0068D2;
    cursor: pointer;
}
a:link, a:visited {
    text-decoration: none;
    color: #0068D2;
}
a:hover, a:active {
    text-decoration: underline;
    color: #0068D2;
}
body {
    font: 12px/18px"Lucida Grande", "Lucida Sans Unicode", sans-serif;
}
#contacts-table {
    border-collapse: collapse;
}
#contacts-table, #contacts-table th, #contacts-table td {
    padding: 8px 16px;
    text-align: left;
    border: 0px solid #B9BABE;
}
#contacts-table th {
    font-weight: bold;
    font-size: 14px;
    color: #29344B;
}
#contacts-table td {
    color: #000;
}
#contacts-table tr:nth-child(2n) {
    background: #E8EDFF;
}
#contacts-form {
    padding: 10px;
}
.text input, .button input {
    padding: 5px;
    margin: 0;
    border: 1px solid #ccc;
    -moz-border-radius: 2px;
    -webkit-border-radius: 2px;
    border-radius: 2px;
}
#contacts-form .item {
    margin: 3px 0;
}
#contacts-form label, #contacts-form .field {
    display: inline-block;
    color: #0C0B07;
}
#contacts-form label {
    width: 110px;
    font-weight: bold;
    text-align: right;
    color: #666;
}
#contacts-form .text input {
    width: 176px;
    padding: 3px;
}
#contacts-form .button {
    display: inline-block;
}
#contacts-form .button-wrapper {
    padding-left: 113px;
}
.button input {
    padding: 4px 8px;
    color: #343434;
    background-color: #fdfdfd;
    background: -moz-linear-gradient(#fdfdfd, #e1e1e1);
    background: -webkit-gradient(linear, 0 0, 0 100%, from(#fdfdfd), to(#e1e1e1));
}
.button-default input {
    font-weight: bold;
    color: #fff;
    background-color: #7ca0c7;
    background: -moz-linear-gradient(#acc6e1, #7ca0c7);
    background: -webkit-gradient(linear, 0 0, 0 100%, from(#acc6e1), to(#7ca0c7));
    border-color: #5b80b2;
}

JavaScript

var Contacts = {
    index: window.localStorage.getItem("Contacts:index"),
    $table: document.getElementById("contacts-table"),
    $form: document.getElementById("contacts-form"),
    $button_save: document.getElementById("contacts-op-save"),
    $button_discard: document.getElementById("contacts-op-discard"),

    init: function () {
        // initialize storage index
        if (!Contacts.index) {
            window.localStorage.setItem("Contacts:index", Contacts.index = 1);
        }

        // initialize form
        Contacts.$form.reset();
        Contacts.$button_discard.addEventListener("click", function (event) {
            Contacts.$form.reset();
            Contacts.$form.id_entry.value = 0;
        }, true);
        Contacts.$form.addEventListener("submit", function (event) {
            var entry = {
                id: parseInt(this.id_entry.value),
                first_name: this.first_name.value,
                last_name: this.last_name.value,
                email: this.email.value
            };
            if (entry.id == 0) { // add
                Contacts.storeAdd(entry);
                Contacts.tableAdd(entry);
            } else { // edit
                Contacts.storeEdit(entry);
                Contacts.tableEdit(entry);
            }

            this.reset();
            this.id_entry.value = 0;
            event.preventDefault();
        }, true);

        // initialize table
        if (window.localStorage.length - 1) {
            var contacts_list = [],
                i, key;
            for (i = 0; i < window.localStorage.length; i++) {
                key = window.localStorage.key(i);
                if (/Contacts:\d+/.test(key)) {
                    contacts_list.push(JSON.parse(window.localStorage.getItem(key)));
                }
            }

            if (contacts_list.length) {
                contacts_list.sort(function (a, b) {
                    return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
             ...