Changeset View
Standalone View
webroot/rsrc/js/core/ToolTip.js
Show All 25 Lines | show : function(root, scale, align, content) { | ||||
"and 'W' (west) are supported." | "and 'W' (west) are supported." | ||||
); | ); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
var node = JX.$N( | var node = JX.$N( | ||||
'div', | 'div', | ||||
{ className: 'jx-tooltip-container jx-tooltip-align-' + align }, | { className: 'jx-tooltip-container' }, | ||||
[ | [ | ||||
JX.$N('div', { className: 'jx-tooltip' }, content), | JX.$N('div', { className: 'jx-tooltip' }, content), | ||||
JX.$N('div', { className: 'jx-tooltip-anchor' }) | JX.$N('div', { className: 'jx-tooltip-anchor' }) | ||||
]); | ]); | ||||
node.style.maxWidth = scale + 'px'; | node.style.maxWidth = scale + 'px'; | ||||
JX.Tooltip.hide(); | JX.Tooltip.hide(); | ||||
this._node = node; | this._node = node; | ||||
// Append the tip to the document, but offscreen, so we can measure it. | // Append the tip to the document, but offscreen, so we can measure it. | ||||
node.style.left = '-10000px'; | node.style.left = '-10000px'; | ||||
document.body.appendChild(node); | document.body.appendChild(node); | ||||
// Jump through some hoops trying to auto-position the tooltip | |||||
var pos = this._getSmartPosition(align, root, node); | |||||
pos.setPos(node); | |||||
}, | |||||
epriestley: Since `a` is a `JX.Vector`, you can simplify this slightly:
a.setPos(node);
Also, consider… | |||||
_getSmartPosition: function (align, root, node) { | |||||
var pos = JX.Tooltip._proposePosition(align, root, node); | |||||
Not Done Inline ActionsSince this method isn't meant to be called from outside of JX.Tooltip, preface the method name with an underscore: _getPosition epriestley: Since this method isn't meant to be called from outside of `JX.Tooltip`, preface the method… | |||||
// If toolip is offscreen, try to be clever | |||||
if (!JX.Tooltip.isOnScreen(pos, node)) { | |||||
align = JX.Tooltip._getImprovedOrientation(pos, node); | |||||
pos = JX.Tooltip._proposePosition(align, root, node); | |||||
Not Done Inline ActionsWe should underscore-prefix these too. epriestley: We should underscore-prefix these too. | |||||
} | |||||
Not Done Inline ActionsThis looks like debugging code. epriestley: This looks like debugging code. | |||||
JX.Tooltip._setAnchor(align); | |||||
return pos; | |||||
}, | |||||
_proposePosition: function (align, root, node) { | |||||
var p = JX.$V(root); | var p = JX.$V(root); | ||||
var d = JX.Vector.getDim(root); | var d = JX.Vector.getDim(root); | ||||
var n = JX.Vector.getDim(node); | var n = JX.Vector.getDim(node); | ||||
var l = 0; | |||||
var t = 0; | |||||
// Move the tip so it's nicely aligned. | // Caculate the tip so it's nicely aligned. | ||||
switch (align) { | switch (align) { | ||||
case 'N': | case 'N': | ||||
node.style.left = parseInt(p.x - ((n.x - d.x) / 2), 10) + 'px'; | l = parseInt(p.x - ((n.x - d.x) / 2), 10); | ||||
node.style.top = parseInt(p.y - n.y, 10) + 'px'; | t = parseInt(p.y - n.y, 10); | ||||
break; | break; | ||||
case 'E': | case 'E': | ||||
node.style.left = parseInt(p.x + d.x, 10) + 'px'; | l = parseInt(p.x + d.x, 10); | ||||
node.style.top = parseInt(p.y - ((n.y - d.y) / 2), 10) + 'px'; | t = parseInt(p.y - ((n.y - d.y) / 2), 10); | ||||
break; | break; | ||||
case 'S': | case 'S': | ||||
node.style.left = parseInt(p.x - ((n.x - d.x) / 2), 10) + 'px'; | l = parseInt(p.x - ((n.x - d.x) / 2), 10); | ||||
node.style.top = parseInt(p.y + d.y + 5, 10) + 'px'; | t = parseInt(p.y + d.y + 5, 10); | ||||
Not Done Inline Actions(Leftover debugging code.) epriestley: (Leftover debugging code.) | |||||
break; | break; | ||||
case 'W': | case 'W': | ||||
node.style.left = parseInt(p.x - n.x - 5, 10) + 'px'; | l = parseInt(p.x - n.x - 5, 10); | ||||
node.style.top = parseInt(p.y - ((n.y - d.y) / 2), 10) + 'px'; | t = parseInt(p.y - ((n.y - d.y) / 2), 10); | ||||
break; | break; | ||||
} | } | ||||
return new JX.Vector(l, t); | |||||
}, | |||||
isOnScreen: function (a, node) { | |||||
Not Done Inline ActionsI don't think this is worth adjusting since no one will ever hit it (at least, we can wait for someone to complain), but since we're only looking at one position (the top left corner of the tip), this could give us the wrong result for some tips. Fore example, if if the thing being tipped is near the bottom of the screen and the tip has "S" alignment, the top left corner of the tip might be visible, but most of the tip text might not be. If we wanted to be perfect here, we could check that all four corners of the tip are on screen. epriestley: I don't think this is worth adjusting since no one will ever hit it (at least, we can wait for… | |||||
var s = JX.Vector.getScroll(); | |||||
var v = JX.Vector.getViewport(); | |||||
var max_x = s.x + v.x; | |||||
Not Done Inline ActionsThis will always be true unless a.y == s.y and a.x == s.x, so I think something is off here. epriestley: This will always be true unless `a.y == s.y` and `a.x == s.x`, so I think something is off here. | |||||
var max_y = s.y + v.y; | |||||
var corners = this._getNodeCornerPositions(a, node); | |||||
Not Done Inline ActionsBy convention, prefer to name local variables in lowercase_with_underscores. See the style guide. epriestley: By convention, prefer to name local variables in `lowercase_with_underscores`. See the [[ https… | |||||
// Check if any of the corners are offscreen | |||||
for (var i = 0; i < corners.length; i++) { | |||||
var corner = corners[i]; | |||||
if (corner.x < s.x || | |||||
corner.y < s.y || | |||||
corner.x > max_x || | |||||
corner.y > max_y) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
}, | |||||
_getImprovedOrientation: function (a, node) { | |||||
// Try to predict the "more correct" orientation | |||||
var s = JX.Vector.getScroll(); | |||||
var v = JX.Vector.getViewport(); | |||||
var max_x = s.x + v.x; | |||||
var max_y = s.y + v.y; | |||||
var corners = this._getNodeCornerPositions(a, node); | |||||
for (var i = 0; i < corners.length; i++) { | |||||
var corner = corners[i]; | |||||
if (corner.y < v.y) { | |||||
return 'S'; | |||||
} else | |||||
if (corner.x < v.x) { | |||||
return 'E'; | |||||
} else | |||||
if (corner.y > max_y) { | |||||
return 'N'; | |||||
} else | |||||
if (corner.x > max_x) { | |||||
return 'W'; | |||||
} else { | |||||
return 'N'; | |||||
} | |||||
} | |||||
}, | |||||
_getNodeCornerPositions: function(pos, node) { | |||||
// Get positions of all four corners of a node | |||||
var n = JX.Vector.getDim(node); | |||||
return [new JX.Vector(pos.x, pos.y), | |||||
new JX.Vector(pos.x + n.x, pos.y), | |||||
new JX.Vector(pos.x, pos.y + n.y), | |||||
new JX.Vector(pos.x + n.x, pos.y + n.y)]; | |||||
}, | |||||
_setAnchor: function (align) { | |||||
// Orient the little tail | |||||
JX.DOM.alterClass(this._node, 'jx-tooltip-align-' + align, true); | |||||
}, | }, | ||||
hide : function() { | hide : function() { | ||||
if (this._node) { | if (this._node) { | ||||
JX.DOM.remove(this._node); | JX.DOM.remove(this._node); | ||||
this._node = null; | this._node = null; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}); | }); |
Since a is a JX.Vector, you can simplify this slightly:
Also, consider a more meaningful name for the variable a.