Update wmts-hidpi, add nicer-api-docs
This commit is contained in:
999
nicer-api-docs/closure-library/closure/goog/ui/tooltip.js
Normal file
999
nicer-api-docs/closure-library/closure/goog/ui/tooltip.js
Normal file
@@ -0,0 +1,999 @@
|
||||
// Copyright 2007 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 Tooltip widget implementation.
|
||||
*
|
||||
* @author eae@google.com (Emil A Eklund)
|
||||
* @see ../demos/tooltip.html
|
||||
*/
|
||||
|
||||
goog.provide('goog.ui.Tooltip');
|
||||
goog.provide('goog.ui.Tooltip.CursorTooltipPosition');
|
||||
goog.provide('goog.ui.Tooltip.ElementTooltipPosition');
|
||||
goog.provide('goog.ui.Tooltip.State');
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.math.Box');
|
||||
goog.require('goog.math.Coordinate');
|
||||
goog.require('goog.positioning');
|
||||
goog.require('goog.positioning.AnchoredPosition');
|
||||
goog.require('goog.positioning.Corner');
|
||||
goog.require('goog.positioning.Overflow');
|
||||
goog.require('goog.positioning.OverflowStatus');
|
||||
goog.require('goog.positioning.ViewportPosition');
|
||||
goog.require('goog.structs.Set');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.ui.Popup');
|
||||
goog.require('goog.ui.PopupBase');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tooltip widget. Can be attached to one or more elements and is shown, with a
|
||||
* slight delay, when the the cursor is over the element or the element gains
|
||||
* focus.
|
||||
*
|
||||
* @param {Element|string=} opt_el Element to display tooltip for, either
|
||||
* element reference or string id.
|
||||
* @param {?string=} opt_str Text message to display in tooltip.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
|
||||
* @constructor
|
||||
* @extends {goog.ui.Popup}
|
||||
*/
|
||||
goog.ui.Tooltip = function(opt_el, opt_str, opt_domHelper) {
|
||||
/**
|
||||
* Dom Helper
|
||||
* @type {goog.dom.DomHelper}
|
||||
* @private
|
||||
*/
|
||||
this.dom_ = opt_domHelper || (opt_el ?
|
||||
goog.dom.getDomHelper(goog.dom.getElement(opt_el)) :
|
||||
goog.dom.getDomHelper());
|
||||
|
||||
goog.ui.Popup.call(this, this.dom_.createDom(
|
||||
'div', {'style': 'position:absolute;display:none;'}));
|
||||
|
||||
/**
|
||||
* Cursor position relative to the page.
|
||||
* @type {!goog.math.Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
this.cursorPosition = new goog.math.Coordinate(1, 1);
|
||||
|
||||
/**
|
||||
* Elements this widget is attached to.
|
||||
* @type {goog.structs.Set}
|
||||
* @private
|
||||
*/
|
||||
this.elements_ = new goog.structs.Set();
|
||||
|
||||
// Attach to element, if specified
|
||||
if (opt_el) {
|
||||
this.attach(opt_el);
|
||||
}
|
||||
|
||||
// Set message, if specified.
|
||||
if (opt_str != null) {
|
||||
this.setText(opt_str);
|
||||
}
|
||||
};
|
||||
goog.inherits(goog.ui.Tooltip, goog.ui.Popup);
|
||||
|
||||
|
||||
/**
|
||||
* List of active (open) tooltip widgets. Used to prevent multiple tooltips
|
||||
* from appearing at once.
|
||||
*
|
||||
* @type {!Array.<goog.ui.Tooltip>}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.activeInstances_ = [];
|
||||
|
||||
|
||||
/**
|
||||
* Active element reference. Used by the delayed show functionality to keep
|
||||
* track of the element the mouse is over or the element with focus.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.activeEl_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* CSS class name for tooltip.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.className = goog.getCssName('goog-tooltip');
|
||||
|
||||
|
||||
/**
|
||||
* Delay in milliseconds since the last mouseover or mousemove before the
|
||||
* tooltip is displayed for an element.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.showDelayMs_ = 500;
|
||||
|
||||
|
||||
/**
|
||||
* Timer for when to show.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.showTimer;
|
||||
|
||||
|
||||
/**
|
||||
* Delay in milliseconds before tooltips are hidden.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.hideDelayMs_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Timer for when to hide.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.hideTimer;
|
||||
|
||||
|
||||
/**
|
||||
* Element that triggered the tooltip. Note that if a second element triggers
|
||||
* this tooltip, anchor becomes that second element, even if its show is
|
||||
* cancelled and the original tooltip survives.
|
||||
*
|
||||
* @type {Element|undefined}
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.anchor;
|
||||
|
||||
|
||||
/**
|
||||
* Possible states for the tooltip to be in.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.ui.Tooltip.State = {
|
||||
INACTIVE: 0,
|
||||
WAITING_TO_SHOW: 1,
|
||||
SHOWING: 2,
|
||||
WAITING_TO_HIDE: 3,
|
||||
UPDATING: 4 // waiting to show new hovercard while old one still showing.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Popup activation types. Used to select a positioning strategy.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.ui.Tooltip.Activation = {
|
||||
CURSOR: 0,
|
||||
FOCUS: 1
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the anchor has seen the cursor move or has received focus since the
|
||||
* tooltip was last shown. Used to ignore mouse over events triggered by view
|
||||
* changes and UI updates.
|
||||
* @type {boolean|undefined}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.seenInteraction_;
|
||||
|
||||
|
||||
/**
|
||||
* Whether the cursor must have moved before the tooltip will be shown.
|
||||
* @type {boolean|undefined}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.requireInteraction_;
|
||||
|
||||
|
||||
/**
|
||||
* If this tooltip's element contains another tooltip that becomes active, this
|
||||
* property identifies that tooltip so that we can check if this tooltip should
|
||||
* not be hidden because the nested tooltip is active.
|
||||
* @type {goog.ui.Tooltip}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.childTooltip_;
|
||||
|
||||
|
||||
/**
|
||||
* If this tooltip is inside another tooltip's element, then it may have
|
||||
* prevented that tooltip from hiding. When this tooltip hides, we'll need
|
||||
* to check if the parent should be hidden as well.
|
||||
* @type {goog.ui.Tooltip}
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.parentTooltip_;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the dom helper that is being used on this component.
|
||||
* @return {goog.dom.DomHelper} The dom helper used on this component.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getDomHelper = function() {
|
||||
return this.dom_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.ui.Tooltip} Active tooltip in a child element, or null if none.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getChildTooltip = function() {
|
||||
return this.childTooltip_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attach to element. Tooltip will be displayed when the cursor is over the
|
||||
* element or when the element has been active for a few milliseconds.
|
||||
*
|
||||
* @param {Element|string} el Element to display tooltip for, either element
|
||||
* reference or string id.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.attach = function(el) {
|
||||
el = goog.dom.getElement(el);
|
||||
|
||||
this.elements_.add(el);
|
||||
goog.events.listen(el, goog.events.EventType.MOUSEOVER,
|
||||
this.handleMouseOver, false, this);
|
||||
goog.events.listen(el, goog.events.EventType.MOUSEOUT,
|
||||
this.handleMouseOutAndBlur, false, this);
|
||||
goog.events.listen(el, goog.events.EventType.MOUSEMOVE,
|
||||
this.handleMouseMove, false, this);
|
||||
goog.events.listen(el, goog.events.EventType.FOCUS,
|
||||
this.handleFocus, false, this);
|
||||
goog.events.listen(el, goog.events.EventType.BLUR,
|
||||
this.handleMouseOutAndBlur, false, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detach from element(s).
|
||||
*
|
||||
* @param {Element|string=} opt_el Element to detach from, either element
|
||||
* reference or string id. If no element is
|
||||
* specified all are detached.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.detach = function(opt_el) {
|
||||
if (opt_el) {
|
||||
var el = goog.dom.getElement(opt_el);
|
||||
this.detachElement_(el);
|
||||
this.elements_.remove(el);
|
||||
} else {
|
||||
var a = this.elements_.getValues();
|
||||
for (var el, i = 0; el = a[i]; i++) {
|
||||
this.detachElement_(el);
|
||||
}
|
||||
this.elements_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detach from element.
|
||||
*
|
||||
* @param {Element} el Element to detach from.
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.detachElement_ = function(el) {
|
||||
goog.events.unlisten(el, goog.events.EventType.MOUSEOVER,
|
||||
this.handleMouseOver, false, this);
|
||||
goog.events.unlisten(el, goog.events.EventType.MOUSEOUT,
|
||||
this.handleMouseOutAndBlur, false, this);
|
||||
goog.events.unlisten(el, goog.events.EventType.MOUSEMOVE,
|
||||
this.handleMouseMove, false, this);
|
||||
goog.events.unlisten(el, goog.events.EventType.FOCUS,
|
||||
this.handleFocus, false, this);
|
||||
goog.events.unlisten(el, goog.events.EventType.BLUR,
|
||||
this.handleMouseOutAndBlur, false, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets delay in milliseconds before tooltip is displayed for an element.
|
||||
*
|
||||
* @param {number} delay The delay in milliseconds.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setShowDelayMs = function(delay) {
|
||||
this.showDelayMs_ = delay;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The delay in milliseconds before tooltip is displayed for an
|
||||
* element.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getShowDelayMs = function() {
|
||||
return this.showDelayMs_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets delay in milliseconds before tooltip is hidden once the cursor leavs
|
||||
* the element.
|
||||
*
|
||||
* @param {number} delay The delay in milliseconds.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setHideDelayMs = function(delay) {
|
||||
this.hideDelayMs_ = delay;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The delay in milliseconds before tooltip is hidden once the
|
||||
* cursor leaves the element.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getHideDelayMs = function() {
|
||||
return this.hideDelayMs_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets tooltip message as plain text.
|
||||
*
|
||||
* @param {string} str Text message to display in tooltip.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setText = function(str) {
|
||||
goog.dom.setTextContent(this.getElement(), str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets tooltip message as HTML markup.
|
||||
*
|
||||
* @param {string} str HTML message to display in tooltip.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setHtml = function(str) {
|
||||
this.getElement().innerHTML = str;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets tooltip element.
|
||||
*
|
||||
* @param {Element} el HTML element to use as the tooltip.
|
||||
* @override
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setElement = function(el) {
|
||||
var oldElement = this.getElement();
|
||||
if (oldElement) {
|
||||
goog.dom.removeNode(oldElement);
|
||||
}
|
||||
goog.ui.Tooltip.superClass_.setElement.call(this, el);
|
||||
if (el) {
|
||||
var body = this.dom_.getDocument().body;
|
||||
body.insertBefore(el, body.lastChild);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The tooltip message as plain text.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getText = function() {
|
||||
return goog.dom.getTextContent(this.getElement());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {string} The tooltip message as HTML.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getHtml = function() {
|
||||
return this.getElement().innerHTML;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.ui.Tooltip.State} Current state of tooltip.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getState = function() {
|
||||
return this.showTimer ?
|
||||
(this.isVisible() ? goog.ui.Tooltip.State.UPDATING :
|
||||
goog.ui.Tooltip.State.WAITING_TO_SHOW) :
|
||||
this.hideTimer ? goog.ui.Tooltip.State.WAITING_TO_HIDE :
|
||||
this.isVisible() ? goog.ui.Tooltip.State.SHOWING :
|
||||
goog.ui.Tooltip.State.INACTIVE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether tooltip requires the mouse to have moved or the anchor receive
|
||||
* focus before the tooltip will be shown.
|
||||
* @param {boolean} requireInteraction Whether tooltip should require some user
|
||||
* interaction before showing tooltip.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setRequireInteraction = function(requireInteraction) {
|
||||
this.requireInteraction_ = requireInteraction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the coord is in the tooltip.
|
||||
* @param {goog.math.Coordinate} coord Coordinate being tested.
|
||||
* @return {boolean} Whether the coord is in the tooltip.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.isCoordinateInTooltip = function(coord) {
|
||||
// Check if coord is inside the the tooltip
|
||||
if (!this.isVisible()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var offset = goog.style.getPageOffset(this.getElement());
|
||||
var size = goog.style.getSize(this.getElement());
|
||||
return offset.x <= coord.x && coord.x <= offset.x + size.width &&
|
||||
offset.y <= coord.y && coord.y <= offset.y + size.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called before the popup is shown.
|
||||
*
|
||||
* @return {boolean} Whether tooltip should be shown.
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.onBeforeShow = function() {
|
||||
if (!goog.ui.PopupBase.prototype.onBeforeShow.call(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide all open tooltips except if this tooltip is triggered by an element
|
||||
// inside another tooltip.
|
||||
if (this.anchor) {
|
||||
for (var tt, i = 0; tt = goog.ui.Tooltip.activeInstances_[i]; i++) {
|
||||
if (!goog.dom.contains(tt.getElement(), this.anchor)) {
|
||||
tt.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
goog.array.insert(goog.ui.Tooltip.activeInstances_, this);
|
||||
|
||||
var element = this.getElement();
|
||||
element.className = this.className;
|
||||
this.clearHideTimer();
|
||||
|
||||
// Register event handlers for tooltip. Used to prevent the tooltip from
|
||||
// closing if the cursor is over the tooltip rather then the element that
|
||||
// triggered it.
|
||||
goog.events.listen(element, goog.events.EventType.MOUSEOVER,
|
||||
this.handleTooltipMouseOver, false, this);
|
||||
goog.events.listen(element, goog.events.EventType.MOUSEOUT,
|
||||
this.handleTooltipMouseOut, false, this);
|
||||
|
||||
this.clearShowTimer();
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called after the popup is hidden.
|
||||
*
|
||||
* @protected
|
||||
* @suppress {underscore}
|
||||
* @override
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.onHide_ = function() {
|
||||
goog.array.remove(goog.ui.Tooltip.activeInstances_, this);
|
||||
|
||||
// Hide all open tooltips triggered by an element inside this tooltip.
|
||||
var element = this.getElement();
|
||||
for (var tt, i = 0; tt = goog.ui.Tooltip.activeInstances_[i]; i++) {
|
||||
if (tt.anchor && goog.dom.contains(element, tt.anchor)) {
|
||||
tt.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
// If this tooltip is inside another tooltip, start hide timer for that
|
||||
// tooltip in case this tooltip was the only reason it was still showing.
|
||||
if (this.parentTooltip_) {
|
||||
this.parentTooltip_.startHideTimer();
|
||||
}
|
||||
|
||||
goog.events.unlisten(element, goog.events.EventType.MOUSEOVER,
|
||||
this.handleTooltipMouseOver, false, this);
|
||||
goog.events.unlisten(element, goog.events.EventType.MOUSEOUT,
|
||||
this.handleTooltipMouseOut, false, this);
|
||||
|
||||
this.anchor = undefined;
|
||||
// If we are still waiting to show a different hovercard, don't abort it
|
||||
// because you think you haven't seen a mouse move:
|
||||
if (this.getState() == goog.ui.Tooltip.State.INACTIVE) {
|
||||
this.seenInteraction_ = false;
|
||||
}
|
||||
|
||||
goog.ui.PopupBase.prototype.onHide_.call(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called by timer from mouse over handler. Shows tooltip if cursor is still
|
||||
* over the same element.
|
||||
*
|
||||
* @param {Element} el Element to show tooltip for.
|
||||
* @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
|
||||
* at.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.maybeShow = function(el, opt_pos) {
|
||||
// Assert that the mouse is still over the same element, and that we have not
|
||||
// detached from the anchor in the meantime.
|
||||
if (this.anchor == el && this.elements_.contains(this.anchor)) {
|
||||
if (this.seenInteraction_ || !this.requireInteraction_) {
|
||||
// If it is currently showing, then hide it, and abort if it doesn't hide.
|
||||
this.setVisible(false);
|
||||
if (!this.isVisible()) {
|
||||
this.positionAndShow_(el, opt_pos);
|
||||
}
|
||||
} else {
|
||||
this.anchor = undefined;
|
||||
}
|
||||
}
|
||||
this.showTimer = undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.structs.Set} Elements this widget is attached to.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getElements = function() {
|
||||
return this.elements_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} Active element reference.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getActiveElement = function() {
|
||||
return this.activeEl_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} activeEl Active element reference.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.setActiveElement = function(activeEl) {
|
||||
this.activeEl_ = activeEl;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows tooltip for a specific element.
|
||||
*
|
||||
* @param {Element} el Element to show tooltip for.
|
||||
* @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
|
||||
* at.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.showForElement = function(el, opt_pos) {
|
||||
this.attach(el);
|
||||
this.activeEl_ = el;
|
||||
|
||||
this.positionAndShow_(el, opt_pos);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets tooltip position and shows it.
|
||||
*
|
||||
* @param {Element} el Element to show tooltip for.
|
||||
* @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
|
||||
* at.
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.positionAndShow_ = function(el, opt_pos) {
|
||||
this.anchor = el;
|
||||
this.setPosition(opt_pos ||
|
||||
this.getPositioningStrategy(goog.ui.Tooltip.Activation.CURSOR));
|
||||
this.setVisible(true);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called by timer from mouse out handler. Hides tooltip if cursor is still
|
||||
* outside element and tooltip, or if a child of tooltip has the focus.
|
||||
* @param {Element} el Tooltip's anchor when hide timer was started.
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.maybeHide = function(el) {
|
||||
this.hideTimer = undefined;
|
||||
if (el == this.anchor) {
|
||||
if ((this.activeEl_ == null || (this.activeEl_ != this.getElement() &&
|
||||
!this.elements_.contains(this.activeEl_))) &&
|
||||
!this.hasActiveChild()) {
|
||||
this.setVisible(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether tooltip element contains an active child tooltip,
|
||||
* and should thus not be hidden. When the child tooltip is hidden, it
|
||||
* will check if the parent should be hidden, too.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.hasActiveChild = function() {
|
||||
return !!(this.childTooltip_ && this.childTooltip_.activeEl_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Saves the current mouse cursor position to {@code this.cursorPosition}.
|
||||
* @param {goog.events.BrowserEvent} event MOUSEOVER or MOUSEMOVE event.
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.saveCursorPosition_ = function(event) {
|
||||
var scroll = this.dom_.getDocumentScroll();
|
||||
this.cursorPosition.x = event.clientX + scroll.x;
|
||||
this.cursorPosition.y = event.clientY + scroll.y;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for mouse over events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} event Event object.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.handleMouseOver = function(event) {
|
||||
var el = this.getAnchorFromElement(/** @type {Element} */ (event.target));
|
||||
this.activeEl_ = /** @type {Element} */ (el);
|
||||
this.clearHideTimer();
|
||||
if (el != this.anchor) {
|
||||
this.anchor = el;
|
||||
this.startShowTimer(/** @type {Element} */ (el));
|
||||
this.checkForParentTooltip_();
|
||||
this.saveCursorPosition_(event);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Find anchor containing the given element, if any.
|
||||
*
|
||||
* @param {Element} el Element that triggered event.
|
||||
* @return {Element} Element in elements_ array that contains given element,
|
||||
* or null if not found.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getAnchorFromElement = function(el) {
|
||||
// FireFox has a bug where mouse events relating to <input> elements are
|
||||
// sometimes duplicated (often in FF2, rarely in FF3): once for the
|
||||
// <input> element and once for a magic hidden <div> element. Javascript
|
||||
// code does not have sufficient permissions to read properties on that
|
||||
// magic element and thus will throw an error in this call to
|
||||
// getAnchorFromElement_(). In that case we swallow the error.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=330961
|
||||
try {
|
||||
while (el && !this.elements_.contains(el)) {
|
||||
el = /** @type {Element} */ (el.parentNode);
|
||||
}
|
||||
return el;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for mouse move events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} event MOUSEMOVE event.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.handleMouseMove = function(event) {
|
||||
this.saveCursorPosition_(event);
|
||||
this.seenInteraction_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for focus events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} event Event object.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.handleFocus = function(event) {
|
||||
var el = this.getAnchorFromElement(/** @type {Element} */ (event.target));
|
||||
this.activeEl_ = el;
|
||||
this.seenInteraction_ = true;
|
||||
|
||||
if (this.anchor != el) {
|
||||
this.anchor = el;
|
||||
var pos = this.getPositioningStrategy(goog.ui.Tooltip.Activation.FOCUS);
|
||||
this.clearHideTimer();
|
||||
this.startShowTimer(/** @type {Element} */ (el), pos);
|
||||
|
||||
this.checkForParentTooltip_();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return a Position instance for repositioning the tooltip. Override in
|
||||
* subclasses to customize the way repositioning is done.
|
||||
*
|
||||
* @param {goog.ui.Tooltip.Activation} activationType Information about what
|
||||
* kind of event caused the popup to be shown.
|
||||
* @return {!goog.positioning.AbstractPosition} The position object used
|
||||
* to position the tooltip.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.getPositioningStrategy = function(activationType) {
|
||||
if (activationType == goog.ui.Tooltip.Activation.CURSOR) {
|
||||
var coord = this.cursorPosition.clone();
|
||||
return new goog.ui.Tooltip.CursorTooltipPosition(coord);
|
||||
}
|
||||
return new goog.ui.Tooltip.ElementTooltipPosition(this.activeEl_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Looks for an active tooltip whose element contains this tooltip's anchor.
|
||||
* This allows us to prevent hides until they are really necessary.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.checkForParentTooltip_ = function() {
|
||||
if (this.anchor) {
|
||||
for (var tt, i = 0; tt = goog.ui.Tooltip.activeInstances_[i]; i++) {
|
||||
if (goog.dom.contains(tt.getElement(), this.anchor)) {
|
||||
tt.childTooltip_ = this;
|
||||
this.parentTooltip_ = tt;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for mouse out and blur events.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} event Event object.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.handleMouseOutAndBlur = function(event) {
|
||||
var el = this.getAnchorFromElement(/** @type {Element} */ (event.target));
|
||||
var elTo = this.getAnchorFromElement(
|
||||
/** @type {Element} */ (event.relatedTarget));
|
||||
if (el == elTo) {
|
||||
// We haven't really left the anchor, just moved from one child to
|
||||
// another.
|
||||
return;
|
||||
}
|
||||
|
||||
if (el == this.activeEl_) {
|
||||
this.activeEl_ = null;
|
||||
}
|
||||
|
||||
this.clearShowTimer();
|
||||
this.seenInteraction_ = false;
|
||||
if (this.isVisible() && (!event.relatedTarget ||
|
||||
!goog.dom.contains(this.getElement(), event.relatedTarget))) {
|
||||
this.startHideTimer();
|
||||
} else {
|
||||
this.anchor = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for mouse over events for the tooltip element.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} event Event object.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.handleTooltipMouseOver = function(event) {
|
||||
var element = this.getElement();
|
||||
if (this.activeEl_ != element) {
|
||||
this.clearHideTimer();
|
||||
this.activeEl_ = element;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for mouse out events for the tooltip element.
|
||||
*
|
||||
* @param {goog.events.BrowserEvent} event Event object.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.handleTooltipMouseOut = function(event) {
|
||||
var element = this.getElement();
|
||||
if (this.activeEl_ == element && (!event.relatedTarget ||
|
||||
!goog.dom.contains(element, event.relatedTarget))) {
|
||||
this.activeEl_ = null;
|
||||
this.startHideTimer();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper method, starts timer that calls maybeShow. Parameters are passed to
|
||||
* the maybeShow method.
|
||||
*
|
||||
* @param {Element} el Element to show tooltip for.
|
||||
* @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
|
||||
* at.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.startShowTimer = function(el, opt_pos) {
|
||||
if (!this.showTimer) {
|
||||
this.showTimer = goog.Timer.callOnce(
|
||||
goog.bind(this.maybeShow, this, el, opt_pos), this.showDelayMs_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper method called to clear the show timer.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.clearShowTimer = function() {
|
||||
if (this.showTimer) {
|
||||
goog.Timer.clear(this.showTimer);
|
||||
this.showTimer = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper method called to start the close timer.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.startHideTimer = function() {
|
||||
if (this.getState() == goog.ui.Tooltip.State.SHOWING) {
|
||||
this.hideTimer = goog.Timer.callOnce(
|
||||
goog.bind(this.maybeHide, this, this.anchor), this.getHideDelayMs());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper method called to clear the close timer.
|
||||
* @protected
|
||||
*/
|
||||
goog.ui.Tooltip.prototype.clearHideTimer = function() {
|
||||
if (this.hideTimer) {
|
||||
goog.Timer.clear(this.hideTimer);
|
||||
this.hideTimer = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.ui.Tooltip.prototype.disposeInternal = function() {
|
||||
this.setVisible(false);
|
||||
this.clearShowTimer();
|
||||
this.detach();
|
||||
if (this.getElement()) {
|
||||
goog.dom.removeNode(this.getElement());
|
||||
}
|
||||
this.activeEl_ = null;
|
||||
delete this.dom_;
|
||||
goog.ui.Tooltip.superClass_.disposeInternal.call(this);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Popup position implementation that positions the popup (the tooltip in this
|
||||
* case) based on the cursor position. It's positioned below the cursor to the
|
||||
* right if there's enough room to fit all of it inside the Viewport. Otherwise
|
||||
* it's displayed as far right as possible either above or below the element.
|
||||
*
|
||||
* Used to position tooltips triggered by the cursor.
|
||||
*
|
||||
* @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
|
||||
* @param {number=} opt_arg2 Top position.
|
||||
* @constructor
|
||||
* @extends {goog.positioning.ViewportPosition}
|
||||
*/
|
||||
goog.ui.Tooltip.CursorTooltipPosition = function(arg1, opt_arg2) {
|
||||
goog.positioning.ViewportPosition.call(this, arg1, opt_arg2);
|
||||
};
|
||||
goog.inherits(goog.ui.Tooltip.CursorTooltipPosition,
|
||||
goog.positioning.ViewportPosition);
|
||||
|
||||
|
||||
/**
|
||||
* Repositions the popup based on cursor position.
|
||||
*
|
||||
* @param {Element} element The DOM element of the popup.
|
||||
* @param {goog.positioning.Corner} popupCorner The corner of the popup element
|
||||
* that that should be positioned adjacent to the anchorElement.
|
||||
* @param {goog.math.Box=} opt_margin A margin specified in pixels.
|
||||
* @override
|
||||
*/
|
||||
goog.ui.Tooltip.CursorTooltipPosition.prototype.reposition = function(
|
||||
element, popupCorner, opt_margin) {
|
||||
var viewportElt = goog.style.getClientViewportElement(element);
|
||||
var viewport = goog.style.getVisibleRectForElement(viewportElt);
|
||||
var margin = opt_margin ? new goog.math.Box(opt_margin.top + 10,
|
||||
opt_margin.right, opt_margin.bottom, opt_margin.left + 10) :
|
||||
new goog.math.Box(10, 0, 0, 10);
|
||||
|
||||
if (goog.positioning.positionAtCoordinate(this.coordinate, element,
|
||||
goog.positioning.Corner.TOP_START, margin, viewport,
|
||||
goog.positioning.Overflow.ADJUST_X | goog.positioning.Overflow.FAIL_Y
|
||||
) & goog.positioning.OverflowStatus.FAILED) {
|
||||
goog.positioning.positionAtCoordinate(this.coordinate, element,
|
||||
goog.positioning.Corner.TOP_START, margin, viewport,
|
||||
goog.positioning.Overflow.ADJUST_X |
|
||||
goog.positioning.Overflow.ADJUST_Y);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Popup position implementation that positions the popup (the tooltip in this
|
||||
* case) based on the element position. It's positioned below the element to the
|
||||
* right if there's enough room to fit all of it inside the Viewport. Otherwise
|
||||
* it's displayed as far right as possible either above or below the element.
|
||||
*
|
||||
* Used to position tooltips triggered by focus changes.
|
||||
*
|
||||
* @param {Element} element The element to anchor the popup at.
|
||||
* @constructor
|
||||
* @extends {goog.positioning.AnchoredPosition}
|
||||
*/
|
||||
goog.ui.Tooltip.ElementTooltipPosition = function(element) {
|
||||
goog.positioning.AnchoredPosition.call(this, element,
|
||||
goog.positioning.Corner.BOTTOM_RIGHT);
|
||||
};
|
||||
goog.inherits(goog.ui.Tooltip.ElementTooltipPosition,
|
||||
goog.positioning.AnchoredPosition);
|
||||
|
||||
|
||||
/**
|
||||
* Repositions the popup based on element position.
|
||||
*
|
||||
* @param {Element} element The DOM element of the popup.
|
||||
* @param {goog.positioning.Corner} popupCorner The corner of the popup element
|
||||
* that should be positioned adjacent to the anchorElement.
|
||||
* @param {goog.math.Box=} opt_margin A margin specified in pixels.
|
||||
* @override
|
||||
*/
|
||||
goog.ui.Tooltip.ElementTooltipPosition.prototype.reposition = function(
|
||||
element, popupCorner, opt_margin) {
|
||||
var offset = new goog.math.Coordinate(10, 0);
|
||||
|
||||
if (goog.positioning.positionAtAnchor(this.element, this.corner, element,
|
||||
popupCorner, offset, opt_margin,
|
||||
goog.positioning.Overflow.ADJUST_X | goog.positioning.Overflow.FAIL_Y
|
||||
) & goog.positioning.OverflowStatus.FAILED) {
|
||||
goog.positioning.positionAtAnchor(this.element,
|
||||
goog.positioning.Corner.TOP_RIGHT, element,
|
||||
goog.positioning.Corner.BOTTOM_LEFT, offset, opt_margin,
|
||||
goog.positioning.Overflow.ADJUST_X |
|
||||
goog.positioning.Overflow.ADJUST_Y);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user