From 172981c95e6d0d8f7acd119f30e3cddb1d9cea83 Mon Sep 17 00:00:00 2001 From: Owen Leonard Date: Fri, 5 Apr 2024 16:05:56 +0000 Subject: [PATCH] Bug 36528: Correct JS assets included in self checkout slip template The self checkout's slip print template includes some assets which it doesn't need (enquire.js) and lacks other that it does (i18n-related files). This patch correct the problem. The patch also wraps some code in global.js with a check that the relevant library has been loaded so that we don't get errors when the asset isn't included. To test, apply the patch and clear your browser cache. - With WebBasedSelfCheck enabled, log in to the self checkout module and check some items out. - Click "Finish" and then "Print receipt..." - Check the browser console on the receipt page. There should be no errors. - Log in to the OPAC and click the "Messaging" tab on the patron summary page. - Test that the "Digests only" table heading icon shows a tooltip. - Test that enquire.js is still loading correctly by performing a catalog search and narrowing your browser. When the window is narrow enough, the facets sidebar should collapse into a "Refine your search" button. Note that the "js_in_body" qa warning is a false positive. Signed-off-by: David Nind Signed-off-by: Kyle M Hall Signed-off-by: Katrin Fischer (cherry picked from commit 3b9a43ec5a5ce24865f93a345215858b74348b2b) Signed-off-by: Fridolin Somers --- .../bootstrap/en/modules/sco/printslip.tt | 12 +- koha-tmpl/opac-tmpl/bootstrap/js/global.js | 291 +++++++++++------- 2 files changed, 182 insertions(+), 121 deletions(-) diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/sco/printslip.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/sco/printslip.tt index be7add462e..6f49dc0293 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/sco/printslip.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/sco/printslip.tt @@ -13,12 +13,20 @@ [% IF stylesheet %] [% END %] - + +[% IF lang && lang != 'en' %] + [% Asset.js(lang _ '/js/locale_data.js') | $raw %] +[% END %] +[% Asset.js('js/Gettext.js') | $raw %] +[% Asset.js('js/i18n.js') | $raw %] [% Asset.js("lib/jquery/jquery-3.6.0.min.js") | $raw %] [% Asset.js("lib/jquery/jquery-migrate-3.3.2.min.js") | $raw %] [% Asset.js("lib/fontfaceobserver.min.js") | $raw %] -[% Asset.js("lib/enquire.min.js") | $raw %] [% Asset.js("js/global.js") | $raw %] [% INCLUDE 'slip-print.inc' #printThenClose %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/js/global.js b/koha-tmpl/opac-tmpl/bootstrap/js/global.js index 83b21779ae..9a48e3a8f5 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/js/global.js +++ b/koha-tmpl/opac-tmpl/bootstrap/js/global.js @@ -1,88 +1,105 @@ /* global enquire readCookie updateBasket delCookie __ */ -(function( w ){ +(function (w) { // if the class is already set, the font has already been loaded - if( w.document.documentElement.className.indexOf( "fonts-loaded" ) > -1 ){ + if (w.document.documentElement.className.indexOf("fonts-loaded") > -1) { return; } - var PrimaryFont = new w.FontFaceObserver( "NotoSans", { - weight: 400 + var PrimaryFont = new w.FontFaceObserver("NotoSans", { + weight: 400, }); - PrimaryFont.load(null, 5000).then(function(){ - w.document.documentElement.className += " fonts-loaded"; - }, function(){ - console.log("Failed"); - }); -}( this )); + PrimaryFont.load(null, 5000).then( + function () { + w.document.documentElement.className += " fonts-loaded"; + }, + function () { + // Could not load web font + } + ); +})(this); // http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery/5341855#5341855 -String.prototype.format = function() { return formatstr(this, arguments) } +String.prototype.format = function () { + return formatstr(this, arguments); +}; function formatstr(str, col) { - col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1); + 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++]; } + if (m == "%%") { + return "%"; + } + if (m == "%s") { + return col[idx++]; + } return col[n]; }); -}; +} var HtmlCharsToEscape = { - '&': '&', - '<': '<', - '>': '>' + "&": "&", + "<": "<", + ">": ">", }; -String.prototype.escapeHtml = function() { - return this.replace(/[&<>]/g, function(c) { +String.prototype.escapeHtml = function () { + return this.replace(/[&<>]/g, function (c) { return HtmlCharsToEscape[c] || c; }); }; -function escape_str(s){ +function escape_str(s) { return s != null ? s.escapeHtml() : ""; } function confirmDelete(message) { - return (confirm(message) ? true : false); + return confirm(message) ? true : false; } function Dopop(link) { - newin=window.open(link,'popup','width=660,height=450,toolbar=false,scrollbars=yes,resizable=yes'); + newin = window.open( + link, + "popup", + "width=660,height=450,toolbar=false,scrollbars=yes,resizable=yes" + ); } -jQuery.fn.preventDoubleFormSubmit = function() { - jQuery(this).submit(function() { - if (this.beenSubmitted) - return false; - else - this.beenSubmitted = true; +jQuery.fn.preventDoubleFormSubmit = function () { + jQuery(this).submit(function () { + if (this.beenSubmitted) return false; + else this.beenSubmitted = true; }); }; -function prefixOf (s, tok) { +function prefixOf(s, tok) { var index = s.indexOf(tok); return s.substring(0, index); } -function suffixOf (s, tok) { +function suffixOf(s, tok) { var index = s.indexOf(tok); return s.substring(index + 1); } -$("body").on("keypress", ".noEnterSubmit", function(e){ +$("body").on("keypress", ".noEnterSubmit", function (e) { return checkEnter(e); }); // http://jennifermadden.com/javascript/stringEnterKeyDetector.html -function checkEnter(e){ //e is event object passed from function invocation +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) + 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 - ){ + 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; @@ -91,9 +108,10 @@ function checkEnter(e){ //e is event object passed from function invocation // Adapted from https://gist.github.com/jnormore/7418776 function confirmModal(message, title, yes_label, no_label, callback) { - $("#bootstrap-confirm-box-modal").data('confirm-yes', false); - if($("#bootstrap-confirm-box-modal").length == 0) { - $("body").append('' + ); + $("#bootstrap-confirm-box-modal-submit").on("click", function () { + $("#bootstrap-confirm-box-modal").data("confirm-yes", true); + $("#bootstrap-confirm-box-modal").modal("hide"); return false; }); - $("#bootstrap-confirm-box-modal").on('hide.bs.modal', function () { - if(callback) callback($("#bootstrap-confirm-box-modal").data('confirm-yes')); + $("#bootstrap-confirm-box-modal").on("hide.bs.modal", function () { + if (callback) + callback($("#bootstrap-confirm-box-modal").data("confirm-yes")); }); } - $("#bootstrap-confirm-box-modal .modal-header h4").text( title || "" ); - if( message && message != "" ){ - $("#bootstrap-confirm-box-modal .modal-body").html( message || "" ); + $("#bootstrap-confirm-box-modal .modal-header h4").text(title || ""); + if (message && message != "") { + $("#bootstrap-confirm-box-modal .modal-body").html(message || ""); } else { $("#bootstrap-confirm-box-modal .modal-body").remove(); } - $("#bootstrap-confirm-box-modal-submit").text( yes_label || 'Confirm' ); - $("#bootstrap-confirm-box-modal-cancel").text( no_label || 'Cancel' ); - $("#bootstrap-confirm-box-modal").modal('show'); + $("#bootstrap-confirm-box-modal-submit").text(yes_label || "Confirm"); + $("#bootstrap-confirm-box-modal-cancel").text(no_label || "Cancel"); + $("#bootstrap-confirm-box-modal").modal("show"); } - // Function to check errors from AJAX requests -const checkError = function(response) { +const checkError = function (response) { if (response.status >= 200 && response.status <= 299) { return response.json(); } else { @@ -144,92 +163,112 @@ const checkError = function(response) { }; //Add jQuery :focusable selector -(function($) { +(function ($) { function visible(element) { - return $.expr.filters.visible(element) && !$(element).parents().addBack().filter(function() { - return $.css(this, 'visibility') === 'hidden'; - }).length; + return ( + $.expr.filters.visible(element) && + !$(element) + .parents() + .addBack() + .filter(function () { + return $.css(this, "visibility") === "hidden"; + }).length + ); } function focusable(element, isTabIndexNotNaN) { - var map, mapName, img, nodeName = element.nodeName.toLowerCase(); - if ('area' === nodeName) { + var map, + mapName, + img, + nodeName = element.nodeName.toLowerCase(); + if ("area" === nodeName) { map = element.parentNode; mapName = map.name; - if (!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') { + if ( + !element.href || + !mapName || + map.nodeName.toLowerCase() !== "map" + ) { return false; } - img = $('img[usemap=#' + mapName + ']')[0]; + img = $("img[usemap=#" + mapName + "]")[0]; return !!img && visible(img); } - return (/input|select|textarea|button|object/.test(nodeName) ? - !element.disabled : - 'a' === nodeName ? - element.href || isTabIndexNotNaN : - isTabIndexNotNaN) && + return ( + (/input|select|textarea|button|object/.test(nodeName) + ? !element.disabled + : "a" === nodeName + ? element.href || isTabIndexNotNaN + : isTabIndexNotNaN) && // the element and all of its ancestors must be visible - visible(element); + visible(element) + ); } - $.extend($.expr[':'], { - focusable: function(element) { - return focusable(element, !isNaN($.attr(element, 'tabindex'))); - } + $.extend($.expr[":"], { + focusable: function (element) { + return focusable(element, !isNaN($.attr(element, "tabindex"))); + }, }); })(jQuery); -enquire.register("screen and (max-width:608px)", { - match : function() { - if($("body.scrollto").length > 0){ - window.scrollTo( 0, $(".maincontent").offset().top ); - } - } -}); +if (typeof enquire == "object") { + enquire.register("screen and (max-width:608px)", { + match: function () { + if ($("body.scrollto").length > 0) { + window.scrollTo(0, $(".maincontent").offset().top); + } + }, + }); -enquire.register("screen and (min-width:992px)", { - match : function() { - facetMenu( "show" ); - }, - unmatch : function() { - facetMenu( "hide" ); - } -}); + enquire.register("screen and (min-width:992px)", { + match: function () { + facetMenu("show"); + }, + unmatch: function () { + facetMenu("hide"); + }, + }); +} -function facetMenu( action ){ - if( action == "show" ){ - $(".menu-collapse-toggle").off("click", facetHandler ); +function facetMenu(action) { + if (action == "show") { + $(".menu-collapse-toggle").off("click", facetHandler); $(".menu-collapse").show(); } else { - $(".menu-collapse-toggle").on("click", facetHandler ).removeClass("menu-open"); + $(".menu-collapse-toggle") + .on("click", facetHandler) + .removeClass("menu-open"); $(".menu-collapse").hide(); } } -var facetHandler = function(e){ +var facetHandler = function (e) { e.preventDefault(); $(this).toggleClass("menu-open"); $(".menu-collapse").toggle(); }; -$(document).ready(function(){ +$(document).ready(function () { $("html").removeClass("no-js").addClass("js"); - $(".close").click(function(){ + $(".close").click(function () { window.close(); }); $(".focus").focus(); $(".js-show").show(); $(".js-hide").hide(); - if( $(window).width() < 991 ){ + if ($(window).width() < 991) { facetMenu("hide"); } // clear the basket when user logs out - $("#logout").click(function(){ + $("#logout").click(function () { var nameCookie = "bib_list"; var valCookie = readCookie(nameCookie); - if (valCookie) { // basket has contents - updateBasket(0,null); + if (valCookie) { + // basket has contents + updateBasket(0, null); delCookie(nameCookie); return true; } else { @@ -237,51 +276,65 @@ $(document).ready(function(){ } }); - $(".loginModal-trigger").on("click",function(e){ + $(".loginModal-trigger").on("click", function (e) { e.preventDefault(); var button = $(this); - var context = button.data('return'); - if ( context ) { + var context = button.data("return"); + if (context) { let return_url = window.location.pathname; let params = window.location.search; - var tab = button.data('tab'); - if ( tab ) { - params = params ? params + '&tab=' + tab : '?tab=' + tab; + var tab = button.data("tab"); + if (tab) { + params = params ? params + "&tab=" + tab : "?tab=" + tab; } return_url += params; - $('#modalAuth').append(''); + $("#modalAuth").append( + '' + ); } $("#loginModal").modal("show"); }); - $("#loginModal").on("shown.bs.modal", function(){ + $("#loginModal").on("shown.bs.modal", function () { $("#muserid").focus(); }); - $("#scrolltocontent").click(function() { + $("#scrolltocontent").click(function () { var content = $(".maincontent"); if (content.length > 0) { - $('html,body').animate({ - scrollTop: content.first().offset().top - }, - 'slow'); - content.first().find(':focusable').eq(0).focus(); + $("html,body").animate( + { + scrollTop: content.first().offset().top, + }, + "slow" + ); + content.first().find(":focusable").eq(0).focus(); } }); - $('[data-toggle="tooltip"]').tooltip(); + if (typeof bootstrap == "object") { + $('[data-toggle="tooltip"]').tooltip(); + } /* Scroll back to top button */ - $("body").append(''); + $("body").append( + '' + ); $("#backtotop").hide(); - $(window).on("scroll", function(){ - if ( $(window).scrollTop() < 300 ) { + $(window).on("scroll", function () { + if ($(window).scrollTop() < 300) { $("#backtotop").fadeOut(); } else { $("#backtotop").fadeIn(); } }); - $("#backtotop").on("click", function(e) { + $("#backtotop").on("click", function (e) { e.preventDefault(); - $("html,body").animate({scrollTop: 0}, "slow"); + $("html,body").animate({ scrollTop: 0 }, "slow"); }); }); -- 2.39.5