/*jslint vars: true, browser: true, white: true */ /*global jQuery, IQVOC */ IQVOC.treeview = (function($) { "use strict"; function Treeview(container) { this.container = container.jquery ? container : $(container); $(container).each(function() { var url = $(this).data('url'); var container = this; var dragabbleSupport = $(container).data('dragabble'); var polyhierarchySupport = $(container).data('polyhierarchy-support'); var saveLabel = $(container).data('save-label'); var copyLabel = $(container).data('copy-label'); var undoLabel = $(container).data('undo-label'); // build tree data from html markup var data = $(this).children('li').map(function() { var item = $(this); return { label: item.children('a').html(), load_on_demand: item.data('has-children'), locked: item.data('locked'), id: item.attr('id'), url: item.children('a').attr('href'), update_url: item.data('update-url'), published: item.data('published'), additionalText: item.children('span.additional_info') }; }); $(this).tree({ dragAndDrop: dragabbleSupport ? true : false, autoEscape: false, selectable: false, closedIcon: $(''), openedIcon: $(''), data: data, dataUrl: function(node) { var uri = URI(url).addQuery('root', node.id); return uri.normalize().toString(); }, onCreateLi: function(node, $li) { var link = buildLink(node.url, node.name, node.additionalText); $li.find('.jqtree-title').replaceWith(link); // mark published/unpublished items if (typeof node.published !== 'undefined' && !node.published) { // modify draft link var href = URI(link.attr('href')); link.attr('href', href.addQuery('published', 0)); link.addClass('unpublished'); } else { link.addClass('published'); } if (dragabbleSupport) { // mark locked items if (typeof node.locked !== 'undefined' && node.locked) { // add icon only to the first element of the collection. // the second one could be a nodelist for parents nodes. $(link[0]).after(' '); } if (typeof node.locked !== 'undefined' && !node.locked) { // add icon only to the first element of the collection. // the second one could be a nodelist for parents nodes. $(link[0]).after(' '); } } if(node.moved) { $li.data('node-id', node.id); $li.data('old-parent-node-id', node.old_parent_id); $li.data('new-parent-node-id', node.target_node_id); $li.data('old-previous-sibling-id', node.old_previous_sibling_id); $li.data('update-url', node.update_url); var saveButton = $(''); var copyButton = $(''); var undoButton = $(''); // add icon only to the first element of the collection. // the second one could be a nodelist for parents nodes. $(link[0]).after(saveButton, undoButton); if(polyhierarchySupport) { saveButton.after(copyButton); } } }, onIsMoveHandle: function($element) { // dom element which acts as move handle return ($element.is('.fa-arrows')); }, onCanMoveTo: function(moved_node, target_node, position){ // prevent node movement inside parent node if (moved_node.parent === target_node.parent && position === 'after'){ return false; } // prevent locked node movement else if (moved_node.locked === true || target_node.locked === true) { return false; } // only drop node inside nodes, no ordering else if (position === 'after') { return false; } else { return true; } } }); }); // mark moved nodes $('ul.hybrid-treeview').on('tree.move', function(event) { var moved_node = event.move_info.moved_node; $(this).tree('updateNode', moved_node, { moved: true, target_node_id: event.move_info.target_node.id }); if (moved_node.getPreviousSibling() !== null) { $(this).tree('updateNode', moved_node, {old_previous_sibling_id: moved_node.getPreviousSibling().id}); } if (typeof moved_node.parent.id !== 'undefined') { $(this).tree('updateNode', moved_node, {old_parent_id: moved_node.parent.id}); } }); // save/copy moved node $('ul.hybrid-treeview').on('click', 'button.node-btn', function(event) { var $tree = $('ul.hybrid-treeview'); var treeAction = $(this).data('tree-action'); var updateUrl = $(this).closest('li').data('update-url'); var movedNodeId = $(this).closest('li').data('node-id'); var oldParentNodeId = $(this).closest('li').data('old-parent-node-id'); var oldPreviousSiblingId = $(this).closest('li').data('old-previous-sibling-id'); var newParentNodeId = $(this).closest('li').data('new-parent-node-id'); $.ajax({ url : updateUrl, type : 'PATCH', data : { tree_action: treeAction, moved_node_id: movedNodeId, old_parent_node_id: oldParentNodeId, new_parent_node_id: newParentNodeId }, statusCode: { 200: function() { [movedNodeId, newParentNodeId, oldParentNodeId].forEach(function(nodeId){ setToDraft(nodeId, $tree); }); // add node to old parent, necessary to see both node directly after movement, // this is not necessary if you refresh the page if (treeAction === 'copy') { var node = $tree.tree('getNodeById', movedNodeId); if (typeof oldPreviousSiblingId !== 'undefined') { var old_previous_sibling = $tree.tree('getNodeById', oldPreviousSiblingId); $tree.tree('addNodeAfter', node, old_previous_sibling); } else if (typeof oldParentNodeId !== 'undefined') { var old_parent_node = $tree.tree('getNodeById', oldParentNodeId); $tree.tree('appendNode', node, old_parent_node); } } } } }); }); // reset moved node $('ul.hybrid-treeview').on('click', 'button.reset-node-btn', function(event) { var $tree = $('ul.hybrid-treeview'); var nodeId = $(this).closest('li').data('node-id'); var oldPreviousSiblingId = $(this).closest('li').data('old-previous-sibling-id'); var oldParentNodeId = $(this).closest('li').data('old-parent-node-id'); moveToOldPosition(nodeId, oldPreviousSiblingId, oldParentNodeId, $tree); }); function setToDraft(nodeId, $tree) { if (typeof nodeId !== 'undefined') { var moved_node = $tree.tree('getNodeById', nodeId); $tree.tree('updateNode', moved_node, { moved: false, published: false }); } } function moveToOldPosition(nodeId, oldPreviousSiblingId, oldParentNodeId, $tree) { var node = $tree.tree('getNodeById', nodeId); if (typeof oldPreviousSiblingId !== 'undefined') { var old_previous_sibling = $tree.tree('getNodeById', oldPreviousSiblingId); $tree.tree('moveNode', node, old_previous_sibling, 'after'); } else if (typeof oldParentNodeId !== 'undefined') { var oldParentNode = $tree.tree('getNodeById', oldParentNodeId); $tree.tree('moveNode', node, oldParentNode, 'inside'); } $tree.tree('updateNode', node, {moved: false}); } function buildLink(url, label, additionalText) { var link = $('').attr('href', url).html(label); if (additionalText) { link = link.after(' ', additionalText); } return link; } } return function(selector) { return new Treeview(selector); }; }(jQuery));