// 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. goog.provide('goog.fx.AbstractDragDropTest'); goog.setTestOnly('goog.fx.AbstractDragDropTest'); goog.require('goog.array'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('goog.functions'); goog.require('goog.fx.AbstractDragDrop'); goog.require('goog.fx.DragDropItem'); goog.require('goog.math.Box'); goog.require('goog.math.Coordinate'); goog.require('goog.style'); goog.require('goog.testing.events'); goog.require('goog.testing.events.Event'); goog.require('goog.testing.jsunit'); var targets = [ {box_: new goog.math.Box(0, 3, 1, 1)}, {box_: new goog.math.Box(0, 7, 2, 6)}, {box_: new goog.math.Box(2, 2, 3, 1)}, {box_: new goog.math.Box(4, 1, 6, 1)}, {box_: new goog.math.Box(4, 9, 7, 6)}, {box_: new goog.math.Box(9, 9, 10, 1)} ]; var targets2 = [ {box_: new goog.math.Box(10, 50, 20, 10)}, {box_: new goog.math.Box(20, 50, 30, 10)}, {box_: new goog.math.Box(60, 50, 70, 10)}, {box_: new goog.math.Box(70, 50, 80, 10)} ]; var targets3 = [ {box_: new goog.math.Box(0, 4, 1, 1)}, {box_: new goog.math.Box(1, 6, 4, 5)}, {box_: new goog.math.Box(5, 5, 6, 2)}, {box_: new goog.math.Box(2, 1, 5, 0)} ]; /** * Test the utility function which tells how two one dimensional ranges * overlap. */ function testRangeOverlap() { assertEquals(RangeOverlap.LEFT, rangeOverlap(1, 2, 3, 4)); assertEquals(RangeOverlap.LEFT, rangeOverlap(2, 3, 3, 4)); assertEquals(RangeOverlap.LEFT_IN, rangeOverlap(1, 3, 2, 4)); assertEquals(RangeOverlap.IN, rangeOverlap(1, 3, 1, 4)); assertEquals(RangeOverlap.IN, rangeOverlap(2, 3, 1, 4)); assertEquals(RangeOverlap.IN, rangeOverlap(3, 4, 1, 4)); assertEquals(RangeOverlap.RIGHT_IN, rangeOverlap(2, 4, 1, 3)); assertEquals(RangeOverlap.RIGHT, rangeOverlap(2, 3, 1, 2)); assertEquals(RangeOverlap.RIGHT, rangeOverlap(3, 4, 1, 2)); assertEquals(RangeOverlap.CONTAINS, rangeOverlap(1, 4, 2, 3)); } /** * An enum describing how two ranges overlap (non-symmetrical relation). * @enum {number} */ RangeOverlap = { LEFT: 1, // First range is placed to the left of the second. LEFT_IN: 2, // First range overlaps on the left side of the second. IN: 3, // First range is completely contained in the second. RIGHT_IN: 4, // First range overlaps on the right side of the second. RIGHT: 5, // First range is placed to the right side of the second. CONTAINS: 6 // First range contains the second. }; /** * Computes how two one dimensional ranges overlap. * * @param {number} left1 Left inclusive bound of the first range. * @param {number} right1 Right exclusive bound of the first range. * @param {number} left2 Left inclusive bound of the second range. * @param {number} right2 Right exclusive bound of the second range. * @return {RangeOverlap} The enum value describing the type of the overlap. */ function rangeOverlap(left1, right1, left2, right2) { if (right1 <= left2) return RangeOverlap.LEFT; if (left1 >= right2) return RangeOverlap.RIGHT; var leftIn = left1 >= left2; var rightIn = right1 <= right2; if (leftIn && rightIn) return RangeOverlap.IN; if (leftIn) return RangeOverlap.RIGHT_IN; if (rightIn) return RangeOverlap.LEFT_IN; return RangeOverlap.CONTAINS; } /** * Tells whether two boxes overlap. * * @param {goog.math.Box} box1 First box in question. * @param {goog.math.Box} box2 Second box in question. * @return {boolean} Whether boxes overlap in any way. */ function boxOverlaps(box1, box2) { var horizontalOverlap = rangeOverlap(box1.left, box1.right, box2.left, box2.right); var verticalOverlap = rangeOverlap(box1.top, box1.bottom, box2.top, box2.bottom); return horizontalOverlap != RangeOverlap.LEFT && horizontalOverlap != RangeOverlap.RIGHT && verticalOverlap != RangeOverlap.LEFT && verticalOverlap != RangeOverlap.RIGHT; } /** * Tests if the utility function to compute box overlapping functions properly. */ function testBoxOverlaps() { // Overlapping tests. var box2 = new goog.math.Box(1, 4, 4, 1); // Corner overlaps. assertTrue('NW overlap', boxOverlaps(new goog.math.Box(0, 2, 2, 0), box2)); assertTrue('NE overlap', boxOverlaps(new goog.math.Box(0, 5, 2, 3), box2)); assertTrue('SE overlap', boxOverlaps(new goog.math.Box(3, 5, 5, 3), box2)); assertTrue('SW overlap', boxOverlaps(new goog.math.Box(3, 2, 5, 0), box2)); // Inside. assertTrue( 'Inside overlap', boxOverlaps(new goog.math.Box(2, 3, 3, 2), box2)); // Around. assertTrue( 'Outside overlap', boxOverlaps(new goog.math.Box(0, 5, 5, 0), box2)); // Edge overlaps. assertTrue('N overlap', boxOverlaps(new goog.math.Box(0, 3, 2, 2), box2)); assertTrue('E overlap', boxOverlaps(new goog.math.Box(2, 5, 3, 3), box2)); assertTrue('S overlap', boxOverlaps(new goog.math.Box(3, 3, 5, 2), box2)); assertTrue('W overlap', boxOverlaps(new goog.math.Box(2, 2, 3, 0), box2)); assertTrue('N-in overlap', boxOverlaps(new goog.math.Box(0, 5, 2, 0), box2)); assertTrue('E-in overlap', boxOverlaps(new goog.math.Box(0, 5, 5, 3), box2)); assertTrue('S-in overlap', boxOverlaps(new goog.math.Box(3, 5, 5, 0), box2)); assertTrue('W-in overlap', boxOverlaps(new goog.math.Box(0, 2, 5, 0), box2)); // Does not overlap. var box2 = new goog.math.Box(3, 6, 6, 3); // Along the edge - shorter. assertFalse( 'N-in no overlap', boxOverlaps(new goog.math.Box(1, 5, 2, 4), box2)); assertFalse( 'E-in no overlap', boxOverlaps(new goog.math.Box(4, 8, 5, 7), box2)); assertFalse( 'S-in no overlap', boxOverlaps(new goog.math.Box(7, 5, 8, 4), box2)); assertFalse( 'N-in no overlap', boxOverlaps(new goog.math.Box(4, 2, 5, 1), box2)); // By the corner. assertFalse( 'NE no overlap', boxOverlaps(new goog.math.Box(1, 8, 2, 7), box2)); assertFalse( 'SE no overlap', boxOverlaps(new goog.math.Box(7, 8, 8, 7), box2)); assertFalse( 'SW no overlap', boxOverlaps(new goog.math.Box(7, 2, 8, 1), box2)); assertFalse( 'NW no overlap', boxOverlaps(new goog.math.Box(1, 2, 2, 1), box2)); // Perpendicular to an edge. assertFalse( 'NNE no overlap', boxOverlaps(new goog.math.Box(1, 7, 2, 5), box2)); assertFalse( 'NEE no overlap', boxOverlaps(new goog.math.Box(2, 8, 4, 7), box2)); assertFalse( 'SEE no overlap', boxOverlaps(new goog.math.Box(5, 8, 7, 7), box2)); assertFalse( 'SSE no overlap', boxOverlaps(new goog.math.Box(7, 7, 8, 5), box2)); assertFalse( 'SSW no overlap', boxOverlaps(new goog.math.Box(7, 4, 8, 2), box2)); assertFalse( 'SWW no overlap', boxOverlaps(new goog.math.Box(5, 2, 7, 1), box2)); assertFalse( 'NWW no overlap', boxOverlaps(new goog.math.Box(2, 2, 4, 1), box2)); assertFalse( 'NNW no overlap', boxOverlaps(new goog.math.Box(1, 4, 2, 2), box2)); // Along the edge - longer. assertFalse('N no overlap', boxOverlaps(new goog.math.Box(0, 7, 1, 2), box2)); assertFalse('E no overlap', boxOverlaps(new goog.math.Box(2, 9, 7, 8), box2)); assertFalse('S no overlap', boxOverlaps(new goog.math.Box(8, 7, 9, 2), box2)); assertFalse('W no overlap', boxOverlaps(new goog.math.Box(2, 1, 7, 0), box2)); } /** * Checks whether a given box overlaps any of given DnD target boxes. * * @param {goog.math.Box} box The box to check. * @param {Array} targets The array of targets with boxes to check * if they overlap with the given box. * @return {boolean} Whether the box overlaps any of the target boxes. */ function boxOverlapsTargets(box, targets) { return goog.array.some( targets, function(target) { return boxOverlaps(box, target.box_); }); } function testMaybeCreateDummyTargetForPosition() { var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = targets; testGroup.targetBox_ = new goog.math.Box(0, 9, 10, 1); var target = testGroup.maybeCreateDummyTargetForPosition_(3, 3); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(3, 3, target.box_)); target = testGroup.maybeCreateDummyTargetForPosition_(2, 4); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(2, 4, target.box_)); target = testGroup.maybeCreateDummyTargetForPosition_(2, 7); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(2, 7, target.box_)); testGroup.targetList_.push({box_: new goog.math.Box(5, 6, 6, 0)}); target = testGroup.maybeCreateDummyTargetForPosition_(3, 3); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(3, 3, target.box_)); target = testGroup.maybeCreateDummyTargetForPosition_(2, 7); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(2, 7, target.box_)); target = testGroup.maybeCreateDummyTargetForPosition_(6, 3); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(6, 3, target.box_)); target = testGroup.maybeCreateDummyTargetForPosition_(0, 3); assertNull(target); target = testGroup.maybeCreateDummyTargetForPosition_(9, 0); assertNull(target); } function testMaybeCreateDummyTargetForPosition2() { var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = targets2; testGroup.targetBox_ = new goog.math.Box(10, 50, 80, 10); var target = testGroup.maybeCreateDummyTargetForPosition_(30, 40); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(30, 40, target.box_)); target = testGroup.maybeCreateDummyTargetForPosition_(45, 40); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(45, 40, target.box_)); testGroup.targetList_.push({box_: new goog.math.Box(40, 50, 50, 40)}); target = testGroup.maybeCreateDummyTargetForPosition_(30, 40); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); target = testGroup.maybeCreateDummyTargetForPosition_(45, 35); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); } function testMaybeCreateDummyTargetForPosition3BoxHasDecentSize() { var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = targets3; testGroup.targetBox_ = new goog.math.Box(0, 6, 6, 0); var target = testGroup.maybeCreateDummyTargetForPosition_(3, 3); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(3, 3, target.box_)); assertEquals('(1t, 5r, 5b, 1l)', target.box_.toString()); } function testMaybeCreateDummyTargetForPosition4() { var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = targets; testGroup.targetBox_ = new goog.math.Box(0, 9, 10, 1); for (var x = testGroup.targetBox_.left; x < testGroup.targetBox_.right; x++) { for (var y = testGroup.targetBox_.top; y < testGroup.targetBox_.bottom; y++) { var inRealTarget = false; for (var i = 0; i < testGroup.targetList_.length; i++) { if (testGroup.isInside(x, y, testGroup.targetList_[i].box_)) { inRealTarget = true; break; } } if (!inRealTarget) { var target = testGroup.maybeCreateDummyTargetForPosition_(x, y); if (target) { assertFalse( 'Fake target for point(' + x + ',' + y + ') should ' + 'not overlap any real targets.', boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(x, y, target.box_)); } } } } } function testMaybeCreateDummyTargetForPosition_NegativePositions() { var negTargets = [ {box_: new goog.math.Box(-20, 10, -5, 1)}, {box_: new goog.math.Box(20, 10, 30, 1)} ]; var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = negTargets; testGroup.targetBox_ = new goog.math.Box(-20, 10, 30, 1); var target = testGroup.maybeCreateDummyTargetForPosition_(1, 5); assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_)); assertTrue(testGroup.isInside(1, 5, target.box_)); } function testMaybeCreateDummyTargetOutsideScrollableContainer() { var targets = [ {box_: new goog.math.Box(0, 3, 10, 1)}, {box_: new goog.math.Box(20, 3, 30, 1)} ]; var target = targets[0]; var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = targets; testGroup.targetBox_ = new goog.math.Box(0, 3, 30, 1); testGroup.addScrollableContainer(document.getElementById('container1')); var container = testGroup.scrollableContainers_[0]; container.containedTargets_.push(target); container.box_ = new goog.math.Box(0, 3, 5, 1); // shorter than target target.scrollableContainer_ = container; // mouse cursor is below scrollable target but not the actual target var dummyTarget = testGroup.maybeCreateDummyTargetForPosition_(2, 7); // dummy target should not overlap the scrollable container assertFalse(boxOverlaps(dummyTarget.box_, container.box_)); // but should overlap the actual target, since not all of it is visible assertTrue(boxOverlaps(dummyTarget.box_, target.box_)); } function testMaybeCreateDummyTargetInsideScrollableContainer() { var targets = [ {box_: new goog.math.Box(0, 3, 10, 1)}, {box_: new goog.math.Box(20, 3, 30, 1)} ]; var target = targets[0]; var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = targets; testGroup.targetBox_ = new goog.math.Box(0, 3, 30, 1); testGroup.addScrollableContainer(document.getElementById('container1')); var container = testGroup.scrollableContainers_[0]; container.containedTargets_.push(target); container.box_ = new goog.math.Box(0, 3, 20, 1); // longer than target target.scrollableContainer_ = container; // mouse cursor is below both the scrollable and the actual target var dummyTarget = testGroup.maybeCreateDummyTargetForPosition_(2, 15); // dummy target should overlap the scrollable container assertTrue(boxOverlaps(dummyTarget.box_, container.box_)); // but not overlap the actual target assertFalse(boxOverlaps(dummyTarget.box_, target.box_)); } function testCalculateTargetBox() { var testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = []; goog.array.forEach(targets, function(target) { testGroup.targetList_.push(target); testGroup.calculateTargetBox_(target.box_); }); assertTrue( goog.math.Box.equals( testGroup.targetBox_, new goog.math.Box(0, 9, 10, 1))); testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = []; goog.array.forEach(targets2, function(target) { testGroup.targetList_.push(target); testGroup.calculateTargetBox_(target.box_); }); assertTrue( goog.math.Box.equals( testGroup.targetBox_, new goog.math.Box(10, 50, 80, 10))); testGroup = new goog.fx.AbstractDragDrop(); testGroup.targetList_ = []; goog.array.forEach(targets3, function(target) { testGroup.targetList_.push(target); testGroup.calculateTargetBox_(target.box_); }); assertTrue( goog.math.Box.equals( testGroup.targetBox_, new goog.math.Box(0, 6, 6, 0))); } function testIsInside() { var add = new goog.fx.AbstractDragDrop(); // The box in question. // 10,20+++++20,20 // + | // 10,30-----20,30 var box = new goog.math.Box(20, 20, 30, 10); assertTrue( 'A point somewhere in the middle of the box should be inside.', add.isInside(15, 25, box)); assertTrue( 'A point in top-left corner should be inside the box.', add.isInside(10, 20, box)); assertTrue( 'A point on top border should be inside the box.', add.isInside(15, 20, box)); assertFalse( 'A point in top-right corner should be outside the box.', add.isInside(20, 20, box)); assertFalse( 'A point on right border should be outside the box.', add.isInside(20, 25, box)); assertFalse( 'A point in bottom-right corner should be outside the box.', add.isInside(20, 30, box)); assertFalse( 'A point on bottom border should be outside the box.', add.isInside(15, 30, box)); assertFalse( 'A point in bottom-left corner should be outside the box.', add.isInside(10, 30, box)); assertTrue( 'A point on left border should be inside the box.', add.isInside(10, 25, box)); add.dispose(); } function testAddingRemovingScrollableContainers() { var group = new goog.fx.AbstractDragDrop(); var el1 = goog.dom.createElement(goog.dom.TagName.DIV); var el2 = goog.dom.createElement(goog.dom.TagName.DIV); assertEquals(0, group.scrollableContainers_.length); group.addScrollableContainer(el1); assertEquals(1, group.scrollableContainers_.length); group.addScrollableContainer(el2); assertEquals(2, group.scrollableContainers_.length); group.removeAllScrollableContainers(); assertEquals(0, group.scrollableContainers_.length); } function testScrollableContainersCalculation() { var group = new goog.fx.AbstractDragDrop(); var target = new goog.fx.AbstractDragDrop(); group.addTarget(target); group.addScrollableContainer(document.getElementById('container1')); var container = group.scrollableContainers_[0]; var item1 = new goog.fx.DragDropItem(document.getElementById('child1')); var item2 = new goog.fx.DragDropItem(document.getElementById('child2')); target.items_.push(item1); group.recalculateDragTargets(); group.recalculateScrollableContainers(); assertEquals(1, container.containedTargets_.length); assertEquals(container, group.targetList_[0].scrollableContainer_); target.items_.push(item2); group.recalculateDragTargets(); assertEquals(1, container.containedTargets_.length); assertNull(group.targetList_[0].scrollableContainer_); group.recalculateScrollableContainers(); assertEquals(2, container.containedTargets_.length); assertEquals(container, group.targetList_[1].scrollableContainer_); } function testMouseDownEventDefaultAction() { var group = new goog.fx.AbstractDragDrop(); var target = new goog.fx.AbstractDragDrop(); group.addTarget(target); var item1 = new goog.fx.DragDropItem(document.getElementById('child1')); group.items_.push(item1); item1.setParent(group); group.init(); var mousedownDefaultPrevented = !goog.testing.events.fireMouseDownEvent(item1.element); assertFalse( 'Default action of mousedown event should not be cancelled.', mousedownDefaultPrevented); } // See http://b/7494613. function testMouseUpOutsideElement() { var group = new goog.fx.AbstractDragDrop(); var target = new goog.fx.AbstractDragDrop(); group.addTarget(target); var item1 = new goog.fx.DragDropItem(document.getElementById('child1')); group.items_.push(item1); item1.setParent(group); group.init(); group.startDrag = goog.functions.error('startDrag should not be called.'); goog.testing.events.fireMouseDownEvent(item1.element); goog.testing.events.fireMouseUpEvent(item1.element.parentNode); // This should have no effect (not start a drag) since the previous event // should have cleared the listeners. goog.testing.events.fireMouseOutEvent(item1.element); group.dispose(); target.dispose(); } function testScrollBeforeMoveDrag() { var group = new goog.fx.AbstractDragDrop(); var target = new goog.fx.AbstractDragDrop(); group.addTarget(target); var container = document.getElementById('container1'); group.addScrollableContainer(container); var childEl = document.getElementById('child1'); var item = new goog.fx.DragDropItem(childEl); item.currentDragElement_ = childEl; target.items_.push(item); group.recalculateDragTargets(); group.recalculateScrollableContainers(); // Simulare starting a drag. var moveEvent = { 'clientX': 8, 'clientY': 10, 'type': goog.events.EventType.MOUSEMOVE, 'relatedTarget': childEl, 'preventDefault': function() {} }; group.startDrag(moveEvent, item); // Simulate scrolling before the first move drag event. var scrollEvent = {'target': container}; assertNotThrows(goog.bind(group.containerScrollHandler_, group, scrollEvent)); } function testMouseMove_mouseOutBeforeThreshold() { // Setup dragdrop and item var itemEl = goog.dom.createElement(goog.dom.TagName.DIV); var childEl = goog.dom.createElement(goog.dom.TagName.DIV); itemEl.appendChild(childEl); var add = new goog.fx.AbstractDragDrop(); var item = new goog.fx.DragDropItem(itemEl); item.setParent(add); add.items_.push(item); // Simulate maybeStartDrag item.startPosition_ = new goog.math.Coordinate(10, 10); item.currentDragElement_ = itemEl; // Test var draggedItem = null; add.startDrag = function(event, item) { draggedItem = item; }; var event = new goog.testing.events.Event(goog.events.EventType.MOUSEOUT, childEl); // Drag distance is only 2. event.clientX = 8; event.clientY = 10; item.mouseMove_(event); assertEquals( 'DragStart should not be fired for mouseout on child element.', null, draggedItem); var event = new goog.testing.events.Event(goog.events.EventType.MOUSEOUT, itemEl); // Drag distance is only 2. event.clientX = 8; event.clientY = 10; item.mouseMove_(event); assertEquals( 'DragStart should be fired for mouseout on main element.', item, draggedItem); } function testGetDragElementPosition() { var testGroup = new goog.fx.AbstractDragDrop(); var sourceEl = goog.dom.createElement(goog.dom.TagName.DIV); document.body.appendChild(sourceEl); var pageOffset = goog.style.getPageOffset(sourceEl); var pos = testGroup.getDragElementPosition(sourceEl); assertEquals( 'Drag element position should be source element page offset', pageOffset.x, pos.x); assertEquals( 'Drag element position should be source element page offset', pageOffset.y, pos.y); sourceEl.style.marginLeft = '5px'; sourceEl.style.marginTop = '7px'; pageOffset = goog.style.getPageOffset(sourceEl); pos = testGroup.getDragElementPosition(sourceEl); assertEquals( 'Drag element position should be adjusted for source element ' + 'margins', pageOffset.x - 10, pos.x); assertEquals( 'Drag element position should be adjusted for source element ' + 'margins', pageOffset.y - 14, pos.y); } function testDragEndEvent() { function testDragEndEventInternal(shouldContainItemData) { var testGroup = new goog.fx.AbstractDragDrop(); var childEl = document.getElementById('child1'); var item = new goog.fx.DragDropItem(childEl); item.currentDragElement_ = childEl; testGroup.items_.push(item); testGroup.recalculateDragTargets(); // Simulate starting a drag var startEvent = { 'clientX': 0, 'clientY': 0, 'type': goog.events.EventType.MOUSEMOVE, 'relatedTarget': childEl, 'preventDefault': function() {} }; testGroup.startDrag(startEvent, item); testGroup.activeTarget_ = new goog.fx.ActiveDropTarget_( new goog.math.Box(0, 0, 0, 0), testGroup, item, childEl); goog.events.listen( testGroup, goog.fx.AbstractDragDrop.EventType.DRAGEND, function(event) { if (shouldContainItemData) { assertEquals( 'The drag end event should contain a drop target', testGroup, event.dropTarget); assertEquals( 'The drag end event should contain a drop target item', item, event.dropTargetItem); assertEquals( 'The drag end event should contain a drop target element', childEl, event.dropTargetElement); } else { assertUndefined( 'The drag end event shouldn\'t contain a drop target', event.dropTarget); assertUndefined( 'The drag end event shouldn\'t contain a drop target item', event.dropTargetItem); assertUndefined( 'The drag end event shouldn\'t contain a drop target element', event.dropTargetElement); } }); testGroup.endDrag( {'clientX': 0, 'clientY': 0, 'dragCanceled': !shouldContainItemData}); testGroup.dispose(); item.dispose(); } testDragEndEventInternal(false); testDragEndEventInternal(true); } function testDropEventHasBrowserEvent() { var testGroup = new goog.fx.AbstractDragDrop(); var childEl = document.getElementById('child1'); var item = new goog.fx.DragDropItem(childEl); item.currentDragElement_ = childEl; testGroup.items_.push(item); testGroup.recalculateDragTargets(); // Simulate starting a drag var startBrowserEvent = { 'clientX': 0, 'clientY': 0, 'type': goog.events.EventType.MOUSEMOVE, 'relatedTarget': childEl, 'preventDefault': function() {}, }; testGroup.startDrag(startBrowserEvent, item); testGroup.activeTarget_ = new goog.fx.ActiveDropTarget_( new goog.math.Box(0, 0, 0, 0), testGroup, item, childEl); var endBrowserEvent = { 'clientX': 0, 'clientY': 0, 'type': goog.events.EventType.MOUSEUP, 'ctrlKey': false, 'altKey': true }; goog.events.listen( testGroup, goog.fx.AbstractDragDrop.EventType.DROP, function(event) { var browserEvent = event.browserEvent; assertEquals( 'The drop event should contain the browser event', endBrowserEvent, browserEvent); }); testGroup.endDrag({ 'clientX': 0, 'clientY': 0, 'dragCanceled': false, 'browserEvent': endBrowserEvent }); testGroup.dispose(); item.dispose(); } // Helper function for manual debugging. function drawTargets(targets, multiplier) { var colors = ['green', 'blue', 'red', 'lime', 'pink', 'silver', 'orange']; var cont = document.getElementById('cont'); cont.innerHTML = ''; for (var i = 0; i < targets.length; i++) { var box = targets[i].box_; var el = goog.dom.createElement(goog.dom.TagName.DIV); el.style.top = (box.top * multiplier) + 'px'; el.style.left = (box.left * multiplier) + 'px'; el.style.width = ((box.right - box.left) * multiplier) + 'px'; el.style.height = ((box.bottom - box.top) * multiplier) + 'px'; el.style.backgroundColor = colors[i]; cont.appendChild(el); } }