mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 07:20:12 +01:00
Implement click-and-drag integration to translate the board canvas
Fixes #232
This commit is contained in:
parent
b5dabfe886
commit
5eb67e803a
3 changed files with 57 additions and 12 deletions
|
|
@ -19,6 +19,9 @@ BlazeComponent.extendComponent({
|
||||||
var handle = subManager.subscribe('board', Session.get('currentBoard'));
|
var handle = subManager.subscribe('board', Session.get('currentBoard'));
|
||||||
self.isBoardReady.set(handle.ready());
|
self.isBoardReady.set(handle.ready());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self._isDragging = false;
|
||||||
|
self._lastDragPositionX = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
openNewListForm: function() {
|
openNewListForm: function() {
|
||||||
|
|
@ -34,7 +37,7 @@ BlazeComponent.extendComponent({
|
||||||
|
|
||||||
scrollLeft: function(position) {
|
scrollLeft: function(position) {
|
||||||
position = position || 0;
|
position = position || 0;
|
||||||
var $container = $(this.find('.js-lists'));
|
var $container = $(this.listsDom);
|
||||||
var containerWidth = $container.width();
|
var containerWidth = $container.width();
|
||||||
var currentScrollPosition = $container.scrollLeft();
|
var currentScrollPosition = $container.scrollLeft();
|
||||||
if (position < currentScrollPosition) {
|
if (position < currentScrollPosition) {
|
||||||
|
|
@ -66,6 +69,33 @@ BlazeComponent.extendComponent({
|
||||||
// component.
|
// component.
|
||||||
'mouseenter .board-overlay': function() {
|
'mouseenter .board-overlay': function() {
|
||||||
this.showOverlay.set(false);
|
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();
|
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
|
// We want to animate the card details window closing. We rely on CSS
|
||||||
// transition for the actual animation.
|
// transition for the actual animation.
|
||||||
lists._uihooks = {
|
self.listsDom._uihooks = {
|
||||||
removeElement: function(node) {
|
removeElement: function(node) {
|
||||||
var removeNode = _.once(function() {
|
var removeNode = _.once(function() {
|
||||||
node.parentNode.removeChild(node);
|
node.parentNode.removeChild(node);
|
||||||
|
|
@ -90,7 +120,7 @@ Template.boardBody.onRendered(function() {
|
||||||
flexBasis: 0,
|
flexBasis: 0,
|
||||||
padding: 0
|
padding: 0
|
||||||
});
|
});
|
||||||
$(lists).one(CSSEvents.transitionend, removeNode);
|
$(self.listsDom).one(CSSEvents.transitionend, removeNode);
|
||||||
} else {
|
} else {
|
||||||
removeNode();
|
removeNode();
|
||||||
}
|
}
|
||||||
|
|
@ -100,9 +130,10 @@ Template.boardBody.onRendered(function() {
|
||||||
if (! Meteor.user() || ! Meteor.user().isBoardMember())
|
if (! Meteor.user() || ! Meteor.user().isBoardMember())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
self.$(lists).sortable({
|
self.$(self.listsDom).sortable({
|
||||||
tolerance: 'pointer',
|
tolerance: 'pointer',
|
||||||
helper: 'clone',
|
helper: 'clone',
|
||||||
|
handle: '.js-list-header',
|
||||||
items: '.js-list:not(.js-list-composer)',
|
items: '.js-list:not(.js-list-composer)',
|
||||||
placeholder: 'list placeholder',
|
placeholder: 'list placeholder',
|
||||||
distance: 7,
|
distance: 7,
|
||||||
|
|
@ -126,7 +157,8 @@ Template.boardBody.onRendered(function() {
|
||||||
|
|
||||||
// Disable drag-dropping while in multi-selection mode
|
// Disable drag-dropping while in multi-selection mode
|
||||||
self.autorun(function() {
|
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
|
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@
|
||||||
position: relative
|
position: relative
|
||||||
min-height: 20px
|
min-height: 20px
|
||||||
|
|
||||||
|
&.ui-sortable-handle
|
||||||
|
cursor: grab
|
||||||
|
|
||||||
.list-header-name
|
.list-header-name
|
||||||
display: inline
|
display: inline
|
||||||
font-size: 16px
|
font-size: 16px
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
// escape we execute the action which have a valid condition and his the highest
|
// escape we execute the action which have a valid condition and his the highest
|
||||||
// in the label hierarchy.
|
// in the label hierarchy.
|
||||||
EscapeActions = {
|
EscapeActions = {
|
||||||
|
_nextclickPrevented: false,
|
||||||
|
|
||||||
_actions: [],
|
_actions: [],
|
||||||
|
|
||||||
// Executed in order
|
// Executed in order
|
||||||
|
|
@ -60,12 +62,20 @@ EscapeActions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
clickExecute: function(target, maxLabel) {
|
clickExecute: function(target, maxLabel) {
|
||||||
return this._execute({
|
if (this._nextclickPrevented) {
|
||||||
maxLabel: maxLabel,
|
this._nextclickPrevented = false;
|
||||||
multipleActions: false,
|
} else {
|
||||||
isClick: true,
|
return this._execute({
|
||||||
clickTarget: target
|
maxLabel: maxLabel,
|
||||||
});
|
multipleActions: false,
|
||||||
|
isClick: true,
|
||||||
|
clickTarget: target
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
preventNextClick: function() {
|
||||||
|
this._nextclickPrevented = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_stopClick: function(action, clickTarget) {
|
_stopClick: function(action, clickTarget) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue