1810 lines
74 KiB
JavaScript
1810 lines
74 KiB
JavaScript
(function e(t, n, r) {
|
||
function s(o, u) {
|
||
if (!n[o]) {
|
||
if (!t[o]) {
|
||
var a = typeof require == "function" && require;
|
||
if (!u && a) return a(o, !0);
|
||
if (i) return i(o, !0);
|
||
var f = new Error("Cannot find module '" + o + "'");
|
||
throw f.code = "MODULE_NOT_FOUND", f
|
||
}
|
||
var l = n[o] = {
|
||
exports: {}
|
||
};
|
||
t[o][0].call(l.exports, function (e) {
|
||
var n = t[o][1][e];
|
||
return s(n ? n : e)
|
||
}, l, l.exports, e, t, n, r)
|
||
}
|
||
return n[o].exports
|
||
}
|
||
var i = typeof require == "function" && require;
|
||
for (var o = 0; o < r.length; o++) s(r[o]);
|
||
return s
|
||
})({
|
||
1: [function (require, module, exports) {
|
||
/**
|
||
* jKanban
|
||
* Vanilla Javascript plugin for manage kanban boards
|
||
*
|
||
* @site: http://www.riccardotartaglia.it/jkanban/
|
||
* @author: Riccardo Tartaglia
|
||
*/
|
||
|
||
//Require dragula
|
||
var dragula = require('dragula');
|
||
|
||
(function () {
|
||
|
||
this.jKanban = function () {
|
||
var self = this;
|
||
this.element = '';
|
||
this.container = '';
|
||
this.boardContainer = [];
|
||
this.dragula = dragula;
|
||
this.drake = '';
|
||
this.drakeBoard = '';
|
||
this.addItemButton = false;
|
||
defaults = {
|
||
element: '',
|
||
gutter: '15px',
|
||
widthBoard: '250px',
|
||
responsive: '700',
|
||
responsivePercentage: false,
|
||
boards: {
|
||
data: {},
|
||
items: {},
|
||
list: []
|
||
},
|
||
getAvatar: function () {},
|
||
openLink: function () {},
|
||
getTags: function () {},
|
||
getTextColor: function () { return '#000'; },
|
||
cursors: {},
|
||
tags: [],
|
||
dragBoards: true,
|
||
addItemButton: false,
|
||
readOnly: false,
|
||
dragEl: function (el, source) {},
|
||
dragendEl: function (el) {},
|
||
dropEl: function (el, target, source, sibling) {},
|
||
dragcancelEl: function (el, boardId) {},
|
||
dragBoard: function (el, source) {},
|
||
dragendBoard: function (el) {},
|
||
dropBoard: function (el, target, source, sibling) {},
|
||
click: function (el) {},
|
||
boardTitleclick: function (el, boardId) {},
|
||
addItemClick: function (el, boardId) {},
|
||
renderMd: function (md) {},
|
||
refresh: function () {},
|
||
onChange: function () {}
|
||
};
|
||
|
||
if (arguments[0] && typeof arguments[0] === "object") {
|
||
this.options = __extendDefaults(defaults, arguments[0]);
|
||
}
|
||
|
||
var removeUnusedTags = function (boards) {
|
||
var tags = self.options.getTags(boards);
|
||
var filter = self.options.tags || [];
|
||
var toClean = [];
|
||
filter.forEach(function (tag) {
|
||
if (tags.indexOf(tag) === -1) { toClean.push(tag); }
|
||
});
|
||
toClean.forEach(function (t) {
|
||
var idx = filter.indexOf(t);
|
||
if (idx === -1) { return; }
|
||
filter.splice(idx, 1);
|
||
});
|
||
// If all the tags have bene remove, make sure we show everything again
|
||
if (!filter.length) {
|
||
$('.kanban-item-hidden').removeClass('kanban-item-hidden');
|
||
}
|
||
};
|
||
|
||
this.init = function () {
|
||
// set initial boards
|
||
__setBoard();
|
||
|
||
// Scroll on drag
|
||
var $el = $(self.element)
|
||
var $inner = $el.find('.kanban-container');
|
||
var leftRegion = $el.position().left + 10;
|
||
var rightRegion = $(window).width() - 10;
|
||
var activeBoard;
|
||
var $aB;
|
||
var setActiveDrag = function (board) {
|
||
activeBoard = undefined;
|
||
if (!board) { return; }
|
||
if (!board.classList.contains('kanban-drag')) { return; }
|
||
activeBoard = board;
|
||
$aB = $(activeBoard);
|
||
};
|
||
var onMouseMove = function (isItem) {
|
||
return function (e) {
|
||
if (e.which !== 1) { return; } // left click
|
||
var distance = 20;
|
||
// If this is an item drag, check scroll
|
||
if (isItem && activeBoard) {
|
||
var rect = activeBoard.getBoundingClientRect();
|
||
if (e.pageX > rect.left && e.pageX < rect.right) {
|
||
if (e.pageY < (rect.top + 10)) {
|
||
distance *= -1;
|
||
$aB.scrollTop(distance + $aB.scrollTop()) ;
|
||
} else if (e.pageY > (rect.bottom - 10)) {
|
||
$aB.scrollTop(distance + $aB.scrollTop()) ;
|
||
}
|
||
}
|
||
}
|
||
// Itme or board: horizontal scroll if needed
|
||
if (e.pageX < leftRegion) {
|
||
distance *= -1;
|
||
$el.scrollLeft(distance + $el.scrollLeft()) ;
|
||
} else if (e.pageX >= rightRegion) {
|
||
$el.scrollLeft(distance + $el.scrollLeft()) ;
|
||
}
|
||
};
|
||
};
|
||
|
||
//set drag with dragula
|
||
if (window.innerWidth > self.options.responsive) {
|
||
|
||
//Init Drag Board
|
||
self.drakeBoard = self.dragula([self.container, self.trashContainer], {
|
||
moves: function (el, source, handle, sibling) {
|
||
if (self.options.readOnly) { return false; }
|
||
if (!self.options.dragBoards) { return false; }
|
||
return (handle.classList.contains('kanban-board-header') || handle.classList.contains('kanban-title-board'));
|
||
},
|
||
accepts: function (el, target, source, sibling) {
|
||
if (self.options.readOnly) { return false; }
|
||
if (sibling && sibling.getAttribute('id') === "kanban-addboard") { return false; }
|
||
return target.classList.contains('kanban-container') ||
|
||
target.classList.contains('kanban-trash');
|
||
},
|
||
revertOnSpill: true,
|
||
direction: 'horizontal',
|
||
})
|
||
.on('drag', function (el, source) {
|
||
el.classList.add('is-moving');
|
||
self.options.dragBoard(el, source);
|
||
if (typeof (el.dragfn) === 'function') {
|
||
el.dragfn(el, source);
|
||
}
|
||
$(document).on('mousemove', onMouseMove());
|
||
})
|
||
.on('dragend', function (el) {
|
||
el.classList.remove('is-moving');
|
||
self.options.dragendBoard(el);
|
||
$(document).off('mousemove');
|
||
if (typeof (el.dragendfn) === 'function')
|
||
el.dragendfn(el);
|
||
})
|
||
.on('over', function (el, target, source) {
|
||
if (!target.classList.contains('kanban-trash')) { return false; }
|
||
$('.kanban-trash').addClass('kanban-trash-active');
|
||
})
|
||
.on('out', function (el, target) {
|
||
if (!target.classList.contains('kanban-trash')) { return false; }
|
||
$('.kanban-trash').removeClass('kanban-trash-active');
|
||
})
|
||
.on('drop', function (el, target, source, sibling) {
|
||
el.classList.remove('is-moving');
|
||
self.options.dropBoard(el, target, source, sibling);
|
||
if (typeof (el.dropfn) === 'function') {
|
||
el.dropfn(el, target, source, sibling);
|
||
}
|
||
|
||
var id = Number($(el).attr('data-id'));
|
||
var list = self.options.boards.list || [];
|
||
|
||
var index1 = list.indexOf(id);
|
||
if (index1 === -1) { return; }
|
||
|
||
// Move to trash?
|
||
if (target.classList.contains('kanban-trash')) {
|
||
list.splice(index1, 1);
|
||
delete self.options.boards.data[id];
|
||
self.onChange();
|
||
return;
|
||
}
|
||
|
||
var index2;
|
||
var id2 = Number($(sibling).attr("data-id"));
|
||
if (sibling && id2) {
|
||
index2 = list.indexOf(id2);
|
||
}
|
||
// If we can't find the drop position, drop at the end
|
||
if (typeof(index2) === "undefined" || index2 === -1) {
|
||
index2 = list.length;
|
||
}
|
||
|
||
console.log("Switch " + index1 + " and " + index2);
|
||
if (index1 < index2) {
|
||
index2 = index2 - 1;
|
||
}
|
||
list.splice(index1, 1);
|
||
list.splice(index2, 0, id);
|
||
// send event that board has changed
|
||
self.onChange();
|
||
self.setBoards(self.options.boards);
|
||
});
|
||
|
||
//Init Drag Item
|
||
self.drake = self.dragula(self.boardContainer, {
|
||
moves: function (el, source, handle, sibling) {
|
||
if (self.options.readOnly) { return false; }
|
||
if (el.classList.contains('new-item')) { return false; }
|
||
return el.classList.contains('kanban-item');
|
||
},
|
||
accepts: function (el, target, source, sibling) {
|
||
if (self.options.readOnly) { return false; }
|
||
return true;
|
||
},
|
||
revertOnSpill: true
|
||
})
|
||
.on('cancel', function(el, container, source) {
|
||
self.enableAllBoards();
|
||
})
|
||
.on('drag', function (el, source) {
|
||
// we need to calculate the position before starting to drag
|
||
self.dragItemPos = self.findElementPosition(el);
|
||
|
||
setActiveDrag();
|
||
el.classList.add('is-moving');
|
||
$(document).on('mousemove', onMouseMove(el));
|
||
|
||
self.options.dragEl(el, source);
|
||
if (el !== null && typeof (el.dragfn) === 'function') {
|
||
el.dragfn(el, source);
|
||
}
|
||
})
|
||
.on('dragend', function (el) {
|
||
console.log("In dragend");
|
||
el.classList.remove('is-moving');
|
||
self.options.dragendEl(el);
|
||
$(document).off('mousemove');
|
||
if (el !== null && typeof (el.dragendfn) === 'function') {
|
||
el.dragendfn(el);
|
||
}
|
||
})
|
||
.on('cancel', function (el, container, source) {
|
||
console.log("In cancel");
|
||
el.classList.remove('is-moving');
|
||
var boardId = $(source).closest('kanban-board').data('id');
|
||
self.options.dragcancelEl(el, boardId);
|
||
})
|
||
.on('over', function (el, target, source) {
|
||
setActiveDrag(target);
|
||
if (!target.classList.contains('kanban-trash')) { return false; }
|
||
target.classList.add('kanban-trash-active');
|
||
})
|
||
.on('out', function (el, target) {
|
||
setActiveDrag();
|
||
if (!target.classList.contains('kanban-trash')) { return false; }
|
||
target.classList.remove('kanban-trash-active');
|
||
})
|
||
.on('drop', function(el, target, source, sibling) {
|
||
self.enableAllBoards();
|
||
el.classList.remove('is-moving');
|
||
|
||
console.log("In drop");
|
||
|
||
var id1 = Number($(el).attr('data-eid'));
|
||
|
||
// Move to trash?
|
||
if (target.classList.contains('kanban-trash')) {
|
||
self.moveItem(id1);
|
||
self.onChange();
|
||
return;
|
||
}
|
||
|
||
// Find the new board
|
||
var targetId = Number($(target).closest('.kanban-board').data('id'));
|
||
if (!targetId) { return; }
|
||
var board2 = __findBoardJSON(targetId);
|
||
var id2 = $(sibling).attr('data-eid');
|
||
if (id2) { id2 = Number(id2); }
|
||
var pos2 = id2 ? board2.item.indexOf(id2) : board2.item.length;
|
||
if (pos2 === -1) { pos2 = board2.item.length; }
|
||
|
||
// Remove the "move" effect
|
||
if (el !== null) {
|
||
el.classList.remove('is-moving');
|
||
}
|
||
|
||
// Move the item
|
||
self.moveItem(id1, board2, pos2);
|
||
|
||
// send event that board has changed
|
||
self.onChange();
|
||
self.setBoards(self.options.boards);
|
||
})
|
||
}
|
||
};
|
||
|
||
var findItem = function (eid) {
|
||
var boards = self.options.boards;
|
||
var list = boards.list || [];
|
||
var res = [];
|
||
list.forEach(function (id) {
|
||
var b = boards.data[id];
|
||
if (!b) { return; }
|
||
var items = b.item || [];
|
||
var idx = items.indexOf(eid);
|
||
if (idx === -1) { return; }
|
||
// This board contains our item...
|
||
res.push({
|
||
board: b,
|
||
pos: idx
|
||
});
|
||
});
|
||
return res;
|
||
};
|
||
this.moveItem = function (eid, board, pos) {
|
||
var boards = self.options.boards;
|
||
var list = boards.list || [];
|
||
var from = [];
|
||
var same = -1;
|
||
var from = findItem(eid);
|
||
// Remove the item from its board
|
||
from.forEach(function (obj) {
|
||
obj.board.item.splice(obj.pos, 1);
|
||
if (obj.board === board) { same = obj.pos; }
|
||
});
|
||
// If it's a deletion, remove the item data
|
||
if (!board) {
|
||
delete boards.items[eid];
|
||
removeUnusedTags(boards);
|
||
self.options.refresh();
|
||
return;
|
||
}
|
||
// If it's moved to the same board at a bigger index, decrement the index by one
|
||
// (we just removed one element)
|
||
if (same !== -1 && same < pos) {
|
||
pos = pos - 1;
|
||
}
|
||
board.item.splice(pos, 0, eid);
|
||
};
|
||
|
||
this.enableAllBoards = function() {
|
||
var allB = document.querySelectorAll('.kanban-board');
|
||
if (allB.length > 0 && allB !== undefined) {
|
||
for (var i = 0; i < allB.length; i++) {
|
||
allB[i].classList.remove('disabled-board');
|
||
}
|
||
}
|
||
};
|
||
|
||
var getElementNode = function (element) {
|
||
var nodeItem = document.createElement('div');
|
||
nodeItem.classList.add('kanban-item');
|
||
nodeItem.dataset.eid = element.id;
|
||
if (element.color) {
|
||
if (/color/.test(element.color)) {
|
||
// Palette color
|
||
nodeItem.classList.add('cp-kanban-palette-'+element.color);
|
||
} else {
|
||
// Hex color code
|
||
var textColor = self.options.getTextColor(element.color);
|
||
nodeItem.setAttribute('style', 'background-color:#'+element.color+';color:'+textColor+';');
|
||
}
|
||
}
|
||
var nodeCursors = document.createElement('div');
|
||
nodeCursors.classList.add('cp-kanban-cursors');
|
||
Object.keys(self.options.cursors).forEach(function (id) {
|
||
var c = self.options.cursors[id];
|
||
if (Number(c.item) !== Number(element.id)) { return; }
|
||
var el = self.options.getAvatar(c);
|
||
nodeCursors.appendChild(el);
|
||
});
|
||
var nodeItemText = document.createElement('div');
|
||
nodeItemText.classList.add('kanban-item-text');
|
||
nodeItemText.dataset.eid = element.id;
|
||
nodeItemText.innerText = element.title;
|
||
nodeItem.appendChild(nodeItemText);
|
||
// Check if this card is filtered out
|
||
if (Array.isArray(self.options.tags) && self.options.tags.length) {
|
||
var hide = !Array.isArray(element.tags) ||
|
||
!element.tags.some(function (tag) {
|
||
return self.options.tags.indexOf(tag) !== -1;
|
||
});
|
||
if (hide) {
|
||
nodeItem.classList.add('kanban-item-hidden');
|
||
}
|
||
}
|
||
if (element.body) {
|
||
var html = self.renderMd(element.body);
|
||
var nodeBody = document.createElement('div');
|
||
nodeBody.classList.add('kanban-item-body');
|
||
$(nodeBody).on('click', 'a', function (e) {
|
||
e.preventDefault();
|
||
var a = e.target;
|
||
if (!a.href) { return; }
|
||
self.options.openLink(a.href);
|
||
});
|
||
nodeBody.onclick = function (e) {
|
||
e.preventDefault();
|
||
};
|
||
nodeBody.innerHTML = html;
|
||
nodeItem.appendChild(nodeBody);
|
||
}
|
||
if (Array.isArray(element.tags)) {
|
||
var nodeTags = document.createElement('div');
|
||
nodeTags.classList.add('kanban-item-tags');
|
||
element.tags.forEach(function (_tag) {
|
||
var tag = document.createElement('span');
|
||
tag.innerText = _tag;
|
||
nodeTags.appendChild(tag);
|
||
});
|
||
nodeItem.appendChild(nodeTags);
|
||
}
|
||
nodeItem.appendChild(nodeCursors);
|
||
//add function
|
||
nodeItem.clickfn = element.click;
|
||
nodeItem.dragfn = element.drag;
|
||
nodeItem.dragendfn = element.dragend;
|
||
nodeItem.dropfn = element.drop;
|
||
__onclickHandler(nodeItemText);
|
||
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;
|
||
};
|
||
|
||
this.addForm = function (boardID, formItem) {
|
||
var board = self.element.querySelector('[data-id="' + boardID + '"] .kanban-drag');
|
||
board.appendChild(formItem);
|
||
return self;
|
||
};
|
||
|
||
var getBoardNode = function (board) {
|
||
var boards = self.options.boards;
|
||
var boardWidth = self.options.widthBoard;
|
||
//create node
|
||
var boardNode = document.createElement('div');
|
||
boardNode.dataset.id = board.id;
|
||
boardNode.classList.add('kanban-board');
|
||
var boardNodeInner = document.createElement('div');
|
||
boardNodeInner.classList.add('kanban-board-inner');
|
||
//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) {
|
||
if (/color/.test(board.color)) {
|
||
// Palette color
|
||
headerBoard.classList.add('cp-kanban-palette-'+board.color);
|
||
boardNodeInner.classList.add('cp-kanban-palette-'+board.color);
|
||
} else if (!/^[0-9a-f]{6}$/.test(board.color)) {
|
||
// "string" color (red, blue, etc.)
|
||
headerBoard.classList.add("kanban-header-" + board.color);
|
||
} else {
|
||
// Hex color code
|
||
var textColor = self.options.getTextColor(board.color);
|
||
headerBoard.setAttribute('style', 'background-color:#'+board.color+';color:'+textColor+';');
|
||
}
|
||
}
|
||
|
||
titleBoard = document.createElement('div');
|
||
titleBoard.classList.add('kanban-title-board');
|
||
titleBoard.innerText = board.title;
|
||
|
||
titleBoard.clickfn = board.boardTitleClick;
|
||
__onboardTitleClickHandler(titleBoard);
|
||
headerBoard.appendChild(titleBoard);
|
||
|
||
var nodeCursors = document.createElement('div');
|
||
nodeCursors.classList.add('cp-kanban-cursors');
|
||
Object.keys(self.options.cursors).forEach(function (id) {
|
||
var c = self.options.cursors[id];
|
||
if (Number(c.board) !== Number(board.id)) { return; }
|
||
var el = self.options.getAvatar(c);
|
||
nodeCursors.appendChild(el);
|
||
});
|
||
headerBoard.appendChild(nodeCursors);
|
||
|
||
//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('span');
|
||
addBoardItem.classList.add('kanban-title-button');
|
||
addBoardItem.innerText = '+';
|
||
footerBoard.appendChild(addBoardItem);
|
||
__onAddItemClickHandler(addBoardItem);
|
||
|
||
//board assembly
|
||
boardNode.appendChild(boardNodeInner);
|
||
boardNodeInner.appendChild(headerBoard);
|
||
boardNodeInner.appendChild(contentBoard);
|
||
boardNodeInner.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 boards = self.options.boards;
|
||
boards.list = boards.list || [];
|
||
boards.data = boards.data || {};
|
||
for (var index in boards.list) {
|
||
// single board
|
||
var boardkey = boards.list[index];
|
||
var board = boards.data[boardkey];
|
||
if (!board) { continue; } // XXX clean invalid data
|
||
|
||
var boardNode = getBoardNode(board);
|
||
|
||
//board add
|
||
self.container.appendChild(boardNode);
|
||
}
|
||
|
||
// send event that board has changed
|
||
self.onChange();
|
||
|
||
return self;
|
||
}
|
||
|
||
this.setBoards = function (boards) {
|
||
var scroll = {};
|
||
// Fix the tags
|
||
removeUnusedTags(boards);
|
||
// Remove all boards
|
||
for (var i in this.options.boards.list) {
|
||
var boardkey = this.options.boards.list[i];
|
||
scroll[boardkey] = $('.kanban-board[data-id="'+boardkey+'"] .kanban-drag').scrollTop();
|
||
this.removeBoard(boardkey);
|
||
}
|
||
this.options.boards = boards;
|
||
// Add all new boards
|
||
this.addBoards();
|
||
self.options.refresh();
|
||
// Preserve scroll
|
||
this.options.boards.list.forEach(function (id) {
|
||
if (!scroll[id]) { return; }
|
||
$('.kanban-board[data-id="'+id+'"] .kanban-drag').scrollTop(scroll[id]);
|
||
});
|
||
}
|
||
|
||
this.findBoard = function (id) {
|
||
var el = self.element.querySelector('[data-id="' + id + '"]');
|
||
return el;
|
||
}
|
||
|
||
this.findElement = function (id) {
|
||
var el = self.element.querySelector('[data-eid="' + id + '"]');
|
||
return el;
|
||
}
|
||
|
||
this.findElementPosition = function (el) {
|
||
// we are looking at the element position in the child array
|
||
return $(el.parentNode.children).index(el);
|
||
}
|
||
|
||
this.getBoardElements = function (id) {
|
||
var board = self.element.querySelector('[data-id="' + id + '"] .kanban-drag');
|
||
return (board.childNodes);
|
||
}
|
||
|
||
this.removeElement = function (el) {
|
||
if (typeof (el) === 'string')
|
||
el = self.element.querySelector('[data-eid="' + el + '"]');
|
||
el.remove();
|
||
|
||
// send event that board has changed
|
||
self.onChange();
|
||
|
||
return self;
|
||
};
|
||
|
||
this.removeBoard = function (board) {
|
||
var id;
|
||
if (typeof (board) === 'string' || typeof (board) === "number") {
|
||
id = board;
|
||
board = self.element.querySelector('[data-id="' + board + '"]');
|
||
} else if (board) {
|
||
id = board.id;
|
||
}
|
||
if (board) {
|
||
board.remove();
|
||
|
||
// send event that board has changed
|
||
self.onChange();
|
||
}
|
||
|
||
// Remove duplicates
|
||
if (id) { $(self.element).find('.kanban-board[data-id="' + board + '"]').remove(); }
|
||
|
||
return self;
|
||
}
|
||
|
||
this.renderMd = function (md) {
|
||
return self.options.renderMd(md);
|
||
}
|
||
this.onChange = function () {
|
||
self.options.onChange();
|
||
}
|
||
|
||
this.getBoardsJSON = function (id) {
|
||
return self.options.boards;
|
||
}
|
||
|
||
this.getBoardJSON = function (id) {
|
||
return __findBoardJSON(id);
|
||
}
|
||
this.getItemJSON = function (id) {
|
||
return (self.options.boards.items || {})[id];
|
||
};
|
||
|
||
//PRIVATE FUNCTION
|
||
function __extendDefaults(source, properties) {
|
||
var property;
|
||
for (property in properties) {
|
||
if (properties.hasOwnProperty(property)) {
|
||
source[property] = properties[property];
|
||
}
|
||
}
|
||
return source;
|
||
}
|
||
|
||
function __setBoard() {
|
||
self.element = document.querySelector(self.options.element);
|
||
//create container
|
||
var boardContainerOuter = document.createElement('div');
|
||
boardContainerOuter.classList.add('kanban-container-outer');
|
||
var boardContainer = document.createElement('div');
|
||
boardContainer.classList.add('kanban-container');
|
||
boardContainerOuter.appendChild(boardContainer);
|
||
var addBoard = document.createElement('div');
|
||
addBoard.id = 'kanban-addboard';
|
||
addBoard.innerText = '+';
|
||
boardContainer.appendChild(addBoard);
|
||
var trash = self.trashContainer = document.createElement('div');
|
||
trash.setAttribute('id', 'kanban-trash');
|
||
trash.setAttribute('class', 'kanban-trash');
|
||
var trashBg = document.createElement('div');
|
||
var trashIcon = document.createElement('i');
|
||
trashIcon.setAttribute('class', 'fa fa-trash');
|
||
trash.appendChild(trashIcon);
|
||
trash.appendChild(trashBg);
|
||
self.boardContainer.push(trash);
|
||
|
||
self.container = boardContainer;
|
||
//add boards
|
||
self.addBoards();
|
||
//appends to container
|
||
self.element.appendChild(boardContainerOuter);
|
||
self.element.appendChild(trash);
|
||
|
||
// send event that board has changed
|
||
self.onChange();
|
||
};
|
||
|
||
function __onclickHandler(nodeItem, clickfn) {
|
||
nodeItem.addEventListener('click', function (e) {
|
||
e.preventDefault;
|
||
e.stopPropagation();
|
||
self.options.click(this);
|
||
if (typeof (this.clickfn) === 'function')
|
||
this.clickfn(this);
|
||
});
|
||
}
|
||
|
||
function __onboardTitleClickHandler(nodeItem, clickfn) {
|
||
nodeItem.addEventListener('click', function (e) {
|
||
e.preventDefault;
|
||
self.options.boardTitleClick(this, e);
|
||
if (typeof (this.clickfn) === 'function')
|
||
this.clickfn(this);
|
||
});
|
||
}
|
||
|
||
function __onAddItemClickHandler(nodeItem, clickfn) {
|
||
nodeItem.addEventListener('click', function (e) {
|
||
e.preventDefault;
|
||
e.stopPropagation();
|
||
self.options.addItemClick(this);
|
||
if (typeof (this.clickfn) === 'function')
|
||
this.clickfn(this);
|
||
});
|
||
}
|
||
|
||
function __findBoardJSON(id) {
|
||
return (self.options.boards.data || {})[id];
|
||
}
|
||
|
||
|
||
//init plugin
|
||
this.init();
|
||
};
|
||
}());
|
||
|
||
|
||
}, {
|
||
"dragula": 9
|
||
}],
|
||
2: [function (require, module, exports) {
|
||
module.exports = function atoa(a, n) {
|
||
return Array.prototype.slice.call(a, n);
|
||
}
|
||
|
||
}, {}],
|
||
3: [function (require, module, exports) {
|
||
'use strict';
|
||
|
||
var ticky = require('ticky');
|
||
|
||
module.exports = function debounce(fn, args, ctx) {
|
||
if (!fn) {
|
||
return;
|
||
}
|
||
ticky(function run() {
|
||
fn.apply(ctx || null, args || []);
|
||
});
|
||
};
|
||
|
||
}, {
|
||
"ticky": 10
|
||
}],
|
||
4: [function (require, module, exports) {
|
||
'use strict';
|
||
|
||
var atoa = require('atoa');
|
||
var debounce = require('./debounce');
|
||
|
||
module.exports = function emitter(thing, options) {
|
||
var opts = options || {};
|
||
var evt = {};
|
||
if (thing === undefined) {
|
||
thing = {};
|
||
}
|
||
thing.on = function (type, fn) {
|
||
if (!evt[type]) {
|
||
evt[type] = [fn];
|
||
} else {
|
||
evt[type].push(fn);
|
||
}
|
||
return thing;
|
||
};
|
||
thing.once = function (type, fn) {
|
||
fn._once = true; // thing.off(fn) still works!
|
||
thing.on(type, fn);
|
||
return thing;
|
||
};
|
||
thing.off = function (type, fn) {
|
||
var c = arguments.length;
|
||
if (c === 1) {
|
||
delete evt[type];
|
||
} else if (c === 0) {
|
||
evt = {};
|
||
} else {
|
||
var et = evt[type];
|
||
if (!et) {
|
||
return thing;
|
||
}
|
||
et.splice(et.indexOf(fn), 1);
|
||
}
|
||
return thing;
|
||
};
|
||
thing.emit = function () {
|
||
var args = atoa(arguments);
|
||
return thing.emitterSnapshot(args.shift()).apply(this, args);
|
||
};
|
||
thing.emitterSnapshot = function (type) {
|
||
var et = (evt[type] || []).slice(0);
|
||
return function () {
|
||
var args = atoa(arguments);
|
||
var ctx = this || thing;
|
||
if (type === 'error' && opts.throws !== false && !et.length) {
|
||
throw args.length === 1 ? args[0] : args;
|
||
}
|
||
et.forEach(function emitter(listen) {
|
||
if (opts.async) {
|
||
debounce(listen, args, ctx);
|
||
} else {
|
||
listen.apply(ctx, args);
|
||
}
|
||
if (listen._once) {
|
||
thing.off(type, listen);
|
||
}
|
||
});
|
||
return thing;
|
||
};
|
||
};
|
||
return thing;
|
||
};
|
||
|
||
}, {
|
||
"./debounce": 3,
|
||
"atoa": 2
|
||
}],
|
||
5: [function (require, module, exports) {
|
||
(function (global) {
|
||
'use strict';
|
||
|
||
var customEvent = require('custom-event');
|
||
var eventmap = require('./eventmap');
|
||
var doc = global.document;
|
||
var addEvent = addEventEasy;
|
||
var removeEvent = removeEventEasy;
|
||
var hardCache = [];
|
||
|
||
if (!global.addEventListener) {
|
||
addEvent = addEventHard;
|
||
removeEvent = removeEventHard;
|
||
}
|
||
|
||
module.exports = {
|
||
add: addEvent,
|
||
remove: removeEvent,
|
||
fabricate: fabricateEvent
|
||
};
|
||
|
||
function addEventEasy(el, type, fn, capturing) {
|
||
return el.addEventListener(type, fn, capturing);
|
||
}
|
||
|
||
function addEventHard(el, type, fn) {
|
||
return el.attachEvent('on' + type, wrap(el, type, fn));
|
||
}
|
||
|
||
function removeEventEasy(el, type, fn, capturing) {
|
||
return el.removeEventListener(type, fn, capturing);
|
||
}
|
||
|
||
function removeEventHard(el, type, fn) {
|
||
var listener = unwrap(el, type, fn);
|
||
if (listener) {
|
||
return el.detachEvent('on' + type, listener);
|
||
}
|
||
}
|
||
|
||
function fabricateEvent(el, type, model) {
|
||
var e = eventmap.indexOf(type) === -1 ? makeCustomEvent() : makeClassicEvent();
|
||
if (el.dispatchEvent) {
|
||
el.dispatchEvent(e);
|
||
} else {
|
||
el.fireEvent('on' + type, e);
|
||
}
|
||
|
||
function makeClassicEvent() {
|
||
var e;
|
||
if (doc.createEvent) {
|
||
e = doc.createEvent('Event');
|
||
e.initEvent(type, true, true);
|
||
} else if (doc.createEventObject) {
|
||
e = doc.createEventObject();
|
||
}
|
||
return e;
|
||
}
|
||
|
||
function makeCustomEvent() {
|
||
return new customEvent(type, {
|
||
detail: model
|
||
});
|
||
}
|
||
}
|
||
|
||
function wrapperFactory(el, type, fn) {
|
||
return function wrapper(originalEvent) {
|
||
var e = originalEvent || global.event;
|
||
e.target = e.target || e.srcElement;
|
||
e.preventDefault = e.preventDefault || function preventDefault() {
|
||
e.returnValue = false;
|
||
};
|
||
e.stopPropagation = e.stopPropagation || function stopPropagation() {
|
||
e.cancelBubble = true;
|
||
};
|
||
e.which = e.which || e.keyCode;
|
||
fn.call(el, e);
|
||
};
|
||
}
|
||
|
||
function wrap(el, type, fn) {
|
||
var wrapper = unwrap(el, type, fn) || wrapperFactory(el, type, fn);
|
||
hardCache.push({
|
||
wrapper: wrapper,
|
||
element: el,
|
||
type: type,
|
||
fn: fn
|
||
});
|
||
return wrapper;
|
||
}
|
||
|
||
function unwrap(el, type, fn) {
|
||
var i = find(el, type, fn);
|
||
if (i) {
|
||
var wrapper = hardCache[i].wrapper;
|
||
hardCache.splice(i, 1); // free up a tad of memory
|
||
return wrapper;
|
||
}
|
||
}
|
||
|
||
function find(el, type, fn) {
|
||
var i, item;
|
||
for (i = 0; i < hardCache.length; i++) {
|
||
item = hardCache[i];
|
||
if (item.element === el && item.type === type && item.fn === fn) {
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
|
||
}).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
}, {
|
||
"./eventmap": 6,
|
||
"custom-event": 7
|
||
}],
|
||
6: [function (require, module, exports) {
|
||
(function (global) {
|
||
'use strict';
|
||
|
||
var eventmap = [];
|
||
var eventname = '';
|
||
var ron = /^on/;
|
||
|
||
for (eventname in global) {
|
||
if (ron.test(eventname)) {
|
||
eventmap.push(eventname.slice(2));
|
||
}
|
||
}
|
||
|
||
module.exports = eventmap;
|
||
|
||
}).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
}, {}],
|
||
7: [function (require, module, exports) {
|
||
(function (global) {
|
||
|
||
var NativeCustomEvent = global.CustomEvent;
|
||
|
||
function useNative() {
|
||
try {
|
||
var p = new NativeCustomEvent('cat', {
|
||
detail: {
|
||
foo: 'bar'
|
||
}
|
||
});
|
||
return 'cat' === p.type && 'bar' === p.detail.foo;
|
||
} catch (e) {}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Cross-browser `CustomEvent` constructor.
|
||
*
|
||
* https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent
|
||
*
|
||
* @public
|
||
*/
|
||
|
||
module.exports = useNative() ? NativeCustomEvent :
|
||
|
||
// IE >= 9
|
||
'function' === typeof document.createEvent ? function CustomEvent(type, params) {
|
||
var e = document.createEvent('CustomEvent');
|
||
if (params) {
|
||
e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail);
|
||
} else {
|
||
e.initCustomEvent(type, false, false, void 0);
|
||
}
|
||
return e;
|
||
} :
|
||
|
||
// IE <= 8
|
||
function CustomEvent(type, params) {
|
||
var e = document.createEventObject();
|
||
e.type = type;
|
||
if (params) {
|
||
e.bubbles = Boolean(params.bubbles);
|
||
e.cancelable = Boolean(params.cancelable);
|
||
e.detail = params.detail;
|
||
} else {
|
||
e.bubbles = false;
|
||
e.cancelable = false;
|
||
e.detail = void 0;
|
||
}
|
||
return e;
|
||
}
|
||
|
||
}).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
}, {}],
|
||
8: [function (require, module, exports) {
|
||
'use strict';
|
||
|
||
var cache = {};
|
||
var start = '(?:^|\\s)';
|
||
var end = '(?:\\s|$)';
|
||
|
||
function lookupClass(className) {
|
||
var cached = cache[className];
|
||
if (cached) {
|
||
cached.lastIndex = 0;
|
||
} else {
|
||
cache[className] = cached = new RegExp(start + className + end, 'g');
|
||
}
|
||
return cached;
|
||
}
|
||
|
||
function addClass(el, className) {
|
||
var current = el.className;
|
||
if (!current.length) {
|
||
el.className = className;
|
||
} else if (!lookupClass(className).test(current)) {
|
||
el.className += ' ' + className;
|
||
}
|
||
}
|
||
|
||
function rmClass(el, className) {
|
||
el.className = el.className.replace(lookupClass(className), ' ').trim();
|
||
}
|
||
|
||
module.exports = {
|
||
add: addClass,
|
||
rm: rmClass
|
||
};
|
||
|
||
}, {}],
|
||
9: [function (require, module, exports) {
|
||
(function (global) {
|
||
'use strict';
|
||
|
||
var emitter = require('contra/emitter');
|
||
var crossvent = require('crossvent');
|
||
var classes = require('./classes');
|
||
var doc = document;
|
||
var documentElement = doc.documentElement;
|
||
|
||
function dragula(initialContainers, options) {
|
||
var len = arguments.length;
|
||
if (len === 1 && Array.isArray(initialContainers) === false) {
|
||
options = initialContainers;
|
||
initialContainers = [];
|
||
}
|
||
var _mirror; // mirror image
|
||
var _source; // source container
|
||
var _item; // item being dragged
|
||
var _offsetX; // reference x
|
||
var _offsetY; // reference y
|
||
var _moveX; // reference move x
|
||
var _moveY; // reference move y
|
||
var _initialSibling; // reference sibling when grabbed
|
||
var _currentSibling; // reference sibling now
|
||
var _copy; // item used for copying
|
||
var _renderTimer; // timer for setTimeout renderMirrorImage
|
||
var _lastDropTarget = null; // last container item was over
|
||
var _grabbed; // holds mousedown context until first mousemove
|
||
|
||
var o = options || {};
|
||
if (o.moves === void 0) {
|
||
o.moves = always;
|
||
}
|
||
if (o.accepts === void 0) {
|
||
o.accepts = always;
|
||
}
|
||
if (o.invalid === void 0) {
|
||
o.invalid = invalidTarget;
|
||
}
|
||
if (o.containers === void 0) {
|
||
o.containers = initialContainers || [];
|
||
}
|
||
if (o.isContainer === void 0) {
|
||
o.isContainer = never;
|
||
}
|
||
if (o.copy === void 0) {
|
||
o.copy = false;
|
||
}
|
||
if (o.copySortSource === void 0) {
|
||
o.copySortSource = false;
|
||
}
|
||
if (o.revertOnSpill === void 0) {
|
||
o.revertOnSpill = false;
|
||
}
|
||
if (o.removeOnSpill === void 0) {
|
||
o.removeOnSpill = false;
|
||
}
|
||
if (o.direction === void 0) {
|
||
o.direction = 'vertical';
|
||
}
|
||
if (o.ignoreInputTextSelection === void 0) {
|
||
o.ignoreInputTextSelection = true;
|
||
}
|
||
if (o.mirrorContainer === void 0) {
|
||
o.mirrorContainer = doc.body;
|
||
}
|
||
|
||
var drake = emitter({
|
||
containers: o.containers,
|
||
start: manualStart,
|
||
end: end,
|
||
cancel: cancel,
|
||
remove: remove,
|
||
destroy: destroy,
|
||
canMove: canMove,
|
||
dragging: false
|
||
});
|
||
|
||
if (o.removeOnSpill === true) {
|
||
drake.on('over', spillOver).on('out', spillOut);
|
||
}
|
||
|
||
events();
|
||
|
||
return drake;
|
||
|
||
function isContainer(el) {
|
||
return drake.containers.indexOf(el) !== -1 || o.isContainer(el);
|
||
}
|
||
|
||
function events(remove) {
|
||
var op = remove ? 'remove' : 'add';
|
||
touchy(documentElement, op, 'mousedown', grab);
|
||
touchy(documentElement, op, 'mouseup', release);
|
||
}
|
||
|
||
function eventualMovements(remove) {
|
||
var op = remove ? 'remove' : 'add';
|
||
touchy(documentElement, op, 'mousemove', startBecauseMouseMoved);
|
||
}
|
||
|
||
function movements(remove) {
|
||
var op = remove ? 'remove' : 'add';
|
||
crossvent[op](documentElement, 'selectstart', preventGrabbed); // IE8
|
||
crossvent[op](documentElement, 'click', preventGrabbed);
|
||
}
|
||
|
||
function destroy() {
|
||
events(true);
|
||
release({});
|
||
}
|
||
|
||
function preventGrabbed(e) {
|
||
if (_grabbed) {
|
||
e.preventDefault();
|
||
}
|
||
}
|
||
|
||
function grab(e) {
|
||
_moveX = e.clientX;
|
||
_moveY = e.clientY;
|
||
|
||
var ignore = whichMouseButton(e) !== 1 || e.metaKey || e.ctrlKey;
|
||
if (ignore) {
|
||
return; // we only care about honest-to-god left clicks and touch events
|
||
}
|
||
var item = e.target;
|
||
var context = canStart(item);
|
||
if (!context) {
|
||
return;
|
||
}
|
||
_grabbed = context;
|
||
eventualMovements();
|
||
if (e.type === 'mousedown') {
|
||
if (isInput(item)) { // see also: https://github.com/bevacqua/dragula/issues/208
|
||
item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176
|
||
} else {
|
||
e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155
|
||
}
|
||
}
|
||
}
|
||
|
||
function startBecauseMouseMoved(e) {
|
||
if (!_grabbed) {
|
||
return;
|
||
}
|
||
if (whichMouseButton(e) === 0) {
|
||
release({});
|
||
return; // when text is selected on an input and then dragged, mouseup doesn't fire. this is our only hope
|
||
}
|
||
// truthy check fixes #239, equality fixes #207
|
||
if (e.clientX !== void 0 && e.clientX === _moveX && e.clientY !== void 0 && e.clientY === _moveY) {
|
||
return;
|
||
}
|
||
if (o.ignoreInputTextSelection) {
|
||
var clientX = getCoord('clientX', e);
|
||
var clientY = getCoord('clientY', e);
|
||
var elementBehindCursor = doc.elementFromPoint(clientX, clientY);
|
||
if (isInput(elementBehindCursor)) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
var grabbed = _grabbed; // call to end() unsets _grabbed
|
||
eventualMovements(true);
|
||
movements();
|
||
end();
|
||
start(grabbed);
|
||
|
||
var offset = getOffset(_item);
|
||
_offsetX = getCoord('pageX', e) - offset.left;
|
||
_offsetY = getCoord('pageY', e) - offset.top;
|
||
|
||
classes.add(_copy || _item, 'gu-transit');
|
||
renderMirrorImage();
|
||
drag(e);
|
||
}
|
||
|
||
function canStart(item) {
|
||
if (drake.dragging && _mirror) {
|
||
return;
|
||
}
|
||
if (isContainer(item)) {
|
||
return; // don't drag container itself
|
||
}
|
||
var handle = item;
|
||
while (getParent(item) && isContainer(getParent(item)) === false) {
|
||
if (o.invalid(item, handle)) {
|
||
return;
|
||
}
|
||
item = getParent(item); // drag target should be a top element
|
||
if (!item) {
|
||
return;
|
||
}
|
||
}
|
||
var source = getParent(item);
|
||
if (!source) {
|
||
return;
|
||
}
|
||
if (o.invalid(item, handle)) {
|
||
return;
|
||
}
|
||
|
||
var movable = o.moves(item, source, handle, nextEl(item));
|
||
if (!movable) {
|
||
return;
|
||
}
|
||
|
||
return {
|
||
item: item,
|
||
source: source
|
||
};
|
||
}
|
||
|
||
function canMove(item) {
|
||
return !!canStart(item);
|
||
}
|
||
|
||
function manualStart(item) {
|
||
var context = canStart(item);
|
||
if (context) {
|
||
start(context);
|
||
}
|
||
}
|
||
|
||
function start(context) {
|
||
if (isCopy(context.item, context.source)) {
|
||
_copy = context.item.cloneNode(true);
|
||
drake.emit('cloned', _copy, context.item, 'copy');
|
||
}
|
||
|
||
_source = context.source;
|
||
_item = context.item;
|
||
_initialSibling = _currentSibling = nextEl(context.item);
|
||
|
||
drake.dragging = true;
|
||
drake.emit('drag', _item, _source);
|
||
}
|
||
|
||
function invalidTarget() {
|
||
return false;
|
||
}
|
||
|
||
function end() {
|
||
if (!drake.dragging) {
|
||
return;
|
||
}
|
||
var item = _copy || _item;
|
||
drop(item, getParent(item));
|
||
}
|
||
|
||
function ungrab() {
|
||
_grabbed = false;
|
||
eventualMovements(true);
|
||
movements(true);
|
||
}
|
||
|
||
function release(e) {
|
||
ungrab();
|
||
|
||
if (!drake.dragging) {
|
||
return;
|
||
}
|
||
var item = _copy || _item;
|
||
var clientX = getCoord('clientX', e);
|
||
var clientY = getCoord('clientY', e);
|
||
var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
|
||
var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
|
||
if (dropTarget && ((_copy && o.copySortSource) || (!_copy || dropTarget !== _source))) {
|
||
drop(item, dropTarget);
|
||
} else if (o.removeOnSpill) {
|
||
remove();
|
||
} else {
|
||
cancel();
|
||
}
|
||
}
|
||
|
||
function drop(item, target) {
|
||
var parent = getParent(item);
|
||
if (_copy && o.copySortSource && target === _source) {
|
||
parent.removeChild(_item);
|
||
}
|
||
if (isInitialPlacement(target)) {
|
||
drake.emit('cancel', item, _source, _source);
|
||
} else {
|
||
drake.emit('drop', item, target, _source, _currentSibling);
|
||
}
|
||
cleanup();
|
||
}
|
||
|
||
function remove() {
|
||
if (!drake.dragging) {
|
||
return;
|
||
}
|
||
var item = _copy || _item;
|
||
var parent = getParent(item);
|
||
if (parent) {
|
||
parent.removeChild(item);
|
||
}
|
||
drake.emit(_copy ? 'cancel' : 'remove', item, parent, _source);
|
||
cleanup();
|
||
}
|
||
|
||
function cancel(revert) {
|
||
if (!drake.dragging) {
|
||
return;
|
||
}
|
||
var reverts = arguments.length > 0 ? revert : o.revertOnSpill;
|
||
var item = _copy || _item;
|
||
var parent = getParent(item);
|
||
var initial = isInitialPlacement(parent);
|
||
if (initial === false && reverts) {
|
||
if (_copy) {
|
||
if (parent) {
|
||
parent.removeChild(_copy);
|
||
}
|
||
} else {
|
||
_source.insertBefore(item, _initialSibling);
|
||
}
|
||
}
|
||
if (initial || reverts) {
|
||
drake.emit('cancel', item, _source, _source);
|
||
} else {
|
||
drake.emit('drop', item, parent, _source, _currentSibling);
|
||
}
|
||
cleanup();
|
||
}
|
||
|
||
function cleanup() {
|
||
var item = _copy || _item;
|
||
ungrab();
|
||
removeMirrorImage();
|
||
if (item) {
|
||
classes.rm(item, 'gu-transit');
|
||
}
|
||
if (_renderTimer) {
|
||
clearTimeout(_renderTimer);
|
||
}
|
||
drake.dragging = false;
|
||
if (_lastDropTarget) {
|
||
drake.emit('out', item, _lastDropTarget, _source);
|
||
}
|
||
drake.emit('dragend', item);
|
||
_source = _item = _copy = _initialSibling = _currentSibling = _renderTimer = _lastDropTarget = null;
|
||
}
|
||
|
||
function isInitialPlacement(target, s) {
|
||
var sibling;
|
||
if (s !== void 0) {
|
||
sibling = s;
|
||
} else if (_mirror) {
|
||
sibling = _currentSibling;
|
||
} else {
|
||
sibling = nextEl(_copy || _item);
|
||
}
|
||
return target === _source && sibling === _initialSibling;
|
||
}
|
||
|
||
function findDropTarget(elementBehindCursor, clientX, clientY) {
|
||
var target = elementBehindCursor;
|
||
while (target && !accepted()) {
|
||
target = getParent(target);
|
||
}
|
||
return target;
|
||
|
||
function accepted() {
|
||
var droppable = isContainer(target);
|
||
if (droppable === false) {
|
||
return false;
|
||
}
|
||
|
||
var immediate = getImmediateChild(target, elementBehindCursor);
|
||
var reference = getReference(target, immediate, clientX, clientY);
|
||
var initial = isInitialPlacement(target, reference);
|
||
if (initial) {
|
||
return true; // should always be able to drop it right back where it was
|
||
}
|
||
return o.accepts(_item, target, _source, reference);
|
||
}
|
||
}
|
||
|
||
function drag(e) {
|
||
if (!_mirror) {
|
||
return;
|
||
}
|
||
e.preventDefault();
|
||
|
||
var clientX = getCoord('clientX', e);
|
||
var clientY = getCoord('clientY', e);
|
||
var x = clientX - _offsetX;
|
||
var y = clientY - _offsetY;
|
||
|
||
_mirror.style.left = x + 'px';
|
||
_mirror.style.top = y + 'px';
|
||
|
||
var item = _copy || _item;
|
||
var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
|
||
var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
|
||
var changed = dropTarget !== null && dropTarget !== _lastDropTarget;
|
||
if (changed || dropTarget === null) {
|
||
out();
|
||
_lastDropTarget = dropTarget;
|
||
over();
|
||
}
|
||
var parent = getParent(item);
|
||
if (dropTarget === _source && _copy && !o.copySortSource) {
|
||
if (parent) {
|
||
parent.removeChild(item);
|
||
}
|
||
return;
|
||
}
|
||
var reference;
|
||
var immediate = getImmediateChild(dropTarget, elementBehindCursor);
|
||
if (immediate !== null) {
|
||
reference = getReference(dropTarget, immediate, clientX, clientY);
|
||
} else if (o.revertOnSpill === true && !_copy) {
|
||
reference = _initialSibling;
|
||
dropTarget = _source;
|
||
} else {
|
||
if (_copy && parent) {
|
||
parent.removeChild(item);
|
||
}
|
||
return;
|
||
}
|
||
if (
|
||
(reference === null && changed) ||
|
||
reference !== item &&
|
||
reference !== nextEl(item)
|
||
) {
|
||
_currentSibling = reference;
|
||
dropTarget.insertBefore(item, reference);
|
||
drake.emit('shadow', item, dropTarget, _source);
|
||
}
|
||
|
||
function moved(type) {
|
||
drake.emit(type, item, _lastDropTarget, _source);
|
||
}
|
||
|
||
function over() {
|
||
if (changed) {
|
||
moved('over');
|
||
}
|
||
}
|
||
|
||
function out() {
|
||
if (_lastDropTarget) {
|
||
moved('out');
|
||
}
|
||
}
|
||
}
|
||
|
||
function spillOver(el) {
|
||
classes.rm(el, 'gu-hide');
|
||
}
|
||
|
||
function spillOut(el) {
|
||
if (drake.dragging) {
|
||
classes.add(el, 'gu-hide');
|
||
}
|
||
}
|
||
|
||
function renderMirrorImage() {
|
||
if (_mirror) {
|
||
return;
|
||
}
|
||
var rect = _item.getBoundingClientRect();
|
||
_mirror = _item.cloneNode(true);
|
||
_mirror.style.width = getRectWidth(rect) + 'px';
|
||
_mirror.style.height = getRectHeight(rect) + 'px';
|
||
classes.rm(_mirror, 'gu-transit');
|
||
classes.add(_mirror, 'gu-mirror');
|
||
o.mirrorContainer.appendChild(_mirror);
|
||
touchy(documentElement, 'add', 'mousemove', drag);
|
||
classes.add(o.mirrorContainer, 'gu-unselectable');
|
||
drake.emit('cloned', _mirror, _item, 'mirror');
|
||
}
|
||
|
||
function removeMirrorImage() {
|
||
if (_mirror) {
|
||
classes.rm(o.mirrorContainer, 'gu-unselectable');
|
||
touchy(documentElement, 'remove', 'mousemove', drag);
|
||
getParent(_mirror).removeChild(_mirror);
|
||
_mirror = null;
|
||
}
|
||
}
|
||
|
||
function getImmediateChild(dropTarget, target) {
|
||
var immediate = target;
|
||
while (immediate !== dropTarget && getParent(immediate) !== dropTarget) {
|
||
immediate = getParent(immediate);
|
||
}
|
||
if (immediate === documentElement) {
|
||
return null;
|
||
}
|
||
return immediate;
|
||
}
|
||
|
||
function getReference(dropTarget, target, x, y) {
|
||
var horizontal = o.direction === 'horizontal';
|
||
var reference = target !== dropTarget ? inside() : outside();
|
||
return reference;
|
||
|
||
function outside() { // slower, but able to figure out any position
|
||
var len = dropTarget.children.length;
|
||
var i;
|
||
var el;
|
||
var rect;
|
||
for (i = 0; i < len; i++) {
|
||
el = dropTarget.children[i];
|
||
rect = el.getBoundingClientRect();
|
||
if (horizontal && (rect.left + rect.width / 2) > x) {
|
||
return el;
|
||
}
|
||
if (!horizontal && (rect.top + rect.height / 2) > y) {
|
||
return el;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function inside() { // faster, but only available if dropped inside a child element
|
||
var rect = target.getBoundingClientRect();
|
||
if (horizontal) {
|
||
return resolve(x > rect.left + getRectWidth(rect) / 2);
|
||
}
|
||
return resolve(y > rect.top + getRectHeight(rect) / 2);
|
||
}
|
||
|
||
function resolve(after) {
|
||
return after ? nextEl(target) : target;
|
||
}
|
||
}
|
||
|
||
function isCopy(item, container) {
|
||
return typeof o.copy === 'boolean' ? o.copy : o.copy(item, container);
|
||
}
|
||
}
|
||
|
||
function touchy(el, op, type, fn) {
|
||
var touch = {
|
||
mouseup: 'touchend',
|
||
mousedown: 'touchstart',
|
||
mousemove: 'touchmove'
|
||
};
|
||
var pointers = {
|
||
mouseup: 'pointerup',
|
||
mousedown: 'pointerdown',
|
||
mousemove: 'pointermove'
|
||
};
|
||
var microsoft = {
|
||
mouseup: 'MSPointerUp',
|
||
mousedown: 'MSPointerDown',
|
||
mousemove: 'MSPointerMove'
|
||
};
|
||
if (global.navigator.pointerEnabled) {
|
||
crossvent[op](el, pointers[type], fn);
|
||
} else if (global.navigator.msPointerEnabled) {
|
||
crossvent[op](el, microsoft[type], fn);
|
||
} else {
|
||
crossvent[op](el, touch[type], fn);
|
||
crossvent[op](el, type, fn);
|
||
}
|
||
}
|
||
|
||
function whichMouseButton(e) {
|
||
if (e.touches !== void 0) {
|
||
return e.touches.length;
|
||
}
|
||
if (e.which !== void 0 && e.which !== 0) {
|
||
return e.which;
|
||
} // see https://github.com/bevacqua/dragula/issues/261
|
||
if (e.buttons !== void 0) {
|
||
return e.buttons;
|
||
}
|
||
var button = e.button;
|
||
if (button !== void 0) { // see https://github.com/jquery/jquery/blob/99e8ff1baa7ae341e94bb89c3e84570c7c3ad9ea/src/event.js#L573-L575
|
||
return button & 1 ? 1 : button & 2 ? 3 : (button & 4 ? 2 : 0);
|
||
}
|
||
}
|
||
|
||
function getOffset(el) {
|
||
var rect = el.getBoundingClientRect();
|
||
return {
|
||
left: rect.left + getScroll('scrollLeft', 'pageXOffset'),
|
||
top: rect.top + getScroll('scrollTop', 'pageYOffset')
|
||
};
|
||
}
|
||
|
||
function getScroll(scrollProp, offsetProp) {
|
||
if (typeof global[offsetProp] !== 'undefined') {
|
||
return global[offsetProp];
|
||
}
|
||
if (documentElement.clientHeight) {
|
||
return documentElement[scrollProp];
|
||
}
|
||
return doc.body[scrollProp];
|
||
}
|
||
|
||
function getElementBehindPoint(point, x, y) {
|
||
var p = point || {};
|
||
var state = p.className;
|
||
var el;
|
||
p.className += ' gu-hide';
|
||
el = doc.elementFromPoint(x, y);
|
||
p.className = state;
|
||
return el;
|
||
}
|
||
|
||
function never() {
|
||
return false;
|
||
}
|
||
|
||
function always() {
|
||
return true;
|
||
}
|
||
|
||
function getRectWidth(rect) {
|
||
return rect.width || (rect.right - rect.left);
|
||
}
|
||
|
||
function getRectHeight(rect) {
|
||
return rect.height || (rect.bottom - rect.top);
|
||
}
|
||
|
||
function getParent(el) {
|
||
return el.parentNode === doc ? null : el.parentNode;
|
||
}
|
||
|
||
function isInput(el) {
|
||
return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT' || isEditable(el);
|
||
}
|
||
|
||
function isEditable(el) {
|
||
if (!el) {
|
||
return false;
|
||
} // no parents were editable
|
||
if (el.contentEditable === 'false') {
|
||
return false;
|
||
} // stop the lookup
|
||
if (el.contentEditable === 'true') {
|
||
return true;
|
||
} // found a contentEditable element in the chain
|
||
return isEditable(getParent(el)); // contentEditable is set to 'inherit'
|
||
}
|
||
|
||
function nextEl(el) {
|
||
return el.nextElementSibling || manually();
|
||
|
||
function manually() {
|
||
var sibling = el;
|
||
do {
|
||
sibling = sibling.nextSibling;
|
||
} while (sibling && sibling.nodeType !== 1);
|
||
return sibling;
|
||
}
|
||
}
|
||
|
||
function getEventHost(e) {
|
||
// on touchend event, we have to use `e.changedTouches`
|
||
// see http://stackoverflow.com/questions/7192563/touchend-event-properties
|
||
// see https://github.com/bevacqua/dragula/issues/34
|
||
if (e.targetTouches && e.targetTouches.length) {
|
||
return e.targetTouches[0];
|
||
}
|
||
if (e.changedTouches && e.changedTouches.length) {
|
||
return e.changedTouches[0];
|
||
}
|
||
return e;
|
||
}
|
||
|
||
function getCoord(coord, e) {
|
||
var host = getEventHost(e);
|
||
var missMap = {
|
||
pageX: 'clientX', // IE8
|
||
pageY: 'clientY' // IE8
|
||
};
|
||
if (coord in missMap && !(coord in host) && missMap[coord] in host) {
|
||
coord = missMap[coord];
|
||
}
|
||
return host[coord];
|
||
}
|
||
|
||
module.exports = dragula;
|
||
|
||
}).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
}, {
|
||
"./classes": 8,
|
||
"contra/emitter": 4,
|
||
"crossvent": 5
|
||
}],
|
||
10: [function (require, module, exports) {
|
||
var si = typeof setImmediate === 'function',
|
||
tick;
|
||
if (si) {
|
||
tick = function (fn) {
|
||
setImmediate(fn);
|
||
};
|
||
} else {
|
||
tick = function (fn) {
|
||
setTimeout(fn, 0);
|
||
};
|
||
}
|
||
|
||
module.exports = tick;
|
||
}, {}]
|
||
}, {}, [1]);
|