diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less
index 248c66c1d..e1f5ab274 100644
--- a/www/kanban/app-kanban.less
+++ b/www/kanban/app-kanban.less
@@ -89,6 +89,7 @@
@button-size: 50px;
#kanban-addboard {
+ order: 2;
margin: 30px;
border: 1px solid;
width: @button-size;
diff --git a/www/kanban/inner.js b/www/kanban/inner.js
index c764927bc..6b041c44d 100644
--- a/www/kanban/inner.js
+++ b/www/kanban/inner.js
@@ -99,7 +99,13 @@ define([
} else {
verbose("Initializing with boards content " + boards);
}
- boards = defaultBoards;
+
+ // XXX TODO
+ /*
+ Delete a board ==> remove from array, delete the data + delete the items
+ Delete an item ==> remove from array + delete the item data
+ */
+
// Remove any existing elements
$(".kanban-container-outer").remove();
@@ -133,21 +139,23 @@ define([
verbose("An edit is already active");
//return;
}
- kanban.inEditMode = true;
- $(el).find('button').remove();
+ var eid = $(el).attr('data-eid');
+ kanban.inEditMode = eid;
var name = $(el).text();
$(el).html('');
+
+ // Add input
var $input = getInput().val(name).appendTo(el).focus();
$input[0].select();
+
var save = function () {
// Store the value
var name = $input.val();
// Remove the input
$(el).text(name);
// Save the value for the correct board
- var board = $(el).closest('.kanban-board').attr("data-id");
- var pos = kanban.findElementPosition(el.parentNode);
- kanban.getBoardJSON(board).item[pos].title = name;
+ var item = kanban.getItemJSON(eid);
+ item.title = name;
kanban.onChange();
// Unlock edit mode
kanban.inEditMode = false;
@@ -182,11 +190,14 @@ define([
verbose("An edit is already active");
//return;
}
- kanban.inEditMode = true;
+ var boardId = $(el).closest('.kanban-board').attr("data-id");
+ kanban.inEditMode = boardId;
+
var name = $(el).text();
$(el).html('');
var $input = getInput().val(name).appendTo(el).focus();
$input[0].select();
+
var save = function () {
// Store the value
var name = $input.val();
@@ -196,8 +207,7 @@ define([
// Remove the input
$(el).text(name);
// Save the value for the correct board
- var board = $(el.parentNode.parentNode).attr("data-id");
- kanban.getBoardJSON(board).title = name;
+ kanban.getBoardJSON(boardId).title = name;
kanban.onChange();
// Unlock edit mode
kanban.inEditMode = false;
@@ -294,7 +304,7 @@ define([
verbose("An edit is already active");
//return;
}
- kanban.inEditMode = true;
+ kanban.inEditMode = "new";
// create a form to enter element
var boardId = $(el.parentNode.parentNode).attr("data-id");
var $item = $('
', {'class': 'kanban-item new-item'});
@@ -305,7 +315,9 @@ define([
$item.remove();
kanban.inEditMode = false;
if (!$input.val()) { return; }
+ var id = Hash.createChannelId();
kanban.addElement(boardId, {
+ "id": id,
"title": $input.val(),
});
};
@@ -336,20 +348,20 @@ define([
$(addBoardDefault).attr('title', Messages.kanban_addBoard);
addBoardDefault.addEventListener('click', function () {
if (framework.isReadOnly()) { return; }
- var counter = 1;
+ /*var counter = 1;
// Get the new board id
var boardExists = function (b) { return b.id === "board" + counter; };
while (kanban.options.boards.some(boardExists)) { counter++; }
+ */
+ var id = Hash.createChannelId();
- kanban.addBoards([{
- "id": "board" + counter,
+ kanban.addBoard({
+ "id": id,
"title": Messages.kanban_newBoard,
"color": COLORS[Math.floor(Math.random()*COLORS.length)], // random color
- "item": [{
- "title": Messages._getKey('kanban_item', [1]),
- }]
- }]);
+ "item": []
+ });
kanban.onChange();
});
@@ -403,86 +415,73 @@ define([
$container.addClass('cp-app-readonly');
});
- var getSelectedElement = function () {
- var node = document.getSelection().anchorNode;
- return (node.nodeType === 3 ? node.parentNode : node);
- };
var getCursor = function () {
if (!kanban || !kanban.inEditMode) { return; }
try {
- var el = getSelectedElement();
- var input = $(el).is('input') ? el : $(el).find('input')[0];
- if (!input) { return; }
- var $input = $(input);
-
- var pos;
- var $item = $(el).closest('.kanban-item');
- if ($item.length) {
- pos = kanban.findElementPosition($item[0]);
+ var id = kanban.inEditMode;
+ var newBoard;
+ var $el = $container.find('[data-id="'+id+'"]');
+ if (id === "new") {
+ $el = $container.find('.kanban-item.new-item');
+ newBoard = $el.closest('.kanban-board').attr('data-id');
+ } else if (!$el.length) {
+ $el = $container.find('[data-eid="'+id+'"]');
}
- var board = $input.closest('.kanban-board').attr('data-id');
+ if (!$el.length) { return; }
+ var $input = $el.find('input');
+ if (!$input.length) { return; }
+ var input = $input[0];
+
var val = ($input.val && $input.val()) || '';
var start = input.selectionStart;
var end = input.selectionEnd;
-
- var boardEl = kanban.options.boards.find(function (b) {
- return b.id === board;
- });
- var oldVal = ((pos ? boardEl.item[pos] : boardEl) || {}).title;
+ var json = kanban.getBoardJSON(id) || kanban.getItemJSON(id);
+ // XXX only title for now...
+ var oldVal = json && json.title;
return {
- board: board,
- pos: pos,
+ id: id,
+ newBoard: newBoard,
value: val,
start: start,
end: end,
oldValue: oldVal
};
} catch (e) {
+ console.error(e);
return {};
}
};
var restoreCursor = function (data) {
try {
- var boardEl = kanban.options.boards.find(function (b) {
- return b.id === data.board;
- });
- if (!boardEl) { return; }
+ var id = data.id;
- var $board = $('.kanban-board[data-id="'+data.board+'"');
-
- // Editing a board title...
- if (!data.pos && $board.length) {
- if (boardEl.title !== data.oldValue) { return; }
- $board.find('.kanban-title-board').click();
- var $boardInput = $board.find('.kanban-title-board input');
- $boardInput.val(data.value);
- $boardInput[0].selectionStart = data.start;
- $boardInput[0].selectionEnd = data.end;
- return;
- }
- // Editing a deleted board title: abort
- if (!data.pos) {
- return;
- }
-
- // An item was added: add a new item
- if (!data.oldValue) {
- $board.find('.kanban-title-button.fa-plus').click();
- var $newInput = $board.find('.kanban-item:last-child input');
+ // An item was being added: add a new item
+ if (id === "new" && !data.oldValue) {
+ var $newBoard = $('.kanban-board[data-id="'+data.newBoard+'"]');
+ $newBoard.find('.kanban-title-button.fa-plus').click();
+ var $newInput = $newBoard.find('.kanban-item:last-child input');
$newInput.val(data.value);
$newInput[0].selectionStart = data.start;
$newInput[0].selectionEnd = data.end;
return;
}
- // An item was edited: click on the correct item
- var newVal = boardEl.item[data.pos];
- if (!newVal || newVal.title !== data.oldValue) { return; }
- var $el = $('.kanban-board[data-id="' + data.board + '"]')
- .find('.kanban-item:nth-child('+(data.pos + 1)+')');
- $el.find('.kanban-item-text').click();
+ // Edit a board title or a card title
+ var $el = $container.find('.kanban-board[data-id="'+id+'"]');
+ if (!$el.length) {
+ $el = $container.find('.kanban-item[data-eid="'+id+'"]');
+ }
+ if (!$el.length) { return; }
+
+ var json = kanban.getBoardJSON(id) || kanban.getItemJSON(id);
+
+ // if the value was changed by a remote user, abort
+ if (data.oldValue !== json.title) { return; }
+
+ // Editing a board title...
+ $el.find('.kanban-title-board, .kanban-item-text').click();
var $input = $el.find('input');
if ($input.length) {
$input.val(data.value);
@@ -490,6 +489,7 @@ define([
$input[0].selectionEnd = data.end;
}
} catch (e) {
+ console.error(e);
return;
}
};
@@ -509,6 +509,7 @@ define([
if (Sortify(currentContent) !== Sortify(remoteContent)) {
var cursor = getCursor();
+ console.error(cursor);
verbose("Content is different.. Applying content");
kanban.setBoards(remoteContent);
kanban.inEditMode = false;
diff --git a/www/kanban/jkanban.js b/www/kanban/jkanban.js
index af127ff08..a9b199d4d 100644
--- a/www/kanban/jkanban.js
+++ b/www/kanban/jkanban.js
@@ -45,7 +45,6 @@
this.drake = '';
this.drakeBoard = '';
this.addItemButton = false;
- this.buttonContent = '+';
defaults = {
element: '',
gutter: '15px',
@@ -60,7 +59,6 @@
},
dragBoards: true,
addItemButton: false,
- buttonContent: '+',
readOnly: false,
dragEl: function (el, source) {},
dragendEl: function (el) {},
@@ -230,22 +228,14 @@ console.log(source, target, sourceId, targetId, board1, board2);
}
};
- this.addElement = function (boardID, element) {
-
- // add Element to JSON
- var boardJSON = __findBoardJSON(boardID);
- boardJSON.item.push({
- title: element.title
- });
- var board = self.element.querySelector('[data-id="' + boardID + '"] .kanban-drag');
+ var getElementNode = function (element) {
var nodeItem = document.createElement('div');
nodeItem.classList.add('kanban-item');
- if (element.id) {
- nodeItem.setAttribute('data-eid', element.id)
- }
+ nodeItem.dataset.eid = element.id;
var nodeItemText = document.createElement('div');
nodeItemText.classList.add('kanban-item-text');
- nodeItemText.innerHTML = element.title;
+ nodeItemText.dataset.eid = element.id;
+ nodeItemText.innerText = element.title;
nodeItem.appendChild(nodeItemText);
//add function
nodeItem.clickfn = element.click;
@@ -253,8 +243,21 @@ console.log(source, target, sourceId, targetId, board1, board2);
nodeItem.dragendfn = element.dragend;
nodeItem.dropfn = element.drop;
__onclickHandler(nodeItemText);
- __onColorClickHandler(nodeItem, "item");
- board.appendChild(nodeItem);
+ //__onColorClickHandler(nodeItem, "item");
+ return nodeItem;
+ };
+
+ this.addElement = function (boardID, element) {
+
+ // add Element to JSON
+ var boardJSON = __findBoardJSON(boardID);
+
+ boardJSON.item.push(element.id);
+ self.options.boards.items = self.options.boards.items || {};
+ self.options.boards.items[element.id] = element;
+
+ var board = self.element.querySelector('[data-id="' + boardID + '"] .kanban-drag');
+ board.appendChild(getElementNode(element));
// send event that board has changed
self.onChange();
return self;
@@ -266,15 +269,90 @@ console.log(source, target, sourceId, targetId, board1, board2);
return self;
};
-
- this.addBoards = function(boards) {
+ var getBoardNode = function (board) {
+ var boards = self.options.boards;
var boardWidth = self.options.widthBoard;
- var addButton = self.options.addItemButton;
- var buttonContent = self.options.buttonContent;
+ //create node
+ var boardNode = document.createElement('div');
+ boardNode.dataset.id = board.id;
+ boardNode.classList.add('kanban-board');
+ //set style
+ if (self.options.responsivePercentage) {
+ boardNode.style.width = boardWidth + '%';
+ } else {
+ boardNode.style.width = boardWidth;
+ }
+ boardNode.style.marginLeft = self.options.gutter;
+ boardNode.style.marginRight = self.options.gutter;
+ // header board
+ var headerBoard = document.createElement('header');
+ if (board.class !== '' && board.class !== undefined) {
+ var allClasses = board.class.split(",");
+ } else {
+ allClasses = [];
+ }
+ headerBoard.classList.add('kanban-board-header');
+ allClasses.map(function (value) {
+ headerBoard.classList.add(value);
+ });
+ if (board.color !== '' && board.color !== undefined) {
+ // XXX color
+ headerBoard.classList.add("kanban-header-" + board.color);
+ }
+ titleBoard = document.createElement('div');
+ titleBoard.classList.add('kanban-title-board');
+ titleBoard.innerText = board.title;
+ titleBoard.clickfn = board.boardTitleClick;
+ __onboardTitleClickHandler(titleBoard);
+ headerBoard.appendChild(titleBoard);
+ //content board
+ var contentBoard = document.createElement('main');
+ contentBoard.classList.add('kanban-drag');
+ //add drag to array for dragula
+ self.boardContainer.push(contentBoard);
+ (board.item || []).forEach(function (itemkey) {
+ //create item
+ var itemKanban = boards.items[itemkey];
+ if (!itemKanban) { return; } // XXX clean invalid data
+ var nodeItem = getElementNode(itemKanban);
+ contentBoard.appendChild(nodeItem);
+ });
+
+ //footer board
+ var footerBoard = document.createElement('footer');
+ footerBoard.classList.add('kanban-board-footer');
+ //add button
+ var addBoardItem = document.createElement('button');
+ $(addBoardItem).addClass("kanban-title-button btn btn-default fa fa-plus");
+ footerBoard.appendChild(addBoardItem);
+ __onAddItemClickHandler(addBoardItem);
+
+ //board assembly
+ boardNode.appendChild(headerBoard);
+ boardNode.appendChild(contentBoard);
+ boardNode.appendChild(footerBoard);
+
+ return boardNode;
+ };
+ this.addBoard = function (board) {
+ if (!board || !board.id) { return; }
+ var boards = self.options.boards;
+ boards.data = boards.data || {};
+ boards.list = boards.list || [];
+ // If it already there, abort
+ boards.data[board.id] = board;
+ if (boards.list.indexOf(board.id) !== -1) { return; }
+
+ boards.list.push(board.id);
+ var boardNode = getBoardNode(board);
+ self.container.appendChild(boardNode);
+ };
+
+ this.addBoards = function() {
//for on all the boards
- var old = self.options.boards;
+ var boards = self.options.boards;
boards.list = boards.list || [];
boards.data = boards.data || {};
for (var index in boards.list) {
@@ -283,111 +361,8 @@ console.log(source, target, sourceId, targetId, board1, board2);
var board = boards.data[boardkey];
if (!board) { continue; } // XXX clean invalid data
- // Remote changes, we had to reset our data
- if (old !== boards && old.list.indexOf(boardKey === -1)) {
- old.list.push(boardKey);
- }
+ var boardNode = getBoardNode(board);
- //create node
- var boardNode = document.createElement('div');
- boardNode.dataset.id = board.id;
- boardNode.classList.add('kanban-board');
- //set style
- if (self.options.responsivePercentage) {
- boardNode.style.width = boardWidth + '%';
- } else {
- boardNode.style.width = boardWidth;
- }
- boardNode.style.marginLeft = self.options.gutter;
- boardNode.style.marginRight = self.options.gutter;
- // header board
- var headerBoard = document.createElement('header');
- if (board.class !== '' && board.class !== undefined) {
- var allClasses = board.class.split(",");
- } else {
- allClasses = [];
- }
- headerBoard.classList.add('kanban-board-header');
- allClasses.map(function (value) {
- headerBoard.classList.add(value);
- });
- if (board.color !== '' && board.color !== undefined) {
- /*
- headerBoard._jscLinkedInstance = undefined;
- jscolorL = new jscolor(headerBoard,{showOnClick: false, valueElement:undefined});
- jscolorL.fromString(board.color);
- headerBoard._jscLinkedInstance = undefined;
- */
- // XXX fixed list of color: use class?
- headerBoard.classList.add("kanban-header-" + board.color);
- }
- titleBoard = document.createElement('div');
- titleBoard.classList.add('kanban-title-board');
- titleBoard.innerHTML = board.title;
- //titleBoard.setAttribute('title', board.title);
- titleBoard.clickfn = board.boardTitleClick;
- __onboardTitleClickHandler(titleBoard);
- headerBoard.appendChild(titleBoard);
- //__onColorClickHandler(headerBoard, "board"); // XXX color
-
- // add button to the board
- /* // XXX delete board button ==> removed
- var btn = document.createElement("BUTTON");
- btn.setAttribute("class", "kanban-title-button btn btn-default btn-xs fa fa-times");
- headerBoard.appendChild(btn);
- __onButtonClickHandler(btn, board.id);
- */
-
- //content board
- var contentBoard = document.createElement('main');
- contentBoard.classList.add('kanban-drag');
- //add drag to array for dragula
- self.boardContainer.push(contentBoard);
- (board.item || []).forEach(function (itemkey) {
- //create item
- var itemKanban = boards.items[itemkey];
- if (!itemKanban) { return; } // XXX clean invalid data
- var nodeItem = document.createElement('div');
- nodeItem.classList.add('kanban-item');
- nodeItem.dataset.eid = itemKanban.id;
- var nodeItemText = document.createElement('div');
- nodeItemText.classList.add('kanban-item-text');
- nodeItemText.dataset.eid = itemKanban.id;
- nodeItemText.innerHTML = itemKanban.title;
- nodeItem.appendChild(nodeItemText);
- //add function
- nodeItemText.clickfn = itemKanban.click;
- nodeItemText.dragfn = itemKanban.drag;
- nodeItemText.dragendfn = itemKanban.dragend;
- nodeItemText.dropfn = itemKanban.drop;
- //add click handler of item
- __onclickHandler(nodeItemText);
- /*
- // XXX color handle color differently
- if (itemKanban.color !== '' && itemKanban.color !== undefined) {
- jscolorL = new jscolor(nodeItem,{
- showOnClick: false, valueElement:undefined
- });
- jscolorL.fromString(itemKanban.color);
- }*/
- //__onColorClickHandler(nodeItem, "item"); // XXX color
-
- contentBoard.appendChild(nodeItem);
- });
-
- //footer board
- var footerBoard = document.createElement('footer');
- footerBoard.classList.add('kanban-board-footer');
- //add button
- var addBoardItem = document.createElement('button');
- $(addBoardItem).addClass("kanban-title-button btn btn-default fa fa-plus");
- footerBoard.appendChild(addBoardItem);
- __onAddItemClickHandler(addBoardItem);
-
- //board assembly
- boardNode.appendChild(headerBoard);
- boardNode.appendChild(contentBoard);
- boardNode.appendChild(footerBoard);
//board add
self.container.appendChild(boardNode);
}
@@ -400,16 +375,12 @@ console.log(source, target, sourceId, targetId, board1, board2);
this.setBoards = function (boards) {
//self.element
- for (var boardkey in this.options.boards.list) {
- //var board = this.options.boards[boardkey];
- this.removeBoard(boardKey);
+ for (var i in this.options.boards.list) {
+ var boardkey = boards.list[i];
+ this.removeBoard(boardkey);
}
- this.options.boards = {
- list: [],
- data: boards.data || {},
- items: boards.items || {}
- };
- this.addBoards(boards);
+ this.options.boards = boards;
+ this.addBoards();
}
this.findBoard = function (id) {
@@ -472,6 +443,9 @@ console.log(source, target, sourceId, targetId, board1, board2);
this.getBoardJSON = function (id) {
return __findBoardJSON(id);
}
+ this.getItemJSON = function (id) {
+ return (self.options.boards.items || {})[id];
+ };
//PRIVATE FUNCTION
function __extendDefaults(source, properties) {
@@ -499,7 +473,7 @@ console.log(source, target, sourceId, targetId, board1, board2);
self.container = boardContainer;
//add boards
- self.addBoards(self.options.boards);
+ self.addBoards();
//appends to container
self.element.appendChild(boardContainerOuter);