diff --git a/htdocs/includes/jquery/plugins/tablednd/README.txt b/htdocs/includes/jquery/plugins/tablednd/README.txt index d6c3c823993..9de4f5db79e 100644 --- a/htdocs/includes/jquery/plugins/tablednd/README.txt +++ b/htdocs/includes/jquery/plugins/tablednd/README.txt @@ -1,3 +1,5 @@ ----- jquery.tablednd ----- - New versions are found into directory js of https://github.com/isocra/TableDnD -- Version 0.9.1 not compatible with jquery 3.0+, so master git branch used. \ No newline at end of file +- Distribution available on 'npm install tablednd' +- Current version V1.0 RC for 7.0 alpha +- TODO update to V1.0 for 7.0 beta \ No newline at end of file diff --git a/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.js b/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.js index 5ac2cce6524..f00d3940456 100644 --- a/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.js +++ b/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.js @@ -2,674 +2,601 @@ * TableDnD plug-in for JQuery, allows you to drag and drop table rows * You can set up various options to control how the system will work * Copyright (c) Denis Howlett - * Licensed like jQuery, see http://docs.jquery.com/License. - * - * Configuration options: - * - * onDragStyle - * This is the style that is assigned to the row during drag. There are limitations to the styles that can be - * associated with a row (such as you can't assign a border--well you can, but it won't be - * displayed). (So instead consider using onDragClass.) The CSS style to apply is specified as - * a map (as used in the jQuery css(...) function). - * onDropStyle - * This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations - * to what you can do. Also this replaces the original style, so again consider using onDragClass which - * is simply added and then removed on drop. - * onDragClass - * This class is added for the duration of the drag and then removed when the row is dropped. It is more - * flexible than using onDragStyle since it can be inherited by the row cells and other content. The default - * is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your - * stylesheet. - * onDrop - * Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table - * and the row that was dropped. You can work out the new order of the rows by using - * table.rows. - * onDragStart - * Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the - * table and the row which the user has started to drag. - * onDragStop - * Pass a function that will be called when the user stops dragging regardless of if the rows have been - * rearranged. The function takes 2 parameters: the table and the row which the user was dragging. - * onAllowDrop - * Pass a function that will be called as a row is over another row. If the function returns true, allow - * dropping on that row, otherwise not. The function takes 2 parameters: the dragged row and the row under - * the cursor. It returns a boolean: true allows the drop, false doesn't allow it. - * scrollAmount - * This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the - * window. The page should automatically scroll up or down as appropriate (tested in IE6, IE7, Safari, FF2, - * FF3 beta - * dragHandle - * This is a jQuery mach string for one or more cells in each row that is draggable. If you - * specify this, then you are responsible for setting cursor: move in the CSS and only these cells - * will have the drag behaviour. If you do not specify a dragHandle, then you get the old behaviour where - * the whole row is draggable. - * - * Other ways to control behaviour: - * - * Add class="nodrop" to any rows for which you don't want to allow dropping, and class="nodrag" to any rows - * that you don't want to be draggable. - * - * Inside the onDrop method you can also call $.tableDnD.serialize() this returns a string of the form - * []=&[]= so that you can send this back to the server. The table must have - * an ID as must all the rows. - * - * Other methods: - * - * $("...").tableDnDUpdate() - * Will update all the matching tables, that is it will reapply the mousedown method to the rows (or handle cells). - * This is useful if you have updated the table rows using Ajax and you want to make the table draggable again. - * The table maintains the original configuration (so you don't have to specify it again). - * - * $("...").tableDnDSerialize() - * Will serialize and return the serialized string as above, but for each of the matching tables--so it can be - * called from anywhere and isn't dependent on the currentTable being set up correctly before calling - * - * Known problems: - * - Auto-scoll has some problems with IE7 (it scrolls even when it shouldn't), work-around: set scrollAmount to 0 - * - * Version 0.2: 2008-02-20 First public version - * Version 0.3: 2008-02-07 Added onDragStart option - * Made the scroll amount configurable (default is 5 as before) - * Version 0.4: 2008-03-15 Changed the noDrag/noDrop attributes to nodrag/nodrop classes - * Added onAllowDrop to control dropping - * Fixed a bug which meant that you couldn't set the scroll amount in both directions - * Added serialize method - * Version 0.5: 2008-05-16 Changed so that if you specify a dragHandle class it doesn't make the whole row - * draggable - * Improved the serialize method to use a default (and settable) regular expression. - * Added tableDnDupate() and tableDnDSerialize() to be called when you are outside the table - * Version 0.6: 2011-12-02 Added support for touch devices - * Version 0.7 2012-04-09 Now works with jQuery 1.7 and supports touch, tidied up tabs and spaces + * License: MIT. + * See https://github.com/isocra/TableDnD */ + +/*jshint -W054 */ + !function ($, window, document, undefined) { - // Determine if this is a touch device - var hasTouch = 'ontouchstart' in document.documentElement, - startEvent = 'touchstart mousedown', - moveEvent = 'touchmove mousemove', - endEvent = 'touchend mouseup'; - - $(document).ready(function () { - function parseStyle(css) { - var objMap = {}, - parts = css.match(/([^;:]+)/g) || []; - while (parts.length) - objMap[parts.shift()] = parts.shift().trim(); - - return objMap; +// Determine if this is a touch device +var hasTouch = 'ontouchstart' in document.documentElement, + startEvent = 'touchstart mousedown', + moveEvent = 'touchmove mousemove', + endEvent = 'touchend mouseup'; + +$(document).ready(function () { + function parseStyle(css) { + var objMap = {}, + parts = css.match(/([^;:]+)/g) || []; + while (parts.length) + objMap[parts.shift()] = parts.shift().trim(); + + return objMap; + } + $('table').each(function () { + if ($(this).data('table') == 'dnd') { + + $(this).tableDnD({ + onDragStyle: $(this).data('ondragstyle') && parseStyle($(this).data('ondragstyle')) || null, + onDropStyle: $(this).data('ondropstyle') && parseStyle($(this).data('ondropstyle')) || null, + onDragClass: $(this).data('ondragclass') === undefined && "tDnD_whileDrag" || $(this).data('ondragclass'), + onDrop: $(this).data('ondrop') && new Function('table', 'row', $(this).data('ondrop')), // 'return eval("'+$(this).data('ondrop')+'");') || null, + onDragStart: $(this).data('ondragstart') && new Function('table', 'row' ,$(this).data('ondragstart')), // 'return eval("'+$(this).data('ondragstart')+'");') || null, + onDragStop: $(this).data('ondragstop') && new Function('table', 'row' ,$(this).data('ondragstop')), + scrollAmount: $(this).data('scrollamount') || 5, + sensitivity: $(this).data('sensitivity') || 10, + hierarchyLevel: $(this).data('hierarchylevel') || 0, + indentArtifact: $(this).data('indentartifact') || '
 
