UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

461 lines (370 loc) 12.3 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * Sebastian Werner (wpbasti) * Andreas Ecker (ecker) * Adrian Olaru (adrianolaru) ************************************************************************ */ /** * The tooltip manager globally manages the tooltips of all widgets. It will * display tooltips if the user hovers a widgets with a tooltip and hides all * other tooltips. */ qx.Class.define("qx.ui.tooltip.Manager", { type : "singleton", extend : qx.core.Object, /* ***************************************************************************** CONSTRUCTOR ***************************************************************************** */ construct : function() { this.base(arguments); // Register events qx.event.Registration.addListener(document.body, "pointerover", this.__onPointerOverRoot, this, true); // Instantiate timers this.__showTimer = new qx.event.Timer(); this.__showTimer.addListener("interval", this.__onShowInterval, this); this.__hideTimer = new qx.event.Timer(); this.__hideTimer.addListener("interval", this.__onHideInterval, this); // Init pointer position this.__pointerPosition = { left: 0, top: 0 }; }, /* ***************************************************************************** PROPERTIES ***************************************************************************** */ properties : { /** Holds the current ToolTip instance */ current : { check : "qx.ui.tooltip.ToolTip", nullable : true, apply : "_applyCurrent" }, /** Show all invalid form fields tooltips . */ showInvalidToolTips : { check : "Boolean", init : true }, /** Show all tooltips. */ showToolTips : { check : "Boolean", init : true } }, /* ***************************************************************************** MEMBERS ***************************************************************************** */ members : { __pointerPosition : null, __hideTimer : null, __showTimer : null, __sharedToolTip: null, __sharedErrorToolTip: null, /** * Get the shared tooltip, which is used to display the * {@link qx.ui.core.Widget#toolTipText} and * {@link qx.ui.core.Widget#toolTipIcon} properties of widgets. * You can use this public shared instance to e.g. customize the * look and feel. * * @return {qx.ui.tooltip.ToolTip} The shared tooltip */ getSharedTooltip : function() { if (!this.__sharedToolTip) { this.__sharedToolTip = new qx.ui.tooltip.ToolTip().set({ rich: true }); } return this.__sharedToolTip; }, /** * Get the shared tooltip, which is used to display the * {@link qx.ui.core.Widget#toolTipText} and * {@link qx.ui.core.Widget#toolTipIcon} properties of widgets. * You can use this public shared instance to e.g. customize the * look and feel of the validation tooltips like * <code>getSharedErrorTooltip().getChildControl("atom").getChildControl("label").set({rich: true, wrap: true, width: 80})</code> * * @return {qx.ui.tooltip.ToolTip} The shared tooltip */ getSharedErrorTooltip : function() { if (!this.__sharedErrorToolTip) { this.__sharedErrorToolTip = new qx.ui.tooltip.ToolTip().set({ appearance: "tooltip-error", rich: true }); this.__sharedErrorToolTip.setLabel(""); // trigger label widget creation this.__sharedErrorToolTip.syncAppearance(); } return this.__sharedErrorToolTip; }, /* --------------------------------------------------------------------------- PROPERTY APPLY ROUTINES --------------------------------------------------------------------------- */ // property apply _applyCurrent : function(value, old) { // Return if the new tooltip is a child of the old one if (old && qx.ui.core.Widget.contains(old, value)) { return; } // If old tooltip existing, hide it and clear widget binding if (old) { if (!old.isDisposed()) { old.exclude(); } this.__showTimer.stop(); this.__hideTimer.stop(); } var Registration = qx.event.Registration; var el = document.body; // If new tooltip is not null, set it up and start the timer if (value) { this.__showTimer.startWith(value.getShowTimeout()); // Register hide handler Registration.addListener(el, "pointerout", this.__onPointerOutRoot, this, true); Registration.addListener(el, "focusout", this.__onFocusOutRoot, this, true); Registration.addListener(el, "pointermove", this.__onPointerMoveRoot, this, true); } else { // Deregister hide handler Registration.removeListener(el, "pointerout", this.__onPointerOutRoot, this, true); Registration.removeListener(el, "focusout", this.__onFocusOutRoot, this, true); Registration.removeListener(el, "pointermove", this.__onPointerMoveRoot, this, true); } }, /* --------------------------------------------------------------------------- TIMER EVENT HANDLER --------------------------------------------------------------------------- */ /** * Event listener for the interval event of the show timer. * * @param e {qx.event.type.Event} Event object */ __onShowInterval : function(e) { var current = this.getCurrent(); if (current && !current.isDisposed()) { this.__hideTimer.startWith(current.getHideTimeout()); if (current.getPlaceMethod() == "widget") { current.placeToWidget(current.getOpener()); } else { current.placeToPoint(this.__pointerPosition); } current.show(); } this.__showTimer.stop(); }, /** * Event listener for the interval event of the hide timer. * * @param e {qx.event.type.Event} Event object */ __onHideInterval : function(e) { var current = this.getCurrent(); if(current && !current.getAutoHide()) { return; } if (current && !current.isDisposed()) { current.exclude(); } this.__hideTimer.stop(); this.resetCurrent(); }, /* --------------------------------------------------------------------------- POINTER EVENT HANDLER --------------------------------------------------------------------------- */ /** * Global pointer move event handler * * @param e {qx.event.type.Pointer} The move pointer event */ __onPointerMoveRoot : function(e) { var pos = this.__pointerPosition; pos.left = Math.round(e.getDocumentLeft()); pos.top = Math.round(e.getDocumentTop()); }, /** * Searches for the tooltip of the target widget. If any tooltip instance * is found this instance is bound to the target widget and the tooltip is * set as {@link #current} * * @param e {qx.event.type.Pointer} pointerover event */ __onPointerOverRoot : function(e) { var target = qx.ui.core.Widget.getWidgetByElement(e.getTarget()); // take first coordinates as backup if no move event will be fired (e.g. touch devices) this.__onPointerMoveRoot(e); this.showToolTip(target); }, /** * Explicitly show tooltip for particular form item. * * @param target {Object | null} widget to show tooltip for */ showToolTip : function(target) { if (!target){ return; } var tooltip, tooltipText, tooltipIcon, invalidMessage; // Search first parent which has a tooltip while (target != null) { tooltip = target.getToolTip(); tooltipText = target.getToolTipText() || null; tooltipIcon = target.getToolTipIcon() || null; if (qx.Class.hasInterface(target.constructor, qx.ui.form.IForm) && !target.isValid()) { invalidMessage = target.getInvalidMessage(); } if (tooltip || tooltipText || tooltipIcon || invalidMessage) { break; } target = target.getLayoutParent(); } //do nothing if if (!target //don't have a target // tooltip is disabled and the value of showToolTipWhenDisabled is false || (!target.getEnabled() && !target.isShowToolTipWhenDisabled() ) //tooltip is blocked || target.isBlockToolTip() //an invalid message isn't set and tooltips are disabled || (!invalidMessage && !this.getShowToolTips()) //an invalid message is set and invalid tooltips are disabled || (invalidMessage && !this.getShowInvalidToolTips())) { return; } if (invalidMessage) { tooltip = this.getSharedErrorTooltip().set({ label: invalidMessage }); } if (!tooltip) { tooltip = this.getSharedTooltip().set({ label: tooltipText, icon: tooltipIcon }); } this.setCurrent(tooltip); tooltip.setOpener(target); }, /** * Resets the property {@link #current} if there was a * tooltip and no new one is created. * * @param e {qx.event.type.Pointer} pointerout event */ __onPointerOutRoot : function(e) { var target = qx.ui.core.Widget.getWidgetByElement(e.getTarget()); if (!target) { return; } var related = qx.ui.core.Widget.getWidgetByElement(e.getRelatedTarget()); if (!related && e.getPointerType() == "mouse") { return; } var tooltip = this.getCurrent(); // If there was a tooltip and // - the destination target is the current tooltip // or // - the current tooltip contains the destination target if (tooltip && (related == tooltip || qx.ui.core.Widget.contains(tooltip, related))) { return; } // If the destination target exists and the target contains it if (related && target && qx.ui.core.Widget.contains(target, related)) { return; } if(tooltip && !tooltip.getAutoHide()) { return; } // If there was a tooltip and there is no new one if (tooltip && !related) { this.setCurrent(null); } else { this.resetCurrent(); } }, /* --------------------------------------------------------------------------- FOCUS EVENT HANDLER --------------------------------------------------------------------------- */ /** * Reset the property {@link #current} if the * current tooltip is the tooltip of the target widget. * * @param e {qx.event.type.Focus} blur event */ __onFocusOutRoot : function(e) { var target = qx.ui.core.Widget.getWidgetByElement(e.getTarget()); if (!target) { return; } var tooltip = this.getCurrent(); if(tooltip && !tooltip.getAutoHide()) { return; } // Only set to null if blurred widget is the // one which has created the current tooltip if (tooltip && tooltip == target.getToolTip()) { this.setCurrent(null); } } }, /* ***************************************************************************** DESTRUCTOR ***************************************************************************** */ destruct : function() { // Deregister events qx.event.Registration.removeListener(document.body, "pointerover", this.__onPointerOverRoot, this, true); // Dispose timers this._disposeObjects("__showTimer", "__hideTimer", "__sharedToolTip"); this.__pointerPosition = null; } });