From 0e98e33b33427ab0fff363f286e5d5e94a7802f2 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 9 Aug 2014 08:49:01 -0700 Subject: [PATCH] When dragging stuff around, compensate for changes in scroll position Summary: Ref T5240. This fixes dragging stuff and using the mousewheel or keyboard to scroll the window during the drag. (It does not fix "dragging near the edge of the container should scroll it" yet.) Test Plan: Dragged stuff around on task list and workboards in Safari, Firefox and Chrome. Used mousewheel and shift + mousewheel to scroll the document and containers during drag. Object remained under the cursor. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5240 Differential Revision: https://secure.phabricator.com/D10186 --- resources/celerity/map.php | 52 ++++++++++---------- webroot/rsrc/externals/javelin/lib/Vector.js | 29 +++++++++++ webroot/rsrc/js/core/DraggableList.js | 10 +++- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 7cbdcc902a..5255879bb7 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => 'c7059fd9', - 'core.pkg.js' => 'eb8d4f82', + 'core.pkg.js' => '14887b3d', 'darkconsole.pkg.js' => 'df001cab', 'differential.pkg.css' => '4a93db37', 'differential.pkg.js' => 'eb182ccd', @@ -202,7 +202,7 @@ return array( 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', 'rsrc/externals/javelin/lib/Router.js' => '29274e2b', 'rsrc/externals/javelin/lib/URI.js' => '6eff08aa', - 'rsrc/externals/javelin/lib/Vector.js' => '23cbb8ac', + 'rsrc/externals/javelin/lib/Vector.js' => 'cc1bd0b0', 'rsrc/externals/javelin/lib/Workflow.js' => 'd149e002', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', @@ -417,7 +417,7 @@ return array( 'rsrc/js/application/projects/behavior-boards-dropdown.js' => '0ec56e1d', 'rsrc/js/application/projects/behavior-project-boards.js' => 'd4bf1f3c', 'rsrc/js/application/projects/behavior-project-create.js' => '065227cc', - 'rsrc/js/application/projects/behavior-reorder-columns.js' => '09eee344', + 'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb', 'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf', 'rsrc/js/application/releeph/releeph-request-state-change.js' => 'ab836011', 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f', @@ -441,7 +441,7 @@ return array( 'rsrc/js/application/uiexample/notification-example.js' => '7a9677fc', 'rsrc/js/core/Busy.js' => '6453c869', 'rsrc/js/core/DragAndDropFileUpload.js' => 'f61aa8ec', - 'rsrc/js/core/DraggableList.js' => '2cad29d1', + 'rsrc/js/core/DraggableList.js' => 'bfccc644', 'rsrc/js/core/FileUpload.js' => 'a4ae61bf', 'rsrc/js/core/Hovercard.js' => '7e8468ae', 'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2', @@ -647,7 +647,7 @@ return array( 'javelin-behavior-releeph-request-typeahead' => 'de2e896f', 'javelin-behavior-remarkup-preview' => 'f7379f45', 'javelin-behavior-reorder-applications' => '76b9fc3e', - 'javelin-behavior-reorder-columns' => '09eee344', + 'javelin-behavior-reorder-columns' => 'e1d25dfb', 'javelin-behavior-repository-crossreference' => 'f9539603', 'javelin-behavior-search-reorder-queries' => 'e9581f08', 'javelin-behavior-select-on-click' => '4e3e79a6', @@ -688,7 +688,7 @@ return array( 'javelin-typeahead-static-source' => '316b8fa1', 'javelin-uri' => '6eff08aa', 'javelin-util' => 'e7995242', - 'javelin-vector' => '23cbb8ac', + 'javelin-vector' => 'cc1bd0b0', 'javelin-view' => '0f764c35', 'javelin-view-html' => 'e5b406f9', 'javelin-view-interpreter' => '0c33c1a0', @@ -716,7 +716,7 @@ return array( 'phabricator-crumbs-view-css' => '7fbf25b8', 'phabricator-dashboard-css' => 'a2bfdcbf', 'phabricator-drag-and-drop-file-upload' => 'f61aa8ec', - 'phabricator-draggable-list' => '2cad29d1', + 'phabricator-draggable-list' => 'bfccc644', 'phabricator-fatal-config-template-css' => '25d446d6', 'phabricator-feed-css' => '4e544db4', 'phabricator-file-upload' => 'a4ae61bf', @@ -876,13 +876,6 @@ return array( 'javelin-mask', 'phabricator-drag-and-drop-file-upload', ), - '09eee344' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-workflow', - 'javelin-dom', - 'phabricator-draggable-list', - ), '0a3f3021' => array( 'javelin-behavior', 'javelin-stratcom', @@ -995,10 +988,6 @@ return array( 'javelin-dom', 'javelin-vector', ), - '23cbb8ac' => array( - 'javelin-install', - 'javelin-event', - ), '2926fff2' => array( 'javelin-behavior', 'javelin-dom', @@ -1019,14 +1008,6 @@ return array( 'javelin-stratcom', 'javelin-dom', ), - '2cad29d1' => array( - 'javelin-install', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - 'javelin-vector', - 'javelin-magical-init', - ), '2fa810fc' => array( 'javelin-behavior', 'javelin-dom', @@ -1645,6 +1626,14 @@ return array( 'javelin-util', 'phabricator-shaped-request', ), + 'bfccc644' => array( + 'javelin-install', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + 'javelin-vector', + 'javelin-magical-init', + ), 'c4569c05' => array( 'javelin-magical-init', 'javelin-install', @@ -1664,6 +1653,10 @@ return array( 'javelin-stratcom', 'phabricator-phtize', ), + 'cc1bd0b0' => array( + 'javelin-install', + 'javelin-event', + ), 'd149e002' => array( 'javelin-stratcom', 'javelin-request', @@ -1761,6 +1754,13 @@ return array( 'javelin-dom', 'phabricator-prefab', ), + 'e1d25dfb' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-workflow', + 'javelin-dom', + 'phabricator-draggable-list', + ), 'e1ff79b1' => array( 'javelin-behavior', 'javelin-stratcom', diff --git a/webroot/rsrc/externals/javelin/lib/Vector.js b/webroot/rsrc/externals/javelin/lib/Vector.js index 4c155e18a8..2ef915ec8b 100644 --- a/webroot/rsrc/externals/javelin/lib/Vector.js +++ b/webroot/rsrc/externals/javelin/lib/Vector.js @@ -297,6 +297,35 @@ JX.install('Vector', { ); }, + + /** + * Get the aggregate scroll offsets for a node and all of its parents. + * + * Note that this excludes scroll at the document level, because it does + * not normally impact operations in document coordinates, which everything + * on this class returns. Use @{method:getScroll} to get the document scroll + * position. + * + * @param Node Node to determine offsets for. + * @return JX.Vector New vector with aggregate scroll offsets. + */ + getAggregateScrollForNode: function(node) { + var x = 0; + var y = 0; + + do { + if (node == document.body || node == document.documentElement) { + break; + } + + x += node.scrollLeft || 0; + y += node.scrollTop || 0; + node = node.parentNode; + } while (node); + + return new JX.$V(x, y); + }, + /** * Determine the size of the viewport (basically, the browser window) by * building a new vector where the 'x' component corresponds to the width diff --git a/webroot/rsrc/js/core/DraggableList.js b/webroot/rsrc/js/core/DraggableList.js index 7c0d649f83..e698aa6115 100644 --- a/webroot/rsrc/js/core/DraggableList.js +++ b/webroot/rsrc/js/core/DraggableList.js @@ -44,6 +44,7 @@ JX.install('DraggableList', { _dragging : null, _locked : 0, _origin : null, + _originScroll : null, _target : null, _targets : null, _dimensions : null, @@ -166,6 +167,7 @@ JX.install('DraggableList', { this._dragging = e.getNode(this._sigil); this._origin = JX.$V(e); + this._originScroll = JX.Vector.getAggregateScrollForNode(this._dragging); this._dimensions = JX.$V(this._dragging); for (var ii = 0; ii < this._group.length; ii++) { @@ -359,7 +361,12 @@ JX.install('DraggableList', { // adjust the cursor position for the change in node document position. // Do this before choosing a new target to avoid a flash of nonsense. - var origin = this._origin; + var scroll = JX.Vector.getAggregateScrollForNode(this._dragging); + + var origin = { + x: this._origin.x + (this._originScroll.x - scroll.x), + y: this._origin.y + (this._originScroll.y - scroll.y) + }; var adjust_h = 0; var adjust_y = 0; @@ -463,6 +470,7 @@ JX.install('DraggableList', { } return this; } + } });