Page MenuHomePhabricator

D10455.diff
No OneTemporary

D10455.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -8,7 +8,7 @@
return array(
'names' => array(
'core.pkg.css' => '974635bb',
- 'core.pkg.js' => '47fd11f0',
+ 'core.pkg.js' => 'f0e2c091',
'darkconsole.pkg.js' => 'df001cab',
'differential.pkg.css' => '36884139',
'differential.pkg.js' => '73337d1d',
@@ -412,7 +412,7 @@
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => 'fe9a552f',
'rsrc/js/application/ponder/behavior-votebox.js' => '4e9b766b',
'rsrc/js/application/projects/behavior-boards-dropdown.js' => '0ec56e1d',
- 'rsrc/js/application/projects/behavior-project-boards.js' => 'a6c6a058',
+ 'rsrc/js/application/projects/behavior-project-boards.js' => '0676345e',
'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb',
'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
@@ -438,7 +438,7 @@
'rsrc/js/application/uiexample/notification-example.js' => '7a9677fc',
'rsrc/js/core/Busy.js' => '6453c869',
'rsrc/js/core/DragAndDropFileUpload.js' => '8c49f386',
- 'rsrc/js/core/DraggableList.js' => '2a6a1041',
+ 'rsrc/js/core/DraggableList.js' => 'a16ec1c6',
'rsrc/js/core/FileUpload.js' => 'a4ae61bf',
'rsrc/js/core/Hovercard.js' => '7e8468ae',
'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2',
@@ -636,7 +636,7 @@
'javelin-behavior-policy-control' => 'f3fef818',
'javelin-behavior-policy-rule-editor' => 'fe9a552f',
'javelin-behavior-ponder-votebox' => '4e9b766b',
- 'javelin-behavior-project-boards' => 'a6c6a058',
+ 'javelin-behavior-project-boards' => '0676345e',
'javelin-behavior-project-create' => '065227cc',
'javelin-behavior-refresh-csrf' => '7814b593',
'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf',
@@ -713,7 +713,7 @@
'phabricator-crumbs-view-css' => 'a49339de',
'phabricator-dashboard-css' => 'a2bfdcbf',
'phabricator-drag-and-drop-file-upload' => '8c49f386',
- 'phabricator-draggable-list' => '2a6a1041',
+ 'phabricator-draggable-list' => 'a16ec1c6',
'phabricator-fatal-config-template-css' => '25d446d6',
'phabricator-feed-css' => '7bfc6f12',
'phabricator-file-upload' => 'a4ae61bf',
@@ -851,6 +851,15 @@
'javelin-stratcom',
'javelin-workflow',
),
+ '0676345e' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-vector',
+ 'javelin-stratcom',
+ 'javelin-workflow',
+ 'phabricator-draggable-list',
+ ),
'06e05112' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -987,14 +996,6 @@
'javelin-install',
'javelin-util',
),
- '2a6a1041' => array(
- 'javelin-install',
- 'javelin-dom',
- 'javelin-stratcom',
- 'javelin-util',
- 'javelin-vector',
- 'javelin-magical-init',
- ),
'2b228192' => array(
'javelin-behavior',
'javelin-dom',
@@ -1477,6 +1478,14 @@
'javelin-dom',
'javelin-reactor-dom',
),
+ 'a16ec1c6' => array(
+ 'javelin-install',
+ 'javelin-dom',
+ 'javelin-stratcom',
+ 'javelin-util',
+ 'javelin-vector',
+ 'javelin-magical-init',
+ ),
'a4ae61bf' => array(
'javelin-install',
'javelin-dom',
@@ -1485,14 +1494,6 @@
'a5d7cf86' => array(
'javelin-dom',
),
- 'a6c6a058' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-util',
- 'javelin-stratcom',
- 'javelin-workflow',
- 'phabricator-draggable-list',
- ),
'a80d0378' => array(
'javelin-behavior',
'javelin-stratcom',
diff --git a/src/view/layout/AphrontMultiColumnView.php b/src/view/layout/AphrontMultiColumnView.php
--- a/src/view/layout/AphrontMultiColumnView.php
+++ b/src/view/layout/AphrontMultiColumnView.php
@@ -139,11 +139,14 @@
->addPadding(PHUI::PADDING_MEDIUM_BOTTOM);
}
- return phutil_tag(
+ return javelin_tag(
'div',
array(
'class' => 'aphront-multi-column-view',
'id' => $this->getID(),
+ // TODO: It would be nice to convert this to an AphrontTagView and
+ // use addSigil() from Workboards instead of hard-coding this.
+ 'sigil' => 'aphront-multi-column-view',
),
$board);
}
diff --git a/webroot/rsrc/js/application/projects/behavior-project-boards.js b/webroot/rsrc/js/application/projects/behavior-project-boards.js
--- a/webroot/rsrc/js/application/projects/behavior-project-boards.js
+++ b/webroot/rsrc/js/application/projects/behavior-project-boards.js
@@ -3,6 +3,7 @@
* @requires javelin-behavior
* javelin-dom
* javelin-util
+ * javelin-vector
* javelin-stratcom
* javelin-workflow
* phabricator-draggable-list
@@ -88,6 +89,41 @@
return 0;
}
+ function getcontainer() {
+ return JX.DOM.find(
+ JX.$(config.boardID),
+ 'div',
+ 'aphront-multi-column-view');
+ }
+
+ function onbegindrag(item) {
+ // If the longest column on the board is taller than the window, the board
+ // will scroll vertically. Dragging an item to the longest column may
+ // make it longer, by the total height of the board, plus the height of
+ // the drop target.
+
+ // If this happens, the scrollbar will jump around and the scroll position
+ // can be adjusted in a disorienting way. To reproduce this, drag a task
+ // to the bottom of the longest column on a scrolling board and wave the
+ // task in and out of the column. The scroll bar will jump around and
+ // it will be hard to lock onto a target.
+
+ // To fix this, set the minimum board height to the current board height
+ // plus the size of the drop target (which is the size of the item plus
+ // a bit of margin). This makes sure the scroll bar never needs to
+ // recalculate.
+
+ var item_size = JX.Vector.getDim(item);
+ var container = getcontainer();
+ var container_size = JX.Vector.getDim(container);
+
+ container.style.minHeight = (item_size.y + container_size.y + 12) + 'px';
+ }
+
+ function onenddrag() {
+ getcontainer().style.minHeight = '';
+ }
+
function ondrop(list, item, after) {
list.lock();
JX.DOM.alterClass(item, 'drag-sending', true);
@@ -151,6 +187,9 @@
list.listen('didDrop', JX.bind(null, ondrop, list));
+ list.listen('didBeginDrag', JX.bind(null, onbegindrag));
+ list.listen('didEndDrag', JX.bind(null, onenddrag));
+
lists.push(list);
onupdate(cols[ii]);
diff --git a/webroot/rsrc/js/core/DraggableList.js b/webroot/rsrc/js/core/DraggableList.js
--- a/webroot/rsrc/js/core/DraggableList.js
+++ b/webroot/rsrc/js/core/DraggableList.js
@@ -53,6 +53,7 @@
_ghostNode : null,
_group : null,
_lastMousePosition: null,
+ _lastAdjust: null,
getRootNode : function() {
return this._root;
@@ -174,7 +175,6 @@
for (var ii = 0; ii < this._group.length; ii++) {
this._group[ii]._clearTarget();
- this._group[ii]._generateTargets();
}
if (!this.invoke('didBeginDrag', this._dragging).getPrevented()) {
@@ -189,17 +189,48 @@
}
},
- _generateTargets : function() {
- var targets = [];
- var items = this.findItems();
- for (var ii = 0; ii < items.length; ii++) {
- targets.push({
- item: items[ii],
- y: JX.$V(items[ii]).y + (JX.Vector.getDim(items[ii]).y / 2)
- });
+ _getTargets : function() {
+ if (this._targets === null) {
+ var targets = [];
+ var items = this.findItems();
+ for (var ii = 0; ii < items.length; ii++) {
+ var item = items[ii];
+
+ var ipos = JX.$V(item);
+ if (item == this._dragging) {
+ // If the item we're measuring is also the item we're dragging,
+ // we need to measure its position as though it was still in the
+ // list, not its current position in the document (which is
+ // under the cursor). To do this, adjust the measured position by
+ // removing the offsets we added to put the item underneath the
+ // cursor.
+ if (this._lastAdjust) {
+ ipos.x -= this._lastAdjust.x;
+ ipos.y -= this._lastAdjust.y;
+ }
+ }
+
+ targets.push({
+ item: items[ii],
+ y: ipos.y + (JX.Vector.getDim(items[ii]).y / 2)
+ });
+ }
+ targets.sort(function(u, v) { return v.y - u.y; });
+ this._targets = targets;
+ }
+
+ return this._targets;
+ },
+
+ _dirtyTargetCache: function() {
+ if (this._hasGroup()) {
+ var group = this._group;
+ for (var ii = 0; ii < group.length; ii++) {
+ group[ii]._targets = null;
+ }
+ } else {
+ this._targets = null;
}
- targets.sort(function(u, v) { return v.y - u.y; });
- this._targets = targets;
return this;
},
@@ -264,7 +295,7 @@
_getCurrentTarget : function(p) {
var ghost = this.getGhostNode();
- var targets = this._targets;
+ var targets = this._getTargets();
var dragging = this._dragging;
var adjust_h = JX.Vector.getDim(ghost).y;
@@ -348,6 +379,12 @@
return;
}
+ if (e.getType() == 'scroll') {
+ // If this is a scroll event, the positions of drag targets may have
+ // changed.
+ this._dirtyTargetCache();
+ }
+
var p = JX.$V(this._lastMousePosition.x, this._lastMousePosition.y);
var group = this._group;
@@ -402,6 +439,7 @@
}
p.y -= origin.y;
+ this._lastAdjust = new JX.Vector(p.x, p.y);
p.setPos(this._dragging);
e.kill();
@@ -442,6 +480,8 @@
for (var ii = 0; ii < group.length; ii++) {
JX.DOM.alterClass(group[ii].getRootNode(), 'drag-target-list', false);
group[ii]._clearTarget();
+ group[ii]._dirtyTargetCache();
+ group[ii]._lastAdjust = null;
}
if (!this.invoke('didEndDrag', dragging).getPrevented()) {

File Metadata

Mime Type
text/plain
Expires
Sun, May 12, 2:40 AM (3 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6287317
Default Alt Text
D10455.diff (10 KB)

Event Timeline