Bug 20600: (follow-up) Move template JavaScript to the footer

This patch moves the ILL requests template's JavaScript to the footer.

Also changed:
 - Removed unused jQuery checkboxes plugin
 - Some <input> tags have been corrected to be self-closing.
 - Title tag has been corrected
 - Table row limit of 10 has been removed in favor of accepting default
   used elsewhere.

To test, apply the patch and follow the original test plan for this bug.
Everything should work as expected.

Signed-off-by: Andrew Isherwood <andrew.isherwood@ptfs-europe.com>

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
This commit is contained in:
Owen Leonard 2018-06-05 14:24:00 +00:00 committed by Nick Clemens
parent 07ab5ab1f7
commit 7ab87c2dcd
1 changed files with 497 additions and 8 deletions

View File

@ -3,9 +3,9 @@
[% USE Branches %]
[% USE Koha %]
[% USE KohaDates %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; ILL requests &rsaquo;</title>
<title>Koha &rsaquo; ILL requests</title>
[% INCLUDE 'doc-head-close.inc' %]
[% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") | $raw %]
[% Asset.css("css/datatables.css") | $raw %]
@ -551,19 +551,19 @@
</li>
<li>
<label for="illfilter_dateplaced_start">Date placed between:</label>
<input type="text" name="illfilter_dateplaced_start" id="illfilter_dateplaced_start" class="datepicker">
<input type="text" name="illfilter_dateplaced_start" id="illfilter_dateplaced_start" class="datepicker" />
</li>
<li>
<label for="illfilter_dateplaced_end">and:</label>
<input type="text" name="illfilter_dateplaced_end" id="illfilter_dateplaced_end" class="datepicker">
<input type="text" name="illfilter_dateplaced_end" id="illfilter_dateplaced_end" class="datepicker" />
</li>
<li>
<label for="illfilter_datemodified_start">Updated between:</label>
<input type="text" name="illfilter_datemodified_start" id="illfilter_datemodified_start" class="datepicker">
<input type="text" name="illfilter_datemodified_start" id="illfilter_datemodified_start" class="datepicker" />
</li>
<li>
<label for="illfilter_datemodified_end">and:</label>
<input type="text" name="illfilter_datemodified_end" id="illfilter_datemodified_end" class="datepicker">
<input type="text" name="illfilter_datemodified_end" id="illfilter_datemodified_end" class="datepicker" />
</li>
<li>
<label for="illfilter_branchname">Library:</label>
@ -573,7 +573,7 @@
</li>
<li>
<label for="illfilter_barcode">Patron barcode:</label>
<input type="text" name="illfilter_barcode" id="illfilter_barcode">
<input type="text" name="illfilter_barcode" id="illfilter_barcode" />
</li>
</ol>
<fieldset class="action">
@ -639,7 +639,7 @@
<ol>
<li>
<label for="partner_filter">Filter partner libraries:</label>
<input type="text" id="partner_filter">
<input type="text" id="partner_filter" />
</li>
<li>
<label for="partners" class="required">Select partner libraries:</label>
@ -1001,4 +1001,493 @@
[% CATCH %]
[% END %]
[% MACRO jsinclude BLOCK %]
[% INCLUDE 'datatables.inc' %]
[% INCLUDE 'calendar.inc' %]
<script>
$(document).ready(function() {
// Illview Datatable setup
var table;
// Filters that are active
var activeFilters = {};
// Fields we don't want to display
var ignore = [
'accessurl',
'backend',
'branchcode',
'completed',
'capabilities',
'cost',
'medium',
'notesopac',
'notesstaff',
'replied'
];
// Fields we need to expand (flatten)
var expand = [
'metadata',
'patron'
];
// Expanded fields
// This is auto populated
var expanded = {};
// The core fields that should be displayed first
var core = [
'metadata_Author',
'metadata_Title',
'borrowername',
'patron_cardnumber',
'biblio_id',
'library',
'status',
'placed',
'placed_formatted',
'updated',
'updated_formatted',
'illrequest_id',
'action'
];
// Filterable columns
var filterable = {
status: {
prep: function(tableData, oData) {
var uniques = {};
tableData.forEach(function(row) {
var resolvedName = getStatusName(
oData[0].capabilities[row.status].name
);
uniques[resolvedName] = 1
});
Object.keys(uniques).sort().forEach(function(unique) {
$('#illfilter_status').append(
'<option value="' + unique +
'">' + unique + '</option>'
);
});
},
listener: function() {
var me = 'status';
$('#illfilter_status').change(function() {
var sel = $('#illfilter_status option:selected').val();
if (sel && sel.length > 0) {
activeFilters[me] = function() {
table.column(6).search(sel);
}
} else {
if (activeFilters.hasOwnProperty(me)) {
delete activeFilters[me];
}
}
});
},
clear: function() {
$('#illfilter_status').val('');
}
},
pickupBranch: {
prep: function(tableData, oData) {
var uniques = {};
tableData.forEach(function(row) {
uniques[row.library.branchname] = 1
});
Object.keys(uniques).sort().forEach(function(unique) {
$('#illfilter_branchname').append(
'<option value="' + unique +
'">' + unique + '</option>'
);
});
},
listener: function() {
var me = 'pickupBranch';
$('#illfilter_branchname').change(function() {
var sel = $('#illfilter_branchname option:selected').val();
if (sel && sel.length > 0) {
activeFilters[me] = function() {
table.column(5).search(sel);
}
} else {
if (activeFilters.hasOwnProperty(me)) {
delete activeFilters[me];
}
}
});
},
clear: function() {
$('#illfilter_branchname').val('');
}
},
barcode: {
listener: function() {
var me = 'barcode';
$('#illfilter_barcode').change(function() {
var val = $('#illfilter_barcode').val();
if (val && val.length > 0) {
activeFilters[me] = function() {
table.column(3).search(val);
}
} else {
if (activeFilters.hasOwnProperty(me)) {
delete activeFilters[me];
}
}
});
},
clear: function() {
$('#illfilter_barcode').val('');
}
},
dateModified: {
clear: function() {
$('#illfilter_datemodified_start, #illfilter_datemodified_end').val('');
}
},
datePlaced: {
clear: function() {
$('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val('');
}
}
};
// Remove any fields we're ignoring
var removeIgnore = function(dataObj) {
dataObj.forEach(function(thisRow) {
ignore.forEach(function(thisIgnore) {
if (thisRow.hasOwnProperty(thisIgnore)) {
delete thisRow[thisIgnore];
}
});
});
};
// Expand any fields we're expanding
var expandExpand = function(row) {
expand.forEach(function(thisExpand) {
if (row.hasOwnProperty(thisExpand)) {
if (!expanded.hasOwnProperty(thisExpand)) {
expanded[thisExpand] = [];
}
var expandObj = row[thisExpand];
Object.keys(expandObj).forEach(
function(thisExpandCol) {
var expColName = thisExpand + '_' + thisExpandCol;
// Keep a list of fields that have been expanded
// so we can create toggle links for them
if (expanded[thisExpand].indexOf(expColName) == -1) {
expanded[thisExpand].push(expColName);
}
expandObj[expColName] =
expandObj[thisExpandCol];
delete expandObj[thisExpandCol];
}
);
$.extend(true, row, expandObj);
delete row[thisExpand];
}
});
};
// Build a de-duped list of all column names
var allCols = {};
core.map(function(thisCore) {
allCols[thisCore] = 1;
});
// Strip the expand prefix if it exists, we do this for display
var stripPrefix = function(value) {
expand.forEach(function(thisExpand) {
var regex = new RegExp(thisExpand + '_', 'g');
value = value.replace(regex, '');
});
return value;
};
// Our 'render' function for borrowerlink
var createPatronLink = function(data, type, row) {
return '<a title="' + _("View borrower details") + '" ' +
'href="/cgi-bin/koha/members/moremember.pl?' +
'borrowernumber='+row.borrowernumber+'">' +
row.patron_firstname + ' ' + row.patron_surname +
'</a>';
};
// Our 'render' function for the library name
var createLibrary = function(data, type, row) {
return row.library.branchname;
};
// Render function for request ID
var createRequestId = function(data, type, row) {
return row.id_prefix + row.illrequest_id;
};
// Render function for request status
var createStatus = function(data, type, row, meta) {
var origData = meta.settings.oInit.originalData;
if (origData.length > 0) {
var status_name = meta.settings.oInit.originalData[0].capabilities[
row.status
].name;
return getStatusName(status_name);
} else {
return '';
}
};
var getStatusName = function(origName) {
switch( origName ) {
case "New request":
return _("New request");
case "Requested":
return _("Requested");
case "Requested from partners":
return _("Requested from partners");
case "Request reverted":
return _("Request reverted");
case "Queued request":
return _("Queued request");
case "Cancellation requested":
return _("Cancellation requested");
case "Completed":
return _("Completed");
case "Delete request":
return _("Delete request");
default:
return origName;
}
};
// Render function for creating a row's action link
var createActionLink = function(data, type, row) {
return '<a class="btn btn-default btn-sm" ' +
'href="/cgi-bin/koha/ill/ill-requests.pl?' +
'method=illview&amp;illrequest_id=' +
row.illrequest_id +
'">' + _("Manage request") + '</a>';
};
// Columns that require special treatment
var specialCols = {
action: {
name: '',
func: createActionLink
},
borrowername: {
name: _("Patron"),
func: createPatronLink
},
illrequest_id: {
name: _("Request number"),
func: createRequestId
},
status: {
name: _("Status"),
func: createStatus
},
biblio_id: {
name: _("Biblio ID")
},
library: {
name: _("Library"),
func: createLibrary
},
updated: {
name: _("Updated on"),
},
patron_cardnumber: {
name: _("Patron barcode")
}
};
// Toggle request attributes in Illview
$('#toggle_requestattributes').on('click', function(e) {
e.preventDefault();
$('#requestattributes').toggleClass('content_hidden');
});
// Filter partner list
$('#partner_filter').keyup(function() {
var needle = $('#partner_filter').val();
$('#partners > option').each(function() {
var regex = new RegExp(needle, 'i');
if (
needle.length == 0 ||
$(this).is(':selected') ||
$(this).text().match(regex)
) {
$(this).show();
} else {
$(this).hide();
}
});
});
// Display the modal containing request supplier metadata
$('#ill-request-display-metadata').on('click', function(e) {
e.preventDefault();
$('#dataPreview').modal({show:true});
});
// Get our data from the API and process it prior to passing
// it to datatables
var ajax = $.ajax(
'/api/v1/illrequests?embed=metadata,patron,capabilities,library'
).done(function() {
var data = JSON.parse(ajax.responseText);
// Make a copy, we'll be removing columns next and need
// to be able to refer to data that has been removed
var dataCopy = $.extend(true, [], data);
// Remove all columns we're not interested in
removeIgnore(dataCopy);
// Expand columns that need it and create an array
// of all column names
$.each(dataCopy, function(k, row) {
expandExpand(row);
});
// Assemble an array of column definitions for passing
// to datatables
var colData = [];
Object.keys(allCols).forEach(function(thisCol) {
// Create the base column object
var colObj = {
name: thisCol,
className: thisCol,
defaultContent: ''
};
// We may need to process the data going in this
// column, so do it if necessary
if (
specialCols.hasOwnProperty(thisCol) &&
specialCols[thisCol].hasOwnProperty('func')
) {
colObj.render = specialCols[thisCol].func;
} else {
colObj.data = thisCol;
}
colData.push(colObj);
});
// Initialise the datatable
table = $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, {
'aoColumnDefs': [
{ // Last column shouldn't be sortable or searchable
'aTargets': [ 'actions' ],
'bSortable': false,
'bSearchable': false
},
{ // Hide the two date columns we use just for sorting
'aTargets': [ 'placed', 'updated' ],
'bVisible': false,
'bSearchable': true
},
{ // When sorting 'placed', we want to use the
// unformatted column
'aTargets': [ 'placed_formatted'],
'iDataSort': 7
},
{ // When sorting 'updated', we want to use the
// unformatted column
'aTargets': [ 'updated_formatted'],
'iDataSort': 9
}
],
'aaSorting': [[ 9, 'desc' ]], // Default sort, updated descending
'processing': true, // Display a message when manipulating
'sPaginationType': "full_numbers", // Pagination display
'deferRender': true, // Improve performance on big datasets
'data': dataCopy,
'columns': colData,
'originalData': data, // Enable render functions to access
// our original data
'initComplete': function() {
// Prepare any filter elements that need it
for (var el in filterable) {
if (filterable.hasOwnProperty(el)) {
if (filterable[el].hasOwnProperty('prep')) {
filterable[el].prep(dataCopy, data);
}
if (filterable[el].hasOwnProperty('listener')) {
filterable[el].listener();
}
}
}
}
}));
// Custom date range filtering
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
var placedStart = $('#illfilter_dateplaced_start').datepicker('getDate');
var placedEnd = $('#illfilter_dateplaced_end').datepicker('getDate');
var modifiedStart = $('#illfilter_datemodified_start').datepicker('getDate');
var modifiedEnd = $('#illfilter_datemodified_end').datepicker('getDate');
var rowPlaced = data[7] ? new Date(data[7]) : null;
var rowModified = data[9] ? new Date(data[9]) : null;
var placedPassed = true;
var modifiedPassed = true;
if (placedStart && rowPlaced && rowPlaced < placedStart) {
placedPassed = false
};
if (placedEnd && rowPlaced && rowPlaced > placedEnd) {
placedPassed = false;
}
if (modifiedStart && rowModified && rowModified < modifiedStart) {
modifiedPassed = false
};
if (modifiedEnd && rowModified && rowModified > modifiedEnd) {
modifiedPassed = false;
}
return placedPassed && modifiedPassed;
});
}
);
var clearSearch = function() {
table.search('').columns().search('');
activeFilters = {};
for (var filter in filterable) {
if (
filterable.hasOwnProperty(filter) &&
filterable[filter].hasOwnProperty('clear')
) {
filterable[filter].clear();
}
}
table.draw();
};
// Apply any search filters, or clear any previous
// ones
$('#illfilter_form').submit(function(event) {
event.preventDefault();
table.search('').columns().search('');
for (var active in activeFilters) {
if (activeFilters.hasOwnProperty(active)) {
activeFilters[active]();
}
}
table.draw();
});
// Clear all filters
$('#clear_search').click(function() {
clearSearch();
});
});
</script>
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]