Owen Leonard
a512ae01fc
This patch removes the use of jquery.cookie to store "last patron" information, using localStorage instead. jquery.cookie.js is obsolete. See Bug 24624. localStorage has been chosen as an alternative in this situation because it does not require transmission between the client and the server. See Bug 12410. Because there is no "session only" option with localStorage, additional handling of the showLastPatron data is added to the login page. That takes care of "stale" last patron information if user didn't log out but the session expired for some reason. To test apply the patch and enable the showLastPatron system preference. 1. Load a patron's account for checkout 2. Navigate away from patron-related pages: Perform a catalog search from the search header form and open the detail page from the search results. Confirm that the correct last patron information still shows. 3. Load another patron's account for checkout - There should now be a "Last patron" link in the breadcrumbs bar which links to the patron in step 1. Hovering your mouse over the link should display a tooltip containing the patron's name and card number. - Click the "X" to clear the last patron information. The last patron link should go away. 4. Log out and log back in. The last patron information should be gone. Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Julian Maurice <julian.maurice@biblibre.com> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
322 lines
11 KiB
JavaScript
322 lines
11 KiB
JavaScript
/* global shortcut delCookie delBasket Sticky */
|
|
/* exported paramOfUrl addBibToContext delBibToContext */
|
|
if ( KOHA === undefined ) var KOHA = {};
|
|
|
|
function _(s) { return s; } // dummy function for gettext
|
|
|
|
// http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery/5341855#5341855
|
|
String.prototype.format = function() { return formatstr(this, arguments); };
|
|
function formatstr(str, col) {
|
|
col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);
|
|
var idx = 0;
|
|
return str.replace(/%%|%s|%(\d+)\$s/g, function (m, n) {
|
|
if (m == "%%") { return "%"; }
|
|
if (m == "%s") { return col[idx++]; }
|
|
return col[n];
|
|
});
|
|
}
|
|
|
|
var HtmlCharsToEscape = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>'
|
|
};
|
|
String.prototype.escapeHtml = function() {
|
|
return this.replace(/[&<>]/g, function(c) {
|
|
return HtmlCharsToEscape[c] || c;
|
|
});
|
|
};
|
|
|
|
/*
|
|
* Void method for numbers, for consistency
|
|
*/
|
|
Number.prototype.escapeHtml = function() {
|
|
return this;
|
|
};
|
|
|
|
// http://stackoverflow.com/questions/14859281/select-tab-by-name-in-jquery-ui-1-10-0/16550804#16550804
|
|
$.fn.tabIndex = function () {
|
|
return $(this).parent().children('div').index(this);
|
|
};
|
|
$.fn.selectTabByID = function (tabID) {
|
|
$(this).tabs("option", "active", $( tabID ).tabIndex());
|
|
};
|
|
|
|
$(document).ready(function() {
|
|
$('#header_search').tabs().on( "tabsactivate", function(e, ui) { $(this).find("div:visible").find('input').eq(0).focus(); });
|
|
|
|
$(".close").click(function(){ window.close(); });
|
|
|
|
if($("#header_search #checkin_search").length > 0){ shortcut.add('Alt+r',function (){ $("#header_search").selectTabByID("#checkin_search"); $("#ret_barcode").focus(); }); } else { shortcut.add('Alt+r',function (){ location.href="/cgi-bin/koha/circ/returns.pl"; }); }
|
|
if($("#header_search #circ_search").length > 0){ shortcut.add('Alt+u',function (){ $("#header_search").selectTabByID("#circ_search"); $("#findborrower").focus(); }); } else { shortcut.add('Alt+u',function(){ location.href="/cgi-bin/koha/circ/circulation.pl"; }); }
|
|
if($("#header_search #catalog_search").length > 0){ shortcut.add('Alt+q',function (){ $("#header_search").selectTabByID("#catalog_search"); $("#search-form").focus(); }); } else { shortcut.add('Alt+q',function(){ location.href="/cgi-bin/koha/catalogue/search.pl"; }); }
|
|
if($("#header_search #renew_search").length > 0){ shortcut.add('Alt+w',function (){ $("#header_search").selectTabByID("#renew_search"); $("#ren_barcode").focus(); }); } else { shortcut.add('Alt+w',function(){ location.href="/cgi-bin/koha/circ/renew.pl"; }); }
|
|
|
|
$("#header_search > ul > li").show();
|
|
|
|
$(".focus").focus();
|
|
$(".validated").each(function() {
|
|
$(this).validate();
|
|
});
|
|
|
|
$("#logout").on("click",function(){
|
|
logOut();
|
|
});
|
|
$("#helper").on("click",function(){
|
|
openHelp();
|
|
return false;
|
|
});
|
|
|
|
$("body").on("keypress", ".noEnterSubmit", function(e){
|
|
return checkEnter(e);
|
|
});
|
|
|
|
$(".keep_text").on("click",function(){
|
|
var field_index = $(this).parent().index();
|
|
keep_text( field_index );
|
|
});
|
|
|
|
$(".toggle_element").on("click",function(e){
|
|
e.preventDefault();
|
|
$( $(this).data("element") ).toggle();
|
|
if (typeof Sticky !== "undefined" && typeof hcSticky === "function") {
|
|
Sticky.hcSticky('update');
|
|
}
|
|
});
|
|
|
|
var navmenulist = $("#navmenulist");
|
|
if( navmenulist.length > 0 ){
|
|
var path = location.pathname.substring(1);
|
|
var url = window.location.toString();
|
|
var params = '';
|
|
if ( url.match(/\?(.+)$/) ) {
|
|
params = "?" + RegExp.$1;
|
|
}
|
|
$("a[href$=\"/" + path + params + "\"]", navmenulist).addClass("current");
|
|
}
|
|
|
|
$("#catalog-search-link a").on("hover", function(){
|
|
$("#catalog-search-dropdown a").toggleClass("catalog-search-dropdown-hover");
|
|
});
|
|
|
|
if ( localStorage.getItem("lastborrowernumber") ){
|
|
if( $("#hiddenborrowernumber").val() != localStorage.getItem("lastborrowernumber") ) {
|
|
$("#lastborrower-window").detach().appendTo("#breadcrumbs");
|
|
$("#lastborrowerlink").show();
|
|
$("#lastborrowerlink").prop("title", localStorage.getItem("lastborrowername") + " (" + localStorage.getItem("lastborrowercard") + ")");
|
|
$("#lastborrowerlink").prop("href", "/cgi-bin/koha/circ/circulation.pl?borrowernumber=" + localStorage.getItem("lastborrowernumber"));
|
|
$("#lastborrower-window").css("display", "inline-block");
|
|
}
|
|
}
|
|
|
|
if( !localStorage.getItem("lastborrowernumber") || ( $("#hiddenborrowernumber").val() != localStorage.getItem("lastborrowernumber") && localStorage.getItem("currentborrowernumber") != $("#hiddenborrowernumber").val())) {
|
|
if( $("#hiddenborrowernumber").val() ){
|
|
localStorage.setItem("lastborrowernumber", $("#hiddenborrowernumber").val() );
|
|
localStorage.setItem("lastborrowername", $("#hiddenborrowername").val() );
|
|
localStorage.setItem("lastborrowercard", $("#hiddenborrowercard").val() );
|
|
}
|
|
}
|
|
|
|
if( $("#hiddenborrowernumber").val() ){
|
|
localStorage.setItem("currentborrowernumber", $("#hiddenborrowernumber").val() );
|
|
}
|
|
|
|
$("#lastborrower-remove").click(function() {
|
|
removeLastBorrower();
|
|
$("#lastborrower-window").hide();
|
|
});
|
|
|
|
/* Search results browsing */
|
|
/* forms with action leading to search */
|
|
$("form[action*='search.pl']").submit(function(){
|
|
resetSearchContext();
|
|
});
|
|
/* any link to launch a search except navigation links */
|
|
$("[href*='search.pl?']").not(".nav").not('.searchwithcontext').click(function(){
|
|
resetSearchContext();
|
|
});
|
|
/* any link to a detail page from the results page. */
|
|
$("#bookbag_form a[href*='detail.pl?']").click(function(){
|
|
resetSearchContext();
|
|
});
|
|
|
|
});
|
|
|
|
function removeLastBorrower(){
|
|
localStorage.removeItem("lastborrowernumber");
|
|
localStorage.removeItem("lastborrowername");
|
|
localStorage.removeItem("lastborrowercard");
|
|
localStorage.removeItem("currentborrowernumber");
|
|
}
|
|
|
|
// http://jennifermadden.com/javascript/stringEnterKeyDetector.html
|
|
function checkEnter(e){ //e is event object passed from function invocation
|
|
var characterCode; // literal character code will be stored in this variable
|
|
if(e && e.which){ //if which property of event object is supported (NN4)
|
|
characterCode = e.which; //character code is contained in NN4's which property
|
|
} else {
|
|
characterCode = e.keyCode; //character code is contained in IE's keyCode property
|
|
}
|
|
if( characterCode == 13 //if generated character code is equal to ascii 13 (if enter key)
|
|
&& e.target.nodeName == "INPUT"
|
|
&& e.target.type != "submit" // Allow enter to submit using the submit button
|
|
){
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function clearHoldFor(){
|
|
$.removeCookie("holdfor", { path: '/' });
|
|
}
|
|
|
|
function logOut(){
|
|
if( typeof delBasket == 'function' ){
|
|
delBasket('main', true);
|
|
}
|
|
clearHoldFor();
|
|
removeLastBorrower();
|
|
}
|
|
|
|
function openHelp(){
|
|
window.open( "/cgi-bin/koha/help.pl", "_blank");
|
|
}
|
|
|
|
jQuery.fn.preventDoubleFormSubmit = function() {
|
|
jQuery(this).submit(function() {
|
|
$("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
|
|
if (this.beenSubmitted)
|
|
return false;
|
|
else
|
|
this.beenSubmitted = true;
|
|
});
|
|
};
|
|
|
|
function openWindow(link,name,width,height) {
|
|
name = (typeof name == "undefined")?'popup':name;
|
|
width = (typeof width == "undefined")?'600':width;
|
|
height = (typeof height == "undefined")?'400':height;
|
|
var newwin;
|
|
//IE <= 9 can't handle a "name" with whitespace
|
|
try {
|
|
newin=window.open(link,name,'width='+width+',height='+height+',resizable=yes,toolbar=false,scrollbars=yes,top');
|
|
} catch(e) {
|
|
newin=window.open(link,null,'width='+width+',height='+height+',resizable=yes,toolbar=false,scrollbars=yes,top');
|
|
}
|
|
}
|
|
|
|
// Use this function to remove the focus from any element for
|
|
// repeated scanning actions on errors so the librarian doesn't
|
|
// continue scanning and miss the error.
|
|
function removeFocus() {
|
|
$(':focus').blur();
|
|
}
|
|
|
|
function toUC(f) {
|
|
var x=f.value.toUpperCase();
|
|
f.value=x;
|
|
return true;
|
|
}
|
|
|
|
function confirmDelete(message) {
|
|
return (confirm(message) ? true : false);
|
|
}
|
|
|
|
function confirmClone(message) {
|
|
return (confirm(message) ? true : false);
|
|
}
|
|
|
|
function playSound( sound ) {
|
|
if ( ! ( sound.indexOf('http://') === 0 || sound.indexOf('https://') === 0 ) ) {
|
|
sound = AUDIO_ALERT_PATH + sound;
|
|
}
|
|
document.getElementById("audio-alert").innerHTML = '<audio src="' + sound + '" autoplay="autoplay" autobuffer="autobuffer"></audio>';
|
|
}
|
|
|
|
// For keeping the text when navigating the search tabs
|
|
function keep_text(clicked_index) {
|
|
var searchboxes = document.getElementsByClassName("head-searchbox");
|
|
var persist = searchboxes[0].value;
|
|
|
|
for (i = 0; i < searchboxes.length - 1; i++) {
|
|
if (searchboxes[i].value != searchboxes[i+1].value) {
|
|
if (i === searchboxes.length-2) {
|
|
if (searchboxes[i].value != searchboxes[0].value) {
|
|
persist = searchboxes[i].value;
|
|
} else if (searchboxes.length === 2) {
|
|
if (clicked_index === 0) {
|
|
persist = searchboxes[1].value;
|
|
}
|
|
} else {
|
|
persist = searchboxes[i+1].value;
|
|
}
|
|
} else if (searchboxes[i+1].value != searchboxes[i+2].value) {
|
|
persist = searchboxes[i+1].value;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < searchboxes.length; i++) {
|
|
searchboxes[i].value = persist;
|
|
}
|
|
}
|
|
|
|
// Extends jQuery API
|
|
jQuery.extend({uniqueArray:function(array){
|
|
return $.grep(array, function(el, index) {
|
|
return index === $.inArray(el, array);
|
|
});
|
|
}});
|
|
|
|
function removeByValue(arr, val) {
|
|
for(var i=0; i<arr.length; i++) {
|
|
if(arr[i] == val) {
|
|
arr.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function paramOfUrl( url, param ) {
|
|
param = param.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
|
|
var regexS = "[\\?&]"+param+"=([^&#]*)";
|
|
var regex = new RegExp( regexS );
|
|
var results = regex.exec( url );
|
|
if( results == null ) {
|
|
return "";
|
|
} else {
|
|
return results[1];
|
|
}
|
|
}
|
|
|
|
function addBibToContext( bibnum ) {
|
|
bibnum = parseInt(bibnum, 10);
|
|
var bibnums = getContextBiblioNumbers();
|
|
bibnums.push(bibnum);
|
|
setContextBiblioNumbers( bibnums );
|
|
setContextBiblioNumbers( $.uniqueArray( bibnums ) );
|
|
}
|
|
|
|
function delBibToContext( bibnum ) {
|
|
var bibnums = getContextBiblioNumbers();
|
|
removeByValue( bibnums, bibnum );
|
|
setContextBiblioNumbers( $.uniqueArray( bibnums ) );
|
|
}
|
|
|
|
function setContextBiblioNumbers( bibnums ) {
|
|
$.cookie('bibs_selected', JSON.stringify( bibnums ));
|
|
}
|
|
|
|
function getContextBiblioNumbers() {
|
|
var r = $.cookie('bibs_selected');
|
|
if ( r ) {
|
|
return JSON.parse(r);
|
|
}
|
|
r = new Array();
|
|
return r;
|
|
}
|
|
|
|
function resetSearchContext() {
|
|
setContextBiblioNumbers( new Array() );
|
|
}
|