From c2960aa743bf8d00f60cfbde1410593390e19b8c Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 5 Apr 2013 11:01:56 -0700 Subject: [PATCH] Load hovercards on-demand Summary: See discussion in D5563. This loads hovercards on-demand, and shows them once they load. Ref T1048. Test Plan: Made a preview comment like `T1`, waved my mouse over it, got a hovercard shortly thereafter. Reviewers: AnhNhan Reviewed By: AnhNhan CC: aran Maniphest Tasks: T1048 Differential Revision: https://secure.phabricator.com/D5588 --- src/__celerity_resource_map__.php | 16 ++-- webroot/rsrc/js/application/core/Hovercard.js | 84 ++++++++++--------- .../js/application/core/behavior-hovercard.js | 29 ++----- 3 files changed, 60 insertions(+), 69 deletions(-) diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index cc54415874..b50bd1e28f 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -1905,14 +1905,15 @@ celerity_register_resource_map(array( ), 'javelin-behavior-phabricator-hovercards' => array( - 'uri' => '/res/8366e963/rsrc/js/application/core/behavior-hovercard.js', + 'uri' => '/res/65824840/rsrc/js/application/core/behavior-hovercard.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-behavior', 1 => 'javelin-behavior-device', 2 => 'javelin-stratcom', - 3 => 'phabricator-hovercard', + 3 => 'javelin-vector', + 4 => 'phabricator-hovercard', ), 'disk' => '/rsrc/js/application/core/behavior-hovercard.js', ), @@ -3042,16 +3043,15 @@ celerity_register_resource_map(array( ), 'phabricator-hovercard' => array( - 'uri' => '/res/1db6db48/rsrc/js/application/core/Hovercard.js', + 'uri' => '/res/a6eafd28/rsrc/js/application/core/Hovercard.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-install', - 1 => 'javelin-util', - 2 => 'javelin-dom', - 3 => 'javelin-vector', - 4 => 'javelin-request', - 5 => 'phabricator-busy', + 1 => 'javelin-dom', + 2 => 'javelin-vector', + 3 => 'javelin-request', + 4 => 'javelin-uri', ), 'disk' => '/rsrc/js/application/core/Hovercard.js', ), diff --git a/webroot/rsrc/js/application/core/Hovercard.js b/webroot/rsrc/js/application/core/Hovercard.js index 85fdaa5cd2..5907dd4d21 100644 --- a/webroot/rsrc/js/application/core/Hovercard.js +++ b/webroot/rsrc/js/application/core/Hovercard.js @@ -1,10 +1,9 @@ /** * @requires javelin-install - * javelin-util * javelin-dom * javelin-vector * javelin-request - * phabricator-busy + * javelin-uri * @provides phabricator-hovercard * @javelin */ @@ -14,31 +13,54 @@ JX.install('Hovercard', { statics : { _node : null, _activeRoot : null, - - _didScrape : false, + _visiblePHID : null, fetchUrl : '/search/hovercard/retrieve/', /** * Hovercard storage. {"PHID-XXXX-YYYY":"<...>", ...} */ - cards : {}, + _cards : {}, + + getAnchor : function() { + return this._activeRoot; + }, + + getCard : function() { + return this._node; + }, show : function(root, phid) { + var self = JX.Hovercard; + self.hide(); + + self._visiblePHID = phid; + self._activeRoot = root; // Hovercards are all loaded by now, but when somebody previews a comment // for example it may not be loaded yet. - if (!JX.Hovercard.cards[phid]) { - JX.Hovercard.load([phid]); + if (!(phid in self._cards)) { + self._load([phid]); + } else { + self._drawCard(phid); + } + }, + + _drawCard : function(phid) { + var self = JX.Hovercard; + if (phid != self._visiblePHID) { + return; + } + if (!(phid in self._cards)) { + return; } + var root = self._activeRoot; var node = JX.$N('div', { className: 'jx-hovercard-container' }, - JX.Hovercard.cards[phid]); + JX.$H(self._cards[phid])); - JX.Hovercard.hide(); - this._node = node; - this._activeRoot = root; + self._node = node; // Append the card to the document, but offscreen, so we can measure it. node.style.left = '-10000px'; @@ -70,16 +92,15 @@ JX.install('Hovercard', { node.style.left = x + 'px'; node.style.top = y + 'px'; - }, hide : function() { - if (this._node) { - JX.DOM.remove(this._node); - this._node = null; - } - if (this._activeRoot) { - this._activeRoot = null; + var self = JX.Hovercard; + self._visiblePHID = null; + self._activeRoot = null; + if (self._node) { + JX.DOM.remove(self._node); + self._node = null; } }, @@ -88,8 +109,9 @@ JX.install('Hovercard', { * * @param list phids */ - load : function(phids) { - var uri = JX.$U(JX.Hovercard.fetchUrl); + _load : function(phids) { + var self = JX.Hovercard; + var uri = JX.$U(self.fetchUrl); for (var ii = 0; ii < phids.length; ii++) { uri.setQueryParam("phids["+ii+"]", phids[ii]); @@ -97,28 +119,10 @@ JX.install('Hovercard', { new JX.Request(uri, function(r) { for (var phid in r.cards) { - JX.Hovercard.cards[phid] = JX.$H(r.cards[phid]); + self._cards[phid] = r.cards[phid]; + self._drawCard(phid); } }).send(); - }, - - // For later probably - // Currently unused - scrapeAndLoad: function() { - if (!JX.Hovercard._didScrape) { - // I assume links only for now - var cards = JX.DOM.scry(document, 'a', 'hovercard'); - var phids = []; - var data; - for (var i = 0; i < cards.length; i++) { - data = JX.Stratcom.getData(cards[i]); - phids.push(data.hoverPHID); - } - - JX.Hovercard.load(phids); - - JX.Hovercard._didScrape = true; - } } } }); diff --git a/webroot/rsrc/js/application/core/behavior-hovercard.js b/webroot/rsrc/js/application/core/behavior-hovercard.js index e55368c875..7a12e78232 100644 --- a/webroot/rsrc/js/application/core/behavior-hovercard.js +++ b/webroot/rsrc/js/application/core/behavior-hovercard.js @@ -3,25 +3,17 @@ * @requires javelin-behavior * javelin-behavior-device * javelin-stratcom + * javelin-vector * phabricator-hovercard * @javelin */ JX.behavior('phabricator-hovercards', function(config) { - // First find all hovercard-able object on page and load them in a batch - JX.Hovercard.scrapeAndLoad(); - - // Event stuff JX.Stratcom.listen( - ['mouseover'], + 'mouseover', 'hovercard', function (e) { - if (e.getType() == 'mouseout') { - JX.Hovercard.hide(); - return; - } - if (JX.Device.getDevice() != 'desktop') { return; } @@ -34,19 +26,15 @@ JX.behavior('phabricator-hovercards', function(config) { }); JX.Stratcom.listen( - ['mousemove'], + 'mousemove', null, function (e) { - if (JX.Device.getDevice() != 'desktop') { + if (!JX.Hovercard.getCard()) { return; } - if (!JX.Hovercard._node) { - return; - } - - var root = JX.Hovercard._activeRoot; - var node = JX.Hovercard._node.firstChild; + var root = JX.Hovercard.getAnchor(); + var node = JX.Hovercard.getCard(); var mouse = JX.$V(e); var node_pos = JX.$V(node); @@ -74,16 +62,15 @@ JX.behavior('phabricator-hovercards', function(config) { // Cursor is too far to the right. if (mouse.x > Math.max(root_pos.x + root_dim.x, node_pos.x + node_dim.x) + margin) { - JX.Hovercard.hide(); } }); // When we leave the page, hide any visible hovercards. If we don't do this, // clicking a link with a hovercard and then hitting "back" will give you a - // phantom tooltip. + // phantom card. We also hide cards if the window resizes. JX.Stratcom.listen( - 'unload', + ['unload', 'onresize'], null, function(e) { JX.Hovercard.hide();