1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Make JX.Tooltip more conservative about positioning

Summary:
Fixes T10687. Fixes T12064.

  - Primarily, adds a margin around the edge of the screen for the purposes of aligning the tooltip.
  - Also, tries to flip the tooltip if it can (e.g., if the tooltip normally goes east, try west first), then tries other positions exhastively.

Test Plan:
{F2309363}

{F2309364}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12064, T10687

Differential Revision: https://secure.phabricator.com/D17145
This commit is contained in:
epriestley 2017-01-05 08:49:47 -08:00
parent 1f2306999b
commit 5ff02058a4
2 changed files with 73 additions and 54 deletions

View file

@ -10,7 +10,7 @@ return array(
'conpherence.pkg.css' => '0b64e988',
'conpherence.pkg.js' => '6249a1cf',
'core.pkg.css' => '9c725fa0',
'core.pkg.js' => 'f998932d',
'core.pkg.js' => 'a2ead3fe',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => 'f69afb45',
'differential.pkg.js' => '40b18f35',
@ -489,7 +489,7 @@ return array(
'rsrc/js/core/ShapedRequest.js' => '7cbe244b',
'rsrc/js/core/TextAreaUtils.js' => '320810c8',
'rsrc/js/core/Title.js' => '485aaa6c',
'rsrc/js/core/ToolTip.js' => '6323f942',
'rsrc/js/core/ToolTip.js' => 'b5c62c3b',
'rsrc/js/core/behavior-active-nav.js' => 'e379b58e',
'rsrc/js/core/behavior-audio-source.js' => '59b251eb',
'rsrc/js/core/behavior-autofocus.js' => '7319e029',
@ -816,7 +816,7 @@ return array(
'phabricator-standard-page-view' => '894d8a25',
'phabricator-textareautils' => '320810c8',
'phabricator-title' => '485aaa6c',
'phabricator-tooltip' => '6323f942',
'phabricator-tooltip' => 'b5c62c3b',
'phabricator-ui-example-css' => '528b19de',
'phabricator-uiexample-javelin-view' => 'd4a14807',
'phabricator-uiexample-reactor-button' => 'd19198c8',
@ -1418,12 +1418,6 @@ return array(
'javelin-install',
'javelin-util',
),
'6323f942' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-vector',
),
'635de1ec' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1903,6 +1897,12 @@ return array(
'javelin-install',
'javelin-dom',
),
'b5c62c3b' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-vector',
),
'b5d57730' => array(
'javelin-install',
'javelin-stratcom',

View file

@ -65,15 +65,48 @@ JX.install('Tooltip', {
_getSmartPosition: function (align, root, node) {
var self = JX.Tooltip;
var pos = self._proposePosition(align, root, node);
// If toolip is offscreen, try to be clever
if (!JX.Tooltip.isOnScreen(pos, node)) {
align = self._getImprovedOrientation(pos, node);
pos = self._proposePosition(align, root, node);
// Figure out how to position the tooltip on screen. We will try the
// configured aligment first.
var try_alignments = [align];
// If the configured alignment does not fit, we'll try the opposite
// alignment.
var opposites = {
N: 'S',
S: 'N',
E: 'W',
W: 'E'
};
try_alignments.push(opposites[align]);
// Then we'll try the other alignments, in arbitrary order.
for (var k in opposites) {
try_alignments.push(k);
}
self._setAnchor(align);
var use_alignment = null;
var use_pos = null;
for (var ii = 0; ii < try_alignments.length; ii++) {
var try_alignment = try_alignments[ii];
var pos = self._proposePosition(try_alignment, root, node);
if (self.isOnScreen(pos, node)) {
use_alignment = try_alignment;
use_pos = pos;
break;
}
}
// If we don't come up with a good answer, default to the configured
// alignment.
if (use_alignment === null) {
use_alignment = align;
use_pos = self._proposePosition(use_alignment, root, node);
}
self._setAnchor(use_alignment);
return pos;
},
@ -108,56 +141,24 @@ JX.install('Tooltip', {
},
isOnScreen: function (a, node) {
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 view = this._getViewBoundaries();
var corners = this._getNodeCornerPositions(a, node);
// Check if any of the corners are offscreen
// 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) {
if (corner.x < view.w ||
corner.y < view.n ||
corner.x > view.e ||
corner.y > view.s) {
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
// 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),
@ -165,6 +166,24 @@ JX.install('Tooltip', {
new JX.Vector(pos.x + n.x, pos.y + n.y)];
},
_getViewBoundaries: function() {
var s = JX.Vector.getScroll();
var v = JX.Vector.getViewport();
var max_x = s.x + v.x;
var max_y = s.y + v.y;
// Even if the corner is technically on the screen, don't allow the
// tip to display too close to the edge of the screen.
var margin = 16;
return {
w: s.x + margin,
e: max_x - margin,
n: s.y + margin,
s: max_y - margin
};
},
_setAnchor: function (align) {
// Orient the little tail
JX.DOM.alterClass(this._node, 'jx-tooltip-align-' + align, true);