JSFiddle - React, Tailwind, and code Playground

by Alexander

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
<div class="SFAEquipmentGrant">
    <div class="wizard-header">
        <h3><abbr title="School Food Authority">SFA</abbr> Equipment Assistance Grant Application <small>Fiscal Yeay 2014</small></h3>
    </div>
    <div class="alert alert-info">
        <i class="fa fa-info-circle fa-lg fa-fw"></i><strong>Deadline:</strong> Applications must be submitted by <strong>MM/DD/YYYY</strong>.
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Please Login</h3>
        </div>
        <div class="panel-body">
            <div class="container">
                <form class="form-signin" role="form" data-bind="submit: login">
                    <input type="text" class="form-control" data-bind="value: username" placeholder="CE ID" required autofocus />
                    <input type="password" class="form-control" data-bind="value: password" placeholder="Password" required />
                    <button class="btn btn-lg btn-primary" type="submit">Sign in</button>
                    <button id="loginHelp" type="button" class="btn btn-default pull-right" data-container="body" data-toggle="popover" data-placement="top" data-original-title="Help" data-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">
                        <i class="fa fa-question-circle fa-lg"></i>Login  Help
                    </button>
                    <!--...

CSS

@import url(http://fonts.googleapis.com/css?family=Open+Sans|Spinnaker);

body, .badge, input {
    font-family: 'Open Sans', sans-serif;
}
.fa {
    margin-left: 2px;
}
button .fa {
    margin-right: 4px;
}
input.error {
    color: red;
    border-color: red;    
}
.wizard-header {
    font-family:'Spinnaker', sans-serif;
}
.SFAEquipmentGrant {
    margin: 0 8px;
    min-width: 250px;
}
#login-error {
    margin-top: 15px;
}
.form-signin {
  max-width: 330px;
  padding: 15px;
  margin: 0 auto;
}
.form-signin .checkbox {
  margin-bottom: 10px;
  font-weight: normal;
}
.form-signin .form-control {
  position: relative;
  height: auto;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
  padding: 10px;
  font-size: 16px;
}
.form-signin .form-control:focus {
  z-index: 2;
}
.form-signin input[type="email"] {
  margin-bottom: -1px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
  margin-bottom: 10px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

JavaScript

$('#loginHelp').popover()
$('.alert .close').on("click", function(e) {
    //closeAlert();
    viewModel.errorMessage = '';
});

ko.validation.configure({
    insertMessages: true,
    decorateElement: true,
    errorElementClass: 'error',
    messagesOnModified: false
});

function LoginViewModel() {
    var self = this;
    self.username = ko.observable().extend({
        required: true
    });
    self.password = ko.observable().extend({
        required: true
    });
    self.errors = ko.validation.group(self);
    self.login = function(e) {
        if (self.errors() == 0) {
            alert('No errors');
        } else {
            self.errors.showAllMessages(true);
        }
    };
};
$(function () {
    ko.applyBindings(LoginViewModel());
});