window.handler = new Object();
/*! Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)  */
;(function($){ // secure $ jQuery alias
// jquery.event.drag.js - rev 14 - release 1.2
// Liscensed under the MIT License (MIT-LICENSE.txt)
// http://www.opensource.org/licenses/mit-license.php
// Created: 2008-06-04 | Updated: 2008-10-06
/*******************************************************************************************/
// Events: drag, dragstart, dragend
/*******************************************************************************************/

// jquery method
$.fn.drag = function( fn1, fn2, fn3 ){
  if ( fn2 ) this.bind('dragstart', fn1 ); // 2+ args
  if ( fn3 ) this.bind('dragend', fn3 ); // 3 args
  return !fn1 ? this.trigger('drag') // 0 args
    : this.bind('drag', fn2 ? fn2 : fn1 ); // 1+ args
  };

// local refs
var $event = $.event, $special = $event.special,

// special event configuration
drag = $special.drag = {
  not: ':input', // don't begin to drag on event.targets that match this selector
  distance: 0, // default distance dragged before dragstart
  setup: function( data ){
    data = $.extend({ distance: drag.distance, not: drag.not }, data || {});
    data.distance = squared( data.distance ); //  x� + y� = distance�
    $event.add( this, "mousedown", handler, data );
    },
  teardown: function(){
    $event.remove( this, "mousedown", handler );
    if ( this === drag.dragging ) drag.dragging = drag.proxy = null; // deactivate element
    selectable( this, true ); // enable text selection
    }
  };

// handle drag-releatd DOM events
handler = function ( event ){
  var elem = this, returned, data = event.data || {};
  // mousemove or mouseup
  if ( elem === document ){
    // update event properties...
    event.dragTarget = elem = data.elem; // drag source element
    event.dragProxy = drag.proxy || elem; // proxy element or source
    event.cursorOffsetX = data.pageX - data.left; // mousedown offset
    event.cursorOffsetY = data.pageY - data.top; // mousedown offset
    event.offsetX = event.pageX - event.cursorOffsetX; // element offset
    event.offsetY = event.pageY - event.cursorOffsetY; // element offset
    }
  // mousedown, check some initial props to avoid the switch statement
  else
    if ( drag.dragging || event.which!=1 || $( event.target ).is( data.not ) ) return;
  // handle various events
  switch ( event.type ){
    // mousedown, left click, event.target is not restricted, init dragging
    case 'mousedown':
      $.extend( data, $( elem ).offset(), {
        elem: elem, target: event.target,
        pageX: event.pageX, pageY: event.pageY
        }); // store some initial attributes
      $event.add( document, "mousemove mouseup", handler, data );
      selectable( elem, false ); // disable text selection
      return false; // prevents text selection in safari
    // mousemove, check distance, start dragging
    case !drag.dragging && 'mousemove':
      if ( squared( event.pageX-data.pageX )
        + squared( event.pageY-data.pageY ) //  x� + y� = distance�
        < data.distance ) break; // distance tolerance not reached
      event.target = data.target; // force target from "mousedown" event (fix distance issue)
      returned = hijack( event, "dragstart", elem ); // trigger "dragstart", return proxy element
      if ( returned !== false ){ // "dragstart" not rejected
        drag.dragging = elem; // activate element
        drag.proxy = event.dragProxy = $( returned )[0] || elem; // set proxy
        }
    // mousemove, dragging
    case 'mousemove':
      if ( drag.dragging ){
        returned = hijack( event, "drag", elem ); // trigger "drag"
        if ( $special.drop ){ // manage drop events
          $special.drop.allowed = ( returned !== false ); // prevent drop
          $special.drop.handler( event ); // "dropstart", "dropend"
          }
        if ( returned !== false ) break; // "drag" not rejected, stop
        event.type = "mouseup"; // helps "drop" handler behave
        }
    // mouseup, stop dragging
    case 'mouseup':
      $event.remove( document, "mousemove mouseup", handler ); // remove page events
      if ( drag.dragging ){
        if ( $special.drop ) $special.drop.handler( event ); // "drop"
        hijack( event, "dragend", elem ); // trigger "dragend"
        }
      selectable( elem, true ); // enable text selection
      drag.dragging = drag.proxy = null; // deactivate element
      break;
    }
  };

// set event type to custom value, and handle it
function hijack ( event, type, elem ){
  event.type = type; // force the event type
  return $event.handle.call( elem, event );
  };

// return the value squared
function squared ( value ){ return Math.pow( value, 2 ); };

// toggles text selection attributes
function selectable ( elem, bool ){
  if ( !elem ) return; // maybe element was removed ?
  elem.unselectable = bool ? "off" : "on"; // IE
  elem.onselectstart = function(){ return bool; }; // IE
  if ( elem.style ) elem.style.MozUserSelect = bool ? "" : "none"; // FF
  };

/*******************************************************************************************/
})( jQuery ); // confine scope
