@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+73 -54
+9 -9
resources/celerity/map.php
··· 10 10 'conpherence.pkg.css' => '0b64e988', 11 11 'conpherence.pkg.js' => '6249a1cf', 12 12 'core.pkg.css' => '9c725fa0', 13 - 'core.pkg.js' => 'f998932d', 13 + 'core.pkg.js' => 'a2ead3fe', 14 14 'darkconsole.pkg.js' => 'e7393ebb', 15 15 'differential.pkg.css' => 'f69afb45', 16 16 'differential.pkg.js' => '40b18f35', ··· 489 489 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', 490 490 'rsrc/js/core/TextAreaUtils.js' => '320810c8', 491 491 'rsrc/js/core/Title.js' => '485aaa6c', 492 - 'rsrc/js/core/ToolTip.js' => '6323f942', 492 + 'rsrc/js/core/ToolTip.js' => 'b5c62c3b', 493 493 'rsrc/js/core/behavior-active-nav.js' => 'e379b58e', 494 494 'rsrc/js/core/behavior-audio-source.js' => '59b251eb', 495 495 'rsrc/js/core/behavior-autofocus.js' => '7319e029', ··· 816 816 'phabricator-standard-page-view' => '894d8a25', 817 817 'phabricator-textareautils' => '320810c8', 818 818 'phabricator-title' => '485aaa6c', 819 - 'phabricator-tooltip' => '6323f942', 819 + 'phabricator-tooltip' => 'b5c62c3b', 820 820 'phabricator-ui-example-css' => '528b19de', 821 821 'phabricator-uiexample-javelin-view' => 'd4a14807', 822 822 'phabricator-uiexample-reactor-button' => 'd19198c8', ··· 1418 1418 'javelin-install', 1419 1419 'javelin-util', 1420 1420 ), 1421 - '6323f942' => array( 1422 - 'javelin-install', 1423 - 'javelin-util', 1424 - 'javelin-dom', 1425 - 'javelin-vector', 1426 - ), 1427 1421 '635de1ec' => array( 1428 1422 'javelin-behavior', 1429 1423 'javelin-stratcom', ··· 1902 1896 'b5c256b8' => array( 1903 1897 'javelin-install', 1904 1898 'javelin-dom', 1899 + ), 1900 + 'b5c62c3b' => array( 1901 + 'javelin-install', 1902 + 'javelin-util', 1903 + 'javelin-dom', 1904 + 'javelin-vector', 1905 1905 ), 1906 1906 'b5d57730' => array( 1907 1907 'javelin-install',
+64 -45
webroot/rsrc/js/core/ToolTip.js
··· 65 65 66 66 _getSmartPosition: function (align, root, node) { 67 67 var self = JX.Tooltip; 68 - var pos = self._proposePosition(align, root, node); 68 + 69 + // Figure out how to position the tooltip on screen. We will try the 70 + // configured aligment first. 71 + var try_alignments = [align]; 72 + 73 + // If the configured alignment does not fit, we'll try the opposite 74 + // alignment. 75 + var opposites = { 76 + N: 'S', 77 + S: 'N', 78 + E: 'W', 79 + W: 'E' 80 + }; 81 + try_alignments.push(opposites[align]); 82 + 83 + // Then we'll try the other alignments, in arbitrary order. 84 + for (var k in opposites) { 85 + try_alignments.push(k); 86 + } 87 + 88 + var use_alignment = null; 89 + var use_pos = null; 90 + for (var ii = 0; ii < try_alignments.length; ii++) { 91 + var try_alignment = try_alignments[ii]; 92 + 93 + var pos = self._proposePosition(try_alignment, root, node); 94 + if (self.isOnScreen(pos, node)) { 95 + use_alignment = try_alignment; 96 + use_pos = pos; 97 + break; 98 + } 99 + } 69 100 70 - // If toolip is offscreen, try to be clever 71 - if (!JX.Tooltip.isOnScreen(pos, node)) { 72 - align = self._getImprovedOrientation(pos, node); 73 - pos = self._proposePosition(align, root, node); 101 + // If we don't come up with a good answer, default to the configured 102 + // alignment. 103 + if (use_alignment === null) { 104 + use_alignment = align; 105 + use_pos = self._proposePosition(use_alignment, root, node); 74 106 } 75 107 76 - self._setAnchor(align); 108 + self._setAnchor(use_alignment); 109 + 77 110 return pos; 78 111 }, 79 112 ··· 108 141 }, 109 142 110 143 isOnScreen: function (a, node) { 111 - var s = JX.Vector.getScroll(); 112 - var v = JX.Vector.getViewport(); 113 - var max_x = s.x + v.x; 114 - var max_y = s.y + v.y; 115 - 144 + var view = this._getViewBoundaries(); 116 145 var corners = this._getNodeCornerPositions(a, node); 117 146 118 - // Check if any of the corners are offscreen 147 + // Check if any of the corners are offscreen. 119 148 for (var i = 0; i < corners.length; i++) { 120 149 var corner = corners[i]; 121 - if (corner.x < s.x || 122 - corner.y < s.y || 123 - corner.x > max_x || 124 - corner.y > max_y) { 150 + if (corner.x < view.w || 151 + corner.y < view.n || 152 + corner.x > view.e || 153 + corner.y > view.s) { 125 154 return false; 126 155 } 127 156 } 128 157 return true; 129 158 }, 130 159 131 - _getImprovedOrientation: function (a, node) { 132 - // Try to predict the "more correct" orientation 133 - var s = JX.Vector.getScroll(); 134 - var v = JX.Vector.getViewport(); 135 - var max_x = s.x + v.x; 136 - var max_y = s.y + v.y; 137 - 138 - var corners = this._getNodeCornerPositions(a, node); 139 - 140 - for (var i = 0; i < corners.length; i++) { 141 - var corner = corners[i]; 142 - if (corner.y < v.y) { 143 - return 'S'; 144 - } else 145 - if (corner.x < v.x) { 146 - return 'E'; 147 - } else 148 - if (corner.y > max_y) { 149 - return 'N'; 150 - } else 151 - if (corner.x > max_x) { 152 - return 'W'; 153 - } else { 154 - return 'N'; 155 - } 156 - } 157 - }, 158 - 159 160 _getNodeCornerPositions: function(pos, node) { 160 - // Get positions of all four corners of a node 161 + // Get positions of all four corners of a node. 161 162 var n = JX.Vector.getDim(node); 162 163 return [new JX.Vector(pos.x, pos.y), 163 164 new JX.Vector(pos.x + n.x, pos.y), 164 165 new JX.Vector(pos.x, pos.y + n.y), 165 166 new JX.Vector(pos.x + n.x, pos.y + n.y)]; 167 + }, 168 + 169 + _getViewBoundaries: function() { 170 + var s = JX.Vector.getScroll(); 171 + var v = JX.Vector.getViewport(); 172 + var max_x = s.x + v.x; 173 + var max_y = s.y + v.y; 174 + 175 + // Even if the corner is technically on the screen, don't allow the 176 + // tip to display too close to the edge of the screen. 177 + var margin = 16; 178 + 179 + return { 180 + w: s.x + margin, 181 + e: max_x - margin, 182 + n: s.y + margin, 183 + s: max_y - margin 184 + }; 166 185 }, 167 186 168 187 _setAnchor: function (align) {