JSFiddle - React, Tailwind, and code Playground

by CyberLight

HTML

<script src="http://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>
<script src="https://raw.github.com/CodeSeven/KoLite/master/knockout.dirtyFlag.js"></script>
<div class ="userform" data-bind="with: user">
    <h4>Test user information</h4>
    <label>Name</label>
    <input type="text" data-bind="value: name"/>
    <label>E-mail</label>
    <input type="text" data-bind="value: email"/>
    <label>Address</label>
    <input type="text" data-bind="value: address"/>
    <div class="awards-title">
        <h4>Awards:</h4>
    </div>
    <div class="userAwardForm" data-bind="foreach: awards">
        <div class="userAwardForm">
            <label>Type of award:</label>
            <input type="text" data-bind="value: awardType">
            <label>Name of Contest</label>
            <input type="text" data-bind="value: contestName">
        </div>
    </div>
</div>
<div class="dirty-status">
    <span>Dirty status:   </span><a href="#" data-bind="text: modelStatus(), css: {ok : !dirtyFlag().isDirty(), nok : dirtyFlag().isDirty()}"  class="modern"></a>
</div>

<input type="button" class="Button" value="Reset dirty status" data-bind="click: clearDirty">

CSS

body{
    background-color: #456192 ;
    margin:20px;
}

label{
    display:block;
    color: white;
}
div.userform, div.userAwardForm{
   padding: 10px;
   border: solid white 1px;
}

div.userAwardForm{
    margin-top: 10px;
}

div.userform h4{
    font-weight : bold;
    font-size:24px;
    margin-bottom: 15px;
    color: white;
}

.awards-title{
    margin-top:10px;
}

.modern {
    height: 40px;
    padding: 0 5px;
    line-height: 40px;
    font-size: 14px;
    font-weight: bold;
    color: white;
    text-shadow: -1px -1px 0 #333;
    border-radius: 3px;
    text-decoration:none;
}
.ok{
     background: -moz-linear-gradient(#84AB69, #334823);
    background: -webkit-linear-gradient(#84AB69, #334823);
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#84AB69', endColorstr='#334823')";
}

.nok{
     background: -moz-linear-gradient(#ED3812, #7A1F05);
    background: -webkit-linear-gradient(#ED3812, #7A1F05);
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ED3812', endColorstr='#7A1F05')";
}

.dirty-status{
    height: 50px;
}

.dirty-status span{
    color: white;
}

.Button
{
    position: relative;
    cursor: pointer;
    display: inline-block;
    border: 1px solid #d5d5d5;
    text-decoration: none;
    font: 16px Arial;
    font-weight: bold;
    text-align: center;
    text-shadow:0px 0px 0px #444444;
    background: #ffffff;
    padding: 10px 16px;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
    color: #c13737;
    -moz-box-shadow:inset 0px 0px 0px;
    -webkit-box-shadow:inset 0px 0px 0px;
    box-shadow:inset 0px 0px 0px,
    0 3px 0 #aeaeae,
    0 5px 0 #c13737,
    0 8px 0 #aeaeae,
    0 10px 6px rgba(0,0,0, .60);
}

.Button:hover {
    background: #eeeeee;
    color: #eb5e7f;
    -moz-box-shadow:inset 0px 0px 0px;
    -webkit-box-shadow:inset 0px 0px 0px;
    box-shadow:inset 0px 0px 0px ,
    0 3px 0 rgba(235,94,127, .30),
    0 3px 0 #aeaeae,
    0...

JavaScript

$(function() {
    function Award(atp, contestNamev){
        var awardType = ko.observable(atp),
            contestName = ko.observable(contestNamev);
        return {
            awardType : awardType,
            contestName : contestName
        }
    }
            
    function Vm(){
        var user = {
            name : ko.observable('Alexey'),
            email : ko.observable('alexey@mail.me'),
            address : ko.observable('Moskow st. Petrov 12'),
            awards : ko.observableArray([new Award('silver','The best speaker'), new Award('gold','Brain Storm #2')])
        },
        dirtyFlag = ko.DirtyFlag(user);
        return {
            user : user,
            dirtyFlag : dirtyFlag,
            modelStatus : ko.computed(function(){
                return dirtyFlag().isDirty() ? "Changes detected" : "No changes";
            }),
            clearDirty : function(){
                dirtyFlag().reset();             
            }
        }
    };
  
    ko.applyBindings(new Vm());
});