X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/b37ceabb82336ee82757cd32efe353cfab8ec267..f5240829880f87e0cf581c6a296e436fdef0ef80:/examples/docs/source/Reorderer.html diff --git a/examples/docs/source/Reorderer.html b/examples/docs/source/Reorderer.html new file mode 100644 index 00000000..f2f55c0a --- /dev/null +++ b/examples/docs/source/Reorderer.html @@ -0,0 +1,435 @@ + + + + The source code + + + + +
/*!
+ * Ext JS Library 3.3.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+
/** + * @class Ext.ux.Reorderer + * @extends Object + * Generic base class for handling reordering of items. This base class must be extended to provide the + * actual reordering functionality - the base class just sets up events and abstract logic functions. + * It will fire events and set defaults, deferring the actual reordering to a doReorder implementation. + * See Ext.ux.TabReorderer for an example. + */ +Ext.ux.Reorderer = Ext.extend(Object, { +
/** + * @property defaults + * @type Object + * Object containing default values for plugin configuration details. These can be overridden when + * constructing the plugin + */ + defaults: { +
/** + * @cfg animate + * @type Boolean + * If set to true, the rearranging of the toolbar items is animated + */ + animate: true, + +
/** + * @cfg animationDuration + * @type Number + * The duration of the animation used to move other toolbar items out of the way + */ + animationDuration: 0.2, + +
/** + * @cfg defaultReorderable + * @type Boolean + * True to make every toolbar draggable unless reorderable is specifically set to false. + * This defaults to false + */ + defaultReorderable: false + }, + +
/** + * Creates the plugin instance, applies defaults + * @constructor + * @param {Object} config Optional config object + */ + constructor: function(config) { + Ext.apply(this, config || {}, this.defaults); + }, + +
/** + * Initializes the plugin, stores a reference to the target + * @param {Mixed} target The target component which contains the reorderable items + */ + init: function(target) { +
/** + * @property target + * @type Ext.Component + * Reference to the target component which contains the reorderable items + */ + this.target = target; + + this.initEvents(); + + var items = this.getItems(), + length = items.length, + i; + + for (i = 0; i < length; i++) { + this.createIfReorderable(items[i]); + } + }, + +
/** + * Reorders the items in the target component according to the given mapping object. Example: + * this.reorder({ + * 1: 5, + * 3: 2 + * }); + * Would move the item at index 1 to index 5, and the item at index 3 to index 2 + * @param {Object} mappings Object containing current item index as key and new index as property + */ + reorder: function(mappings) { + var target = this.target; + + if (target.fireEvent('before-reorder', mappings, target, this) !== false) { + this.doReorder(mappings); + + target.fireEvent('reorder', mappings, target, this); + } + }, + +
/** + * Abstract function to perform the actual reordering. This MUST be overridden in a subclass + * @param {Object} mappings Mappings of the old item indexes to new item indexes + */ + doReorder: function(paramName) { + throw new Error("doReorder must be implemented in the Ext.ux.Reorderer subclass"); + }, + + /** + * Should create and return an Ext.dd.DD for the given item. This MUST be overridden in a subclass + * @param {Mixed} item The item to create a DD for. This could be a TabPanel tab, a Toolbar button, etc + * @return {Ext.dd.DD} The DD for the given item + */ + createItemDD: function(item) { + throw new Error("createItemDD must be implemented in the Ext.ux.Reorderer subclass"); + }, + +
/** + * Sets up the given Toolbar item as a draggable + * @param {Mixed} button The item to make draggable (usually an Ext.Button instance) + */ + createItemDD: function(button) { + var el = button.getEl(), + id = el.id, + tbar = this.target, + me = this; + + button.dd = new Ext.dd.DD(el, undefined, { + isTarget: false + }); + + button.dd.constrainTo(tbar.getEl()); + button.dd.setYConstraint(0, 0, 0); + + Ext.apply(button.dd, { + b4StartDrag: function() { + this.startPosition = el.getXY(); + + //bump up the z index of the button being dragged but keep a reference to the original + this.startZIndex = el.getStyle('zIndex'); + el.setStyle('zIndex', 10000); + + button.suspendEvents(); + }, + + onDrag: function(e) { + //calculate the button's index within the toolbar and its current midpoint + var buttonX = el.getXY()[0], + deltaX = buttonX - this.startPosition[0], + items = tbar.items.items, + oldIndex = items.indexOf(button), + newIndex; + + //find which item in the toolbar the midpoint is currently over + for (var index = 0; index < items.length; index++) { + var item = items[index]; + + if (item.reorderable && item.id != button.id) { + //find the midpoint of the button + var box = item.getEl().getBox(), + midpoint = (me.buttonXCache[item.id] || box.x) + (box.width / 2), + movedLeft = oldIndex > index && deltaX < 0 && buttonX < midpoint, + movedRight = oldIndex < index && deltaX > 0 && (buttonX + el.getWidth()) > midpoint; + + if (movedLeft || movedRight) { + me[movedLeft ? 'onMovedLeft' : 'onMovedRight'](button, index, oldIndex); + break; + } + } + } + }, + +
/** + * After the drag has been completed, make sure the button being dragged makes it back to + * the correct location and resets its z index + */ + endDrag: function() { + //we need to update the cache here for cases where the button was dragged but its + //position in the toolbar did not change + me.updateButtonXCache(); + + el.moveTo(me.buttonXCache[button.id], undefined, { + duration: me.animationDuration, + scope : this, + callback: function() { + button.resumeEvents(); + + tbar.fireEvent('reordered', button, tbar); + } + }); + + el.setStyle('zIndex', this.startZIndex); + } + }); + }, + + /** + * @private + * Creates a DD instance for a given item if it is reorderable + * @param {Mixed} item The item + */ + createIfReorderable: function(item) { + if (this.defaultReorderable && item.reorderable == undefined) { + item.reorderable = true; + } + + if (item.reorderable && !item.dd) { + if (item.rendered) { + this.createItemDD(item); + } else { + item.on('render', this.createItemDD.createDelegate(this, [item]), this, {single: true}); + } + } + }, + +
/** + * Returns an array of items which will be made draggable. This defaults to the contents of this.target.items, + * but can be overridden - e.g. for TabPanels + * @return {Array} The array of items which will be made draggable + */ + getItems: function() { + return this.target.items.items; + }, + +
/** + * Adds before-reorder and reorder events to the target component + */ + initEvents: function() { + this.target.addEvents( +
/** + * @event before-reorder + * Fires before a reorder occurs. Return false to cancel + * @param {Object} mappings Mappings of the old item indexes to new item indexes + * @param {Mixed} component The target component + * @param {Ext.ux.TabReorderer} this The plugin instance + */ + 'before-reorder', + +
/** + * @event reorder + * Fires after a reorder has occured. + * @param {Object} mappings Mappings of the old item indexes to the new item indexes + * @param {Mixed} component The target component + * @param {Ext.ux.TabReorderer} this The plugin instance + */ + 'reorder' + ); + } +}); + +
/** + * @class Ext.ux.HBoxReorderer + * @extends Ext.ux.Reorderer + * Description + */ +Ext.ux.HBoxReorderer = Ext.extend(Ext.ux.Reorderer, { +
/** + * Initializes the plugin, decorates the container with additional functionality + */ + init: function(container) { +
/** + * This is used to store the correct x value of each button in the array. We need to use this + * instead of the button's reported x co-ordinate because the buttons are animated when they move - + * if another onDrag is fired while the button is still moving, the comparison x value will be incorrect + */ + this.buttonXCache = {}; + + container.on({ + scope: this, + add : function(container, item) { + this.createIfReorderable(item); + } + }); + + //super sets a reference to the toolbar in this.target + Ext.ux.HBoxReorderer.superclass.init.apply(this, arguments); + }, + +
/** + * Sets up the given Toolbar item as a draggable + * @param {Mixed} button The item to make draggable (usually an Ext.Button instance) + */ + createItemDD: function(button) { + if (button.dd != undefined) { + return; + } + + var el = button.getEl(), + id = el.id, + me = this, + tbar = me.target; + + button.dd = new Ext.dd.DD(el, undefined, { + isTarget: false + }); + + el.applyStyles({ + position: 'absolute' + }); + + //if a button has a menu, it is disabled while dragging with this function + var menuDisabler = function() { + return false; + }; + + Ext.apply(button.dd, { + b4StartDrag: function() { + this.startPosition = el.getXY(); + + //bump up the z index of the button being dragged but keep a reference to the original + this.startZIndex = el.getStyle('zIndex'); + el.setStyle('zIndex', 10000); + + button.suspendEvents(); + if (button.menu) { + button.menu.on('beforeshow', menuDisabler, me); + } + }, + + startDrag: function() { + this.constrainTo(tbar.getEl()); + this.setYConstraint(0, 0, 0); + }, + + onDrag: function(e) { + //calculate the button's index within the toolbar and its current midpoint + var buttonX = el.getXY()[0], + deltaX = buttonX - this.startPosition[0], + items = tbar.items.items, + length = items.length, + oldIndex = items.indexOf(button), + newIndex, index, item; + + //find which item in the toolbar the midpoint is currently over + for (index = 0; index < length; index++) { + item = items[index]; + + if (item.reorderable && item.id != button.id) { + //find the midpoint of the button + var box = item.getEl().getBox(), + midpoint = (me.buttonXCache[item.id] || box.x) + (box.width / 2), + movedLeft = oldIndex > index && deltaX < 0 && buttonX < midpoint, + movedRight = oldIndex < index && deltaX > 0 && (buttonX + el.getWidth()) > midpoint; + + if (movedLeft || movedRight) { + me[movedLeft ? 'onMovedLeft' : 'onMovedRight'](button, index, oldIndex); + break; + } + } + } + }, + +
/** + * After the drag has been completed, make sure the button being dragged makes it back to + * the correct location and resets its z index + */ + endDrag: function() { + //we need to update the cache here for cases where the button was dragged but its + //position in the toolbar did not change + me.updateButtonXCache(); + + el.moveTo(me.buttonXCache[button.id], el.getY(), { + duration: me.animationDuration, + scope : this, + callback: function() { + button.resumeEvents(); + if (button.menu) { + button.menu.un('beforeshow', menuDisabler, me); + } + + tbar.fireEvent('reordered', button, tbar); + } + }); + + el.setStyle('zIndex', this.startZIndex); + } + }); + }, + + onMovedLeft: function(item, newIndex, oldIndex) { + var tbar = this.target, + items = tbar.items.items, + length = items.length, + index; + + if (newIndex != undefined && newIndex != oldIndex) { + //move the button currently under drag to its new location + tbar.remove(item, false); + tbar.insert(newIndex, item); + + //set the correct x location of each item in the toolbar + this.updateButtonXCache(); + for (index = 0; index < length; index++) { + var obj = items[index], + newX = this.buttonXCache[obj.id]; + + if (item == obj) { + item.dd.startPosition[0] = newX; + } else { + var el = obj.getEl(); + + el.moveTo(newX, el.getY(), { + duration: this.animationDuration + }); + } + } + } + }, + + onMovedRight: function(item, newIndex, oldIndex) { + this.onMovedLeft.apply(this, arguments); + }, + + /** + * @private + * Updates the internal cache of button X locations. + */ + updateButtonXCache: function() { + var tbar = this.target, + items = tbar.items, + totalX = tbar.getEl().getBox(true).x; + + items.each(function(item) { + this.buttonXCache[item.id] = totalX; + + totalX += item.getEl().getWidth(); + }, this); + } +});
+ + \ No newline at end of file