Koha/koha-tmpl/intranet-tmpl/prog/js/staff-global.js
Lucas Gass b1a326238a
Bug 35134: Use localStorage instead of a cookie
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-03-19 17:34:56 +01:00

1021 lines
33 KiB
JavaScript

/* global shortcut delBasket AUDIO_ALERT_PATH Cookies */
/* exported addBibToContext delBibToContext escape_str escape_price openWindow _ removeFocus toUC confirmDelete confirmClone playSound */
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 = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
};
String.prototype.escapeHtml = function () {
return this.replace(/[&<>]/g, function (c) {
return HtmlCharsToEscape[c] || c;
});
};
function escape_str(s) {
return s != null ? s.escapeHtml() : "";
}
/*
* Void method for numbers, for consistency
*/
Number.prototype.escapeHtml = function () {
return this;
};
function escape_price(p) {
return p != null ? p.escapeHtml().format_price() : "";
}
// 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) {
$("a[href='" + tabID + "']", $(this)).tab("show");
};
function togglePanel(node) {
var panel = node.next();
if (panel.is(":visible")) {
node.addClass("collapsed")
.removeClass("expanded")
.attr("title", __("Click to expand this section"));
panel.hide();
} else {
node.addClass("expanded")
.removeClass("collapsed")
.attr("title", __("Click to collapse this section"));
panel.show();
panel.find("input, select, textarea").eq(0).focus();
}
}
$(document).ready(function () {
//check if sticky element is stuck, if so add floating class
if ($(".sticky").length) {
const observer = new IntersectionObserver(
([e]) =>
e.target.classList.toggle("floating", e.intersectionRatio < 1),
{ threshold: [1] }
);
observer.observe(document.querySelector(".sticky"));
}
//check for a hash before setting focus
let hash = window.location.hash;
if (!hash) {
$(".tab-pane.active input:text:first").focus();
}
$("#header_search a[data-bs-toggle='tab']").on(
"shown.bs.tab",
function (e) {
$(e.target.hash).find("input:text:first").focus();
}
);
$(".close, .close_window").on("click", function (e) {
e.preventDefault();
window.close();
});
$("#checkin_search_panel form").preventDoubleFormSubmit();
if ($("#header_search #checkin_search_panel").length > 0) {
shortcut.add("Alt+r", function () {
$("#header_search").selectTabByID("#checkin_search_panel");
$("#ret_barcode").focus();
});
} else {
shortcut.add("Alt+r", function () {
location.href = "/cgi-bin/koha/circ/returns.pl";
});
}
if ($("#header_search #circ_search_panel").length > 0) {
shortcut.add("Alt+u", function () {
$("#header_search").selectTabByID("#circ_search_panel");
$("#findborrower").focus();
});
} else {
shortcut.add("Alt+u", function () {
location.href = "/cgi-bin/koha/circ/circulation.pl";
});
}
if ($("#header_search #catalog_search_panel").length > 0) {
shortcut.add("Alt+q", function () {
$("#header_search").selectTabByID("#catalog_search_panel");
$("#search-form").focus();
});
} else {
shortcut.add("Alt+q", function () {
location.href = "/cgi-bin/koha/catalogue/search.pl";
});
}
if ($("#header_search #renew_search_panel").length > 0) {
shortcut.add("Alt+w", function () {
$("#header_search").selectTabByID("#renew_search_panel");
$("#ren_barcode").focus();
});
} else {
shortcut.add("Alt+w", function () {
location.href = "/cgi-bin/koha/circ/renew.pl";
});
}
$("#header_search .form-extra-content-toggle").on("click", function () {
const extraContent = $(this)
.closest("form")
.find(".form-extra-content");
if (extraContent.is(":visible")) {
extraContent.hide();
$(this).removeClass("extra-content-open");
} else {
extraContent.show();
$(this).addClass("extra-content-open");
}
});
$(".focus:visible").focus();
$(".validated").each(function () {
$(this).validate();
});
jQuery.validator.addClassRules("decimal", {
number: true,
});
jQuery.validator.addMethod(
"decimal_rate",
function (value, element) {
return (
this.optional(element) ||
/^[\-]?\d{0,2}(\.\d{0,3})*$/.test(value)
);
},
__("Please enter a decimal number in the format: 0.0")
);
jQuery.validator.addClassRules("rate", {
decimal_rate: true,
});
$("#logout").on("click", function () {
logOut();
});
$("#helper").on("click", function () {
openHelp();
return false;
});
$("body").on("keypress", ".noEnterSubmit", function (e) {
return checkEnter(e);
});
$("#header_search .nav-tabs a").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();
});
var sidebar_menu = $(".sidebar_menu");
if (sidebar_menu.length > 0) {
sidebar_menu.each(function () {
var path = location.pathname.substring(1);
var url = window.location.toString();
var params = "";
if (url.match(/\?(.+)$/)) {
params = "?" + RegExp.$1;
}
if ($('a[href$="/' + path + params + '"]', $(this)).length == 0) {
$('a[href$="/' + path + '"]', $(this)).addClass("current");
} else {
$('a[href$="/' + path + params + '"]', $(this)).addClass(
"current"
);
}
});
}
$("#catalog-search-link a").on("mouseenter mouseleave", function () {
$("#catalog-search-dropdown a").toggleClass(
"catalog-search-dropdown-hover"
);
});
if (
localStorage.getItem("previousPatrons") ||
$("#hiddenborrowernumber").val()
) {
var previous_patrons = [];
if (localStorage.getItem("previousPatrons")) {
previous_patrons = JSON.parse(
localStorage.getItem("previousPatrons")
);
}
if (previous_patrons.length) {
let p = previous_patrons[0];
$("#lastborrowerlink").show();
$("#lastborrowerlink").prop("title", `${p["name"]} (${p["card"]})`);
$("#lastborrowerlink").prop(
"href",
`/cgi-bin/koha/circ/circulation.pl?borrowernumber=${p["borrowernumber"]}`
);
$("#lastborrower-window").css("display", "inline-flex");
previous_patrons.reverse();
for (i in previous_patrons) {
p = previous_patrons[i];
const el = `<li><a class="dropdown-item" href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=${p["borrowernumber"]}">${p["name"]} (${p["card"]})</a></li>`;
$("#lastBorrowerList").prepend(el);
}
}
if ($("#hiddenborrowernumber").val()) {
// Remove this patron from the list if they are already there
previous_patrons = previous_patrons.filter(function (p) {
return p["borrowernumber"] != $("#hiddenborrowernumber").val();
});
const previous_patron = {
borrowernumber: escape_str($("#hiddenborrowernumber").val()),
name: escape_str($("#hiddenborrowername").val()),
card: escape_str($("#hiddenborrowercard").val()),
};
previous_patrons.unshift(previous_patron);
// Limit to number of patrons specified in showLastPatronCount
if (previous_patrons.length > showLastPatronCount)
previous_patrons.pop();
localStorage.setItem(
"previousPatrons",
JSON.stringify(previous_patrons)
);
}
}
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 () {
$('[name^="limit"]').each(function () {
if ($(this).val() == "") {
$(this).prop("disabled", "disabled");
}
});
var disabledPrior = false;
$(".search-term-row").each(function () {
if (disabledPrior) {
$(this).find('select[name="op"]').prop("disabled", "disabled");
disabledPrior = false;
}
if ($(this).find('input[name="q"]').val() == "") {
$(this).find("input").prop("disabled", "disabled");
$(this).find("select").prop("disabled", "disabled");
disabledPrior = true;
}
});
resetSearchContext();
saveOrClearSimpleSearchParams();
});
/* 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();
});
// add back to top button on each staff page
$("body").append(
'<button id="backtotop" class="btn btn-default" aria-label="' +
__("Back to top") +
'"><i class="fa fa-arrow-up" aria-hidden="true"></i></button>'
);
$("#backtotop").hide();
$(window).scroll(function () {
if ($(window).scrollTop() < 300) {
$("#backtotop").fadeOut();
} else {
$("#backtotop").fadeIn();
}
});
$("#backtotop").click(function (e) {
e.preventDefault();
$("html,body").animate({ scrollTop: 0 }, "slow");
});
$("body").on("change", "#set-library-branch", function () {
var selectedBranch = $("#set-library-branch").val();
$("#set-library-desk_id")
.children()
.each(function () {
if ($(this).attr("id") === "nodesk") {
// set no desk by default, should be first element
$(this).prop("selected", true);
$(this).prop("disabled", false);
$(this).show();
} else if ($(this).hasClass(selectedBranch)) {
$("#nodesk").prop("disabled", true); // we have desk, no need for nodesk option
$("#nodesk").hide();
$(this).prop("disabled", false);
$(this).show();
if (
selectedBranch == $(".logged-in-branch-code").html() &&
$(".logged-in-desk-id").length
) {
$("#set-library-desk_id").val(
$(".logged-in-desk-id").html()
);
} else {
$("#nodesk").hide();
$("#set-library-desk_id").val(
$(
"#set-library-desk_id option:not([disabled]):first"
).val()
);
}
} else {
$(this).prop("disabled", true);
$(this).hide();
}
});
$("#set-library-register_id").val("");
$("#set-library-register_id")
.children()
.each(function () {
// default to no-register
if ($(this).is("#noregister")) {
$(this).prop("selected", true);
} else if ($(this).hasClass(selectedBranch)) {
// display branch registers
$(this).prop("disabled", false);
$(this).show();
// default to branch default if there is one
if ($(this).hasClass("default")) {
$(this).prop("selected", true);
}
} else {
// hide non-branch registers
$(this).hide();
$(this).prop("disabled", true);
}
});
});
$("body").on(
"click",
"#setlibrary_panel #cancel_set_library",
function (e) {
e.preventDefault();
$("#setlibrary_panel")
.removeClass("setlibrary_panel_open")
.html("")
.hide();
}
);
$("#branch_select_cog").on("click", function (e) {
e.stopPropagation();
let setlibrary_panel = $("#setlibrary_panel");
if (setlibrary_panel.hasClass("setlibrary_panel_open")) {
setlibrary_panel
.removeClass("setlibrary_panel_open")
.html("")
.hide();
} else {
setlibrary_panel.addClass("setlibrary_panel_open").show();
$("#setlibrary_panel").load(
"/cgi-bin/koha/circ/set-library.pl #set-library-form",
function () {
// setLibraryDeskOptions();
}
);
}
});
$("#logged-in-dropdown").on("hidden.bs.dropdown", function () {
$("#setlibrary_panel")
.removeClass("setlibrary_panel_open")
.html("")
.hide();
});
if ($('[data-bs-toggle="tooltip"]').length) {
$('[data-bs-toggle="tooltip"]').tooltip();
}
if ($(".pagination.output").length > 0) {
$(".output.first").append(__("First"));
$(".output.previous").append(__("Previous"));
$(".output.next").prepend(__("Next"));
$(".output.last").prepend(__("Last"));
}
$(".collapsed,.expanded").on("click", function (e) {
e.preventDefault();
togglePanel($(this));
});
});
function removeLastBorrower() {
localStorage.removeItem("previousPatrons");
}
// 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() {
Cookies.remove("holdfor", { path: "/", SameSite: "Lax" });
}
function logOut() {
if (typeof delBasket == "function") {
delBasket("main", true);
}
clearHoldFor();
removeLastBorrower();
localStorage.removeItem("sql_reports_activetab");
localStorage.removeItem("searches");
localStorage.removeItem("bibs_selected");
localStorage.removeItem("patron_search_selections");
localStorage.removeItem("item_search_selections");
localStorage.removeItem("copiedPermissions");
localStorage.removeItem("popup_window_width");
localStorage.removeItem("popup_window_height");
// Remove DataTables states
Object.keys(localStorage).forEach(k => {
if (k.match(/^DataTables_/)) {
localStorage.removeItem(k);
}
});
}
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;
//IE <= 9 can't handle a "name" with whitespace
try {
window.open(
link,
name,
"width=" +
width +
",height=" +
height +
",resizable=yes,toolbar=false,scrollbars=yes,top"
);
} catch (e) {
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 (var 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 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) {
localStorage.setItem("bibs_selected", JSON.stringify(bibnums));
}
function getContextBiblioNumbers() {
var r = localStorage.getItem("bibs_selected");
if (r) {
return JSON.parse(r);
}
r = new Array();
return r;
}
function resetSearchContext() {
setContextBiblioNumbers(new Array());
}
function saveOrClearSimpleSearchParams() {
// Simple masthead search - pass value for display on details page
var pulldown_selection;
var searchbox_value;
if ($("#cat-search-block select.advsearch").length) {
pulldown_selection = $("#cat-search-block select.advsearch").val();
} else {
pulldown_selection = "";
}
if ($("#cat-search-block #search-form").length) {
searchbox_value = $("#cat-search-block #search-form").val();
} else {
searchbox_value = "";
}
localStorage.setItem("cat_search_pulldown_selection", pulldown_selection);
localStorage.setItem("searchbox_value", searchbox_value);
}
function patron_autocomplete(node, options) {
let link_to;
let url_params;
let on_select_callback;
if (options) {
if (options["link-to"]) {
link_to = options["link-to"];
}
if (options["url-params"]) {
url_params = options["url-params"];
}
if (options["on-select-callback"]) {
on_select_callback = options["on-select-callback"];
}
}
return (node
.autocomplete({
source: function (request, response) {
let q = buildPatronSearchQuery(request.term);
let params = {
_page: 1,
_per_page: 10,
q: JSON.stringify(q),
_order_by: "+me.surname,+me.firstname",
};
$.ajax({
data: params,
type: "GET",
url: "/api/v1/patrons",
headers: {
"x-koha-embed": "library",
},
success: function (data) {
return response(data);
},
error: function (e) {
if (e.state() != "rejected") {
alert(
__(
"An error occurred. Check the logs for details."
)
);
}
return response();
},
});
},
minLength: 3,
select: function (event, ui) {
if (ui.item.link) {
window.location.href = ui.item.link;
} else if (on_select_callback) {
return on_select_callback(event, ui);
}
},
focus: function (event, ui) {
event.preventDefault(); // Don't replace the text field
},
})
.data("ui-autocomplete")._renderItem = function (ul, item) {
if (link_to) {
item.link =
link_to == "circ"
? "/cgi-bin/koha/circ/circulation.pl"
: link_to == "reserve"
? "/cgi-bin/koha/reserve/request.pl"
: "/cgi-bin/koha/members/moremember.pl";
item.link +=
(url_params ? "?" + url_params + "&" : "?") +
"borrowernumber=" +
item.patron_id;
} else {
item.link = null;
}
var cardnumber = "";
if (item.cardnumber != "") {
// Display card number in parentheses if it exists
cardnumber = " (" + item.cardnumber + ") ";
}
if (item.library_id == loggedInLibrary) {
loggedInClass = "ac-currentlibrary";
} else {
loggedInClass = "";
}
return $("<li></li>")
.addClass(loggedInClass)
.data("ui-autocomplete-item", item)
.append(
"" +
(item.link ? '<a href="' + item.link + '">' : "<a>") +
(item.surname ? item.surname.escapeHtml() : "") +
", " +
(item.preferred_name
? item.preferred_name.escapeHtml()
: item.firstname
? item.firstname.escapeHtml()
: "") +
" " +
(item.middle_name ? item.middle_name.escapeHtml() : "") +
" " +
(item.other_name
? "(" + item.other_name.escapeHtml() + ")"
: "") +
cardnumber.escapeHtml() +
" " +
(item.date_of_birth
? $date(item.date_of_birth) +
'<span class="age_years"> (' +
$get_age(item.date_of_birth) +
" " +
__("years") +
")</span>,"
: "") +
" " +
$format_address(item, {
no_line_break: true,
include_li: false,
}) +
" " +
(!singleBranchMode
? '<span class="badge ac-library">' +
item.library.name.escapeHtml() +
"</span>"
: "") +
(item.expired
? '<span class="badge text-bg-warning">' +
__("Expired") +
"</span>"
: "") +
(item.restricted
? '<span class="badge text-bg-danger">' +
__("Restricted") +
"</span>"
: "") +
"</a>"
)
.appendTo(ul);
});
}
function expandPatronSearchFields(search_fields) {
switch (search_fields) {
case "standard":
return defaultPatronSearchFields;
break;
case "full_address":
return "streetnumber|streettype|address|address2|city|state|zipcode|country";
break;
case "all_emails":
return "email|emailpro|B_email";
break;
case "all_phones":
return "phone|phonepro|B_phone|altcontactphone|mobile";
break;
default:
return search_fields;
}
}
/**
* Build patron search query
* - term: The full search term input by the user
* You can then pass a list of options:
* - search_type: (String) 'contains' or 'starts_with', defaults to defaultPatronSearchMethod (see js_includes.inc)
* - search_fields: (String) comma-separated list of specific fields, defaults to defaultPatronSearchFields (see js_includes.inc)
* - extended_attribute_types: (JSON object) contains the patron searchable attribute types to be searched on (see patron-search.inc)
* - table_prefix: (String) table name to prefix the fields with, defaults to 'me'
*/
function buildPatronSearchQuery(term, options) {
let q = [];
let table_prefix;
let leading_wildcard;
let search_fields = [];
let patterns = term.split(/[\s,]+/).filter(function (s) {
return s.length;
});
// Bail if no patterns
if (patterns.length == 0) {
return q;
}
// Table prefix: If table_prefix options exists, use that
if (typeof options !== "undefined" && options.table_prefix) {
table_prefix = options.table_prefix;
// If not, default to 'me'
} else {
table_prefix = "me";
}
// Leading wildcard: If search_type option exists, use that
if (typeof options !== "undefined" && options.search_type) {
leading_wildcard = options.search_type === "contains" ? "%" : "";
// If not, use DefaultPatronSearchMethod system preference instead
} else {
leading_wildcard = defaultPatronSearchMethod === "contains" ? "%" : "";
}
let searched_attribute_fields = [];
// Search fields: If search_fields option exists, we use that
if (typeof options !== "undefined" && options.search_fields) {
expand_fields = expandPatronSearchFields(options.search_fields);
expand_fields.split("|").forEach(function (field, i) {
if (field.startsWith("_ATTR_")) {
let attr_field = field.replace("_ATTR_", "");
searched_attribute_fields.push(attr_field);
} else {
search_fields.push(field);
}
});
// If not, we use DefaultPatronSearchFields system preference instead
} else {
search_fields = defaultPatronSearchFields.split("|");
}
// Add each pattern for each search field
let pattern_subquery_and = [];
patterns.forEach(function (pattern, i) {
let pattern_subquery_or = [];
search_fields.forEach(function (field, i) {
pattern_subquery_or.push({
[table_prefix + "." + field]: {
like: leading_wildcard + pattern + "%",
},
});
if (field == "dateofbirth") {
try {
let d = $date_to_rfc3339(pattern);
pattern_subquery_or.push({
[table_prefix + "." + field]: d,
});
} catch {
// Hide the warning if the date is not correct
}
}
});
pattern_subquery_and.push(pattern_subquery_or);
});
q.push({ "-and": pattern_subquery_and });
// Add full search term for each search field
let term_subquery_or = [];
search_fields.forEach(function (field, i) {
term_subquery_or.push({
[table_prefix + "." + field]: {
like: leading_wildcard + term + "%",
},
});
});
q.push({ "-or": term_subquery_or });
// Add each pattern for each extended patron attributes
if (
typeof options !== "undefined" &&
((options.search_fields == "standard" &&
options.extended_attribute_types &&
options.extended_attribute_types.length > 0) ||
searched_attribute_fields.length > 0) &&
extendedPatronAttributes
) {
extended_attribute_codes_to_search =
searched_attribute_fields.length > 0
? searched_attribute_fields
: options.extended_attribute_types;
extended_attribute_subquery_and = [];
patterns.forEach(function (pattern, i) {
let extended_attribute_sub_or = [];
extended_attribute_sub_or.push({
"extended_attributes.value": {
like: leading_wildcard + pattern + "%",
},
"extended_attributes.code": extended_attribute_codes_to_search,
});
extended_attribute_subquery_and.push(extended_attribute_sub_or);
});
q.push({ "-and": extended_attribute_subquery_and });
}
return q;
}
function selectBsTabByHash(tabs_container_id) {
/* Check for location.hash in the page URL */
/* If present the location hash will be used to activate the correct tab */
var hash = document.location.hash;
if (hash !== "") {
$("#" + tabs_container_id + ' a[href="' + hash + '"]').tab("show");
} else {
$("#" + tabs_container_id + " a:first").tab("show");
}
}
/**
* Fades out a Font Awesome icon, fades in a replacement, and back
* @param {object} element - jQuery object representing the icon's container
* @param {string} start - The icon which will be temporarily replaced
* @param {string} replacement - The icon which will be the temporary replacement
*/
function toggleBtnIcon(element, start, replacement) {
let icon = element.find("." + start);
icon.fadeOut(1000, function () {
$(this)
.removeClass(start)
.addClass(replacement)
.fadeIn(1000, function () {
$(this).fadeOut(1000, function () {
$(this)
.removeClass(replacement)
.addClass(start)
.fadeIn(1000);
});
});
});
}
/**
* Returns a roughly ideal position to scroll an element into view
* @param {string} target - The HTML id of the element to scroll into view
* @param {string} elemid - The HTML id of the element which might obscure
* the view of the target element e.g. a floating toolbar
* @return {number} - The y-coordinate to pass to window.scrollTo()
*/
function getScrollto(target, elemid) {
var dest = $("#" + target);
var yoffset = dest.offset();
if (elemid != "") {
var element = $("#" + elemid);
var elem_height = element.outerHeight();
} else {
elem_height = 0;
}
return yoffset.top - elem_height - 20;
}