Draggies

The projects we are currently working on. :)

Draggies

Postby comstar » Sun Feb 28, 2010 2:19 pm

Here's the source for that drag-and-drop demo.
Attachments
draggies.src.tgz
(56.98 KiB) Downloaded 13 times
Nobody writes jokes in base 13. I may be a pretty sad person, but I don't make jokes in base 13.
User avatar
comstar
Seaman
 
Posts: 332
Joined: Tue May 24, 2005 11:19 am
Location: Santa Cruz, CA

Re: Draggies

Postby comstar » Sun Feb 28, 2010 2:24 pm

For easier viewing, I'll post the key pieces of it:

server.js : this runs on the server
Code: Select all
var sys = require('sys'),
    http = require('http'),
    fs = require('fs'),
    json = require('./json'),
    faye = require('./faye');

var comet = new faye.NodeAdapter({mount: '/fayeclient', timeout: 45}),
    client = comet.getClient();

// setup sync client; TODO move into a separate module
var state = {};
client.subscribe('/general', function(message) {
// TODO discard malformed messages
   if (!message.client || !message.type) return;
   sys.puts('sync noticed message from client ' + message.client);
   sys.puts('message type == ' + message.type);
   switch (message.type) {
      case 'place' :
         state[message.el] || (state[message.el] = {});
         process.mixin(state[message.el], {
            x: message.x,
            y: message.y
         });
         break;
      case 'text' :
         process.mixin(state[message.el], {
            text: message.text,
         });
         break;
      case 'delete' :
         delete state[message.el];
         break;
   }
   sys.puts("state: ");
   sys.puts(json.stringify(state));
});

var port = 80;

sys.puts('Listening on ' + port);

http.createServer(function(req, resp) {
   sys.puts(req.method + ' ' + req.url);
   if (comet.call(req, resp)) {
      sys.puts('** Handled by faye');
      return;
   }

  var path = (req.url === '/') ? '/index.html' : req.url;
  if (path === '/sync') {
      sys.puts('** Handled by syncserver');
      resp.sendHeader(200, {'Content-Type': 'text/html'});
      resp.write(json.stringify(state));
      resp.close();
      return;
  }
  sys.puts('** Handled by file server');
  fs.readFile('./static/' + path).addCallback(function(content) {
    resp.sendHeader(200, {'Content-Type': 'text/html'});
    resp.write(content);
    resp.close();
  }).addErrback(function(){
    resp.sendHeader(404, {'Content-Type': 'text/html'});
    resp.write('<html><head><title>404 not found</title></head><body>404 Not Found</body></html>');
    resp.close();
  });
}).listen(port);



draggies.js : this runs on the client
Code: Select all
if (typeof console == "undefined") { console = {log: function(m){}} };

var Remote = function(fayeclient, clientId) {
   var fayepath = '/general';

   this.publish = function(message){
      return fayeclient.publish(fayepath, message);
   };

   this.clientId = clientId;

   fayeclient.subscribe(fayepath, function(message) {
      console.log('message recieved');
      console.log(message);
      if (message.client == clientId) {
         console.log('loopback; ignore');
         return;
      }
      $('body').trigger('dg-message', message);
   });

   $('body').bind('dg-message', function(e, args) {
      args.type && $('body').trigger('dg-' + args.type, args);
   });
}

Remote.prototype = {
   fire: function(eventType, parameters) {
      console.log('starting fayesend');
      var data = { client: this.clientId, type: eventType };
      $.extend(data, parameters);
      console.log('sending data');
      console.log(data);
      this.publish(data);
   }
};

