1 $(document).ready(function() {
3 // Illview Datatable setup
7 // Filters that are active
8 var activeFilters = {};
11 var prefilters = $('table#ill-requests').data('prefilters');
13 // Fields we need to expand (flatten)
21 // This is auto populated
27 prep: function(tableData, oData) {
29 tableData.forEach(function(row) {
31 if (row.status_alias) {
32 resolvedName = row.status_alias.lib;
34 resolvedName = getStatusName(
35 row.capabilities[row.status].name,
39 uniques[resolvedName] = 1
41 Object.keys(uniques).sort().forEach(function(unique) {
42 $('#illfilter_status').append(
43 '<option value="' + unique +
44 '">' + unique + '</option>'
48 listener: function() {
50 $('#illfilter_status').change(function() {
51 var sel = $('#illfilter_status option:selected').val();
52 if (sel && sel.length > 0) {
53 activeFilters[me] = function() {
54 table.api().column(13).search(sel);
57 if (activeFilters.hasOwnProperty(me)) {
58 delete activeFilters[me];
64 $('#illfilter_status').val('');
68 prep: function(tableData, oData) {
70 tableData.forEach(function(row) {
71 uniques[row.library_branchname] = 1
73 Object.keys(uniques).sort().forEach(function(unique) {
74 $('#illfilter_branchname').append(
75 '<option value="' + unique +
76 '">' + unique + '</option>'
80 listener: function() {
81 var me = 'pickupBranch';
82 $('#illfilter_branchname').change(function() {
83 var sel = $('#illfilter_branchname option:selected').val();
84 if (sel && sel.length > 0) {
85 activeFilters[me] = function() {
86 table.api().column(12).search(sel);
89 if (activeFilters.hasOwnProperty(me)) {
90 delete activeFilters[me];
96 $('#illfilter_branchname').val('');
100 listener: function() {
102 $('#illfilter_patron').change(function() {
103 var val = $('#illfilter_patron').val();
104 if (val && val.length > 0) {
105 activeFilters[me] = function() {
106 table.api().column(10).search(val);
109 if (activeFilters.hasOwnProperty(me)) {
110 delete activeFilters[me];
116 $('#illfilter_patron').val('');
120 listener: function () {
122 $('#illfilter_keyword').change(function () {
123 var val = $('#illfilter_keyword').val();
124 if (val && val.length > 0) {
125 activeFilters[me] = function () {
126 table.api().search(val);
129 if (activeFilters.hasOwnProperty(me)) {
130 delete activeFilters[me];
136 $('#illfilter_keyword').val('');
141 $('#illfilter_datemodified_start, #illfilter_datemodified_end').val('');
146 $('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val('');
149 }; //END Filterable columns
151 // Expand any fields we're expanding
152 var expandExpand = function(row) {
153 expand.forEach(function(thisExpand) {
154 if (row.hasOwnProperty(thisExpand)) {
155 if (!expanded.hasOwnProperty(thisExpand)) {
156 expanded[thisExpand] = [];
158 var expandObj = row[thisExpand];
159 Object.keys(expandObj).forEach(
160 function(thisExpandCol) {
161 var expColName = thisExpand + '_' + thisExpandCol.replace(/\s/g,'_');
162 // Keep a list of fields that have been expanded
163 // so we can create toggle links for them
164 if (expanded[thisExpand].indexOf(expColName) == -1) {
165 expanded[thisExpand].push(expColName);
167 expandObj[expColName] =
168 expandObj[thisExpandCol];
169 delete expandObj[thisExpandCol];
172 $.extend(true, row, expandObj);
173 delete row[thisExpand];
179 // Strip the expand prefix if it exists, we do this for display
180 var stripPrefix = function(value) {
181 expand.forEach(function(thisExpand) {
182 var regex = new RegExp(thisExpand + '_', 'g');
183 value = value.replace(regex, '');
188 // Our 'render' function for borrowerlink
189 var createPatronLink = function(data, type, row) {
190 var patronLink = '<a title="' + ill_borrower_details + '" ' +
191 'href="/cgi-bin/koha/members/moremember.pl?' +
192 'borrowernumber='+row.borrowernumber+'">';
193 if ( row.patron_firstname ) {
194 patronLink = patronLink + row.patron_firstname + ' ';
196 patronLink = patronLink + row.patron_surname +
197 ' (' + row.patron_cardnumber + ')' + '</a>';
201 // Our 'render' function for biblio_id
202 var createBiblioLink = function(data, type, row) {
203 return (row.biblio_id) ?
204 '<a title="' + ill_biblio_details + '" ' +
205 'href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' +
206 row.biblio_id + '">' +
211 // Our 'render' function for title
212 var createTitle = function(data, type, row) {
214 row.hasOwnProperty('metadata_container_title') &&
215 row.metadata_container_title
216 ) ? row.metadata_container_title : row.metadata_title;
219 // Render function for request ID
220 var createRequestId = function(data, type, row) {
221 return row.id_prefix + row.illrequest_id;
224 // Render function for type
225 var createType = function(data, type, row) {
226 if (!row.hasOwnProperty('metadata_Type') || !row.metadata_Type) {
227 if (row.hasOwnProperty('medium') && row.medium) {
228 row.metadata_Type = row.medium;
230 row.metadata_Type = null;
233 return row.metadata_Type;
236 // Render function for request status
237 var createStatus = function(data, type, row, meta) {
238 if (row.status_alias) {
239 return row.status_alias.lib
240 ? row.status_alias.lib
241 : row.status_alias.authorised_value;
243 var status_name = row.capabilities[row.status].name;
244 return getStatusName(status_name, row);
248 var getStatusName = function(origName, row) {
251 return ill_statuses.new;
253 return ill_statuses.req;
254 case "Requested from partners":
255 var statStr = ill_statuses.genreq;
257 row.hasOwnProperty('requested_partners') &&
258 row.requested_partners &&
259 row.requested_partners.length > 0
261 statStr += ' (' + row.requested_partners + ')';
264 case "Request reverted":
265 return ill_statuses.rev;
266 case "Queued request":
267 return ill_statuses.que;
268 case "Cancellation requested":
269 return ill_statuses.canc;
271 return ill_statuses.comp;
272 case "Delete request":
273 return ill_statuses.del;
279 // Render function for creating a row's action link
280 var createActionLink = function(data, type, row) {
281 return '<a class="btn btn-default btn-sm" ' +
282 'href="/cgi-bin/koha/ill/ill-requests.pl?' +
283 'method=illview&illrequest_id=' +
285 '">' + ill_manage + '</a>';
288 // Columns that require special treatment
291 func: createActionLink,
295 func: createRequestId
301 name: ill_columns.biblio_id,
302 func: createBiblioLink,
312 name: ill_columns.updated
316 func: createPatronLink
320 // Display the modal containing request supplier metadata
321 $('#ill-request-display-log').on('click', function(e) {
323 $('#requestLog').modal({show:true});
326 // Toggle request attributes in Illview
327 $('#toggle_requestattributes').on('click', function(e) {
329 $('#requestattributes').toggleClass('content_hidden');
332 // Toggle new comment form in Illview
333 $('#toggle_addcomment').on('click', function(e) {
335 $('#addcomment').toggleClass('content_hidden');
338 var illfilter_dateplaced_start = $("#illfilter_dateplaced_start").flatpickr({
339 onClose: function( selectedDates, dateText, instance) {
340 validate_date( selectedDates, instance );
341 illfilter_dateplaced_end.set('minDate', selectedDates[0]);
345 var illfilter_dateplaced_end = $("#illfilter_dateplaced_end").flatpickr({
346 onClose: function( selectedDates, dateText, instance) {
347 validate_date( selectedDates, instance );
351 var illfilter_datemodified_start = $("#illfilter_datemodified_start").flatpickr({
352 onClose: function( selectedDates, dateText, instance) {
353 validate_date( selectedDates, instance );
354 illfilter_datemodified_end.set('minDate', selectedDates[0]);
358 var illfilter_datemodified_end = $("#illfilter_datemodified_end").flatpickr({
359 onClose: function( selectedDates, dateText, instance) {
360 validate_date( selectedDates, instance );
364 // Filter partner list
365 // Record the list of all options
366 var ill_partner_options = $('#partners > option');
367 $('#partner_filter').keyup(function() {
368 var needle = $('#partner_filter').val();
369 var regex = new RegExp(needle, 'i');
371 ill_partner_options.each(function() {
373 needle.length == 0 ||
374 $(this).is(':selected') ||
375 $(this).text().match(regex)
377 filtered.push($(this));
380 $('#partners').empty().append(filtered);
383 // Display the modal containing request supplier metadata
384 $('#ill-request-display-metadata').on('click', function(e) {
386 $('#dataPreview').modal({show:true});
389 // Allow us to chain Datatable render helpers together, so we
390 // can use our custom functions and render.text(), which
391 // provides us with data sanitization
392 $.fn.dataTable.render.multi = function(renderArray) {
393 return function(d, type, row, meta) {
394 for(var r = 0; r < renderArray.length; r++) {
395 var toCall = renderArray[r].hasOwnProperty('display') ?
396 renderArray[r].display :
398 d = toCall(d, type, row, meta);
404 // Get our data from the API and process it prior to passing
406 var filterParam = prefilters ? '&' + prefilters : '';
407 // Only fire the request if we're on an appropriate page
410 // ILL list requests page
411 window.location.href.match(/ill\/ill-requests\.pl/) &&
412 window.location.search.length == 0
414 // Patron profile page
415 window.location.href.match(/members\/ill-requests\.pl/)
418 '/api/v1/illrequests?embed=metadata,patron,capabilities,library,status_alias,comments,requested_partners'
421 var data = JSON.parse(ajax.responseText);
422 // Make a copy, we'll be removing columns next and need
423 // to be able to refer to data that has been removed
424 var dataCopy = $.extend(true, [], data);
425 // Expand columns that need it and create an array
426 // of all column names
427 $.each(dataCopy, function(k, row) {
431 // Assemble an array of column definitions for passing
434 columns_settings.forEach(function(thisCol) {
435 var colName = thisCol.columnname;
436 // Create the base column object
437 var colObj = $.extend({}, thisCol);
438 colObj.name = colName;
439 colObj.className = colName;
440 colObj.defaultContent = '';
442 // We may need to process the data going in this
443 // column, so do it if necessary
445 specialCols.hasOwnProperty(colName) &&
446 specialCols[colName].hasOwnProperty('func')
449 specialCols[colName].func
451 if (!specialCols[colName].skipSanitize) {
453 $.fn.dataTable.render.text()
457 colObj.render = $.fn.dataTable.render.multi(
461 colObj.data = colName;
462 colObj.render = $.fn.dataTable.render.text()
464 // Make sure properties that aren't present in the API
465 // response are populated with null to avoid Datatables
466 // choking on their absence
467 dataCopy.forEach(function(thisData) {
468 if (!thisData.hasOwnProperty(colName)) {
469 thisData[colName] = null;
472 colData.push(colObj);
475 // Initialise the datatable
476 table = KohaTable("ill-requests", {
478 { // Last column shouldn't be sortable or searchable
479 'aTargets': [ 'actions' ],
483 { // When sorting 'placed', we want to use the
484 // unformatted column
485 'aTargets': [ 'placed_formatted'],
488 { // When sorting 'updated', we want to use the
489 // unformatted column
490 'aTargets': [ 'updated_formatted'],
493 { // When sorting 'completed', we want to use the
494 // unformatted column
495 'aTargets': [ 'completed_formatted'],
499 'aaSorting': [[ 16, 'desc' ]], // Default sort, updated descending
500 'processing': true, // Display a message when manipulating
501 'sPaginationType': "full_numbers", // Pagination display
502 'deferRender': true, // Improve performance on big datasets
504 "dom": '<"top pager"<"table_entries"ilp><"table_controls"B>>tr<"bottom pager"ip>',
506 'originalData': data, // Enable render functions to access
508 'initComplete': function() {
510 // Prepare any filter elements that need it
511 for (var el in filterable) {
512 if (filterable.hasOwnProperty(el)) {
513 if (filterable[el].hasOwnProperty('prep')) {
514 filterable[el].prep(dataCopy, data);
516 if (filterable[el].hasOwnProperty('listener')) {
517 filterable[el].listener();
523 }, columns_settings);
525 // Custom date range filtering
526 $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
527 var placedStart = illfilter_dateplaced_start.selectedDates[0];
528 var placedEnd = illfilter_dateplaced_end.selectedDates[0];
529 var modifiedStart = illfilter_datemodified_start.selectedDates[0];
530 var modifiedEnd = illfilter_datemodified_end.selectedDates[0];
531 var rowPlaced = data[14] ? new Date(data[14]) : null;
532 var rowModified = data[16] ? new Date(data[16]) : null;
533 var placedPassed = true;
534 var modifiedPassed = true;
535 if (placedStart && rowPlaced && rowPlaced < placedStart) {
538 if (placedEnd && rowPlaced && rowPlaced > placedEnd) {
539 placedPassed = false;
541 if (modifiedStart && rowModified && rowModified < modifiedStart) {
542 modifiedPassed = false
544 if (modifiedEnd && rowModified && rowModified > modifiedEnd) {
545 modifiedPassed = false;
548 return placedPassed && modifiedPassed;
553 } //END if window.location.search.length == 0
555 var clearSearch = function() {
556 table.api().search('').columns().search('');
558 for (var filter in filterable) {
560 filterable.hasOwnProperty(filter) &&
561 filterable[filter].hasOwnProperty('clear')
563 filterable[filter].clear();
569 // Apply any search filters, or clear any previous
571 $('#illfilter_form').submit(function(event) {
572 event.preventDefault();
573 table.api().search('').columns().search('');
574 for (var active in activeFilters) {
575 if (activeFilters.hasOwnProperty(active)) {
576 activeFilters[active]();
583 $('#clear_search').click(function() {