JSFiddle - React, Tailwind, and code Playground

by jashwant

HTML

<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<div id="wrapper" class="container">
      <div id="flashWrapper">
          <div id="flash" class="alert alert-error"></div>  
      </div>
      <h3 id="title">
        Speed Dialer
      </h3>
      <ul id="grid">
        <script id="smartKeyTemplate" type='text/html'> 
          <div class="key btn"><%= hot_key %><span class="icon icon-trash pull-right"></span></div>
          <div class="edit">
            <input type="text" class="num" value="<%= num %>" placeholder="Enter number" />
            <input type="text" class="lbl" value="<%= label %>" placeholder="Enter label" />
            <div class="action">
              <button class='save-btn btn btn-info'>Save <span class="icon-ok icon icon-white"></span></button>
              <button class='cancel-btn btn btn-info'>Cancel <span class="icon-remove icon icon-white"></span></button>
            </div>
          </div> 
        </script> 
      </ul>
    </div>

CSS

ul {
     list-style: none;
 }
 #wrapper {
     margin-top: 20px;
     width: 260px;
 }
 #flashWrapper {
     height:40px;
 }
 #flash {
     display: none;
 }
 #title {
     color: #F96E5B;
     text-align: center;
 }
 #grid {
     position: relative;
     height: 260px;
     margin: 0 auto;
     -webkit-border-radius: 4px;
     -moz-border-radius: 4px;
     border-radius: 4px;
     background-color: #f6f6f6;
     border: 1px solid #e6e6e6;
 }
 .editing {
     border: 1px solid #E6E6E6;
     -webkit-border-radius: 4px;
     -moz-border-radius: 4px;
     border-radius: 4px;
 }
 .key {
     font-size: 18px;
     color: #666;
     line-height: 50px;
     position: relative;
     padding: 0;
     width: 100%;
 }
 .editing .key {
     width: 100%;
     font-size: 24px;
     cursor: default;
 }
 .icon-trash {
     display: none;
     position: absolute;
     right: 15px;
     top: 15px;
     cursor: pointer;
 }
 .assigned.editing .icon-trash {
     display: inline;
 }
 .dial .icon-trash.hidden {
     display: none;
 }
 .action {
     text-align: center;
     margin-top: 20px;
 }
 .overlay {
     z-index: 1;
 }
 .dial {
     color: #777;
     position: absolute;
     background: #f6f6f6;
     width: 50px;
     height: 50px;
 }
 .dial.assigned .key {
     color: Green;
 }
 .editing.assigned .key {
     color : #777;
 }
 .dial > .edit {
     display: none;
     margin: 20px;
 }
 .left0 {
     left: 40px;
 }
 .left1 {
     left:100px;
 }
 .left2 {
     left: 160px;
 }
 .top0 {
     top: 20px;
 }
 .top1 {
     top:80px;
 }
 .top2 {
     top:140px;
 }
 .top3 {
     top:200px;
 }

JavaScript

(function ($) {
    $(window).on('beforeunload', function () {
        if ($('.editing').length > 0) return 'You have unsaved changes. Are you sure, you want to leave ?';
    });

    var ItemView = Backbone.View.extend({
        tagName: 'li',
        className: function () {
            // The trick to place everything in phone dial style
            var hot_key = this.model.get('hot_key');
            var index = (hot_key === 0) ? 10 : hot_key - 1;
            var left = 'left' + (index % 3);
            var top = 'top' + (parseInt(index / 3, 10));
            return left + ' dial ' + top;
        },
        template: _.template($('#smartKeyTemplate').html()),
        events: {
            'click .key': 'edit',
                'keydown input': 'keyActions',
                'click .save-btn': 'save',
                'click .cancel-btn': 'cancel',
                'mouseenter': 'hover',
                'mouseleave': 'hover',
                'click .icon-trash': 'delete'
        },

        initialize: function () {
            this.HOT_KEYS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
            this.model.on('change', this.render, this);
            this.model.on('destroy', this.remove, this);
        },
        edit: function () {
            if (this.$el.hasClass('editing')) {
                return;
            }
            this.$el.addClass('editing');
            this.$('.icon-trash').removeClass('hidden');
            var position = this.$el.position();
            this.$el.data('css', {
                left: position.left,
                top: position.top,
                width: this.$el.css('width'),
                height: this.$el.css('height')
            });

            var dynamics = {
                left: '-5px',
                top: '-5px',
                height: '100%',
                width: '100%'
            };
            var self = this;
            this.$el.addClass('overlay').stop().animate(dynamics, 500, function () {
               ...