$(function(){
   var getNewId = function() {
         // TODO overwrite with a hashing algorithm?
         return 'xxxxxxxx-xxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
         });
      };

   $('body').bind('dg-place', function(e, message) {
      console.log('place handler');
      console.log(message);
      if ($('#'+message.el)[0]) {
         $('#'+message.el).css({
            left: message.x,
            top: message.y
         });
      } else {
          newBox(message.el, {left: message.x, top: message.y});
      }
      console.log(message.el);
   });

   $('body').bind('dg-text', function(e, message) {
      console.log('text handler');
      console.log(message);
      $('#'+message.el).html('<span class="dg-letter">'+message.text+'</span>');
   });

   $('body').bind('dg-delete', function(e, message) {
      console.log('deletion handler');
      console.log(message);
      $('#'+message.el).remove();
   });

   var clientId = getNewId(),
       fayeclient = new Faye.Client('/fayeclient'),
       remote = new Remote(fayeclient, clientId),
       selected = null,
       select = function(el) {
          $(selected).removeClass('dg-selected');
          selected = el == null ? null : $(el).addClass('dg-selected');
       },
       newBox = function(id, data) {
         var boxHtml = data.text
            ? '<div class="dg-box"><span class="dg-letter">'+data.text+'</div>'
            : '<div class="dg-box"></div>';
         return $(boxHtml).appendTo($('#dg-boxstart'))
            .draggable({
               containment: 'window',
               distance: 30,
               grid: [51, 51],
               stop: function(event, ui){
                  if (ui.helper.hasClass('dg-dead')) return;
                  select(ui.helper);
                  remote.fire('place', {
                     el: ui.helper.attr('id'),
                     x: ui.position.left,
                     y: ui.position.top
                  });
               }
            }).css({
               top: data.top || data.y,
               left: data.left || data.x
            }).attr('id', id)
            .click(function(e) {
               console.log('box click fired');
               console.log(e.currentTarget);
               select(e.currentTarget);
            });
      };

   $(".dg-spawn").draggable({
      containment: 'window',
      grid: [51, 51],
      helper: 'clone',
      stop: function(event, ui){
         var newId = 'dg-box-' + getNewId();
         var box = newBox(newId, ui.position);
         select(box);
         remote.fire('place', {
            el: newId,
            x: ui.position.left,
            y: ui.position.top,
         });
      }
   });

   $(".dg-trash").droppable({
      drop: function(event, ui){
         if (ui.draggable.hasClass('dg-target')) return;
         remote.fire('delete', { el: ui.draggable.attr('id')});
         ui.draggable.addClass('dg-dead').remove();
      }
   });

   // listen for deselect-click
   $('html').add('.dg-banner').click(function(e){
      e.preventDefault();
      // deselect any selected items
      if (e.target == this) {
         console.log('click deselect');
         select(null);
      }
   });

   // listen for ESC (deselect)
   // TODO get this shit working
   /*$(document).keypress(function(e){
      console.log('keypress');
      console.log(e);
      e.charCode == 27 && console.log('ESC triggered');
   });*/
   $(document).keydown(function(e){
      console.log('keydown');
      console.log(e.keyCode);
      var key = e.which || e.keyCode;
      if (32 <= key && key <= 126) {
         //set selected state to keyCode
         var text = String.fromCharCode(key);
         $(selected).html('<span class="dg-letter">' + text + '</div>');
         remote.fire('text', { el: $(selected).attr('id'), text: text });
      }
   });

   $.getJSON('/sync', function(data) {
      console.log('sync data recieved: ');
      console.log(data);
      $.each(data, function(id, data) {
         newBox(id, data);
      });
   });
});


html :
Code: Select all
<html>
<head>
   <title>draggies</title>
   <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?3.0.0/build/cssreset/reset-min.css&3.0.0/build/cssfonts/fonts-min.css">
   <link rel="stylesheet" href="draggies.css"/>
   <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
   <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
   <script type="text/javascript" src="fayeclient.js"></script>
   <script type="text/javascript" src="draggies.js"></script>
</head>
<body>

<div class="dg-banner">
   <div class="dg-target dg-spawn">
      Drag me
   </div>
   <div class="dg-target dg-trash">
      Trash
   </div>
</div>
<div id="dg-boxstart">
</div>

</body>
</html>


css :
Code: Select all
html, body {
   background-color: #888;
}

.dg-banner {
   border: 1px solid black;
   border-left-width: 0;
   border-right-width: 0;
   background-color: white;
   height: 120px;
   position: relative;
}

.dg-target {
   border: 2px solid black;
   height: 100px;
   width: 100px;
   background-color: white;
}

.dg-spawn {
   position: absolute;
   top: 8px;
   left: 8px;
}

.dg-trash {
   position: absolute;
   top: 8px;
   right: 8px;
   border-color: red;
   color: red;
}

.dg-box {
   height: 100px;
   width: 100px;
   background-color: white;
   border: 1px solid black;
   position: absolute;
   top: 0;
   left: 0;
   text-align: center;
}

.dg-box .dg-letter {
   font-size: 764%;
}

.dg-selected {
   background-color: orange;
}

Nobody writes jokes in base 13. I may be a pretty sad person, but I don't make jokes in base 13.
User avatar
comstar
Seaman
 
Posts: 332
Joined: Tue May 24, 2005 11:19 am
Location: Santa Cruz, CA

Re: Draggies

Postby comstar » Sun Feb 28, 2010 2:25 pm

This is what runs the js on the server:

http://nodejs.org/

This is the faye toolkit I used for the project:

http://github.com/jcoglan/faye/
Nobody writes jokes in base 13. I may be a pretty sad person, but I don't make jokes in base 13.
User avatar
comstar
Seaman
 
Posts: 332
Joined: Tue May 24, 2005 11:19 am
Location: Santa Cruz, CA


Return to Local Projects

Who is online

Users browsing this forum: No registered users and 1 guest

cron