aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/fx/draglistgroup.js
diff options
context:
space:
mode:
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/fx/draglistgroup.js')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/fx/draglistgroup.js1268
1 files changed, 0 insertions, 1268 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/fx/draglistgroup.js b/contexts/data/lib/closure-library/closure/goog/fx/draglistgroup.js
deleted file mode 100644
index 6f36719..0000000
--- a/contexts/data/lib/closure-library/closure/goog/fx/draglistgroup.js
+++ /dev/null
@@ -1,1268 +0,0 @@
-// Copyright 2008 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview A DragListGroup is a class representing a group of one or more
- * "drag lists" with items that can be dragged within them and between them.
- *
- * @see ../demos/draglistgroup.html
- */
-
-
-goog.provide('goog.fx.DragListDirection');
-goog.provide('goog.fx.DragListGroup');
-goog.provide('goog.fx.DragListGroup.EventType');
-goog.provide('goog.fx.DragListGroupEvent');
-
-goog.require('goog.asserts');
-goog.require('goog.dom');
-goog.require('goog.dom.NodeType');
-goog.require('goog.dom.classes');
-goog.require('goog.events.Event');
-goog.require('goog.events.EventHandler');
-goog.require('goog.events.EventTarget');
-goog.require('goog.events.EventType');
-goog.require('goog.fx.Dragger');
-goog.require('goog.fx.Dragger.EventType');
-goog.require('goog.math.Coordinate');
-goog.require('goog.style');
-
-
-
-/**
- * A class representing a group of one or more "drag lists" with items that can
- * be dragged within them and between them.
- *
- * Example usage:
- * var dragListGroup = new goog.fx.DragListGroup();
- * dragListGroup.setDragItemHandleHoverClass(className1, className2);
- * dragListGroup.setDraggerElClass(className3);
- * dragListGroup.addDragList(vertList, goog.fx.DragListDirection.DOWN);
- * dragListGroup.addDragList(horizList, goog.fx.DragListDirection.RIGHT);
- * dragListGroup.init();
- *
- * @extends {goog.events.EventTarget}
- * @constructor
- */
-goog.fx.DragListGroup = function() {
- goog.events.EventTarget.call(this);
-
- /**
- * The drag lists.
- * @type {Array.<Element>}
- * @private
- */
- this.dragLists_ = [];
-
- /**
- * All the drag items. Set by init().
- * @type {Array.<Element>}
- * @private
- */
- this.dragItems_ = [];
-
- /**
- * Which drag item corresponds to a given handle. Set by init().
- * Specifically, this maps from the unique ID (as given by goog.getUid)
- * of the handle to the drag item.
- * @type {Object}
- * @private
- */
- this.dragItemForHandle_ = {};
-
- /**
- * The event handler for this instance.
- * @type {goog.events.EventHandler}
- * @private
- */
- this.eventHandler_ = new goog.events.EventHandler(this);
-
- /**
- * Whether the setup has been done to make all items in all lists draggable.
- * @type {boolean}
- * @private
- */
- this.isInitialized_ = false;
-
- /**
- * Whether the currDragItem is always displayed. By default the list
- * collapses, the currDragItem's display is set to none, when we do not
- * hover over a draglist.
- * @type {boolean}
- * @private
- */
- this.isCurrDragItemAlwaysDisplayed_ = false;
-
- /**
- * Whether to update the position of the currDragItem as we drag, i.e.,
- * insert the currDragItem each time to the position where it would land if
- * we were to end the drag at that point. Defaults to true.
- * @type {boolean}
- * @private
- */
- this.updateWhileDragging_ = true;
-};
-goog.inherits(goog.fx.DragListGroup, goog.events.EventTarget);
-
-
-/**
- * Enum to indicate the direction that a drag list grows.
- * @enum {number}
- */
-goog.fx.DragListDirection = {
- DOWN: 0, // common
- RIGHT: 2, // common
- LEFT: 3, // uncommon (except perhaps for right-to-left interfaces)
- RIGHT_2D: 4, // common + handles multiple lines if items are wrapped
- LEFT_2D: 5 // for rtl languages
-};
-
-
-/**
- * Events dispatched by this class.
- * @type {Object}
- */
-goog.fx.DragListGroup.EventType = {
- BEFOREDRAGSTART: 'beforedragstart',
- DRAGSTART: 'dragstart',
- BEFOREDRAGMOVE: 'beforedragmove',
- DRAGMOVE: 'dragmove',
- BEFOREDRAGEND: 'beforedragend',
- DRAGEND: 'dragend'
-};
-
-
-// The next 4 are user-supplied CSS classes.
-
-
-/**
- * The user-supplied CSS classes to add to a drag item on hover (not during a
- * drag action).
- * @type {Array|undefined}
- * @private
- */
-goog.fx.DragListGroup.prototype.dragItemHoverClasses_;
-
-
-/**
- * The user-supplied CSS classes to add to a drag item handle on hover (not
- * during a drag action).
- * @type {Array|undefined}
- * @private
- */
-goog.fx.DragListGroup.prototype.dragItemHandleHoverClasses_;
-
-
-/**
- * The user-supplied CSS classes to add to the current drag item (during a drag
- * action).
- * @type {Array|undefined}
- * @private
- */
-goog.fx.DragListGroup.prototype.currDragItemClasses_;
-
-
-/**
- * The user-supplied CSS class to add to the clone of the current drag item
- * that's actually being dragged around (during a drag action).
- * @type {string|undefined}
- * @private
- */
-goog.fx.DragListGroup.prototype.draggerElClass_;
-
-
-// The next 5 are info applicable during a drag action.
-
-
-/**
- * The current drag item being moved.
- * Note: This is only defined while a drag action is happening.
- * @type {Element}
- * @private
- */
-goog.fx.DragListGroup.prototype.currDragItem_;
-
-
-/**
- * The drag list that {@code this.currDragItem_} is currently hovering over, or
- * null if it is not hovering over a list.
- * @type {Element}
- * @private
- */
-goog.fx.DragListGroup.prototype.currHoverList_;
-
-
-/**
- * The original drag list that the current drag item came from. We need to
- * remember this in case the user drops the item outside of any lists, in which
- * case we return the item to its original location.
- * Note: This is only defined while a drag action is happening.
- * @type {Element}
- * @private
- */
-goog.fx.DragListGroup.prototype.origList_;
-
-
-/**
- * The original next item in the original list that the current drag item came
- * from. We need to remember this in case the user drops the item outside of
- * any lists, in which case we return the item to its original location.
- * Note: This is only defined while a drag action is happening.
- * @type {Element}
- * @private
- */
-goog.fx.DragListGroup.prototype.origNextItem_;
-
-
-/**
- * The current item in the list we are hovering over. We need to remember
- * this in case we do not update the position of the current drag item while
- * dragging (see {@code updateWhileDragging_}). In this case the current drag
- * item will be inserted into the list before this element when the drag ends.
- * @type {Element}
- * @private
- */
-goog.fx.DragListGroup.prototype.currHoverItem_;
-
-
-/**
- * The clone of the current drag item that's actually being dragged around.
- * Note: This is only defined while a drag action is happening.
- * @type {Element}
- * @private
- */
-goog.fx.DragListGroup.prototype.draggerEl_;
-
-
-/**
- * The dragger object.
- * Note: This is only defined while a drag action is happening.
- * @type {goog.fx.Dragger}
- * @private
- */
-goog.fx.DragListGroup.prototype.dragger_;
-
-
-/**
- * The amount of distance, in pixels, after which a mousedown or touchstart is
- * considered a drag.
- * @type {number}
- * @private
- */
-goog.fx.DragListGroup.prototype.hysteresisDistance_ = 0;
-
-
-/**
- * Sets the property of the currDragItem that it is always displayed in the
- * list.
- */
-goog.fx.DragListGroup.prototype.setIsCurrDragItemAlwaysDisplayed = function() {
- this.isCurrDragItemAlwaysDisplayed_ = true;
-};
-
-
-/**
- * Sets the private property updateWhileDragging_ to false. This disables the
- * update of the position of the currDragItem while dragging. It will only be
- * placed to its new location once the drag ends.
- */
-goog.fx.DragListGroup.prototype.setNoUpdateWhileDragging = function() {
- this.updateWhileDragging_ = false;
-};
-
-
-/**
- * Sets the distance the user has to drag the element before a drag operation
- * is started.
- * @param {number} distance The number of pixels after which a mousedown and
- * move is considered a drag.
- */
-goog.fx.DragListGroup.prototype.setHysteresis = function(distance) {
- this.hysteresisDistance_ = distance;
-};
-
-
-/**
- * @return {number} distance The number of pixels after which a mousedown and
- * move is considered a drag.
- */
-goog.fx.DragListGroup.prototype.getHysteresis = function() {
- return this.hysteresisDistance_;
-};
-
-
-/**
- * Adds a drag list to this DragListGroup.
- * All calls to this method must happen before the call to init().
- * Remember that all child nodes (except text nodes) will be made draggable to
- * any other drag list in this group.
- *
- * @param {Element} dragListElement Must be a container for a list of items
- * that should all be made draggable.
- * @param {goog.fx.DragListDirection} growthDirection The direction that this
- * drag list grows in (i.e. if an item is appended to the DOM, the list's
- * bounding box expands in this direction).
- * @param {boolean=} opt_unused Unused argument.
- * @param {string=} opt_dragHoverClass CSS class to apply to this drag list when
- * the draggerEl hovers over it during a drag action.
- */
-goog.fx.DragListGroup.prototype.addDragList = function(
- dragListElement, growthDirection, opt_unused, opt_dragHoverClass) {
- goog.asserts.assert(!this.isInitialized_);
-
- dragListElement.dlgGrowthDirection_ = growthDirection;
- dragListElement.dlgDragHoverClass_ = opt_dragHoverClass;
- this.dragLists_.push(dragListElement);
-};
-
-
-/**
- * Sets a user-supplied function used to get the "handle" element for a drag
- * item. The function must accept exactly one argument. The argument may be
- * any drag item element.
- *
- * If not set, the default implementation uses the whole drag item as the
- * handle.
- *
- * @param {function(Element): Element} getHandleForDragItemFn A function that,
- * given any drag item, returns a reference to its "handle" element
- * (which may be the drag item element itself).
- */
-goog.fx.DragListGroup.prototype.setFunctionToGetHandleForDragItem = function(
- getHandleForDragItemFn) {
- goog.asserts.assert(!this.isInitialized_);
- this.getHandleForDragItem_ = getHandleForDragItemFn;
-};
-
-
-/**
- * Sets a user-supplied CSS class to add to a drag item on hover (not during a
- * drag action).
- * @param {...!string} var_args The CSS class or classes.
- */
-goog.fx.DragListGroup.prototype.setDragItemHoverClass = function(var_args) {
- goog.asserts.assert(!this.isInitialized_);
- this.dragItemHoverClasses_ = goog.array.slice(arguments, 0);
-};
-
-
-/**
- * Sets a user-supplied CSS class to add to a drag item handle on hover (not
- * during a drag action).
- * @param {...!string} var_args The CSS class or classes.
- */
-goog.fx.DragListGroup.prototype.setDragItemHandleHoverClass = function(
- var_args) {
- goog.asserts.assert(!this.isInitialized_);
- this.dragItemHandleHoverClasses_ = goog.array.slice(arguments, 0);
-};
-
-
-/**
- * Sets a user-supplied CSS class to add to the current drag item (during a
- * drag action).
- *
- * If not set, the default behavior adds visibility:hidden to the current drag
- * item so that it is a block of empty space in the hover drag list (if any).
- * If this class is set by the user, then the default behavior does not happen
- * (unless, of course, the class also contains visibility:hidden).
- *
- * @param {...!string} var_args The CSS class or classes.
- */
-goog.fx.DragListGroup.prototype.setCurrDragItemClass = function(var_args) {
- goog.asserts.assert(!this.isInitialized_);
- this.currDragItemClasses_ = goog.array.slice(arguments, 0);
-};
-
-
-/**
- * Sets a user-supplied CSS class to add to the clone of the current drag item
- * that's actually being dragged around (during a drag action).
- * @param {string} draggerElClass The CSS class.
- */
-goog.fx.DragListGroup.prototype.setDraggerElClass = function(draggerElClass) {
- goog.asserts.assert(!this.isInitialized_);
- this.draggerElClass_ = draggerElClass;
-};
-
-
-/**
- * Performs the initial setup to make all items in all lists draggable.
- */
-goog.fx.DragListGroup.prototype.init = function() {
- if (this.isInitialized_) {
- return;
- }
-
- for (var i = 0, numLists = this.dragLists_.length; i < numLists; i++) {
- var dragList = this.dragLists_[i];
-
- var dragItems = goog.dom.getChildren(dragList);
- for (var j = 0, numItems = dragItems.length; j < numItems; ++j) {
- var dragItem = dragItems[j];
- var dragItemHandle = this.getHandleForDragItem_(dragItem);
-
- var uid = goog.getUid(dragItemHandle);
- this.dragItemForHandle_[uid] = dragItem;
-
- if (this.dragItemHoverClasses_) {
- this.eventHandler_.listen(
- dragItem, goog.events.EventType.MOUSEOVER,
- this.handleDragItemMouseover_);
- this.eventHandler_.listen(
- dragItem, goog.events.EventType.MOUSEOUT,
- this.handleDragItemMouseout_);
- }
- if (this.dragItemHandleHoverClasses_) {
- this.eventHandler_.listen(
- dragItemHandle, goog.events.EventType.MOUSEOVER,
- this.handleDragItemHandleMouseover_);
- this.eventHandler_.listen(
- dragItemHandle, goog.events.EventType.MOUSEOUT,
- this.handleDragItemHandleMouseout_);
- }
-
- this.dragItems_.push(dragItem);
- this.eventHandler_.listen(dragItemHandle,
- [goog.events.EventType.MOUSEDOWN, goog.events.EventType.TOUCHSTART],
- this.handlePotentialDragStart_);
- }
- }
-
- this.isInitialized_ = true;
-};
-
-
-/** @override */
-goog.fx.DragListGroup.prototype.disposeInternal = function() {
- this.eventHandler_.dispose();
-
- for (var i = 0, n = this.dragLists_.length; i < n; i++) {
- var dragList = this.dragLists_[i];
- // Note: IE doesn't allow 'delete' for fields on HTML elements (because
- // they're not real JS objects in IE), so we just set them to undefined.
- dragList.dlgGrowthDirection_ = undefined;
- dragList.dlgDragHoverClass_ = undefined;
- }
-
- this.dragLists_.length = 0;
- this.dragItems_.length = 0;
- this.dragItemForHandle_ = null;
-
- // In the case where a drag event is currently in-progress and dispose is
- // called, this cleans up the extra state.
- this.cleanupDragDom_();
-
- goog.fx.DragListGroup.superClass_.disposeInternal.call(this);
-};
-
-
-/**
- * Caches the heights of each drag list and drag item, except for the current
- * drag item.
- *
- * @param {Element} currDragItem The item currently being dragged.
- * @private
- */
-goog.fx.DragListGroup.prototype.recacheListAndItemBounds_ = function(
- currDragItem) {
- for (var i = 0, n = this.dragLists_.length; i < n; i++) {
- var dragList = this.dragLists_[i];
- dragList.dlgBounds_ = goog.style.getBounds(dragList);
- }
-
- for (var i = 0, n = this.dragItems_.length; i < n; i++) {
- var dragItem = this.dragItems_[i];
- if (dragItem != currDragItem) {
- dragItem.dlgBounds_ = goog.style.getBounds(dragItem);
- }
- }
-};
-
-
-/**
- * Handles mouse and touch events which may start a drag action.
- * @param {!goog.events.BrowserEvent} e MOUSEDOWN or TOUCHSTART event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handlePotentialDragStart_ = function(e) {
- var uid = goog.getUid(/** @type {Node} */ (e.currentTarget));
- this.currDragItem_ = /** @type {Element} */ (this.dragItemForHandle_[uid]);
-
- this.draggerEl_ = this.cloneNode_(this.currDragItem_);
- if (this.draggerElClass_) {
- // Add CSS class for the clone, if any.
- goog.dom.classes.add(this.draggerEl_, this.draggerElClass_);
- }
-
- // Place the clone (i.e. draggerEl) at the same position as the actual
- // current drag item. This is a bit tricky since
- // goog.style.getPageOffset() gets the left-top pos of the border, but
- // goog.style.setPageOffset() sets the left-top pos of the margin.
- // It's difficult to adjust for the margins of the clone because it's
- // difficult to read it: goog.style.getComputedStyle() doesn't work for IE.
- // Instead, our workaround is simply to set the clone's margins to 0px.
- this.draggerEl_.style.margin = '0';
- this.draggerEl_.style.position = 'absolute';
- this.draggerEl_.style.visibility = 'hidden';
- var doc = goog.dom.getOwnerDocument(this.currDragItem_);
- doc.body.appendChild(this.draggerEl_);
-
- // Important: goog.style.setPageOffset() only works correctly for IE when the
- // element is already in the document.
- var currDragItemPos = goog.style.getPageOffset(this.currDragItem_);
- goog.style.setPageOffset(this.draggerEl_, currDragItemPos);
-
- this.dragger_ = new goog.fx.Dragger(this.draggerEl_);
- this.dragger_.setHysteresis(this.hysteresisDistance_);
-
- // Listen to events on the dragger. These handlers will be unregistered at
- // DRAGEND, when the dragger is disposed of. We can't use eventHandler_,
- // because it creates new references to the handler functions at each
- // dragging action, and keeps them until DragListGroup is disposed of.
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.START,
- this.handleDragStart_, false, this);
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
- this.handleDragEnd_, false, this);
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.EARLY_CANCEL,
- this.cleanup_, false, this);
- this.dragger_.startDrag(e);
-};
-
-
-/**
- * Handles the start of a drag action.
- * @param {!goog.fx.DragEvent} e goog.fx.Dragger.EventType.START event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragStart_ = function(e) {
- if (!this.dispatchEvent(new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, this, e.browserEvent,
- this.currDragItem_, null, null))) {
- e.preventDefault();
- this.cleanup_();
- return;
- }
-
- // Record the original location of the current drag item.
- // Note: this.origNextItem_ may be null.
- this.origList_ = /** @type {Element} */ (this.currDragItem_.parentNode);
- this.origNextItem_ = goog.dom.getNextElementSibling(this.currDragItem_);
- this.currHoverItem_ = this.origNextItem_;
- this.currHoverList_ = this.origList_;
-
- // If there's a CSS class specified for the current drag item, add it.
- // Otherwise, make the actual current drag item hidden (takes up space).
- if (this.currDragItemClasses_) {
- goog.dom.classes.add.apply(null,
- goog.array.concat(this.currDragItem_, this.currDragItemClasses_));
- } else {
- this.currDragItem_.style.visibility = 'hidden';
- }
-
- // Precompute distances from top-left corner to center for efficiency.
- var draggerElSize = goog.style.getSize(this.draggerEl_);
- this.draggerEl_.halfWidth = draggerElSize.width / 2;
- this.draggerEl_.halfHeight = draggerElSize.height / 2;
-
- this.draggerEl_.style.visibility = '';
-
- // Record the bounds of all the drag lists and all the other drag items. This
- // caching is for efficiency, so that we don't have to recompute the bounds on
- // each drag move. Do this in the state where the current drag item is not in
- // any of the lists, except when update while dragging is disabled, as in this
- // case the current drag item does not get removed until drag ends.
- if (this.updateWhileDragging_) {
- this.currDragItem_.style.display = 'none';
- }
- this.recacheListAndItemBounds_(this.currDragItem_);
- this.currDragItem_.style.display = '';
-
- // Listen to events on the dragger.
- goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
- this.handleDragMove_, false, this);
-
- this.dispatchEvent(
- new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.DRAGSTART, this, e.browserEvent,
- this.currDragItem_, this.draggerEl_, this.dragger_));
-};
-
-
-/**
- * Handles a drag movement (i.e. DRAG event fired by the dragger).
- *
- * @param {goog.fx.DragEvent} dragEvent Event object fired by the dragger.
- * @return {boolean} The return value for the event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragMove_ = function(dragEvent) {
-
- // Compute the center of the dragger element (i.e. the cloned drag item).
- var draggerElPos = goog.style.getPageOffset(this.draggerEl_);
- var draggerElCenter = new goog.math.Coordinate(
- draggerElPos.x + this.draggerEl_.halfWidth,
- draggerElPos.y + this.draggerEl_.halfHeight);
-
- // Check whether the center is hovering over one of the drag lists.
- var hoverList = this.getHoverDragList_(draggerElCenter);
-
- // If hovering over a list, find the next item (if drag were to end now).
- var hoverNextItem =
- hoverList ? this.getHoverNextItem_(hoverList, draggerElCenter) : null;
-
- var rv = this.dispatchEvent(
- new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.BEFOREDRAGMOVE, this, dragEvent,
- this.currDragItem_, this.draggerEl_, this.dragger_,
- draggerElCenter, hoverList, hoverNextItem));
- if (!rv) {
- return false;
- }
-
- if (hoverList) {
- if (this.updateWhileDragging_) {
- this.insertCurrDragItem_(hoverList, hoverNextItem);
- } else {
- // If update while dragging is disabled do not insert
- // the dragged item, but update the hovered item instead.
- this.updateCurrHoverItem(hoverNextItem, draggerElCenter);
- }
- this.currDragItem_.style.display = '';
- // Add drag list's hover class (if any).
- if (hoverList.dlgDragHoverClass_) {
- goog.dom.classes.add(hoverList, hoverList.dlgDragHoverClass_);
- }
-
- } else {
- // Not hovering over a drag list, so remove the item altogether unless
- // specified otherwise by the user.
- if (!this.isCurrDragItemAlwaysDisplayed_) {
- this.currDragItem_.style.display = 'none';
- }
-
- // Remove hover classes (if any) from all drag lists.
- for (var i = 0, n = this.dragLists_.length; i < n; i++) {
- var dragList = this.dragLists_[i];
- if (dragList.dlgDragHoverClass_) {
- goog.dom.classes.remove(dragList, dragList.dlgDragHoverClass_);
- }
- }
- }
-
- // If the current hover list is different than the last, the lists may have
- // shrunk, so we should recache the bounds.
- if (hoverList != this.currHoverList_) {
- this.currHoverList_ = hoverList;
- this.recacheListAndItemBounds_(this.currDragItem_);
- }
-
- this.dispatchEvent(
- new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.DRAGMOVE, this, dragEvent,
- /** @type {Element} */ (this.currDragItem_),
- this.draggerEl_, this.dragger_,
- draggerElCenter, hoverList, hoverNextItem));
-
- // Return false to prevent selection due to mouse drag.
- return false;
-};
-
-
-/**
- * Clear all our temporary fields that are only defined while dragging, and
- * all the bounds info stored on the drag lists and drag elements.
- * @param {!goog.events.Event=} opt_e EARLY_CANCEL event from the dragger if
- * cleanup_ was called as an event handler.
- * @private
- */
-goog.fx.DragListGroup.prototype.cleanup_ = function(opt_e) {
- this.cleanupDragDom_();
-
- this.currDragItem_ = null;
- this.currHoverList_ = null;
- this.origList_ = null;
- this.origNextItem_ = null;
- this.draggerEl_ = null;
- this.dragger_ = null;
-
- // Note: IE doesn't allow 'delete' for fields on HTML elements (because
- // they're not real JS objects in IE), so we just set them to null.
- for (var i = 0, n = this.dragLists_.length; i < n; i++) {
- this.dragLists_[i].dlgBounds_ = null;
- }
- for (var i = 0, n = this.dragItems_.length; i < n; i++) {
- this.dragItems_[i].dlgBounds_ = null;
- }
-};
-
-
-/**
- * Handles the end or the cancellation of a drag action, i.e. END or CLEANUP
- * event fired by the dragger.
- *
- * @param {!goog.fx.DragEvent} dragEvent Event object fired by the dragger.
- * @return {boolean} Whether the event was handled.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragEnd_ = function(dragEvent) {
- var rv = this.dispatchEvent(
- new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.BEFOREDRAGEND, this, dragEvent,
- /** @type {Element} */ (this.currDragItem_),
- this.draggerEl_, this.dragger_));
- if (!rv) {
- return false;
- }
-
- // If update while dragging is disabled insert the current drag item into
- // its intended location.
- if (!this.updateWhileDragging_) {
- this.insertCurrHoverItem();
- }
-
- // The DRAGEND handler may need the new order of the list items. Clean up the
- // garbage.
- // TODO(user): Regression test.
- this.cleanupDragDom_();
-
- this.dispatchEvent(
- new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.DRAGEND, this, dragEvent,
- this.currDragItem_, this.draggerEl_, this.dragger_));
-
- this.cleanup_();
-
- return true;
-};
-
-
-/**
- * Cleans up DOM changes that are made by the {@code handleDrag*} methods.
- * @private
- */
-goog.fx.DragListGroup.prototype.cleanupDragDom_ = function() {
- // Disposes of the dragger and remove the cloned drag item.
- goog.dispose(this.dragger_);
- if (this.draggerEl_) {
- goog.dom.removeNode(this.draggerEl_);
- }
-
- // If the current drag item is not in any list, put it back in its original
- // location.
- if (this.currDragItem_ && this.currDragItem_.style.display == 'none') {
- // Note: this.origNextItem_ may be null, but insertBefore() still works.
- this.origList_.insertBefore(this.currDragItem_, this.origNextItem_);
- this.currDragItem_.style.display = '';
- }
-
- // If there's a CSS class specified for the current drag item, remove it.
- // Otherwise, make the current drag item visible (instead of empty space).
- if (this.currDragItemClasses_ && this.currDragItem_) {
- goog.dom.classes.remove.apply(null,
- goog.array.concat(this.currDragItem_, this.currDragItemClasses_));
- } else if (this.currDragItem_) {
- this.currDragItem_.style.visibility = 'visible';
- }
-
- // Remove hover classes (if any) from all drag lists.
- for (var i = 0, n = this.dragLists_.length; i < n; i++) {
- var dragList = this.dragLists_[i];
- if (dragList.dlgDragHoverClass_) {
- goog.dom.classes.remove(dragList, dragList.dlgDragHoverClass_);
- }
- }
-};
-
-
-/**
- * Default implementation of the function to get the "handle" element for a
- * drag item. By default, we use the whole drag item as the handle. Users can
- * change this by calling setFunctionToGetHandleForDragItem().
- *
- * @param {Element} dragItem The drag item to get the handle for.
- * @return {Element} The dragItem element itself.
- * @private
- */
-goog.fx.DragListGroup.prototype.getHandleForDragItem_ = function(dragItem) {
- return dragItem;
-};
-
-
-/**
- * Handles a MOUSEOVER event fired on a drag item.
- * @param {goog.events.BrowserEvent} e The event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragItemMouseover_ = function(e) {
- goog.dom.classes.add.apply(null,
- goog.array.concat(/** @type {Element} */ (e.currentTarget),
- this.dragItemHoverClasses_));
-};
-
-
-/**
- * Handles a MOUSEOUT event fired on a drag item.
- * @param {goog.events.BrowserEvent} e The event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragItemMouseout_ = function(e) {
- goog.dom.classes.remove.apply(null,
- goog.array.concat(/** @type {Element} */ (e.currentTarget),
- this.dragItemHoverClasses_));
-};
-
-
-/**
- * Handles a MOUSEOVER event fired on the handle element of a drag item.
- * @param {goog.events.BrowserEvent} e The event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragItemHandleMouseover_ = function(e) {
- goog.dom.classes.add.apply(null,
- goog.array.concat(/** @type {Element} */ (e.currentTarget),
- this.dragItemHandleHoverClasses_));
-};
-
-
-/**
- * Handles a MOUSEOUT event fired on the handle element of a drag item.
- * @param {goog.events.BrowserEvent} e The event.
- * @private
- */
-goog.fx.DragListGroup.prototype.handleDragItemHandleMouseout_ = function(e) {
- goog.dom.classes.remove.apply(null,
- goog.array.concat(/** @type {Element} */ (e.currentTarget),
- this.dragItemHandleHoverClasses_));
-};
-
-
-/**
- * Helper for handleDragMove_().
- * Given the position of the center of the dragger element, figures out whether
- * it's currently hovering over any of the drag lists.
- *
- * @param {goog.math.Coordinate} draggerElCenter The center position of the
- * dragger element.
- * @return {Element} If currently hovering over a drag list, returns the drag
- * list element. Else returns null.
- * @private
- */
-goog.fx.DragListGroup.prototype.getHoverDragList_ = function(draggerElCenter) {
-
- // If the current drag item was in a list last time we did this, then check
- // that same list first.
- var prevHoverList = null;
- if (this.currDragItem_.style.display != 'none') {
- prevHoverList = /** @type {Element} */ (this.currDragItem_.parentNode);
- // Important: We can't use the cached bounds for this list because the
- // cached bounds are based on the case where the current drag item is not
- // in the list. Since the current drag item is known to be in this list, we
- // must recompute the list's bounds.
- var prevHoverListBounds = goog.style.getBounds(prevHoverList);
- if (this.isInRect_(draggerElCenter, prevHoverListBounds)) {
- return prevHoverList;
- }
- }
-
- for (var i = 0, n = this.dragLists_.length; i < n; i++) {
- var dragList = this.dragLists_[i];
- if (dragList == prevHoverList) {
- continue;
- }
- if (this.isInRect_(draggerElCenter, dragList.dlgBounds_)) {
- return dragList;
- }
- }
-
- return null;
-};
-
-
-/**
- * Checks whether a coordinate position resides inside a rectangle.
- * @param {goog.math.Coordinate} pos The coordinate position.
- * @param {goog.math.Rect} rect The rectangle.
- * @return {boolean} True if 'pos' is within the bounds of 'rect'.
- * @private
- */
-goog.fx.DragListGroup.prototype.isInRect_ = function(pos, rect) {
- return pos.x > rect.left && pos.x < rect.left + rect.width &&
- pos.y > rect.top && pos.y < rect.top + rect.height;
-};
-
-
-/**
- * Updates the value of currHoverItem_.
- *
- * This method is used for insertion only when updateWhileDragging_ is false.
- * The below implementation is the basic one. This method can be extended by
- * a subclass to support changes to hovered item (eg: highlighting). Parametr
- * opt_draggerElCenter can be used for more sophisticated effects.
- *
- * @param {Element} hoverNextItem element of the list that is hovered over.
- * @param {goog.math.Coordinate=} opt_draggerElCenter current position of
- * the dragged element.
- * @protected
- */
-goog.fx.DragListGroup.prototype.updateCurrHoverItem = function(
- hoverNextItem, opt_draggerElCenter) {
- if (hoverNextItem) {
- this.currHoverItem_ = hoverNextItem;
- }
-};
-
-
-/**
- * Inserts the currently dragged item in its new place.
- *
- * This method is used for insertion only when updateWhileDragging_ is false
- * (otherwise there is no need for that). In the basic implementation
- * the element is inserted before the currently hovered over item (this can
- * be changed by overriding the method in subclasses).
- *
- * @protected
- */
-goog.fx.DragListGroup.prototype.insertCurrHoverItem = function() {
- this.origList_.insertBefore(this.currDragItem_, this.currHoverItem_);
-};
-
-
-/**
- * Helper for handleDragMove_().
- * Given the position of the center of the dragger element, plus the drag list
- * that it's currently hovering over, figures out the next drag item in the
- * list that follows the current position of the dragger element. (I.e. if
- * the drag action ends right now, it would become the item after the current
- * drag item.)
- *
- * @param {Element} hoverList The drag list that we're hovering over.
- * @param {goog.math.Coordinate} draggerElCenter The center position of the
- * dragger element.
- * @return {Element} Returns the earliest item in the hover list that belongs
- * after the current position of the dragger element. If all items in the
- * list should come before the current drag item, then returns null.
- * @private
- */
-goog.fx.DragListGroup.prototype.getHoverNextItem_ = function(
- hoverList, draggerElCenter) {
- if (hoverList == null) {
- throw Error('getHoverNextItem_ called with null hoverList.');
- }
-
- // The definition of what it means for the draggerEl to be "before" a given
- // item in the hover drag list is not always the same. It changes based on
- // the growth direction of the hover drag list in question.
- /** @type {number} */
- var relevantCoord;
- var getRelevantBoundFn;
- var isBeforeFn;
- var pickClosestRow = false;
- var distanceToClosestRow = undefined;
- switch (hoverList.dlgGrowthDirection_) {
- case goog.fx.DragListDirection.DOWN:
- // "Before" means draggerElCenter.y is less than item's bottom y-value.
- relevantCoord = draggerElCenter.y;
- getRelevantBoundFn = goog.fx.DragListGroup.getBottomBound_;
- isBeforeFn = goog.fx.DragListGroup.isLessThan_;
- break;
- case goog.fx.DragListDirection.RIGHT_2D:
- pickClosestRow = true;
- case goog.fx.DragListDirection.RIGHT:
- // "Before" means draggerElCenter.x is less than item's right x-value.
- relevantCoord = draggerElCenter.x;
- getRelevantBoundFn = goog.fx.DragListGroup.getRightBound_;
- isBeforeFn = goog.fx.DragListGroup.isLessThan_;
- break;
- case goog.fx.DragListDirection.LEFT_2D:
- pickClosestRow = true;
- case goog.fx.DragListDirection.LEFT:
- // "Before" means draggerElCenter.x is greater than item's left x-value.
- relevantCoord = draggerElCenter.x;
- getRelevantBoundFn = goog.fx.DragListGroup.getLeftBound_;
- isBeforeFn = goog.fx.DragListGroup.isGreaterThan_;
- break;
- }
-
- // This holds the earliest drag item found so far that should come after
- // this.currDragItem_ in the hover drag list (based on draggerElCenter).
- var earliestAfterItem = null;
- // This is the position of the relevant bound for the earliestAfterItem,
- // where "relevant" is determined by the growth direction of hoverList.
- var earliestAfterItemRelevantBound;
-
- var hoverListItems = goog.dom.getChildren(hoverList);
- for (var i = 0, n = hoverListItems.length; i < n; i++) {
- var item = hoverListItems[i];
- if (item == this.currDragItem_) {
- continue;
- }
-
- var relevantBound = getRelevantBoundFn(item.dlgBounds_);
- // When the hoverlist is broken into multiple rows (i.e., in the case of
- // LEFT_2D and RIGHT_2D) it is no longer enough to only look at the
- // x-coordinate alone in order to find the {@earliestAfterItem} in the
- // hoverlist. Make sure it is chosen from the row closest to the
- // {@code draggerElCenter}.
- if (pickClosestRow) {
- var distanceToRow = goog.fx.DragListGroup.verticalDistanceFromItem_(item,
- draggerElCenter);
- // Initialize the distance to the closest row to the current value if
- // undefined.
- if (!goog.isDef(distanceToClosestRow)) {
- distanceToClosestRow = distanceToRow;
- }
- if (isBeforeFn(relevantCoord, relevantBound) &&
- (earliestAfterItemRelevantBound == undefined ||
- (distanceToRow < distanceToClosestRow) ||
- ((distanceToRow == distanceToClosestRow) &&
- (isBeforeFn(relevantBound, earliestAfterItemRelevantBound) ||
- relevantBound == earliestAfterItemRelevantBound)))) {
- earliestAfterItem = item;
- earliestAfterItemRelevantBound = relevantBound;
- }
- // Update distance to closest row.
- if (distanceToRow < distanceToClosestRow) {
- distanceToClosestRow = distanceToRow;
- }
- } else if (isBeforeFn(relevantCoord, relevantBound) &&
- (earliestAfterItemRelevantBound == undefined ||
- isBeforeFn(relevantBound, earliestAfterItemRelevantBound))) {
- earliestAfterItem = item;
- earliestAfterItemRelevantBound = relevantBound;
- }
- }
- // If we ended up picking an element that is not in the closest row it can
- // only happen if we should have picked the last one in which case there is
- // no consecutive element.
- if (!goog.isNull(earliestAfterItem) &&
- goog.fx.DragListGroup.verticalDistanceFromItem_(
- earliestAfterItem, draggerElCenter) > distanceToClosestRow) {
- return null;
- } else {
- return earliestAfterItem;
- }
-};
-
-
-/**
- * Private helper for getHoverNextItem().
- * Given an item and a target determine the vertical distance from the item's
- * center to the target.
- * @param {Element} item The item to measure the distance from.
- * @param {goog.math.Coordinate} target The (x,y) coordinate of the target
- * to measure the distance to.
- * @return {number} The vertical distance between the center of the item and
- * the target.
- * @private
- */
-goog.fx.DragListGroup.verticalDistanceFromItem_ = function(item, target) {
- var itemBounds = item.dlgBounds_;
- var itemCenterY = itemBounds.top + (itemBounds.height - 1) / 2;
- return Math.abs(target.y - itemCenterY);
-};
-
-
-/**
- * Private helper for getHoverNextItem_().
- * Given the bounds of an item, computes the item's bottom y-value.
- * @param {goog.math.Rect} itemBounds The bounds of the item.
- * @return {number} The item's bottom y-value.
- * @private
- */
-goog.fx.DragListGroup.getBottomBound_ = function(itemBounds) {
- return itemBounds.top + itemBounds.height - 1;
-};
-
-
-/**
- * Private helper for getHoverNextItem_().
- * Given the bounds of an item, computes the item's right x-value.
- * @param {goog.math.Rect} itemBounds The bounds of the item.
- * @return {number} The item's right x-value.
- * @private
- */
-goog.fx.DragListGroup.getRightBound_ = function(itemBounds) {
- return itemBounds.left + itemBounds.width - 1;
-};
-
-
-/**
- * Private helper for getHoverNextItem_().
- * Given the bounds of an item, computes the item's left x-value.
- * @param {goog.math.Rect} itemBounds The bounds of the item.
- * @return {number} The item's left x-value.
- * @private
- */
-goog.fx.DragListGroup.getLeftBound_ = function(itemBounds) {
- return itemBounds.left || 0;
-};
-
-
-/**
- * Private helper for getHoverNextItem_().
- * @param {number} a Number to compare.
- * @param {number} b Number to compare.
- * @return {boolean} Whether a is less than b.
- * @private
- */
-goog.fx.DragListGroup.isLessThan_ = function(a, b) {
- return a < b;
-};
-
-
-/**
- * Private helper for getHoverNextItem_().
- * @param {number} a Number to compare.
- * @param {number} b Number to compare.
- * @return {boolean} Whether a is greater than b.
- * @private
- */
-goog.fx.DragListGroup.isGreaterThan_ = function(a, b) {
- return a > b;
-};
-
-
-/**
- * Inserts the current drag item to the appropriate location in the drag list
- * that we're hovering over (if the current drag item is not already there).
- *
- * @param {Element} hoverList The drag list we're hovering over.
- * @param {Element} hoverNextItem The next item in the hover drag list.
- * @private
- */
-goog.fx.DragListGroup.prototype.insertCurrDragItem_ = function(
- hoverList, hoverNextItem) {
- if (this.currDragItem_.parentNode != hoverList ||
- goog.dom.getNextElementSibling(this.currDragItem_) != hoverNextItem) {
- // The current drag item is not in the correct location, so we move it.
- // Note: hoverNextItem may be null, but insertBefore() still works.
- hoverList.insertBefore(this.currDragItem_, hoverNextItem);
- }
-};
-
-
-/**
- * Note: Copied from abstractdragdrop.js. TODO(user): consolidate.
- * Creates copy of node being dragged.
- *
- * @param {Element} sourceEl Element to copy.
- * @return {Element} The clone of {@code sourceEl}.
- * @private
- */
-goog.fx.DragListGroup.prototype.cloneNode_ = function(sourceEl) {
- var clonedEl = /** @type {Element} */ (sourceEl.cloneNode(true));
- switch (sourceEl.tagName.toLowerCase()) {
- case 'tr':
- return goog.dom.createDom(
- 'table', null, goog.dom.createDom('tbody', null, clonedEl));
- case 'td':
- case 'th':
- return goog.dom.createDom(
- 'table', null, goog.dom.createDom('tbody', null, goog.dom.createDom(
- 'tr', null, clonedEl)));
- default:
- return clonedEl;
- }
-};
-
-
-
-/**
- * The event object dispatched by DragListGroup.
- * The fields draggerElCenter, hoverList, and hoverNextItem are only available
- * for the BEFOREDRAGMOVE and DRAGMOVE events.
- *
- * @param {string} type The event type string.
- * @param {goog.fx.DragListGroup} dragListGroup A reference to the associated
- * DragListGroup object.
- * @param {goog.events.BrowserEvent|goog.fx.DragEvent} event The event fired
- * by the browser or fired by the dragger.
- * @param {Element} currDragItem The current drag item being moved.
- * @param {Element} draggerEl The clone of the current drag item that's actually
- * being dragged around.
- * @param {goog.fx.Dragger} dragger The dragger object.
- * @param {goog.math.Coordinate=} opt_draggerElCenter The current center
- * position of the draggerEl.
- * @param {Element=} opt_hoverList The current drag list that's being hovered
- * over, or null if the center of draggerEl is outside of any drag lists.
- * If not null and the drag action ends right now, then currDragItem will
- * end up in this list.
- * @param {Element=} opt_hoverNextItem The current next item in the hoverList
- * that the draggerEl is hovering over. (I.e. If the drag action ends
- * right now, then this item would become the next item after the new
- * location of currDragItem.) May be null if not applicable or if
- * currDragItem would be added to the end of hoverList.
- * @constructor
- * @extends {goog.events.Event}
- */
-goog.fx.DragListGroupEvent = function(
- type, dragListGroup, event, currDragItem, draggerEl, dragger,
- opt_draggerElCenter, opt_hoverList, opt_hoverNextItem) {
- goog.events.Event.call(this, type);
-
- /**
- * A reference to the associated DragListGroup object.
- * @type {goog.fx.DragListGroup}
- */
- this.dragListGroup = dragListGroup;
-
- /**
- * The event fired by the browser or fired by the dragger.
- * @type {goog.events.BrowserEvent|goog.fx.DragEvent}
- */
- this.event = event;
-
- /**
- * The current drag item being move.
- * @type {Element}
- */
- this.currDragItem = currDragItem;
-
- /**
- * The clone of the current drag item that's actually being dragged around.
- * @type {Element}
- */
- this.draggerEl = draggerEl;
-
- /**
- * The dragger object.
- * @type {goog.fx.Dragger}
- */
- this.dragger = dragger;
-
- /**
- * The current center position of the draggerEl.
- * @type {goog.math.Coordinate|undefined}
- */
- this.draggerElCenter = opt_draggerElCenter;
-
- /**
- * The current drag list that's being hovered over, or null if the center of
- * draggerEl is outside of any drag lists. (I.e. If not null and the drag
- * action ends right now, then currDragItem will end up in this list.)
- * @type {Element|undefined}
- */
- this.hoverList = opt_hoverList;
-
- /**
- * The current next item in the hoverList that the draggerEl is hovering over.
- * (I.e. If the drag action ends right now, then this item would become the
- * next item after the new location of currDragItem.) May be null if not
- * applicable or if currDragItem would be added to the end of hoverList.
- * @type {Element|undefined}
- */
- this.hoverNextItem = opt_hoverNextItem;
-};
-goog.inherits(goog.fx.DragListGroupEvent, goog.events.Event);