', + autoWidthAdjust: $(this).data('autowidthadjust') || true, + autoCleanRelations: $(this).data('autocleanrelations') || true, + jsonPretifySeparator: $(this).data('jsonpretifyseparator') || '\t', + serializeRegexp: $(this).data('serializeregexp') && new RegExp($(this).data('serializeregexp')) || /[^\-]*$/, + serializeParamName: $(this).data('serializeparamname') || false, + dragHandle: $(this).data('draghandle') || null + }); } - $('table').each(function () { - if ($(this).data('table') == 'dnd') { - - $(this).tableDnD({ - onDragStyle: $(this).data('ondragstyle') && parseStyle($(this).data('ondragstyle')) || null, - onDropStyle: $(this).data('ondropstyle') && parseStyle($(this).data('ondropstyle')) || null, - onDragClass: $(this).data('ondragclass') == undefined && "tDnD_whileDrag" || $(this).data('ondragclass'), - onDrop: $(this).data('ondrop') && new Function('table', 'row', $(this).data('ondrop')), // 'return eval("'+$(this).data('ondrop')+'");') || null, - onDragStart: $(this).data('ondragstart') && new Function('table', 'row' ,$(this).data('ondragstart')), // 'return eval("'+$(this).data('ondragstart')+'");') || null, - onDragStop: $(this).data('ondragstop') && new Function('table', 'row' ,$(this).data('ondragstop')), - scrollAmount: $(this).data('scrollamount') || 5, - sensitivity: $(this).data('sensitivity') || 10, - hierarchyLevel: $(this).data('hierarchylevel') || 0, - indentArtifact: $(this).data('indentartifact') || '
 
