text: /*!
   * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
   * Dual-licensed under the BSD or MIT licenses
   */
  ;(function($, window, document, undefined)
  {
  	var hasTouch = 'ontouchstart' in window;
  
  	/**
  	 * Detect CSS pointer-events property
  	 * events are normally disabled on the dragging element to avoid conflicts
  	 * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
  	 */
  	var hasPointerEvents = (function()
  	{
  		var el    = document.createElement('div'),
  			docEl = document.documentElement;
  		if (!('pointerEvents' in el.style)) {
  			return false;
  		}
  		el.style.pointerEvents = 'auto';
  		el.style.pointerEvents = 'x';
  		docEl.appendChild(el);
  		var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
  		docEl.removeChild(el);
  		return !!supports;
  	})();
  
  	var eStart  = hasTouch ? 'touchstart'  : 'mousedown',
  		eMove   = hasTouch ? 'touchmove'   : 'mousemove',
  		eEnd    = hasTouch ? 'touchend'    : 'mouseup';
  		eCancel = hasTouch ? 'touchcancel' : 'mouseup';
  
  	var defaults = {
  			listNodeName    : 'ol',
  			itemNodeName    : 'li',
  			rootClass       : 'dd',
  			listClass       : 'dd-list',
  			notClass		: 'dd-not',
  			itemClass       : 'dd-item',
  			dragClass       : 'dd-dragel',            
  			handleClass     : 'dd-handle',
  			collapsedClass  : 'dd-collapsed',
  			placeClass      : 'dd-placeholder',
  			emptyClass      : 'dd-empty',
  			passiveClass	: 'dd-passive',
  			expandBtnHTML   : '<i data-action="expand" class="fa fa-plus-square"></i>',
  			collapseBtnHTML : '<i data-action="collapse" class="fa fa-minus-square"></i>',
  			group           : 0,
  			maxDepth        : 5,
  			threshold       : 20,
  			dragReverse     : false,
  			dropCallback    : null
  		};
  
  	function Plugin(element, options)
  	{
  		this.w  = $(window);
  		this.el = $(element);
  		this.options = $.extend({}, defaults, options);
  		this.init();
  	}
  
  	Plugin.prototype = {
  
  		init: function()
  		{
  			var list = this;
  
  			list.reset();
  
  			list.el.data('nestable-group', this.options.group);
  
  			list.placeEl = $('<div class="' + list.options.placeClass + '"/>');
  
  			$.each(this.el.find(list.options.itemNodeName), function(k, el) {
  				list.setParent($(el));
  			});
  
  			list.el.on('click', 'i', function(e) {
  				if (list.dragEl || (!hasTouch && e.button !== 0)) {
  					return;
  				}
  				var target = $(e.currentTarget),
  					action = target.data('action'),
  					item   = target.parent(list.options.itemNodeName);
  				if (action === 'collapse') {
  					list.collapseItem(item);
  				}
  				if (action === 'expand') {
  					list.expandItem(item);
  				}
  			});
  
  			var onStartEvent = function(e)
  			{
  				var handle = $(e.target);
  				if (!handle.hasClass(list.options.handleClass)) {
  					handle = handle.parents('.' + list.options.handleClass).first();
  				}
  				if (!handle.length || list.dragEl || (!hasTouch && e.button !== 0) || (hasTouch && e.touches.length !== 1)) {
  					return;
  				}
  				e.preventDefault();
  				list.dragStart(hasTouch ? e.touches[0] : e);
  			};
  
  			var onMoveEvent = function(e)
  			{
  				if (list.dragEl) {
  					e.preventDefault();
  					list.dragMove(hasTouch ? e.touches[0] : e);
  				}
  			};
  
  			var onEndEvent = function(e)
  			{
  				if (list.dragEl) {
  					e.preventDefault();
  					list.dragStop(hasTouch ? e.touches[0] : e);
  				}
  			};
  
  			if (hasTouch) {
  				list.el[0].addEventListener(eStart, onStartEvent, false);
  				window.addEventListener(eMove, onMoveEvent, false);
  				window.addEventListener(eEnd, onEndEvent, false);
  				window.addEventListener(eCancel, onEndEvent, false);
  			} else {
  				list.el.on(eStart, onStartEvent);
  				list.w.on(eMove, onMoveEvent);
  				list.w.on(eEnd, onEndEvent);
  			}
  
  		},
  
  		serialize: function()
  		{
  			var data,
  				depth = 0,
  				list  = this;
  				step  = function(level, depth)
  				{
  					var array = [ ],
  						items = level.children(list.options.itemNodeName);
  					items.each(function()
  					{
  						var li   = $(this),
  							item = $.extend({}, li.data()),
  							sub  = li.children(list.options.listNodeName);
  						if (sub.length) {
  							item.children = step(sub, depth + 1);
  						}
  						array.push(item);
  					});
  					return array;
  				};
  			data = step(list.el.find(list.options.listNodeName).first(), depth);
  			return data;
  		},
  
  		serialise: function()
  		{
  			return this.serialize();
  		},
  
  		reset: function()
  		{
  			this.mouse = {
  				offsetX   : 0,
  				offsetY   : 0,
  				startX    : 0,
  				startY    : 0,
  				lastX     : 0,
  				lastY     : 0,
  				nowX      : 0,
  				nowY      : 0,
  				distX     : 0,
  				distY     : 0,
  				dirAx     : 0,
  				dirX      : 0,
  				dirY      : 0,
  				lastDirX  : 0,
  				lastDirY  : 0,
  				distAxX   : 0,
  				distAxY   : 0
  			};
  			this.moving     = false;
  			this.dragEl     = null;
  			this.dragRootEl = null;
  			this.dragDepth  = 0;
  			this.hasNewRoot = false;
  			this.pointEl    = null;
  		},
  
  		expandItem: function(li)
  		{
  			li.removeClass(this.options.collapsedClass);
  			li.children('[data-action="expand"]').hide();
  			li.children('[data-action="collapse"]').show();
  			li.children(this.options.listNodeName).show();
  		},
  
  		collapseItem: function(li)
  		{
  			var lists = li.children(this.options.listNodeName);
  			if (lists.length) {
  				li.addClass(this.options.collapsedClass);
  				li.children('[data-action="collapse"]').hide();
  				li.children('[data-action="expand"]').show();
  				li.children(this.options.listNodeName).hide();
  			}
  		},
  
  		expandAll: function()
  		{
  			var list = this;
  			list.el.find(list.options.itemNodeName).each(function() {
  				list.expandItem($(this));
  			});
  		},
  
  		collapseAll: function()
  		{
  			var list = this;
  			list.el.find(list.options.itemNodeName).each(function() {
  				list.collapseItem($(this));
  			});
  		},
  
  		setParent: function(li)
  		{
  			// RED
  			if (li.children(this.options.listNodeName).length && li.has('button').length == 0) {
  				li.prepend($(this.options.expandBtnHTML));
  				li.prepend($(this.options.collapseBtnHTML));
  			}
  			li.children('[data-action="expand"]').hide();
  		},
  
  		unsetParent: function(li)
  		{
  			li.removeClass(this.options.collapsedClass);
  			li.children('[data-action]').remove();
  			li.children(this.options.listNodeName).remove();
  		},
  
  		dragStart: function(e)
  		{
  			var mouse    = this.mouse,
  				target   = $(e.target),
  				dragItem = target.parents(this.options.itemNodeName).first();
  
  			// if not move class, stop drag
  			if(dragItem.hasClass(this.options.notClass)) return;
  
  			this.placeEl.css('height', dragItem.height());
  
  			mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
  			mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
  
  			// RED
  			if(this.options.dragReverse) {
  				var fix = dragItem.width() - target.outerWidth();
  				mouse.offsetX = e.pageX - target.offset().left + fix;
  			}
  
  			mouse.startX = mouse.lastX = e.pageX;
  			mouse.startY = mouse.lastY = e.pageY;
  
  			this.dragRootEl = this.el;
  
  			this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
  			this.dragEl.css('width', dragItem.width());
  
  			// fix for zepto.js
  			//dragItem.after(this.placeEl).detach().appendTo(this.dragEl);
  			dragItem.after(this.placeEl);
  			dragItem[0].parentNode.removeChild(dragItem[0]);
  			dragItem.appendTo(this.dragEl);
  
  			// Append ghost element to body
  			$(document.body).append(this.dragEl);
  			this.dragEl.css({
  				'left' : e.pageX - mouse.offsetX,
  				'top'  : e.pageY - mouse.offsetY
  			});
  			// total depth of dragging item
  			var i, depth,
  				items = this.dragEl.find(this.options.itemNodeName);
  			for (i = 0; i < items.length; i++) {
  				depth = $(items[i]).parents(this.options.listNodeName).length;
  				if (depth > this.dragDepth) {
  					this.dragDepth = depth;
  				}
  			}
  		},
  
  		dragStop: function(e)
  		{
  			// fix for zepto.js
  			//this.placeEl.replaceWith(this.dragEl.children(this.options.itemNodeName + ':first').detach());
  			var el = this.dragEl.children(this.options.itemNodeName).first();
  			el[0].parentNode.removeChild(el[0]);
  			this.placeEl.replaceWith(el);
  
  			this.dragEl.remove();
  			this.el.trigger('reorder');
  
  			//Let's find out new parent id
  			var parentItem = el.parent().parent();
  			var parentId = null;
  			
  			if(parentItem !== null && !parentItem.is('.' + this.options.rootClass))
  				parentId = parentItem.data('id');
  			
  			if($.isFunction(this.options.dropCallback)) {
  				this.options.dropCallback.call(this, el.data('id'), el, parentId);
  			}
  
  			if (this.hasNewRoot) {
  				this.dragRootEl.trigger('reorder');
  			}
  			this.reset();
  		},
  
  		dragMove: function(e)
  		{
  			var list, parent, prev, next, depth,
  				opt   = this.options,
  				mouse = this.mouse;
  
  			this.dragEl.css({
  				'left' : e.pageX - mouse.offsetX,
  				'top'  : e.pageY - mouse.offsetY
  			});
  
  			// mouse position last events
  			mouse.lastX = mouse.nowX;
  			mouse.lastY = mouse.nowY;
  			// mouse position this events
  			mouse.nowX  = e.pageX;
  			mouse.nowY  = e.pageY;
  			// distance mouse moved between events
  			mouse.distX = mouse.nowX - mouse.lastX;
  			mouse.distY = mouse.nowY - mouse.lastY;
  			// direction mouse was moving
  			mouse.lastDirX = mouse.dirX;
  			mouse.lastDirY = mouse.dirY;
  			// direction mouse is now moving (on both axis)
  			mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
  			mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
  			// axis mouse is now moving on
  			var newAx   = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
  
  			// do nothing on first move
  			if (!mouse.moving) {
  				mouse.dirAx  = newAx;
  				mouse.moving = true;
  				return;
  			}
  
  			// calc distance moved on this axis (and direction)
  			if (mouse.dirAx !== newAx) {
  				mouse.distAxX = 0;
  				mouse.distAxY = 0;
  			} else {
  				mouse.distAxX += Math.abs(mouse.distX);
  				if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
  					mouse.distAxX = 0;
  				}
  				mouse.distAxY += Math.abs(mouse.distY);
  				if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {
  					mouse.distAxY = 0;
  				}
  			}
  			mouse.dirAx = newAx;
  
  			/**
  			 * move horizontal
  			 */
  			if (mouse.dirAx && mouse.distAxX >= opt.threshold) {
  				// reset move distance on x-axis for new phase
  				mouse.distAxX = 0;
  				prev = this.placeEl.prev(opt.itemNodeName);
  				// increase horizontal level if previous sibling exists and is not collapsed
  				if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
  					// cannot increase level when item above is collapsed
  					list = prev.find(opt.listNodeName).last();
  					// check if depth limit has reached
  					depth = this.placeEl.parents(opt.listNodeName).length;
  
  					if (depth + this.dragDepth <= opt.maxDepth) {
  						// create new sub-level if one doesn't exist
  						if (!list.length) {
  							list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);
  							list.append(this.placeEl);
  							prev.append(list);
  							this.setParent(prev);
  						} else {
  							// else append to next level up
  							list = prev.children(opt.listNodeName).last();
  							list.append(this.placeEl);
  						}
  					}
  				}
  				// decrease horizontal level
  				if (mouse.distX < 0) {
  					// we can't decrease a level if an item preceeds the current one
  					next = this.placeEl.next(opt.itemNodeName);
  					if (!next.length) {
  						parent = this.placeEl.parent();
  						this.placeEl.parents(opt.itemNodeName).first().after(this.placeEl);
  						if (!parent.children().length) {
  							this.unsetParent(parent.parent());
  						}
  					}
  				}
  			}
  
  			var isEmpty = false;
  
  			// find list item under cursor
  			if (!hasPointerEvents) {
  				this.dragEl[0].style.visibility = 'hidden';
  			}
  			this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - document.body.scrollTop));
  			if (!hasPointerEvents) {
  				this.dragEl[0].style.visibility = 'visible';
  			}
  			if (this.pointEl.hasClass(opt.handleClass)) {
  				this.pointEl = this.pointEl.parent(opt.itemNodeName);
  			}
  			if (this.pointEl.hasClass(opt.passiveClass)) {
  				this.pointEl = this.pointEl.parent(opt.itemNodeName);
  			}
  			if (this.pointEl.hasClass(opt.emptyClass)) {
  				isEmpty = true;
  			}
  			else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {
  				return;
  			}
  
  			// find parent list of item under cursor
  			var pointElRoot = this.pointEl.parents('.' + opt.rootClass).first(),
  				isNewRoot   = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
  
  			/**
  			 * move vertical
  			 */
  			if (!mouse.dirAx || isNewRoot || isEmpty) {
  				// check if groups match if dragging over new root
  				if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
  					return;
  				}
  				// check depth limit
  				depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
  
  				// console.log('basso ' + depth);
  				// RED
  				/*if (depth > opt.maxDepth) {
  					return;
  				}*/
  				var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
  					parent = this.placeEl.parent();
  				// if empty create new list to replace empty placeholder
  				if (isEmpty) {
  					list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
  					list.append(this.placeEl);
  					this.pointEl.replaceWith(list);
  				}
  				else if (before) {
  					this.pointEl.before(this.placeEl);
  				}
  				else {
  					this.pointEl.after(this.placeEl);
  				}
  				if (!parent.children().length) {
  					this.unsetParent(parent.parent());
  				}
  				if (!this.dragRootEl.find(opt.itemNodeName).length) {
  					this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>');
  				}
  				// parent root list has changed
  				if (isNewRoot) {
  					this.hasNewRoot = true;
  					this.dragRootEl = pointElRoot;
  				}
  			}
  		}
  
  	};
  
  	$.fn.nestable = function(params)
  	{
  		var lists  = this,
  			retval = this;
  
  		lists.each(function()
  		{
  			var plugin = $(this).data("nestable");
  
  			if (!plugin) {
  				$(this).data("nestable", new Plugin(this, params));
  				$(this).data("nestable-id", new Date().getTime());
  			} else {
  				if (typeof params === 'string' && typeof plugin[params] === 'function') {
  					retval = plugin[params]();
  				}
  			}
  		});
  
  		return retval || lists;
  	};
  
  })(window.jQuery || window.Zepto, window, document);
  