summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorMaxime Quandalle <maxime@quandalle.com>2015-08-28 03:35:18 +0200
committerMaxime Quandalle <maxime@quandalle.com>2015-08-28 03:35:18 +0200
commit5eb67e803af0fd674f85a80e47913fa13fed24b2 (patch)
treeaa13e102e4d227d3ed546be959fb504be74326cd /client
parentb5dabfe88695a8f8211b29fea0dc16131c9a1829 (diff)
downloadwekan-5eb67e803af0fd674f85a80e47913fa13fed24b2.tar.gz
wekan-5eb67e803af0fd674f85a80e47913fa13fed24b2.tar.bz2
wekan-5eb67e803af0fd674f85a80e47913fa13fed24b2.zip
Implement click-and-drag integration to translate the board canvas
Fixes #232
Diffstat (limited to 'client')
-rw-r--r--client/components/boards/boardBody.js44
-rw-r--r--client/components/lists/list.styl3
-rw-r--r--client/lib/escapeActions.js22
3 files changed, 57 insertions, 12 deletions
diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js
index 4ed62bdc..8a1941d6 100644
--- a/client/components/boards/boardBody.js
+++ b/client/components/boards/boardBody.js
@@ -19,6 +19,9 @@ BlazeComponent.extendComponent({
var handle = subManager.subscribe('board', Session.get('currentBoard'));
self.isBoardReady.set(handle.ready());
});
+
+ self._isDragging = false;
+ self._lastDragPositionX = 0;
},
openNewListForm: function() {
@@ -34,7 +37,7 @@ BlazeComponent.extendComponent({
scrollLeft: function(position) {
position = position || 0;
- var $container = $(this.find('.js-lists'));
+ var $container = $(this.listsDom);
var containerWidth = $container.width();
var currentScrollPosition = $container.scrollLeft();
if (position < currentScrollPosition) {
@@ -66,6 +69,33 @@ BlazeComponent.extendComponent({
// component.
'mouseenter .board-overlay': function() {
this.showOverlay.set(false);
+ },
+
+ // Click-and-drag action
+ 'mousedown .board-canvas': function(evt) {
+ if ($(evt.target).closest('a,.js-list-header').length === 0) {
+ this._isDragging = true;
+ this._lastDragPositionX = evt.clientX;
+ }
+ },
+ 'mouseup': function(evt) {
+ if (this._isDragging) {
+ this._isDragging = false;
+ }
+ },
+ 'mousemove': function(evt) {
+ if (this._isDragging) {
+ // Update the canvas position
+ this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX;
+ this._lastDragPositionX = evt.clientX;
+ // Disable browser text selection while dragging
+ evt.stopPropagation();
+ evt.preventDefault();
+ // Don't close opened card or inlined form at the end of the
+ // click-and-drag.
+ EscapeActions.executeUpTo('popup-close');
+ EscapeActions.preventNextClick();
+ }
}
}];
}
@@ -76,11 +106,11 @@ Template.boardBody.onRendered(function() {
self.scrollLeft();
- var lists = this.find('.js-lists');
+ self.listsDom = this.find('.js-lists');
// We want to animate the card details window closing. We rely on CSS
// transition for the actual animation.
- lists._uihooks = {
+ self.listsDom._uihooks = {
removeElement: function(node) {
var removeNode = _.once(function() {
node.parentNode.removeChild(node);
@@ -90,7 +120,7 @@ Template.boardBody.onRendered(function() {
flexBasis: 0,
padding: 0
});
- $(lists).one(CSSEvents.transitionend, removeNode);
+ $(self.listsDom).one(CSSEvents.transitionend, removeNode);
} else {
removeNode();
}
@@ -100,9 +130,10 @@ Template.boardBody.onRendered(function() {
if (! Meteor.user() || ! Meteor.user().isBoardMember())
return;
- self.$(lists).sortable({
+ self.$(self.listsDom).sortable({
tolerance: 'pointer',
helper: 'clone',
+ handle: '.js-list-header',
items: '.js-list:not(.js-list-composer)',
placeholder: 'list placeholder',
distance: 7,
@@ -126,7 +157,8 @@ Template.boardBody.onRendered(function() {
// Disable drag-dropping while in multi-selection mode
self.autorun(function() {
- self.$(lists).sortable('option', 'disabled', MultiSelection.isActive());
+ self.$(self.listsDom).sortable('option', 'disabled',
+ MultiSelection.isActive());
});
// If there is no data in the board (ie, no lists) we autofocus the list
diff --git a/client/components/lists/list.styl b/client/components/lists/list.styl
index bfa0f348..40e5ea94 100644
--- a/client/components/lists/list.styl
+++ b/client/components/lists/list.styl
@@ -60,6 +60,9 @@
position: relative
min-height: 20px
+ &.ui-sortable-handle
+ cursor: grab
+
.list-header-name
display: inline
font-size: 16px
diff --git a/client/lib/escapeActions.js b/client/lib/escapeActions.js
index 1297cfb0..fa113bf3 100644
--- a/client/lib/escapeActions.js
+++ b/client/lib/escapeActions.js
@@ -4,6 +4,8 @@
// escape we execute the action which have a valid condition and his the highest
// in the label hierarchy.
EscapeActions = {
+ _nextclickPrevented: false,
+
_actions: [],
// Executed in order
@@ -60,12 +62,20 @@ EscapeActions = {
},
clickExecute: function(target, maxLabel) {
- return this._execute({
- maxLabel: maxLabel,
- multipleActions: false,
- isClick: true,
- clickTarget: target
- });
+ if (this._nextclickPrevented) {
+ this._nextclickPrevented = false;
+ } else {
+ return this._execute({
+ maxLabel: maxLabel,
+ multipleActions: false,
+ isClick: true,
+ clickTarget: target
+ });
+ }
+ },
+
+ preventNextClick: function() {
+ this._nextclickPrevented = true;
},
_stopClick: function(action, clickTarget) {