text: YUI.add('sortable', function (Y, NAME) {
  
  
      /**
       * The class allows you to create a Drag & Drop reordered list.
       * @module sortable
       */
      /**
       * The class allows you to create a Drag & Drop reordered list.
       * @class Sortable
       * @extends Base
       * @constructor
       */
  
  
      var Sortable = function() {
          Sortable.superclass.constructor.apply(this, arguments);
      },
      CURRENT_NODE = 'currentNode',
      OPACITY_NODE = 'opacityNode',
      CONT = 'container',
      ID = 'id',
      ZINDEX = 'zIndex',
      OPACITY = 'opacity',
      PARENT_NODE = 'parentNode',
      NODES = 'nodes',
      NODE = 'node';
  
  
      Y.extend(Sortable, Y.Base, {
          /**
          * @property delegate
          * @type DD.Delegate
          * @description A reference to the DD.Delegate instance.
          */
          delegate: null,
          /**
          * @property drop
          * @type DD.Drop
          * @description A reference to the DD.Drop instance
          */
          drop: null,
          initializer: function() {
              var id = 'sortable-' + Y.guid(),
                  delConfig = {
                      container: this.get(CONT),
                      nodes: this.get(NODES),
                      target: true,
                      invalid: this.get('invalid'),
                      dragConfig: {
                          groups: [ id ]
                      }
                  }, del;
  
              if (this.get('handles')) {
                  delConfig.handles = this.get('handles');
              }
              del = new Y.DD.Delegate(delConfig);
  
              this.set(ID, id);
  
              del.dd.plug(Y.Plugin.DDProxy, {
                  moveOnEnd: false,
                  cloneNode: true
              });
  
              this.drop =  new Y.DD.Drop({
                  node: this.get(CONT),
                  bubbleTarget: del,
                  groups: del.dd.get('groups')
              });
              this.drop.on('drop:enter', Y.bind(this._onDropEnter, this));
  
              del.on({
                  'drag:start': Y.bind(this._onDragStart, this),
                  'drag:end': Y.bind(this._onDragEnd, this),
                  'drag:over': Y.bind(this._onDragOver, this),
                  'drag:drag': Y.bind(this._onDrag, this)
              });
  
              this.delegate = del;
              Sortable.reg(this, id);
          },
          _up: null,
          _y: null,
          _onDrag: function(e) {
              if (e.pageY < this._y) {
                  this._up = true;
              } else if (e.pageY > this._y) {
                  this._up = false;
              }
  
              this._y = e.pageY;
          },
          /**
          * @private
          * @method _onDropEnter
          * @param Event e The Event Object
          * @description Handles the DropEnter event to append a new node to a target.
          */
          _onDropEnter: function(e) {
              var dropNode = e.drop.get(NODE),
                  dragNode = e.drag.get(NODE);
  
              if (!dropNode.test(this.get(NODES)) &&
                  !dragNode.get(PARENT_NODE).compareTo(dropNode)) {
                  dropNode.append(dragNode);
              }
          },
          /**
          * @private
          * @method _onDragOver
          * @param Event e The Event Object
          * @description Handles the DragOver event that moves the object in the list or to another list.
          */
          _onDragOver: function(e) {
              if (!e.drop.get(NODE).test(this.get(NODES))) {
                  return;
              }
              if (e.drag.get(NODE) === e.drop.get(NODE)) {
                  return;
              }
              // is drop a child of drag?
              if (e.drag.get(NODE).contains(e.drop.get(NODE))) {
                  return;
              }
              var same = false, dir, oldNode, newNode, dropsort, dropNode,
                  moveType = this.get('moveType').toLowerCase();
  
              if (e.drag.get(NODE).get(PARENT_NODE).contains(e.drop.get(NODE))) {
                  same = true;
              }
              if (same && moveType === 'move') {
                  moveType = 'insert';
              }
              switch (moveType) {
                  case 'insert':
                      dir = ((this._up) ? 'before' : 'after');
                      dropNode = e.drop.get(NODE);
                      if (Y.Sortable._test(dropNode, this.get(CONT))) {
                          dropNode.append(e.drag.get(NODE));
                      } else {
                          dropNode.insert(e.drag.get(NODE), dir);
                      }
                      break;
                  case 'swap':
                      Y.DD.DDM.swapNode(e.drag, e.drop);
                      break;
                  case 'move':
                  case 'copy':
                      dropsort = Y.Sortable.getSortable(e.drop.get(NODE).get(PARENT_NODE));
  
                      if (!dropsort) {
                          return;
                      }
  
                      Y.DD.DDM.getDrop(e.drag.get(NODE)).addToGroup(dropsort.get(ID));
  
                      //Same List
                      if (same) {
                          Y.DD.DDM.swapNode(e.drag, e.drop);
                      } else {
                          if (this.get('moveType') === 'copy') {
                              //New List
                              oldNode = e.drag.get(NODE);
                              newNode = oldNode.cloneNode(true);
  
                              newNode.set(ID, '');
                              e.drag.set(NODE, newNode);
                              dropsort.delegate.createDrop(newNode, [dropsort.get(ID)]);
                              oldNode.setStyles({
                                  top: '',
                                  left: ''
                              });
                          }
                          e.drop.get(NODE).insert(e.drag.get(NODE), 'before');
                      }
                      break;
              }
  
              this.fire(moveType, { same: same, drag: e.drag, drop: e.drop });
              this.fire('moved', { same: same, drag: e.drag, drop: e.drop });
          },
          /**
          * @private
          * @method _onDragStart
          * @param Event e The Event Object
          * @description Handles the DragStart event and initializes some settings.
          */
          _onDragStart: function() {
              var del = this.delegate,
                  lastNode = del.get('lastNode');
              if (lastNode && lastNode.getDOMNode()) {
                  lastNode.setStyle(ZINDEX, '');
              }
              del.get(this.get(OPACITY_NODE)).setStyle(OPACITY, this.get(OPACITY));
              del.get(CURRENT_NODE).setStyle(ZINDEX, '999');
          },
          /**
          * @private
          * @method _onDragEnd
          * @param Event e The Event Object
          * @description Handles the DragEnd event that cleans up the settings in the drag:start event.
          */
          _onDragEnd: function() {
              this.delegate.get(this.get(OPACITY_NODE)).setStyle(OPACITY, 1);
              this.delegate.get(CURRENT_NODE).setStyle(ZINDEX, '');
              this.delegate.get(CURRENT_NODE).setStyles({
                  top: '',
                  left: ''
              });
              this.sync();
          },
          /**
          * @method plug
          * @param Class cls The class to plug
          * @param Object config The class config
          * @description Passthrough to the DD.Delegate.ddplug method
          * @chainable
          */
          plug: function(cls, config) {
              //I don't like this.. Not at all, need to discuss with the team
              if (cls && cls.NAME.substring(0, 4).toLowerCase() === 'sort') {
                  this.constructor.superclass.plug.call(this, cls, config);
              } else {
                  this.delegate.dd.plug(cls, config);
              }
              return this;
          },
          /**
          * @method sync
          * @description Passthrough to the DD.Delegate syncTargets method.
          * @chainable
          */
          sync: function() {
              this.delegate.syncTargets();
              return this;
          },
          destructor: function() {
              this.drop.destroy();
              this.delegate.destroy();
              Sortable.unreg(this, this.get(ID));
          },
          /**
          * @method join
          * @param Sortable sel The Sortable list to join with
          * @param String type The type of join to do: full, inner, outer, none. Default: full
          * @description Join this Sortable with another Sortable instance.
          * <ul>
          *   <li>full: Exchange nodes with both lists.</li>
          *   <li>inner: Items can go into this list from the joined list.</li>
          *   <li>outer: Items can go out of the joined list into this list.</li>
          *   <li>none: Removes the join.</li>
          * </ul>
          * @chainable
          */
          join: function(sel, type) {
              if (!(sel instanceof Y.Sortable)) {
                  Y.error('Sortable: join needs a Sortable Instance');
                  return this;
              }
              if (!type) {
                  type = 'full';
              }
              type = type.toLowerCase();
              var method = '_join_' + type;
  
              if (this[method]) {
                  this[method](sel);
              }
  
              return this;
          },
          /**
          * @private
          * @method _join_none
          * @param Sortable sel The Sortable to remove the join from
          * @description Removes the join with the passed Sortable.
          */
          _join_none: function(sel) {
              this.delegate.dd.removeFromGroup(sel.get(ID));
              sel.delegate.dd.removeFromGroup(this.get(ID));
          },
          /**
          * @private
          * @method _join_full
          * @param Sortable sel The Sortable list to join with
          * @description Joins both of the Sortables together.
          */
          _join_full: function(sel) {
              this.delegate.dd.addToGroup(sel.get(ID));
              sel.delegate.dd.addToGroup(this.get(ID));
          },
          /**
          * @private
          * @method _join_outer
          * @param Sortable sel The Sortable list to join with
          * @description Allows this Sortable to accept items from the passed Sortable.
          */
          _join_outer: function(sel) {
              this.delegate.dd.addToGroup(sel.get(ID));
          },
          /**
          * @private
          * @method _join_inner
          * @param Sortable sel The Sortable list to join with
          * @description Allows this Sortable to give items to the passed Sortable.
          */
          _join_inner: function(sel) {
              sel.delegate.dd.addToGroup(this.get(ID));
          },
          /**
          * A custom callback to allow a user to extract some sort of id or any other data
          * from the node to use in the "ordering list" and then that data should be returned from the callback.
          * @method getOrdering
          * @param Function callback
          * @return Array
          */
          getOrdering: function(callback) {
              var ordering = [];
  
              if (!Y.Lang.isFunction(callback)) {
                  callback = function (node) {
                      return node;
                  };
              }
  
              Y.one(this.get(CONT)).all(this.get(NODES)).each(function(node) {
                  ordering.push(callback(node));
              });
              return ordering;
         }
      }, {
          NAME: 'sortable',
          ATTRS: {
              /**
              * @attribute handles
              * @description Drag handles to pass on to the internal DD.Delegate instance.
              * @type Array
              */
              handles: {
                  value: false
              },
              /**
              * @attribute container
              * @description A selector query to get the container to listen for mousedown events on. All "nodes" should be a child of this container.
              * @type String
              */
              container: {
                  value: 'body'
              },
              /**
              * @attribute nodes
              * @description A selector query to get the children of the "container" to make draggable elements from.
              * @type String
              */
              nodes: {
                  value: '.dd-draggable'
              },
              /**
              * @attribute opacity
              * @description The opacity to change the proxy item to when dragging.
              * @type String
              */
              opacity: {
                  value: '.75'
              },
              /**
              * @attribute opacityNode
              * @description The node to set opacity on when dragging (dragNode or currentNode). Default: currentNode.
              * @type String
              */
              opacityNode: {
                  value: 'currentNode'
              },
              /**
              * @attribute id
              * @description The id of this Sortable, used to get a reference to this Sortable list from another list.
              * @type String
              */
              id: {
                  value: null
              },
              /**
              * @attribute moveType
              * @description How should an item move to another list: insert, swap, move, copy. Default: insert
              * @type String
              */
              moveType: {
                  value: 'insert'
              },
              /**
              * @attribute invalid
              * @description A selector string to test if a list item is invalid and not sortable
              * @type String
              */
              invalid: {
                  value: ''
              }
          },
          /**
          * @static
          * @property _sortables
          * @private
          * @type Object
          * @description Hash map of all Sortables on the page.
          */
          _sortables: {},
          /**
          * @static
          * @method _test
          * @param {Node} node The node instance to test.
          * @param {String|Node} test The node instance or selector string to test against.
          * @description Test a Node or a selector for the container
          */
          _test: function(node, test) {
              var ret;
              if (test instanceof Y.Node) {
                  ret = (test === node);
              } else {
                  ret = node.test(test);
              }
              return ret;
          },
          /**
          * @static
          * @method getSortable
          * @param {String|Node} node The node instance or selector string to use to find a Sortable instance.
          * @description Get a Sortable instance back from a node reference or a selector string.
          */
          getSortable: function(node) {
              var s = null,
                  id = null;
              node = Y.one(node);
              id = node.get(ID);
              if(id && Y.Sortable._sortables[id]) {
                  return Y.Sortable._sortables[id];
              }
              Y.Object.each(Y.Sortable._sortables, function(v) {
                  if (Y.Sortable._test(node, v.get(CONT))) {
                      s = v;
                  }
              });
              return s;
          },
          /**
          * @static
          * @method reg
          * @param Sortable s A Sortable instance.
          * @param String id (optional) The id of the sortable instance.
          * @description Register a Sortable instance with the singleton to allow lookups later.
          */
          reg: function(s, id) {
              if (!id) {
                  id = s.get(ID);
              }
              Y.Sortable._sortables[id] = s;
          },
          /**
          * @static
          * @method unreg
          * @param Sortable s A Sortable instance.
          * @param String id (optional) The id of the sortable instance.
          * @description Unregister a Sortable instance with the singleton.
          */
          unreg: function(s, id) {
              if (!id) {
                  id = s.get(ID);
              }
              if (id && Y.Sortable._sortables[id]) {
                  delete Y.Sortable._sortables[id];
                  return;
              }
              Y.Object.each(Y.Sortable._sortables, function(v, k) {
                  if (v === s) {
                      delete Sortable._sortables[k];
                  }
              });
          }
      });
  
      Y.Sortable = Sortable;
  
      /**
      * @event copy
      * @description A Sortable node was moved with a copy.
      * @param {EventFacade} event An Event Facade object
      * @param {Boolean} event.same Moved to the same list.
      * @param {DD.Drag} event.drag The drag instance.
      * @param {DD.Drop} event.drop The drop instance.
      */
      /**
      * @event move
      * @description A Sortable node was moved with a move.
      * @param {EventFacade} event An Event Facade object with the following specific property added:
      * @param {Boolean} event.same Moved to the same list.
      * @param {DD.Drag} event.drag The drag instance.
      * @param {DD.Drop} event.drop The drop instance.
      */
      /**
      * @event insert
      * @description A Sortable node was moved with an insert.
      * @param {EventFacade} event An Event Facade object with the following specific property added:
      * @param {Boolean} event.same Moved to the same list.
      * @param {DD.Drag} event.drag The drag instance.
      * @param {DD.Drop} event.drop The drop instance.
      */
      /**
      * @event swap
      * @description A Sortable node was moved with a swap.
      * @param {EventFacade} event An Event Facade object with the following specific property added:
      * @param {Boolean} event.same Moved to the same list.
      * @param {DD.Drag} event.drag The drag instance.
      * @param {DD.Drop} event.drop The drop instance.
      */
      /**
      * @event moved
      * @description A Sortable node was moved.
      * @param {EventFacade} event An Event Facade object with the following specific property added:
      * @param {Boolean} event.same Moved to the same list.
      * @param {DD.Drag} event.drag The drag instance.
      * @param {DD.Drop} event.drop The drop instance.
      */
  
  
  
  }, '@VERSION@', {"requires": ["dd-delegate", "dd-drop-plugin", "dd-proxy"]});
  