From 81d12ad2641a739623254d41357a42de969ecb29 Mon Sep 17 00:00:00 2001 From: Owen Leonard Date: Mon, 30 Oct 2023 17:53:41 +0000 Subject: [PATCH] Bug 35249: Use DataTables RowReorder extension instead of tableDND jQuery plugin Signed-off-by: Jonathan Druart Signed-off-by: Nick Clemens Signed-off-by: Katrin Fischer --- .../datatables/dataTables.rowReorder.min.js | 4 + .../datatables/rowReorder.dataTables.min.css | 36 + .../lib/jquery/plugins/jquery.tablednd.js | 672 ------------------ .../prog/css/src/staff-global.scss | 20 +- .../searchengine/elasticsearch/mappings.tt | 12 +- .../prog/js/elasticsearch-mappings.js | 15 +- 6 files changed, 70 insertions(+), 689 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/lib/datatables/dataTables.rowReorder.min.js create mode 100644 koha-tmpl/intranet-tmpl/lib/datatables/rowReorder.dataTables.min.css delete mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.tablednd.js diff --git a/koha-tmpl/intranet-tmpl/lib/datatables/dataTables.rowReorder.min.js b/koha-tmpl/intranet-tmpl/lib/datatables/dataTables.rowReorder.min.js new file mode 100644 index 0000000000..19c1e8a656 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/lib/datatables/dataTables.rowReorder.min.js @@ -0,0 +1,4 @@ +/*! RowReorder 1.4.1 + * © SpryMedia Ltd - datatables.net/license + */ +!function(o){var r,n;"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(t){return o(t,window,document)}):"object"==typeof exports?(r=require("jquery"),n=function(t,e){e.fn.dataTable||require("datatables.net")(t,e)},"undefined"==typeof window?module.exports=function(t,e){return t=t||window,e=e||r(t),n(t,e),o(e,t,t.document)}:(n(window,r),module.exports=o(r,window,window.document))):o(jQuery,window,document)}(function(v,d,a,s){"use strict";function i(t,e){if(!l.versionCheck||!l.versionCheck("1.10.8"))throw"DataTables RowReorder requires DataTables 1.10.8 or newer";if(this.c=v.extend(!0,{},l.defaults.rowReorder,i.defaults,e),this.s={bodyTop:null,dt:new l.Api(t),getDataFn:l.ext.oApi._fnGetObjectDataFn(this.c.dataSrc),middles:null,scroll:{},scrollInterval:null,setDataFn:l.ext.oApi._fnSetObjectDataFn(this.c.dataSrc),start:{top:0,left:0,offsetTop:0,offsetLeft:0,nodes:[],rowIndex:0},windowHeight:0,documentOuterHeight:0,domCloneOuterHeight:0,dropAllowed:!0},this.dom={clone:null,cloneParent:null,dtScroll:v("div.dataTables_scrollBody",this.s.dt.table().container())},e=this.s.dt.settings()[0],t=e.rowreorder)return t;this.dom.dtScroll.length||(this.dom.dtScroll=v(this.s.dt.table().container(),"tbody")),(e.rowreorder=this)._constructor()}var l=v.fn.dataTable,t=(v.extend(i.prototype,{_constructor:function(){var r=this,n=this.s.dt,t=v(n.table().node());"static"===t.css("position")&&t.css("position","relative"),v(n.table().container()).on("mousedown.rowReorder touchstart.rowReorder",this.c.selector,function(t){var e,o;if(r.c.enable)return!!v(t.target).is(r.c.excludedChildren)||(e=v(this).closest("tr"),(o=n.row(e)).any()?(r._emitEvent("pre-row-reorder",{node:o.node(),index:o.index()}),r._mouseDown(t,e),!1):void 0)}),n.on("destroy.rowReorder",function(){v(n.table().container()).off(".rowReorder"),n.off(".rowReorder")}),this._keyup=this._keyup.bind(this)},_cachePositions:function(){var t=this.s.dt,r=v(t.table().node()).find("thead").outerHeight(),e=v.unique(t.rows({page:"current"}).nodes().toArray()),e=v.map(e,function(t,e){var o=v(t).position().top-r;return(o+o+v(t).outerHeight())/2});this.s.middles=e,this.s.bodyTop=v(t.table().body()).offset().top,this.s.windowHeight=v(d).height(),this.s.documentOuterHeight=v(a).outerHeight(),this.s.bodyArea=this._calcBodyArea()},_clone:function(t){var e=this.s.dt,e=v(e.table().node().cloneNode(!1)).addClass("dt-rowReorder-float").append("").append(t.clone(!1)),o=t.outerWidth(),r=t.outerHeight(),n=v(v(this.s.dt.table().node()).parent()),s=n.width(),n=n.scrollLeft(),i=t.children().map(function(){return v(this).width()}),t=(e.width(o).height(r).find("tr").children().each(function(t){this.style.width=i[t]+"px"}),v("
").addClass("dt-rowReorder-float-parent").width(s).append(e).appendTo("body").scrollLeft(n));this.dom.clone=e,this.dom.cloneParent=t,this.s.domCloneOuterHeight=e.outerHeight()},_clonePosition:function(t){var e=this.s.start,o=this._eventToPage(t,"Y")-e.top,t=this._eventToPage(t,"X")-e.left,r=this.c.snapX,o=o+e.offsetTop,r=!0===r?e.offsetLeft:"number"==typeof r?e.offsetLeft+r:t+e.offsetLeft+this.dom.cloneParent.scrollLeft();o<0?o=0:o+this.s.domCloneOuterHeight>this.s.documentOuterHeight&&(o=this.s.documentOuterHeight-this.s.domCloneOuterHeight),this.dom.cloneParent.css({top:o,left:r})},_emitEvent:function(o,r){var n;return this.s.dt.iterator("table",function(t,e){t=v(t.nTable).triggerHandler(o+".dt",r);t!==s&&(n=t)}),n},_eventToPage:function(t,e){return(-1!==t.type.indexOf("touch")?t.originalEvent.touches[0]:t)["page"+e]},_mouseDown:function(t,e){var o=this,r=this.s.dt,n=this.s.start,s=this.c.cancelable,i=e.offset(),i=(n.top=this._eventToPage(t,"Y"),n.left=this._eventToPage(t,"X"),n.offsetTop=i.top,n.offsetLeft=i.left,n.nodes=v.unique(r.rows({page:"current"}).nodes().toArray()),this._cachePositions(),this._clone(e),this._clonePosition(t),this._eventToPage(t,"Y")-this.s.bodyTop),r=(n.rowIndex=this._calcRowIndexByPos(i),(this.dom.target=e).addClass("dt-rowReorder-moving"),v(a).on("mouseup.rowReorder touchend.rowReorder",function(t){o._mouseUp(t)}).on("mousemove.rowReorder touchmove.rowReorder",function(t){o._mouseMove(t)}),v(d).width()===v(a).width()&&v(a.body).addClass("dt-rowReorder-noOverflow"),this.dom.dtScroll);this.s.scroll={windowHeight:v(d).height(),windowWidth:v(d).width(),dtTop:r.length?r.offset().top:null,dtLeft:r.length?r.offset().left:null,dtHeight:r.length?r.outerHeight():null,dtWidth:r.length?r.outerWidth():null},s&&v(a).on("keyup",this._keyup)},_mouseMove:function(t){this._clonePosition(t);for(var e,o,r=this.s.start,n=this.c.cancelable,s=(n&&(e=this.s.bodyArea,o=this._calcCloneParentArea(),this.s.dropAllowed=this._rectanglesIntersect(e,o),this.s.dropAllowed?v(this.dom.cloneParent).removeClass("drop-not-allowed"):v(this.dom.cloneParent).addClass("drop-not-allowed")),this._eventToPage(t,"Y")-this.s.bodyTop),i=this.s.middles,d=null,a=0,l=i.length;athis.s.lastInsert?r.rowIndex+1:r.rowIndex),this.dom.target.toggleClass("dt-rowReorder-moving",this.s.dropAllowed)),this._moveTargetIntoPosition(d),this._shiftScroll(t)},_mouseUp:function(t){var e=this,o=this.s.dt,r=this.c.dataSrc;if(this.s.dropAllowed){for(var n,s,i,d=this.s.start.nodes,a=v.unique(o.rows({page:"current"}).nodes().toArray()),l={},c=[],h=[],u=this.s.getDataFn,f=this.s.setDataFn,w=0,p=d.length;wthis.s.lastInsert?(this.dom.target.insertAfter(e[t-1]),"after"):(this.dom.target.insertBefore(e[t]),"before"),this._cachePositions(),this.s.lastInsert=t,this._emitEvent("row-reorder-changed",{insertPlacement:o,insertPoint:t,row:r.row(this.dom.target)}))},_cleanupDragging:function(){var t=this.c.cancelable;this.dom.clone.remove(),this.dom.cloneParent.remove(),this.dom.clone=null,this.dom.cloneParent=null,this.dom.target.removeClass("dt-rowReorder-moving"),v(a).off(".rowReorder"),v(a.body).removeClass("dt-rowReorder-noOverflow"),clearInterval(this.s.scrollInterval),this.s.scrollInterval=null,t&&v(a).off("keyup",this._keyup)},_shiftScroll:function(t){var e,o,r=this,n=(this.s.dt,this.s.scroll),s=!1,i=t.pageY-a.body.scrollTop;in.windowHeight+v(d).scrollTop()-65&&(e=5),null!==n.dtTop&&t.pageYn.dtTop+n.dtHeight-65&&(o=5),e||o?(n.windowVert=e,n.dtVert=o,s=!0):this.s.scrollInterval&&(clearInterval(this.s.scrollInterval),this.s.scrollInterval=null),!this.s.scrollInterval&&s&&(this.s.scrollInterval=setInterval(function(){var t;n.windowVert&&(t=v(a).scrollTop(),v(a).scrollTop(t+n.windowVert),t!==v(a).scrollTop())&&(t=parseFloat(r.dom.cloneParent.css("top")),r.dom.cloneParent.css("top",t+n.windowVert)),n.dtVert&&(t=r.dom.dtScroll[0],n.dtVert)&&(t.scrollTop+=n.dtVert)},20))},_calcBodyArea:function(t){var e=this.s.dt,o=v(e.table().body()).offset();return{left:o.left,top:o.top,right:o.left+v(e.table().body()).width(),bottom:o.top+v(e.table().body()).height()}},_calcCloneParentArea:function(t){this.s.dt;var e=v(this.dom.cloneParent).offset();return{left:e.left,top:e.top,right:e.left+v(this.dom.cloneParent).width(),bottom:e.top+v(this.dom.cloneParent).height()}},_rectanglesIntersect:function(t,e){return!(t.left>=e.right||e.left>=t.right||t.top>=e.bottom||e.top>=t.bottom)},_calcRowIndexByPos:function(r){var t=this.s.dt,e=v.unique(t.rows({page:"current"}).nodes().toArray()),n=-1,s=v(t.table().node()).find("thead").outerHeight();return v.each(e,function(t,e){var o=v(e).position().top-s,e=o+v(e).outerHeight();o<=r&&r<=e&&(n=t)}),n},_keyup:function(t){this.c.cancelable&&27===t.which&&(t.preventDefault(),this._cancel())},_cancel:function(){var t=this.s.start,t=t.rowIndex>this.s.lastInsert?t.rowIndex+1:t.rowIndex;this._moveTargetIntoPosition(t),this._cleanupDragging(),this._emitEvent("row-reorder-canceled",[this.s.start.rowIndex])}}),i.defaults={dataSrc:0,editor:null,enable:!0,formOptions:{},selector:"td:first-child",snapX:!1,update:!0,excludedChildren:"a",cancelable:!1},v.fn.dataTable.Api);return t.register("rowReorder()",function(){return this}),t.register("rowReorder.enable()",function(e){return e===s&&(e=!0),this.iterator("table",function(t){t.rowreorder&&(t.rowreorder.c.enable=e)})}),t.register("rowReorder.disable()",function(){return this.iterator("table",function(t){t.rowreorder&&(t.rowreorder.c.enable=!1)})}),i.version="1.4.1",v.fn.dataTable.RowReorder=i,v.fn.DataTable.RowReorder=i,v(a).on("init.dt.dtr",function(t,e,o){var r,n;"dt"===t.namespace&&(t=e.oInit.rowReorder,r=l.defaults.rowReorder,t||r)&&(n=v.extend({},t,r),!1!==t)&&new i(e,n)}),l}); \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/lib/datatables/rowReorder.dataTables.min.css b/koha-tmpl/intranet-tmpl/lib/datatables/rowReorder.dataTables.min.css new file mode 100644 index 0000000000..ced1e62583 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/lib/datatables/rowReorder.dataTables.min.css @@ -0,0 +1,36 @@ +div.dt-rowReorder-float-parent { + table-layout: fixed; + outline: 2px solid green; + z-index: 2001; + position: absolute !important; + overflow: hidden; + border-radius: 0; +} +div.dt-rowReorder-float-parent table.dt-rowReorder-float { + opacity: 0.9; + background-color: white; + margin: 0 !important; +} +div.dt-rowReorder-float-parent.drop-not-allowed { + cursor: not-allowed; +} +tr.dt-rowReorder-moving { + outline: 2px solid #888; + outline-offset: -2px; +} +body.dt-rowReorder-noOverflow { + overflow-x: hidden; +} +table.dataTable td.reorder { + text-align: center; + cursor: move; +} +html.dark div.dt-rowReorder-float-parent { + outline-color: #52ceff; +} +html.dark div.dt-rowReorder-float-parent table.dt-rowReorder-float { + background-color: var(--dt-html-background); +} +html.dark tr.dt-rowReorder-moving { + outline-color: #aaa; +} diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.tablednd.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.tablednd.js deleted file mode 100644 index f0bd3329cd..0000000000 --- a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.tablednd.js +++ /dev/null @@ -1,672 +0,0 @@ -/** - * 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. - * 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 - */ -!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'; - -// If we're on a touch device, then wire up the events -// see http://stackoverflow.com/a/8456194/1316086 -hasTouch - && $.each("touchstart touchmove touchend".split(" "), function(i, name) { - $.event.fixHooks[name] = $.event.mouseHooks; - }); - - -$(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, - 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, - 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; - } - 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); - - 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; - } - } - return result; - }, - serializeTables: function() { - var result = []; - $('table').each(function() { - this.id && result.push($.param(this.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.id || !table.rows || !table.rows.length) - return {error: { code: 500, message: "Not a valid table, 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/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss index 28beabafc7..b88f1aad05 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss +++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss @@ -4131,6 +4131,16 @@ input.renew { } } +.drag_handle { + cursor: move; + margin-right: 6px; +} + +.drag_placeholder { + border: 1px dotted #AAA; + height: 2em; +} + #manage_stages { ul { padding-left: 0; @@ -4163,16 +4173,6 @@ input.renew { background-color: #F3F3F3; } - .drag_handle { - cursor: move; - margin-right: 6px; - } - - .drag_placeholder { - border: 1px dotted #AAA; - height: 2em; - } - h3 { display: inline-block; } diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt index fb25bed28e..d98c0c903a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt @@ -9,6 +9,7 @@ [% t("Koha") | html %] [% END %] [% INCLUDE 'doc-head-close.inc' %] +