You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
610 lines
21 KiB
610 lines
21 KiB
define([ |
|
"dojo/_base/array", // array.forEach array.indexOf array.map |
|
"dojo/_base/declare", // declare |
|
"dojo/_base/fx", // fx.fadeIn fx.fadeOut |
|
"dojo/dom", // dom.byId |
|
"dojo/dom-class", // domClass.add |
|
"dojo/dom-geometry", // domGeometry.position |
|
"dojo/dom-style", // domStyle.set, domStyle.get |
|
"dojo/_base/lang", // lang.hitch lang.isArrayLike |
|
"dojo/mouse", |
|
"dojo/on", |
|
"dojo/sniff", // has("ie"), has("trident") |
|
"./_base/manager", // manager.defaultDuration |
|
"./place", |
|
"./_Widget", |
|
"./_TemplatedMixin", |
|
"./BackgroundIframe", |
|
"dojo/text!./templates/Tooltip.html", |
|
"./main" // sets dijit.showTooltip etc. for back-compat |
|
], function(array, declare, fx, dom, domClass, domGeometry, domStyle, lang, mouse, on, has, |
|
manager, place, _Widget, _TemplatedMixin, BackgroundIframe, template, dijit){ |
|
|
|
// module: |
|
// dijit/Tooltip |
|
|
|
|
|
// TODO: Tooltip should really share more positioning code with TooltipDialog, like: |
|
// - the orient() method |
|
// - the connector positioning code in show() |
|
// - the dijitTooltip[Dialog] class |
|
// |
|
// The problem is that Tooltip's implementation supplies it's own <iframe> and interacts directly |
|
// with dijit/place, rather than going through dijit/popup like TooltipDialog and other popups (ex: Menu). |
|
|
|
var MasterTooltip = declare("dijit._MasterTooltip", [_Widget, _TemplatedMixin], { |
|
// summary: |
|
// Internal widget that holds the actual tooltip markup, |
|
// which occurs once per page. |
|
// Called by Tooltip widgets which are just containers to hold |
|
// the markup |
|
// tags: |
|
// protected |
|
|
|
// duration: Integer |
|
// Milliseconds to fade in/fade out |
|
duration: manager.defaultDuration, |
|
|
|
templateString: template, |
|
|
|
postCreate: function(){ |
|
this.ownerDocumentBody.appendChild(this.domNode); |
|
|
|
this.bgIframe = new BackgroundIframe(this.domNode); |
|
|
|
// Setup fade-in and fade-out functions. |
|
this.fadeIn = fx.fadeIn({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onShow") }); |
|
this.fadeOut = fx.fadeOut({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onHide") }); |
|
}, |
|
|
|
show: function(innerHTML, aroundNode, position, rtl, textDir, onMouseEnter, onMouseLeave){ |
|
// summary: |
|
// Display tooltip w/specified contents to right of specified node |
|
// (To left if there's no space on the right, or if rtl == true) |
|
// innerHTML: String |
|
// Contents of the tooltip |
|
// aroundNode: DomNode|dijit/place.__Rectangle |
|
// Specifies that tooltip should be next to this node / area |
|
// position: String[]? |
|
// List of positions to try to position tooltip (ex: ["right", "above"]) |
|
// rtl: Boolean? |
|
// Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true |
|
// means "rtl"; specifies GUI direction, not text direction. |
|
// textDir: String? |
|
// Corresponds to `WidgetBase.textdir` attribute; specifies direction of text. |
|
// onMouseEnter: Function? |
|
// Callback function for mouse enter on tooltip |
|
// onMouseLeave: Function? |
|
// Callback function for mouse leave on tooltip |
|
|
|
if(this.aroundNode && this.aroundNode === aroundNode && this.containerNode.innerHTML == innerHTML){ |
|
return; |
|
} |
|
|
|
if(this.fadeOut.status() == "playing"){ |
|
// previous tooltip is being hidden; wait until the hide completes then show new one |
|
this._onDeck=arguments; |
|
return; |
|
} |
|
this.containerNode.innerHTML=innerHTML; |
|
|
|
if(textDir){ |
|
this.set("textDir", textDir); |
|
} |
|
|
|
this.containerNode.align = rtl? "right" : "left"; //fix the text alignment |
|
|
|
var pos = place.around(this.domNode, aroundNode, |
|
position && position.length ? position : Tooltip.defaultPosition, !rtl, lang.hitch(this, "orient")); |
|
|
|
// Position the tooltip connector for middle alignment. |
|
// This could not have been done in orient() since the tooltip wasn't positioned at that time. |
|
var aroundNodeCoords = pos.aroundNodePos; |
|
if(pos.corner.charAt(0) == 'M' && pos.aroundCorner.charAt(0) == 'M'){ |
|
this.connectorNode.style.top = aroundNodeCoords.y + ((aroundNodeCoords.h - this.connectorNode.offsetHeight) >> 1) - pos.y + "px"; |
|
this.connectorNode.style.left = ""; |
|
}else if(pos.corner.charAt(1) == 'M' && pos.aroundCorner.charAt(1) == 'M'){ |
|
this.connectorNode.style.left = aroundNodeCoords.x + ((aroundNodeCoords.w - this.connectorNode.offsetWidth) >> 1) - pos.x + "px"; |
|
}else{ |
|
// Not *-centered, but just above/below/after/before |
|
this.connectorNode.style.left = ""; |
|
this.connectorNode.style.top = ""; |
|
} |
|
|
|
// show it |
|
domStyle.set(this.domNode, "opacity", 0); |
|
this.fadeIn.play(); |
|
this.isShowingNow = true; |
|
this.aroundNode = aroundNode; |
|
|
|
this.onMouseEnter = onMouseEnter || noop; |
|
this.onMouseLeave = onMouseLeave || noop; |
|
}, |
|
|
|
orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ tooltipCorner, /*Object*/ spaceAvailable, /*Object*/ aroundNodeCoords){ |
|
// summary: |
|
// Private function to set CSS for tooltip node based on which position it's in. |
|
// This is called by the dijit popup code. It will also reduce the tooltip's |
|
// width to whatever width is available |
|
// tags: |
|
// protected |
|
|
|
this.connectorNode.style.top = ""; //reset to default |
|
|
|
var heightAvailable = spaceAvailable.h, |
|
widthAvailable = spaceAvailable.w; |
|
|
|
node.className = "dijitTooltip " + |
|
{ |
|
"MR-ML": "dijitTooltipRight", |
|
"ML-MR": "dijitTooltipLeft", |
|
"TM-BM": "dijitTooltipAbove", |
|
"BM-TM": "dijitTooltipBelow", |
|
"BL-TL": "dijitTooltipBelow dijitTooltipABLeft", |
|
"TL-BL": "dijitTooltipAbove dijitTooltipABLeft", |
|
"BR-TR": "dijitTooltipBelow dijitTooltipABRight", |
|
"TR-BR": "dijitTooltipAbove dijitTooltipABRight", |
|
"BR-BL": "dijitTooltipRight", |
|
"BL-BR": "dijitTooltipLeft" |
|
}[aroundCorner + "-" + tooltipCorner]; |
|
|
|
// reset width; it may have been set by orient() on a previous tooltip show() |
|
this.domNode.style.width = "auto"; |
|
|
|
// Reduce tooltip's width to the amount of width available, so that it doesn't overflow screen. |
|
// Note that sometimes widthAvailable is negative, but we guard against setting style.width to a |
|
// negative number since that causes an exception on IE. |
|
var size = domGeometry.position(this.domNode); |
|
if(has("ie") || has("trident")){ |
|
// workaround strange IE bug where setting width to offsetWidth causes words to wrap |
|
size.w += 2; |
|
} |
|
|
|
var width = Math.min((Math.max(widthAvailable,1)), size.w); |
|
|
|
domGeometry.setMarginBox(this.domNode, {w: width}); |
|
|
|
// Reposition the tooltip connector. |
|
if(tooltipCorner.charAt(0) == 'B' && aroundCorner.charAt(0) == 'B'){ |
|
var bb = domGeometry.position(node); |
|
var tooltipConnectorHeight = this.connectorNode.offsetHeight; |
|
if(bb.h > heightAvailable){ |
|
// The tooltip starts at the top of the page and will extend past the aroundNode |
|
var aroundNodePlacement = heightAvailable - ((aroundNodeCoords.h + tooltipConnectorHeight) >> 1); |
|
this.connectorNode.style.top = aroundNodePlacement + "px"; |
|
this.connectorNode.style.bottom = ""; |
|
}else{ |
|
// Align center of connector with center of aroundNode, except don't let bottom |
|
// of connector extend below bottom of tooltip content, or top of connector |
|
// extend past top of tooltip content |
|
this.connectorNode.style.bottom = Math.min( |
|
Math.max(aroundNodeCoords.h/2 - tooltipConnectorHeight/2, 0), |
|
bb.h - tooltipConnectorHeight) + "px"; |
|
this.connectorNode.style.top = ""; |
|
} |
|
}else{ |
|
// reset the tooltip back to the defaults |
|
this.connectorNode.style.top = ""; |
|
this.connectorNode.style.bottom = ""; |
|
} |
|
|
|
return Math.max(0, size.w - widthAvailable); |
|
}, |
|
|
|
_onShow: function(){ |
|
// summary: |
|
// Called at end of fade-in operation |
|
// tags: |
|
// protected |
|
if(has("ie")){ |
|
// the arrow won't show up on a node w/an opacity filter |
|
this.domNode.style.filter=""; |
|
} |
|
}, |
|
|
|
hide: function(aroundNode){ |
|
// summary: |
|
// Hide the tooltip |
|
|
|
if(this._onDeck && this._onDeck[1] == aroundNode){ |
|
// this hide request is for a show() that hasn't even started yet; |
|
// just cancel the pending show() |
|
this._onDeck=null; |
|
}else if(this.aroundNode === aroundNode){ |
|
// this hide request is for the currently displayed tooltip |
|
this.fadeIn.stop(); |
|
this.isShowingNow = false; |
|
this.aroundNode = null; |
|
this.fadeOut.play(); |
|
}else{ |
|
// just ignore the call, it's for a tooltip that has already been erased |
|
} |
|
|
|
this.onMouseEnter = this.onMouseLeave = noop; |
|
}, |
|
|
|
_onHide: function(){ |
|
// summary: |
|
// Called at end of fade-out operation |
|
// tags: |
|
// protected |
|
|
|
this.domNode.style.cssText=""; // to position offscreen again |
|
this.containerNode.innerHTML=""; |
|
if(this._onDeck){ |
|
// a show request has been queued up; do it now |
|
this.show.apply(this, this._onDeck); |
|
this._onDeck=null; |
|
} |
|
} |
|
}); |
|
|
|
if(has("dojo-bidi")){ |
|
MasterTooltip.extend({ |
|
_setAutoTextDir: function(/*Object*/node){ |
|
// summary: |
|
// Resolve "auto" text direction for children nodes |
|
// tags: |
|
// private |
|
|
|
this.applyTextDir(node); |
|
array.forEach(node.children, function(child){ this._setAutoTextDir(child); }, this); |
|
}, |
|
|
|
_setTextDirAttr: function(/*String*/ textDir){ |
|
// summary: |
|
// Setter for textDir. |
|
// description: |
|
// Users shouldn't call this function; they should be calling |
|
// set('textDir', value) |
|
// tags: |
|
// private |
|
|
|
this._set("textDir", textDir); |
|
|
|
if (textDir == "auto"){ |
|
this._setAutoTextDir(this.containerNode); |
|
}else{ |
|
this.containerNode.dir = this.textDir; |
|
} |
|
} |
|
}); |
|
} |
|
|
|
dijit.showTooltip = function(innerHTML, aroundNode, position, rtl, textDir, onMouseEnter, onMouseLeave){ |
|
// summary: |
|
// Static method to display tooltip w/specified contents in specified position. |
|
// See description of dijit/Tooltip.defaultPosition for details on position parameter. |
|
// If position is not specified then dijit/Tooltip.defaultPosition is used. |
|
// innerHTML: String |
|
// Contents of the tooltip |
|
// aroundNode: place.__Rectangle |
|
// Specifies that tooltip should be next to this node / area |
|
// position: String[]? |
|
// List of positions to try to position tooltip (ex: ["right", "above"]) |
|
// rtl: Boolean? |
|
// Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true |
|
// means "rtl"; specifies GUI direction, not text direction. |
|
// textDir: String? |
|
// Corresponds to `WidgetBase.textdir` attribute; specifies direction of text. |
|
// onMouseEnter: Function? |
|
// Callback function for mouse over on tooltip |
|
// onMouseLeave: Function? |
|
// Callback function for mouse leave on tooltip |
|
|
|
// After/before don't work, but for back-compat convert them to the working after-centered, before-centered. |
|
// Possibly remove this in 2.0. Alternately, get before/after to work. |
|
if(position){ |
|
position = array.map(position, function(val){ |
|
return {after: "after-centered", before: "before-centered"}[val] || val; |
|
}); |
|
} |
|
|
|
if(!Tooltip._masterTT){ dijit._masterTT = Tooltip._masterTT = new MasterTooltip(); } |
|
return Tooltip._masterTT.show(innerHTML, aroundNode, position, rtl, textDir, onMouseEnter, onMouseLeave); |
|
}; |
|
|
|
dijit.hideTooltip = function(aroundNode){ |
|
// summary: |
|
// Static method to hide the tooltip displayed via showTooltip() |
|
return Tooltip._masterTT && Tooltip._masterTT.hide(aroundNode); |
|
}; |
|
|
|
// Possible states for a tooltip, see Tooltip.state property for definitions |
|
var DORMANT = "DORMANT", |
|
SHOW_TIMER = "SHOW TIMER", |
|
SHOWING = "SHOWING", |
|
HIDE_TIMER = "HIDE TIMER"; |
|
|
|
function noop(){} |
|
|
|
var Tooltip = declare("dijit.Tooltip", _Widget, { |
|
// summary: |
|
// Pops up a tooltip (a help message) when you hover over a node. |
|
// Also provides static show() and hide() methods that can be used without instantiating a dijit/Tooltip. |
|
|
|
// label: String |
|
// HTML to display in the tooltip. |
|
// Specified as innerHTML when creating the widget from markup. |
|
label: "", |
|
|
|
// showDelay: Integer |
|
// Number of milliseconds to wait after hovering over/focusing on the object, before |
|
// the tooltip is displayed. |
|
showDelay: 400, |
|
|
|
// hideDelay: Integer |
|
// Number of milliseconds to wait after unhovering the object, before |
|
// the tooltip is hidden. Note that blurring an object hides the tooltip immediately. |
|
hideDelay: 400, |
|
|
|
// connectId: String|String[]|DomNode|DomNode[] |
|
// Id of domNode(s) to attach the tooltip to. |
|
// When user hovers over specified dom node(s), the tooltip will appear. |
|
connectId: [], |
|
|
|
// position: String[] |
|
// See description of `dijit/Tooltip.defaultPosition` for details on position parameter. |
|
position: [], |
|
|
|
// selector: String? |
|
// CSS expression to apply this Tooltip to descendants of connectIds, rather than to |
|
// the nodes specified by connectIds themselves. Useful for applying a Tooltip to |
|
// a range of rows in a table, tree, etc. Use in conjunction with getContent() parameter. |
|
// Ex: connectId: myTable, selector: "tr", getContent: function(node){ return ...; } |
|
// |
|
// The application must require() an appropriate level of dojo/query to handle the selector. |
|
selector: "", |
|
|
|
// TODO: in 2.0 remove support for multiple connectIds. selector gives the same effect. |
|
// So, change connectId to a "", remove addTarget()/removeTarget(), etc. |
|
|
|
_setConnectIdAttr: function(/*String|String[]|DomNode|DomNode[]*/ newId){ |
|
// summary: |
|
// Connect to specified node(s) |
|
|
|
// Remove connections to old nodes (if there are any) |
|
array.forEach(this._connections || [], function(nested){ |
|
array.forEach(nested, function(handle){ handle.remove(); }); |
|
}, this); |
|
|
|
// Make array of id's to connect to, excluding entries for nodes that don't exist yet, see startup() |
|
this._connectIds = array.filter(lang.isArrayLike(newId) ? newId : (newId ? [newId] : []), |
|
function(id){ return dom.byId(id, this.ownerDocument); }, this); |
|
|
|
// Make connections |
|
this._connections = array.map(this._connectIds, function(id){ |
|
var node = dom.byId(id, this.ownerDocument), |
|
selector = this.selector, |
|
delegatedEvent = selector ? |
|
function(eventType){ return on.selector(selector, eventType); } : |
|
function(eventType){ return eventType; }, |
|
self = this; |
|
return [ |
|
on(node, delegatedEvent(mouse.enter), function(){ |
|
self._onHover(this); |
|
}), |
|
on(node, delegatedEvent("focusin"), function(){ |
|
self._onHover(this); |
|
}), |
|
on(node, delegatedEvent(mouse.leave), lang.hitch(self, "_onUnHover")), |
|
on(node, delegatedEvent("focusout"), lang.hitch(self, "set", "state", DORMANT)) |
|
]; |
|
}, this); |
|
|
|
this._set("connectId", newId); |
|
}, |
|
|
|
addTarget: function(/*DomNode|String*/ node){ |
|
// summary: |
|
// Attach tooltip to specified node if it's not already connected |
|
|
|
// TODO: remove in 2.0 and just use set("connectId", ...) interface |
|
|
|
var id = node.id || node; |
|
if(array.indexOf(this._connectIds, id) == -1){ |
|
this.set("connectId", this._connectIds.concat(id)); |
|
} |
|
}, |
|
|
|
removeTarget: function(/*DomNode|String*/ node){ |
|
// summary: |
|
// Detach tooltip from specified node |
|
|
|
// TODO: remove in 2.0 and just use set("connectId", ...) interface |
|
|
|
var id = node.id || node, // map from DOMNode back to plain id string |
|
idx = array.indexOf(this._connectIds, id); |
|
if(idx >= 0){ |
|
// remove id (modifies original this._connectIds but that's OK in this case) |
|
this._connectIds.splice(idx, 1); |
|
this.set("connectId", this._connectIds); |
|
} |
|
}, |
|
|
|
buildRendering: function(){ |
|
this.inherited(arguments); |
|
domClass.add(this.domNode,"dijitTooltipData"); |
|
}, |
|
|
|
startup: function(){ |
|
this.inherited(arguments); |
|
|
|
// If this tooltip was created in a template, or for some other reason the specified connectId[s] |
|
// didn't exist during the widget's initialization, then connect now. |
|
var ids = this.connectId; |
|
array.forEach(lang.isArrayLike(ids) ? ids : [ids], this.addTarget, this); |
|
}, |
|
|
|
getContent: function(/*DomNode*/ node){ |
|
// summary: |
|
// User overridable function that return the text to display in the tooltip. |
|
// tags: |
|
// extension |
|
return this.label || this.domNode.innerHTML; |
|
}, |
|
|
|
// state: [private readonly] String |
|
// One of: |
|
// |
|
// - DORMANT: tooltip not SHOWING |
|
// - SHOW TIMER: tooltip not SHOWING but timer set to show it |
|
// - SHOWING: tooltip displayed |
|
// - HIDE TIMER: tooltip displayed, but timer set to hide it |
|
state: DORMANT, |
|
_setStateAttr: function(val){ |
|
if(this.state == val || |
|
(val == SHOW_TIMER && this.state == SHOWING) || |
|
(val == HIDE_TIMER && this.state == DORMANT)){ |
|
return; |
|
} |
|
|
|
if(this._hideTimer){ |
|
this._hideTimer.remove(); |
|
delete this._hideTimer; |
|
} |
|
if(this._showTimer){ |
|
this._showTimer.remove(); |
|
delete this._showTimer; |
|
} |
|
|
|
switch(val){ |
|
case DORMANT: |
|
if(this._connectNode){ |
|
Tooltip.hide(this._connectNode); |
|
delete this._connectNode; |
|
this.onHide(); |
|
} |
|
break; |
|
case SHOW_TIMER: // set timer to show tooltip |
|
// should only get here from a DORMANT state, i.e. tooltip can't be already SHOWING |
|
if(this.state != SHOWING){ |
|
this._showTimer = this.defer(function(){ this.set("state", SHOWING); }, this.showDelay); |
|
} |
|
break; |
|
case SHOWING: // show tooltip and clear timers |
|
var content = this.getContent(this._connectNode); |
|
if(!content){ |
|
this.set("state", DORMANT); |
|
return; |
|
} |
|
|
|
// Show tooltip and setup callbacks for mouseenter/mouseleave of tooltip itself |
|
Tooltip.show(content, this._connectNode, this.position, !this.isLeftToRight(), this.textDir, |
|
lang.hitch(this, "set", "state", SHOWING), lang.hitch(this, "set", "state", HIDE_TIMER)); |
|
|
|
this.onShow(this._connectNode, this.position); |
|
break; |
|
case HIDE_TIMER: // set timer set to hide tooltip |
|
this._hideTimer = this.defer(function(){ this.set("state", DORMANT); }, this.hideDelay); |
|
break; |
|
} |
|
|
|
this._set("state", val); |
|
}, |
|
|
|
_onHover: function(/*DomNode*/ target){ |
|
// summary: |
|
// Despite the name of this method, it actually handles both hover and focus |
|
// events on the target node, setting a timer to show the tooltip. |
|
// tags: |
|
// private |
|
|
|
if(this._connectNode && target != this._connectNode){ |
|
// Tooltip is displaying for another node |
|
this.set("state", DORMANT); |
|
} |
|
this._connectNode = target; // _connectNode means "tooltip currently displayed for this node" |
|
|
|
this.set("state", SHOW_TIMER); // no-op if show-timer already set, or if already showing |
|
}, |
|
|
|
_onUnHover: function(/*DomNode*/ target){ |
|
// summary: |
|
// Handles mouseleave event on the target node, hiding the tooltip. |
|
// tags: |
|
// private |
|
|
|
this.set("state", HIDE_TIMER); // no-op if already dormant, or if hide-timer already set |
|
}, |
|
|
|
// open() and close() aren't used anymore, except from the _BidiSupport/misc/Tooltip test. |
|
// Should probably remove for 2.0, but leaving for now. |
|
open: function(/*DomNode*/ target){ |
|
// summary: |
|
// Display the tooltip; usually not called directly. |
|
// tags: |
|
// private |
|
|
|
this.set("state", DORMANT); |
|
this._connectNode = target; // _connectNode means "tooltip currently displayed for this node" |
|
this.set("state", SHOWING); |
|
}, |
|
|
|
close: function(){ |
|
// summary: |
|
// Hide the tooltip or cancel timer for show of tooltip |
|
// tags: |
|
// private |
|
|
|
this.set("state", DORMANT); |
|
}, |
|
|
|
onShow: function(/*===== target, position =====*/){ |
|
// summary: |
|
// Called when the tooltip is shown |
|
// tags: |
|
// callback |
|
}, |
|
|
|
onHide: function(){ |
|
// summary: |
|
// Called when the tooltip is hidden |
|
// tags: |
|
// callback |
|
}, |
|
|
|
destroy: function(){ |
|
this.set("state", DORMANT); |
|
|
|
// Remove connections manually since they aren't registered to be removed by _WidgetBase |
|
array.forEach(this._connections || [], function(nested){ |
|
array.forEach(nested, function(handle){ handle.remove(); }); |
|
}, this); |
|
|
|
this.inherited(arguments); |
|
} |
|
}); |
|
|
|
Tooltip._MasterTooltip = MasterTooltip; // for monkey patching |
|
Tooltip.show = dijit.showTooltip; // export function through module return value |
|
Tooltip.hide = dijit.hideTooltip; // export function through module return value |
|
|
|
Tooltip.defaultPosition = ["after-centered", "before-centered"]; |
|
|
|
/*===== |
|
lang.mixin(Tooltip, { |
|
// defaultPosition: String[] |
|
// This variable controls the position of tooltips, if the position is not specified to |
|
// the Tooltip widget or *TextBox widget itself. It's an array of strings with the values |
|
// possible for `dijit/place.around()`. The recommended values are: |
|
// |
|
// - before-centered: centers tooltip to the left of the anchor node/widget, or to the right |
|
// in the case of RTL scripts like Hebrew and Arabic |
|
// - after-centered: centers tooltip to the right of the anchor node/widget, or to the left |
|
// in the case of RTL scripts like Hebrew and Arabic |
|
// - above-centered: tooltip is centered above anchor node |
|
// - below-centered: tooltip is centered above anchor node |
|
// |
|
// The list is positions is tried, in order, until a position is found where the tooltip fits |
|
// within the viewport. |
|
// |
|
// Be careful setting this parameter. A value of "above-centered" may work fine until the user scrolls |
|
// the screen so that there's no room above the target node. Nodes with drop downs, like |
|
// DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure |
|
// that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there |
|
// is only room below (or above) the target node, but not both. |
|
}); |
|
=====*/ |
|
return Tooltip; |
|
});
|
|
|