JSFiddle - React, Tailwind, and code Playground

by Couto

HTML

<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<div class="row">
    <div class="well span12">
        <div id="1" class="draggable hidden">1</div>
        <div id="2" class="draggable hidden">2</div>
    </div>
</div>
<div class="row">
  <div class="alert alert-success span1 hidden"><i class="icon-ok"></i>Saved</div>
</div>

CSS

.well {
  margin: 30px 30px 0 30px;
  height: 300px;
  position: relative;
}

.hidden {
display: none;
}

.btn {
  margin: -15px 30px;
}

.alert {
margin: 5px 30px;

}

.icon-ok {
opacity: .5;
margin-right: 5px;
}

.draggable {
  width: 120px;
  height: 120px;
  padding: 10px;
  color: #666;
  text-shadow: 0px 1px 1px #fff;
  border-radius: 5px;
  border: 1px solid #ccc;
  cursor: move;
  -webkit-box-shadow: 0px 0px 5px rgba(0,0,0,.2);
  -moz-box-shadow: 0px 0px 5px rgba(0,0,0,.2);
  -o-box-shadow: 0px 0px 5px rgba(0,0,0,.2);
  -ms-box-shadow: 0px 0px 5px rgba(0,0,0,.2);
  box-shadow: 0px 0px 5px rgba(0,0,0,.2);
  background-image: linear-gradient(bottom, rgb(230,230,230) 0%, rgb(235,235,235) 100%);
  background-image: -o-linear-gradient(bottom, rgb(230,230,230) 0%, rgb(235,235,235) 100%);
  background-image: -moz-linear-gradient(bottom, rgb(230,230,230) 0%, rgb(235,235,235) 100%);
  background-image: -webkit-linear-gradient(bottom, rgb(230,230,230) 0%, rgb(235,235,235) 100%);
  background-image: -ms-linear-gradient(bottom, rgb(230,230,230) 0%, rgb(235,235,235) 100%);
  background-image: -webkit-gradient(
      linear,
      left bottom,
      left top,
      color-stop(0, rgb(230,230,230)),
      color-stop(1, rgb(235,235,235))
  );    
}

JavaScript

$(function() {
    // Pede as posicoes iniciais
    // e no sucesso, cria os elementos draggable nas posicoes correctas
    $.ajax('http://couto.jsapp.us', {
        type: 'GET',
        dataType: 'json'
    }).success(positionateSquares);
    
    // Ouve os eventos de que os draggables vão disparar
    // dragstart para esconder o aviso
    // dragstop para guardar as posicoes
    $('.draggable').on({
        'dragstart': function() {
            $('.alert').fadeOut();
        },
        'dragstop': function(evt, draggable) {
            var positions = {};
            // Quando paramos de arrastar um draggable
            // Vamos buscar as posicoes de todos os elementos draggables
            // e mandamos para o servidor
            $('.draggable').each(function(idx, drag) {
                positions[$(drag).attr('id')] = $(drag).position();
            });
            // Este pedido devia ser um pedido de POST ou PUT
            // mas devido a limitacoes no servidor
            // estou a usar um GET
            $.ajax('http://couto.jsapp.us/save/', {
                type: 'GET',
                dataType: 'json',
                data: encodeURIComponent(JSON.stringify(positions))
            }).success(function() {
                $('.alert-success').fadeIn();
            });

        }
    });

    // Podes ver o codigo de server side em http://jsapp.us/s/298.js
    // O primeiro pedido de todo o sempre (quando nao ha dados na BD)
    // Ele devolve um valor por defeito, somente para posicionarmos os
    // elementos

    function positionateSquares(data) {
        var k;
        data = JSON.parse(data);
        
        for (k in data) {
            if (data.hasOwnProperty(k)) {

                $('#' + k).css({
                    'position': 'absolute',
                    'top': data[k].top + 'px',
                    'left': data[k].left + 'px'
                }).draggable({containment: 'parent'}).fadeIn();
            }
        }
    }


});