From 2e81605c95fb948613e5f8fc5c64cd1e2097a88a Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 28 Feb 2020 15:43:01 +0100 Subject: [PATCH 01/31] New kanban structure with drag&drop support --- www/kanban/inner.js | 72 ++++++++------- www/kanban/jkanban.js | 205 +++++++++++++++++++----------------------- 2 files changed, 133 insertions(+), 144 deletions(-) diff --git a/www/kanban/inner.js b/www/kanban/inner.js index 621d56cae..c764927bc 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -39,9 +39,8 @@ define([ $container.find('.kanban-remove-item').remove(); $container.find('.kanban-board .kanban-item').each(function (i, el) { var pos = kanban.findElementPosition(el); - var board = kanban.options.boards.find(function (b) { - return b.id === $(el.parentNode.parentNode).attr('data-id'); - }); + var boards = kanban.options.boards; + var board = boards.data[$(el.parentNode.parentNode).attr('data-id')]; $('' - 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); - for (var itemkey in board.item) { + (board.item || []).forEach(function (itemkey) { //create item - var itemKanban = board.item[itemkey]; + 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; @@ -387,24 +362,32 @@ 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"); + 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"); - headerBoard.appendChild(addBoardItem); + footerBoard.appendChild(addBoardItem); __onAddItemClickHandler(addBoardItem); //board assembly boardNode.appendChild(headerBoard); boardNode.appendChild(contentBoard); + boardNode.appendChild(footerBoard); //board add self.container.appendChild(boardNode); } @@ -416,12 +399,16 @@ } this.setBoards = function (boards) { - self.element - for (var boardkey in this.options.boards) { - var board = this.options.boards[boardkey]; - this.removeBoard(board.id); + //self.element + for (var boardkey in this.options.boards.list) { + //var board = this.options.boards[boardkey]; + this.removeBoard(boardKey); } - this.options.boards = []; + this.options.boards = { + list: [], + data: boards.data || {}, + items: boards.items || {} + }; this.addBoards(boards); } @@ -508,13 +495,13 @@ var addBoard = document.createElement('div'); addBoard.id = 'kanban-addboard'; addBoard.setAttribute('class', 'fa fa-plus'); + boardContainer.appendChild(addBoard); self.container = boardContainer; //add boards self.addBoards(self.options.boards); //appends to container self.element.appendChild(boardContainerOuter); - self.element.appendChild(addBoard); // send event that board has changed self.onChange(); @@ -571,13 +558,7 @@ } function __findBoardJSON(id) { - var el = [] - self.options.boards.map(function (board) { - if (board.id === id) { - return el.push(board) - } - }) - return el[0] + return (self.options.boards.data || {})[id]; } From 0b5f76d471455ffc3da1e8f78764b9905d3a48b4 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 28 Feb 2020 18:32:15 +0100 Subject: [PATCH 02/31] Fix issues with the new structure and better restoreCursor --- www/kanban/app-kanban.less | 1 + www/kanban/inner.js | 139 ++++++++++----------- www/kanban/jkanban.js | 244 +++++++++++++++++-------------------- 3 files changed, 180 insertions(+), 204 deletions(-) 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); From 889b18a1ff16a48093385c1987b016d989e5991e Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 2 Mar 2020 12:05:09 +0100 Subject: [PATCH 03/31] Drag to remove --- www/kanban/app-kanban.less | 19 +++++++++++++ www/kanban/inner.js | 54 ++++++++++++++++++++++++++++--------- www/kanban/jkanban.css | 2 ++ www/kanban/jkanban.js | 55 +++++++++++++++++++++++++++++--------- 4 files changed, 104 insertions(+), 26 deletions(-) diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less index e1f5ab274..615a5c904 100644 --- a/www/kanban/app-kanban.less +++ b/www/kanban/app-kanban.less @@ -45,6 +45,23 @@ justify-content: space-around; } } + #kanban-trash { + width: 100px; + height: 100px; + align-self: end; + font-size: 40px; + display: flex; + align-items: center; + justify-content: center; + &.kanban-trash-active { + color: red; + border: 1px solid red; + background-color: rgba(255,0,0,0.5); + } + .kanban-item, .kanban-board { + display: none; + } + } .kanban-item { display: flex; @@ -103,6 +120,7 @@ .tools_unselectable(); } +/* .kanban-remove-item { padding: 0 0.5em; visibility: hidden; @@ -112,6 +130,7 @@ visibility: visible; } } +*/ .kanban-additem { float: right; diff --git a/www/kanban/inner.js b/www/kanban/inner.js index 6b041c44d..6a1448009 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -32,28 +32,37 @@ define([ var COLORS = ['yellow', 'green', 'orange', 'blue', 'red', 'purple', 'cyan', 'lightgreen', 'lightblue']; - var addRemoveItemButton = function (framework, kanban) { + var addEditItemButton = function (framework, kanban) { if (!kanban) { return; } if (framework.isReadOnly() || framework.isLocked()) { return; } var $container = $(kanban.element); - $container.find('.kanban-remove-item').remove(); - $container.find('.kanban-board .kanban-item').each(function (i, el) { - var pos = kanban.findElementPosition(el); - var boards = kanban.options.boards; - var board = boards.data[$(el.parentNode.parentNode).attr('data-id')]; + $container.find('.kanban-edit-item').remove(); + $container.find('.kanban-item').each(function (i, el) { + var itemId = $(el).attr('data-eid'); $('