wekan/client/components/boards/boardBody.js
Maxime Quandalle 2c0030da62 Implement multi-selection
The UI and the internal APIs are still rough around the edges but the
feature is basically working. You can now select multiple cards and
move them together or (un|)assign them a label.
2015-05-30 03:50:14 +02:00

148 lines
3.7 KiB
JavaScript

// XXX This event list must be abstracted somewhere else.
var endTransitionEvents = [
'webkitTransitionEnd',
'otransitionend',
'oTransitionEnd',
'msTransitionEnd',
'transitionend'
].join(' ');
BlazeComponent.extendComponent({
template: function() {
return 'boardComponent';
},
onCreated: function() {
this.draggingActive = new ReactiveVar(false);
},
openNewListForm: function() {
this.componentChildren('addListForm')[0].open();
},
setIsDragging: function(bool) {
this.draggingActive.set(bool);
},
scrollLeft: function(position) {
position = position || 0;
var $container = $(this.find('.js-lists'));
var containerWidth = $container.width();
var currentScrollPosition = $container.scrollLeft();
if (position < currentScrollPosition) {
$container.animate({
scrollLeft: position
});
} else if (position > currentScrollPosition + containerWidth) {
$container.animate({
scrollLeft: Math.max(0, position - containerWidth)
});
}
},
currentCardIsInThisList: function() {
var currentCard = Cards.findOne(Session.get('currentCard'));
var listId = this.currentData()._id;
return currentCard && currentCard.listId === listId;
},
onRendered: function() {
var self = this;
self.scrollLeft();
var lists = this.find('.js-lists');
// We want to animate the card details window closing. We rely on CSS
// transition for the actual animation.
lists._uihooks = {
removeElement: function(node) {
var removeNode = _.once(function() {
node.parentNode.removeChild(node);
});
if ($(node).hasClass('js-card-detail')) {
$(node).css({
flex: '0 0 0',
padding: 0
});
$(lists).one(endTransitionEvents, removeNode);
} else {
removeNode();
}
}
};
if (! Meteor.userId() || ! Meteor.user().isBoardMember())
return;
self.$(lists).sortable({
tolerance: 'pointer',
appendTo: '.js-lists',
helper: 'clone',
items: '.js-list:not(.js-list-composer)',
placeholder: 'list placeholder',
start: function(evt, ui) {
ui.placeholder.height(ui.helper.height());
Popup.close();
},
stop: function() {
self.$('.js-lists').find('.js-list:not(.js-list-composer)').each(
function(i, list) {
var data = Blaze.getData(list);
Lists.update(data._id, {
$set: {
sort: i
}
});
}
);
}
});
// Disable drag-dropping while in multi-selection mode
self.autorun(function() {
self.$(lists).sortable('option', 'disabled', MultiSelection.isActive());
});
// If there is no data in the board (ie, no lists) we autofocus the list
// creation form by clicking on the corresponding element.
if (self.data().lists().count() === 0) {
this.openNewListForm();
}
},
sidebarSize: function() {
var sidebar = this.componentChildren('sidebar')[0];
if (sidebar && sidebar.isOpen())
return 'next-sidebar';
}
}).register('boardComponent');
BlazeComponent.extendComponent({
template: function() {
return 'addListForm';
},
// Proxy
open: function() {
this.componentChildren('inlinedForm')[0].open();
},
events: function() {
return [{
submit: function(evt) {
evt.preventDefault();
var title = this.find('.list-name-input');
if ($.trim(title.value)) {
Lists.insert({
title: title.value,
boardId: Session.get('currentBoard'),
sort: $('.list').length
});
title.value = '';
}
}
}];
}
}).register('addListForm');