', - autoWidthAdjust: $(this).data('autowidthadjust') || true, - autoCleanRelations: $(this).data('autocleanrelations') || true, - jsonPretifySeparator: $(this).data('jsonpretifyseparator') || '\t', - serializeRegexp: $(this).data('serializeregexp') && new RegExp($(this).data('serializeregexp')) || /[^\-]*$/, - serializeParamName: $(this).data('serializeparamname') || false, - dragHandle: $(this).data('draghandle') || null - }); - } - - - }); + + }); - - jQuery.tableDnD = { - /** Keep hold of the current table being dragged */ - currentTable: null, - /** Keep hold of the current drag object if any */ - dragObject: null, - /** The current mouse offset */ - mouseOffset: null, - /** Remember the old value of X and Y so that we don't do too much processing */ - oldX: 0, - oldY: 0, - - /** Actually build the structure */ - build: function(options) { - // Set up the defaults if any - - this.each(function() { - // This is bound to each matching table, set up the defaults and override with user options - this.tableDnDConfig = $.extend({ - onDragStyle: null, - onDropStyle: null, - // Add in the default class for whileDragging - onDragClass: "tDnD_whileDrag", - onDrop: null, - onDragStart: null, - onDragStop: null, - scrollAmount: 5, - /** Sensitivity setting will throttle the trigger rate for movement detection */ - sensitivity: 10, - /** Hierarchy level to support parent child. 0 switches this functionality off */ - hierarchyLevel: 0, - /** The html artifact to prepend the first cell with as indentation */ - indentArtifact: '
 
', - /** Automatically adjust width of first cell */ - autoWidthAdjust: true, - /** Automatic clean-up to ensure relationship integrity */ - autoCleanRelations: true, - /** Specify a number (4) as number of spaces or any indent string for JSON.stringify */ - jsonPretifySeparator: '\t', - /** The regular expression to use to trim row IDs */ - serializeRegexp: /[^\-]*$/, - /** If you want to specify another parameter name instead of the table ID */ - serializeParamName: false, - /** If you give the name of a class here, then only Cells with this class will be draggable */ - dragHandle: null - }, options || {}); - - // Now make the rows draggable - $.tableDnD.makeDraggable(this); - // Prepare hierarchy support - this.tableDnDConfig.hierarchyLevel - && $.tableDnD.makeIndented(this); - }); - - // Don't break the chain - return this; - }, - makeIndented: function (table) { - var config = table.tableDnDConfig, - rows = table.rows, - firstCell = $(rows).first().find('td:first')[0], - indentLevel = 0, - cellWidth = 0, - longestCell, - tableStyle; - - if ($(table).hasClass('indtd')) - return null; - - tableStyle = $(table).addClass('indtd').attr('style'); - $(table).css({whiteSpace: "nowrap"}); - - for (var w = 0; w < rows.length; w++) { - if (cellWidth < $(rows[w]).find('td:first').text().length) { - cellWidth = $(rows[w]).find('td:first').text().length; - longestCell = w; - } - } - $(firstCell).css({width: 'auto'}); - for (w = 0; w < config.hierarchyLevel; w++) - $(rows[longestCell]).find('td:first').prepend(config.indentArtifact); - firstCell && $(firstCell).css({width: firstCell.offsetWidth}); - tableStyle && $(table).css(tableStyle); - - for (w = 0; w < config.hierarchyLevel; w++) - $(rows[longestCell]).find('td:first').children(':first').remove(); - - config.hierarchyLevel - && $(rows).each(function () { - indentLevel = $(this).data('level') || 0; - indentLevel <= config.hierarchyLevel - && $(this).data('level', indentLevel) - || $(this).data('level', 0); - for (var i = 0; i < $(this).data('level'); i++) - $(this).find('td:first').prepend(config.indentArtifact); - }); - - return this; - }, - /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */ - makeDraggable: function(table) { - var config = table.tableDnDConfig; - - config.dragHandle - // We only need to add the event to the specified cells - && $(config.dragHandle, table).each(function() { - // The cell is bound to "this" - $(this).bind(startEvent, function(e) { - $.tableDnD.initialiseDrag($(this).parents('tr')[0], table, this, e, config); - return false; - }); - }) - // For backwards compatibility, we add the event to the whole row - // get all the rows as a wrapped set - || $(table.rows).each(function() { - // Iterate through each row, the row is bound to "this" - if (! $(this).hasClass("nodrag")) { - $(this).bind(startEvent, function(e) { - if (e.target.tagName == "TD") { - $.tableDnD.initialiseDrag(this, table, this, e, config); - return false; - } - }).css("cursor", "move"); // Store the tableDnD object - } else { - $(this).css("cursor", ""); // Remove the cursor if we don't have the nodrag class - } - }); - }, - currentOrder: function() { - var rows = this.currentTable.rows; - return $.map(rows, function (val) { - return ($(val).data('level') + val.id).replace(/\s/g, ''); - }).join(''); - }, - initialiseDrag: function(dragObject, table, target, e, config) { - this.dragObject = dragObject; - this.currentTable = table; - this.mouseOffset = this.getMouseOffset(target, e); - this.originalOrder = this.currentOrder(); - - // Now we need to capture the mouse up and mouse move event - // We can use bind so that we don't interfere with other event handlers - $(document) - .bind(moveEvent, this.mousemove) - .bind(endEvent, this.mouseup); - - // Call the onDragStart method if there is one - config.onDragStart - && config.onDragStart(table, target); - }, - updateTables: function() { - this.each(function() { - // this is now bound to each matching table - if (this.tableDnDConfig) - $.tableDnD.makeDraggable(this); - }); - }, - /** Get the mouse coordinates from the event (allowing for browser differences) */ - mouseCoords: function(e) { - if (e.originalEvent.changedTouches) - return { - x: e.originalEvent.changedTouches[0].clientX, - y: e.originalEvent.changedTouches[0].clientY - }; - - if(e.pageX || e.pageY) - return { - x: e.pageX, - y: e.pageY - }; - - return { - x: e.clientX + document.body.scrollLeft - document.body.clientLeft, - y: e.clientY + document.body.scrollTop - document.body.clientTop - }; - }, - /** Given a target element and a mouse eent, get the mouse offset from that element. - To do this we need the element's position and the mouse position */ - getMouseOffset: function(target, e) { - var mousePos, - docPos; - - e = e || window.event; - - docPos = this.getPosition(target); - mousePos = this.mouseCoords(e); - - return { - x: mousePos.x - docPos.x, - y: mousePos.y - docPos.y - }; - }, - /** Get the position of an element by going up the DOM tree and adding up all the offsets */ - getPosition: function(element) { - var left = 0, - top = 0; - - // Safari fix -- thanks to Luis Chato for this! - // Safari 2 doesn't correctly grab the offsetTop of a table row - // this is detailed here: - // http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/ - // the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild. - // note that firefox will return a text node as a first child, so designing a more thorough - // solution may need to take that into account, for now this seems to work in firefox, safari, ie - if (element.offsetHeight == 0) - element = element.firstChild; // a table cell - - while (element.offsetParent) { - left += element.offsetLeft; - top += element.offsetTop; - element = element.offsetParent; - } - - left += element.offsetLeft; - top += element.offsetTop; - - return { - x: left, - y: top - }; - }, - autoScroll: function (mousePos) { - var config = this.currentTable.tableDnDConfig, - yOffset = window.pageYOffset, - windowHeight = window.innerHeight - ? window.innerHeight - : document.documentElement.clientHeight - ? document.documentElement.clientHeight - : document.body.clientHeight; - - // Windows version - // yOffset=document.body.scrollTop; - if (document.all) - if (typeof document.compatMode != 'undefined' - && document.compatMode != 'BackCompat') - yOffset = document.documentElement.scrollTop; - else if (typeof document.body != 'undefined') - yOffset = document.body.scrollTop; - - mousePos.y - yOffset < config.scrollAmount - && window.scrollBy(0, - config.scrollAmount) - || windowHeight - (mousePos.y - yOffset) < config.scrollAmount - && window.scrollBy(0, config.scrollAmount); - - }, - moveVerticle: function (moving, currentRow) { - - if (0 != moving.vertical - // If we're over a row then move the dragged row to there so that the user sees the - // effect dynamically - && currentRow - && this.dragObject != currentRow - && this.dragObject.parentNode == currentRow.parentNode) - 0 > moving.vertical - && this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling) - || 0 < moving.vertical - && this.dragObject.parentNode.insertBefore(this.dragObject, currentRow); - - }, - moveHorizontal: function (moving, currentRow) { - var config = this.currentTable.tableDnDConfig, - currentLevel; - - if (!config.hierarchyLevel - || 0 == moving.horizontal - // We only care if moving left or right on the current row - || !currentRow - || this.dragObject != currentRow) - return null; - - currentLevel = $(currentRow).data('level'); - - 0 < moving.horizontal - && currentLevel > 0 - && $(currentRow).find('td:first').children(':first').remove() - && $(currentRow).data('level', --currentLevel); - - 0 > moving.horizontal - && currentLevel < config.hierarchyLevel - && $(currentRow).prev().data('level') >= currentLevel - && $(currentRow).children(':first').prepend(config.indentArtifact) - && $(currentRow).data('level', ++currentLevel); - - }, - mousemove: function(e) { - var dragObj = $($.tableDnD.dragObject), - config = $.tableDnD.currentTable.tableDnDConfig, - currentRow, - mousePos, - moving, - x, - y; - - e && e.preventDefault(); - - if (!$.tableDnD.dragObject) - return false; - - // prevent touch device screen scrolling - e.type == 'touchmove' - && event.preventDefault(); // TODO verify this is event and not really e - - // update the style to show we're dragging - config.onDragClass - && dragObj.addClass(config.onDragClass) - || dragObj.css(config.onDragStyle); - - mousePos = $.tableDnD.mouseCoords(e); - x = mousePos.x - $.tableDnD.mouseOffset.x; - y = mousePos.y - $.tableDnD.mouseOffset.y; - - // auto scroll the window - $.tableDnD.autoScroll(mousePos); - - currentRow = $.tableDnD.findDropTargetRow(dragObj, y); - moving = $.tableDnD.findDragDirection(x, y); - - $.tableDnD.moveVerticle(moving, currentRow); - $.tableDnD.moveHorizontal(moving, currentRow); - - return false; - }, - findDragDirection: function (x,y) { - var sensitivity = this.currentTable.tableDnDConfig.sensitivity, - oldX = this.oldX, - oldY = this.oldY, - xMin = oldX - sensitivity, - xMax = oldX + sensitivity, - yMin = oldY - sensitivity, - yMax = oldY + sensitivity, - moving = { - horizontal: x >= xMin && x <= xMax ? 0 : x > oldX ? -1 : 1, - vertical : y >= yMin && y <= yMax ? 0 : y > oldY ? -1 : 1 - }; - - // update the old value - if (moving.horizontal != 0) - this.oldX = x; - if (moving.vertical != 0) - this.oldY = y; - - return moving; - }, - /** We're only worried about the y position really, because we can only move rows up and down */ - findDropTargetRow: function(draggedRow, y) { - var rowHeight = 0, - rows = this.currentTable.rows, - config = this.currentTable.tableDnDConfig, - rowY = 0, - row = null; - - for (var i = 0; i < rows.length; i++) { - row = rows[i]; - rowY = this.getPosition(row).y; - rowHeight = parseInt(row.offsetHeight) / 2; - if (row.offsetHeight == 0) { - rowY = this.getPosition(row.firstChild).y; - rowHeight = parseInt(row.firstChild.offsetHeight) / 2; - } - // Because we always have to insert before, we need to offset the height a bit - if (y > (rowY - rowHeight) && y < (rowY + rowHeight)) - // that's the row we're over - // If it's the same as the current row, ignore it - if (draggedRow.is(row) - || (config.onAllowDrop - && !config.onAllowDrop(draggedRow, row)) - // If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic) - || $(row).hasClass("nodrop")) - return null; - else - return row; - } +}); + +jQuery.tableDnD = { + /** Keep hold of the current table being dragged */ + currentTable: null, + /** Keep hold of the current drag object if any */ + dragObject: null, + /** The current mouse offset */ + mouseOffset: null, + /** Remember the old value of X and Y so that we don't do too much processing */ + oldX: 0, + oldY: 0, + + /** Actually build the structure */ + build: function(options) { + // Set up the defaults if any + + this.each(function() { + // This is bound to each matching table, set up the defaults and override with user options + this.tableDnDConfig = $.extend({ + onDragStyle: null, + onDropStyle: null, + // Add in the default class for whileDragging + onDragClass: "tDnD_whileDrag", + onDrop: null, + onDragStart: null, + onDragStop: null, + scrollAmount: 5, + /** Sensitivity setting will throttle the trigger rate for movement detection */ + sensitivity: 10, + /** Hierarchy level to support parent child. 0 switches this functionality off */ + hierarchyLevel: 0, + /** The html artifact to prepend the first cell with as indentation */ + indentArtifact: '
 
', + /** Automatically adjust width of first cell */ + autoWidthAdjust: true, + /** Automatic clean-up to ensure relationship integrity */ + autoCleanRelations: true, + /** Specify a number (4) as number of spaces or any indent string for JSON.stringify */ + jsonPretifySeparator: '\t', + /** The regular expression to use to trim row IDs */ + serializeRegexp: /[^\-]*$/, + /** If you want to specify another parameter name instead of the table ID */ + serializeParamName: false, + /** If you give the name of a class here, then only Cells with this class will be draggable */ + dragHandle: null + }, options || {}); + + // Now make the rows draggable + $.tableDnD.makeDraggable(this); + // Prepare hierarchy support + this.tableDnDConfig.hierarchyLevel + && $.tableDnD.makeIndented(this); + }); + + // Don't break the chain + return this; + }, + makeIndented: function (table) { + var config = table.tableDnDConfig, + rows = table.rows, + firstCell = $(rows).first().find('td:first')[0], + indentLevel = 0, + cellWidth = 0, + longestCell, + tableStyle; + + if ($(table).hasClass('indtd')) return null; - }, - processMouseup: function() { - if (!this.currentTable || !this.dragObject) - return null; - - var config = this.currentTable.tableDnDConfig, - droppedRow = this.dragObject, - parentLevel = 0, - myLevel = 0; - - // Unbind the event handlers - $(document) - .unbind(moveEvent, this.mousemove) - .unbind(endEvent, this.mouseup); - - config.hierarchyLevel - && config.autoCleanRelations - && $(this.currentTable.rows).first().find('td:first').children().each(function () { - myLevel = $(this).parents('tr:first').data('level'); - myLevel - && $(this).parents('tr:first').data('level', --myLevel) - && $(this).remove(); - }) - && config.hierarchyLevel > 1 - && $(this.currentTable.rows).each(function () { - myLevel = $(this).data('level'); - if (myLevel > 1) { - parentLevel = $(this).prev().data('level'); - while (myLevel > parentLevel + 1) { - $(this).find('td:first').children(':first').remove(); - $(this).data('level', --myLevel); - } - } - }); - - // If we have a dragObject, then we need to release it, - // The row will already have been moved to the right place so we just reset stuff - config.onDragClass - && $(droppedRow).removeClass(config.onDragClass) - || $(droppedRow).css(config.onDropStyle); - - this.dragObject = null; - // Call the onDrop method if there is one - config.onDrop - && this.originalOrder != this.currentOrder() - && $(droppedRow).hide().fadeIn('fast') - && config.onDrop(this.currentTable, droppedRow); - - // Call the onDragStop method if there is one - config.onDragStop - && config.onDragStop(this.currentTable, droppedRow); - - this.currentTable = null; // let go of the table too - }, - mouseup: function(e) { - e && e.preventDefault(); - $.tableDnD.processMouseup(); - return false; - }, - jsonize: function(pretify) { - var table = this.currentTable; - if (pretify) - return JSON.stringify( - this.tableData(table), - null, - table.tableDnDConfig.jsonPretifySeparator - ); - return JSON.stringify(this.tableData(table)); - }, - serialize: function() { - return $.param(this.tableData(this.currentTable)); - }, - serializeTable: function(table) { - var result = ""; - var paramName = table.tableDnDConfig.serializeParamName || table.id; - var rows = table.rows; - for (var i=0; i 0) result += "&"; - var rowId = rows[i].id; - if (rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) { - rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0]; - result += paramName + '[]=' + rowId; - } + + tableStyle = $(table).addClass('indtd').attr('style'); + $(table).css({whiteSpace: "nowrap"}); + + for (var w = 0; w < rows.length; w++) { + if (cellWidth < $(rows[w]).find('td:first').text().length) { + cellWidth = $(rows[w]).find('td:first').text().length; + longestCell = w; } - return result; - }, - serializeTables: function() { - var result = []; - $('table').each(function() { - this.id && result.push($.param($.tableDnD.tableData(this))); + } + $(firstCell).css({width: 'auto'}); + for (w = 0; w < config.hierarchyLevel; w++) + $(rows[longestCell]).find('td:first').prepend(config.indentArtifact); + firstCell && $(firstCell).css({width: firstCell.offsetWidth}); + tableStyle && $(table).css(tableStyle); + + for (w = 0; w < config.hierarchyLevel; w++) + $(rows[longestCell]).find('td:first').children(':first').remove(); + + config.hierarchyLevel + && $(rows).each(function () { + indentLevel = $(this).data('level') || 0; + indentLevel <= config.hierarchyLevel + && $(this).data('level', indentLevel) + || $(this).data('level', 0); + for (var i = 0; i < $(this).data('level'); i++) + $(this).find('td:first').prepend(config.indentArtifact); }); - return result.join('&'); - }, - tableData: function (table) { - var config = table.tableDnDConfig, - previousIDs = [], - currentLevel = 0, - indentLevel = 0, - rowID = null, - data = {}, - getSerializeRegexp, - paramName, - currentID, - rows; - - if (!table) - table = this.currentTable; - if (!table || !table.rows || !table.rows.length) - return {error: { code: 500, message: "Not a valid table."}}; - if (!table.id && !config.serializeParamName) - return {error: { code: 500, message: "No serializable unique id provided."}}; - - rows = config.autoCleanRelations - && table.rows - || $.makeArray(table.rows); - paramName = config.serializeParamName || table.id; - currentID = paramName; - - getSerializeRegexp = function (rowId) { - if (rowId && config && config.serializeRegexp) - return rowId.match(config.serializeRegexp)[0]; - return rowId; - }; - - data[currentID] = []; - !config.autoCleanRelations - && $(rows[0]).data('level') - && rows.unshift({id: 'undefined'}); - - - - for (var i=0; i < rows.length; i++) { - if (config.hierarchyLevel) { - indentLevel = $(rows[i]).data('level') || 0; - if (indentLevel == 0) { - currentID = paramName; - previousIDs = []; - } - else if (indentLevel > currentLevel) { - previousIDs.push([currentID, currentLevel]); - currentID = getSerializeRegexp(rows[i-1].id); - } - else if (indentLevel < currentLevel) { - for (var h = 0; h < previousIDs.length; h++) { - if (previousIDs[h][1] == indentLevel) - currentID = previousIDs[h][0]; - if (previousIDs[h][1] >= currentLevel) - previousIDs[h][1] = 0; + + return this; + }, + /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */ + makeDraggable: function(table) { + var config = table.tableDnDConfig; + + config.dragHandle + // We only need to add the event to the specified cells + && $(config.dragHandle, table).each(function() { + // The cell is bound to "this" + $(this).bind(startEvent, function(e) { + $.tableDnD.initialiseDrag($(this).parents('tr')[0], table, this, e, config); + return false; + }); + }) + // For backwards compatibility, we add the event to the whole row + // get all the rows as a wrapped set + || $(table.rows).each(function() { + // Iterate through each row, the row is bound to "this" + if (! $(this).hasClass("nodrag")) { + $(this).bind(startEvent, function(e) { + if (e.target.tagName == "TD") { + $.tableDnD.initialiseDrag(this, table, this, e, config); + return false; } - } - currentLevel = indentLevel; - - if (!$.isArray(data[currentID])) - data[currentID] = []; - rowID = getSerializeRegexp(rows[i].id); - rowID && data[currentID].push(rowID); - } - else { - rowID = getSerializeRegexp(rows[i].id); - rowID && data[currentID].push(rowID); + }).css("cursor", "move"); // Store the tableDnD object + } else { + $(this).css("cursor", ""); // Remove the cursor if we don't have the nodrag class } + }); + }, + currentOrder: function() { + var rows = this.currentTable.rows; + return $.map(rows, function (val) { + return ($(val).data('level') + val.id).replace(/\s/g, ''); + }).join(''); + }, + initialiseDrag: function(dragObject, table, target, e, config) { + this.dragObject = dragObject; + this.currentTable = table; + this.mouseOffset = this.getMouseOffset(target, e); + this.originalOrder = this.currentOrder(); + + // Now we need to capture the mouse up and mouse move event + // We can use bind so that we don't interfere with other event handlers + $(document) + .bind(moveEvent, this.mousemove) + .bind(endEvent, this.mouseup); + + // Call the onDragStart method if there is one + config.onDragStart + && config.onDragStart(table, target); + }, + updateTables: function() { + this.each(function() { + // this is now bound to each matching table + if (this.tableDnDConfig) + $.tableDnD.makeDraggable(this); + }); + }, + /** Get the mouse coordinates from the event (allowing for browser differences) */ + mouseCoords: function(e) { + if (e.originalEvent.changedTouches) + return { + x: e.originalEvent.changedTouches[0].clientX, + y: e.originalEvent.changedTouches[0].clientY + }; + + if(e.pageX || e.pageY) + return { + x: e.pageX, + y: e.pageY + }; + + return { + x: e.clientX + document.body.scrollLeft - document.body.clientLeft, + y: e.clientY + document.body.scrollTop - document.body.clientTop + }; + }, + /** Given a target element and a mouse eent, get the mouse offset from that element. + To do this we need the element's position and the mouse position */ + getMouseOffset: function(target, e) { + var mousePos, + docPos; + + e = e || window.event; + + docPos = this.getPosition(target); + mousePos = this.mouseCoords(e); + + return { + x: mousePos.x - docPos.x, + y: mousePos.y - docPos.y + }; + }, + /** Get the position of an element by going up the DOM tree and adding up all the offsets */ + getPosition: function(element) { + var left = 0, + top = 0; + + // Safari fix -- thanks to Luis Chato for this! + // Safari 2 doesn't correctly grab the offsetTop of a table row + // this is detailed here: + // http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/ + // the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild. + // note that firefox will return a text node as a first child, so designing a more thorough + // solution may need to take that into account, for now this seems to work in firefox, safari, ie + if (element.offsetHeight === 0) + element = element.firstChild; // a table cell + + while (element.offsetParent) { + left += element.offsetLeft; + top += element.offsetTop; + element = element.offsetParent; + } + + left += element.offsetLeft; + top += element.offsetTop; + + return { + x: left, + y: top + }; + }, + autoScroll: function (mousePos) { + var config = this.currentTable.tableDnDConfig, + yOffset = window.pageYOffset, + windowHeight = window.innerHeight + ? window.innerHeight + : document.documentElement.clientHeight + ? document.documentElement.clientHeight + : document.body.clientHeight; + + // Windows version + // yOffset=document.body.scrollTop; + if (document.all) + if (typeof document.compatMode != 'undefined' + && document.compatMode != 'BackCompat') + yOffset = document.documentElement.scrollTop; + else if (typeof document.body != 'undefined') + yOffset = document.body.scrollTop; + + mousePos.y - yOffset < config.scrollAmount + && window.scrollBy(0, - config.scrollAmount) + || windowHeight - (mousePos.y - yOffset) < config.scrollAmount + && window.scrollBy(0, config.scrollAmount); + + }, + moveVerticle: function (moving, currentRow) { + + if (0 !== moving.vertical + // If we're over a row then move the dragged row to there so that the user sees the + // effect dynamically + && currentRow + && this.dragObject !== currentRow + && this.dragObject.parentNode === currentRow.parentNode) + 0 > moving.vertical + && this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling) + || 0 < moving.vertical + && this.dragObject.parentNode.insertBefore(this.dragObject, currentRow); + + }, + moveHorizontal: function (moving, currentRow) { + var config = this.currentTable.tableDnDConfig, + currentLevel; + + if (!config.hierarchyLevel + || 0 === moving.horizontal + // We only care if moving left or right on the current row + || !currentRow + || this.dragObject !== currentRow) + return null; + + currentLevel = $(currentRow).data('level'); + + 0 < moving.horizontal + && currentLevel > 0 + && $(currentRow).find('td:first').children(':first').remove() + && $(currentRow).data('level', --currentLevel); + + 0 > moving.horizontal + && currentLevel < config.hierarchyLevel + && $(currentRow).prev().data('level') >= currentLevel + && $(currentRow).children(':first').prepend(config.indentArtifact) + && $(currentRow).data('level', ++currentLevel); + + }, + mousemove: function(e) { + var dragObj = $($.tableDnD.dragObject), + config = $.tableDnD.currentTable.tableDnDConfig, + currentRow, + mousePos, + moving, + x, + y; + + e && e.preventDefault(); + + if (!$.tableDnD.dragObject) + return false; + + // prevent touch device screen scrolling + e.type === 'touchmove' + && event.preventDefault(); // TODO verify this is event and not really e + + // update the style to show we're dragging + config.onDragClass + && dragObj.addClass(config.onDragClass) + || dragObj.css(config.onDragStyle); + + mousePos = $.tableDnD.mouseCoords(e); + x = mousePos.x - $.tableDnD.mouseOffset.x; + y = mousePos.y - $.tableDnD.mouseOffset.y; + + // auto scroll the window + $.tableDnD.autoScroll(mousePos); + + currentRow = $.tableDnD.findDropTargetRow(dragObj, y); + moving = $.tableDnD.findDragDirection(x, y); + + $.tableDnD.moveVerticle(moving, currentRow); + $.tableDnD.moveHorizontal(moving, currentRow); + + return false; + }, + findDragDirection: function (x,y) { + var sensitivity = this.currentTable.tableDnDConfig.sensitivity, + oldX = this.oldX, + oldY = this.oldY, + xMin = oldX - sensitivity, + xMax = oldX + sensitivity, + yMin = oldY - sensitivity, + yMax = oldY + sensitivity, + moving = { + horizontal: x >= xMin && x <= xMax ? 0 : x > oldX ? -1 : 1, + vertical : y >= yMin && y <= yMax ? 0 : y > oldY ? -1 : 1 + }; + + // update the old value + if (moving.horizontal !== 0) + this.oldX = x; + if (moving.vertical !== 0) + this.oldY = y; + + return moving; + }, + /** We're only worried about the y position really, because we can only move rows up and down */ + findDropTargetRow: function(draggedRow, y) { + var rowHeight = 0, + rows = this.currentTable.rows, + config = this.currentTable.tableDnDConfig, + rowY = 0, + row = null; + + for (var i = 0; i < rows.length; i++) { + row = rows[i]; + rowY = this.getPosition(row).y; + rowHeight = parseInt(row.offsetHeight) / 2; + if (row.offsetHeight === 0) { + rowY = this.getPosition(row.firstChild).y; + rowHeight = parseInt(row.firstChild.offsetHeight) / 2; } - return data; + // Because we always have to insert before, we need to offset the height a bit + if (y > (rowY - rowHeight) && y < (rowY + rowHeight)) + // that's the row we're over + // If it's the same as the current row, ignore it + if (draggedRow.is(row) + || (config.onAllowDrop + && !config.onAllowDrop(draggedRow, row)) + // If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic) + || $(row).hasClass("nodrop")) + return null; + else + return row; } - }; - - jQuery.fn.extend( - { - tableDnD : $.tableDnD.build, - tableDnDUpdate : $.tableDnD.updateTables, - tableDnDSerialize : $.proxy($.tableDnD.serialize, $.tableDnD), - tableDnDSerializeAll : $.tableDnD.serializeTables, - tableDnDData : $.proxy($.tableDnD.tableData, $.tableDnD) + return null; + }, + processMouseup: function() { + if (!this.currentTable || !this.dragObject) + return null; + + var config = this.currentTable.tableDnDConfig, + droppedRow = this.dragObject, + parentLevel = 0, + myLevel = 0; + + // Unbind the event handlers + $(document) + .unbind(moveEvent, this.mousemove) + .unbind(endEvent, this.mouseup); + + config.hierarchyLevel + && config.autoCleanRelations + && $(this.currentTable.rows).first().find('td:first').children().each(function () { + myLevel = $(this).parents('tr:first').data('level'); + myLevel + && $(this).parents('tr:first').data('level', --myLevel) + && $(this).remove(); + }) + && config.hierarchyLevel > 1 + && $(this.currentTable.rows).each(function () { + myLevel = $(this).data('level'); + if (myLevel > 1) { + parentLevel = $(this).prev().data('level'); + while (myLevel > parentLevel + 1) { + $(this).find('td:first').children(':first').remove(); + $(this).data('level', --myLevel); + } + } + }); + + // If we have a dragObject, then we need to release it, + // The row will already have been moved to the right place so we just reset stuff + config.onDragClass + && $(droppedRow).removeClass(config.onDragClass) + || $(droppedRow).css(config.onDropStyle); + + this.dragObject = null; + // Call the onDrop method if there is one + config.onDrop + && this.originalOrder !== this.currentOrder() + && $(droppedRow).hide().fadeIn('fast') + && config.onDrop(this.currentTable, droppedRow); + + // Call the onDragStop method if there is one + config.onDragStop + && config.onDragStop(this.currentTable, droppedRow); + + this.currentTable = null; // let go of the table too + }, + mouseup: function(e) { + e && e.preventDefault(); + $.tableDnD.processMouseup(); + return false; + }, + jsonize: function(pretify) { + var table = this.currentTable; + if (pretify) + return JSON.stringify( + this.tableData(table), + null, + table.tableDnDConfig.jsonPretifySeparator + ); + return JSON.stringify(this.tableData(table)); + }, + serialize: function() { + return $.param(this.tableData(this.currentTable)); + }, + serializeTable: function(table) { + var result = ""; + var paramName = table.tableDnDConfig.serializeParamName || table.id; + var rows = table.rows; + for (var i=0; i 0) result += "&"; + var rowId = rows[i].id; + if (rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) { + rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0]; + result += paramName + '[]=' + rowId; + } } - ); - - }(jQuery, window, window.document); \ No newline at end of file + return result; + }, + serializeTables: function() { + var result = []; + $('table').each(function() { + this.id && result.push($.param($.tableDnD.tableData(this))); + }); + return result.join('&'); + }, + tableData: function (table) { + var config = table.tableDnDConfig, + previousIDs = [], + currentLevel = 0, + indentLevel = 0, + rowID = null, + data = {}, + getSerializeRegexp, + paramName, + currentID, + rows; + + if (!table) + table = this.currentTable; + if (!table || !table.rows || !table.rows.length) + return {error: { code: 500, message: "Not a valid table."}}; + if (!table.id && !config.serializeParamName) + return {error: { code: 500, message: "No serializable unique id provided."}}; + + rows = config.autoCleanRelations + && table.rows + || $.makeArray(table.rows); + paramName = config.serializeParamName || table.id; + currentID = paramName; + + getSerializeRegexp = function (rowId) { + if (rowId && config && config.serializeRegexp) + return rowId.match(config.serializeRegexp)[0]; + return rowId; + }; + + data[currentID] = []; + !config.autoCleanRelations + && $(rows[0]).data('level') + && rows.unshift({id: 'undefined'}); + + + + for (var i=0; i < rows.length; i++) { + if (config.hierarchyLevel) { + indentLevel = $(rows[i]).data('level') || 0; + if (indentLevel === 0) { + currentID = paramName; + previousIDs = []; + } + else if (indentLevel > currentLevel) { + previousIDs.push([currentID, currentLevel]); + currentID = getSerializeRegexp(rows[i-1].id); + } + else if (indentLevel < currentLevel) { + for (var h = 0; h < previousIDs.length; h++) { + if (previousIDs[h][1] === indentLevel) + currentID = previousIDs[h][0]; + if (previousIDs[h][1] >= currentLevel) + previousIDs[h][1] = 0; + } + } + currentLevel = indentLevel; + + if (!$.isArray(data[currentID])) + data[currentID] = []; + rowID = getSerializeRegexp(rows[i].id); + rowID && data[currentID].push(rowID); + } + else { + rowID = getSerializeRegexp(rows[i].id); + rowID && data[currentID].push(rowID); + } + } + return data; + } +}; + +jQuery.fn.extend( + { + tableDnD : $.tableDnD.build, + tableDnDUpdate : $.tableDnD.updateTables, + tableDnDSerialize : $.proxy($.tableDnD.serialize, $.tableDnD), + tableDnDSerializeAll : $.tableDnD.serializeTables, + tableDnDData : $.proxy($.tableDnD.tableData, $.tableDnD) + } +); + +}(jQuery, window, window.document); diff --git a/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.min.js b/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.min.js index be2c3a66b19..c07ff347456 100644 --- a/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.min.js +++ b/htdocs/includes/jquery/plugins/tablednd/jquery.tablednd.min.js @@ -1 +1,2 @@ -!function(t,e,a,n){a.documentElement;t(a).ready(function(){function e(t){for(var e={},a=t.match(/([^;:]+)/g)||[];a.length;)e[a.shift()]=a.shift().trim();return e}t("table").each(function(){"dnd"==t(this).data("table")&&t(this).tableDnD({onDragStyle:t(this).data("ondragstyle")&&e(t(this).data("ondragstyle"))||null,onDropStyle:t(this).data("ondropstyle")&&e(t(this).data("ondropstyle"))||null,onDragClass:void 0==t(this).data("ondragclass")&&"tDnD_whileDrag"||t(this).data("ondragclass"),onDrop:t(this).data("ondrop")&&new Function("table","row",t(this).data("ondrop")),onDragStart:t(this).data("ondragstart")&&new Function("table","row",t(this).data("ondragstart")),onDragStop:t(this).data("ondragstop")&&new Function("table","row",t(this).data("ondragstop")),scrollAmount:t(this).data("scrollamount")||5,sensitivity:t(this).data("sensitivity")||10,hierarchyLevel:t(this).data("hierarchylevel")||0,indentArtifact:t(this).data("indentartifact")||'
 
',autoWidthAdjust:t(this).data("autowidthadjust")||!0,autoCleanRelations:t(this).data("autocleanrelations")||!0,jsonPretifySeparator:t(this).data("jsonpretifyseparator")||"\t",serializeRegexp:t(this).data("serializeregexp")&&new RegExp(t(this).data("serializeregexp"))||/[^\-]*$/,serializeParamName:t(this).data("serializeparamname")||!1,dragHandle:t(this).data("draghandle")||null})})}),jQuery.tableDnD={currentTable:null,dragObject:null,mouseOffset:null,oldX:0,oldY:0,build:function(e){return this.each(function(){this.tableDnDConfig=t.extend({onDragStyle:null,onDropStyle:null,onDragClass:"tDnD_whileDrag",onDrop:null,onDragStart:null,onDragStop:null,scrollAmount:5,sensitivity:10,hierarchyLevel:0,indentArtifact:'
 
',autoWidthAdjust:!0,autoCleanRelations:!0,jsonPretifySeparator:"\t",serializeRegexp:/[^\-]*$/,serializeParamName:!1,dragHandle:null},e||{}),t.tableDnD.makeDraggable(this),this.tableDnDConfig.hierarchyLevel&&t.tableDnD.makeIndented(this)}),this},makeIndented:function(e){var a,n,i=e.tableDnDConfig,r=e.rows,l=t(r).first().find("td:first")[0],o=0,s=0;if(t(e).hasClass("indtd"))return null;n=t(e).addClass("indtd").attr("style"),t(e).css({whiteSpace:"nowrap"});for(var d=0;dt.vertical&&this.dragObject.parentNode.insertBefore(this.dragObject,e.nextSibling)||00&&t(a).find("td:first").children(":first").remove()&&t(a).data("level",--n),0>e.horizontal&&n=n&&t(a).children(":first").prepend(i.indentArtifact)&&t(a).data("level",++n)},mousemove:function(e){var a,n,i,r,l,o=t(t.tableDnD.dragObject),s=t.tableDnD.currentTable.tableDnDConfig;return e&&e.preventDefault(),!!t.tableDnD.dragObject&&("touchmove"==e.type&&event.preventDefault(),s.onDragClass&&o.addClass(s.onDragClass)||o.css(s.onDragStyle),n=t.tableDnD.mouseCoords(e),r=n.x-t.tableDnD.mouseOffset.x,l=n.y-t.tableDnD.mouseOffset.y,t.tableDnD.autoScroll(n),a=t.tableDnD.findDropTargetRow(o,l),i=t.tableDnD.findDragDirection(r,l),t.tableDnD.moveVerticle(i,a),t.tableDnD.moveHorizontal(i,a),!1)},findDragDirection:function(t,e){var a=this.currentTable.tableDnDConfig.sensitivity,n=this.oldX,i=this.oldY,r=n+a,l=i-a,o=i+a,s={horizontal:t>=n-a&&t<=r?0:t>n?-1:1,vertical:e>=l&&e<=o?0:e>i?-1:1};return 0!=s.horizontal&&(this.oldX=t),0!=s.vertical&&(this.oldY=e),s},findDropTargetRow:function(e,a){for(var n=0,i=this.currentTable.rows,r=this.currentTable.tableDnDConfig,l=0,o=null,s=0;sl-n&&a1&&t(this.currentTable.rows).each(function(){if((r=t(this).data("level"))>1)for(i=t(this).prev().data("level");r>i+1;)t(this).find("td:first").children(":first").remove(),t(this).data("level",--r)}),e.onDragClass&&t(n).removeClass(e.onDragClass)||t(n).css(e.onDropStyle),this.dragObject=null,e.onDrop&&this.originalOrder!=this.currentOrder()&&t(n).hide().fadeIn("fast")&&e.onDrop(this.currentTable,n),e.onDragStop&&e.onDragStop(this.currentTable,n),this.currentTable=null},mouseup:function(e){return e&&e.preventDefault(),t.tableDnD.processMouseup(),!1},jsonize:function(t){var e=this.currentTable;return t?JSON.stringify(this.tableData(e),null,e.tableDnDConfig.jsonPretifySeparator):JSON.stringify(this.tableData(e))},serialize:function(){return t.param(this.tableData(this.currentTable))},serializeTable:function(t){for(var e="",a=t.tableDnDConfig.serializeParamName||t.id,n=t.rows,i=0;i0&&(e+="&");var r=n[i].id;r&&t.tableDnDConfig&&t.tableDnDConfig.serializeRegexp&&(e+=a+"[]="+(r=r.match(t.tableDnDConfig.serializeRegexp)[0]))}return e},serializeTables:function(){var e=[];return t("table").each(function(){this.id&&e.push(t.param(t.tableDnD.tableData(this)))}),e.join("&")},tableData:function(e){var a,n,i,r,l=e.tableDnDConfig,o=[],s=0,d=0,h=null,u={};if(e||(e=this.currentTable),!e||!e.rows||!e.rows.length)return{error:{code:500,message:"Not a valid table."}};if(!e.id&&!l.serializeParamName)return{error:{code:500,message:"No serializable unique id provided."}};r=l.autoCleanRelations&&e.rows||t.makeArray(e.rows),a=function(t){return t&&l&&l.serializeRegexp?t.match(l.serializeRegexp)[0]:t},u[i=n=l.serializeParamName||e.id]=[],!l.autoCleanRelations&&t(r[0]).data("level")&&r.unshift({id:"undefined"});for(var c=0;cs)o.push([i,s]),i=a(r[c-1].id);else if(d=s&&(o[f][1]=0);s=d,t.isArray(u[i])||(u[i]=[]),(h=a(r[c].id))&&u[i].push(h)}else(h=a(r[c].id))&&u[i].push(h);return u}},jQuery.fn.extend({tableDnD:t.tableDnD.build,tableDnDUpdate:t.tableDnD.updateTables,tableDnDSerialize:t.proxy(t.tableDnD.serialize,t.tableDnD),tableDnDSerializeAll:t.tableDnD.serializeTables,tableDnDData:t.proxy(t.tableDnD.tableData,t.tableDnD)})}(jQuery,window,window.document); \ No newline at end of file +/*! jquery.tablednd.js 19-11-2017 */ +!function(a,b,c,d){var e=("ontouchstart"in c.documentElement,"touchstart mousedown"),f="touchmove mousemove",g="touchend mouseup";a(c).ready(function(){function b(a){for(var b={},c=a.match(/([^;:]+)/g)||[];c.length;)b[c.shift()]=c.shift().trim();return b}a("table").each(function(){"dnd"==a(this).data("table")&&a(this).tableDnD({onDragStyle:a(this).data("ondragstyle")&&b(a(this).data("ondragstyle"))||null,onDropStyle:a(this).data("ondropstyle")&&b(a(this).data("ondropstyle"))||null,onDragClass:a(this).data("ondragclass")===d&&"tDnD_whileDrag"||a(this).data("ondragclass"),onDrop:a(this).data("ondrop")&&new Function("table","row",a(this).data("ondrop")),onDragStart:a(this).data("ondragstart")&&new Function("table","row",a(this).data("ondragstart")),onDragStop:a(this).data("ondragstop")&&new Function("table","row",a(this).data("ondragstop")),scrollAmount:a(this).data("scrollamount")||5,sensitivity:a(this).data("sensitivity")||10,hierarchyLevel:a(this).data("hierarchylevel")||0,indentArtifact:a(this).data("indentartifact")||'
 
',autoWidthAdjust:a(this).data("autowidthadjust")||!0,autoCleanRelations:a(this).data("autocleanrelations")||!0,jsonPretifySeparator:a(this).data("jsonpretifyseparator")||" ",serializeRegexp:a(this).data("serializeregexp")&&new RegExp(a(this).data("serializeregexp"))||/[^\-]*$/,serializeParamName:a(this).data("serializeparamname")||!1,dragHandle:a(this).data("draghandle")||null})})}),jQuery.tableDnD={currentTable:null,dragObject:null,mouseOffset:null,oldX:0,oldY:0,build:function(b){return this.each(function(){this.tableDnDConfig=a.extend({onDragStyle:null,onDropStyle:null,onDragClass:"tDnD_whileDrag",onDrop:null,onDragStart:null,onDragStop:null,scrollAmount:5,sensitivity:10,hierarchyLevel:0,indentArtifact:'
 
',autoWidthAdjust:!0,autoCleanRelations:!0,jsonPretifySeparator:" ",serializeRegexp:/[^\-]*$/,serializeParamName:!1,dragHandle:null},b||{}),a.tableDnD.makeDraggable(this),this.tableDnDConfig.hierarchyLevel&&a.tableDnD.makeIndented(this)}),this},makeIndented:function(b){var c,d,e=b.tableDnDConfig,f=b.rows,g=a(f).first().find("td:first")[0],h=0,i=0;if(a(b).hasClass("indtd"))return null;d=a(b).addClass("indtd").attr("style"),a(b).css({whiteSpace:"nowrap"});for(var j=0;ja.vertical&&this.dragObject.parentNode.insertBefore(this.dragObject,b.nextSibling)||00&&a(c).find("td:first").children(":first").remove()&&a(c).data("level",--d),void(0>b.horizontal&&d=d&&a(c).children(":first").prepend(e.indentArtifact)&&a(c).data("level",++d))):null},mousemove:function(b){var c,d,e,f,g,h=a(a.tableDnD.dragObject),i=a.tableDnD.currentTable.tableDnDConfig;return b&&b.preventDefault(),a.tableDnD.dragObject?("touchmove"===b.type&&event.preventDefault(),i.onDragClass&&h.addClass(i.onDragClass)||h.css(i.onDragStyle),d=a.tableDnD.mouseCoords(b),f=d.x-a.tableDnD.mouseOffset.x,g=d.y-a.tableDnD.mouseOffset.y,a.tableDnD.autoScroll(d),c=a.tableDnD.findDropTargetRow(h,g),e=a.tableDnD.findDragDirection(f,g),a.tableDnD.moveVerticle(e,c),a.tableDnD.moveHorizontal(e,c),!1):!1},findDragDirection:function(a,b){var c=this.currentTable.tableDnDConfig.sensitivity,d=this.oldX,e=this.oldY,f=d-c,g=d+c,h=e-c,i=e+c,j={horizontal:a>=f&&g>=a?0:a>d?-1:1,vertical:b>=h&&i>=b?0:b>e?-1:1};return 0!==j.horizontal&&(this.oldX=a),0!==j.vertical&&(this.oldY=b),j},findDropTargetRow:function(b,c){for(var d=0,e=this.currentTable.rows,f=this.currentTable.tableDnDConfig,g=0,h=null,i=0;ig-d&&g+d>c)return b.is(h)||f.onAllowDrop&&!f.onAllowDrop(b,h)||a(h).hasClass("nodrop")?null:h;return null},processMouseup:function(){if(!this.currentTable||!this.dragObject)return null;var b=this.currentTable.tableDnDConfig,d=this.dragObject,e=0,h=0;a(c).unbind(f,this.mousemove).unbind(g,this.mouseup),b.hierarchyLevel&&b.autoCleanRelations&&a(this.currentTable.rows).first().find("td:first").children().each(function(){h=a(this).parents("tr:first").data("level"),h&&a(this).parents("tr:first").data("level",--h)&&a(this).remove()})&&b.hierarchyLevel>1&&a(this.currentTable.rows).each(function(){if(h=a(this).data("level"),h>1)for(e=a(this).prev().data("level");h>e+1;)a(this).find("td:first").children(":first").remove(),a(this).data("level",--h)}),b.onDragClass&&a(d).removeClass(b.onDragClass)||a(d).css(b.onDropStyle),this.dragObject=null,b.onDrop&&this.originalOrder!==this.currentOrder()&&a(d).hide().fadeIn("fast")&&b.onDrop(this.currentTable,d),b.onDragStop&&b.onDragStop(this.currentTable,d),this.currentTable=null},mouseup:function(b){return b&&b.preventDefault(),a.tableDnD.processMouseup(),!1},jsonize:function(a){var b=this.currentTable;return a?JSON.stringify(this.tableData(b),null,b.tableDnDConfig.jsonPretifySeparator):JSON.stringify(this.tableData(b))},serialize:function(){return a.param(this.tableData(this.currentTable))},serializeTable:function(a){for(var b="",c=a.tableDnDConfig.serializeParamName||a.id,d=a.rows,e=0;e0&&(b+="&");var f=d[e].id;f&&a.tableDnDConfig&&a.tableDnDConfig.serializeRegexp&&(f=f.match(a.tableDnDConfig.serializeRegexp)[0],b+=c+"[]="+f)}return b},serializeTables:function(){var b=[];return a("table").each(function(){this.id&&b.push(a.param(a.tableDnD.tableData(this)))}),b.join("&")},tableData:function(b){var c,d,e,f,g=b.tableDnDConfig,h=[],i=0,j=0,k=null,l={};if(b||(b=this.currentTable),!b||!b.rows||!b.rows.length)return{error:{code:500,message:"Not a valid table."}};if(!b.id&&!g.serializeParamName)return{error:{code:500,message:"No serializable unique id provided."}};f=g.autoCleanRelations&&b.rows||a.makeArray(b.rows),d=g.serializeParamName||b.id,e=d,c=function(a){return a&&g&&g.serializeRegexp?a.match(g.serializeRegexp)[0]:a},l[e]=[],!g.autoCleanRelations&&a(f[0]).data("level")&&f.unshift({id:"undefined"});for(var m=0;mi)h.push([e,i]),e=c(f[m-1].id);else if(i>j)for(var n=0;n=i&&(h[n][1]=0);i=j,a.isArray(l[e])||(l[e]=[]),k=c(f[m].id),k&&l[e].push(k)}else k=c(f[m].id),k&&l[e].push(k);return l}},jQuery.fn.extend({tableDnD:a.tableDnD.build,tableDnDUpdate:a.tableDnD.updateTables,tableDnDSerialize:a.proxy(a.tableDnD.serialize,a.tableDnD),tableDnDSerializeAll:a.tableDnD.serializeTables,tableDnDData:a.proxy(a.tableDnD.tableData,a.tableDnD)})}(jQuery,window,window.document); \ No newline at end of file