314 lines
11 KiB
JavaScript
314 lines
11 KiB
JavaScript
// 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.ui.PopupMenuTest');
|
|
goog.setTestOnly('goog.ui.PopupMenuTest');
|
|
|
|
goog.require('goog.dom');
|
|
goog.require('goog.events.EventHandler');
|
|
goog.require('goog.events.EventType');
|
|
goog.require('goog.math.Box');
|
|
goog.require('goog.math.Coordinate');
|
|
goog.require('goog.positioning.Corner');
|
|
goog.require('goog.style');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.ui.Menu');
|
|
goog.require('goog.ui.MenuItem');
|
|
goog.require('goog.ui.PopupMenu');
|
|
|
|
var anchor;
|
|
|
|
// Event handler
|
|
var handler;
|
|
var showPopup;
|
|
var beforeShowPopupCalled;
|
|
var popup;
|
|
|
|
function setUp() {
|
|
anchor = goog.dom.getElement('popup-anchor');
|
|
handler = new goog.events.EventHandler();
|
|
popup = new goog.ui.PopupMenu();
|
|
popup.render();
|
|
}
|
|
|
|
function tearDown() {
|
|
handler.dispose();
|
|
popup.dispose();
|
|
}
|
|
|
|
|
|
/**
|
|
* Asserts properties of {@code target} matches the expected value.
|
|
*
|
|
* @param {Object} target The target specifying how the popup menu should be
|
|
* attached to an anchor.
|
|
* @param {Element} expectedElement The expected anchoring element.
|
|
* @param {goog.positioning.Corner} expectedTargetCorner The expected value of
|
|
* the {@code target.targetCorner_} property.
|
|
* @param {goog.positioning.Corner} expectedMenuCorner The expected value of
|
|
* the {@code target.menuCorner_} property.
|
|
* @param {goog.events.EventType} expectedEventType The expected value of the
|
|
* {@code target.eventType_} property.
|
|
* @param {goog.math.Box} expectedMargin The expected value of the
|
|
* {@code target.margin_} property.
|
|
*/
|
|
function assertTarget(target, expectedElement, expectedTargetCorner,
|
|
expectedMenuCorner, expectedEventType, expectedMargin) {
|
|
var expectedTarget = {
|
|
element_: expectedElement,
|
|
targetCorner_: expectedTargetCorner,
|
|
menuCorner_: expectedMenuCorner,
|
|
eventType_: expectedEventType,
|
|
margin_: expectedMargin
|
|
};
|
|
|
|
assertObjectEquals('Target does not match.', expectedTarget, target);
|
|
}
|
|
|
|
|
|
/**
|
|
* Test menu receives BEFORE_SHOW event before it's displayed.
|
|
*/
|
|
function testBeforeShowEvent() {
|
|
var target = popup.createAttachTarget(anchor);
|
|
popup.attach(anchor);
|
|
|
|
function beforeShowPopup(e) {
|
|
// Ensure that the element is not yet visible.
|
|
assertFalse('The element should not be shown when BEFORE_SHOW event is ' +
|
|
'being handled',
|
|
goog.style.isElementShown(popup.getElement()));
|
|
// Verify that current anchor is set before dispatching BEFORE_SHOW.
|
|
assertNotNullNorUndefined(popup.getAttachedElement());
|
|
assertEquals('The attached anchor element is incorrect',
|
|
target.element_, popup.getAttachedElement());
|
|
beforeShowPopupCalled = true;
|
|
return showPopup;
|
|
|
|
};
|
|
function onShowPopup(e) {
|
|
assertEquals('The attached anchor element is incorrect',
|
|
target.element_, popup.getAttachedElement());
|
|
};
|
|
|
|
handler.listen(popup,
|
|
goog.ui.Menu.EventType.BEFORE_SHOW,
|
|
beforeShowPopup);
|
|
handler.listen(popup,
|
|
goog.ui.Menu.EventType.SHOW,
|
|
onShowPopup);
|
|
|
|
beforeShowPopupCalled = false;
|
|
showPopup = false;
|
|
popup.showMenu(target, 0, 0);
|
|
assertTrue('BEFORE_SHOW event handler should be called on #showMenu',
|
|
beforeShowPopupCalled);
|
|
assertFalse('The element should not be shown when BEFORE_SHOW handler ' +
|
|
'returned false',
|
|
goog.style.isElementShown(popup.getElement()));
|
|
|
|
beforeShowPopupCalled = false;
|
|
showPopup = true;
|
|
popup.showMenu(target, 0, 0);
|
|
assertTrue('The element should be shown when BEFORE_SHOW handler ' +
|
|
'returned true',
|
|
goog.style.isElementShown(popup.getElement()));
|
|
}
|
|
|
|
|
|
/**
|
|
* Test the behavior of {@link PopupMenu.isAttachTarget}.
|
|
*/
|
|
function testIsAttachTarget() {
|
|
// Before 'attach' is called.
|
|
assertFalse('Menu should not be attached to the element',
|
|
popup.isAttachTarget(anchor));
|
|
|
|
popup.attach(anchor);
|
|
assertTrue('Menu should be attached to the anchor',
|
|
popup.isAttachTarget(anchor));
|
|
|
|
popup.detach(anchor);
|
|
assertFalse('Menu is expected to be detached from the element',
|
|
popup.isAttachTarget(anchor));
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests the behavior of {@link PopupMenu.createAttachTarget}.
|
|
*/
|
|
function testCreateAttachTarget() {
|
|
// Randomly picking parameters.
|
|
var targetCorner = goog.positioning.Corner.TOP_END;
|
|
var menuCorner = goog.positioning.Corner.BOTTOM_LEFT;
|
|
var contextMenu = false; // Show menu on mouse down event.
|
|
var margin = new goog.math.Box(0, 10, 5, 25);
|
|
|
|
// Simply setting the required parameters.
|
|
var target = popup.createAttachTarget(anchor);
|
|
assertTrue(popup.isAttachTarget(anchor));
|
|
assertTarget(target, anchor, undefined, undefined,
|
|
goog.events.EventType.MOUSEDOWN, undefined);
|
|
|
|
// Creating another target with all the parameters.
|
|
target = popup.createAttachTarget(anchor, targetCorner, menuCorner,
|
|
contextMenu, margin);
|
|
assertTrue(popup.isAttachTarget(anchor));
|
|
assertTarget(target, anchor, targetCorner, menuCorner,
|
|
goog.events.EventType.MOUSEDOWN, margin);
|
|
|
|
// Finally, switch up the 'contextMenu'
|
|
target = popup.createAttachTarget(anchor, undefined, undefined,
|
|
true /*opt_contextMenu*/, undefined);
|
|
assertTarget(target, anchor, undefined, undefined,
|
|
goog.events.EventType.CONTEXTMENU, undefined);
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests the behavior of {@link PopupMenu.getAttachTarget}.
|
|
*/
|
|
function testGetAttachTarget() {
|
|
// Before the menu is attached to the anchor.
|
|
var target = popup.getAttachTarget(anchor);
|
|
assertTrue('Not expecting a target before the element is attach to the menu',
|
|
target == null);
|
|
|
|
// Randomly picking parameters.
|
|
var targetCorner = goog.positioning.Corner.TOP_END;
|
|
var menuCorner = goog.positioning.Corner.BOTTOM_LEFT;
|
|
var contextMenu = false; // Show menu on mouse down event.
|
|
var margin = new goog.math.Box(0, 10, 5, 25);
|
|
|
|
popup.attach(anchor, targetCorner, menuCorner, contextMenu, margin);
|
|
target = popup.getAttachTarget(anchor);
|
|
assertTrue('Failed to get target after attaching element to menu',
|
|
target != null);
|
|
|
|
// Make sure we got the right target back.
|
|
assertTarget(target, anchor, targetCorner, menuCorner,
|
|
goog.events.EventType.MOUSEDOWN, margin);
|
|
}
|
|
|
|
function testSmallViewportSliding() {
|
|
popup.getElement().style.position = 'absolute';
|
|
popup.getElement().style.outline = '1px solid blue';
|
|
var item = new goog.ui.MenuItem('Test Item');
|
|
popup.addChild(item, true);
|
|
item.getElement().style.overflow = 'hidden';
|
|
|
|
var viewport = goog.style.getClientViewportElement();
|
|
var viewportRect = goog.style.getVisibleRectForElement(viewport);
|
|
|
|
var middlePos = Math.floor((viewportRect.right - viewportRect.left) / 2);
|
|
var leftwardPos = Math.floor((viewportRect.right - viewportRect.left) / 3);
|
|
var rightwardPos =
|
|
Math.floor((viewportRect.right - viewportRect.left) / 3 * 2);
|
|
|
|
// Can interpret these positions as widths relative to the viewport as well.
|
|
var smallWidth = leftwardPos;
|
|
var mediumWidth = middlePos;
|
|
var largeWidth = rightwardPos;
|
|
|
|
// Test small menu first. This should be small enough that it will display
|
|
// its upper left corner where we tell it to in all three positions.
|
|
popup.getElement().style.width = smallWidth + 'px';
|
|
|
|
var target = popup.createAttachTarget(anchor);
|
|
popup.attach(anchor);
|
|
|
|
popup.showMenu(target, leftwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: small size, leftward pos',
|
|
new goog.math.Coordinate(leftwardPos, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
popup.showMenu(target, middlePos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: small size, middle pos',
|
|
new goog.math.Coordinate(middlePos, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
popup.showMenu(target, rightwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: small size, rightward pos',
|
|
new goog.math.Coordinate(rightwardPos, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
// Test medium menu next. This should display with its upper left corner
|
|
// at the target when leftward and middle, but on the right it should
|
|
// position its upper right corner at the target instead.
|
|
popup.getElement().style.width = mediumWidth + 'px';
|
|
|
|
popup.showMenu(target, leftwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: medium size, leftward pos',
|
|
new goog.math.Coordinate(leftwardPos, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
popup.showMenu(target, middlePos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: medium size, middle pos',
|
|
new goog.math.Coordinate(middlePos, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
popup.showMenu(target, rightwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: medium size, rightward pos',
|
|
new goog.math.Coordinate(rightwardPos - mediumWidth, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
// Test large menu next. This should display with its upper left corner at
|
|
// the target when leftward, and its upper right corner at the target when
|
|
// rightward, but right in the middle neither corner can be at the target and
|
|
// keep the entire menu onscreen, so it should place its upper right corner
|
|
// at the very right edge of the viewport.
|
|
popup.getElement().style.width = largeWidth + 'px';
|
|
popup.showMenu(target, leftwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: large size, leftward pos',
|
|
new goog.math.Coordinate(leftwardPos, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
popup.showMenu(target, middlePos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: large size, middle pos',
|
|
new goog.math.Coordinate(
|
|
viewportRect.right - viewportRect.left - largeWidth, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
popup.showMenu(target, rightwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: large size, rightward pos',
|
|
new goog.math.Coordinate(rightwardPos - largeWidth, 0),
|
|
goog.style.getPosition(popup.getElement()));
|
|
|
|
// Make sure that the menu still displays correctly if we give the target
|
|
// a target corner. We can't set the overflow policy in that case, but it
|
|
// should still display.
|
|
popup.detach(anchor);
|
|
anchor.style.position = 'absolute';
|
|
anchor.style.left = '24px';
|
|
anchor.style.top = '24px';
|
|
var targetCorner = goog.positioning.Corner.TOP_END;
|
|
target = popup.createAttachTarget(anchor, targetCorner);
|
|
popup.attach(anchor, targetCorner);
|
|
popup.getElement().style.width = smallWidth + 'px';
|
|
popup.showMenu(target, leftwardPos, 0);
|
|
assertObjectEquals(
|
|
'Popup in wrong position: small size, leftward pos, with target corner',
|
|
new goog.math.Coordinate(24, 24),
|
|
goog.style.getPosition(popup.getElement()));
|
|
}
|