123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326 |
- // 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.array');
- goog.require('goog.asserts');
- goog.require('goog.dom');
- goog.require('goog.dom.classlist');
- goog.require('goog.events');
- goog.require('goog.events.Event');
- goog.require('goog.events.EventHandler');
- goog.require('goog.events.EventId');
- goog.require('goog.events.EventTarget');
- goog.require('goog.events.EventType');
- goog.require('goog.fx.Dragger');
- goog.require('goog.math.Coordinate');
- goog.require('goog.string');
- 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
- * @struct
- */
- goog.fx.DragListGroup = function() {
- goog.fx.DragListGroup.base(this, 'constructor');
- /**
- * The user-supplied CSS classes to add to a drag item on hover (not during a
- * drag action).
- * @private {Array|undefined}
- */
- this.dragItemHoverClasses_;
- /**
- * The user-supplied CSS classes to add to a drag item handle on hover (not
- * during a drag action).
- * @private {Array|undefined}
- */
- this.dragItemHandleHoverClasses_;
- /**
- * The user-supplied CSS classes to add to the current drag item (during a
- * drag action).
- * @private {Array|undefined}
- */
- this.currDragItemClasses_;
- /**
- * The user-supplied CSS classes to add to the clone of the current drag item
- * that's actually being dragged around (during a drag action).
- * @private {Array<string>|undefined}
- */
- this.draggerElClasses_;
- /**
- * The current drag item being moved.
- * Note: This is only defined while a drag action is happening.
- * @private {Element}
- */
- this.currDragItem_;
- /**
- * The drag list that {@code this.currDragItem_} is currently hovering over,
- * or null if it is not hovering over a list.
- * @private {Element}
- */
- this.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.
- * @private {Element}
- */
- this.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.
- * @private {Element}
- */
- this.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.
- * @private {Element}
- */
- this.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.
- * @private {HTMLElement}
- */
- this.draggerEl_;
- /**
- * The dragger object.
- * Note: This is only defined while a drag action is happening.
- * @private {goog.fx.Dragger}
- */
- this.dragger_;
- /**
- * The amount of distance, in pixels, after which a mousedown or touchstart is
- * considered a drag.
- * @private {number}
- */
- this.hysteresisDistance_ = 0;
- /**
- * The drag lists.
- * @private {Array<Element>}
- */
- this.dragLists_ = [];
- /**
- * All the drag items. Set by init().
- * @private {Array<Element>}
- */
- 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.
- * @private {Object}
- */
- this.dragItemForHandle_ = {};
- /**
- * The event handler for this instance.
- * @private {goog.events.EventHandler<!goog.fx.DragListGroup>}
- */
- this.eventHandler_ = new goog.events.EventHandler(this);
- /**
- * Whether the setup has been done to make all items in all lists draggable.
- * @private {boolean}
- */
- 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.
- * @private {boolean}
- */
- 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.
- * @private {boolean}
- */
- 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.
- * @enum {!goog.events.EventId<!goog.fx.DragListGroupEvent>}
- */
- goog.fx.DragListGroup.EventType = {
- /**
- * Raised on mouse down, when the dragger is first created. Handle this event
- * to customize the dragger element even if the drag never actually starts (if
- * the mouse never moves beyond hysteresis).
- */
- DRAGGERCREATED:
- new goog.events.EventId(goog.events.getUniqueId('draggercreated')),
- BEFOREDRAGSTART: new goog.events.EventId('beforedragstart'),
- DRAGSTART: new goog.events.EventId('dragstart'),
- BEFOREDRAGMOVE: new goog.events.EventId('beforedragmove'),
- DRAGMOVE: new goog.events.EventId('dragmove'),
- BEFOREDRAGEND: new goog.events.EventId('beforedragend'),
- /** Raised after the dragged item is moved to the new spot. */
- DRAGEND: new goog.events.EventId('dragend'),
- /**
- * Raised whenever the dragger element is removed:
- * - When a drag completes successfully.
- * - If the drag never started due to mouseup within hysteresis.
- * - If the drag was cancelled by a BEFORE* event.
- * - If the drag was cancelled due to focus loss.
- */
- DRAGGERREMOVED:
- new goog.events.EventId(goog.events.getUniqueId('draggerremoved'))
- };
- /**
- * 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_;
- };
- /** @return {boolean} true if the user is currently dragging an element. */
- goog.fx.DragListGroup.prototype.isDragging = function() {
- return !!this.dragger_;
- };
- /**
- * 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. If present, must be a
- * single, valid classname (not a string of space-separated classnames).
- */
- 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_);
- // Split space-separated classes up into an array.
- this.draggerElClasses_ = goog.string.trim(draggerElClass).split(' ');
- };
- /**
- * 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) {
- this.listenForDragEvents(dragItems[j]);
- }
- }
- this.isInitialized_ = true;
- };
- /**
- * Adds a single item to the given drag list and sets up the drag listeners for
- * it.
- * If opt_index is specified the item is inserted at this index, otherwise the
- * item is added as the last child of the list.
- *
- * @param {!Element} list The drag list where to add item to.
- * @param {!Element} item The new element to add.
- * @param {number=} opt_index Index where to insert the item in the list. If not
- * specified item is inserted as the last child of list.
- */
- goog.fx.DragListGroup.prototype.addItemToDragList = function(
- list, item, opt_index) {
- if (goog.isDef(opt_index)) {
- goog.dom.insertChildAt(list, item, opt_index);
- } else {
- goog.dom.appendChild(list, item);
- }
- this.listenForDragEvents(item);
- };
- /** @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.
- *
- */
- goog.fx.DragListGroup.prototype.recacheListAndItemBounds = function() {
- this.recacheListAndItemBounds_(this.currDragItem_);
- };
- /**
- * 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);
- }
- }
- };
- /**
- * Listens for drag events on the given drag item. This method is currently used
- * to initialize drag items.
- *
- * @param {!Element} dragItem the element to initialize. This element has to be
- * in one of the drag lists.
- * @protected
- */
- goog.fx.DragListGroup.prototype.listenForDragEvents = function(dragItem) {
- 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_);
- };
- /**
- * 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_ = /** @type {!HTMLElement} */ (
- this.createDragElementInternal(this.currDragItem_));
- if (this.draggerElClasses_) {
- // Add CSS class for the clone, if any.
- goog.dom.classlist.addAll(
- goog.asserts.assert(this.draggerEl_), this.draggerElClasses_ || []);
- }
- // 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.dispatchEvent(new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.DRAGGERCREATED, this, e,
- this.currDragItem_, this.draggerEl_, this.dragger_));
- this.dragger_.startDrag(e);
- };
- /**
- * Creates copy of node being dragged.
- *
- * @param {Element} sourceEl Element to copy.
- * @return {!Element} The clone of {@code sourceEl}.
- * @deprecated Use goog.fx.Dragger.cloneNode().
- * @private
- */
- goog.fx.DragListGroup.prototype.cloneNode_ = function(sourceEl) {
- return goog.fx.Dragger.cloneNode(sourceEl);
- };
- /**
- * Generates an element to follow the cursor during dragging, given a drag
- * source element. The default behavior is simply to clone the source element,
- * but this may be overridden in subclasses. This method is called by
- * {@code createDragElement()} before the drag class is added.
- *
- * @param {Element} sourceEl Drag source element.
- * @return {!Element} The new drag element.
- * @protected
- * @suppress {deprecated}
- */
- goog.fx.DragListGroup.prototype.createDragElementInternal = function(sourceEl) {
- return this.cloneNode_(sourceEl);
- };
- /**
- * 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.classlist.addAll(
- goog.asserts.assert(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.classlist.add(
- goog.asserts.assert(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.classlist.remove(
- goog.asserts.assert(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_);
- var hadDragger = this.draggerEl_ && this.draggerEl_.parentElement;
- 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.classlist.removeAll(
- goog.asserts.assert(this.currDragItem_),
- this.currDragItemClasses_ || []);
- } else if (this.currDragItem_) {
- this.currDragItem_.style.visibility = '';
- }
- // 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.classlist.remove(
- goog.asserts.assert(dragList), dragList.dlgDragHoverClass_);
- }
- }
- if (hadDragger) {
- this.dispatchEvent(new goog.fx.DragListGroupEvent(
- goog.fx.DragListGroup.EventType.DRAGGERREMOVED, this, null,
- this.currDragItem_, this.draggerEl_, this.dragger_));
- }
- };
- /**
- * 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) {
- var targetEl = goog.asserts.assertElement(e.currentTarget);
- goog.dom.classlist.addAll(targetEl, 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) {
- var targetEl = goog.asserts.assertElement(e.currentTarget);
- goog.dom.classlist.removeAll(targetEl, 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) {
- var targetEl = goog.asserts.assertElement(e.currentTarget);
- goog.dom.classlist.addAll(targetEl, 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) {
- var targetEl = goog.asserts.assertElement(e.currentTarget);
- goog.dom.classlist.removeAll(
- targetEl, 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 = 0;
- 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);
- }
- };
- /**
- * The event object dispatched by DragListGroup.
- * The fields draggerElCenter, hoverList, and hoverNextItem are only available
- * for the BEFOREDRAGMOVE and DRAGMOVE events.
- *
- * @param {!goog.fx.DragListGroup.EventType} type
- * @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
- * @struct
- * @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);
|