From b1d8a2efacfc929ff7e85198161e106f066d8024 Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Wed, 19 Feb 2020 11:33:14 -0300 Subject: [PATCH] Bug 24561: Add a Datatables api wrapper that implements filter and order embedded columns This patch adds the ability to filter and order by embedded columns. To use it you must in JS: $('datatable_selector').api({datatables_options}) where datatables_options are all datatables options plus: 1. embed: [list of embeddable tables] This option adds x-koha-embed header to request. 2. header_filter: true|false This option if true sets x-koha-query header with stringyfied json of filters Oderable and searchable columns must define data option as string, otherwise filter and order won't be possible. If you must custom the output, use the render function. For example: * Don't > $('.table_selector').api({ > columns: [ > { > data: function(row, type, val, meta) { > return ''+row.holds.patron.firstname+''; > }, > orderable: true, > searchable: true > } > ] > }); * Do > $('.table_selector').api({ > columns: [ > { > data: 'holds.patron.firstname', > render: function(row, type, val, meta) { > return ''+row.holds.patron.firstname+''; > }, > orderable: true, > searchable: true > } > ] > }); To test you must implement and test bug 20936, where it will be used. Signed-off-by: Kyle M Hall Signed-off-by: Tomas Cohen Arazi Signed-off-by: Jonathan Druart --- koha-tmpl/intranet-tmpl/prog/js/datatables.js | 91 +++++++++++++++++++ .../opac-tmpl/bootstrap/js/datatables.js | 91 +++++++++++++++++++ 2 files changed, 182 insertions(+) diff --git a/koha-tmpl/intranet-tmpl/prog/js/datatables.js b/koha-tmpl/intranet-tmpl/prog/js/datatables.js index 10845eb8db..a48112eda5 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/datatables.js +++ b/koha-tmpl/intranet-tmpl/prog/js/datatables.js @@ -502,3 +502,94 @@ function filterDataTable( table, column, term ){ table.search( term ).draw("page"); } } + +jQuery.fn.dataTable.ext.errMode = function(settings, note, message) { + console.warn(message); +}; + +(function($) { + + $.fn.api = function(options) { + var settings = null; + if(options) { + settings = $.extend(true, {}, dataTablesDefaults, { + 'deferRender': true, + "paging": true, + 'serverSide': true, + 'searching': true, + 'pagingType': 'full', + 'ajax': { + 'type': 'GET', + 'cache': true, + 'dataSrc': 'data', + 'beforeSend': function(xhr, settings) { + this._xhr = xhr; + if(options.embed) { + xhr.setRequestHeader('x-koha-embed', Array.isArray(options.embed)?options.embed.join(','):options.embed); + } + if(options.header_filter && options.query_parameters) { + xhr.setRequestHeader('x-koha-query', options.query_parameters); + delete options.query_parameters; + } + }, + 'dataFilter': function(data, type) { + var json = {data: JSON.parse(data)}; + if(total = this._xhr.getResponseHeader('x-total-count')) { + json.recordsTotal = total; + json.recordsFiltered = total; + } + return JSON.stringify(json); + }, + 'data': function( data, settings ) { + var length = data.length; + var start = data.start; + + var dataSet = { + _page: Math.floor(start/length) + 1, + _per_page: length + }; + + var filter = data.search.value; + var query_parameters = settings.aoColumns + .filter(function(col) { + return col.bSearchable && typeof col.data == 'string' && (data.columns[col.idx].search.value != '' || filter != '') + }) + .map(function(col) { + var part = {}; + part[!col.data.includes('.')?'me.'+col.data:col.data] = {like: (data.columns[col.idx].search.value != '' ? data.columns[col.idx].search.value : filter)+'%'}; + return part; + }); + + if(query_parameters.length) { + query_parameters = JSON.stringify(query_parameters.length === 1?query_parameters[0]:query_parameters); + if(options.header_filter) { + options.query_parameters = query_parameters; + } else { + dataSet.q = query_parameters; + delete options.query_parameters; + } + } else { + delete options.query_parameters; + } + + dataSet._match = 'starts_with'; + + if(options.columns) { + var order = data.order; + order.forEach(function (e,i) { + var order_col = e.column; + var order_by = options.columns[order_col].data; + var order_dir = e.dir == 'asc' ? '+' : '-'; + dataSet._order_by = order_dir + (!order_by.includes('.')?'me.'+order_by:order_by); + }); + } + + return dataSet; + } + } + }, options); + } + return $(this).dataTable(settings); + }; + +})(jQuery); diff --git a/koha-tmpl/opac-tmpl/bootstrap/js/datatables.js b/koha-tmpl/opac-tmpl/bootstrap/js/datatables.js index 53efbe3554..10dac7cd00 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/js/datatables.js +++ b/koha-tmpl/opac-tmpl/bootstrap/js/datatables.js @@ -123,3 +123,94 @@ jQuery.extend( jQuery.fn.dataTableExt.sort, { }); }()); + +jQuery.fn.dataTable.ext.errMode = function(settings, note, message) { + console.warn(message); +}; + +(function($) { + + $.fn.api = function(options) { + var settings = null; + if(options) { + settings = $.extend(true, {}, dataTablesDefaults, { + 'deferRender': true, + "paging": true, + 'serverSide': true, + 'searching': true, + 'pagingType': 'full', + 'ajax': { + 'type': 'GET', + 'cache': true, + 'dataSrc': 'data', + 'beforeSend': function(xhr, settings) { + this._xhr = xhr; + if(options.embed) { + xhr.setRequestHeader('x-koha-embed', Array.isArray(options.embed)?options.embed.join(','):options.embed); + } + if(options.header_filter && options.query_parameters) { + xhr.setRequestHeader('x-koha-query', options.query_parameters); + delete options.query_parameters; + } + }, + 'dataFilter': function(data, type) { + var json = {data: JSON.parse(data)}; + if(total = this._xhr.getResponseHeader('x-total-count')) { + json.recordsTotal = total; + json.recordsFiltered = total; + } + return JSON.stringify(json); + }, + 'data': function( data, settings ) { + var length = data.length; + var start = data.start; + + var dataSet = { + _page: Math.floor(start/length) + 1, + _per_page: length + }; + + var filter = data.search.value; + var query_parameters = settings.aoColumns + .filter(function(col) { + return col.bSearchable && typeof col.data == 'string' && (data.columns[col.idx].search.value != '' || filter != '') + }) + .map(function(col) { + var part = {}; + part[!col.data.includes('.')?'me.'+col.data:col.data] = {like: (data.columns[col.idx].search.value != '' ? data.columns[col.idx].search.value : filter)+'%'}; + return part; + }); + + if(query_parameters.length) { + query_parameters = JSON.stringify(query_parameters.length === 1?query_parameters[0]:query_parameters); + if(options.header_filter) { + options.query_parameters = query_parameters; + } else { + dataSet.q = query_parameters; + delete options.query_parameters; + } + } else { + delete options.query_parameters; + } + + dataSet._match = 'starts_with'; + + if(options.columns) { + var order = data.order; + order.forEach(function (e,i) { + var order_col = e.column; + var order_by = options.columns[order_col].data; + var order_dir = e.dir == 'asc' ? '+' : '-'; + dataSet._order_by = order_dir + (!order_by.includes('.')?'me.'+order_by:order_by); + }); + } + + return dataSet; + } + } + }, options); + } + return $(this).dataTable(settings); + }; + +})(jQuery); \ No newline at end of file -- 2.20.1