Add drag and drop to structure side_bar
This commit is contained in:
		
							parent
							
								
									63f904d3b0
								
							
						
					
					
						commit
						fd52d00187
					
				
							
								
								
									
										1
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										1
									
								
								Gemfile
								
								
								
								
							|  | @ -10,6 +10,7 @@ gem 'devise', '1.5.3' | ||||||
| gem 'exception_notification' # Send error trace | gem 'exception_notification' # Send error trace | ||||||
| gem 'execjs' | gem 'execjs' | ||||||
| gem 'jquery-rails' | gem 'jquery-rails' | ||||||
|  | gem 'jquery-ui-rails' | ||||||
| 
 | 
 | ||||||
| gem 'kaminari', :git => 'git://github.com/amatsuda/kaminari.git' | gem 'kaminari', :git => 'git://github.com/amatsuda/kaminari.git' | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -96,6 +96,9 @@ GEM | ||||||
|     jquery-rails (1.0.19) |     jquery-rails (1.0.19) | ||||||
|       railties (~> 3.0) |       railties (~> 3.0) | ||||||
|       thor (~> 0.14) |       thor (~> 0.14) | ||||||
|  |     jquery-ui-rails (0.4.0) | ||||||
|  |       jquery-rails | ||||||
|  |       railties (>= 3.1.0) | ||||||
|     json (1.6.5) |     json (1.6.5) | ||||||
|     linecache19 (0.5.12) |     linecache19 (0.5.12) | ||||||
|       ruby_core_source (>= 0.1.4) |       ruby_core_source (>= 0.1.4) | ||||||
|  | @ -269,6 +272,7 @@ DEPENDENCIES | ||||||
|   execjs |   execjs | ||||||
|   factory_girl_rails |   factory_girl_rails | ||||||
|   jquery-rails |   jquery-rails | ||||||
|  |   jquery-ui-rails | ||||||
|   kaminari! |   kaminari! | ||||||
|   mini_magick |   mini_magick | ||||||
|   mongo_session_store-rails3 |   mongo_session_store-rails3 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,391 @@ | ||||||
|  | /* | ||||||
|  |  * jQuery UI Nested Sortable | ||||||
|  |  * v 1.3.4 / 28 apr 2011 | ||||||
|  |  * http://mjsarfatti.com/sandbox/nestedSortable
 | ||||||
|  |  * | ||||||
|  |  * Depends: | ||||||
|  |  *	 jquery.ui.sortable.js 1.8+ | ||||||
|  |  * | ||||||
|  |  * License CC BY-SA 3.0 | ||||||
|  |  * Copyright 2010-2011, Manuele J Sarfatti | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | (function($) { | ||||||
|  | 
 | ||||||
|  | 	$.widget("ui.nestedSortable", $.extend({}, $.ui.sortable.prototype, { | ||||||
|  | 
 | ||||||
|  | 		options: { | ||||||
|  | 			tabSize: 20, | ||||||
|  | 			disableNesting: 'ui-nestedSortable-no-nesting', | ||||||
|  | 			errorClass: 'ui-nestedSortable-error', | ||||||
|  | 			listType: 'ol', | ||||||
|  | 			maxLevels: 0, | ||||||
|  | 			revertOnError: 1 | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_create: function() { | ||||||
|  | 			this.element.data('sortable', this.element.data('nestedSortable')); | ||||||
|  | 			return $.ui.sortable.prototype._create.apply(this, arguments); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		destroy: function() { | ||||||
|  | 			this.element | ||||||
|  | 				.removeData("nestedSortable") | ||||||
|  | 				.unbind(".nestedSortable"); | ||||||
|  | 			return $.ui.sortable.prototype.destroy.apply(this, arguments); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_mouseDrag: function(event) { | ||||||
|  | 
 | ||||||
|  | 			//Compute the helpers position
 | ||||||
|  | 			this.position = this._generatePosition(event); | ||||||
|  | 			this.positionAbs = this._convertPositionTo("absolute"); | ||||||
|  | 
 | ||||||
|  | 			if (!this.lastPositionAbs) { | ||||||
|  | 				this.lastPositionAbs = this.positionAbs; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			//Do scrolling
 | ||||||
|  | 			if(this.options.scroll) { | ||||||
|  | 				var o = this.options, scrolled = false; | ||||||
|  | 				if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { | ||||||
|  | 
 | ||||||
|  | 					if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) | ||||||
|  | 						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; | ||||||
|  | 					else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) | ||||||
|  | 						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; | ||||||
|  | 
 | ||||||
|  | 					if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) | ||||||
|  | 						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; | ||||||
|  | 					else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) | ||||||
|  | 						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; | ||||||
|  | 
 | ||||||
|  | 				} else { | ||||||
|  | 
 | ||||||
|  | 					if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) | ||||||
|  | 						scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); | ||||||
|  | 					else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) | ||||||
|  | 						scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); | ||||||
|  | 
 | ||||||
|  | 					if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) | ||||||
|  | 						scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); | ||||||
|  | 					else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) | ||||||
|  | 						scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); | ||||||
|  | 
 | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) | ||||||
|  | 					$.ui.ddmanager.prepareOffsets(this, event); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			//Regenerate the absolute position used for position checks
 | ||||||
|  | 			this.positionAbs = this._convertPositionTo("absolute"); | ||||||
|  | 
 | ||||||
|  | 			//Set the helper position
 | ||||||
|  | 			if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; | ||||||
|  | 			if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; | ||||||
|  | 
 | ||||||
|  | 			//Rearrange
 | ||||||
|  | 			for (var i = this.items.length - 1; i >= 0; i--) { | ||||||
|  | 
 | ||||||
|  | 				//Cache variables and intersection, continue if no intersection
 | ||||||
|  | 				var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); | ||||||
|  | 				if (!intersection) continue; | ||||||
|  | 
 | ||||||
|  | 				if(itemElement != this.currentItem[0] //cannot intersect with itself
 | ||||||
|  | 					&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
 | ||||||
|  | 					&&	!$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
 | ||||||
|  | 					&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true) | ||||||
|  | 					//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
 | ||||||
|  | 				) { | ||||||
|  | 
 | ||||||
|  | 					$(itemElement).mouseenter(); | ||||||
|  | 
 | ||||||
|  | 					this.direction = intersection == 1 ? "down" : "up"; | ||||||
|  | 
 | ||||||
|  | 					if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { | ||||||
|  | 						$(itemElement).mouseleave(); | ||||||
|  | 						this._rearrange(event, item); | ||||||
|  | 					} else { | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// Clear emtpy ul's/ol's
 | ||||||
|  | 					this._clearEmpty(itemElement); | ||||||
|  | 
 | ||||||
|  | 					this._trigger("change", event, this._uiHash()); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			var parentItem = (this.placeholder[0].parentNode.parentNode | ||||||
|  | 				       && $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length) | ||||||
|  | 				       ? $(this.placeholder[0].parentNode.parentNode) | ||||||
|  | 				       : null, | ||||||
|  | 			    level = this._getLevel(this.placeholder), | ||||||
|  | 			    childLevels = this._getChildLevels(this.helper), | ||||||
|  | 			    previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null; | ||||||
|  | 
 | ||||||
|  | 			if (previousItem != null) { | ||||||
|  | 				while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0]) { | ||||||
|  | 					if (previousItem[0].previousSibling) { | ||||||
|  | 						previousItem = $(previousItem[0].previousSibling); | ||||||
|  | 					} else { | ||||||
|  | 						previousItem = null; | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			newList = document.createElement(o.listType); | ||||||
|  | 
 | ||||||
|  | 			this.beyondMaxLevels = 0; | ||||||
|  | 
 | ||||||
|  | 			// If the item is moved to the left, send it to its parent level
 | ||||||
|  | 			if (parentItem != null && this.positionAbs.left < parentItem.offset().left) { | ||||||
|  | 				parentItem.after(this.placeholder[0]); | ||||||
|  | 				this._clearEmpty(parentItem[0]); | ||||||
|  | 				this._trigger("change", event, this._uiHash()); | ||||||
|  | 			} | ||||||
|  | 			// If the item is below another one and is moved to the right, make it a children of it
 | ||||||
|  | 			else if (previousItem != null && this.positionAbs.left > previousItem.offset().left + o.tabSize) { | ||||||
|  | 				this._isAllowed(previousItem, level+childLevels+1); | ||||||
|  | 				if (!previousItem.children(o.listType).length) { | ||||||
|  | 					previousItem[0].appendChild(newList); | ||||||
|  | 				} | ||||||
|  | 				previousItem.children(o.listType)[0].appendChild(this.placeholder[0]); | ||||||
|  | 				this._trigger("change", event, this._uiHash()); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				this._isAllowed(parentItem, level+childLevels); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			//Post events to containers
 | ||||||
|  | 			this._contactContainers(event); | ||||||
|  | 
 | ||||||
|  | 			//Interconnect with droppables
 | ||||||
|  | 			if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); | ||||||
|  | 
 | ||||||
|  | 			//Call callbacks
 | ||||||
|  | 			this._trigger('sort', event, this._uiHash()); | ||||||
|  | 
 | ||||||
|  | 			this.lastPositionAbs = this.positionAbs; | ||||||
|  | 			return false; | ||||||
|  | 
 | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_mouseStop: function(event, noPropagation) { | ||||||
|  | 
 | ||||||
|  | 			// If the item is in a position not allowed, send it back
 | ||||||
|  | 			if (this.beyondMaxLevels) { | ||||||
|  | 
 | ||||||
|  | 				this.placeholder.removeClass(this.options.errorClass); | ||||||
|  | 
 | ||||||
|  | 				if (this.options.revertOnError) { | ||||||
|  | 					if (this.domPosition.prev) { | ||||||
|  | 						$(this.domPosition.prev).after(this.placeholder); | ||||||
|  | 					} else { | ||||||
|  | 						$(this.domPosition.parent).prepend(this.placeholder); | ||||||
|  | 					} | ||||||
|  | 					this._trigger("revert", event, this._uiHash()); | ||||||
|  | 				} else { | ||||||
|  | 					var parent = this.placeholder.parent().closest(this.options.items); | ||||||
|  | 
 | ||||||
|  | 					for (var i = this.beyondMaxLevels - 1; i > 0; i--) { | ||||||
|  | 						parent = parent.parent().closest(this.options.items); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					parent.after(this.placeholder); | ||||||
|  | 					this._trigger("change", event, this._uiHash()); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Clean last empty ul/ol
 | ||||||
|  | 			for (var i = this.items.length - 1; i >= 0; i--) { | ||||||
|  | 				var item = this.items[i].item[0]; | ||||||
|  | 				this._clearEmpty(item); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$.ui.sortable.prototype._mouseStop.apply(this, arguments); | ||||||
|  | 
 | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		serialize: function(o) { | ||||||
|  | 
 | ||||||
|  | 			var items = this._getItemsAsjQuery(o && o.connected), | ||||||
|  | 			    str = []; o = o || {}; | ||||||
|  | 
 | ||||||
|  | 			$(items).each(function() { | ||||||
|  | 				var res = ($(o.item || this).attr(o.attribute || 'id') || '') | ||||||
|  | 						.match(o.expression || (/(.+)[-=_](.+)/)), | ||||||
|  | 				    pid = ($(o.item || this).parent(o.listType) | ||||||
|  | 						.parent('li') | ||||||
|  | 						.attr(o.attribute || 'id') || '') | ||||||
|  | 						.match(o.expression || (/(.+)[-=_](.+)/)); | ||||||
|  | 
 | ||||||
|  | 				if (res) { | ||||||
|  | 					str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']') | ||||||
|  | 						+ '=' | ||||||
|  | 						+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : 'root')); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			if(!str.length && o.key) { | ||||||
|  | 				str.push(o.key + '='); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return str.join('&'); | ||||||
|  | 
 | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		toHierarchy: function(o) { | ||||||
|  | 
 | ||||||
|  | 			o = o || {}; | ||||||
|  | 			var sDepth = o.startDepthCount || 0, | ||||||
|  | 			    ret = []; | ||||||
|  | 
 | ||||||
|  | 			$(this.element).children('li').each(function () { | ||||||
|  | 				var level = _recursiveItems($(this)); | ||||||
|  | 				ret.push(level); | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			return ret; | ||||||
|  | 
 | ||||||
|  | 			function _recursiveItems(li) { | ||||||
|  | 				var id = ($(li).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); | ||||||
|  | 				if (id) { | ||||||
|  | 					var item = {"id" : id[2]}; | ||||||
|  | 					if ($(li).children(o.listType).children('li').length > 0) { | ||||||
|  | 						item.children = []; | ||||||
|  | 						$(li).children(o.listType).children('li').each(function() { | ||||||
|  | 							var level = _recursiveItems($(this)); | ||||||
|  | 							item.children.push(level); | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					return item; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		toArray: function(o) { | ||||||
|  | 
 | ||||||
|  | 			o = o || {}; | ||||||
|  | 			var sDepth = o.startDepthCount || 0, | ||||||
|  | 			    ret = [], | ||||||
|  | 			    left = 2; | ||||||
|  | 
 | ||||||
|  | 			ret.push({ | ||||||
|  | 				"item_id": 'root', | ||||||
|  | 				"parent_id": 'none', | ||||||
|  | 				"depth": sDepth, | ||||||
|  | 				"left": '1', | ||||||
|  | 				"right": ($('li', this.element).length + 1) * 2 | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			$(this.element).children('li').each(function () { | ||||||
|  | 				left = _recursiveArray(this, sDepth + 1, left); | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			ret = ret.sort(function(a,b){ return (a.left - b.left); }); | ||||||
|  | 
 | ||||||
|  | 			return ret; | ||||||
|  | 
 | ||||||
|  | 			function _recursiveArray(item, depth, left) { | ||||||
|  | 
 | ||||||
|  | 				var right = left + 1, | ||||||
|  | 				    id, | ||||||
|  | 				    pid; | ||||||
|  | 
 | ||||||
|  | 				if ($(item).children(o.listType).children('li').length > 0) { | ||||||
|  | 					depth ++; | ||||||
|  | 					$(item).children(o.listType).children('li').each(function () { | ||||||
|  | 						right = _recursiveArray($(this), depth, right); | ||||||
|  | 					}); | ||||||
|  | 					depth --; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/)); | ||||||
|  | 
 | ||||||
|  | 				if (depth === sDepth + 1) { | ||||||
|  | 					pid = 'root'; | ||||||
|  | 				} else { | ||||||
|  | 					var parentItem = ($(item).parent(o.listType) | ||||||
|  | 						.parent('li') | ||||||
|  | 						.attr(o.attribute || 'id')) | ||||||
|  | 						.match(o.expression || (/(.+)[-=_](.+)/)); | ||||||
|  | 					pid = parentItem[2]; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (id) { | ||||||
|  | 						ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right}); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				left = right + 1; | ||||||
|  | 				return left; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_clearEmpty: function(item) { | ||||||
|  | 
 | ||||||
|  | 			var emptyList = $(item).children(this.options.listType); | ||||||
|  | 			if (emptyList.length && !emptyList.children().length) { | ||||||
|  | 				emptyList.remove(); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_getLevel: function(item) { | ||||||
|  | 
 | ||||||
|  | 			var level = 1; | ||||||
|  | 
 | ||||||
|  | 			if (this.options.listType) { | ||||||
|  | 				var list = item.closest(this.options.listType); | ||||||
|  | 				while (!list.is('.ui-sortable')) { | ||||||
|  | 					level++; | ||||||
|  | 					list = list.parent().closest(this.options.listType); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return level; | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_getChildLevels: function(parent, depth) { | ||||||
|  | 			var self = this, | ||||||
|  | 			    o = this.options, | ||||||
|  | 			    result = 0; | ||||||
|  | 			depth = depth || 0; | ||||||
|  | 
 | ||||||
|  | 			$(parent).children(o.listType).children(o.items).each(function (index, child) { | ||||||
|  | 					result = Math.max(self._getChildLevels(child, depth + 1), result); | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			return depth ? result + 1 : result; | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		_isAllowed: function(parentItem, levels) { | ||||||
|  | 			var o = this.options; | ||||||
|  | 			// Are we trying to nest under a no-nest or are we nesting too deep?
 | ||||||
|  | 			if (parentItem == null || !(parentItem.hasClass(o.disableNesting))) { | ||||||
|  | 				if (o.maxLevels < levels && o.maxLevels != 0) { | ||||||
|  | 					this.placeholder.addClass(o.errorClass); | ||||||
|  | 					this.beyondMaxLevels = levels - o.maxLevels; | ||||||
|  | 				} else { | ||||||
|  | 					this.placeholder.removeClass(o.errorClass); | ||||||
|  | 					this.beyondMaxLevels = 0; | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				this.placeholder.addClass(o.errorClass); | ||||||
|  | 				if (o.maxLevels < levels && o.maxLevels != 0) { | ||||||
|  | 					this.beyondMaxLevels = levels - o.maxLevels; | ||||||
|  | 				} else { | ||||||
|  | 					this.beyondMaxLevels = 1; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	})); | ||||||
|  | 
 | ||||||
|  | 	$.ui.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.ui.nestedSortable.prototype.options); | ||||||
|  | })(jQuery); | ||||||
|  | @ -5,6 +5,9 @@ | ||||||
| // the compiled file.
 | // the compiled file.
 | ||||||
| //
 | //
 | ||||||
| //= require jquery
 | //= require jquery
 | ||||||
|  | //= require jquery.ui.draggable
 | ||||||
|  | //= require jquery.ui.droppable
 | ||||||
|  | //= require jquery.ui.sortable
 | ||||||
| //= require jquery_ujs
 | //= require jquery_ujs
 | ||||||
| //= require bootstrap
 | //= require bootstrap
 | ||||||
| //= require jquery.isotope.min
 | //= require jquery.isotope.min
 | ||||||
|  | @ -14,4 +17,5 @@ | ||||||
| //= require side_bar_history
 | //= require side_bar_history
 | ||||||
| //= require page_edit
 | //= require page_edit
 | ||||||
| //= require tinymce-jquery
 | //= require tinymce-jquery
 | ||||||
| //= require tinymce_orbit
 | //= require tinymce_orbit
 | ||||||
|  | //= require lib/jquery.ui.nestedSortable.js
 | ||||||
|  | @ -6,13 +6,13 @@ | ||||||
| .nav-list li { | .nav-list li { | ||||||
| 	position: relative; | 	position: relative; | ||||||
| } | } | ||||||
| .nav-list ul { | .nav-list ol { | ||||||
| 	margin-left: 10px; | 	margin-left: 10px; | ||||||
| } | } | ||||||
| .nav-list ul li { | .nav-list ol li { | ||||||
| 	padding: 5px 0; | 	padding: 5px 0; | ||||||
| } | } | ||||||
| .nav-list ul li a { | .nav-list ol li a { | ||||||
| 	font-size: 13px; | 	font-size: 13px; | ||||||
| 	padding: 3px 0px; | 	padding: 3px 0px; | ||||||
| 	display: block; | 	display: block; | ||||||
|  |  | ||||||
|  | @ -15,6 +15,10 @@ class Admin::ItemsController < ApplicationController | ||||||
|       @item = get_homepage |       @item = get_homepage | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   def update_position | ||||||
|  |     render :nothing => true | ||||||
|  |   end | ||||||
|    |    | ||||||
|   protected |   protected | ||||||
|    |    | ||||||
|  |  | ||||||
|  | @ -9,8 +9,8 @@ module Admin::ItemHelper | ||||||
|         when 'Link' |         when 'Link' | ||||||
|           dest = admin_link_path(node) |           dest = admin_link_path(node) | ||||||
|       end |       end | ||||||
|       ret << "<ul>" unless node.parent.nil? |       # ret << "<ol>" unless node.parent.nil? | ||||||
|       ret << "<li>" |       ret << "<li id='#{node.id}'>" | ||||||
|       ret << "<div class='with_action'>" |       ret << "<div class='with_action'>" | ||||||
|       ret << (link_to node.i18n_variable[I18n.locale], dest) |       ret << (link_to node.i18n_variable[I18n.locale], dest) | ||||||
|       ret << "<div class='quick-edit hide'>" |       ret << "<div class='quick-edit hide'>" | ||||||
|  | @ -22,7 +22,7 @@ module Admin::ItemHelper | ||||||
|       ret << "</div>" |       ret << "</div>" | ||||||
|       ret << render_children(node) |       ret << render_children(node) | ||||||
|       ret << "</li>" |       ret << "</li>" | ||||||
|       ret << "</ul>" unless node.parent.nil? |       # ret << "</ol>" unless node.parent.nil? | ||||||
|     end |     end | ||||||
|     ret.html_safe |     ret.html_safe | ||||||
|   end |   end | ||||||
|  | @ -31,13 +31,27 @@ module Admin::ItemHelper | ||||||
|     children = parent.ordered_children |     children = parent.ordered_children | ||||||
|     if !children.entries.blank? |     if !children.entries.blank? | ||||||
|       ret = '' |       ret = '' | ||||||
|  |       ret << "<ol class='#{'sortable' if parent.parent.nil?}'>" | ||||||
|       children.each do |child| |       children.each do |child| | ||||||
|         ret << render_node_and_children(child) |         ret << render_node_and_children(child) | ||||||
|       end |       end | ||||||
|  |       ret << '</ol>' | ||||||
|       ret |       ret | ||||||
|     else |     else | ||||||
|       '' |       '' | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|    |    | ||||||
| end | end | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # <ol class="sortable"> | ||||||
|  | #   <li><div>Some content</div></li> | ||||||
|  | #   <li><div>Some content</div> | ||||||
|  | #     <ol> | ||||||
|  | #       <li><div>Some sub-item content</div></li> | ||||||
|  | #       <li><div>Some sub-item content</div></li> | ||||||
|  | #     </ol> | ||||||
|  | #   </li> | ||||||
|  | #   <li><div>Some content</div></li> | ||||||
|  | # </ol> | ||||||
|  | @ -1 +1,28 @@ | ||||||
| <%= render_node_and_children(Item.first(:conditions => {:parent_id => nil})) %> | <%= render_node_and_children(Item.first(:conditions => {:parent_id => nil})) %> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | 	$(document).ready(function(){ | ||||||
|  | 		$('ol.sortable').nestedSortable({ | ||||||
|  | 			disableNesting: 'no-nest', | ||||||
|  | 			forcePlaceholderSize: true, | ||||||
|  | 			handle: 'div', | ||||||
|  | 			helper:	'clone', | ||||||
|  | 			items: 'li', | ||||||
|  | 			maxLevels: 3, | ||||||
|  | 			opacity: .6, | ||||||
|  | 			placeholder: 'placeholder', | ||||||
|  | 			revert: 250, | ||||||
|  | 			tabSize: 25, | ||||||
|  | 			tolerance: 'pointer', | ||||||
|  | 			toleranceElement: '> div', | ||||||
|  | 
 | ||||||
|  | 			stop: function(event, ui) { | ||||||
|  | 				$.post("<%= admin_update_position_path %>", { id: ui.item.attr('id'), parent_id: ui.item.parent().closest('li').attr('id'), position: ui.item.index() } ); | ||||||
|  |         // console.log("parent: " + ui.item.parent().closest('li').attr('id')); | ||||||
|  |         // console.log("id: " + ui.item.attr('id')); | ||||||
|  |         // console.log("position: " + ui.item.index()); | ||||||
|  |     	} | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | </script> | ||||||
|  | @ -23,9 +23,9 @@ | ||||||
| 		</div> | 		</div> | ||||||
| 		<div class="viewport"> | 		<div class="viewport"> | ||||||
| 			<div id='back_sidebar' class="overview"> | 			<div id='back_sidebar' class="overview"> | ||||||
| 				<ul class="nav nav-list"> | 				<ol class="nav nav-list"> | ||||||
| 					<%= yield :sidebar %> | 					<%= yield :sidebar %> | ||||||
| 				</ul> | 				</ol> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</nav> | 	</nav> | ||||||
|  |  | ||||||
|  | @ -49,6 +49,7 @@ Orbit::Application.routes.draw do | ||||||
|       get 'add_attribute_field' |       get 'add_attribute_field' | ||||||
|     end |     end | ||||||
|     resources :items |     resources :items | ||||||
|  |     match 'update_position' => 'items#update_position' | ||||||
|     resources :links do |     resources :links do | ||||||
|       member do |       member do | ||||||
|         get 'delete' |         get 'delete' | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue