JQuery Library

JQuery modifications are a great way to customize the look and feel of your Koha install. Here are a few tips to remember when writing JQuery modifications:
* For the staff side, all JQuery statements go in the IntranetUserJS system preference
* For the OPAC, all JQuery statements go in the OPACUserJS system preference
* You must include $(document).ready(function(){ <multiple statements go here> }); inside the preference, around your statements. Most examples listed below are considered "statements" while some show the full preference code.
* Clients must have Javascript enabled in their browsers for these changes to take effect.
===Template===
Developers: Please use the following template to add your JQuery statements to the wiki.
==== JQuery Title ====
* Developer: Name of JQuery developer
* Creation Date: the date you entered the script (YYYY-MM-DD)
* Purpose: Purpose of the JQuery script
* Status: Completed / In progress
* Intranet or OPAC?: 
* Version: (The Koha version you are using this with, or Any, if applicable) 
 
 Some JQuery code
 
----
===Intranet JQuery Statements===
==== Add Hyperlink to Action Logs for a given Hold ====
* Developer: Kyle Hall
* Creation Date: 2020-01-30
* Purpose: Adds a tiny asterisk beside the cancel hold button that links to the action logs for the hold
* Status: Completed
* Version: any
$(document).ready(function() {
 if (window.location.href.indexOf("reserve/request.pl") > -1) {
 $("a.cancel-hold").each(function() {
 let url = $(this).attr('href');
 let reserve_id = getURLParameter(url, 'reserve_id');
 $(this).after(`<a title="Action logs for this hold" target="_blank" href="/cgi-bin/koha/tools/viewlog.pl?do_it=1&modules=HOLDS&object=${reserve_id}">*</a>`);
 });
 }
});
function getURLParameter(url, name) {
 return (RegExp(name + '=' + '(.+?)(&|$)').exec(url) || [, null])[1];
}
==== Highlight scanned barcode on biblio ====
* Developer: Lucas Gass
* Creation Date: 2022-06-29
* Purpose: Highlght scanned item on bib when searching by barcode
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.11
 
 $(document).ready(function () {
 if ( $('#catalog_detail').length && window.location.href.indexOf("found1=1") > -1 ) {
 setTimeout(function() {
 let search_value = $('#search-form').val().trim(); 
 let barcode_index = $('th:contains("Barcode")').index() +1; //add one for nth-child
 $('#holdings_table tbody tr td:nth-child('+barcode_index+')').each( function() {
 	if ( $(this).text() === search_value ) {
 	$(this).parent().addClass('found_bc');
 $(this).parent().children('td').css('background' , 'khaki');
 }
 })
 //now clear the search form
 if ( $('#cat-search-block').length ) {
 $('#search-form').val();
 localStorage.setItem('searchbox_value', );
 $('#search-form').focus();
 }
 }, 100);
 }
});
 
==== Alternative to AllFinesNeedOverride ====
* Developer: Kyle M Hall
* Purpose: Alternative to AllFinesNeedOverride in case you need to disable it for SIP2 to allow checkouts for patrons with fines or fees
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
$(document).ready(function() {
 if ($("a[href^='/cgi-bin/koha/members/pay.pl?borrowernumber=']")) {
 $('#circ_circulation_issue input').attr('disabled', 'disabled');
 $('#circ_circulation_issue button').hide();
 $("<button id='allow-circulation' class='btn btn-danger'>Patron owes fees</button>").insertAfter('#circ_circulation_issue button');
 $('#allow-circulation').on('click', function(e) {
 e.preventDefault();
 $('#circ_circulation_issue input').removeAttr('disabled');
 $('#circ_circulation_issue button').show();
 $('#allow-circulation').hide();
 });
 }
});
 
==== Hide a dataTable column ====
* Developer: Kyle M Hall
* Purpose: To hide a column of a dataTable with jQuery
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
In this example, we are hiding the 3rd column ("base-level allocated") of the budgets table in acquisitions
 
$( document ).ready(function() {
 $('#budgeth').on( 'init.dt', function () {
 $('#budgeth').dataTable().fnSetColumnVis( 4, false );
 });
});
 
==== Uncheck renew by default ====
* Developer: Kyle M Hall
* Purpose: Stop renew checkboxes from being checked by default on check out page
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
$( document ).ready(function() {
 $('#issues-table').on( 'init.dt', function () {
 $('.renew').attr('checked', false);
 });
});
 
==== Hide patron messages for library ====
* Developer: Kyle M Hall
* Purpose: To hide non-public patron messages from rubbernecking patrons, displaying the message only after clicking a "Show message" link
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
$(document).ready(function(){
 if (window.location.href.indexOf("circ/circulation.pl") > -1) {
 $("#messages .circ-hlt i").addClass("hidden-message").hide();
 $("#messages .circ-hlt i").parent().append("<a class='show-hidden-message' href=>[Show Message]</a>");
 $(".show-hidden-message").on('click', function() {
 $(this). parent().children('.hidden-message').show();
 $(this). parent().children('.show-hidden-message').hide();
 return false;
 });
 }
}); 
 
==== Set all library pulldowns to the logged in library ====
* Developer: Kyle M Hall
* Updated by: Christopher Brannon
* Purpose: To set all library pulldowns to the logged in library by default
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
 $( document ).ready(function() {
 var library_name = $.trim($('#drop3 strong').text());
 $(document.body).find('option').filter(function(index) {
 return library_name === $(this).text();
 }).attr("selected", "selected")
 });
 
* Version: 19.x
Not sure when this changed, but have noticed in 19.05 this doesn't work. Here is an update, and it also limits the pulldowns to the reports. Change "#rep_guided_reports_start" to "document.body" if you want any pulldown throughout Koha that selects branches to be set:
 
 var library_name = $.trim($('#user-menu span.logged-in-branch-name:first').text());
 $('#rep_guided_reports_start').find('option').filter(function(index) {
 return library_name === $(this).text();
 }).attr("selected", "selected");
 
==== Modify Labels on memberentry.pl (Patron edit screen) ====
* Developer: Liz Rea (NEKLS)
* Purpose: To change phone/email labels from Home/Mobile Phone to Phone/Email (primary) and Phone/Email (secondary). Also adds a helpful tip as to which field will be printed on transit slips.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
 $("#memberentry_contact label[for='phone']").html("Primary Phone :");
 $("#memberentry_contact label[for='email']").html("Primary Email :");
 $("#memberentry_contact label[for='emailpro']").html("Alternate Email :");
 $("#memberentry_contact li:contains('Primary Phone')").append(" Shows on transit slips");
 $("#memberentry_contact li:contains('Primary Email')").append(" Shows on transit slips");
 
This second bit changes the labels on the patron detail page:
 
 $("#patron-information .label:contains('Home:')").html('Primary Phone:');
 $("#patron-information .label:contains('Work:')").html('Alternate Phone:');
 $("#patron-information .label:contains('Email (work):')").html('Alternate Email:');
 $("#patron-information .label:contains('Email (home):')").html('Primary Email:');
 
==== Style required Patron Attribute as Required ====
* Developer: Owen Leonard with Nicole Engard
* Purpose: You can mark an attribute required in the system preferences, but it doesn't highlight it in red. This will add the required class to the attribute.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Older Versions (default in at least 16.11+ ...)
 
//style attribute in red since it's required
 $("#memberentry_patron_attributes label[for='patron_attr_4']").addClass("required");
 
==== Relabel Sort1 on Patron Record ====
* Developer: Lucas Gass, ByWater Solutions
* Purpose: This will allow you to relabel the sort 1 field on the patron add form and patron display to 'Township' (just replace with your own label).
* Status: Completed - updated 4/16/21 to prevent also changing sort1 in acquisitions
* Intranet or OPAC?: Intranet
* Version: Any
 
/* change sort1 label on member details page */
if ( $('#pat_moremember').length ) {
 $('#patron-sort1 .label').text('Township:');
}
/* change sort1 label on member entry form page */
if ( $('#pat_memberentrygen').length ) {
 $('label[for="sort1"]').text('Township:');
}
 
==== Remove Upcoming Events row from the messaging preferences table ====
* Developer: Liz Rea (NEKLS)
* Purpose: Remove the Upcoming Events row from the messaging prefs table. This was confusing because upcoming events notification requires additional software, but was always offered even if the additional software wasn't installed. This JQuery removes that row in the preferences table.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
 $("#memberentry_messaging_prefs tr:contains('Upcoming Events')").empty();
 $("#patron-messaging-prefs tr:contains('Upcoming Events')").empty();
 
==== Remove Return All functionality from check out screen/Patron Detail page ====
* Developer: Liz Rea (NEKLS)
* Purpose: Since the Return All functionality is only partially complete (it doesn't process holds correctly when used, a big problem in our system) we have chosen to remove the column for Return all, and the associated button. 
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
 $("#finesholdsissues #issuest").find("tbody td:last-child,thead th:last-child").hide();
 $("#finesholdsissues").find('input[id=return_all]').hide();
 $("#patronlists #issuest").find("tbody td:last-child,thead th:last-child").hide();
 
==== Remove Delete link from the News items on the Staff home screen ====
* Developer: Liz Rea (NEKLS)
* Purpose: Some of our librarians were deleting news items, we wanted to remove the link.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
 $(".newsfooter a:contains('Delete')").hide();
 
==== Adds Focus to Cataloging Search ====
* Developer: Liz Rea (NEKLS)
* Purpose: The cataloging search didn't seem to get focus after adding a bib. This adds that functionality.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.0.x (afaik)
 
 $("#addbooks_search input[name=q]:eq(0)").focus();
 
==== Hide a field on Patron detail screen ====
* Developer: Liz Rea (NEKLS)
* Purpose: Hide a desired field on the Patron detail screen
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any 
 
 $("#patron-information li:contains('Mobile:')").hide();
 
==== Hide left side menu on given page in staff client to have more space for contents ====
* Developer: Marc Véron
* Purpose: Hide th menu in the left column to get more space for big table e.g. in Administration->Circulation and fine rules
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any - Does not work on Koha 21.05
 if ((""+window.location).indexOf("smart-rules.pl")>=0) {
 $("#navmenu").hide();
 $(".yui-t1 #yui-main .yui-b").css("margin-left", "1em"); 
 }
==== Change the staff client's "Change Password" field to password type input ====
* Developer: Owen Leonard (Nelsonville Public Library)
* Purpose: Change the staff client's "Change Password" field to password type input. Useful if your staff client terminal is viewable by the public. This also removes Koha's default "suggested password" from the field.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.2 
 
 $(document).ready(function(){
 $("#newpassword").parent().append("<input type=\"password\" value=\"\" size=\"20\" id=\"newpassword\" name=\"newpassword\">").end().remove();
 });
 
==== Add additional searches to Intranet ====
* Developer: Magnus Enger, but based on "Add additional searches to OPAC" by Jared Camins-Esakov above
* Purpose: Adds additional searches to the Intranet Search type dropdown, in a specific place in the drop down
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
* Note: The goal here is to add the Dewey index after the "Subject as Phrase" index, and indent it to the same level as that index. Since matching is done on the values of elements in the list of options (and not on the text labels) this should work across translations too. 
 
 $('option[value="su,phr"]').after("<option value='Dewey-classification'>     Dewey</option>");
 
==== Remove link to Holds to pull page ====
* Developer: Ian Walls
* Purpose: Removes "Holds to pull" link from the circulation page
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
* Note: Often, the Holds to pull list is deprecated for library use vs. the Holds Queue. This query removes the link in an effort to remove staff confusion. Sponsored by MassCat.
 
 $("ul li:contains('Holds to pull')").remove();
 
==== Streamline Import Patrons page ====
* Developer: Daniel Grobani
* Purpose: removes unneeded fields and sets desired values
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: LLEK 4.0200019
 
 // remove "default values" fieldset
 $('form[action] legend:contains("Default values")').parent().remove();
 // set record matching field to ID
 $('fieldset:has(legend:contains("Field to use for record matching")) #matchpoint').val("ID");
 // overwrite matching record
 $('#overwrite_cardnumberno').attr('checked', 'false');
 $('#overwrite_cardnumberyes').attr('checked', 'true');
 // replace only included extended attributes
 $('#ext_preserve_0').attr('checked', 'false');
 $('#ext_preserve_1').attr('checked', 'true');
 
==== Point out there is a button for renewing items at bottom of patron page ====
* Developer: Jared Camins-Esakov, ByWater Solutions
* Purpose: Alerting staff to the fact that they can renew/return items directly from the patron record; particularly relevant for patrons with huge numbers of items checked out, where staff might forget about the renewal button at the bottom
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.4
 
 $("#issuest").parent().prepend("See below to renew all or selected items.");
 
==== Don't Allow Checkout Overrides ====
* Developer: Scott Merrill , CAUSE
* Purpose: Removes the override option for circulation rules that block checkouts... right now, if you have a maximum line of X item type out to a patron type, you'll always get a prompt asking if you want to override, this removes the prompt
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.4+
 
$("#circ_needsconfirmation ul li:contains('This patron can\'t check out this
item per library circulation policy')").parent().siblings().hide();
 
==== Hide Streetnumber field on Patron edit screen ====
* Developer: Joy Nelson, ByWater Solutions
* Purpose: Remove the Street Number field from the patron edit screen.
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.6+
 
$("#entryform #streetnumber").parent().hide();
==== Hide the Patron column in the Holds Que report ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Hides the Patron column in the Holds Que report but could be changed to hide any column within the report.
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.6+
 
$("#holdst .hq-patron").hide();
==== Add a link to self checkout on intranet login screen ====
* Developer: Koha Community
* Purpose: Add a link to the built-in self checkout function to the intranet login screen
* Status: Completed
* Intranet
* Version: Any
 
 $("#login .submit").parent().after("<a href=\"http://YOUR_KOHA_OPAC_URL/cgi-bin/koha/sco/sco-main.pl\" target=\"_blank\">Self-Checkout</a>"); 
 
==== Keyboard shortcuts to quickly change tab while showing or editing MARC records ====
* Developer: Stefano Bargioni (Pontificia Università della Santa Croce) - 2012-04-26
* Purpose: Keyboard shortcuts to change tab while showing or editing MARC records
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any 
 
// MARC bib edit
if (location.pathname.indexOf('cataloguing/addbiblio.pl')>-1) {
	$(document).keydown(function(e) {
		if (e.target.tagName == 'INPUT') return;
		if (e.target.tagName == 'TEXTAREA') return;
		var f = 0; // flag
		var c = e.which; // code key pressed
		if (c>=48 && c<=57) {f=1; c-=48;} // 0..9 keyboard
		if (c>=96 && c<=105) {f=1; c-=96;} // 0..9 keypad
		if (f==0) return;
		var marc_sections = $('#addbibliotabs ul li a').text().replace(/[^0-9]/g,);
		var marc_section = marc_sections.indexOf(c);
		if (marc_section == -1) return;
		$($('#addbibliotabs ul li a')[marc_section]).click();
	});
}
// MARC bib show
if (location.pathname.indexOf('catalogue/MARCdetail.pl')>-1) {
	$(document).keydown(function(e) {
		if (e.target.tagName == 'INPUT') return;
		if (e.target.tagName == 'TEXTAREA') return;
		var f = 0; // flag
		var c = e.which; // code key pressed
		if (c>=48 && c<=57) {f=1; c-=48;} // 0..9 keyboard
		if (c>=96 && c<=105) {f=1; c-=96;} // 0..9 keypad
		if (f==0) return;
		var marc_sections = $('#bibliotabs ul li a').text().replace(/[^0-9]/g,);
		var marc_section = marc_sections.indexOf(c);
		if (marc_section == -1) return;
		$($('#bibliotabs ul li a')[marc_section]).click();
	});
}
// MARC auth show
if (location.pathname.indexOf('authorities/detail.pl')>-1) {
	$(document).keydown(function(e) {
		if (e.target.tagName == 'INPUT') return;
		if (e.target.tagName == 'TEXTAREA') return;
		var f = 0; // flag
		var c = e.which; // code key pressed
		if (c>=48 && c<=57) {f=1; c-=48;} // 0..9 keyboard
		if (c>=96 && c<=105) {f=1; c-=96;} // 0..9 keypad
		if (f==0) return;
		var marc_sections = $('#authoritiestabs ul li a').text().replace(/[^0-9]/g,);
		var marc_section = marc_sections.indexOf(c);
		if (marc_section == -1) return;
		$($('#authoritiestabs ul li a')[marc_section]).click();
	});
}
// MARC auth edit
if (location.pathname.indexOf('authorities/authorities.pl')>-1) {
	$(document).keydown(function(e) {
		if (e.target.tagName == 'INPUT') return;
		if (e.target.tagName == 'TEXTAREA') return;
		var f = 0; // flag
		var c = e.which; // code key pressed
		if (c>=48 && c<=57) {f=1; c-=48;} // 0..9 keyboard
		if (c>=96 && c<=105) {f=1; c-=96;} // 0..9 keypad
		if (f==0) return;
		var marc_sections = $('#authoritytabs ul li a').text().replace(/[^0-9]/g,);
		var marc_section = marc_sections.indexOf(c);
		if (marc_section == -1) return;
		$($('#authoritytabs ul li a')[marc_section]).click();
	});
}
 
==== Hide SQL statement when running guided report ====
* Developer: Galen Charlton
* Purpose: Hide the SQL query when running a guided report
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.4.x and later
 
 $("#sql_output").hide();
 
==== Set sort order to ascending call number if selecting call number search in the staff interface ====
* Developer: Galen Charlton
* Purpose: Set sort order to ascending call number if selecting call number search in the staff interface
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.0.x and later (tested in 3.8.x)
 
 $("select.advsearch").change(function() {
 var idx = $(this).val();
 if (idx.substring(0, 7) == 'callnum') {
 $("select#sort_by").val('call_number_asc');
 }
 });
 
==== Add a filter to the patron various tables in staff interface ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library), based of original code by Kobi Lidershnider at http://kobikobi.wordpress.com/2008/09/15/using-jquery-to-filter-table-rows/
* Purpose: To help find information in various tables, such as the Account and Pay fines portions of patron Fines, Edit items in cataloging, or the details screen for a bib in the staff catalog.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
//Add filter to various tables
$("#yui-main div[class='tabs-container'] table").attr("class","filterable"); //filter for fines
$("#yui-main div[id='cataloguing_additem_itemlist'] table").attr("class","filterable"); //filter for Edit items in cataloging
$("#yui-main div[id='bibliodetails'] table").attr("class","filterable"); //filter for bib items in staff catalog
$("Filter: <input type='text' id='FilterTextBox' name='FilterTextBox' /><a href='#' class='clear' rel='nofollow'> Clear</a></p>").insertBefore("#yui-main table[class='filterable']");
$(".filterable tr:has(td)").each(function(){var t = $(this).text().toLowerCase();
$("").hide().text(t).appendTo(this);
});//each tr
 $("#FilterTextBox").keyup(function(){
 var s = $(this).val().toLowerCase().split(" ");
 //show all rows.
 $(".filterable tr:hidden").show();
 $.each(s, function(){
 $(".filterable tr:visible .indexColumn:not(:contains('"
 + this + "'))").parent().hide();
 });//each
 });//key up.
$(".clear").click(function(){
 $("#FilterTextBox").val("").keyup();
 return false;
 });
//end filters
==== Clean up patron details screen ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library)
* Purpose: Remove unused lines in the Alternate address or Alternative contact sections of the Patron Details screen.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
//Condense Patron Display
$("#patron-alternate-address,#patron-alternative-contact").find("li").hide();
$("#patron-alternate-address li,#patron-alternative-contact li") 
 .contents() 
 .filter(function() { 
 return this.nodeType == Node.TEXT_NODE; 
 }).wrap(""); 
$("#patron-alternate-address,#patron-alternative-contact").find(".availablecontent").each(function() {
$(this).parent("li").show();
});
//end Condense Patron Display
==== Alert staff about missing email or phone upon checkout ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Purpose: Alert staff about missing email or phone upon checkout.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
* Note: Alert staff upon item checkout that a patron's email or phone is blank.'''
 
// Confirm that we're on the "Checking Out" page
myvar0 = /circulation\.pl/.test(window.location.pathname);
// is there a mailto: link on this page?
myvar1 = $('a[href*="mailto"]').length;
myvar2 = $("#nophonestored").length;
if(myvar0 != 0 && myvar1 == 0) {
 alert('Patron email is blank!');
 }
if(myvar0 != 0 && myvar2 != 0) {
 alert('Phone number is missing!');
 }
 
==== Alert inattentive staff to read patron notes ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Purpose: Alert staff about blank email upon checkout.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
* Note: Alert inattentive staff to read and resolve patron notes upon item checkout. This alert is repeated upon every page reload.'''
 
 // alert any circulation notes
 // Confirm that we're on the "Checking Out" page
 myvar0 = /circulation\.pl/.test(window.location.pathname);
	myvar4 = $('#circnotes').length;
 if (myvar0 != 0 && myvar4 != 0) {
		myvar5 = $('#circnotes span.circ-hlt').text();
		alert(myvar5);
	}
 
==== Add 'Hide/Unhide $0.00 balances' toggle button to fines screen ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium
* Purpose: Creates a toggle button that hides or shows any lines from the patron fines table that have been paid in full.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.8
* Note: The button requires 2 parts. The first part adds a Jquery selector called 'contentIs.' The second statement creates the toggle button. For the button to work correctly you must include the statement to create the 'contentIs' selector.'''
 
//add the “contentIs” selector to return exact matches
$.expr[':'].contentIs = function(el, idx, meta) {
 return $(el).text() === meta[3];
};
//end “contentIs” selector
//begin Zero Balance Button
//Adds a toggle button to the account tab on the patron fines screen that hides or shows any lines in a patron's account with an outstanding balance of zero
var new_btn = $('<button id="0hide">Hide/Unhide $0.00 balances</button>');
new_btn.insertBefore('#PatronAccountTable:first');
$('#0hide').click(function() {
$(".credit:contentIs(0.00)").parents("tr").toggle();
});
//end Zero Balance Button
 
==== Change Manual Credit to Add Note ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Purpose: Change the Manual Credit function to an Add Note function.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
* Note: Manual Credit was problematic for us, especially in reporting. Our staff used it only because of the notes field in order to give a reason when writing off a fine. Since the form assumes $0.00 upon submission, we just hide the amount field and then change the text on various elements.'''
 
//rename the tab from "Create manual credit" to "Add note"
 $('a[href*="mancredit"]').text('Add note');
// Also if we're on the "Create manual credit" subpage: 
 myvar0 = /mancredit\.pl/.test(window.location.pathname);
 if(myvar0 != 0) {
 $("li:contains('Amount: ')").hide();
 $("legend:contains('Manual credit')").text('Add note');
 $("input[name='add']").val('Create note');
 }
 
==== Remove 23:59 time dues from Circ and Catalogue when hourly loans are not in use ====
* Developer: Liz Rea (Catalyst IT)
* Purpose: Remove the time due from intranet detail and circulation pages.
* Intranet or OPAC?: Intranet
* Version: 3.8+
 
 $("#issuest td:contains('23:59')").each(function() {
 var text = $(this).text().replace('23:59', );
 $(this).text(text);
 });
 $(".datedue:contains('23:59')").each(function() {
 var text = $(this).text().replace('23:59', );
 $(this).text(text);
 }); 
 
Looks like it is obsolete since use of as_due_date added by Bug 11148
==== Force Staff to use Datepicker when altering due dates, renewal dates, and suspend until dates ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium
* Purpose: Since incorrectly formatted due dates can be entered in the "specify due date", "renewal date", and "suspend until" input boxes (and incorrectly formatted dates can cause system errors), this jQuery forces staff to use the calendar datepicker to choose dates for these options.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.8
 
//BEGIN Force staff to use datepicker for altering due dates, renewal dates, and suspend unitl dates
$("#duedatespec").attr("readonly", "readonly");
$("#newduedate").attr("readonly", "readonly");
$("#suspend_until").attr("readonly", "readonly");
$(".hint:contains('Specify due date (MM/DD/YYYY):')").text('Use calendar button to choose new Due Date');
$("p:contains(Renewal due date:)").prepend('Use calendar button to choose ');
$(".hint:contains('Specify date on which to resume (MM/DD/YYYY):')").text('Use calendar button to specify the date when holds will resume');
//END Force staff to use datepicker for altering due dates, renewal dates, and suspend unitl dates
 
==== Hide some of the displayed fields when adding or editing an item ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium
* Purpose: Hides selected fields in the "Add item" and "Edit item" pages. 
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10
* Note: Catalogers in our consortium want the default display of these screens to be shorter but they also need the ability to look at all fields if necessary. This example hides the 0, 1, 4, f, and j subfields. To remove different fields from the default display when the page loads add "li:contains(SUBFIELD -)" to the selector.
 
//BEGIN Hide and Show All Fields buttons for Catalogers
$(".yui-u #cataloguing_additem_newitem .rows li:contains('0 - '), li:contains('1 - '), li:contains('4 - '), li:contains('f - '), li:contains('j - ')").hide();
var new_btn = $('<button id="cataddhide">Show all fields</button>');
new_btn.prependTo('.yui-u #cataloguing_additem_newitem .rows');
$('#cataddhide').click(function(e) {
e.preventDefault();
$(".yui-u #cataloguing_additem_newitem .rows li:contains(' ')").show();
$('#cataddhide').fadeOut();
});
//END Show All Fields buttons for Catalogers
 
==== Preview OPAC syspref changes ====
* Developer: Jared Camins-Esakov, C & P Bibliography Services
* Purpose: Provides a preview for basic OPAC customizations on the OPAC syspref page.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10+ with bug 10405 and a special web server configuration
* Note: You will need to adjust the preview URLs for your particular installation. The URLs used in this sample were especially configured so that /cgi-bin/koha/opac/ would be forwarded to the OPAC. Also be aware that only part of the script goes in $(document).ready(..). To make this clear, I have included the $(document).ready(...) in the script.
 
function showPreview(url) {
 document.getElementById('opac-preview').src = url;
 $('#preview-loading').show();
 $('#opac-preview').load(function () {
 $('#opac-preview').show();
 $('#region-opaccredits', $('#opac-preview').contents()).html($('#pref_opaccredits').val());
 $('#region-opacheader', $('#opac-preview').contents()).html($('#pref_opacheader').val());
 $('#opacmainuserblock', $('#opac-preview').contents()).html($('#pref_OpacMainUserBlock').val());
 $('#opacmainuserblockmobile', $('#opac-preview').contents()).html($('#pref_OpacMainUserBlockMobile').val());
 $('#region-opacnav', $('#opac-preview').contents()).html($('#pref_OpacNav').val());
 $('#region-opacnavbottom', $('#opac-preview').contents()).html($('#pref_OpacNavBottom').val());
 $('#noresultsfound', $('#opac-preview').contents()).html($('#pref_OPACNoResultsFound').val());
 $('#opacresultssidebar', $('#opac-preview').contents()).html($('#pref_OPACResultsSidebar').val());
 $('#region-opacusercss', $('#opac-preview').contents()).replaceWith('<style id="region-opacusercss" type="text/css">' + $('#pref_OPACUserCSS').val() + '</style>');
 $('#region-opacuserjs', $('#opac-preview').contents()).replaceWith('<' + 'script id="region-opacuserjs" type="text/javascript">' + $('#pref_opacuserjs').val() + '<' + '/script>');
 $('#preview-loading').hide();
 });
}
$(document).ready(function () {
 if ($('#pref_OpacNav').size() > 0) {
 $('#doc3').after('Preview changes<button type="button" class="btn" id="preview-main">Main page</button><button type="button" class="btn" id="preview-results">Results</button><button type="button" class="btn" id="preview-details">Details</button><button type="button" class="btn active" id="preview-hide">Hide</button><img id="preview-loading" style="display: none;" src="/intranet-tmpl/prog/img/loading-small.gif"/><iframe id="opac-preview" style="height: 20em; width: 100%; display: none;"></iframe>');
 $('#preview-main').click(function () {
 showPreview('/cgi-bin/koha/opac/opac-main.pl');
 });
 $('#preview-results').click(function () {
 showPreview('/cgi-bin/koha/opac/opac-search.pl?idx=&q=pqf%3D%40attr+1%3D_ALLRECORDS+%40attr+2%3D103+%22%22&branch_group_limit=');
 });
 $('#preview-details').click(function () {
 showPreview('/cgi-bin/koha/opac/opac-detail.pl?biblionumber=1');
 });
 $('#preview-hide').click(function () {
 $('#opac-preview').hide();
 });
 }
});
 
==== Populate Username with Cardnumber ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Copy cardnumber to username field on new patron form
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
//Causes the user cardnumber to auto populate to the Username.
$("#entryform #cardnumber").blur(function(){
$("#entryform #userid").val($("#entryform #cardnumber").val());
});
 
==== Validate patron data fields ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Purpose: Validate data when creating or editing patron records.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.12
* Note: Koha performs only basic validation (i.e. required fields). This jQuery script replaces the default SAVE button with a VALIDATE button which runs a custom validation using regular expressions. Upon successful validation it submits the form data. NOTE - this script is very large and will require additional customization to fit your library, since it contains our library's unique patron categorycodes and our validation definitions. For example, we require 2 email addresses for all patrons, but allow the 2 addresses to be the same for only some categorycodes, while requiring them to be different for other categorycodes.
 
 //hide the miniature EDIT links on the patron details screen
 $("#patron-alternate-address").next('div').hide();
 $("#patron-alternative-contact").next('div').hide();
 $("#patron-messaging-prefs").next('div').hide();
 $('div.yui-u div.action a:contains("Edit")').hide();
 $('#patron-information a:contains("Edit")').hide();
 // validate patron EDIT data by hiding the SAVE button, running an inline validation script, then submitting the form if it passes validation.
 //we can secretly bypass validation if the shift key is pressed, so we bind the keydown event to a specific textarea in order to check for a pressed SHIFT key
 $('textarea#patron_attr_4').keyup(function (e) {
 if (e.which == 16) $.isShift = false;
 }).keydown(function (e) {
 if (e.which == 16) $.isShift = true;
 });
 // create the validation function
 patronValidate = function () {
 //if the shift key is pressed then skip validation
 if ($.isShift) {
 return check_form_borrowers();
 } else {
 //start with an empty alert message
 var mes = "";
 //get all our variables
 var surname = $('input[id=surname]').val();
 var firstname = $('input[id=firstname]').val();
 var address = $('input[id=address]').val();
 var city = $('input[id=city]').val();
 var state = $('input[id=state]').val();
 var zipcode = $('input[id=zipcode]').val();
 var phone = $('input[id=phone]').val();
 var phonepro = $('input[id=phonepro]').val();
 var email = $('input[id=email]').val();
 var emailpro = $('input[id=emailpro]').val();
 var cardnumber = $('input[id=cardnumber]').val();
 var categorycode = $('select[id=categorycode]').val();
 var dateexpiry = $('input[id=to]').val();
 var userid = $('input[id=userid]').val();
 var school = $('select[id=patron_attr_3]').val();
 var rnumber = $('textarea[id=patron_attr_2]').val();
 //create our arrays for expiration dates and eRaider validation
 var fullYear = ['ADMIN', 'EMPLOYEE', 'FACULTY', 'RETIRED', 'STAFF'];
 var nonTTUHSC = ['CLINFAC', 'CONTRACTS', 'DEBTORS', 'FRIEND', 'PRECEPTOR', 'HOSPITAL'];
 //create our regexes
 // case-sensitive regexes
 var cardnumberReg = /(^P[A-Z0-9]{5}$)|(^R[0-9]{8}$)/;
 var stateReg = /^([A-Z]{2}$)/;
 var useridReg = /^([a-z0-9_]{3,8})$/;
 // case-insensitive regexes
 var surnameReg = /^[a-zA-Z\-\\'\ ]+$/;
 var firstnameReg = /^[a-zA-Z\-]+$/;
 var cityReg = /^[a-zA-Z ]+$/;
 var addressReg = /^(([0-9]{1,5}|POB|RT) .+)/;
 var zipReg = /(^[0-9]{5}(-[0-9]{4})?$)/;
 var phoneReg = /^([2-9][0-9]{2}-[0-9]{3}-[0-9]{4})$/;
 var emailReg = /^([a-z0-9\-]+\.([a-z]\.)?[a-z\-]+@ttuhsc\.edu)$/i;
 var emailReg2 = /^(.+@.+\.[a-z]{2,3})$/i;
 var alumniReg = /^((11\/30\/20[0-9]{2})|(02\/15\/20[0-9]{2})|(06\/30\/20[0-9]{2}))$/;
 var clinfacReg = /^(08\/31\/20[0-9]{2}$)/;
 var higheredReg = /^(06\/30\/20[0-9]{2}$)/;
 var hospitalReg = /^(12\/31\/20[0-8][0-9]$)/;
 var studentReg = /^((05\/31\/20[0-9]{2})|(08\/15\/20[0-9]{2})|(12\/31\/20[0-8][0-9]))$/;
 var rnumblankReg = /^$/
 var rnumReg = /^(R[0-9]{8})$/;
 // validate surname
 if (!surnameReg.test(surname)) {
 mes = mes + "\nLast name contains invalid characters.\n";
 }
 // validate firstname
 if (!firstnameReg.test(firstname)) {
 mes = mes + "\nFirst name contains invalid characters (e.g. spaces).\n";
 }
 // validate city
 if (!cityReg.test(city)) {
 mes = mes + "\nCity contains invalid characters.\n";
 }
 // validate street address
 if (!addressReg.test(address)) {
 mes = mes + "\nStreet address must begin with a number, POB or RT\n";
 }
 // validate state
 if (!stateReg.test(state)) {
 mes = mes + "\nState abbreviation must be exactly 2 uppercase characters.\n";
 }
 // validate zipcode
 if (!zipReg.test(zipcode)) {
 mes = mes + "\nZip code looks invalid.\n";
 }
 // validate primary phone
 if (!phoneReg.test(phone)) {
 mes = mes + "\nPrimary phone must be exactly XXX-XXX-XXXX\n";
 }
 // validate secondary phone
 if (!phoneReg.test(phonepro)) {
 mes = mes + "\nSecondary phone must be exactly XXX-XXX-XXXX\n";
 }
 // validate both email addresses
 if (!emailReg2.test(email)) {
 mes = mes + "\nPrimary email looks invalid.\n";
 }
 if (!emailReg2.test(emailpro)) {
 mes = mes + "\nSecondary email looks invalid.\n";
 }
 /* some categorycodes require 2 email addresses
 if ((nonTTUHSC.indexOf(categorycode) == -1 || categorycode == 'ALUMNI' ) && email == emailpro) {
 mes = mes + "\nPatron class \'" +
	categorycode + "\' requires 2 distinct email addresses.\n";
 }*/
 //validate the cardnumber
 if (!cardnumberReg.test(cardnumber)) {
 mes = mes + "\nCardnumber is invalid.\n";
 }
 //validate the userid if affiliated
 if (nonTTUHSC.indexOf(categorycode) == -1 && !useridReg.test(userid)) {
 mes = mes + "\nUsername \(eRaider\) must be lowercase letters and numbers only.\n";
 }
 //validate the school
 if (school == ) {
 mes = mes + "\nYou must chose a school or choose \'Other\'.\n";
 }
 //set or check dateexpiry based upon categorycode
 if (fullYear.indexOf(categorycode) != -1) {
 $('input[id=to]').val('12/31/2099');
 }
 if (categorycode == 'CLINFAC' && !clinfacReg.test(dateexpiry)) {
 mes = mes + "\nClinical Faculty must expire on exactly 08\/31\/20xx.\n";
 }
 if (categorycode == 'HIGHERED' && !higheredReg.test(dateexpiry)) {
 mes = mes + "\nResidents and Fellows must expire on exactly 06\/30\/20xx.\n";
 }
 if (categorycode == 'HOSPITAL' && !hospitalReg.test(dateexpiry)) {
 mes = mes + "\nHospital employees must expire on exactly 12\/31\/20xx.\n";
 }
 if (categorycode == 'ALUMNI' && !alumniReg.test(dateexpiry)) {
 mes = mes + "\nAlumni must expire on exactly 02\/15\/20xx, or 06\/30\/20xx, or 11\/30\/20xx.\n";
 }
 if (categorycode == 'STUDENT' && !studentReg.test(dateexpiry)) {
 mes = mes + "\nStudents must expire on exactly 05\/31\/20xx, or 08\/15\/20xx, or 12\/31\/20xx.\n";
 }
 //R numbers are not required,
 //but if used, they should validate
 if (!rnumblankReg.test(rnumber) && !rnumReg.test(rnumber)) {
 mes = mes + "\nR number must begin with \'R\' and be 8 digits.\n";
 }
 // display the alert
 if (mes != "") {
 alert(mes);
 return false;
 } else {
 alert("All data looks good!");
 // submit the validated form
 check_form_borrowers();
 }
 }
 };
 // Hide the SAVE button, create the VALIDATE button
 $('#entryform > fieldset.action').prepend('<input id="validate" type="submit" value="Validate" onclick="return patronValidate();" name="validate">');
 $('#entryform input[name=save]').hide();
 
==== Validate patron data fields variation for v21.x ====
* Developers: Christopher Brannon - Coeur d'Alene Public Library / Cooperative Information Network
* Purpose: Validate data when creating or editing patron records.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.x
* Note: This is an update of the previous version. Just updated with changes for the more recent versions of Koha, and shows other validation variations.
 
 /* Hide all miniture EDIT links on the patron details screen */
 #pat_moremember #patron-information a.btn, #pat_moremember #patron-messaging-prefs a.btn, #pat_moremember #patron-library-details a.btn, #pat_moremember #patron-alternative-contact a.btn, #pat_moremember #patroninfo-heading a.btn {
 display: none;
 }
 
 
	// create the validation function
	patronValidate = function () {
	//start with an empty alert message
	var mes = "";
	//get all our variables
	var surname = $('input[id=surname]').val();
	var firstname = $('input[id=firstname]').val();
	var othernames = $('input[id=othernames]').val();
	var maddress = $('input[id=address]').val();
	var mcity = $('input[id=city]').val();
	var mstate = $('input[id=state]').val();
	var mzipcode = $('input[id=zipcode]').val();
	var pphone = $('input[id=phone]').val();
	var pemail = $('input[id=email]').val();
	var paddress = $('input[id=B_address]').val();
	var pcity = $('input[id=B_city]').val();
	var pstate = $('input[id=B_state]').val();
	var pzipcode = $('input[id=B_zipcode]').val();
	var sphone = $('input[id=phonepro]').val();
	var semail = $('input[id=emailpro]').val();
	var smsphone = $('#SMSnumber').val();
	//create our regexes
	// case-sensitive regexes
	var mstateReg = /^([A-Z]{2}$)/;
	var pstateReg = /^([A-Z]{2}$)|^$/;
	// case-insensitive regexes
	var spaceReg = /^\s|\s$/;
	var surnameReg = /^[a-zA-Z][a-zA-Z\-'\ \,]*[a-zA-Z]$/;
	var firstnameReg = /^[a-zA-Z][a-zA-Z\-'\ \,]*[a-zA-Z]$/;
	var mcityReg = /^[a-zA-Z][a-zA-Z \']+[a-zA-Z]$/;
	var maddressReg = /^(([0-9]{1,5}|PO Box [0-9]*|(RR|HC|PSC|UNIT)\s[0-9]*\sBox).+)[a-zA-Z0-9\.]*$|ADDRESS UPDATE REQUIRED/;
	var maddressTempReg = /^(202)\s.*(harrison)/i;
	var mzipReg = /(^[0-9]{5}(-[0-9]{4})?$)/;
	var pphoneReg = /^([2-9][0-9]{2}-[0-9]{3}-[0-9]{4})$|^NA$/;
	var emailReg = /^([a-z0-9_-]+)([._-]([0-9a-z_-]+))*@([a-z0-9]+)([._-]([0-9a-z]+))*([.]([a-z0-9]+){2,4})$|^$/i;
	var paddressReg = /^(([0-9]{1,5}|(RR|HC|PSC|UNIT)\s[0-9]*\sBox).+)[a-zA-Z0-9\.]*$|^$/;
	var pcityReg = /^[a-zA-Z][a-zA-Z \']+[a-zA-Z]$|^$/;
	var pzipReg = /(^[0-9]{5}(-[0-9]{4})?$)|^$/;
	var sphoneReg = /^([2-9][0-9]{2}-[0-9]{3}-[0-9]{4})$|^$/;
	// validate surname
	if (!surnameReg.test(surname)) {
	mes = mes + "\nLast name contains invalid characters.\n";
	}
	if (spaceReg.test(surname)) {
	mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate firstname
	if (!firstnameReg.test(firstname)) {
	mes = mes + "\nFirst/Middle name(s) contains invalid characters.\n";
	}
	if (spaceReg.test(firstname)) {
	mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate othernames
	if (spaceReg.test(othernames)) {
	mes = mes + "\nOther name contains a space at the beginning or end of the field.)\n";
	}
	// verify if birth date is blank when needed (This example test against our children categories, which all start with MINOR.)
	if (($('input[name=dateofbirth]').val() == "") && ($("#categorycode_entry").val().match('^MINOR'))) {
	mes = mes + "\nMinor category requires a birth date.\n";
	}
	// validate category (This test does not allow our self check category (SELF) to be saved.)
	if ($("#categorycode_entry").val() == 'SELF') {
	mes = mes + "\nPlease change Patron Category.\n";
	}
	// validate mail city
	if (!mcityReg.test(mcity)) {
	 mes = mes + "\nMail city contains invalid characters.\n";
	}
	if (spaceReg.test(mcity)) {
	 mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate physical city
	if (!pcityReg.test(pcity)) {
	 mes = mes + "\nPhysical city contains invalid characters. Leave blank if unused.\n";
	}
	if (spaceReg.test(pcity)) {
	 mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate mail street address
	if (!maddressReg.test(maddress)) {
	 mes = mes + "\nMail street address not formatted properly (i.e. begins with number, PO Box, RR, HC, PSC or UNIT.)\n";
	}
	if (spaceReg.test(maddress)) {
	 mes = mes + "\nA space has been found at beginning or end of the mailing address.\n";
	}
	// validate physical street address
	if (!paddressReg.test(paddress)) {
	 mes = mes + "\nPhysical street address not formatted properly (i.e. begins with number, RR, HC, PSC or UNIT. Cannot be PO Box. Leave blank if unused.)\n";
	}
	if (spaceReg.test(paddress)) {
	 mes = mes + "\nA space has been found at beginning or end of the physical address.)\n";
	}
	// check for duplicate addresses
	if (maddress == paddress && maddressReg.test(maddress)) {
	 mes = mes + "\nAddresses can not be the same!\n";
	}
	 // check for po box (PO Box 1737 with 83701 ZipCode is part of the Address Confientiality Program / Can't ask for Physical Address)
	 if ((maddress == 'PO Box 1737') && (mzipcode == '83701')) {
		mes = mes;
	 } else if (maddress.substr(0,6) == "PO Box" && (paddress == "" || pcity == "" || pstate == "" || pzipcode == "")) {
		 mes = mes + "\nPhysical address required if Primary address is a PO Box!\n";
	 }
	// validate mail state
	if (!mstateReg.test(mstate)) {
	 mes = mes + "\nMail state abbreviation must be exactly 2 uppercase characters.\n";
	}
	if (spaceReg.test(mstate)) {
	 mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate physical state
	if (!pstateReg.test(pstate)) {
	 mes = mes + "\nPhysical state abbreviation must be exactly 2 uppercase characters. Leave blank if unused.\n";
	}
	if (spaceReg.test(pstate)) {
	 mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate mail zipcode
	if (!mzipReg.test(mzipcode)) {
	 mes = mes + "\nMail zip code must in entered like XXXXX[-XXXX].\n";
	}
	if (spaceReg.test(mzipcode)) {
	 mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate physical zipcode
	if (!pzipReg.test(pzipcode)) {
	 mes = mes + "\nPhysical zip code must in entered like XXXXX[-XXXX]. Leave blank if unused.\n";
	}
	if (spaceReg.test(pzipcode)) {
	 mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	 
	// validate primary phone
	if (!pphoneReg.test(pphone)) {
	mes = mes + "\nPrimary phone must be exactly XXX-XXX-XXXX or NA\n";
	}
	if (spaceReg.test(pphone)) {
	mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// validate secondary phone
	if (!sphoneReg.test(sphone)) {
	mes = mes + "\nSecondary phone must be exactly XXX-XXX-XXXX. Leave blank if unused.\n";
	}
	if (spaceReg.test(sphone)) {
	mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// check for duplicate phone
	if (pphone == sphone && pphone !="NA" && pphoneReg.test(pphone)) {
	mes = mes + "\nPhone numbers can not be the same!\n";
	}
	// validate both email addresses
	if (!emailReg.test(pemail)) {
	mes = mes + "\nPrimary email looks invalid. Leave blank if unused.\n";
	}
	if (spaceReg.test(pemail)) {
	mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	if (!emailReg.test(semail)) {
	mes = mes + "\nSecondary email looks invalid. Leave blank if unused.\n";
	}
	if (spaceReg.test(semail)) {
	mes = mes + "(A space has been found at beginning or end of the field.)\n";
	}
	// check for duplicate e-mail
	if (pemail == semail && pemail !="") {
	mes = mes + "\nE-mail addresses can not be the same!\n";
	}
	 
	//check if SMS values are set correctly
	if (smsphone != && smsphone.length != 12) {
	mes = mes + "\nSMS phone number needs to be set correctly! (+1XXXXXXXXXX)\n";
	}
	// display the alert
	if (mes != "") {
	 alert(mes);
	 return false;
	} else {
	// submit the validated form
	 if( check_form_borrowers() ){
		 $("#entryform").submit();
	 }
	}
	};
	// Hide the SAVE button, create the VALIDATE button
	$('#pat_memberentrygen #saverecord').replaceWith('<button id="validate" class="btn btn-small toggler" name="validate" style="margin-left: 0px;" onclick="return patronValidate();"> Save</button>');
 
==== Brute force patron entry correction for v21.x ====
* Developers: Christopher Brannon - Coeur d'Alene Public Library / Cooperative Information Network
* Purpose: Correct patron data entry word by word as you type. This forces consistent data entry as you type, but allows for going back to correct for unusual cases.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.x
 
 //Brute force patron entry correction (v21.05)
 //Are you in the member edit page?
 if ($('#pat_memberentrygen').length) {
 //Correct data entry
 function capitalizeWords(str) {
 var words = str.split(' ');
 if (words[words.length - 1].startsWith('Mc') || words[words.length - 1].startsWith('Mac') || words[words.length - 1].startsWith('DeA') || words[words.length - 1].startsWith('PO') || words[words.length - 1].startsWith('II') || words[words.length - 1].startsWith('III') || words[words.length - 1].startsWith('IV') || words[words.length - 1].contains("\'")) {
 return words.join(' ');
 } else {
 words[words.length - 1] = words[words.length - 1].replace(/\b[\w']+\b/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
 var newString = words.join(' ').replace(/D\'a/g,"d'A");
 return newString;
 }
 }
 function removePeriods(str) {
 return str.replace(/\./g,);
 }
 function fixAbbreviations(str) {
 var words = str.split(' ');
 words[words.length - 1] = words[words.length - 1].replace(" Av "," Ave ").replace("Avenue","Ave").replace(" Str ","St").replace("Street","St").replace("Place","Pl").replace("Circle","Cir").replace("Space","Sp").replace("Lane","Ln").replace("Drive","Dr");
 var newString = words.join(' ');
 return newString;
 }
 function makeUpperCase(str) {
 return str.toUpperCase();
 }
 function digitsOnly(str) {
 return str.replace(/[^0-9\.]/g,);
 }
 function formatPhone(str) {
 str.replace(/[^0-9\.]/g,);
 if (str.length == 3 || str.length == 7) {
 return str + '-';
 } else {
 return str;
 }
 }
 function formatPhoneNew(str) {
 if (!str) return str;
 var re = new RegExp(/[NA]/g);
 if (re.test(str)) {
 return str;
 } else {
 const phoneNumber = str.replace(/[^\d]/g, );
 const phoneNumberLength = phoneNumber.length;
 if (phoneNumberLength < 4) return phoneNumber;
 if (phoneNumberLength < 7) {
 return `${phoneNumber.slice(0,3)}-${phoneNumber.slice(3)}`;
 }
 return `${phoneNumber.slice(0,3)}-${phoneNumber.slice(3,6)}-${phoneNumber.slice(6,10)}`;
 }
 }
 //Capitalize and remove periods
 $('#surname,#firstname,#address,#city,#B_address,#B_city,#altcontactsurname,#altcontactfirstname,#altcontactaddress1').on('keyup',function() {
 $(this).val(capitalizeWords($(this).val()));
 $(this).val(removePeriods($(this).val()));
 });
 //Fix Street Abbreviations
 $('#address,#B_address,#altcontactaddress1').on('keyup',function() {
 $(this).val(fixAbbreviations($(this).val()));
 });
 //Change to all uppercase
 $('#state,#B_state,#altcontactstate').on('keyup',function(){
 $(this).val(makeUpperCase($(this).val()));
 });
 //Limit to 2 characters
 $('#state,#B_state,#altcontactstate').attr('maxlength',2);
 //Limit to 5 digits
 $('#zipcode,#B_zipcode,#altcontactzipcode').attr('maxlength',5).on('keyup',function(){
 $(this).val(digitsOnly($(this).val()));
 });
 //Format phone number
 $('#phone,#phonepro,#altcontactphone').attr('maxlength',12).on('keyup',function(){
 $(this).val(formatPhoneNew($(this).val()));
 });
 }
 //END Brute force patron entry correction (v21.05)
 
==== Hide Add Child from Patron Page ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Hide the add child button
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.12+
 
$("a#addchild.btn.btn-small").hide();
 
==== Hide Duplicate from Patron Page ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Hide the duplicate button
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.12+
 
$("a#duplicate.btn.btn-small").hide();
 
==== Hide Duplicate and Add Child from Patron Page ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Hide the duplicate and add child buttons
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10- and below
 
$("#addchild,#duplicate").closest("li").hide();
 
==== Rename Renew All Button ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Rename 'renew or return checked items' button
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10+
 
 $("input[value='Renew or return checked items']").attr("value","Renew checked items");
 $("input[value='Renew or Return checked items']").attr("value","Renew checked items");
 
==== Hide current location column in holdings table (3.10) ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Removes the Current location column in Holdings table
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10
 
$("#holdings tr td:nth-child(2)").remove();
$("#holdings tr th:nth-child(2)").remove();
 
==== Hide current location column in holdings table (3.12) ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Removes the Current location column in Holdings table
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.12+
 
$("#holdings td.location").hide(); 
$("#holdings th:contains('Current location')").hide();
 
==== Hide Topic & Places Facets ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Removes the Current location column in Holdings table
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10+
 
$("li#su-geo_id").hide();
$("li#su-to_id").hide();
 
==== Select an attribute value by default ====
* Developer: Owen Leonard & Nicole C. Engard
* Purpose: This assumes that you have a patron attribute with an authorized value and selects a default value for you
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10+
 
$("#patron_attr_1").find("option[value='VALUEHERE']").attr("selected","selected");
 
==== Select an attribute value by default only on add patron add screen ====
* Developer: Lisette Scheer
* Purpose: This assumes you have a patron attribute with an authorized value and selects a default value for you only when creating a new patron (not duplicating or adding a child)
* Status:
* Intranet or OPAC?: Intranet
* Version: 19.05+
 
if (window.location.href.inxedOf("memberentry.pl?op=add") > -1) {
$("#patron_attr_1").val("VALUEHERE");}
 
==== Interrupt check-in process for hold/transfer confirmations ====
* Developer: Christopher Brannon
* Purpose: Stop staff from overlooking a hold/transfer confirmation during the check-in process.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10+
* Note: This will interrupt the process of check-in by taking the focus away from the check-in text box if a confirmation screen appears for holds or transfers. If another book is scanned, nothing will happen. I've also colored the print button green to draw attention to the message. This is the preferred button for us. You can change the color of a different button if your workflow is different. 
 
//Check for Check-In Alerts
if ($('#return2,#hold-found1,#hold-found2,#item-transfer').length){
$("#barcode").blur();
$("input[class='print']").css({backgroundColor: 'lightgreen'});
}
//end Checking for Alerts
 
==== Passing Cardnumber/barcode through to UserID ====
* Developer: Ed Veal, ByWater Solutions
* Creation Date: 2013-10-17
* Purpose: Using Cardnumber/Barcode for UserId
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: 3.8 and 3.10 (not tested in 3.12)
 
 $("#entryform #cardnumber").blur(function(){
$("#entryform #userid").val($("#entryform #cardnumber").val());
});
 
==== Find string and add a span around it ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Add a class tag to an element without one by finding it. In this case find the string rcvd and add a around it.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10
 
$(document).ready(function(){
$('p').html(function(i,h){
return h.replace('(rcvd)', '(rcvd)');
});
});
 
==== Highlight patron's home library ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Add a class tag to an element without one by finding it. In this case find the string rcvd and add a around it.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10
 
$(document).ready(function(){
//highlight the home library on the left of the patron record in red
$('ul').html(function(i,h){
return h.replace('Home library:', 'Home library:');
});
});
 
==== Hide price column on check out summary ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: This hides the Price column found when looking at patron's checkouts
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.12
 
$("#issuest tr td:nth-child(8)").hide();
$("#issuest th:contains('Price')").hide();
$("#issuest tfoot tr td:nth-child(3)").hide();
 
==== Highlight return notice for items previously lost "Item was lost, now found" ====
* Developer: Chris Meech
* Purpose: Increase viability of returns notice for lost items -"Item was lost, now found"
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.10
 
//Highlight return notice Item was lost, now found
$(document).ready(function(){ 
$( ".problem:contains('Item was lost, now found')" ).css({"backgroundColor": "black", "color": "white", "font-size":"200%"})
 });
 
==== Hide default framework in cataloging ====
* Developer: Olugbenga Adara, Projektlink Konsult Limited
* Creation Date: 2014-03-26
* Purpose: This will hide the Default Framework options on addbiblio.pl and addbooks.pl pages
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14 (AFAIK) 
 
 $("a[href$='frameworkcode=']").hide();
 $("#Frameworks option[value=Default]").hide();
 $('li.z3950searchFw:first').hide();
 
==== Allow only a supervisor to write off a fine ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Creation Date: 2014-04-11
* Purpose: Koha 3.12 does not allow for granular control over the Write Off functions. This code mimics supervisory control by hiding the Write Off All and Write Off buttons, then requiring the input of a secret supervisor code to unhide the Write Off button.
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.12 
 
 //create the writeoffallow function
 function writeoffallow() {
 var superid = prompt('Enter your supervisor ID:');
 // use your own secret code here in place of 9999
 if (superid == '9999') {
 $('input[type="submit"][value="Write off"]').show();
 } else {
 alert('Incorrect Supervisor ID');
 }
 }
 //hide the Write Off All button
 $('#woall').hide();
 //hide the Write off button
 $('input[type="submit"][value="Write off"]').hide();
 //create the supervisor link
 $('#payselected').after(' <a id="supervisor" href="#">Supervisor</a> ');
 //assign the click handler
 $("#supervisor").click(writeoffallow);
 
==== Allow only a supervisor to lift a manual restriction ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Creation Date: 2014-04-16
* Purpose: Koha 3.14 does not allow for granular control over the new Manual Restriction functions. This code mimics supervisory control by hiding the remove links, then requiring the input of a secret supervisor code to unhide the remove links.
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14 
 
//create the superlift function
 function superlift() {
 var superid = prompt('Enter your supervisor ID:');
 // use your own secret code here in place of 9999
 if (superid == '9999') {
$('a.remove_restriction').show();
 } else {
 alert('Incorrect Supervisor ID');
 }
 }
// hide the REMOVE RESTRICTION links
$('a.remove_restriction').hide();
// create the SUPERVISOR link
$('#add_manual_restriction').after(' | <a id="supervisor2" href="#">Supervisor</a> ');
 //assign the click handler
 $("#supervisor2").click(superlift);
// hide the Patron Flags section on the Patron Edit screen because we do not use them
$('legend:contains("Patron account flags")').parent().hide();
// hide the Patron Restrictions section on the Patron Edit screen
$('legend:contains("Patron restrictions")').parent().hide();
 
==== Change default encoding to MARC-8 ====
* Developer: Nicole Engard, ByWater Solutions
* Creation Date: 2014-05-10
* Purpose: Make the default encoding when staging records Marc8 instead of UTF8
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14
 
$(document).ready(function(){
if (window.location.href.indexOf("tools/stage-marc-import.pl") > -1) {
$("#encoding option[value='utf8']").removeAttr("selected");
$("#encoding option[value='MARC-8']").attr("selected","selected");
}
 });
 
==== Focus on 'add to basket' instead of vendor search ====
* Developer: Nicole Engard, ByWater Solutions
* Creation Date: 2014-05-10
* Purpose: Move focus from search box on basket page and to the add item to basket area
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14
 
 $(document).ready(function(){
if (window.location.href.indexOf("acqui/basket.pl") > -1) {
$("input[name='supplier']").blur();
$("input[name='q']").focus();
}
 });
 
==== Focus on add to list ====
* Developer: Nicole Engard, ByWater Solutions
* Creation Date: 2014-05-10
* Purpose: Add focus lists page and to the add item to list area
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14
 
 $(document).ready(function(){
if (window.location.href.indexOf("virtualshelves/shelves.pl") > -1) {
$("input[name='addbarcode']").focus();
}
 });
 
==== Change default tab on the main page to Search ====
* Developer: Fridolin SOMERS, Biblibre and Nicole Engard, ByWater Solutions
* Creation Date: 2014-06-03
* Purpose: Makes it so that the tab fixed on the main page of the staff client is the 'search the catalog' tab.
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.16
 
$(document).ready(function(){
if (window.location.href.indexOf("cgi-bin/koha/mainpage.pl") > -1) {
$("#header_search a[href='#catalog_search']").click();
}
});
 
==== Add hotkeys to staff client ====
* Developer: Mark Lesniak, Rahway Public Library
* Creation Date: 2014-06-25
* Purpose: Adds hot keys to the staff client
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14
 
$(document).bind('keydown', function(e) {
// Shift + escape to return home (just escape in
// Google Chrome)
if(e.which === 27){
window.location.href = "http://" + document.domain; // Return to domain root
}
if(e.altKey){
switch (e.which)
{
// Alt + w = Print page
case 87:
printx_window("page");
break;
// Alt + p = Print Quickslip
case 80:
printx_window("qslip");
break;
// Alt + m = Print summary
case 77:
printx_window("slip");
break;
}
} // End alternate key
}); // End keypress bindings
 
==== Change "Available" to "Checked in or on hold" ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium
* Purpose: Changes "XX Items available" to "XX Items checked in or on hold" in the search results in the staff client in the right hand column.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.14
 
//BEGIN Change "available" in search results to "checked in/on hold"
$("#searchresults .availability strong:contains('available')").text(function () {
 return $(this).text().replace("available", "checked in or waiting on hold"); 
});
//END Change "available" in search results to "checked in/on hold"
 
==== Hide locations/copies on Staff search results ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/CIN
* Purpose: Condenses copy information so staff don't have to scroll so much through search results.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.14
 
//Condense Locations on Staff Catalog Results
$("#bookbag_form div[class='availability']").children("ul").hide();
$("#bookbag_form div[class='availability'] strong").wrap("<a class='viewLocations' />");
$("#bookbag_form div[class='availability'] strong").append(" (+) (-)");
$("#bookbag_form div[class='availability']").parent("td").attr('width','290');
//Trigger for condensed locations
$(".viewLocations").click(function() {
$(this).find(".instruct").toggle();
$(this).parent().parent().find("ul").toggle("slow");
});
//end Condense Locations
 
==== Remove links for staff to change logged in location ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/CIN
* Purpose: Reduce the ability for staff to change their circing/cataloging location easily. This will not prevent staff from changing the home location in the patron edit screen.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.14
 
//Remove library and label from login
$("#loginform label[for='branch']").hide();
$("#loginform #branch").hide();
//end Remove library from login
//Remove Set Library from Circulation page
$("#bd div[class='yui-u first'] li:contains('Set library')").hide();
//end Remove Set Library
//Remove Set Library from main page
$("#header ul[class='dropdown-menu'] li:contains('Set library')").hide();
//end Remove Set Library
 
==== Hide non-local copies when searching staff interface ====
* Developer: Nick Clemens, VOKAL
* Creation Date: 2014-03-29
* Purpose: Hides non-local copies, by logged in library, in staff search results and adds a button to show them
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.14 
 
//Add button to revert view 
$("#catalog_results #selection_ops").append('<a class="btn btn-mini" id="plain_old_results" href="#"> Brief/Full Results</a>');
$("#plain_old_results").click(function(){
 $(".availability").children("ul").toggle();
 $(".availability strong").toggle();
 $(".availability .status").toggle();
 $(".unavailable").toggle();
 return false;
});
//Show only ‘Owned by [logged in library]’ or ‘No Local Copies’ in staff search results
 var loglibnode=$(".loggedinusername").nextAll().eq(1);
 var loglibtext=$.trim(loglibnode.text());
 $(".availability").each(function(){
 var ownedlocal=false;
 var our_copy_item;
 $(this).children("ul").each(function(){
 our_copy_item=$(this).find('li:contains("'+loglibtext+'")')
 if(our_copy_item.length){
		ownedlocal=true;
 $(this).parent('.availability').after("",our_copy_item,"");
 } 
 });
 $(this).append("Click title for full availability");
 if(ownedlocal){$(this).append("Local Copies:");}
 else{$(this).prepend('No Local Copies');}
 
 });
 $(".availability").children("ul").hide();
 $(".availability strong").hide();
 $(".availability .status").hide();
 $(".unavailable").hide();
 
==== Show Local Copy Status in Staff Search Results, Hide all others (Updated for 21.11) ====
* Developer: Ryan Sipes/Heather Braum (NEKLS), Christopher Brannon (Coeur d'Alene Public Library/CIN), Nick Clemens (VOKAL), Jason Robb (SEKLS)
* Creation Date: 2022-06-08
* Purpose: Version 21.11 added a class (.results_available_count) that broke the original code. This accommodates that new class and fixes an issue where the list item was not making it inside the ul element which results in a cleaner display.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.14 - 21.11 
 //Show only 'Local copies [logged in library]' or 'No local copies'
 var libcode = $('#logged-in-info-full .logged-in-branch-name').text();
 $(".availability").each(function() {
 var ownedlocal = false;
 $(this).children("ul").hide().addClass('lctoggle');
 $(this).children("ul").each(function() {
 var local_copy_check = $(this).find('li:contains("'+libcode+'")');
 var local_copy = $(local_copy_check).wrap("").parent();
 if (local_copy.length) {
 ownedlocal = true;
 $(this).parent('.availability').append("Local Copies:").append(local_copy).removeClass('lctoggle'); 
 }
 });
 if (ownedlocal === false) {
 $(this).append("No Local Copies ");
 }
 });
 
 //Condense locations
 $("#bookbag_form .results_available_count,div[class='availability'] strong").wrap("<a class='viewLocations' />");
 $("#bookbag_form .results_available_count,div[class='availability'] strong").append(" (show all) (show local)");
 $("#bookbag_form div[class='availability']").parent("td").attr('width', '290');
 
 //Trigger to expand/condense locations
 $(".viewLocations").click(function() {
 $(this).find(".instruct").toggle();
 $(this).parent().parent().find(".lctoggle").toggle("slow");
 });
==== Fix Subject Search Links ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/CIN
* Purpose: Subject search links in records break if the subject contains parenthesis. This jquery strips the parenthesis from the url link, making the link usable again.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.14
 
//Fix subject search by striping parenthesis from url links
$('#catalogue_detail_biblio a[href*="su:"]').attr('href', function(_,v){
 return v.replace(/(\w)(\(|\))(\w)/g,'$1 $3')
}).attr('href', function(_,v){
 return v.replace(/(\(|\))/g,)
});
//End fix subject search
 
==== Enhance Expiration Date on Patron Details Screen ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/CIN
* Purpose: Helps expired or soon to be expired date stand out on the Patron Details screen. The value in line 8 (+30) should reflect the same value you have set for NotifyBorrowerDeparture preference.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.14
 
//Enhance expiration date on patron details page
$("#patron-library-details li:contains('Expiration date: ')").attr('id','patronExpiration');
var ed=new Date();
var edat=( '0' + (ed.getDate()) ).slice( -2 );
var emon=( '0' + (ed.getMonth()+1) ).slice( -2 );
var eyear=ed.getFullYear();
var todaysDate=eyear+'-'+emon+'-'+edat;
ed.setDate(ed.getDate()+30);
edat=( '0' + (ed.getDate()) ).slice( -2 );
emon=( '0' + (ed.getMonth()+1) ).slice( -2 );
eyear=ed.getFullYear();
var expireSoon=eyear+'-'+emon+'-'+edat;
ed=new Date($("#patronExpiration").text().match(/\d{2}\/\d{2}\/\d{4}/g));
edat=( '0' + (ed.getDate()) ).slice( -2 );
emon=( '0' + (ed.getMonth()+1) ).slice( -2 );
eyear=ed.getFullYear();
var expireDate=eyear+'-'+emon+'-'+edat;
if(expireDate >= todaysDate && expireDate < expireSoon){
$("#patronExpiration").attr('style','color: red;').append(' (Expires soon!)');
}
if(expireDate < todaysDate){
$("#patronExpiration").attr('style','color: red;').append(' (EXPIRED!)');
};
//End enhance expiration date
 
==== Hide Check in Column on Checkout Table ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/CIN + Kyle Hall - ByWater Solutions
* Purpose: Hides the check in column in the patron checkout Ajax table. The check in feature in this screen tends to skip hold and transfer actions, which is why we hide it. Traditional jQuery can't catch adjust this table because the table is populated after the page is loaded, so it was necessary to watch for Ajax events. Thanks to Kyle Hall for figuring out the logistics with capturing the Ajax events for me. This code also disables the forgive fines checkbox and rewords the button below the table. The first function using "ajaxSend.dt" will catch elements in the rendered table structure before the table is populated. The function using "init.dt" will catch everything else once the table is populated.
* Creation Date: 2014-10-28
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.16
 
//Hide check-in column in patron account screens
 $('#issues-table').on( 'ajaxSend.dt', function () {
 $("#issues-table th:last-child").hide();
 $("#issues-table #exemptfine").parent().hide();
 $("#RenewCheckinChecked").html(" Renew checked items");
});
$('#issues-table').on( 'init.dt', function () {
 $("#issues-table").find("tbody tr:gt(0) td:last-child").hide();
});
//end Hide check-in
 
==== Move overdue items to the top of the current checkouts table ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium
* Purpose: In Koha 3.16 the new checkouts table sorts all of the patrons items by date checked out. This means that if the patron has any overdue items, they appear at the bottom of the table and if the patron has a lot of checkouts it can take a lot of scrolling to find the overdues. This code groups any overdue checkouts at the top of the table under a big pink banner that says "Patron has overdue items." It also, thanks to some advice from Christopher Brannon at CIN, disables the column sort on the due date column since that sort does not work correctly.
* Creation Date: 2014-11-06
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.16
 
//BEGIN Move overdues to the top of the table
 $('#issues-table').on( 'init.dt', function () {
 $("#issues-table:has(.overdue)").attr('od','overduetable');
 if($("#issues-table").attr('od')) {
 $("#issues-table tbody").attr("class","checkoutbody");
 $('.checkoutbody tr:first').before('Patron has overdue items');
 $("#issues-table .overdue").parents("tr").insertAfter("#overduetr");
 };
 $("#issues-table th:first").off("click").removeClass();
 });
//END Move overdues to the top of the table
 
==== Move overdue items to the top of the current checkouts table (19.x) ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium / Christopher Brannon - Coeur d'Alene Public Library / CIN
* Creation Date: 2020-02-11
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.x
* Notes: This version builds off George's code above by highlighting the barcode in pink when there are overdues. It will also add functionality by removing the pink header and pink from the barcode, and removing the overdue message when there are no longer any overdues left.
//Enhance Overdues in Checkout Table
$('#issues-table').on( 'init.dt', function () {
	var TableWidth = $('#issues-table th:last-child').index();
	$('#issues-table').attr('rows',TableWidth);
	if ($("#issues-table span").hasClass("overdue")) {
 	$("#issues-table thead").append('Patron has overdue items');
 	$("#issues-table .overdue").parents("tr").prependTo("#issues-table tbody");
	}
 	$('#newonholdduedate').parents('td').show();
 	$('#exemptfine,label[for="exemptfine"]').hide();
});
jQuery.fn.extend({
	CheckOverdue: function() {
 if ($('#circ_circulation #circmessages span:contains("Overdues:")').is(':visible')) {
 $('#circ_circulation #barcode').css('background-color','pink');
 } else {
 $('#circ_circulation #barcode').css('background-color',);
 }
 },
 	SetOverdue: function(x) {
 		if (x == 'show') {
 	$('#circ_circulation #circmessages span:contains("Overdues:")').parent('li').show();
 	$('#circ_circulation #overduetr,#pat_moremember #overduetr').show();
 	$('#circ_circulation #barcode').css('background-color','pink');
 } else if (x == 'hide') {
 	$('#circ_circulation #circmessages span:contains("Overdues:")').parent('li').hide();
 $('#circ_circulation #overduetr,#pat_moremember #overduetr').hide();
 	$('#circ_circulation #barcode').css('background-color',);
 }
	}
});
$('#circ_circulation').CheckOverdue();
$('#circ_circulation #RenewCheckinChecked,#circ_circulation #RenewAll,#pat_moremember #RenewCheckinChecked,#pat_moremember #RenewAll').on('click', function() {
 	CheckOverdue = 0;
 	$(this).SetOverdue('hide')
	$(document).ajaxStop(function() {
 	$('span.overdue').each(function() {
 	$(this).SetOverdue('show')
 });
 	});
});
//end Enhance Overdues
==== Move overdue items to the top of the current checkouts table (20.x) ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium / Christopher Brannon - Coeur d'Alene Public Library / CIN
* Creation Date: 2021-09-02
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 20.x
* Notes: This version modifies the 19.x version by dressing up the header more and adding bootstrap labels to each overdue line.
 //Overdue badges for circulation.pl and moremember.pl
 $('#issues-table').on( 'init.dt', function () {
 $('#circ_circulation span.overdue,#pat_moremember span.overdue').prepend('OVERDUE');
 });
 //END Overdue badge for circulation.pl and moremember.pl
 
 //Enhance Overdues in Checkout Table
 $('#issues-table').on( 'init.dt', function () {
 $('#issues-table').attr('rows','14');
 if ($("#issues-table span").hasClass("overdue")) {
 $("#issues-table thead").append(' Patron has overdue items ');
 $("#issues-table .overdue").parents("tr").prependTo("#issues-table tbody");
 }
 $('#newonholdduedate').parents('td').show();
 $('#exemptfine,label[for="exemptfine"]').hide();
 });
 jQuery.fn.extend({
	CheckOverdue: function() {
 if ($('#circ_circulation #circmessages span:contains("Overdues:")').is(':visible')) {
 $('#circ_circulation #barcode').css('background-color','pink');
 } else {
 $('#circ_circulation #barcode').css('background-color',);
 }
 },
 	SetOverdue: function(x) {
 	 if (x == 'show') {
 	$('#circ_circulation #circmessages span:contains("Overdues:")').parent('li').show();
 	$('#circ_circulation #overduetr,#pat_moremember #overduetr').show();
 	$('#circ_circulation #barcode').css('background-color','pink');
 } else if (x == 'hide') {
 $('#circ_circulation #circmessages span:contains("Overdues:")').parent('li').hide();
 $('#circ_circulation #overduetr,#pat_moremember #overduetr').hide();
 	$('#circ_circulation #barcode').css('background-color',);
 }
	}
 });
 $('#circ_circulation').CheckOverdue();
 $('#circ_circulation #RenewCheckinChecked,#circ_circulation #RenewAll,#pat_moremember #RenewCheckinChecked,#pat_moremember #RenewAll').on('click', function() {
 	CheckOverdue = 0;
 	$(this).SetOverdue('hide');
	$(document).ajaxStop(function() {
 $('span.overdue').each(function() {
 	$(this).SetOverdue('show');
 });
 	});
 });
 $('#circ_circulation #duedatespec').on('blur', function() {
 $('#circ_circulation #barcode').focus();
 });
 //end Enhance Overdues
==== Move filter bar to the top of the "Saved reports" table ====
* Developer: George H. Williams - Latah County Library District / VALNet library consortium
* Purpose: Moves the filter bar from the bottom of the "Saved reports" table to the top of that table.
* Creation Date: 2014-11-04
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.16
 
//BEGIN Move reports filter tool to top of reports table
 $(window).bind("load", function() {
 $("#table_reports_wrapper .bottom.pager").insertBefore("#table_reports");
 });
//END Move reports filter tool to top of reports table
 
==== Relabel state to be Province ====
* Developer: Nicole Engard
* Purpose: Relabel state to be Province
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
$(document).ready(function(){
 $("#memberentry_mainaddress label[for='state']").html("Province:");
 $("#table_cities th:contains('State')").html("Province");
 $("label[for='city_state']").html("Province:");
});
 
==== Hide sort fields from patron screen ====
* Developer: David Roberts (PTFS Europe)
* Creation Date: 2015-02-05
* Purpose: Hide sort 1 and sort 2 fields from patron registration
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.18 
 
$("#memberentry_library_management label[for='sort1']").hide();
$("#memberentry_library_management label[for='sort2']").hide();
$("#memberentry_library_management #sort1").hide();
$("#memberentry_library_management #sort2").hide();
 
==== MARC21 documentation links while adding an authority ====
* Developer: Stefano Bargioni
* Creation Date: 2013-12-06
* Purpose: Show MARC21 documentation links while adding an authority
* Status: Complete. Will become unuseful when Bug 10941 will be pushed to master.
* Intranet or OPAC?: Intranet
* Version: 3.18 
* Adaptations to other languages: Spanish.
if (location.pathname.indexOf('authorities/authorities.pl')>-1) {
	var tags = $('div[id^=div_indicator_tag_]');
	for (var i=0; i < tags.length; i++) {
		var t = $(tags[i]);
		var tag_name = t.attr('id').replace(/div_indicator_tag_/,).substr(0,3);
		t.find('span:first').after('<a href="#" class="marcdocs" title="LC MARC auth specifications" onclick="MARC21FieldAuth(\+tag_name+'\'); return false"> ?</a>');
	}
	$('.marcdocs').css({'color':'blue','font-weight':'bold'});
}
function MARC21FieldAuth(tag_name) {
 if (tag_name == '000') {
 window.open("http://www.loc.gov/marc/authority/adleader.html");
 }
 else if (tag_name.search('09') == 0) {
 window.open("http://www.loc.gov/marc/authority/ad09x.html");
 }
 else {
 window.open("http://www.loc.gov/marc/authority/ad"+("000"+tag_name).slice(-3) + ".html");
 }
}
==== Add search by biblionumber option to staff client search drop-down ====
* Developer: Indranil Das Gupta, L2C2 Technologies. (based on "Add additional searches to OPAC" by Jared Camins-Esakov)
* Purpose: To append a search by biblionumber option to the search options drop-down on staff client search page.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
$(document).ready(function(){
 $("select[name='idx']").append("<option value='biblionumber'>Biblionumber</option>");
});
 
==== Hides Auto renew option ====
* Developer: Ed Veal
* Purpose: Hides the “Auto renew” option from the checkout screen
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: tested 3.18 
 
// Hides the Auto-renew feature 
$(document).ready(function(){ 
$("div.date-select label[for='auto_renew']").remove();
$("div.date-select input[id='auto_renew']").remove(); 
}); 
==== Show cost of checkouts on print slips ====
* Developer: Kyle M Hall
* Purpose: Shows what it would have cost to purchase all the items checked out today, based on the items.price field. This should work in the regular checkouts slip and also the quick slip.
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: tested 3.18 
First, add this to your checkedout block on your slip:
<<items.price>>
items.replacementprice could also be used instead of items.price
Next, add this somewhere on the slip:
Cost of buying these items:
$
Cost of using the library:
Priceless!
Lastly, add this to the bottom of your slip:
<script type="text/javascript">
var x = document.getElementsByClassName("price");
var i;
var total = 0;
for (i = 0; i < x.length; i++) {
 var cost = parseFloat( x[i].innerHTML );
 if ( ! isNaN( cost ) ) {
 total += cost;
 }
}
document.getElementById("price").innerHTML = total.toFixed(2);
</script>
==== Show only last four digits of cardnumber on slip ====
* Developer: Kyle M Hall
* Purpose: Replace all but the last four digits of a cardnumber with asterisks on a print slip
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: tested 3.20
First, add this to your slip:
Cardnumber: <<borrowers.cardnumber>>
Next, add this to the bottom of the slip:
<script type="text/javascript">
var cardnumber = document.getElementById("cardnumber");
var inner_html = cardnumber.innerHTML;
var length = inner_html.length - 4;
var last_four = inner_html.substring( length );
var stars = Array(length).join("*")
cardnumber.innerHTML = stars + last_four;
</script>
==== Copy Input to All Textboxes in Header Search ====
* Developer: Christopher Brannon
* Purpose: Copy your input in the header search to all four search boxes so you dont have to start over if you find you are on the wrong tab
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: tested 3.18 
//Copy Header Search Input Box
 $('#header_search input:not(.submit)').keyup(function() {
 var txtClone = $(this).val();
 $('#header_search #findborrower,#header_search #ret_barcode,#header_search #searchmember,#header_search #search-form').val(txtClone);
 });
//End copy
==== Enhance No item with barcode message ====
* Developer: Christopher Brannon - Coeur dAlene Public Library - Cooperative Information Network
* Creation Date: 2016-03-01
* Purpose: Make messages alerting staff that item/barcode is not found stand out from other alerts
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: tested 3.18
 
 //Enhance No item with barcode message
$("p.problem:contains('No item with barcode:')").parent("div").removeClass("alert").css("background-color","red").css("border","1px solid #e0c726").css("background","rgba(0, 0, 0, 0) -moz-linear-gradient(center top , #FAECEC 0%, #FAECEC 9%, #FC1B1B 89%, #FA2A2A 100%) repeat scroll 0 0");
 //End Enhance
 
==== Copy mobile phone to SMS field ====
* Developer: Nicole Engard ByWater Solutions
* Creation Date: 2016-03-29
* Purpose: Take the contents of the mobile phone field and populate the SMS field with a +1 and the number
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.22
 
//Add the +1 to the SMS number field and SMS to fill in with Mobile
if ($("#memberentry_messaging_prefs input[id='SMSnumber']").val() == ) {
$("#entryform #mobile").blur(function(){
	$("#memberentry_messaging_prefs input[id='SMSnumber']").val("+1"+$("#entryform #mobile").val());
});
 }
 
==== Add a check/uncheck all libraries button to export.pl ====
* Developer: Nick Clemens. ByWater Solutions
* Creation Date: 2016-04-15
* Purpose: Add a button to allow for checking/unchecking all libraries on the export tool
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 
 
$("#tools_export label:contains('Library:')").append("<button id='libcheck' type='button'>Uncheck all</button>");
$("#libcheck").click( function() {
 if( $(this).text() == "Check all" ) {
 $(".branchgriditem input").prop('checked',true);
 $(this).text('Uncheck all');
 }
 else {
$(".branchgriditem input").prop('checked',false);
 $(this).text('Check all'); 
}
 
==== Fill in default values for indicators and hide them from catalographers ====
* Developer: Joachim Ganseman. Koninklijk Conservatorium Brussel
* Creation Date: 2016-06-23
* Purpose: Speed up catalography by automatically filling in indicators for fields where they are always the same.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 16.05
 
if ( $("#cat_addbiblio") ) {	// only do this in the addbiblio form
 // Fill in default values for some indicators
 $("input[name^='tag_028_indicator1']").val("2"); // Field 028 : Default to plate nr
 $("input[name^='tag_028_indicator2']").val("0");
 $("input[name^='tag_100_indicator1']").val("1"); // Field 100 : Default to Family Name
 $("input[name^='tag_490_indicator1']").val("0"); // Field 490 : Default to untraced series
 $("input[name^='tag_542_indicator1']").val("1"); // Field 542 : Default to publicly available info
 $("input[name^='tag_650_indicator1']").val("0"); // Field 650 : Default to "undefined level, no thesaurus"
 $("input[name^='tag_650_indicator2']").val("4");	
 $("input[name^='tag_700_indicator1']").val("1"); // Field 700 : Default to Family Name
 // Now hide all indicator elements in the input form from the user. 
 $("input[class~='indicator']").hide();
}; // end if
 
==== Check validity of ISBN, ISSN, ISMN and URL before submitting the addbiblio form ====
* Developer: Joachim Ganseman. Koninklijk Conservatorium Brussel
* Creation Date: 2016-06-23
* Purpose: Avoid incorrect numbers or URLs to be added to the database.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 16.05
 
if ( $("#cat_addbiblio") )	// only do this in the addbiblio form
{
 // add an additional event handler to the save buttons ( one already exists: .onOption() ) 
 $("#saverecord, #saveandview, #saveanditems, #saveandcontinue").click( function( event ) {
 var mes = "";
 // run all tests as functions which might add a new error message to the existing ones
 mes = test020a( mes ); 
 mes = test022a( mes );
 mes = test024a( mes );
 mes = test856a( mes );
 if (mes != "") {
 alert(mes);
 event.stopImmediatePropagation();	// block the other event handlers which trigger submission of the form
 return false;
 } else {
 return true;
 }
 });
}; // end if in addbiblio form
/* Helper function to test whether ISBN is correctly prefixed 10- or 13-digit. Does not calculate checksum. */
// regex adapted from http://regexlib.com/REDetails.aspx?regexp_id=1640
var test020a = function( mes ) {
 var ISBNregex = /^(97(8|9))?\d{9}(\d|X)$/;
 $("[id^='tag_020_subfield_a']").each( function() { // loop over all ISBN fields
 var value = $(this).val();
 if (!value || value == "") { return true; }; // 'continue' statement
 if (!ISBNregex.test(value)) {
 $(this).addClass("subfield_not_filled"); // color the background of this field
 mes += "Field 020$a: Invalid ISBN format! Please correct, or put it in subfield $z.\n";
 } else {
 $(this).removeClass("subfield_not_filled"); // reset background of this field
 }
 });
 return mes;
};
/* Helper function to test whether ISSN is formatted as '1234-5678' */ 
var test022a = function( mes ) {
 var ISSNregex = /^\d{4}-\d{3}(\d|X)$/;
 $("[id^='tag_022_subfield_a']").each( function() { // loop over all ISSN fields
 var value = $(this).val();
 if (!value || value == "") { return true; }; // 'continue' statement
 if (!ISSNregex.test(value)) {
 $(this).addClass("subfield_not_filled");
 mes += "Field 022$a: Invalid ISSN format! Please correct, or put it in subfield $y.\n";
 } else {
 $(this).removeClass("subfield_not_filled");
 }
 });
 return mes;
};
 
/* Helper function to test whether ISMN is properly formatted */
// note: this assumes field 024 is only used for ISMN and not for any other std number. 
var test024a = function( mes ) {
 var ISMNregex = /^((9790)|M)\d{9}$/;
 $("[id^='tag_024_subfield_a']").each( function() { // loop over all ISMN fields
 var value = $(this).val();
 if (!value || value == "") { return true; }; // 'continue' statement
 if (!ISMNregex.test(value)) {
 $(this).addClass("subfield_not_filled");
 mes += "Field 024$a: Invalid ISMN format! Please correct, or put it in subfield $z.\n";
 } else {
 $(this).removeClass("subfield_not_filled");
 }
 });
 return mes;
}; 
 
/* Helper function for formatting of URLs (currently only supporting https, http, ftp) */
// Regex adapted from http://regexlib.com/REDetails.aspx?regexp_id=1048 
var test856u = function( mes ) {
 var uriRegex = /^(((ht|f)tp(s?))\:\/\/)?((([a-zA-Z0-9_\-]{1,}\.)+[a-zA-Z]{2,})|((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(\?(\.?\d)\.)){4}))(:[a-zA-Z0-9]+)?(\/[a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~]*)?$/;
 $("[id^='tag_856_subfield_u']").each ( function() {
 var value = $(this).val();
 if (!value || value == "") { return true; }; // continue statement
 if (!uriRegex.test(value)) {
 $(this).addClass("subfield_not_filled");
 mes += "Field 856$u: Invalid URL. \n";
 } else {
 $(this).removeClass("subfield_not_filled");
 }
 });
 return mes;
}; 
 
 
==== Pass data from the addbiblio to the additem form ====
* Developer: Joachim Ganseman. Koninklijk Conservatorium Brussel
* Creation Date: 2016-06-23
* Purpose: Speed up catalography by automatically filling fields of the additem form with data from the addbiblio form.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 16.05
 
if ( $("#cat_addbiblio") ) { // only do this in the addbiblio form
 // add an additional event handler to the save buttons: when saved, store data in browser. 
 $("#saverecord, #saveandview, #saveanditems, #saveandcontinue").click( function( event ) {
 // copy values that need to be available in additem.pl to HTML5 sessionStorage (no need for cookies)
 sessionStorage.setItem( "current_callnumber", $("[id^='tag_001_subfield_00']").val() ); // our callnumber is recorded in 001
 sessionStorage.setItem( "current_accessrestriction", $("[id^='tag_506_subfield_a']").val() ); // our accessrestriction is recorded in 506
 sessionStorage.setItem( "current_status", $("[id^='tag_583_subfield_l']").val() ); // our lost status is recorded in 583
 return true;
 }
}; // end if in the addbiblio form
if ( $("#cat_additem") ) { // only do this in the additem form.
 // pre-fill the 952$1 "lost status". In Koha default settings, this is encoded as "1" in subfield 1.
 $("[id^='tag_952_subfield_1']").val( (sessionStorage.getItem("current_status") == "LOST") ? "1" : "" );
 // pre-fill the 952$7 "not for loan status". In Koha default settings, this is encoded as "1" in subfield 7.
 $("[id^='tag_952_subfield_7']").val( (sessionStorage.getItem("current_accessrestriction") != "") ? "1" : "" );
 // pre-fill the 952$o "full call number" field.
 $("[id^='tag_952_subfield_o']").val( sessionStorage.getItem("current_callnumber") );
}; // end if in the additem form
 
==== Copy data entered in one field to another ====
* Developer: Joachim Ganseman. Koninklijk Conservatorium Brussel
* Creation Date: 2016-06-23
* Purpose: Speed up catalography by automatically filling in duplicated fields.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 16.05
 
// Example: in addbiblio form, copy data from field 001, once entered, into field 590$a
$("[id^='tag_001_subfield_00']").blur( function() {
 $("[id^='tag_590_subfield_a']").val( $("[id^='tag_001_subfield_00']").val() );
});
 
==== Autofill catalographer information in the addbiblio form ====
* Developer: Joachim Ganseman. Koninklijk Conservatorium Brussel
* Creation Date: 2016-06-23
* Purpose: Automatically add data that records who did the catalography to a bibliographic record.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 16.05
 
if ( $("#cat_addbiblio") ) { // only do this in the addbiblio form
 // put string "Catalography:" in field 583$a
 $("[id^='tag_583_subfield_a']").val("Catalography:");
 // copy login of the current user to field 583$k 
 $("[id^='tag_583_subfield_k']").val( $(".loggedinusername").text() );
 // if not yet set, copy current date in yyyymmdd format to field 583$c
 var yyyymmdd = (new Date()).toISOString().slice(0,10).replace(/-/g,""); // note: this is the GMT date!
 var currentdate = $("[id^='tag_583_subfield_c']").val();
 if (!currentdate || currentdate == "") 
 {
 $("[id^='tag_583_subfield_c']").val(yyyymmdd);
 }
}; // end if addbiblio
 
==== Remove "Pay selected" button from "Pay fines" tab in Fines module ====
* Developer: George H. Williams - Northeast Kansas Library System
* Purpose: Removes the "Pay selected" button - There is a bug in 3.22 (see https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=15397) that is causing fee payment problems with the "Pay selected" button. This jQuery should remove that button until the bug can be fixed which should prevent new problems from being created
* Creation Date: 2016.07.18
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.22
 
//BEGIN Hides "Pay selected" button on the Pay fines tab in the Fines module
 $('#payselected').hide();
//END
 
==== Change where the patron link on returns.pl points ====
* Developer: Jason Robb (SEKLS)
* Purpose: In the table generated by check-ins on returns.pl, the patron link directs to the moremember.pl for the patron. This code causes that link to instead point to circulation.pl for the patron.
* Creation Date: 8/11/2016
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.22
 
var0 = $('body').is("#circ_returns");
if(var0 !=0) {
$('a').each(function() {
 this.href = this.href.replace('members/moremember.pl', 'circ/circulation.pl');
		}
	)}
 
==== Hide fields on add/edit items page based on field label====
* Developer: Jason Robb (SEKLS)
* Purpose: Hides fields on the add/edit items screen (additem.pl). Streamlines workflow and prevents data from being entered into the wrong field.
* Creation Date: 8/11/2016
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 3.22
* Note: Some fields are hidden by default via the frameworks. I still included those in this as removing them in this manner also removes the extra space their absence creates which makes the screen look cleaner.
 
var0 = $('body').is("#cat_additem");
if(var0 !=0) {
 $('span:contains("Source of classification or shelving scheme")').parent().parent().parent().hide();
 $('span:contains("Materials specified (bound volume or other part)")').parent().parent().parent().hide();
 $('span:contains("Use restrictions")').parent().parent().parent().hide();
 $('span:contains("Uniform Resource Identifier")').parent().parent().parent().hide();
 $('span:contains("Price effective from")').parent().parent().parent().hide();
 $('span:contains("Price effective from")').parent().parent().parent().hide();
 $('span:contains("Price effective from")').parent().parent().parent().hide();
 $('span:contains("Inventory number")').parent().parent().parent().hide();
 $('span:contains("Shelving control number")').parent().parent().parent().hide();
 $('span:contains("Date last checked out")').parent().parent().parent().hide();
 $('span:contains("Total Checkouts")').parent().parent().parent().hide();
 $('span:contains("Total Renewals")').parent().parent().parent().hide();
 $('span:contains("Total Holds")').parent().parent().parent().hide();
 $('span:contains("Checked out")').parent().parent().parent().hide();
 $('span:contains("Date last seen")').parent().parent().parent().hide();
 $('span:contains("Coded location qualifier")').parent().parent().parent().hide();
 }
 
==== Add clear and preset permission buttons to user permissions page (v16.x) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds permission clear and preset buttons to user permissions page.
* Creation Date: 2/21/2017
* Updated: 11/07/2019
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 16.x
 
//Permissions Quick Set
$('#pat_member-flags #permissionstree').before('<button id="cleartree" type="button" style="font-size:12px; margin-left:5px;"> Clear All Flags</button><button id="setcirc" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Circ</button><button id="setmanager" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Manager</button><button id="copypref" type="button" style="font-size:12px; margin-left:5px;"> Copy to (borrower #): </button> <input type="text" id="copypref_bor">');
$( "#cleartree" ).click(function() {
 $('#pat_member-flags input[name="flag"]').removeAttr('checked');
 $('#pat_member-flags li.collapsable').find('div').click();
});
$( "#setcirc" ).click(function() {
 $('#pat_member-flags input[name="flag"]').removeAttr('checked').removeAttr('disabled');
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #reserveforothers_place_holds, #flag-10, #reports_execute_reports').each(function() {
	$(this).click();
 $(this).closest('li.expandable').find('div').click();
 });
});
$( "#setmanager" ).click(function() {
 $('#pat_member-flags input[name="flag"]').removeAttr('checked').removeAttr('disabled');
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #flag-6, #flag-9, #flag-10, #tools_inventory, #tools_items_batchmod, #reports_execute_reports').each(function() {
	$(this).click();
 $(this).closest('li.expandable').find('div').click();
 });
});
//End Permissions Quick Set
 
==== Add clear and preset permission buttons to user permissions page (v19.x) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds permission clear and preset buttons to user permissions page.
* Creation Date: 10/17/2019
* Updated: 11/07/2019
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.x
 
//Permissions Quick Set
$('#pat_member-flags #permissionstree div.permissions').before('<button id="cleartree" type="button" style="font-size:12px; margin-left:5px;"> Clear All Flags</button><button id="setcirc" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Circ</button><button id="setmanager" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Manager</button>');
$( "#cleartree" ).click(function() {
 $('#pat_member-flags input[name="flag"]').removeAttr('checked');
 $('#pat_member-flags').find('a.togglechildren_off:visible').click();
});
$( "#setcirc" ).click(function() {
 $('#pat_member-flags input[name="flag"]').removeAttr('checked').removeAttr('disabled');
 $('#pat_member-flags').find('a.togglechildren_off:visible').click();
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #reserveforothers_place_holds, #flag-10, #reports_execute_reports').each(function() {
	$(this).click();
 $(this).closest('div.parent').find('a.togglechildren_on:visible').click();
 });
});
$( "#setmanager" ).click(function() {
 $('#pat_member-flags input[name="flag"]').removeAttr('checked').removeAttr('disabled');
 $('#pat_member-flags').find('a.togglechildren_off:visible').click();
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #flag-6, #flag-9, #flag-10, #tools_inventory, #tools_items_batchmod, #reports_execute_reports').each(function() {
	$(this).click();
 $(this).closest('div.parent').find('a.togglechildren_on:visible').click();
 });
});
//End Permissions Quick Set
 
==== Add clear and preset permission buttons, and a copy button to user permissions page (v20.x) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds permission clear and preset buttons to user permissions page, plus a button to copy current permissions to another borrower via cardnumber.
* Instructions: Requires a public report (see below). report?id= must be updated with your report number.
* Creation Date: 04/17/2019
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 23.05
* Updated: 01/25/2024
* Update Notes: Updated target selection on save button for the copy and save permissions function. Class was changed on button after 23.05. Removed redundant clear permissions button as there is a link that does the same thing. Switched to api to grab borrowernumber rather than depending on a report. CB
 
 //Permissions Quick Set (v23.05)
 //Create Buttons
 $('#pat_member-flags #permissionstree div.permissions').before('<button id="setcircsingle" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Circ (Single Account)</button><button id="setcircshared" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Circ (Shared Account)</button><button id="setmanager" type="button" style="font-size:12px; margin-left:5px;"> Set Basic Manager</button><button id="copypref" type="button" style="font-size:12px; margin-left:5px;"> Copy Permissions to...</button>');
 //Basic Circ Button Settings (Single Account)
 $( "#setcircsingle" ).click(function() {
 $( "#cleartree" ).click();
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #reserveforothers_place_holds, #flag-10, #suggestions_suggestions_manage, #tools_batch_upload_patron_images, #reports_execute_reports, #flag-17, #clubs_enroll, #cash_management_cashup, #cash_management_takepayment').each(function() {
	 $(this).click();
 $(this).closest('div.parent').find('a.togglechildren_on:visible').click();
 });
 });
 //Basic Circ Button Settings (Shared Account)
 $( "#setcircshared" ).click(function() {
 $( "#cleartree" ).click();
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #reserveforothers_place_holds, #flag-10, #suggestions_suggestions_manage, #tools_batch_upload_patron_images, #reports_execute_reports, #clubs_enroll, #cash_management_takepayment').each(function() {
	 $(this).click();
 $(this).closest('div.parent').find('a.togglechildren_on:visible').click();
 });
 });
 //Basic Manager Button Settings
 $( "#setmanager" ).click(function() {
 $( "#cleartree" ).click();
 $('#pat_member-flags').find('#circulate_circulate_remaining_permissions, #circulate_force_checkout, #circulate_manage_restrictions, #flag-2, #flag-4, #flag-6, #flag-9, #flag-10, #suggestions_suggestions_manage, #tools_batch_upload_patron_images, #tools_inventory, #tools_items_batchmod, #reports_execute_reports, #flag-17, #clubs_enroll, #cash_management_cashup, #cash_management_takepayment').each(function() {
	 $(this).click();
 $(this).closest('div.parent').find('a.togglechildren_on:visible').click();
 });
 });
 //Copy Permissions Button Modal and Settings
 $('#pat_member-flags').append('<form method="post" action="submit"><input type="hidden" name="" value="">Copy Permissions<label for="infoCardNumber">Card Number (Target User): </label><input id="infoCardNumber" type="text" size="10"><button id="btnCopySave" type="button" class="btn btn-default" style="background-image: none; background-color: rgb(105, 162, 104);"> Copy & Save Permissions</button><button id="btnCopyCancel" data-dismiss="modal" aria-hidden="true" class="btn"> Cancel</button> <!-- /.modal-footer --></form> <!-- /.confirm --> <!-- /.modal-content --> <!-- /.modal-dialog -->');
 //Copy and Save if Enter is pressed
 $('#CopyPermissionsModal').keypress(function(e){
 if(e.keyCode==13) {
 $('#btnCopySave').click();
 return false;
 }
 });
 //Open Modal
 $('#pat_member-flags #copypref').on('click', function() {
 $('#CopyPermissionsModal').modal('show');
 $('#CopyPermissionsModal').on('shown.bs.modal', function () {
 $('#infoCardNumber').focus();
 });
 });
 //Change Borrower Number and Save
 $('#pat_member-flags #btnCopySave').on('click', function () {
 //Get patron data
 var usrCardNumber = $('#infoCardNumber').val();
 var usrBorrowerNumber;
 var url = '/api/v1/patrons?cardnumber=' + usrCardNumber;
	$.ajax({
	 async: false,
	 url: url,
	 success: function(data) {
	 usrBorrowerNumber = [data[0].patron_id];
	 }
	});
 $('#pat_member-flags #borrowernumber').val(usrBorrowerNumber);
 $('#btnCopyCancel').click();
 $('#pat_member-flags #permissions_toolbar button[type="submit"]').click();
 });
 //Create alert to display after permissions are copied.
 $('#pat_moremember #patron-id').after(' Permissions copied to new user.');
 //Display alert next to patron info showing permissions have been copied.
 $('#pat_moremember').each(function() {
 var referrer = document.referrer;
 var URLParams = new URLSearchParams(window.location.search);
 var URLBorrower = URLParams.get('borrowernumber');
 var referrerBorrower = referrer.split("=").pop(); 
 if ((referrer.indexOf("member-flags.pl") >= 0) && (URLBorrower != referrerBorrower)) {
 $('#PermissionsUpdate').fadeIn().delay(3000).fadeOut();
 }
 });
 //END Permissions Quick Set
 
==== Create button to hide left hand navigation menu on the circulation rules page ====
* Developer: George Williams (NExpress)
* Purpose: Becasue the circulation rules table is 7 miles wide, it can be hard to follow which line you're looking at from one end of the table to the other. This jQuery creates a button to hide left hand navigation menu on the circulaiton and fine rules page so that if you don't need that menu you can fit more of the rules table on one screen.
* Creation Date: 3/30/2017
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: developed on 3.22.08 - Broken on 21.05
 //BEGIN Create button to hide left hand navigation bar
 $("#admin_smart-rules #navmenu").parent().prepend("<button id='navhide' type='button'>Hide admin column</button>");
 $("#navhide").click( function() {
 $("#navhide").hide();
 $("#navmenu").hide();
 $(".yui-t1 #yui-main .yui-b").css("margin-left", "1em"); 
 });
 //END
==== Move rows in the circulaiton and fine rules table to move it to the bottom with click ====
* Developer: George Williams (NExpress)
* Purpose: Becasue the circulation rules table is 7 miles wide, it can be hard to follow which line you're looking at from one end of the table to the other. This jQuery moves any row of the rules table to the bottom of the table in order to make it easier to for your eyes to track across the screen.
* Creation Date: 3/30/2017
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 3.22.08 - Tested and confirmed as working on 21.05
 //BEGIN Click on circ rule to move it to the bottom of the table
 $("#default-circulation-rules tr:contains(Edit)").click(function() {
 $(this).insertBefore("#edit_row");
 });
 //END
==== Add drop down to filter circulation and fine rules table ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Creation Date: 2019-05-03
* Purpose: Filters the Circulation and Fine Rules table by patron category so that it is easier to read.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
 
 //Add the drop down with the patron category values
 $("div.help").after("<label>Filter by Patron Category: <select id='rulesSearch'><option value='All Patron Categories'>All Patron Categories</option><option value='Patron Category 1'>Patron Category 1</option><option value='Patron Category 2'>Patron Category 2</option></select></label>");
 //Triggered when a value is selected in the drop down
 $("#rulesSearch").change(function(){
 var optselect = $("#rulesSearch").val(); //Creates a variable from the value of the option chosen in drop down
 $("#default-circulation-rules tbody tr").hide(); //Hides all rows in the table
 $("#default-circulation-rules tbody tr:contains("+optselect+")").show(); //Shows the rows that contain the chosen value
 if(optselect == "All Patron Categories"){$("#default-circulation-rules tbody tr").show();} //Shows all rows if 'All Patron Categories' is selected
 });
 
==== Autofill "Hold expires on" date when placing a request in the staff client ====
* Developer: George Williams (NExpress)
* Purpose: Autofills the "Hold expires on date" with the date 1 year from today when placing a request from the staff client. There is a corresponding piece of jQuery for the OPAC in the OPAC section. The future date can be modified by changing the values in the day, month, and year variables.
* Creation Date: 3/30/2017
* Status: Completed - Can cause errors around Leap Day when jQuery calculates a nonexistent date (like 2/29/20201)
* Intranet or OPAC?: Intranet
* Version: Developed on 3.16
* Koha breadcrumbs: Catalog › TITLENAME › Place a hold on TITLENAME
//BEGIN Set newly placed holds in staff client to expire after one year if not filled
 var holdtodate = new Date();
 var day = ("0" + holdtodate.getDate()).slice(-2);
 var month = ("0" + (holdtodate.getMonth() + 1)).slice(-2);
 var year = ("0" + (holdtodate.getFullYear() + 1)).slice(-4);
 var holdtill = (month) + "/" + (day) + "/" + (year);
 $('#hold-request-form .holddateto').val(holdtill);
//END
==== Autofill "Hold expires on" date when placing a request in the staff client ====
* Developer: Lucas Gass (Bywater Solutions)
* Purpose: Autofills the "Hold expires on date" with the date 1 year from today when placing a request from the staff client. There is a corresponding piece of jQuery for the OPAC in the OPAC section. The future date can be modified by changing the values in the day, month, and year variables.
* Creation Date: 8/25/20
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.11
//BEGIN Set newly placed holds in staff client to expire after one year if not filled
$(document).ready(function() {
 if ( $('#circ_request').length ) {
 $.getScript( "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" )
 .done(function( script, textStatus ) {
 $('#hold-request-form #to').val( moment().add(1, 'years').calendar() );
 })
 .fail(function( jqxhr, settings, exception ) {
 console.log( 'Could not load MomentJS' );
 });
 }
});
//END
==== Force staff to select SMS provider and enter SMS number before checkboxes can be checked ====
* Developer: George Williams (NExpress)
* Purpose: There is a bug in Koha 16.11 that breaks patron messaging if SMS checkboxes are checked but no SMS provider is selected. This jQuery attempts to fix this by 1) disabling the checkboxes and SMS number entry if no provider is selected 2) clearing the SMS number and all SMS checkboxes if the provider is removed 3) forcing the SMS number to 10 numeric characters with no punctuation or spaces 4) moving the SMS provider and SMS number above the messaging preferences table so it is more intuitive for staff to enter that information first 5) and finally renaming the SMS labels from "SMS" to "Text message" because many staff at our libraries don't know what SMS means. There is corresponding jQuery for the OPAC below
* Creation Date: 4/10/2017
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 16.11.05
* Koha breadcrumbs: Home › Patrons › Add patron
* Koha breadcrumbs: Home › Patrons › PATRONNAME › Modify patron
//BEGIN SMS changes in the staff client
 //BEGIN Hides SMS number and all SMS checkboxes when page is loaded
 $("#SMSnumber").parent().hide();
 $("#sms1, #sms2, #sms4, #sms5, #sms6").attr("disabled","disabled");
 //BEGIN Show SMS number if provider is not null and clear number and all SMS checkboxes if the provider is changed to null
 $("body").on("mousemove change click keyup", function(){
 if($("#sms_provider_id").val() != ""){
 $("#SMSnumber").parent().show("slow");
 } else {
 $("#SMSnumber").parent().hide("slow");
 $("#SMSnumber").val("");
 $("#smsbuttons").hide();
 $("#sms1, #sms2, #sms4, #sms5, #sms6").attr("disabled", "disabled");
 $("#sms1, #sms2, #sms4, #sms5, #sms6").prop("checked", false);
 }
 });
 //BEGIN Enable SMS checkboxes only if SMS number is 10 digits and force SMS number entry to numerals only - no punctuation, alphanumeric characters, or spaces
 $("#SMSnumber").attr('maxlength','10');
 $('#SMSnumber').keydown(function (e) {
 if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
 (e.keyCode == 65 && e.ctrlKey === true) ||
 (e.keyCode >= 35 && e.keyCode <= 40)) {
 return;
 }
 if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
 e.preventDefault();
 }
 });
 $("body").on("mousemove change click keyup", function(){
 if($("#SMSnumber").val().length == 10){
 $("#sms1, #sms2, #sms4, #sms5, #sms6").removeAttr("disabled");
 $("#smsbuttons").show("slow");
 } else {
 $("#sms1, #sms2, #sms4, #sms5, #sms6").attr("disabled", "disabled");
 $("#sms1, #sms2, #sms4, #sms5, #sms6").prop("checked", false);
 $("#smsbuttons").hide("slow");
 }
 });
 //BEGIN Move SMS stuff above the table so that the first fields that need to be filled out are the first ones that staff see
 $("#memberentry_messaging_prefs > table").wrap('');
 $("#memberentry_messaging_prefs label:contains('SMS number:')").parent().wrap('');
 $("#memberentry_messaging_prefs label:contains('SMS provider:')").parent().wrap('');
 $("#smsnumbermove").prependTo("#messagetable").parent();
 $("#smsprovidermove").prependTo("#messagetable").parent();
 //BEGIN Rename SMS "Text messaging" for the sake of staff who don't know what SMS stands for
 $('#memberentry_messaging_prefs label, #memberentry_messaging_prefs th').each(function() {
 var text = $(this).text();
 $(this).text(text.replace('SMS', 'Text message')); 
 });
	
==== Allow to reorder automatic item modification by age rules ====
* Developer: Kidclamp
* Purpose: Reorder (move up) item modification rules
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
$( document ).ready(function() {
 $("#tools_automatic_item_modification_by_age #rules fieldset legend").each(function(){ 
 $(this).prepend('<a class="moveup" href="#">Up</a> '); 
 }); 
 $(".moveup").click(function(){ 
 $(this).closest("fieldset").insertBefore( $(this).closest("fieldset").prev() ); 
 });
});
 
==== Disable (more-or-less) Firefox Screenshots on all pages in Koha ====
* Developer: George Williams (NExpress)
* Purpose: Disables Firefox's new Screenshots button which includes a feature that saves screenshots to an unsecured location in the cloud.
* Creation Date: 09/14/2017
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 16.11
* Koha breadcrumbs: Home › *
* Note: If someone does try to use Firefox Screenshots and this jQuery is in Koha, Firefox Screenshots may start sending warning messages to the browser.
//BEGIN disable Firefox Screenshots whenever the mouse is moved
 $('html').mousemove(function() {
 $('#firefox-screenshots-preselection-iframe').remove();
 });
//END
==== Hide non-local patrons on the "Update patron records" page ====
* Developer: George Williams (NExpress)
* Purpose: With 50+ branches it can be hard for staff to find the patrons from their library on the "Update patron records" screen. This hides all non-local-library patrons from the patron update screen. This includes an optional button so that those may actually need to see all of the patrons needing updates can see everyone if they choose.
* Creation Date: 11/29/2017
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 16.11
* Koha breadcrumbs: Home › Patrons › Update patron records
//BEGIN Hide patron update notices from other branches
 $(window).load(function(){
 var loglibnode=$("#logged-in-branch-name").text();
 $('#pending_updates h3 a:not(:contains("('+loglibnode+'"))').parent().hide();
 $('#pending_updates a:not(:contains("('+loglibnode+'"))').parent().next('.ui-accordion-content').hide();
 });
//BEGIN Add button to show all pending patron updates (optional)
 $('#yui-main > h2:contains(Update patron records)').parent().prepend("<button id='pudshow' type='button'>Show all pending updates</button>");
 $("#pudshow").click( function() {
 $("#pudshow").hide();
 $('#pending_updates h3 a:not(:contains("('+loglibnode+'"))').parent().show();
 });
==== Prevent over-write-offs ====
* Developer: George Williams (NExpress)
* Purpose: Now that we have partial write-offs staff can accidentally write-off an amount greater than the amount owed on an individual fee, thus adding a credit to the patron's account (community bug 20120). This prevents a write-off amount greater than the amount outstanding on an individual fee until such a time that this bug is patched.
* Creation Date: 2018.02.15
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 17.05.08
* Koha breadcrumbs: Home › Patrons › Pay fines for PATRONNAME › Write off an individual fine
//BEGIN Prevent over-write-offs
 $("#amountwrittenoff").attr("type", "number");
 $("#amountwrittenoff").attr("step", "any");
 $("#amountwrittenoff").attr("min", "0");
 $("#amountwrittenoff").attr("max", $("#amountwrittenoff").val());
==== Sort the SMS providers drop-down ====
* Developer: George Williams (NExpress)
* Purpose: The SMS provider drop-down is sorted in the order the provider was added rather than alphabetically by provider name. This makes it difficult for library staff to find providers not added the the list in alphabetical order. This jquery sorts the list alphabetically leaving "Unknown" at the top and maintaining any provider already selected if editing a patron record. Related to community bug 20439.
* Creation Date: 2018.05.07
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 17.05.10
* Koha breadcrumbs: Home › Patrons › PATRONNAME › Modify patron | Home › Patrons › Add patron
//BEGIN force SMS provider to sort alphabetically, put "Unknown" at top of list, and keep any pre-existing selection after sort is finished
 $("#sms_provider_id option:contains('Unknown')").text(' Unknown');
 $("#sms_provider_id").one( "click", function() {
 var preselected = $('#sms_provider_id option:selected').val();
 $("#sms_provider_id").html($('#sms_provider_id option').sort(function(x, y) {
 return $(x).text().toUpperCase() < $(y).text().toUpperCase() ? -1 : 1;
 }));
 $("#sms_provider_id").val(preselected);
 });
==== Hide unnecessary language tabs on Edit notice screen ====
* Developer: Magnus Enger
* Creation Date: 2018-06-06
* Purpose: If you have a number of languages activated on a server, and an instance that does not use all of them, you might want to hide the ones you do not use in the list of language tabs that show up when you edit a notice/slip. 
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 17.11
 
 $("#tabs li").remove(":contains('es-ES')");
 
==== Preserve white spaces of Control Fields ====
* Developer: Stefano Bargioni
* Creation Date: 2018-06-22
* Purpose: Preserve white spaces of Control Fields in MARC view (bib and auth records), and show position of char on mouse hover.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 17.11 (also tested on 3.12, 3.18, 3.22)
 
if ( location.pathname.indexOf('catalogue/MARCdetail.pl')>-1 || location.pathname.indexOf('authorities/detail.pl')>-1 ) {
 var tags = $('.tag_title:contains("00")'); // includes x00
 for (var i = 0; i < tags.length; i++) {
 var tag = tags[i];
 if ($(tag).text().trim().indexOf('00')==0) { // apply only to 00x
 var tag = tags[i];
 var p = $(tag).parent().find('p');
 // p.text() is divided in lines; the first one is "@", the last one is the tag value
 var ts = p.text().trim().split('\n');
 var ts_last = ts.length-1;
 ts[ts_last] = ts[ts_last].replace(/^ +/,); // left trim
 // char by char
 var tc = ;
 for (var j = 0; j < ts[ts_last].length; j++) {
 var c = ts[ts_last][j];
 tc += ''+c+'';
 }
 p.html('  '+ts[0]+''+tc+'');
 $('.white_space_pre').css({"font-family":"monospace", "white-space":"pre"});
 $('.char_fixed').css({'border':'1px solid lightgray', 'margin':'1px', 'padding':'2px'});
 $('.char_fixed').tooltip({ "show": { "effect":"blind", "duration":800 } });
 $('.char_fixed').hover(
 function() {
 $(this).css('background-color','yellow');
 },
 function() {
 $(this).css('background-color',);
 }
 )
 }
 }
}
 
==== Hide JSON URL in Reports Table ====
* Developer: Andrew Fuerste-Henry
* Creation Date: 2018-09-19
* Purpose: Hide the column of JSON urls in the reports table 
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
 
$("#table_reports td.report_json_url").hide(); 
$("#table_reports th:contains('JSON URL')").hide();
 
==== Copy Last 4 Digits of Card Number Into Password on Patron Creation ====
* Developer: Lucas Gass
* Creation Date: 2018-09-20
* Purpose: Autopopulate password with the last four digits of the cardnumber, does not work with AutoMemberNum
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
 
$(document).ready(function () {
 if ( $('#pat_memberentrygen').length > 0 ) { 
 $("#cardnumber").on("keyup change", function() {
 var cardNum = this.value; 
 var lastFour = cardNum.substring(cardNum.length-4, cardNum.length );
 if (cardNum.length > 3){
 $("#password, #password2").val(lastFour);
 }
 });
 }
 });
 
==== Copy Card Number Into Username ====
* Developer: Andrew Fuerste-Henry
* Creation Date: 2018-09-21
* Purpose: Autopopulate username with cardnumber, does not work with AutoMemberNum
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
 
$(document).ready(function () {
 if ( $('#pat_memberentrygen').length > 0 ) { 
 $("#cardnumber").on("keyup change", function() {
 var cardNum = this.value; 
 if (cardNum.length > 13){
 $("#userid").val(cardNum);
 }
 });
 }
 });
 
==== Select preferred notice language in new patron page ====
* Developer: Fridolin Somers
* Creation Date: 2018-09-20
* Purpose: In new patron page, automatically select 'default' in preferred notice language, instead of current staff interface language
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 17.11
$(document).ready(function () {
 $("body#pat_memberentrygen input[name='op'][value='insert']").parent().find("select[name='lang']").val("default").change();
});
input[name='op'][value='insert'] is to avoid changing existing value on edition of an existing patron, since page is the same has new patron creation.
==== Add button 'Exit without saving' when editing an authority record ====
* Developer: Stefano Bargioni (Pontificia Università della Santa Croce)
* Creation Date: 2018-11-14
* Purpose: Allow cataloguer to exit without saving modifications (or use browser button 'go back')
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
var authid = $('h1').text().replace(/[^0-9]/g,);
$('#toolbar').append('\
	<a href="detail.pl?authid='+authid+'" id="exitauth" class="btn btn-default btn-sm" accesskey="z">\
	 Exit without saving</a>\
	');
==== Payment Type Enhancement ====
* Developer: Christopher Brannon (CrispyBran) (Coeur d'Alene Public Library)
* Creation Date: 2018-11-29
* Purpose: Make the payment type required on payments, hide it on the Write off selected page (18.11), and ask for check number if check is chosen
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
if($("#pat_paycollect input[value='writeoff']").length) {
$('#pat_paycollect input[name="submitbutton"]').before('<button id="validate" class="btn btn-small toggler" name="validate" style="margin-left: 0px;" onclick="return validatePayType();"> Confirm</button>');
$("#pat_paycollect #payment_type").parent('li').hide();
} else {
$('#pat_paycollect input[name="submitbutton"]').before('<button id="validate" class="btn btn-small toggler" name="validate" style="margin-left: 0px;" onclick="return validatePayType();"> Confirm</button>');
}
$('#pat_paycollect input[name="submitbutton"]').hide();
// create the validation function
validatePayType = function () {
//start with an empty alert message
var mes = "";
// validate payment_type
if ($("#pat_paycollect #payment_type").val() == && !$("#pat_paycollect input[value='writeoff']").length) {
mes = mes + "\nPlease select a Payment Type.\n";
}
// grab Check Number
var checkNum=;
if ($("#pat_paycollect #payment_type").val() == 'CHECK') {
var checkNum=prompt("Check number");
$('#selected_accts_notes, #payment_note').val(function(index, value) {
if (checkNum == || checkNum === null) {
mes = mes + "\nCheck number not entered!\n";
return;
} else {
return 'Check #' + checkNum + '\n' + value;
}
});
}
// display the alert
if (mes != "") {
 alert(mes);
 return false;
} else {
// submit the validated form
 if( $('#payindivfine').length ){
 $('#payindivfine').submit();
 } else if( $('#payfine').length ) {
	 $('#payfine').submit();
 }
}
};
==== Holdings Enhancement ====
* Developer: Christopher Brannon (CrispyBran) (Coeur d'Alene Public Library)
* Creation Date: 2019-01-10
* Purpose: Show the number of items your library has listed in the current bib record
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
//Count items for your library in holdings
var loggedbranch = $('#circ_request span.logged-in-branch-code').html();
var loggedbranchname = $("span.logged-in-branch-name").html();
var countyouritems = 0;
$('#catalog_detail #holdings_table td.homebranch').each(function(){
 var clone = $(this).clone();
 clone.children().remove();
 clone.text(clone.text().trim());
 if (clone.text() == loggedbranchname) {
 countyouritems++;
 }
});
$('#catalog_detail a:contains("Holdings")').append(' (' + loggedbranchname + ' owns ' + countyouritems + ')'); 
//End count
==== Hold Pickup Enhancement ====
* Developer: Christopher Brannon (CrispyBran) (Coeur d'Alene Public Library)
* Creation Date: 2019-01-10
* Purpose: Show the number of hold requests that will be picked up at your library
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
//Count holds for your library in holds
var loggedbranch = $('#circ_request span.logged-in-branch-code').html();
var loggedbranchname = $("span.logged-in-branch-name").html();
var countyourholds = 0;
$('#circ_request input, #circ_request option:selected').each(function(){
 if ($(this).val() == loggedbranch) {
 countyourholds++;
 }
});
$('#circ_request legend:contains("Existing holds")').append(' (' + countyourholds + ' to be picked up at ' + loggedbranchname + ')'); 
//End count
==== Holdings Count (All Libraries) Enhancement ====
* Developer: Christopher Brannon (CrispyBran) (Coeur d'Alene Public Library)
* Creation Date: 2019-01-11
* Purpose: Display counts of items for all libraries at the top of the holdings list
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
//Holding Count Summary
var byLibrary = {};
$('#catalog_detail #holdings_table td.homebranch').each(function(){
 var LibraryName = $(this).clone();
 LibraryName.children().remove();
 LibraryName.text(LibraryName.text().trim());
 if ( !(byLibrary.hasOwnProperty(LibraryName.text())) ) {
 byLibrary[LibraryName.text()] = 0;
 }
 byLibrary[LibraryName.text()]++;
});
var LibrarySummary = "";
for (var i in byLibrary) {
 LibrarySummary += i + ":" + byLibrary[i] + ", ";
}
LibrarySummary = LibrarySummary.substring(0,LibrarySummary.length - 2);
$('#catalog_detail #holdings').prepend('Item counts: ' + LibrarySummary);
//End holding count summary
==== Hold Pickup Location Count (All Libraries) Enhancement ====
* Developer: Christopher Brannon (CrispyBran) (Coeur d'Alene Public Library)
* Creation Date: 2019-01-11
* Purpose: Display counts of items for pickup at each library at the top of the holds list
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.05
//Hold pickup location summary
var byLibrary = {};
$('#circ_request td:nth-child(7):contains("since")').each(function(){
	var LibraryName = $(this).find('b').text().trim();
 if ( !(byLibrary.hasOwnProperty(LibraryName)) ) {
 byLibrary[LibraryName] = 0;
 }
	byLibrary[LibraryName]++;
});
$('#circ_request select[name="pickup"] option:selected').each(function(){
	var LibraryName = $(this).text();
	if ( !(byLibrary.hasOwnProperty(LibraryName)) ) {
		byLibrary[LibraryName] = 0;
	}
	byLibrary[LibraryName]++;
});
var LibrarySummary = "";
for (var i in byLibrary) {
 LibrarySummary += i + ":" + byLibrary[i] + ", ";
}
LibrarySummary = LibrarySummary.substring(0,LibrarySummary.length - 2);
$('#circ_request legend:contains("Existing holds")').after('Pickup location counts: ' + LibrarySummary + '');
//End hold pickup location summary
==== Hold Pickup Location Count (All Libraries) Enhancement (v21.05) ====
* Developer: Christopher Brannon (CrispyBran) (Coeur d'Alene Public Library)
* Creation Date: 2022-06-03
* Purpose: Display counts of items for pickup at each library at the top of the holds list
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
 //Hold pickup location summary (v21.05)
 if ($('#circ_request').length) {
 var byLibrary = {};
 $('#existing_holds input[name="pickup"]').each(function(){
 var LibraryName = $(this).next('strong').text().trim();
 console.log(LibraryName);
 if ( !(byLibrary.hasOwnProperty(LibraryName)) ) {
 byLibrary[LibraryName] = 0;
 }
 byLibrary[LibraryName]++;
 });
 $('#existing_holds select.pickup_location_dropdown option:selected').each(function(){
	 var LibraryName = $(this).text();
 if ( !(byLibrary.hasOwnProperty(LibraryName)) ) {
 byLibrary[LibraryName] = 0;
	 }
 byLibrary[LibraryName]++;
 });
 var LibrarySummary = "";
 for (var i in byLibrary) {
 LibrarySummary += i + ' ' + byLibrary[i] + ' / ';
 }
 LibrarySummary = LibrarySummary.substring(0,LibrarySummary.length - 2);
 $('#existing_holds #toolbar').after('Pickup location counts: ' + LibrarySummary + '');
 }
 //End hold pickup location summary
==== Set default filters for the inventory tool ====
* Developer: George Williams (Next Search Catalog)
* Purpose: Check the "Homebranch" radio button and select the logged in library as default item location filters when using the inventory tool. 
* Creation Date: 2019.02.01
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 18.05.07
* Koha breadcrumbs: Home > Tools > Inventory
//BEGIN set defaults on inventory tool filters
 $("#tools_inventory #inventory_form input[value='homebranch']").attr("checked","checked");
 var invnode=$(".logged-in-branch-name").text().trim().substring(0, 5);
 $('#tools_inventory #branchloop option:contains('+ invnode +')').attr("selected","selected");
//END
==== Add password randomizer to memberentry ====
* Developer: Jason Robb (SEKnFind/SEKLS)
* Purpose: Copies the password randomizer function from member-password to memberentry
* Creation Date: 2019-03-12
* Status: Completed. Temporary work-around for Bug 22485.
* Intranet or OPAC?: Intranet
* Version: 18.05.08
 function generate_password() {
 	// Always generate a strong password
 	var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 	var length = 3;
 	if (length < 8) length = 8;
 	var password = ;
 	for (var i = 0; i < length; i++) {
 		password += chars.charAt(Math.floor(Math.random() * chars.length));
 	}
 	return password;
 }
 $("body").on('click', "#fillrandom", function(e) {
 	e.preventDefault();
 	var password = ;
 	var pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{3,}/;
 	while (!pattern_regex.test(password)) {
 		password = generate_password();
 	}
 	$("#password").val(password);
 	$("#password").attr('type', 'text');
 	$("#password2").val(password);
 	$("#password2").attr('type', 'text');
 });
 //Adds link after second password box
 $("#pat_memberentrygen #password2").after(" <a href=\"#\" id=\"fillrandom\">" + _("Click to fill with a randomly generated suggestion. ") + "" + _("Passwords will be displayed as text") + ".</a>");
==== Resize Z39.50 pop-up window when loaded ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: I have catalogers at multiple libraries using a wide variety of screen sizes who have complained about the default size of the Z39.50 pop-up window high resolution screens. As written this jQuery makes the height and width of the Z39.50 pop-up 90% of the screen size and pushes it to the top-left corner of the screen and then resizes the columns inside of the pop-up to 75% of the window height.
* Creation Date: 2019.07.12
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 18.05 - runs on 18.11
* Koha breadcrumbs: Home > Cataloging > Z39.50/SRU pop-up
//Cataloging > Z39.50/SRU pop-up
 //BEGIN Resize Z39.50 window
 if (document.location.href.indexOf('z3950_search.pl')>-1) window.resizeTo((screen.width * .9), (screen.height * .9)), window.moveTo(0, 0);
 $(window).on('load resize', function(){
 $('#cat_z3950_search .col-xs-6 .rows, #cat_z3950_search #z3950_search_targets').height($(this).height() * .75);
 $('#cat_z3950_search .col-xs-6 .rows').css('overflow-y', 'scroll')
 });
//END
==== Restrict ability to change branches to specific users ====
* Developer: Jason Robb (SEKnFind/SEKLS)
* Purpose: Prevents access to the 'Set Library' dropdown to specific users
* Creation Date: 2019-09-21
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.11
//Prevent access to the 'Set Library' except for specific users
var loggedUser = $("#logged-in-info-full .loggedinusername").text();
var unrestrictedUsers = ['username1','username2','username3']; //add usernames here for those that need access
if ($.inArray(loggedUser, unrestrictedUsers) == -1) {
 $('a[href*="selectbranchprinter.pl"]').hide();
}
==== Make Alerts (Pending Moderations) More Visible ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Moves the moderations that are pending from the bottom of the screen (which might be off screen) to above the news panel.
* Creation Date: 2019-10-03
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.11
//Area Pending Move
$('#area-pending').prependTo('div.col-sm-3').css('border','1px solid #EEEEEE').css('margin','0.2em').css('width','auto').prepend('Alerts');
$('div.pending-info').css('margin','0.3em').css('background-color','yellow').css('opacity','0.75').css('border-radius','6px').css('padding','3px');
$('div.pending-info a').prepend(' ');
if ($('div.pending-info').is(':hidden')) {
$('#area-pending').hide();
}
//End Move
==== Enhance the visibility of statuses on the detail.pl page for staff (18.x)====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network) with some code from George Williams
* Purpose: Adds icons and color to different statuses in the item detail page for easier readability.
* Creation Date: 2019-10-17
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.11
* See Also: Featured on The Terrific Every-Other-Thursday Training Video S1E2: https://koha-us.org/learn/
//Status Enhance
$('.status .lost, .status .dmg').prepend(' ');
$('.status .intransit').css('color','darkorange').prepend(' ');
$('.status:contains("Not for loan")')
 .contents()
 .filter(function() {
 return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
$('.status .noloan, .status .wdn').css('color','#900').prepend(' ');
$('.status:contains("Item-level")')
 .contents()
 .filter(function() {
 return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
$('.status .ilreqeust:not(:contains("Item-level"))').remove();
$('.status .ilreqeust').html('  There are Item-Level holds on this item.');
$('.status .ilreqeust').next('a').hide();
$('.status:contains("Waiting at")')
 .contents()
 .filter(function() {
 return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
$('.status .waiting-hold:not(:contains("Waiting at"))').remove();
$('.status .waiting-hold').css('color','darkorange').prepend(' ');
//End Enhance
==== Enhance the visibility of statuses on the detail.pl page for staff (19.x)====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network) with some code from George Williams
* Purpose: Adds icons and color to different statuses in the item detail page for easier readability. (Updated for 19.11)
* Creation Date: 2020-06-22
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.11
* See Also: Featured on The Terrific Every-Other-Thursday Training Video S1E2: https://koha-us.org/learn/
//Status Enhance
//Items with Not for loan status need to have a wrapper for easy manipulation
 $('.status:contains("Not for loan")').contents().filter(function() { 
 return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
//Items level hold info needs to have a wrapper for easy manipulation 
 $('.status:contains("There is an item level hold on this item (priority")').contents().filter(function() { 
 	return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
//Waiting holds are wrapped for easy manipulation 
 $('.status:contains("Waiting at")').contents().filter(function() { 
 return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
//Clean up and remove Item level hold wraps around empty spaces 
 $('.ilrequestlow').each(function() { 
 $(this).text($(this).text().trim());
 });
 $('.ilrequestlow:empty').remove();
//Clean up and remove Waiting hold wraps around empty spaces 
 $('.status .waiting-hold:not(:contains("Waiting at"))').remove(); 
//Just gets rid of a lot of hidden and useless white space. Does not change visual look. 
 $('.status').each(function() { 
 $(this).html($(this).html().replace(/\s+/g, " "));
 });
//Lost and Damaged statuses get the triangle bang symbol
 $('.status .lost, .status .dmg').prepend(' ');
//In Transit statues get the truck symbol and are colored orange
 $('.status .intransit').css('color','darkorange').prepend(' ').append(''); 
//Not for loan and Withdrawn statuses are given the crossed out (ban) symbol and colored red
 $('.status .noloan, .status .wdn').css('color','#900').prepend(' '); 
//Item level holds are given info circle symbol
 $('.ilrequestlow').prepend(' '); 
//Waiting hold statuses are given a clock symbol and colored dark orange 
 $('.status .waiting-hold').css('color','darkorange').prepend(' '); 
//Start Hold for info on next line and indent - clean up readability 
 $('.status .waiting-hold').each(function() { 
 $(this).html($(this).html().replace(/Hold for:/g, "- Hold for:"));
 });
//Start due date info on next line and indent - clean up readability 
 $('.status .datedue').each(function() { 
 $(this).html($(this).html().replace(/: due/g, "- Due"));
 });
//End Enhance
==== Remove extra Amazon no image found when there is an image above it ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Makes the Amazon "no image" picture go away.
* Creation Date: 2019-11-04
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 18.11
* Notes: This can't be done via css because a 1x1 image is loaded initially, and then either updated with an image or message. The method is a little more complex because Chrome and Firefox load at different speeds.
//Remove extra Amazon no image found placeholders on results
$('#catalog_results #bookbag_form a.p1 img[alt]').on("load", function() {
 $(this).each(function() {
 if ($(this).width() == 1) {
 $(this).remove();
 }
 });
});
//End Remove extras
==== Remove or optionally hide "Collect from patron" drop-down and "Change to give" calculation from "Make a payment" tab ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: Some of our libraries do not want the "Collect from patron" input box and "Change to give" dialogue to appear on the "Make a payment" tab, and some of them do. The first bit of jQuery completly removes both of these items from the "Make a payment" tab for libraries that do not want them at all, the second option removes them but also inserts a button that can be clicked to make them appear if staff actually wants to use them.
* Creation Date: 2019.11.12
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05
* Koha breadcrumbs: Home > Patrons > Pay fines for PATRONNAME > Pay an individual fine /or/ Pay an amount toward all fines /or/ Pay an amount toward selected fines
Option 1 simply removes "Collect from patron" and "Change to give"
//Patrons > Pay fines for PATRONNAME > Pay an individual fine 
 //Hide "Collected from patron:" and "Change to give:" drop-downs
 $('#pat_paycollect #change, #pat_paycollect #collected').parent().hide();
Option 2 hides "Collect from patron" and "Change to give" behind a button
//Patrons > Pay fines for PATRONNAME > Pay an individual fine /or/ Pay an amount toward all fines /or/ Pay an amount toward selected fines 
 //Hide "Collected from patron:" and "Change to give:" drop-downs but also add a button to make their appearance optional
 $('#pat_paycollect #change, #pat_paycollect #collected').parent().hide();
 $('#pat_paycollect #paid').parent().append("<label></label><button id='changecalc' type='button' class='btn btn-default' style='margin:10px 0px 0px 0px;'>Calculate change</button>");
 $("#changecalc").click( function() {
 $("#changecalc").hide();
 $('#pat_paycollect #change, #pat_paycollect #collected').parent().show();
 });
==== Optionally bypass Code Mirror on IntranetUserJS and OPACUserJS to make these preferences internally searchable again ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: Don't get me wrong - I like Code Mirror. However, now that Code Mirror has been added to IntranetUserJS and OPACUserJS, you can't use the browser's built in "Find on this page..." functions to search through the content in IntranetUserJS or OPACUserJS unless the text you're searching for is actually being displayed on the screen. This jQuery allows you to bypasses Code Mirror so you can search and edit both of these preferences in a simple input box rather than with the code mirror input box. Without too much trouble, this jQuery could also be modified to work with other using Code Mirror (like IntranetmainUserblock or OpacMainUserBlock or IntranetUserCSS etc.) until the Code Mirror search addons can be added to Koha.
* Creation Date: 2019.11.12
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05
* Koha breadcrumbs: Home > Administration > System preferences
//Administration > System preferences
 //BEGIN add link to bypass Code Mirror on IntranetUserJS system preference
 $('#expand_IntranetUserJS').text('Edit with Code Mirror');
 $('#expand_IntranetUserJS').after('<a id="intranomirror" href="#pref_IntranetUserJS">Edit without Code Mirror</a>');
 $("#intranomirror").click( function() {
 $("#expand_IntranetUserJS, #intranomirror").hide();
 $('#pref_IntranetUserJS').show();
 });
 $("#expand_IntranetUserJS").click( function() {
 $("#intranomirror").hide();
 });
 //BEGIN add link to bypass Code Mirror on OPACUserJS system preference
 $('#expand_OPACUserJS').text('Edit with Code Mirror');
 $('#expand_OPACUserJS').after('<a id="opacnomirror" href="#pref_OPACUserJS">Edit without Code Mirror</a>');
 $("#opacnomirror").click( function() {
 $("#expand_OPACUserJS, #opacnomirror").hide();
 $('#pref_OPACUserJS').show();
 });
 $("#expand_OPACUserJS").click( function() {
 $("#opacnomirror").hide();
 });
==== On cataloguing in add a new biblio record, add a label next to MARC tag title ====
* Developer: Emma Perks - BASE Library
* Purpose: Libraries may need to add an instruction, notice or warning for cataloguers adjacent to MARC 008 field
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
$(document).ready(function() {
var3 = $('body').is("#cat_addbiblio"); //Makes sure the change only happens on biblio
if(var3 !=0) {
$("[id^='tag_008']").prepend('Instruction');
}}
==== Transportation cost matrix - move row to top of table ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: I have 53 libraries so the transportation cost matrix is a 53x53 table. To make it easier to follow the rows when I'm making changes, this jQuery causes a row to move to the top of the table when the library name in the "From\To" column of the table is clicked. 
* Creation Date: 2019.11.26
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 18.11
* Version: 23.05 - tested and working
* Koha breadcrumbs: Home > Administration > Transport cost matrix
//Administration > Transportation cost matrix
 //BEGIN Click on library name and row will move to the top of the table
 $("#cost_matrix_form #transport-cost-matrix tr th:nth-child(1)").click(function() {
 $(this).parent().insertAfter("#cost_matrix_form #transport-cost-matrix tbody tr:first");
 });
==== Hide "Forgiven" credit type ====
* Developer: Caroline Cyr La Rose, inLibro
* Creation Date: 2019-11-29
* Purpose: Hide the "Forgiven" option in the manual credits to prevent staff from using it
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 18.05, still works in 19.05, but as of 19.11 you have to write FORGIVEN in capitals.
 
//Use this for 19.05 and earlier
$("#mancredit #type option[value='forgiven']").hide();
//Use this for 19.11 and later
$("#mancredit #type option[value='FORGIVEN']").hide();
 
==== Add link to go directly to a record by its biblionumber ====
* Developer: A. Longoria, Texas State Law Library
* Creation Date: 2019-12-17
* Purpose: This adds a "Go to Biblio" bookmarklet in the staff client that prompts the user for a biblionumber and goes to that record's details page
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.11.06
// Add a "go to biblionumber" feature to the menu at the top left of each page.
var $topLevelMenu = $('#header').find('#toplevelmenu');
var goToBiblioUrl = '/cgi-bin/koha/catalogue/detail.pl?biblionumber='; 
if ($topLevelMenu.length === 1) {
 var $goToBiblioLink = $('<a />')
 .attr('href', 'javascript:var biblio = prompt("Enter biblionumber:"); if (biblio) { window.location = "' + goToBiblioUrl + '" + biblio; }')
 .html(' Go to Biblio');
 var $goToBiblioListItem = $('').append($goToBiblioLink);
 $topLevelMenu.append($goToBiblioListItem);
}
==== Move Check-in alerts to modals when needed ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Creation Date: 2019-12-19
* Purpose: This moves alerts to any modal that appears during check-in, so they are visible.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05
//Enhance Check-in Modals
 $('#circ_returns div.alert').appendTo('#circ_returns div.modal-content');
//End Enhance Modals
==== Pre-select framework in Manage staged MARC records page ====
* Developer: Caroline Cyr La Rose
* Creation Date: 2020-01-10
* Purpose: This changes the default framework that is preselected when importing staged marc records
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05
$("#frameworks option[value=]").removeAttr("selected");
$("#frameworks option[value='YOURFRAMEWORKCODE']").attr("selected","selected");
==== Suppress CART location in item editor ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library / CIN
* Purpose: Prevent staff from adding or duplicating the CART location when editing an item record.
* Creation Date: 2020-02-03
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.x
//Recently Return Selection Disable
$('#cat_additem select[id^="tag_952_subfield_c_"] option[value="CART"]').prop('disabled','true').remove();
//End Recently Return Selection Disable
==== Add button to copy Primary Phone to SMS Number in patron entry ====
* Developer: Lisette Scheer Latah County Library District / Valnet
* Purpose: Add button to copy Primary Phone to SMS Number in patron entry.
* Creation Date: 2020-03-04
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.x
//Add SMS Copy Phone Button
 if (window.location.href.indexOf("memberentry.pl") > -1) {
 $("#entryform #SMSnumber").parent().append("<button id='smscopy' type='button'>Copy Primary Phone</button>");
 $("smscopy").click(function() {
 $("#entryform #SMSnumber").val($("#entryform #phone").val());
 });
 }
//End Add SMS Copy Phone Button
==== Acquisitions - set default quantity to 1 ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: When you order, you always order at least 1. This changes the default quantity from 0 to 1
* Creation Date: 2020-03-16
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.05
//Acquisitions: Set default qty to 1
$( "#acq_neworderempty #quantity").val("1");
==== Serials - set default locale ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: instead of having to always select your locale, this selects it by default. The example is with french (fre) substitute it with your local language
* Creation Date: 2020-03-16
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.05
//Serials: Choose default locale
$( "#ser_subscription-add #locale").val("fre");
==== Serials - check 'create an item record when receiving this serial' by default ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: Most public libraries (here in any case) want to add items to serial records for most of their subscriptions. Instead of having to always select 'create an item record when receiving this serial', this selects it by default. 
* Creation Date: 2020-03-17
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.05
//Serials: default to create an item record
$('#serialsadditems-no').prop('checked', 'false');
$('#serialsadditems-yes').prop('checked', 'true');
----
==== Alert on patron record if address 1/2 contains specified text ====
* Developer: Emma Perks, BASE Library
* Creation Date: 2020-05-29
* Purpose: This displays a pop-up dialog on all pages of the member record if the string exists in the address 1/2 
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: 18.11
 
if ($('div.patroninfo > ul.patronbriefinfo > li.patronaddress1:contains("specify a text string here and enter the same into the patron address 1/2 field")').length > 0) {
 alert('Message appears in a pop-up box');
 }
 
==== Add line break and shelviing location label to holdings table on detail.pl ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: Adds a line break between home library and shelving location and adds label to shelving location
* Creation Date: 2020.06.01
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05; tested on 19.11
* Koha breadcrumbs: Home > Catalog > Details for TITLE
 //Add break between home library and shelving location label
 $('#catalog_detail .shelvingloc').prepend('Shelving location:');
==== Highlight items in CART location on details page ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: Highlights the Home library cell in a table on the details page when an item has a "CART" shelving location. Works really well with 'Add line break and shelviing location label to holdings table on detail.pl.'
* Creation Date: 2020.06.01
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05 - also tested on 19.11
* Koha breadcrumbs: Home > Catalog > Details for TITLE
* Notes: Replace DESCRIPTION in '.shelvingloc:contains("DESCRIPTION")' with the description from your authorized value for CART from the LOC authorized values table
 //Enhance "CART" shelving location
 $('#catalog_detail .shelvingloc:contains("DESCRIPTION")').prepend(' ').parent().css('background','#ffb3ff');
==== Always Show Checkouts Immediately ====
* Developer: Lucas Gass, ByWater Solutions
* Purpose: Always Show Checkouts Immediately without checking the box in the patron record 
* Creation Date: 2020-07-09
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 19.11
$(document).ready(function() {
 if ( typeof script !== 'undefined' && ! $.cookie("issues-table-load-immediately-" + script && $('#pat_moremember, #circ_circulation').length) ) {
 $('#issues-table-load-now-button').click();
 $.cookie("issues-table-load-immediately-" + script, true, { expires: 365 });
 }
});
----
==== Add report number to report name ====
* Developer: George Williams (NEKLS / Next search catalog)
* Purpose: Adds the report number in parenthesis to the name of the report once the report has finished running
* Creation Date: 2020.07.09
* Status: Completed
* Intranet or OPAC?: INTRANET
* Version: Developed on 19.11
* Breadcrumbs: Home › Reports › Guided reports wizard > Saved reports > REPORTNAME Report
 //BEGIN Add report number to the report name once a report has run
 var url = $(location).attr('href');
 if(url.indexOf("guided_reports.pl?reports=") != -1){
 $('#rep_guided_reports_start .col-sm-10 main h1').addClass('addreportnumber');
 $('input[name="param_name"]').parents().prev('h1').removeClass('addreportnumber');
 $('.addreportnumber').first().append(" - (Report #" + $('#limitselect input[name="reports"]').val() + ")")
 }
	
==== Enhance CART shelving location on details page ====
* Developer: George Williams (NEKLS / Next search catalog)
* Purpose: Adds shelving location label to details page, adds icon and changes cell color if shelving loction is CART
* Creation Date: 2020.08/02
* Status: Completed
* Intranet or OPAC?: INTRANET
* Version: Developed on 19.11
* Breadcrumbs: Home › Catalog › Details for TITLE
* See Also: Featured on The Terrific Every-Other-Thursday Training Video S1E1: https://koha-us.org/learn/
 //Remove empty shelving location spans
 $('#catalog_detail .shelvingloc').each(function(){
 if( $(this).text().trim() === )
 $(this).remove();
 });
 //Add doublespace between home library and shelving location and create text label (optional)
 $('#catalog_detail .shelvingloc').prepend('Shelving location:');
 //Enhance "Recently returned" shelving location by adding a FA icon and changing the cell color (change "Recently returned" to match the description your library uses for the CART shelving location)
 $('#catalog_detail .shelvingloc:contains("Recently returned")').prepend(' ').parent().css('background','#ffb3ff');
	
==== Add Links to Collapse Messages on Patron Accounts ====
* Developer: Lisette Scheer
* Creation Date: 2020-08-13
* Purpose: Adds link to collapse/hide messages on the checkout screen and details screen.
* Status: Completed 
* Intranet or OPAC?: Intranet 
* Version: Developed on 19.11 
 
 //-----------------------BEGIN ADD HIDE MESSAGE BUTTON-----------------------//
$(document).ready(function(){
 if (window.location.href.indexOf("circ/circulation.pl") > -1) {
 $("#messages .circ-hlt").addClass("hidden-message").show();
 $("#messages .circ-hlt").parent().prepend("<a class='show-hidden-message' href=>[Collapse Message]</a>");
 $(".show-hidden-message").on('click', function() {
 $(this). parent().children('.circ-hlt').hide();
 $(this). parent().children('.show-hidden-message').hide();
 return false;
 });
 }
});
$(document).ready(function(){
 if (window.location.href.indexOf("members/moremember.pl") > -1) {
 $("#messages .circ-hlt").addClass("hidden-message").show();
 $("#messages .circ-hlt").parent().prepend("<a class='show-hidden-message' href=>[Collapse Message]</a>");
 $(".show-hidden-message").on('click', function() {
 $(this). parent().children('.circ-hlt').hide();
 $(this). parent().children('.show-hidden-message').hide();
 return false;
 });
 }
});
//-----------------------END ADD HIDE MESSAGE BUTTON-----------------------//
 
==== Add Links to Collapse Notes on Patron Accounts ====
* Developer: Lisette Scheer
* Creation Date: 2020-08-13
* Purpose: Adds link to collapse/hide messages on the checkout screen.
* Status: Completed 
* Intranet or OPAC?: Intranet 
* Version: Developed on 19.11 
 
//-----------------------BEGIN ADD HIDE NOTE BUTTON-----------------------//
$(document).ready(function(){
 if (window.location.href.indexOf("circ/circulation.pl") > -1) {
 $("#circnotes .circ-hlt").addClass("hidden-note").show();
 $("#circnotes .circ-hlt").parent().append("<a class='show-hidden-note' href=>[Collapse Note]</a>");
 $(".show-hidden-note").on('click', function() {
 $(this). parent().children('.circ-hlt').hide();
 $(this). parent().children('.show-hidden-note').hide();
 return false;
 });
 }
});
//-----------------------END ADD HIDE NOTE BUTTON-----------------------//
 
==== Make 'Search main heading' the default when searching authorities ====
* Developer: Carlos Lopez
* Creation Date: 2020-09-03
* Purpose: Change the default search in authorities from 'Search main heading ($a only)' to 'Search main heading'
* Status: Completed
* Intranet or OPAC?: Intranet 
* Version: 18.11.11
 
 if (window.location.pathname == '/cgi-bin/koha/authorities/authorities-home.pl') {
 $( "#header_search" ).tabs({ active: 1 });
 }
 
==== Render patron messages as HTML and in Report notes ====
* Developer: George Williams (NEKLS / Next search catalog) with help from ByWater staff
* Purpose: Prior to Koha 16.11, you could use HTML markup in patron messages. From Koha 16.11 onwards, the HTML will not render in patron messages. This adds HTML rendering to existing messages and allows you to use HTML when creating new messages. Prior to Koha 18.11, you could use HTML markup in notes on SQL reports. From Koha 18.11 you can not. This adds HTML rendering to existing report notes and allows you to use HTML when creating new notes on reports.
* Creation Date: 2017.12 and 2019.03
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Created on 16.11; tested and working on 19.11
* Notes: Once the function has been created, it can be applied to any element where you want HTML to render where it currently does not render
* Breadcrumbs: Home › Circulation › Checkouts › PATRONNAME; Home › Reports › Guided reports wizard › Saved reports; Home › Reports › Guided reports wizard › Saved reports › REPORTNAME Report
* See Also: Featured on The Terrific Every-Other-Thursday Training Video S1E4: https://koha-us.org/learn/
 //BEGIN Creates to html function
 $.fn.toHtml=function(){
 return $(this).html($(this).text())
 }
 
 //BEGIN Changes messages back to HTML
 $('#messages .circ-hlt').each(function() {
 $(this).toHtml();
 });
 
 //BEGIN renders notes on reports in HTML
 $("#rep_guided_reports_start .label:contains('Notes:')").parent().wrap("");
 $('#table_reports tr td:nth-child(7), #reportnotes').each(function() {
 $(this).toHtml();
 }); 
==== Make reports button on home page default to saved reports ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Reduce clicks to saved reports by changing the link for the reports button on the home page, and giving the reports page a full navigation menu to get to the other report options.
* Creation Date: 2020.10
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: 19.11
//Tweak Report Navigation
//Home › Reports › Guided reports wizard › Saved reports
 $('#rep_guided_reports_start #navmenulist').replaceWith('Guided reports
<a href="/cgi-bin/koha/reports/guided_reports.pl">Guided reports</a>
<a href="/cgi-bin/koha/reports/guided_reports.pl?phase=Build%20new">Build new</a>
<a href="/cgi-bin/koha/reports/guided_reports.pl?phase=Use%20saved" class="current">Use saved</a>
<a href="/cgi-bin/koha/reports/guided_reports.pl?phase=Create%20report%20from%20SQL">Create from SQL</a>
Statistics wizards
<a href="/cgi-bin/koha/reports/acquisitions_stats.pl">Acquisitions</a>
<a href="/cgi-bin/koha/reports/borrowers_stats.pl">Patrons</a>
<a href="/cgi-bin/koha/reports/catalogue_stats.pl">Catalog</a>
<a href="/cgi-bin/koha/reports/issues_stats.pl">Circulation</a>
<a href="/cgi-bin/koha/reports/serials_stats.pl">Serials</a>
<a href="/cgi-bin/koha/reports/cash_register_stats.pl">Cash register</a>
<a href="/cgi-bin/koha/reports/reserves_stats.pl">Holds</a>
Report plugins
<a href="/cgi-bin/koha/plugins/plugins-home.pl?method=report">Report plugins</a>
Top lists
<a href="/cgi-bin/koha/reports/bor_issues_top.pl">Patrons with the most checkouts</a>
<a href="/cgi-bin/koha/reports/cat_issues_top.pl">Most-circulated items</a>
Inactive
<a href="/cgi-bin/koha/reports/borrowers_out.pl">Patrons who haven\'t checked out</a>
<a href="/cgi-bin/koha/reports/catalogue_out.pl">Items with no checkouts</a>
Other
<a href="/cgi-bin/koha/reports/itemslost.pl">Lost items</a>
<a href="/cgi-bin/koha/reports/orders_by_fund.pl">Orders by fund</a>
<a href="/cgi-bin/koha/reports/manager.pl?report_name=itemtypes">Catalog by item type</a>
<a href="/cgi-bin/koha/reports/issues_avg_stats.pl">Average loan time</a>
<a href="http://schema.koha-community.org/" target="blank">Koha database schema</a>
<a href="http://wiki.koha-community.org/wiki/SQL_Reports_Library" target="blank">Koha reports library</a>
');
 $('#main_intranet-main a.icon_reports').attr('href', '/cgi-bin/koha/reports/guided_reports.pl?phase=Use%20saved')
//End Report Navigation
==== Add Curbside Parking Slips to Patron Checkout Screen ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Alternative to the curbside plugin, this is a simple modification that will add a curbside pickup slip feature to the more menu in the checkout page.
* Creation Date: 2020.11
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: 19.11
* Notes: This jQuery requires a dedicated non-public report that outputs the looks up the borrowers table by borrowernumber and outputs firstname, surname, and cardnumber.
//Holds Waiting Count
 var WaitingHereCount = 0;
 var WaitingTotal = 0;
 $('#circ_circulation #holdswaiting ul strong').each(function(){
 if ($(this).hasClass('waitinghere')) {
 WaitingHereCount++;
 WaitingTotal++;
 } else {
 WaitingTotal++;
 }
 });
 $('#circ_circulation #holdswaiting h4').text(function (_,txt) {
 return txt.slice(0, -1);
 }).prepend(WaitingTotal + ' ');
 if (WaitingHereCount > 0) {
 $('#circ_circulation #holdswaiting h4').append(' (' + WaitingHereCount + ' at this location)');
 }
//End Holds Waiting Count
 
//Get patron name info (First,Last,CardNumber)
 if ($('#circ_circulation').length) {
 var CurrentBorrowerNumber = $('#add_message_form input[name="borrowernumber"]').val();
 $.getJSON("/cgi-bin/koha/svc/report?id=1&sql_params=" + CurrentBorrowerNumber + ".json?_:" + new Date().getTime(), function(data) {
 $.each(data, function(index, value) {
	 $('#circ_circulation').attr('data-patfirstname',value[0]);
 $('#circ_circulation').attr('data-patlastname',value[1]);
 $('#circ_circulation').attr('data-patcardnumber',value[2]);
 });
 });
 }
 
//Curbside Slips
 $('#circ_circulation').append('<form method="post" action="submit" onsubmit="return false;"><input type="hidden" name="" value="">Curbside Pickup<button id="btnCurbsidePrint" type="button" class="btn btn-default" style="background-image: none; background-color: rgb(105, 162, 104);"> Print curbside slip</button><button id="btnCurbsideCancel" data-dismiss="modal" aria-hidden="true" class="btn"> Cancel</button> <!-- /.modal-footer --></form> <!-- /.confirm --> <!-- /.modal-content --> <!-- /.modal-dialog -->');
 $('#CurbsideModal').keypress(function(e){
 if(e.keyCode==13)
 $('#btnCurbsidePrint').click();
 });
 $('#circ_circulation #renewpatron').closest('ul').prepend('<a id="CINCurbside" href="#" data-original-title="" title="">Curbside Pickup</a>');
 $('#circ_circulation #CINCurbside').on('click', function() {
 
 var patFirstName = $('#circ_circulation').attr('data-patfirstname');
 var patLastName = $('#circ_circulation').attr('data-patlastname');
 var patCardNumber = $('#circ_circulation').attr('data-patcardnumber');
 var patPartialName = patLastName;
 var patFullName = ;
 if (patFirstName !=) {
	patPartialName += ', ' + patFirstName.match(/\b./g).join();
	patFullName += patFirstName + ' ';
 }
 patFullName += patLastName;
 
 $('#CurbsideInfo').html('<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Libre Barcode 39">' + patPartialName + '*' + patCardNumber + '*Parking Spot: <input id="infoParking" type="text" class="focus" size="1"> Vehicle: <input id="infoVehicle" type="text" class="focus" size="15">');
 $('#CurbsideModal').modal('show');
});
$('#circ_circulation #btnCurbsidePrint').on('click', function () {
 var infoParkingValue = $('#infoParking').val();
 var infoVehicleValue = $('#infoVehicle').val();
 var patHolds = 'No Holds';
 if($('#holdswaiting h4').length > 0) {
	patHolds = $('#holdswaiting h4').html();
 }
 $('#infoParking').replaceWith(infoParkingValue);
 $('#infoVehicle').replaceWith(infoVehicleValue);
 var CurbsideData = $('#CurbsideInfo').html();
 CurbsideData += patHolds;
 printCurbside(CurbsideData);
});
function printCurbside(elem) {
 var myWindow=window.open(,,);
 myWindow.document.write(elem);
 myWindow.document.close();
 myWindow.focus();
 myWindow.print();
 myWindow.close();
}
//End Curbside Slips
==== Preset branch dropdowns in reports to your branch ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Have report default branch dropdowns to your branch
* Creation Date: 2020.05
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: 19.11
* Notes: While you can always change the branch, if you are mostly running reports for your branch, this will save you a little time, especially if you are in a large consortium.
* See Also: Featured on The Terrific Every-Other-Thursday Training Video S1E7: https://koha-us.org/learn/
//Preset library dropdowns
var library_name = $.trim($('#user-menu span.logged-in-branch-name:first').text());
$('#rep_guided_reports_start').find('option').filter(function(index) {
 return library_name === $(this).text();
}).attr("selected", "selected");
//End Preset
----
==== Change intranet background color for a specific branch ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: Make sure staff notice that they are logged in at a specific branch by changing the intranet background color
* Creation Date: 2021-01
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: 20.05
* Note: In the code, change FPL for the branchcode of the specific branch; you can also change the colour, #ffccff is a very bright pink
$(document).ready(function() {
 if ($("#logged-in-info-full .logged-in-branch-code").text() == "FPL"){
 $("#logged-in-info-full .logged-in-branch-code").parents("body").css("background-color", "#ffccff");
 }
});
----
==== Enhanced Search Facets for Staff ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library / Cooperative Information Network
* Creation Date: 2020-04-01
* Purpose: Collapse and enhance the search facets, adding check boxes, making them responsive and cleaner
* Status: Completed
* Version: 19.11
//Revamp Facets 
 //Place headers around stray section titles so we can control these later.
 $('#search-facets #availability_facet').contents().filter(function() {
 return (this.nodeType === 3 && !/\S/.test(this.nodeValue));
 }).wrap('').end();
 if($('#search-facets #availability_facet h5').text().trim().length < 1) {
 $('#search-facets #availability_facet h5').remove();
 }
 $('#search-facets #availability_facet').contents().filter(function() {
 return this.nodeType === 3;
 }).wrap('').end();
 $('#search-facets').children('ul').children('li').children('span').each(function() {
 	$(this).replaceWith(function(){
 return $("").append($(this).contents());
 	});
 });
 
 //Add functionality to headers for visibility and collapsing/expanding sections, and show entire contents in section
 $('#search-facets').children('ul').children('li').children('h5').wrap('<a class="viewSwitch" style="text-decoration: none; cursor: pointer;" />');
 $('#search-facets a.viewSwitch h5').prepend(' ');
 $('#search-facets a.viewSwitch').parent().children('ul').wrap('');
 $('#search-facets div.contentsToggle').hide();
 $('#search-facets .contentsToggle').find('li.moretoggle').remove();
 $('#search-facets .collapsible-facet').show().removeAttr('class').removeAttr('style');
 $('#search-facets a.viewSwitch').click(function() {
 $(this).parent().children('.contentsToggle').toggle('slow');
 if ($(this).find('i').hasClass('fa-caret-right')) {
 $(this).find('i').addClass('fa-caret-down').removeClass('fa-caret-right');
 } else {
 $(this).find('i').addClass('fa-caret-right').removeClass('fa-caret-down');
 }
 });
 
 //Rebuild and replace facets with improved facets with checkboxes
 $('#search-facets .facet-label a').removeAttr('title').attr('role','status').after(function() {
 	return $(this).clone().attr('role','label');
 });
 $('#search-facets a[role="status"]').html(' ');
 $('#search-facets a[role="label"]').replaceWith(function() { return this.innerHTML; });
 
 //Change facet checkbox to checked if in use
 $('#search-facets a[title^="Remove facet"]').closest('li').contents().filter(function() {
 	return this.nodeType == 3 && this.nodeValue.trim();
 }).remove();
 $('#search-facets a[title^="Remove facet"]').each(function() {
 $(this).prependTo($(this).siblings('span'));
 });
 $('#search-facets a[title^="Remove facet"]').html(' ');
 
 //Expand sections that have active facets
 $('#search-facets a[title^="Remove facet"]').closest('.contentsToggle').siblings('.viewSwitch').trigger('click');
 
 //Add spinner to show that Koha is doing something after click
 $('#search-facets a[title^="Remove facet"]').on('click', function() {
 $(this).find('i').removeClass('fa-check-square').addClass('fa-spinner fa-spin');
 });
 $('#search-facets a[role="status"]').on('click', function() {
 $(this).find('i').removeClass('fa-square-o').addClass('fa-spinner fa-spin');
 });
//End Revamp Facets
 
==== STAFF Enhanced Suspended Hold Listings (v21.11) ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library / Cooperative Information Network
* Creation Date: 2021-03-12
* Updated Date: 2022-09-12
* Purpose: Show suspended and delayed hold listings more clearly
* Status: Completed
* Version: 21.11
/*Ribbon for Suspended Holds*/
.RibbonRowAdjust {
 height: 50px;
}
.SuspendRibbon, .DelayedRibbon {
 height: 20px;
 line-height: 20px;
 padding-left: 15px;
 position: absolute;
 left: -9px;
 top: 25px;
 text-transform: uppercase;
 color: white;
}
.SuspendRibbon:before, .SuspendRibbon:after, .DelayedRibbon:before, .DelayedRibbon:after {
 content: "";
 position: absolute;
}
.SuspendRibbon:before, .DelayedRibbon:before {
 height: 0;
 width: 0;
 top: -8.5px;
 left: 0.1px;
 border-bottom: 9px solid black;
 border-left: 9px solid transparent;
}
.SuspendRibbon:after, .DelayedRibbon:after {
 height: 0;
 width: 0;
 right: -14.5px;
 border-top: 10px solid transparent;
 border-bottom: 10px solid transparent;
}
.SuspendRibbon { 
 width: 130px;
 background: #f54242;
}
.SuspendRibbon:after{
 border-left: 15px solid #f54242;
}
.DelayedRibbon {
 width: 160px;
 background: #f5ad42;
}
.DelayedRibbon:after{
 border-left: 15px solid #f5ad42;
}
 //Suspended Enhancement
 //Regular Suspension on /cgi-bin/koha/reserve/request.pl
 $('#circ_request button:contains("Unsuspend")').parents('tr').children('td:nth-child(2)').addClass('RibbonRowAdjust').css('position','relative').append(' Suspended');
 //Delayed Suspension on /cgi-bin/koha/reserve/request.pl
 $('#circ_request input[name="reservedate"]').each(function() {
 var fetchDate=new Date($(this).val());
 var fetchDay=('0'+(fetchDate.getDate())).slice(-2);
 var fetchMonth=('0'+(fetchDate.getMonth()+1)).slice(-2);
 var fetchYear=fetchDate.getFullYear();
 var reserveDate=fetchYear+fetchMonth+fetchDay;
 fetchDate=new Date();
 fetchDay=('0'+(fetchDate.getDate())).slice(-2);
 fetchMonth=('0'+(fetchDate.getMonth()+1)).slice(-2);
 fetchYear=fetchDate.getFullYear();
 var todaysDate=fetchYear+fetchMonth+fetchDay;
 if (reserveDate > todaysDate) {
 $(this).parents("tr").children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' After ' + $(this).val() + '');
 }
 });
 
 //Flag reservation dates on each row in --- before making changes to cell.
 $('#holds-table').on( 'init.dt', function () {
 $("#holds-table").find("th:contains('Hold date')").attr("id","DateColumn");
 var dateColumn = $("#DateColumn").index() + 1;
 $("#holds-table").find("td:nth-child(" + dateColumn + ")").addClass("reserveDate");
 $(".reserveDate").each(function() {
 var fetchDate=new Date($(this).text());
 var fetchDay=('0'+(fetchDate.getDate())).slice(-2);
 var fetchMonth=('0'+(fetchDate.getMonth()+1)).slice(-2);
 var fetchYear=fetchDate.getFullYear();
 var reserveDate=fetchYear+fetchMonth+fetchDay;
 fetchDate=new Date();
 fetchDay=('0'+(fetchDate.getDate())).slice(-2);
 fetchMonth=('0'+(fetchDate.getMonth()+1)).slice(-2);
 fetchYear=fetchDate.getFullYear();
 var todaysDate=fetchYear+fetchMonth+fetchDay;
 $(this).attr('todaysdate',todaysDate);
 $(this).attr('reservedate',reserveDate);
 });
 //Regular Suspension on /cgi-bin/koha/members/moremember.pl
 $('a.hold-resume').parents('tr').children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' Suspended');
 //Delayed Suspension on /cgi-bin/koha/members/moremember.pl
 $(".reserveDate").each(function() {
 if ($(this).attr("reservedate") > $(this).attr("todaysdate")) {
 $(this).parents("tr").children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' After ' + $(this).text() + '');
 } 
 });
 });
 //End Suspended Enhancement
==== STAFF Enhanced Suspended/Scheduled Hold Listings (v23.05) ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library / Cooperative Information Network
* Creation Date: 2024-01-12
* Updated Date: 2024-01-13
* Purpose: Show suspended, delayed, and scheduled hold listings more clearly
* Status: Completed
* Version: 23.05
/*Ribbon for Suspended Holds*/
.RibbonRowAdjust {
 height: 50px;
}
.SuspendRibbon, .DelayedRibbon {
 height: 20px;
 line-height: 20px;
 padding-left: 15px;
 position: absolute;
 left: -9px;
 top: 25px;
 text-transform: uppercase;
 color: white;
}
.SuspendRibbon:before, .SuspendRibbon:after, .DelayedRibbon:before, .DelayedRibbon:after {
 content: "";
 position: absolute;
}
.SuspendRibbon:before, .DelayedRibbon:before {
 height: 0;
 width: 0;
 top: -8.5px;
 left: 0.1px;
 border-bottom: 9px solid black;
 border-left: 9px solid transparent;
}
.SuspendRibbon:after, .DelayedRibbon:after {
 height: 0;
 width: 0;
 right: -14.5px;
 border-top: 10px solid transparent;
 border-bottom: 10px solid transparent;
}
.SuspendRibbon { 
 width: 130px;
 background: #f54242;
}
.SuspendRibbon:after{
 border-left: 15px solid #f54242;
}
.DelayedRibbon {
 width: 160px;
 background: #f5ad42;
}
.DelayedRibbon:after{
 border-left: 15px solid #f5ad42;
}
 //Get Today's Date
 const date = new Date();
 let day = ('0'+(date.getDate())).slice(-2);
 let month = ('0'+(date.getMonth()+1)).slice(-2);
 let year = date.getFullYear();
 let GlobalCurrentDate = year+'-'+month+'-'+day;
 let GlobalCompareCurrentDate = year.toString()+month.toString()+day.toString();
 //END Get Today's Date
 //Suspended/Scheduled Hold Enhancements (v23.05) 
 //Suspensions on /cgi-bin/koha/reserve/request.pl
 if ($('#circ_request').length) {
 //All Active Suspensions
 $('tr.suspend').children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' Suspended');
 //Delayed Suspensions
 $('tr.suspend input[id^="suspend_until"][value!=""]').each(function() {
 var DelayDate = new Date($(this).val());
 $(this).parents("tr").children('td:nth-child(1)').children('div.SuspendRibbon').replaceWith(' After ' + DelayDate.toLocaleDateString('en-US') + '');
 });
 //Scheduled Holds
 $('input[name="reservedate"]').each(function() {
 let DisplayReserveDate = new Date($(this).val());
 let reserveDay = ('0'+(DisplayReserveDate.getUTCDate())).slice(-2);
 let reserveMonth = ('0'+(DisplayReserveDate.getUTCMonth()+1)).slice(-2);
 let reserveYear = DisplayReserveDate.getUTCFullYear();
 let CompareReserveDate = reserveYear+reserveMonth+reserveDay;
 DisplayReserveDate = reserveMonth+'/'+reserveDay+'/'+reserveYear;
 if (CompareReserveDate > GlobalCompareCurrentDate) {
 $(this).parents("tr").children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' After ' + DisplayReserveDate + '');
 }
 });
 }
 
 // Suspensions on /cgi-bin/koha/members/circulation.pl and /cgi-bin/koha/members/moremember.pl
 if ($('#circ_circulation, #pat_moremember').length) {
 $('#holds-table').on('init.dt', function () {
 //All Active Suspensions
 $('a.hold-resume').parents('tr').children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' Suspended');
 //Delayed Suspensions
 $('a.hold-resume').parents('tr').each( function() {
 let SuspendUntilDate = $(this).find('strong:contains("suspended")').parent('p').text().match(/\b(\d{2}\/\d{2}\/\d{4})/gm);
 if (SuspendUntilDate) {
 $(this).find('div.SuspendRibbon').replaceWith(' After ' + SuspendUntilDate[0] + '');
 }
 });
 //Scheduled Holds
 $('#holds-table').find('th:contains("Hold date")').attr('id','DateColumn');
 var dateColumn = $('#DateColumn').index() + 1;
 $('#holds-table').find('td:nth-child(' + dateColumn + ')').addClass('reserveDate');
 $('.reserveDate:not(:has(>div))').each(function() {
 let reserveDate = new Date($(this).text());
 let reserveDay = ('0'+(reserveDate.getUTCDate())).slice(-2);
 let reserveMonth = ('0'+(reserveDate.getUTCMonth()+1)).slice(-2);
 let reserveYear = reserveDate.getUTCFullYear();
 reserveDate = reserveYear+reserveMonth+reserveDay;
 if (reserveDate > GlobalCompareCurrentDate) {
 $(this).parents("tr").children('td:nth-child(1)').addClass('RibbonRowAdjust').css('position','relative').append(' After ' + $(this).text() + '');
 }
 });
 });
 }
 //END Suspended/Scheduled Hold Enhancements
==== Make purchase suggestion links default to all libraries ====
* Developer: Lucas Gass
* Purpose: Make purchase suggestion links default to all libraries
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Any
 
function suggestionLinks (selector) {
 let full_url = window.location.origin + $(`${selector}`).attr('href');
 let suggestion_url = new URL( full_url );
 let all_branches_path = suggestion_url.pathname + '?branchcode=__ANY__' + suggestion_url.hash;
 $(`${selector}`).attr('href' , all_branches_path ); 
}
if ( $('#main_intranet-main').length && $('#suggestions_pending a').length ) {
 suggestionLinks('#suggestions_pending a');
}
if ( $('#acq_acqui-home').length && $('#acqui_acqui_home_suggestions p a').length ) {
 suggestionLinks('#acqui_acqui_home_suggestions p a');
}
if ( $('#navmenulist').length ) { 
 suggestionLinks('a[href*="/cgi-bin/koha/suggestion/suggestion.pl"]');
}
 
----
==== Bad E-mail Handler ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds buttons next to the primary e-mail field in memberentry.pl to quickly deal with bad e-mails. Will remove or leave the e-mail in the field, depending on the situation, and create a restriction on the account, copying the address in a message explaining the situation with that address.
* Creation Date: 6/10/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 21.05
* Breadcrumbs: Home › Patrons - Edit
 //Expand debarred comment text box
 $('#pat_memberentrygen #debarred_comment').after('<textarea id="debarred_comment" rows="3" cols="100" name="debarred_comment" class="noEnterSubmit" />').remove();
 //Bad E-mail Process
 if($('#pat_memberentrygen #email').val() !=) {
 $('#email').after('  <button id="EmailDoesNotExist" type="button">Doesn\'t exist</button>  <button id="EmailFull" type="button">Mailbox full</button>  <button id="EmailBlocked" type="button">E-mail blocked/disabled</button>');
 }
 $('#pat_memberentrygen #EmailDoesNotExist').on('click', function() {
 $('#restrictions_lgd').click();
 $('#add_manual_restriction').click();
 $('#debarred_comment').val($('#email').val() + ' removed from account. Server reports this address does not exist. Please update patron contact information.').focus().change();
 $('#email').val();
 });
 $('#pat_memberentrygen #EmailFull').on('click', function() {
 $('#restrictions_lgd').click();
 $('#add_manual_restriction').click();
 $('#debarred_comment').val('Server reports mailbox ' + $('#email').val() + ' is full. We cannot send e-mails to this account. Patron needs to address the issue with this address or provide a working address.').focus().change();
 });
 $('#pat_memberentrygen #EmailBlocked').on('click', function() {
 $('#restrictions_lgd').click();
 $('#add_manual_restriction').click();
 $('#debarred_comment').val('Server reports mailbox ' + $('#email').val() + ' is blocking our notifications or is disabled. We cannot send e-mails to this account. Patron needs to address the issue with this address or provide a working address.').focus().change();
 });
 //END Bad E-mail Process
	
==== Add notes to add record page and edit record page ====
* Developer: George Williams (NEKLS / Next search catalog)
* Purpose: Adds descriptions to the tabs on the Add/Edit record pages
* Creation Date: 6/10/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Breadcrumbs: Home › Cataloging › Add MARC record -and- Home › Cataloging › Editing TITLE
===== 19.05 version =====
* Version: Developed on 19.05 / tested and working on 20.05
//BEGIN Add labels to Marc tabs on add record page and edit record page
 $(".toolbar-tabs-container a[href='#tab0XX']").append("Control and coded fields");
 $("#tab0XX h3").append(" - Control and coded fields");
 $(".toolbar-tabs-container a[href='#tab1XX']").append("Main entry");
 $("#tab1XX h3").append(" - Main entry");
 $(".toolbar-tabs-container a[href='#tab2XX']").append("Title and edition");
 $("#tab2XX h3").append(" - Title and edition");
 $(".toolbar-tabs-container a[href='#tab3XX']").append("Physical description");
 $("#tab3XX h3").append(" - Physical description");
 $(".toolbar-tabs-container a[href='#tab4XX']").append("Series");
 $("#tab4XX h3").append(" - Series");
 $(".toolbar-tabs-container a[href='#tab5XX']").append("Notes");
 $("#tab5XX h3").append(" - Notes");
 $(".toolbar-tabs-container a[href='#tab6XX']").append("Subject access");
 $("#tab6XX h3").append(" - Subject access");
 $(".toolbar-tabs-container a[href='#tab7XX']").append("Added and linking entry");
 $("#tab7XX h3").append(" - Added and linking entry");
 $(".toolbar-tabs-container a[href='#tab8XX']").append("Series added entryand electronic access");
 $("#tab8XX h3").append(" - Series added entry and electronic access");
 $(".toolbar-tabs-container a[href='#tab9XX']").append("Koha related");
 $("#tab9XX h3").append(" - Koha related");
	
===== 22.11 version =====
* Version: Updated for Koha 22.11
//Home > Cataloging > Add MARC record - (/cataloguing/addbiblio.pl)
//Home > Cataloging > Editing [biblio.title - etc.] (Record number [biblio.biblionumber]) - (/cataloguing/addbiblio.pl?biblionumber= [biblio.biblionumber])
 //BEGIN Add labels to Marc tabs
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab0XX_panel"]').append('Control and coded fields');
 $('#cat_addbiblio #tab0XX_panel h3').append(' - Control and coded fields');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab1XX_panel"]').append('Main entry');
 $('#cat_addbiblio #tab1XX_panel h3').append(' - Main entry');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab2XX_panel"]').append('Title and edition');
 $('#cat_addbiblio #tab2XX_panel h3').append(' - Title and edition');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab3XX_panel"]').append('Physical description');
 $('#cat_addbiblio #tab3XX_panel h3').append(' - Physical description');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab4XX_panel"]').append('Series');
 $('#cat_addbiblio #tab4XX_panel h3').append(' - Series');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab5XX_panel"]').append('Notes');
 $('#cat_addbiblio #tab5XX_panel h3').append(' - Notes');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab6XX_panel"]').append('Subject access');
 $('#cat_addbiblio #tab6XX_panel h3').append(' - Subject access');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab7XX_panel"]').append('Added and linking entry');
 $('#cat_addbiblio #tab7XX_panel h3').append(' - Added and linking entry');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab8XX_panel"]').append('Series added entryand electronic access');
 $('#cat_addbiblio #tab8XX_panel h3').append(' - Series added entry and electronic access');
 $('#cat_addbiblio .toolbar-tabs-container a[href="#tab9XX_panel"]').append('Koha related');
 $('#cat_addbiblio #tab9XX_panel h3').append(' - Koha related');
==== Automatic Library Setting ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / CIN) (Passed on from unknown author)
* Purpose: Automatically default the branches dropdown in reports to the library you are logged in as.
* Creation Date: 6/23/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05 / tested and working on 20.05
//Preset library dropdowns
var library_name = $.trim($('#user-menu span.logged-in-branch-name:first').text());
$('#rep_guided_reports_start').find('option').filter(function(index) {
 return library_name === $(this).text();
}).attr("selected", "selected");
//End Preset
	
==== Blocking Checkouts - Example 1 ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / CIN)
* Purpose: Block checkouts in circulation based on patron categories
* Creation Date: 8/14/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 19.05 / tested and working on 20.05
* Notes: Example shows 2 categories (SELF and EONLY) that will be blocked from checkout. Replace with the categories of your choice.
 //Disable check out for special accounts on circulation.pl
 if ($('#circ_circulation li.patroncategory:contains("(SELF)"),#circ_circulation li.patroncategory:contains("(EONLY)")').length) {
 $('li.patroncategory:contains("(SELF)"),#circ_circulation li.patroncategory:contains("(EONLY)")').css('color','red');
 $('#mainform').replaceWith('Cannot check out!This patron category cannot checkout items.');
 }
 //END Disable check out for special accounts on circulation.pl
	
==== Blocking Checkouts - Example 2 ====
* Developer: George Williams (Northeast Kansas Library System/ Next search catalog)
* Purpose: Prevents staff from overriding a blocked checkout if the borrower is in a specified category
* Creation Date: 8/1/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 20.05
* Notes: Change "WORD" to match a word or phrase that is unique to the borrower category description for which you want to block overrides
* Breadcrumbs: Home › Circulation › Checkouts › PATRONNAME
//BEGIN block circulation overrides if categories.description contains a specific word
 $('#circ_circulation').each(function() {
 if ($(".patroncategory:contains(WORD)", this).length && $("#circ_needsconfirmation", this).length) {
 $('.patroncategory').css('background', 'pink').wrap('');
 $('#circ_needsconfirmation .approve').attr('disabled', 'disabled');
 $('#circ_needsconfirmation .deny').after('You cannot check out physical items to a borrower with this borrower category under any circumstances.');
 alert('Borrowers in this category are not allowed to check out these materials under any circumstances');
 }
 });
==== Photo ID Reader ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Add the ability to scan a photo ID (USA) and import basic info into new patron form.
* Creation Date: 9/20/2021
* Update Date: 9/13/2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 20.05 / Works with 21.05 / Updated for 22.05
* Notes: Currently works with Chrome and Firefox, and works for the Honeywell 7580g, Datalogic QD2430, and Zebra Symbol DS4308 scanners. Scanner must be a 2D scanner that can read PDF417 barcodes. Some debugging is in place in the console log to determine symbols being used in place of linefeeds. These symbols must be caught and replaced in order to work with your scanner (see section that mentions the above scanners for more details). There is also an area defined in the function that corrects issues found in IDs. For example, in this code, our city "Coeur d'Alene" appears in the barcode as "Coeur D Al". You can use similar code to correct other anomalies. Contact me if you have questions or need help figuring out how to get a scanner to work. UPDATE: Returns focus to surname field when done.
 //Import data from Photo ID (v22.05)
 $('#pat_memberentrygen #toolbar').append('<button class="btn btn-default toggler" id="btnScanPhotoID" name="scan" style="margin-right: 0px; margin-right: 5px;"> Scan Photo ID</button>');
 $('#pat_memberentrygen').append('<form id="formID" method="post" action="submit" onsubmit="return false;">Scan Photo ID<textarea id="inputPhotoIDData" rows="1" cols="1" style="margin-left: -400px;"></textarea><button id="btnPhotoIDClose" data-dismiss="modal" aria-hidden="true" class="btn"> Cancel</button></form>');
 function ProcessPhotoID() {
 //Close modal
 $('#PhotoIDModal').modal('hide');
 $('#PhotoIDModal').on('hidden.bs.modal', function () {
 $('#msgScan').html('Scan Photo ID now...');
 });
 //Separate information into array
 console.log($('#inputPhotoIDData').val());
 var IDSegments = $('#inputPhotoIDData').val().split('\n');
 
 function toTitleCase(str)
 //NEED TO MAKE THIS FUNCTION OPTIONAL
 {
 return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
 }
 //Fix city names that are incomplete
 function FixCity(str) {
 if (str == 'Coeur D Al') {
 return 'Coeur d\'Alene';
 } else {
 return str;
 }
 }
 //Process data
 if (IDSegments != ) {
 var usrLastName,usrFirstName,usrBirth,mStop,usrMailingAddress,usrMailingCity,usrMailingState,usrMailingZip,usrPhysicalAddress,usrPhysicalCity,usrPhysicalState,usrPhysicalZip;
 for (i = 0; i < IDSegments.length; ++i) {
 if (IDSegments[i].startsWith('DCS')) {
 usrLastName = toTitleCase(IDSegments[i].slice(3));
 if (usrLastName.substring(0,2) == 'Mc') {
 usrLastName = 'Mc' + usrLastName.substring(2,3).toUpperCase() + usrLastName.substring(3);
 }
 if (usrLastName.substring(0,3) == 'Mac') {
 $('label[for="surname"]').siblings('span.required').after(' Check capitalization');
 }
 }
 if (IDSegments[i].startsWith('DAC')) {
 usrFirstName = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAD')) {
 usrFirstName += ' ' + toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DBB')) {
 usrBirth = IDSegments[i].slice(3);
 usrBirth = usrBirth.substring(0,2) + '/' + usrBirth.substring(2,4) + '/' + usrBirth.substring(4,8);
 }
 if (IDSegments[i].startsWith('DAG')) {
 usrMailingAddress = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAH')) {
 usrMailingAddress += ' ' + toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAI')) {
 usrMailingCity = FixCity(toTitleCase(IDSegments[i].slice(3)));
 }
 if (IDSegments[i].startsWith('DAJ')) {
 usrMailingState = IDSegments[i].slice(3);
 }
 if (IDSegments[i].startsWith('DAK')) {
 usrMailingZip = toTitleCase(IDSegments[i].slice(3,8));
 }
 if (IDSegments[i].startsWith('DAL')) {
 usrPhysicalAddress = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAM')) {
 usrPhysicalAddress += ' ' + toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAN')) {
 usrPhysicalCity = FixCity(toTitleCase(IDSegments[i].slice(3)));
 }
 if (IDSegments[i].startsWith('DAO')) {
 usrPhysicalState = IDSegments[i].slice(3);
 }
 if (IDSegments[i].startsWith('DAP')) {
 usrPhysicalZip = toTitleCase(IDSegments[i].slice(3,8));
 }
 }
 //Copy data to form fields
 $('#surname').val(usrLastName).css('background-color','yellow');
 $('#firstname').val(usrFirstName).css('background-color','yellow');
 $('#dateofbirth').val(usrBirth).css('background-color','yellow');
 $('#address').val(usrMailingAddress).css('background-color','yellow');
 $('#city').val(usrMailingCity).css('background-color','yellow');
 $('#state').val(usrMailingState).css('background-color','yellow');
 $('#zipcode').val(usrMailingZip).css('background-color','yellow');
 //If secondary address doesn't exist, it usually starts with @
 if (typeof usrPhysicalAddress != 'undefined') {
 $('#B_address').val(usrPhysicalAddress).css('background-color','yellow');
 $('#B_city').val(usrPhysicalCity).css('background-color','yellow');
 $('#B_state').val(usrPhysicalState).css('background-color','yellow');
 $('#B_zipcode').val(usrPhysicalZip).css('background-color','yellow');
 }
 $('#surname').focus();
 }
 }
 $('#pat_memberentrygen #btnScanPhotoID').on('click', function() {
 var TimerActive = 0; //Reset timer
 var ScanActive = 0;
 $('#inputPhotoIDData').val();
 $('#msgScan').html('Scan Photo ID now...');
 $('#PhotoIDModal').modal('show');
 $('#PhotoIDModal').on('shown.bs.modal', function () {
 $('#inputPhotoIDData').focus();
 $('#inputPhotoIDData').unbind();
 $('#inputPhotoIDData').keydown(function(event){
 var code = (event.keyCode || event.which);
 if(event.keyCode == 13) {
 event.preventDefault();
 return false;
 }
 if (code == 120) { //Disable F9 so Firefox doesn't launch reader
 return false;
 }
 });
 $('#inputPhotoIDData').on('keyup', function() {
 if (ScanActive == 0) { //Set Processing Message
 $('#msgScan').html('Processing... please wait.<svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px" viewBox="0 0 105 105" fill="#000"><circle cx="12.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="0s" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="12.5" cy="52.5" r="12.5" fill-opacity=".5"><animate attributeName="fill-opacity" begin="100ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="52.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="300ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="52.5" cy="52.5" r="12.5"><animate attributeName="fill-opacity" begin="600ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="92.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="800ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="92.5" cy="52.5" r="12.5"><animate attributeName="fill-opacity" begin="400ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="12.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="700ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="52.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="500ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="92.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="200ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle></svg>');
 //Processing Graphic from https://github.com/SamHerbert/SVG-Loaders/tree/master/svg-loaders
 ScanActive = 1;
 }
 if (TimerActive == 0) { //Time's up on input
 TimerActive = 1;
 setTimeout(function(){
 console.log('Entire block of data: ');
 console.log($('#inputPhotoIDData').val());
 var checkStart = $('#inputPhotoIDData').val().startsWith('@'); //Check if beginning of barcode starts with @
 if (checkStart) { //Was this a valid barcode?
 ProcessPhotoID();
 } else {
 $('#msgScan').html('That doesn\'t look like a Photo ID. Try again.');
 $('#inputPhotoIDData').val();
 TimerActive = 0;
 ScanActive = 0;
 }
 }, 5000); 
 }
 console.log(event.key);
 //Convert to linefeed - ArrowDown for Honeywell 7580g / ArrowRight for Datalogic QD2430 / Alt for Zebra Symbol DS4308
 if ((event.key == 'ArrowDown') || (event.key == 'ArrowRight') || (event.key == 'Alt')) {
 $('#inputPhotoIDData').val($('#inputPhotoIDData').val() + '\n');
 }
 });
 });
 });
 //END Import data from Photo ID 
==== Photo ID Reader (v22.11) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Add the ability to scan a photo ID (USA) and import basic info into new patron form.
* Creation Date: 9/20/2021
* Update Date: 7/25/2023
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.11
* Notes: Currently works with Chrome and Firefox, and works for the Honeywell 7580g, Datalogic QD2430, Star Micronics BSH-HR2081BT, and Zebra Symbol DS4308 scanners. Scanner must be a 2D scanner that can read PDF417 barcodes. Some debugging is in place in the console log to determine symbols being used in place of linefeeds. These symbols must be caught and replaced in order to work with your scanner (see section that mentions the above scanners for more details). There is also an area defined in the function that corrects issues found in IDs. For example, in this code, our city "Coeur d'Alene" appears in the barcode as "Coeur D Al". You can use similar code to correct other anomalies. Contact me if you have questions or need help figuring out how to get a scanner to work. This version is only for 22.11, which includes the flat picker for birth dates and the new middle name field. May work on Androids, but current tests show that iOS devices are not working. PDF417 will not transmit properly to web form field.
 //Import data from Photo ID (v22.11)
 $('#pat_memberentrygen #toolbar').append('<button class="btn btn-default toggler" id="btnScanPhotoID" name="scan" style="margin-right: 0px; margin-right: 5px;"> Scan Photo ID</button>');
 $('#pat_memberentrygen').append('<form id="formID" method="post" action="submit" onsubmit="return false;">Scan Photo ID<textarea id="inputPhotoIDData" rows="1" cols="1" style="margin-left: -400px;"></textarea><button id="btnPhotoIDClose" data-dismiss="modal" aria-hidden="true" class="btn"> Cancel</button></form>');
 function ProcessPhotoID() {
 //Close modal
 $('#PhotoIDModal').modal('hide');
 $('#PhotoIDModal').on('hidden.bs.modal', function() {
 $('#msgScan').html('Scan Photo ID now...');
 });
 //Separate information into array
 console.log($('#inputPhotoIDData').val());
 var IDSegments = $('#inputPhotoIDData').val().split('\n');
 
 function toTitleCase(str)
 //NEED TO MAKE THIS FUNCTION OPTIONAL
 {
 return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
 }
 //Fix city names that are incomplete
 function FixCity(str) {
 if (str == 'Coeur D Al') {
 return 'Coeur d\'Alene';
 } else {
 return str;
 }
 }
 //Process data
 if (IDSegments != ) {
 var usrLastName,usrFirstName,usrMiddleName,usrBirth,mStop,usrMailingAddress,usrMailingCity,usrMailingState,usrMailingZip,usrPhysicalAddress,usrPhysicalCity,usrPhysicalState,usrPhysicalZip;
 for (i = 0; i < IDSegments.length; ++i) {
 if (IDSegments[i].startsWith('DCS')) {
 usrLastName = toTitleCase(IDSegments[i].slice(3));
 if (usrLastName.substring(0,2) == 'Mc') {
 usrLastName = 'Mc' + usrLastName.substring(2,3).toUpperCase() + usrLastName.substring(3);
 }
 if (usrLastName.substring(0,3) == 'Mac') {
 $('label[for="surname"]').siblings('span.required').after(' Check capitalization');
 }
 }
 if (IDSegments[i].startsWith('DAC')) {
 usrFirstName = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAD')) {
 usrMiddleName = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DBB')) {
 usrBirth = IDSegments[i].slice(3);
 usrBirth = usrBirth.substring(0,2) + '/' + usrBirth.substring(2,4) + '/' + usrBirth.substring(4,8);
 }
 if (IDSegments[i].startsWith('DAG')) {
 usrMailingAddress = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAH')) {
 usrMailingAddress += ' ' + toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAI')) {
 usrMailingCity = FixCity(toTitleCase(IDSegments[i].slice(3)));
 }
 if (IDSegments[i].startsWith('DAJ')) {
 usrMailingState = IDSegments[i].slice(3);
 }
 if (IDSegments[i].startsWith('DAK')) {
 usrMailingZip = toTitleCase(IDSegments[i].slice(3,8));
 }
 if (IDSegments[i].startsWith('DAL')) {
 usrPhysicalAddress = toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAM')) {
 usrPhysicalAddress += ' ' + toTitleCase(IDSegments[i].slice(3));
 }
 if (IDSegments[i].startsWith('DAN')) {
 usrPhysicalCity = FixCity(toTitleCase(IDSegments[i].slice(3)));
 }
 if (IDSegments[i].startsWith('DAO')) {
 usrPhysicalState = IDSegments[i].slice(3);
 }
 if (IDSegments[i].startsWith('DAP')) {
 usrPhysicalZip = toTitleCase(IDSegments[i].slice(3,8));
 }
 }
 //Copy data to form fields
 $('#surname').val(usrLastName).css('background-color','yellow');
 $('#firstname').val(usrFirstName).css('background-color','yellow');
 $('#middle_name').val(usrMiddleName).css('background-color','yellow');
 $('span.flatpickr_wrapper input').val(usrBirth).css('background-color','yellow');
 $('#address').val(usrMailingAddress).css('background-color','yellow');
 $('#city').val(usrMailingCity).css('background-color','yellow');
 $('#state').val(usrMailingState).css('background-color','yellow');
 $('#zipcode').val(usrMailingZip).css('background-color','yellow');
 //If secondary address doesn't exist, it usually starts with @
 if (typeof usrPhysicalAddress != 'undefined') {
 $('#B_address').val(usrPhysicalAddress).css('background-color','yellow');
 $('#B_city').val(usrPhysicalCity).css('background-color','yellow');
 $('#B_state').val(usrPhysicalState).css('background-color','yellow');
 $('#B_zipcode').val(usrPhysicalZip).css('background-color','yellow');
 }
 $('span.flatpickr_wrapper input').focus();
 $('#surname').focus();
 }
 }
 $('#pat_memberentrygen #btnScanPhotoID').on('click', function() {
 var TimerActive = 0; //Reset timer
 var ScanActive = 0;
 $('#inputPhotoIDData').val();
 $('#msgScan').html('Scan Photo ID now...');
 $('#PhotoIDModal').modal('show');
 $('#PhotoIDModal').on('shown.bs.modal', function () {
 $('#inputPhotoIDData').focus();
 $('#inputPhotoIDData').unbind();
 $('#inputPhotoIDData').keydown(function(event){
 var code = (event.keyCode || event.which);
 if(event.keyCode == 13) {
 event.preventDefault();
 return false;
 }
 if (code == 120) { //Disable F9 so Firefox doesn't launch reader
 return false;
 }
 });
 $('#inputPhotoIDData').on('keyup', function() {
 if (ScanActive == 0) { //Set Processing Message
 $('#msgScan').html('Processing... please wait.<svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px" viewBox="0 0 105 105" fill="#000"><circle cx="12.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="0s" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="12.5" cy="52.5" r="12.5" fill-opacity=".5"><animate attributeName="fill-opacity" begin="100ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="52.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="300ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="52.5" cy="52.5" r="12.5"><animate attributeName="fill-opacity" begin="600ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="92.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="800ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="92.5" cy="52.5" r="12.5"><animate attributeName="fill-opacity" begin="400ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="12.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="700ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="52.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="500ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle><circle cx="92.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="200ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite"/></circle></svg>');
 //Processing Graphic from https://github.com/SamHerbert/SVG-Loaders/tree/master/svg-loaders
 ScanActive = 1;
 }
 if (TimerActive == 0) { //Time's up on input
 TimerActive = 1;
 setTimeout(function(){
 console.log('Entire block of data: ');
 console.log($('#inputPhotoIDData').val());
 var checkStart = $('#inputPhotoIDData').val().startsWith('@'); //Check if beginning of barcode starts with @
 if (checkStart) { //Was this a valid barcode?
 ProcessPhotoID();
 } else {
 $('#msgScan').html('That doesn\'t look like a Photo ID. Try again.');
 $('#inputPhotoIDData').val();
 TimerActive = 0;
 ScanActive = 0;
 }
 }, 5000); 
 }
 console.log(event.key);
 //Convert to linefeed - ArrowDown for Honeywell 7580g and Star Micronics BSH-HR2081BT / ArrowRight for Datalogic QD2430 / Alt for Zebra Symbol DS4308 // Enter for Zebra DS9308
 if ((event.key == 'ArrowDown') || (event.key == 'ArrowRight') || (event.key == 'Alt') || (event.key == 'Enter')) {
 $('#inputPhotoIDData').val($('#inputPhotoIDData').val() + '\n');
 }
 });
 });
 });
 //END Import data from Photo ID 
==== Quick Credential Reset ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Reset credentials with some quick set buttons on member-password.pl.
* Creation Date: 9/29/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 20.05
* Notes: This example resets the username to match the patron's card number, and the password to match the patron's last name in ALL CAPS.
 //Quick Credential Reset
 if( $('#pat_member-password').length ) {
 //Create buttons
 $('#newuserid').after('  <button id="ResetDefaults" type="button">Reset credentials to default</button>');
 $('#newpassword').after('  <button id="ResetPassword" type="button">Reset password only</button>');
 var usrBorrowerNumber = $('#borrowernumber').val();
 //Get patron data
 var url = '/api/v1/patrons?patron_id=' + usrBorrowerNumber;
 let patronInfoArr;
 $.ajax({
 async: false,
 url: url,
 success: function(data) {
 patronInfoArr = [data[0].firstname, data[0].surname, data[0].cardnumber];
 }
 });
 //Set button functions
 $('#ResetDefaults').on('click', function() {
 $('#newuserid').val(patronInfoArr[2]);
 $('#newpassword,#newpassword2').val(patronInfoArr[1].toUpperCase());
 });
 $('#ResetPassword').on('click', function() {
 $('#newpassword,#newpassword2').val(patronInfoArr[1].toUpperCase());
 });
 }
 //END Quick Credential Reset
==== Easy fill userid and password buttons ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Fill in passwords and userids on memberentry.pl and member-password.pl
* Creation Date: 10/05/2021
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 20.05
* Notes: This jQuery creates usernames and passwords based on fields already filled in on memberentry.pl and does the same on member-password.pl through the rest api.
//BEGIN Easy fill username options for add/edit borrower
//creates buttons
$("#pat_memberentrygen #userid").parent().append('<label>Usernameoptions:</label><button class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="true">Username options </button><a id="clearid">Delete current username</a><a id="cardid">Use library card number for username</a><a id="nameid">Use firstname.lastname for username (Next default)</a>');
//adds function to buttons
$("#cardid").click(function() {
 $("#entryform #userid").val($("#entryform #cardnumber").val()).focus();
});
$("#nameid").click(function() {
 $("#entryform #userid").val($("#entryform #firstname").val().toLowerCase().replace(/[^a-zA-Z 0-9]+/g, "").replace(" ", "") + '.' + $("#entryform #surname").val().toLowerCase().replace(/[^a-zA-Z 0-9]+/g, "").replace(" ", "")).focus();
});
$("#clearid").click(function() {
 $("#entryform #userid").val("");
});
//BEGIN Easy fill password buttons for add/edit borrower
//creates buttons
$("#pat_memberentrygen #password2").parent().parent().append('<label>Passwordoptions:</label><button class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="true">Password options </button><a id="deletepass">Clear current password data</a><a id="lnamepass">Use last name for password (case sensitive)</a><a id="phonepass">Use last 4 digits of phone for password</a><a id="townpass">Use name of town in lowercase letters</a><a id="birthpass">Use birthdate in format MMDDYYYY (no / marks)</a>');
//adds function to buttons
$("#phonepass").click(function() {
 $("#entryform #password, #entryform #password2").val($("#entryform #phone").val().slice(-4));
});
$("#lnamepass").click(function() {
 $("#entryform #password, #entryform #password2").val($("#entryform #surname").val());
});
$("#townpass").click(function() {
 $("#entryform #password, #entryform #password2").val($("#entryform #city").val().toLowerCase());
});
$("#birthpass").click(function() {
 $("#entryform #password, #entryform #password2").val($("#entryform #dateofbirth").val().replace(/\//g, ));
});
$("#deletepass").click(function() {
 $("#entryform #password, #entryform #password2").val("");
});
//BEGIN Easy fill buttons for resetting username or password on change password page
if ($('#pat_member-password').length) {
 //creates buttons
 $('#newuserid').after('<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="true" >Username options </button><a id="cardid_refill">Use library card number for username</a><a id="nameid_refill">Use firstname.lastname for username (Next default)</a>');
 $('#newpassword2').after('<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="true">Password options </button><a id="lnamepass_refill">Use last name for password (case sensitive)</a><a id="phonepass_refill">Use last 4 digits of phone for password</a><a id="townpass_refill">Use name of town in lowercase letters</a><a id="birthpass_refill">Use birthdate in format MMDDYYYY (no / marks)</a>');
 //gets borrower number from page
 var usrBorrowerNumber = $('#borrowernumber').val();
 //gets patron data from api
 var url = '/api/v1/patrons?patron_id=' + usrBorrowerNumber;
 let patronInfoArr;
 $.ajax({
 async: false,
 url: url,
 success: function(data) {
 patronInfoArr = [data[0].firstname, data[0].surname, data[0].cardnumber, data[0].phone, data[0].city, data[0].date_of_birth];
 }
 });
 
 //adds function to buttons
 $('#nameid_refill').on('click', function() {
 $('#newuserid').val(patronInfoArr[0].toLowerCase() + "." + patronInfoArr[1].toLowerCase());
 });
 $('#cardid_refill').on('click', function() {
 $('#newuserid').val(patronInfoArr[2]);
 });
 $('#lnamepass_refill').on('click', function() {
 $('#newpassword,#newpassword2').val(patronInfoArr[1]);
 });
 $('#phonepass_refill').on('click', function() {
 $('#newpassword,#newpassword2').val(patronInfoArr[3].slice(-4));
 });
 $('#townpass_refill').on('click', function() {
 $('#newpassword,#newpassword2').val(patronInfoArr[4].toLowerCase());
 });
 $('#birthpass_refill').on('click', function() {
 $('#newpassword,#newpassword2').val((patronInfoArr[5].slice(5, 7)) + (patronInfoArr[5].slice(8, 10)) + (patronInfoArr[5].slice(0, 4)));
 });
}
//adds hover function so you don't have to click a button to open it and again to trigger the function
$('.ezfill').mouseover(function() {
 $(this).addClass("open");
});
==== Match the new "Allowed pickup location" dropdown to the logged in library ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Set 
* Creation Date: 
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Developed on 21.05
* Notes: Koha 21.05 has a new dropdown on request.pl called "Allowed pickup locations" that is set by default to the item's home library. This means that when you place an item specific request on an item, you must select the pickup location from the "Allowed pickup locations" dropdown unless you want to pick up the item at the item's home library. This code sets the pickup location to match the default "Pickup at:" location that is set for any "Hold next available item:" request.
//BEGIN Set item specific request dropdowns to current library
 var reqcode = $(".logged-in-branch-code").first().text().trim();
 var reqname = $(".logged-in-branch-name:first").text().trim();
 $('#circ_request #hold-request-form #requestspecific tr td:last-child select option').val(reqcode);
 $('#circ_request #hold-request-form #requestspecific tr td:last-child select option').text(reqname);
==== Highlight titles with holds in the search results table ====
* Developer: Barbara Glassford Johnson (Bedford Public Library)
* Creation Date: 10/30/2021
* Purpose: Highlight holds so that they are easier to spot - those with any value of 1 or more have css applied to them
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
 
//BEGIN highlight titles with holds in search results list on search.pl//
 if (window.location.href.indexOf("search.pl") > -1) {
 $('[id^="reserve_"]:not(:contains("Holds (0)"))').css({"color": "#9e0000", "font-weight": "700"});
 }
 
==== Remove navigation bar from reports printout ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Creation Date: 1/20/2022
* Purpose: Remove the navigation bar from any report results you print
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
 
 //Hide menus when printing report results (v21.05)
 $('#rep_guided_reports_start .navbar').addClass('hidden-print');
 //END Hide menus when printing report results
 
==== Delay displaying tabs until built ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Creation Date: 1/20/2022
* Purpose: Hide tables with tabs until the tabs are built and the page is done loading - instead of watching page being built with the list first and then being converted into tabs.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
 
 //Reveal these tables after tabs finished loading (see CSS) (v21.05)
 $('#rep_guided_reports_start #tabs,#circ_circulation #patronlists,#acq_suggestion #suggestiontabs').css('display','block'); 
 //END Reveal these tables after tabs finished loading (see CSS)
 
 
 /* Hide these tables until tabs finished loading (v21.05) */
 #rep_guided_reports_start #tabs, #circ_circulation #patronlists, #acq_suggestion #suggestiontabs {
 display: none;
 }
 
==== Change text of options on "Print" dropdown ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Change the text of the dropdown options on the "Print" button on the checkout page
* Creation Date: 2018
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: Staff often can't remember the difference between "Print summary," "Print slip," "Print quick slip" etc. This changes the text to make them more descriptive for staff at my libraries. The html could be customized to fit whatever works for your library.
//BEGIN rename print drop-downs
 $('#toolbar #printsummary').html('Full page-summary');
 $('#toolbar #printslip').html('Receipt-all checkouts');
 $('#toolbar #printquickslip').html("Receipt-today's checkouts");
 $('#toolbar #print_overdues').html('Full page-overdue items');
 $('#toolbar #printcheckinslip').html("Reciept-today's checkins");
==== Change receipt printed by icon on checkout page ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Redirect the print icon on the checkout page from "Print slip" to "Print quick slip."
* Creation Date: 2018
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: Staff at my library wanted the printer icon on the checkouts page to activate the "Print quick slip" receipt instead of the "Print slip" receipt.
//BEGIN re-tool print and clear icon to do quick slip
 $('#printclearscreen').hide();
 $('#clearscreen').prepend('<a href="#" title="Print today\'s checkouts and clear screen"></a>');
 $("#circ_circulation #qprintclearscreen").click(function() {
 printx_window("qslip");
 window.location.replace("/cgi-bin/koha/circ/circulation.pl");
 });
==== Highlight print buttons in circulation modals ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Make print buttons on modals stand out during circulation for improved workflow.
* Creation Date: 2/10/2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: I've included an alternative CSS version. Don't need to use both.
 //Check in alert enhancements (v21.05)
 $('#hold-found1 button.print,#hold-found2 button.print, #return1 button.openWin, #return2 button.openWin, #item-transfer-modal button.openWin, #wrong-transfer-modal button.openWin').css('background-image','none').css('background-color','#69a268 !important');
 //END Check in alert enhancements
/* Check in alert enhancements (v21.05) */
#hold-found1 button.print,#hold-found2 button.print, #return1 button.openWin, #return2 button.openWin, #item-transfer-modal button.openWin, #wrong-transfer-modal button.openWin {
	background-image: none;
 	background-color: #69a268 !important;
}
==== Add html to the "No item barcode found" message ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Add html to the "No item barcode found" message on returns.pl
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: With different policies at 50+ libraries I wanted to add a "Best practices" document and some report links to help improve consistency with procedures to the "No item barcode found" message on returns.pl
//BEGIN add content to "No item with barcode" message
 //Wraps a span around the message
 $('.problem.ret_badbarcode').contents().filter(function() {
 return this.nodeType == Node.TEXT_NODE;
 }).wrap("");
 //Isolates the barcode number in the message
 var noibcstring = $('.ibctext').text();
 var noibc = noibcstring.substr(noibcstring.indexOf(": ") + 1).trim()
 //Appends message to the "No item with barcode" message
 //Replace "http://www.koha-us.org" with the website of your best practices document
 //Replace "REPORT_NUMBER" with the numbers of the reports you want available for staff when they see this message
 $('.static_checkin_messages .dialog.alert.audio-alert-warning .problem.ret_badbarcode:contains("No item with barcode:")').append('<a href="http://www.koha-us.org" target="_blank">What to do when \"No item with barcode\" occurs at checkin - best practices document</a><a href="/cgi-bin/koha/reports/guided_reports.pl?reports=REPORT_NUMBER&phase=Run+this+report¶m_name=Enter+barcode+number&sql_params=' + noibc + '&limit=500" target="_blank">Search for this barcode number in REPORT_NUMBER 1</a><a href="/cgi-bin/koha/reports/guided_reports.pl?phase=Run+this+report&reports=REPORT_NUMBER&sql_params=' + noibc + '&limit=50" target="_blank">Search for this barcode number in REPORT_NUMBER 2</a>');
 
==== Remove the trailing / from titles ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Remove the trailing / at the end of titles in search results if there is nothing after it on the same line (author/contributor)
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: We removed the redundant author and contributor info on the title line in results. Since the / is commonly included in marc data, it remains and is unnecessary. You can find similar code for the OPAC below. This example does not include the record detail page, but could easily encompass that page as well. Consult the XSLTs for removal of redundant info on these pages.
 //Remove trailing '/' from title in results (v21.05)
 if ( $('#catalog_results').length) {
 //$('.title_resp_stmt').remove(); This line is needed if you didn't remove it with the XSLT.
 $('.title').each( function() {
 var title_text = $(this).text();
 var title_lastChar = title_text.charAt(title_text.length-2);
 if ( title_lastChar == '/' ) {
 var new_text = title_text.slice(0, -2);
 $(this).text(new_text);
 }
 });
 }
 //END Remove trailing '/' from title in results	
 
==== Embiggen the select boxes on the item search page ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Increase the height of the select boxes on the item search page
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: Updated to include two options - set the height to a specific number of rows or set the height to match the number of available choices.
===== Option 1 - Set the box height to a specific number of rows =====
 //Embiggen item search fields to a specific height
 $('#catalog_itemsearch #itemsearchform select[multiple="multiple"]').attr('size', '12');
 
===== Option 2 - Automatically set the select box to match the number of choices =====
 //Embiggen item search fields to match the number of options available
 $('#catalog_itemsearch #itemsearchform select[multiple="multiple"]').each(function() { 
 $(this).attr('size', $(this).find('option').length);
 });
 
==== Lockdown Library Settings ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Remove the ability to change libraries in Koha unless you are a superlibrarian
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: Tested and working on 21.05
* Notes: Includes CSS code for login lockdown
 /*Lockdown Login*/
 #loginform #branch, #loginform label[for=branch], #loginform #desk_id, #loginform label[for=desk], #loginform #register_id, #loginform label[for=register_id] {
 display: none;
 }
 //Disable library changing
 if (!$('.loggedinusername').hasClass('is_superlibrarian')) {
 //Remove Set Library from header menu
 $('#user-menu ul.dropdown-menu li:contains("Set library")').remove();
 //end Remove Set Library
 //Remove Set Library from Circulation page
 $('#circ_circulation-home ul.buttons-list li:contains("Set library")').remove();
 //end Remove Set Library
 }
 //END Disable library changin
 
==== Self Registration Confirmation Slip ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Repurpose the Print Summary slip to create a self registration confirmation slip that can print information filled in online, ask for additional information, and provide a line for signing so this can be retained for document retention.
* Notes: Rebuilt for 22.05 and Firefox issues. Hijacking an existing slip proved to be problematic for this version of Koha and Firefox, so I reinvented this task by creating a totally new menu item/slip. This is more reliable.
* Creation Date: 2022
* Updated: 2023
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.05
 //Online Registration Confirmation Slip through Print Summary (v22.05)
 if($('ul.patronbriefinfo li.patroncategory').text().includes('SELF')){
 //Build menu selection for a self registered patron
 $('#printsummary').closest('ul').prepend('<a id="mnuSelfRegConf" href="#">Registration Confirmation</a>');
 //Build Slip Info
 //Gather patron information
 var urlParams = new URLSearchParams(window.location.search);
 var usrBorrowerNumber = urlParams.get('borrowernumber');
 var infoRegConf;
 //Get patron data
 var url = '/api/v1/patrons?patron_id=' + usrBorrowerNumber;
 let patronInfoArr;
 $.ajax({
 async: false,
 url: url,
 success: function(data) {
 patronInfoArr = [data[0].firstname, data[0].surname, data[0].address, data[0].city, data[0].state, data[0].postal_code, data[0].altaddress_address, data[0].altaddress_city, data[0].altaddress_state, data[0].altaddress_postal_code, data[0].phone, data[0].secondary_phone, data[0].email, data[0].secondary_email, data[0].category_id];
 }
 });
 if(patronInfoArr[14] == 'SELF'){
 //Build page
 infoRegConf = 'Online Registration Confirmation';
 infoRegConf += 'Name'+(patronInfoArr[0] || )+' '+(patronInfoArr[1] || )+'';
 infoRegConf += 'Mailing Address'+(patronInfoArr[2] || 'None')+''+(patronInfoArr[3] || )+', '+(patronInfoArr[4] || )+' '+(patronInfoArr[5] || )+'';
 infoRegConf += 'Physical Address (if differnt from mailing)'+(patronInfoArr[6] || 'None')+''+(patronInfoArr[7] || )+', '+(patronInfoArr[8] || )+' '+(patronInfoArr[9] || )+'';
 infoRegConf += 'Primary Phone'+(patronInfoArr[10] || 'None')+'';
 infoRegConf += 'Secondary Phone'+(patronInfoArr[11] || 'None')+'';
 infoRegConf += 'Primary E-mail'+(patronInfoArr[12] || 'None')+'';
 infoRegConf += 'Secondary E-mail'+(patronInfoArr[13] || 'None')+'';
 //Gather extra info not included in online registration
 infoRegConf += 'ADDITIONAL INFORMATIONBirth Date_____ / _____ / __________Parent/Guardian Name (if under 18)_______________________________________RelationshipFather / Mother / Guardian (circle one)Contact preferenceE-mail / Text (SMS) / Phone call(Circle all that apply)Do you want to receive the monthly e-newsletter?Yes / No(Circle one)I, as an individual or as the parent/legal guardian of a child, shall comply with all library policies, accept responsibility for all materials borrowed from the library, and will give immediate notice of any change of address. If the card is lost or stolen, I understand I must notify the library immediately. If signing as the parent or legal guardian of a child, I understand that children have access to all materials in the library, and I accept responsibility for monitoring my child\'s access to print, media, and electronic formats, including the internet._______________________________________Signature';
 }
 $('#mnuSelfRegConf').on('click', function () {
 printSelfRegConf(infoRegConf);
 });
 
 function printSelfRegConf(elem) {
 var myWindow=window.open(,,);
 myWindow.document.write(elem);
 myWindow.document.close();
 setTimeout(function(){ 
 myWindow.focus();
 myWindow.print();
 myWindow.close();
 },500);
 }
 }
 //END Online Registration Confirmation Slip through Print Summary
 
==== Circulation rules modifications 3.0 ====
* Developer: George Williams (Northeast Kansas Library System / Next Search Catalog)
* Purpose: Several modifications to the circulation rules matrix table
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
* Notes: This is at least the third version of this code. All of the smaller pieces can be added between the same "$('#default-circulation-rules').on('init.dt', function() { });" function to minimize the length of the code.
===== Create button to hide left side navigation =====
* Purpose: Adds a button to collapse the #navmenu div to the left of the rules matrix table so more of the table will fit on the screen.
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //BEGIN Create button to expand collapsed rule columns
 $('#admin_smart-rules #navmenu').parent().prepend('<a href="#default-circulation-rules"><button id="allshows" type="button" style="margin: 5px">Show full width</button></a>');
 $('#allshows').click(function() {
 $('#navmenu, #allshows').hide();
 $('.row .col-sm-10.col-sm-push-2').removeClass('col-sm-push-2');
 $(window).trigger('resize');
 });
 });
===== Highlight row on hover =====
* Purpose: Moving the mouse over a row highlights that row.
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //BEGIN Highlight row on hover
 $('#default-circulation-rules tr').hover(
 function() {
 $(this).addClass('highlighted-row');
 },
 function() {
 $(this).removeClass('highlighted-row')
 }
 );
 });
===== Click on row to move it to the bottom of the table =====
* Purpose: When you click on a row in the table, it will move to the bottom of the table right above the "Edit" row.
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //Click on row to move it to bottom
 $('#default-circulation-rules tr:contains(Edit)').click(function() {
 $(this).insertBefore('#default-circulation-rules #edit_row');
 $(window).trigger('resize');
 });
 });
===== Click on the footer to sort the table =====
* Purpose: When you click on a cell in the footer, the table will sort based on the values in the column you've clicked on.
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //BEGIN Sort circulation rules by clicking on footer
 $('#default-circulation-rules tfoot tr th').click(function() {
 var table = $(this).parents('table').eq(0);
 var rows = table.find("tbody tr").toArray().sort(comparer($(this).index()));
 this.asc = !this.asc;
 if (!this.asc) {
 rows = rows.reverse();
 }
 for (var i = 0; i < rows.length; i++) {
 table.append(rows[i]);
 }
 $("#default-circulation-rules #edit_row").insertBefore("tfoot");
 $(window).trigger('resize');
 });
 function comparer(index) {
 return function(a, b) {
 var valA = getCellValue(a, index),
 valB = getCellValue(b, index);
 return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB);
 };
 }
 function getCellValue(row, index) {
 return $(row).children('td').eq(index).text();
 }
 });
===== Collapse columns when the header is clicked - REQUIRES CSS =====
* Purpose: When you click on a cell in the header, that column will collapse to 15px wide allowing for more of the table to fit on the page.
* Dependency: Requires that you add the accompanying CSS to IntranetUserCSS.
IntranetUserCSS
/* -Administration › Circulation and fine rules- hides columns in circulation rules (requires accompanying jQuery) */
 th.hiderule, td.hiderule {
 min-width: 15px;
 max-width: 15px;
 text-indent: -9999px;
 }
IntranetUserJS
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //BEGIN Hide unneeded columns in circulation rules by clicking on header (requires accompanying css)
 $('#default-circulation-rules thead th').append('HideColumn');
 $('#default-circulation-rules thead th').click(function() {
 var index = (this.cellIndex + 1);
 var cells = $('#default-circulation-rules tr > :nth-child(' + index + ')');
 cells.toggleClass('hiderule');
 if ($(this).hasClass('hiderule')) {
 $(this).find('span').html('+');
 } else {
 $(this).find('span').html('HideColumn');
 }
 $(window).trigger('resize');
 });
 });
===== Pre-collapse specified columns =====
* Purpose: Automatically collapse columns you specify when the page loads.
* Dependency: Requires that you add the previous code (Collapse columns when the header is clicked - REQUIRES CSS).
* Notes: This following lists every column in this table in Koha 21.05 but only the columns I normally have auto-collapsed are collapsed. Add or remove comment marks ("//") to suit your needs.
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //Hide 'Patron category' row by default
 //$('#default-circulation-rules th:nth-child(1), #default-circulation-rules td:nth-child(1)').addClass('hiderule');
 //Hide 'Item type' row by default
 //$('#default-circulation-rules th:nth-child(2), #default-circulation-rules td:nth-child(2)').addClass('hiderule');
 //Hide 'Actions (1)' row by default
 //$('#default-circulation-rules th:nth-child(3), #default-circulation-rules td:nth-child(3)').addClass('hiderule');
 //Hide 'Note' row by default
 //$('#default-circulation-rules th:nth-child(4), #default-circulation-rules td:nth-child(4)').addClass('hiderule');
 //Hide 'Current checkouts allowed' row by default
 //$('#default-circulation-rules th:nth-child(5), #default-circulation-rules td:nth-child(5)').addClass('hiderule');
 //Hide 'Current on-site checkouts allowed' row by default
 //$('#default-circulation-rules th:nth-child(6), #default-circulation-rules td:nth-child(6)').addClass('hiderule');
 //Hide 'Loan period' row by default
 //$('#default-circulation-rules th:nth-child(7), #default-circulation-rules td:nth-child(7)').addClass('hiderule');
 //Hide 'Days mode' row by default
 $('#default-circulation-rules th:nth-child(8), #default-circulation-rules td:nth-child(8)').addClass('hiderule');
 //Hide 'Unit' row by default
 //$('#default-circulation-rules th:nth-child(9), #default-circulation-rules td:nth-child(9)').addClass('hiderule');
 //Hide 'Hard due date' row by default
 //$('#default-circulation-rules th:nth-child(10), #default-circulation-rules td:nth-child(10)').addClass('hiderule');
 //Hide 'Decreased loan period for high holds (day)' row by default
 $('#default-circulation-rules th:nth-child(11), #default-circulation-rules td:nth-child(11)').addClass('hiderule');
 //Hide 'Fine amount' row by default
 //$('#default-circulation-rules th:nth-child(12), #default-circulation-rules td:nth-child(12)').addClass('hiderule');
 //Hide 'Fine charging interval' row by default
 //$('#default-circulation-rules th:nth-child(13), #default-circulation-rules td:nth-child(13)').addClass('hiderule');
 //Hide 'When to charge' row by default
 //$('#default-circulation-rules th:nth-child(14), #default-circulation-rules td:nth-child(14)').addClass('hiderule');
 //Hide 'Fine grace period' row by default
 //$('#default-circulation-rules th:nth-child(15), #default-circulation-rules td:nth-child(15)').addClass('hiderule');
 //Hide 'Overdue fines cap (amount)' row by default
 //$('#default-circulation-rules th:nth-child(16), #default-circulation-rules td:nth-child(16)').addClass('hiderule');
 //Hide 'Cap fine at replacement price' row by default
 $('#default-circulation-rules th:nth-child(17), #default-circulation-rules td:nth-child(17)').addClass('hiderule');
 //Hide 'Suspension in days (day)' row by default
 $('#default-circulation-rules th:nth-child(18), #default-circulation-rules td:nth-child(18)').addClass('hiderule');
 //Hide 'Max. suspension duration (day)' row by default
 $('#default-circulation-rules th:nth-child(19), #default-circulation-rules td:nth-child(19)').addClass('hiderule');
 //Hide 'Suspension charging interval' row by default
 $('#default-circulation-rules th:nth-child(20), #default-circulation-rules td:nth-child(20)').addClass('hiderule');
 //Hide 'Renewals allowed (count)' row by default
 //$('#default-circulation-rules th:nth-child(21), #default-circulation-rules td:nth-child(21)').addClass('hiderule');
 //Hide 'Renewal period' row by default
 //$('#default-circulation-rules th:nth-child(22), #default-circulation-rules td:nth-child(22)').addClass('hiderule');
 //Hide 'No renewal before' row by default
 $('#default-circulation-rules th:nth-child(23), #default-circulation-rules td:nth-child(23)').addClass('hiderule');
 //Hide 'Automatic renewal' row by default
 $('#default-circulation-rules th:nth-child(24), #default-circulation-rules td:nth-child(24)').addClass('hiderule');
 //Hide 'No automatic renewal after' row by default
 $('#default-circulation-rules th:nth-child(25), #default-circulation-rules td:nth-child(25)').addClass('hiderule');
 //Hide 'No automatic renewal after (hard limit)' row by default
 $('#default-circulation-rules th:nth-child(26), #default-circulation-rules td:nth-child(26)').addClass('hiderule');
 //Hide 'Holds allowed (total)' row by default
 //$('#default-circulation-rules th:nth-child(27), #default-circulation-rules td:nth-child(27)').addClass('hiderule');
 //Hide 'Holds allowed (daily)' row by default
 //$('#default-circulation-rules th:nth-child(28), #default-circulation-rules td:nth-child(28)').addClass('hiderule');
 //Hide 'Holds per record (count)' row by default
 //$('#default-circulation-rules th:nth-child(29), #default-circulation-rules td:nth-child(29)').addClass('hiderule');
 //Hide 'On shelf holds allowed' row by default
 //$('#default-circulation-rules th:nth-child(30), #default-circulation-rules td:nth-child(30)').addClass('hiderule');
 //Hide 'OPAC item level holds' row by default
 //$('#default-circulation-rules th:nth-child(31), #default-circulation-rules td:nth-child(31)').addClass('hiderule');
 //Hide 'Article requests' row by default
 $('#default-circulation-rules th:nth-child(32), #default-circulation-rules td:nth-child(32)').addClass('hiderule');
 //Hide 'Rental discount (%)' row by default
 $('#default-circulation-rules th:nth-child(33), #default-circulation-rules td:nth-child(33)').addClass('hiderule');
 //Hide 'Actions (2)' row by default
 //$('#default-circulation-rules th:nth-child(34), #default-circulation-rules td:nth-child(34)').addClass('hiderule');
 //Replace the text with a + sign on pre-hidden columns
 $("#default-circulation-rules > thead > tr > th.hiderule > span").html("+");
 });
===== Automatically adjust the page for a super-wide browser size =====
* Purpose: When you load a browser that is wider than 2500px, this will hide the left hand navigation and embiggen all automatically pre-collapsed columns.
* Dependency: Requires that you add the previous code (Collapse columns when the header is clicked - REQUIRES CSS).
//BEGIN changes to smart-rules.pl
 $('#default-circulation-rules').on('init.dt', function() {
 //BEGIN expand when super large or multi screen sized page is loaded
 if ($(window).width() > 2500) {
 $('#navmenu, #allshows').hide();
 $('.row .col-sm-10.col-sm-push-2').removeClass('col-sm-push-2');
 $('.hiderule').removeClass();
 $(window).trigger('resize');
 }
 });
==== Also Try - Extend staff searching to other sources ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / CIN)
* Purpose: Allows staff to continue searching for the same search criteria on preset links/sites set in the left navigation panel on the search results page.
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
 //Also Try (v21.05)
 if($('#catalog_results').length){ //Check if you are on the search results page
 var s = $('#breadcrumbs li').has('a[href="#"]').text().trim().match(/'(.*?)'/);
 var searchCriteria = s[1]; //Setting variable with search criteria from the breadcrumbs line
 $('aside').append('Try your search in...'); //Setting header for new links in left navigation panel
 $('#search-also').append('<a href="https://www.amazon.com/s?k=' + searchCriteria + '&i=stripbooks" target="_blank">Amazon Books</a>'); //Start of some new links
 $('#search-also').append('<a href="https://www.amazon.com/s?k=' + searchCriteria + '" target="_blank">Amazon (General Search)</a>');
 $('#search-also').append('<a href="https://www.fantasticfiction.com/search/?searchfor=author&keywords=' + searchCriteria + '" target="_blank">Fantastic Reads (Authors)</a>');
 $('#search-also').append('<a href="https://www.fantasticfiction.com/search/?searchfor=book&keywords=' + searchCriteria + '" target="_blank">Fantastic Reads (Books)</a>');
 $('#search-also').append('<a href="https://www.fantasticfiction.com/search/?searchfor=series&keywords=' + searchCriteria + '" target="_blank">Fantastic Reads (Series)</a>');
 $('#search-also').append('<a href="https://www.goodreads.com/search?utf8=%E2%9C%93&query=' + searchCriteria + '" target="_blank">GoodReads</a>');
 $('#search-also').append('<a href="https://www.google.com/search?q=' + searchCriteria + '" target="_blank">Google</a><a href="https://www.google.com/search?tbm=bks&q=' + searchCriteria + '" target="_blank">Google Books</a>');
 $('#search-also').append('<a href="http://ww2.kdl.org/libcat/WhatsNext.asp?AuthorLastName=&AuthorFirstName=&SeriesName=&CategoryID=0&cmdSearch=Search&Search=1&grouping=&BookTitle=' + searchCriteria + '" target="_blank">What\'s Next (Books)</a>');
 $('#search-also').append('<a href="http://ww2.kdl.org/libcat/WhatsNext.asp?AuthorLastName=&AuthorFirstName=&CategoryID=0&cmdSearch=Search&Search=1&grouping=&BookTitle=&SeriesName=' + searchCriteria + '" target="_blank">What\'s Next (Series)</a>');
 if($('.logged-in-branch-code').first().text() == 'YOURBRANCHCODE') { //This link will only show for a specified branch
 $('#search-also').append('<a href="YOUR LINK HERE">SPECIAL LINK 1</a>');
 }
 if($('.logged-in-branch-code').first().text() == 'ANOTHERBRANCHCODE') { //This link will only show for a different specified branch
 $('#search-also').append('<a href="YOUR LINK HERE">SPECIAL LINK 2</a>');
 }
 $('#search-also').append('');
 $('aside').append('Catalogers search in...'); //New section for cataloger links
 $('#search-catalogers').append('<a href="https://ts360.baker-taylor.com/_layouts/CommerceServer/QuickSearch.aspx?keyword=' + searchCriteria + '" target="_blank">Baker & Taylor</a>');
 $('#search-catalogers').append('<a href="https://www.blackstonelibrary.com/library/catalogsearch/result/?q=' + searchCriteria + '" target="_blank">Blackstone Library</a>');
 $('#search-catalogers').append('');
 }
 //END Also Try
==== Prevent extra whitespace while editing item record ====
* Developer: George H. Williams (Next Search Catalog / Northeast Kansas Library System)
* Purpose: Prevent leading and trailing whitespace on item record - remove doublespaces - while editing item record
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.05
 //BEGIN Prevent leading and trailing whitespace on item record - remove doublespaces
 $('.input_marceditor').on('blur', function() {
 $(this).val(function(i, value) {
 return value.replace(/\s+/g, ' ').trim();
 });
 });
 //END Prevent leading and trailing whitespace on item record - remove doublespaces
==== FCV - Full cataloguing view in bibliographic or authority record ====
* Developer: Stefano Bargioni (Pontificia Università della Santa Croce)
* Purpose: Display the currently edited record in MARC professional view (compact or expanded)
* Creation Date: 2022-09-13
* Last Modification Date: 2023-05-30
* Status: Completed
* Gadget Version: 1.1
* Intranet or OPAC?: Intranet
* Koha Version: 20.11+
function show_marc_record_fcv(e) {
	if (e.target.tagName == 'INPUT') return;
	if (e.target.tagName == 'TEXTAREA') return;
	var c = e.which; // code key pressed, f/F = 70; mouse click: 1
	if (c != 70 && c != 1) return;
	if (e.altKey || e.ctrlKey || e.metaKey) return; // do not act if a modifier key other than shift was also pressed - SB 2022-12-14
	var fcv_compact_view = false;
	if (e.shiftKey) fcv_compact_view = true;
	if ($('#dialog_fcv_modal').hasClass('in')) {
		$('#dialog_fcv_modal').modal('hide');
		return;
	}
	$('#dialog_fcv_modal').modal(); // show the modal window
	// close the modal window pressing 'f' or 'F' or 'esc' or button X
	var H = [];
	H.push('');
	// tags
	var tags = $('.tagnum');
	for (var i = 0; i < tags.length ; i++) {
		var tag = tags[i];
		// indicators
		var indicators = $(tag).closest('li').find('.indicator');
		var ind1 = $(indicators[0]).val() || ' ';
		var ind2 = $(indicators[1]).val() || ' ';
		// subfields
		var subfields = $(tag).closest('li').find('.input_marceditor'); // include textareas
		var fcv_f = 0;
		for (var j = 0; j < subfields.length; j++) {
			var s = subfields[j];
			var sc = $(s).attr('id').substr(17,1)+' '; // subfield code
			if ($(tag).text() < 10) sc = ;
			else sc = '$'+sc+'';
			var v = $(s).val().trim();
			v = v.replace(/</mg,'<');
			if (v) {
				if (fcv_f == 0) {
					H.push(''+$(tag).text());
					H.push(''+ind1);
					H.push(''+ind2);
					if (fcv_compact_view) H.push(''+sc+v);
					else H.push(''+sc+v);
					fcv_f = 1;
				}
				else {
					if (fcv_compact_view) H.push(' '+sc+v);
					else H.push(''+sc+v);
				}
			}
		}
	}
	H.push('');
	$('#dialog_fcv').html().append(H.join('\n'));
}
	
if ($('body').is('#cat_addbiblio') || $('body').is('#auth_authorities')) {
	var fcv_logo = '<img title="click or shift-click" id="fcv_logo" src="https://upload.wikimedia.org/wikipedia/commons/2/2b/Document_text_edit.svg" style="cursor:pointer; width:32px">';
	$('#toolbar .btn-group:last').after('Press f (expanded) or F (compact) to toggle Full Cataloguing View '+fcv_logo+'');
	// setup and append a hidden modal window
	$('body').append(' \
	 \
	 \
	 \
	 \
	 Full Cataloguing View ' + fcv_logo + ' \
	 <button type="button" style="float:right" class="close" data-dismiss="modal" aria-label="Close"> \
	 × \
	 </button> \
	 \
	 \
	 \
	 ... \
	 \
	 \
	 v. 1.1 (2023-05-30), Pontificia Università della Santa Croce - Licence: the same of Koha <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button> \
	 \
	 \
	 \
	 \
	');
	// detect keypress or click events
	$(document).keydown(show_marc_record_fcv);
	$('#fcv_logo').on('click',show_marc_record_fcv);
}
==== Protect borrowers in a specific category from modification or deletion ====
* Developer: George Williams (Northeast Kansas Library System / Next Search Catalog)
* Purpose: Prevents staff from modifying or deleting members of a specific borrower category
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.11
* Notes: Change _put_category_name_here_ to match the name of the category on your system you wish to protect
//Prevent the modification of, deletion of, or circulation to everyone in a specific borrower category
 $('#circ_circulation, #pat_moremember, #pat_memberentrygen, #pat_member-flags').each(function() {
 if ($('.patroninfo .patroncategory:contains("_put_category_name_here_")', this).length) {
 $('#deletepatron, #editpatron').remove();
 $('#saverecord').attr('disabled','disabled').removeClass('btn btn-default').addClass('btn btn-danger').css("color", "white");
 $('#circ_needsconfirmation .approve').remove();
 $('#toolbar').before('This account can only be modified by a system administrator');
 }
 });
==== Display Calendar Events on Home Page ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library/Cooperative Information Network)
* Purpose: Allows you to display the logged in library's upcoming closures from the Koha calendar. Requires sql report listed in notes.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 21.11
* Notes: Requires https://wiki.koha-community.org/wiki/SQL_Reports_Library#Closures_in_the_Next_4_Weeks_for_Specific_Library
* Notes: getJSON reports require you to specifically define each parameter - if it is a repeated parameter that you only enter once in Koha, you have to define it however many times it is used in the report.
 //Library Closure Widget (v22.05)
 if ( $('#main_intranet-main').length ) {
 var branch = $('#logged-in-info-full .logged-in-branch-code').text();
 $('#container-main .col-sm-3').prepend('Upcoming closures');
 $.getJSON("/cgi-bin/koha/svc/report?id=981&sql_params=" + branch + "&sql_params=" + branch + "&sql_params=" + branch + "&sql_params=" + branch + "&sql_params=" + branch + "&sql_params=" + branch + "&sql_params=" + branch, function(data) {
 let closureData = '';
 $.each(data, function(index, value) {
 var newClosureDate = value[0];
 console.log(index + '/' + value);
 newClosureDate = newClosureDate.replace(/-/g,'‑');
 if(index % 2==0){
 closureData += '';
 } else {
 closureData += '';
 }
 closureData += '' + newClosureDate + ': ' + value[1] + '';
 });
 closureData += '';
 $('#closures').html( closureData );
 });
 }
 //END Library Closure Widget
==== Add feedback to batch deletion confirmation screen ====
* Developer: Jason Robb (SEKLS)
* Purpose: Adds a yellow box below the "Your job has been enqueued!" notice that shows number of items in the job and links to a report to list out those items.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.05
* Notes: The "View list" link references this report: https://wiki.koha-community.org/wiki/SQL_Reports_Library#Get_list_of_deleted_items_from_background_job
if ($('body').is('#tools_batchMod-del')) {
 var jobURL = $('a:contains("View detail of the enqueued job")').attr('href').split('id=');
 var jobIDx = jobURL[1];
 
 if (jobIDx.length) { 
 //Append notice with link to report that lists items
 $('.message').last().after('</i> item(s) queued for deletion. ( <a target="_blank" href="/cgi-bin/koha/reports/guided_reports.pl?reports=2929&phase=Run+this+report¶m_name=Deleted+item+Job+ID&sql_params=' + jobIDx +'"> View list </a> )');
 
 //Add total_records count for the job to the appended message
 $.get('/api/v1/jobs/' + jobIDx, function(result) {
 $('#recordcount').replaceWith('' + result.data.report.total_records + '');
 });
 }
}
==== Replace series info in search results via biblio API to avoid tracing ====
* Developer: Jason Robb (SEKLS)
* Purpose: Replaces series info in search results to avoid traced headings in the search string
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.05
* Notes: This is a niche case but demonstrates how to use the biblio API endpoint to pull data into results
 //Add Series to search results via API
 if ( $('#catalog_results').length ) {
 $('tr').each( function() {
 let this_row = $(this);
 let bnum = $(this).find('input').attr('value');
 let url = `/api/v1/biblios/${bnum}`;
 $(this_row.find(".series")).replaceWith("Series: ");
 
 if ( bnum ) {
 $.ajax({
 type: "GET",
 accepts: {"*": "application/marc-in-json" },
 url: url,
 complete: function(data) {
 let bibliodata = data.responseJSON.fields;
 bibliodata.forEach( function(arrayItem) {
						 if ( Object.keys(arrayItem)[0] == '440' ) {
 let the440a = arrayItem['440'].subfields[0].a;
 let the440n = arrayItem['440'].subfields.map(function(element) { return element['n']; } ).join("");
 let the440v = arrayItem['440'].subfields.map(function(element) { return element['v']; } ).join("");
 $(`<a href="/cgi-bin/koha/catalogue/search.pl?idx=se&q=${the440a}">${the440a} </a> ${the440n}${the440v}`).appendTo( this_row.find('.seriez') );
 	}
							if ( Object.keys(arrayItem)[0] == '490' ) {
 let the490a = arrayItem['490'].subfields[0].a;
 let the490v = arrayItem['490'].subfields.map(function(element) { return element['v']; } ).join("");
 $(`<a href="/cgi-bin/koha/catalogue/search.pl?idx=se&q=${the490a}">${the490a} </a> ${the490v}`).appendTo( this_row.find('.seriez') );
 }
 });
 }
 });
 }
 });
 }
==== Condense Acquisition Baskets ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Condense acquisition baskets so you don't have to scroll through mountains of closed baskets to get to your open ones.
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.05
* Notes: Adds a button at the top of the table to show/hide the closed baskets
 //Condense Acquisition Baskets (v22.05)
 if ( $('#acq_booksellers').length ) {
 $('a:contains("Show")').addClass('btn btn-default').css('margin-bottom','5px').css('margin-right','5px').attr('id','btnShowAll');
 $('#btnShowAll').after('<a id="btnShowClosed" class="btn btn-default" style="margin-bottom: 5px; ">Show/Hide closed active baskets</a>');
 $('#acqui_order_supplierlist td:nth-child(9):not([data-order=""])').each(function() {
 $(this).parent('tr').attr('status','closed').hide();
 });
 $('#btnShowClosed').on('click',function() {
 $('tr[status="closed"]').toggle("slow");
 });
 }
 //END Condense Acquisition Baskets (v22.05)
==== Set "Hold starts on" date in future for closed libraries ====
* Developer: George Williams (Next Search Catalog -- NEKLS)
* Purpose: Sets "Holds starts on" date into the future for libraries that are closed
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.05
* Notes: This could be modified to work with arrays if multiple libraries needed to be closed
//BEGIN Set "Hold starts on date" to a specific future date for a branch - makes past dates unavailable as hold starts on dates 
 
 //Set #reserve_date variable by inserting future date here 
 var reserve_date = ("mm/dd/yyyy"); 
 //Set closed_branch_code variable by inserting branchcode here 
 var closed_branchcode = ("BRANCHCODE"); 
 //Set closed branch name value 
 var closed_branch_name = ("Branch name"); 
 //Set today's date as a variable 
 var tsnow = new Date($.now()); 
 var tsday = ("0" + tsnow.getDate()).slice(-2); 
 var tsmonth = ("0" + (tsnow.getMonth() + 1)).slice(-2); 
 var tsyear = ("0" + (tsnow.getFullYear())).slice(-4); 
 var date_now = (tsmonth) + "/" + (tsday) + "/" + (tsyear); 
 //Set variable to get pre-selected branchcode from select2 element 
 var win_request=$('#circ_request #pickup option[selected="selected"]').val(); 
 
 //Staff logged in at closed library 
 //If variable matches closed library, set default "Hold starts on" date to the day before reopening, hide that date, and make it required 
 if (win_request == closed_branchcode) { 
 $('#reserve_date').val(reserve_date).attr('required','true').parents('li').hide(); //inserts date, sets field to required, and hides input 
 } 
 //Staff logged in at an open library 
 //If someone changes the pickup dropdown to closed library, change the "Hold starts on" date to the set date, make it required, and set the flatpickr to use reserve_date as the minimum date allowed 
 //But reset everything when the pickup library is changed back to an open library 
 $('#circ_request #pickup').parent().change( function() { 
 var branch_name = $('#select2-pickup-container').text(); 
 if (branch_name == closed_branch_name) { 
 $('#reserve_date').val(reserve_date); 
 $('#reserve_date').flatpickr({minDate: reserve_date}); //sets the minimum date for the datepicker for reopening 
 $('#reserve_date').attr('required','true'); //makes input required 
 $('#reserve_date').siblings().hide(); //hides extra "X" clear date icons created by messing with the flatpickr plugin 
 } else { 
 //Clears all settings if different library is chosen 
 $('#reserve_date').val(); 
 $('#reserve_date').removeAttr('required'); 
 $('#reserve_date').show().parents().show(); 
 $('#reserve_date').flatpickr({minDate: date_now}); //Sets minimum date back to today's date 
 $('#reserve_date').siblings().hide(); //hides extra "X" clear date icons created by messing with the flatpickr plugin 
 } 
 
 });
==== Put limit on "Add multiple copies of this item" button on additem.pl ====
* Developer: George Williams (Next Search Catalog -- NEKLS)
* Purpose: Sets a limit of 10 items at a time that can be added to a bibliographic record using the "Add multiple copies of this item" button
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.05
* Notes: The max number is set to 10 just as an example. It could be set to any number you like.
//Home > Cataloging > Edit TITLE > items (cataloguing/additem.pl?biblionumber=n)
 //Limit the number of copies that can be added to a biblio using the "Add multiple copies of this item" button
 $('#cat_additem #number_of_copies').attr('type','number').attr('max','10');
==== Transportation cost matrix - Highlight row on hover ====
* Developer: George Williams (Next Search Catalog -- NEKLS)
* Purpose: Highlights row on the transportation cost matrix on hover
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.11
* Version: 23.05 - tested and working
//Home > Administration > Transport cost matrix (transport-cost-matrix.pl)
 //Highlight row on hover
 $('#transport-cost-matrix tr').hover(
 function() {
 $( this ).children().css('background','var(--c_medium_hov)');
 }, function() {
 $( this ).children().css('background','inherit');
 }
 );
==== Transportation cost matrix - Add button to open all input boxes in matrix ====
* Developer: George Williams (Next Search Catalog -- NEKLS)
* Purpose: Creates a button above the Transport cost matrix table that opens all of the closed input boxes on the table
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.11
* Version: 23.05 - tested and working
* Notes: The number of clicks to open the input boxes manually = ((number of branches - 1)squared) * 2. This reduces that number to one single click.
//Home > Administration > Transport cost matrix (transport-cost-matrix.pl)
 //Creates a button at the top of the table
 $('#transport-cost-matrix').prepend('<button id="tcm_open">Open TCM inputs</button>');
 //Adds function to that button
 $('#tcm_open').click(function (event) { 
 event.preventDefault(); 
 $('#transport-cost-matrix tr td div').trigger('click');
 $(".disable_transport_cost").prop('checked' , false);
 $(".cost_input").removeClass("disabled-transfer");
 $(".cost_input").prop('disabled' , false);
 }); 
==== Reminder to process old new books ====
* Developer: Andrew Fuerste-Henry
* Creation Date: 2023-02-01
* Purpose: Insert reminder on home page to remove items 6+ months old from New Books shelves
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: 22.11
 
if ( $('#main_intranet-main').length ) {
 const month = ["January","February","March","April","May","June","July","August","September","October","November","December"]; 
 const t = new Date();
 let today = t.getDate();
 let year = t.getFullYear();
 let mo = t.getMonth();
 let pullnow = new Date(year, mo - 7, today);
 let pullsoon = new Date(year, mo - 6, today);
 
 if ( today < 5) {
 $('#container-main .col-sm-3').prepend(`
			
				It's time to pull new books added in or before .
				<img src="https://www.publicdomainpictures.net/pictures/450000/nahled/vintage-vogel-katze-illustration.jpg" width="200" height="235" alt="old book cat" />
			</div`);
 	$("#pullreminder").css( { "border-style":"solid" , "border-width":"medium" , "border-color":"red" , "background-color":"white", "padding-top": "10px", "padding-left":"10px", "padding-bottom":"10px" , "padding-right": "10px" });
 }
 
	$('#pullnow').html(month[pullnow.getMonth()]);
 if ( today > 27) {
 $('#container-main .col-sm-3').prepend(`
			
				It's almost time to pull new books added in or before .
				<img src="https://www.publicdomainpictures.net/pictures/450000/nahled/vintage-vogel-katze-illustration.jpg" width="200" height="235" alt="old book cat" />
			</div`);
 	$("#pullreminder").css( { "border-style":"solid" , "border-width":"medium" , "border-color":"red" , "background-color":"white", "padding-top": "10px", "padding-left":"10px", "padding-bottom":"10px" , "padding-right": "10px" });
 }
 
	$('#pullsoon').html(month[pullsoon.getMonth()]);
}
 
==== Style checkout area for restricted patrons ====
* Developer: Andrew Fuerste-Henry
* Creation Date: 2023-06-01
* Purpose: Add visual indicator to checkout when patron is in a category with restricted borrowing
* Status: Completed, needs adaptation to local categories and rules
* Intranet or OPAC?: Intranet
* Version: 22.11
 
if ( 
 $(".patroncategory:contains(GUEST)").length && $('#pat_moremember, #circ_circulation').length) {
 $(".patroncategory").css("color", "red");
 $("#circ_circulation_issue").css("background-color", "#ffa242");
 $(".circ_barcode").append('Up to 3 items');
 $(".circ_rule_note").css("font-weight", "normal");
}
 
==== Patron messaging preferences : Auto-check "Digests only" checkbox when "Text message" or "Email" checkbox is selected ====
* Developer: George H. Williams (Northeast Kansas Library System)
* Creation Date: 2023-10-30
* Purpose: Automatically checks the "Digests only" checkbox when "Text message" or "Email" checkbox is selected on Item Due and Advance Notice
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 22.11
//jQuery variable - all pages 
 //Creates URL variable 
 var url = $(location).attr('href'); 
 
//Home > Patrons > Add patron ([borrowercategory]) (members/memberentry.pl?op=add&categorycode=) 
//Home > Patrons > [borrowername] ([borrowercardnumber]) > Modify patron ([borrowercategory]) (members/memberentry.pl?op=modify&destination=circ&borrowernumber=) 
//Requires "jQuery variable - all pages > Creates URL variable" 
 //Force Item due and Advance notice to auto-select "Digests only" when "Text message" or "Email" is selected 
 
 if (url.indexOf('memberentry.pl') != -1) { 
 
 var email1_var = document.getElementById('email1'); 
 var sms1_var = document.getElementById('sms1'); 
 var email2_var = document.getElementById('email2'); 
 var sms2_var = document.getElementById('sms2'); 
 
 $('#email1, #sms1, #digest1').change(function() { 
 if( (email1_var.checked == true) || (sms1_var.checked == true) ) { 
 $('#digest1').prop('checked', 'true'); 
 } 
 }); 
 
 $('#email2, #sms2, #digest2').change(function() { 
 if( (email2_var.checked == true) || (sms2_var.checked == true) ) { 
 $('#digest2').prop('checked', 'true'); 
 } 
 }); 
 
 } 
==== Auto exit patron account with simple countdown timer ====
* Developer: Jason Robb (Southeast Kansas Library System)
* Creation Date: 2024/01/18
* Purpose: Automatically exit patron account after set amount of time. Includes a simple countdown warning positioned to display under the buttons added by enabling DisplayClearScreenButton.
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 23.05
 //FUNCTION: Exit to circ screen
 function exitnow() {
 window.location="/cgi-bin/koha/circ/circulation.pl";
 }
 //Countdown timer
 var counter = 180; //Total seconds before timeout
 var interval = setInterval(function() {
 counter--;
 if (counter <= 0) {
 		clearInterval(interval);
 }else{
 	$('#countdown_time').text(counter);
 }
 }, 1000);
 
 //FUNCTION: Add exit warning to area beneath exit button 
 function exitwarn() {
 var timertext = 'Auto exit in ' + counter + ' seconds';
 $(timertext).hide().prependTo("#circ_circulation_issue").fadeIn();
 }
 
 if (window.location.href.indexOf("circulation.pl") > -1) {
 if ($('#circmessages').length === 1) { //use the presence of the circmessages div to make sure you're on the right page (probably not ideal)
 setTimeout(exitwarn, 60000 * 2); //Add countdown at 2 minutes 60000 * 2
 setTimeout(exitnow, 60000 * 3); //Automatically exit at 3 minutes 60000 * 3
 }
 }
==== Make buttons added by DisplayClearScreenButton more descriptive ====
* Developer: Jason Robb (Southeast Kansas Library System)
* Creation Date: 2024/01/18
* Purpose: Adds wording and styling to the "Print & Exit" and "Exit" buttons added by DisplayClearScreenButton. Includes some CSS that goes in IntranetUserCSS.
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 23.05
//jQuery
 $('#clearscreen a').replaceWith('<a href="/cgi-bin/koha/circ/circulation.pl" title="Exit this account">Exit</a>');
 $('#printclearscreen i').replaceWith('Print & exit');
 $('#printclearscreen').addClass('btn btn-light').css({'right': '61px', 'border' : 'none', 'border-radius' : '0 0 0 5px'});
 $('#clearscreen').addClass('btn btn-light').css({'border': 'none', 'border-radius' : '0'});
/*CSS*/
.btn-light {
 color: #212529;
 background-color: #E6E6E6;
}
.btn-light:hover {
 color: #212529;
 background-color: #ccc !important;
}
#clearscreen a, #printclearscreen a {
 background-color: transparent; 
 border-radius: 0;
 color: #212529;
 font-size: 100%;
 font-weight: normal;
 padding: 0;
 text-shadow: none;
}
#clearscreen a:hover, #printclearscreen a:hover {
 color: #212529;
}
==== Make Exit button from DisplayClearScreenButton glow red after a period of time ====
* Developer: Jason Robb (Southeast Kansas Library System)
* Creation Date: 2024/01/18
* Purpose: Adds a class associated with a subtle glow animation to the "Exit" button to encourage staff to exit an account that's been idle for 1 minute. Includes some CSS that goes in IntranetUserCSS.
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 23.05
//jQuery
 //FUNCTION: Add glow class
 function exitplz() {
 $("#clearscreen a").css('background-color', 'transparent');
 $("#clearscreen").addClass('inner-glow-red');
 }
 if (window.location.href.indexOf("circulation.pl") > -1) {
 if ($('#circmessages').length === 1) { //use the presence of the circmessages div to make sure you're on the right page (probably not ideal)
 setTimeout(exitplz, 60000); //Add countdown at 1 minute 60000
 }
 }
/*CSS*/
.inner-glow-red {
	-webkit-animation: inner-glow-red 2s linear infinite alternate both;
	 animation: inner-glow-red 2s linear infinite alternate both;
}
/*remove animation for browsers with reduced motion enabled*/
@media screen and (prefers-reduced-motion) { 
 .inner-glow-red {
 -webkit-animation: none;
 -moz-animation: none;
 -o-animation: none;
 animation: none;
 }
}
@-webkit-keyframes inner-glow-red{0%{box-shadow: inset 0 0 30px #E6E6E6}100%{box-shadow: inset 0 0 30px #f44336}}@keyframes inner-glow-red{0%{box-shadow: inset 0 0 30px #E6E6E6}100%{box-shadow: inset 0 0 30px #f44336}}
==== Disable check out for special accounts on circulation.pl ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / CIN)
* Creation Date: 2024/01/31
* Purpose: Disable check out for special accounts on circulation.pl, like Self Registered patrons that have not finished registration
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on 21.05
 //Disable check out for special accounts on circulation.pl (v21.05)
 if ($('#circ_circulation li.patroncategory:contains("(SELF)")').length) {
 $('li.patroncategory:contains("(SELF)"),#circ_circulation li.patroncategory:contains("(EONLY)")').css('color','red');
 $('#mainform').replaceWith('Cannot check out!This patron category cannot checkout items.');
 }
 //END Disable check out for special accounts on circulation.pl
==== Add "Print card number" button to patron toolbar ====
* Developer: George H. Williams - Northeast Kansas Library System 
* Creation Date: 2024-03-08
* Purpose: Allows staff to quickly print the borrower's barcode number from the "Check out" or "Details" pages
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: 23.05
* Koha breadcrumbs: Home > Circulation > Checkouts > [Borrower name and barcode number]
* Koha breadcrumbs: Home > Patrons > [Borrower name and barcode number] > Details
//Home > Circulation > Checkouts > [Borrower name and barcode number] - (/circ/circulation.pl?borrowernumber=[borrowernumber]) 
//Home > Patrons > [Borrower name and barcode number] > Details - (/members/moremember.pl?borrowernumber=[borrowernumber]) 
 // Creates button and adds it to the toolbar 
 $('#circ_circulation #toolbar, #pat_moremember #toolbar').append('<a id="nsc_card_print" class="btn btn-default">Print card number</a>'); 
 
 //BEGIN adds function onto the print button 
 $('#nsc_card_print').click(function() { 
 var barcode_cont = $('.patroninfo #hiddenborrowercard').val(); 
 var problemWindow = window.open(, , 'height=500,width=500'); 
 problemWindow.document.write('<html><head><style>body {width: 260px; padding-bottom: 10px; word-wrap: break-word} input {display: none;}</style><title></title></head><body>===== '); 
 problemWindow.document.write(barcode_cont); 
 problemWindow.document.write(' ====='); 
 problemWindow.document.close(); 
 problemWindow.onload = function() { 
 problemWindow.focus(); 
 problemWindow.print(); 
 problemWindow.close(); 
 }; 
 }); 
==== Clean Printing from Reports ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library/CIN)
* Creation Date: 2024-04-11
* Purpose: Print reports and report templates without menus or odd formatting
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: 23.05
* Notes: Adds 'Print Report' link in the Download menu on the report results.
 //Report Printing (v23.05)
 if($('#rep_guided_reports_start #format').length) {
 $('#format').siblings('ul').append('<a id="mnuPrintReport" href="#">Print Report</a>');//Create print link in download menu
 $('#mnuPrintReport').on('click', function () {
 var reportInfo = '<html><head></head><body>' + $('#ReportContent').html() + '</body></html>';
 var myWindow=window.open(,,);
 myWindow.document.write(reportInfo);
 myWindow.document.close();
 setTimeout(function(){ 
 myWindow.focus();
 myWindow.print();
 myWindow.close();
 },500);
 });
 }
 $('#report_results').wrap('');//Wrap report table (You will need to manually add this to your template, if using one.)
 //END Report Printing
==== Limit the use of the "Protected" patron status to Superlibrarians only ====
* Developer: George Williams (NEKLS/Next Search Catalog)
* Purpose: Disables the protected user radio buttons for all users except superlibrarians
* Creation Date: 2024-07-25
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on Koha 24.05
* Koha breadcrumbs: 
** Home > Patrons > [borrower name (cardnumber)] > Modify patron ([borrower category])
**Home > Add patron ([borrower category])
* Koha URL: 
** /members/memberentry.pl?op=edit_form&destination=circ&borrowernumber=[borrowernumber]
** /members/memberentry.pl?op=add_form&categorycode=[category code]
* Note: A patch has been submitted to create a permission for the "Protected" status. This code will not longer be needed when that enhancement is added.
** See https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=36085 for more information
//Disable "Protected" patron status except for superlibrarians
 //Adds a class to the ""Protected: Yes / No" list element
 $('#pat_memberentrygen label[for="protected"]').parent().addClass('next_is_protected');
 //Disable the radio buttons for all users
 $('.next_is_protected input').attr('disabled','disabled');
 //Re-enable the radio buttons when a superlibrarian is logged in
 $('#pat_memberentrygen.is_superlibrarian .next_is_protected input').removeAttr('disabled', 'disabled')
==== Add count of holds to holds queue button on circ home, and emphasize when holds exceed 1 week ====
* Developer: Jason Robb(Southeast Kansas Library System)
* Purpose: Saves a click if the holds queue is empty, brings attention if holds are being ignored
* Creation Date: 2024-08-19
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on Koha 23.05
* Koha breadcrumbs: 
** Home > Circulation
* Koha URL: 
** /circ/circulation-home.pl
* Note: Requires a report to calculate total and oldest hold, and CSS to add emphasis
IntranetUserJS
 //Add a placeholder for the count
 $('#circ_circulation-home .circ-button .fa-tasks').parent().append(' '); 
 var libcode = $('#logged-in-info-full .logged-in-branch-code').text(); //Logged in library code
 var staleCheckerReportNum = ####; //Number of report calculating total and oldest hold
 //Pull count via the report
 if (window.location.href.indexOf("circulation-home.pl") > -1) {
 $.getJSON("/cgi-bin/koha/svc/report?id=" + staleCheckerReportNum + "&sql_params=" + libcode + "&annotated=1" + new Date().getTime(), function(result){
 var hqcount = '' + result[0].total + ''; //Total hold count
 var stalechecker = result[0].oldestHold; //Oldest hold in days
 var daysStale = 7; //Days after which hold is considered stale
 
 //Add a class to the Holds Queue button if the oldest hold exceeds days after which hold is considered stale [requires additional CSS]
 if(stalechecker > daysStale) { 
 $('#circ_circulation-home .circ-button:contains("Holds queue")').first().addClass('buttonglow bg-stripe-r');
 }
 
 //Replace placeholder with count from report
 $("#hqcount").replaceWith(hqcount);
 }
 );
 }
IntranetUserCSS
.bg-stripe-r{
 border-radius: 6px;
 border: 4px double red !important;
 margin-bottom: 8px;
 padding: 4px 0px 0px 0px;
 background-position: 0px !important;
 background: -webkit-repeating-linear-gradient(
 145deg,
 #FFB4B4 1px,
 #FFA4A4 2px,
 #FFA4A4 11px,
 #FFB4B4 12px,
 #FFB4B4 20px
 );
}
.hq-stale {
 font-size: 13px;
 font-weight: bold;
 text-align: center;
}
@-webkit-keyframes glowing {
 0% { -webkit-box-shadow: 0 0 3px #B20000; }
 50% { -webkit-box-shadow: 0 0 40px #FF0000; }
 100% { -webkit-box-shadow: 0 0 3px #B20000; }
}
.buttonglow {
 -webkit-animation: glowing 1500ms infinite;
 -moz-animation: glowing 1500ms infinite;
 -o-animation: glowing 1500ms infinite;
 animation: glowing 1500ms infinite;
}
/*IMPORTANT -- disables glow if user has disabled nonessential motion in the browser settings*/
@media screen and (prefers-reduced-motion) { 
 .buttonglow {
 -webkit-animation: none;
 -moz-animation: none;
 -o-animation: none;
 animation: none;
 }
}
SQL
SELECT 
 COUNT(*) AS total,
 DATEDIFF(MIN(reservedate), (curdate())) * -1 AS oldestHold
FROM tmp_holdsqueue t
LEFT JOIN items USING (itemnumber)
WHERE t.holdingbranch LIKE <<Choose Library|branches>>
==== Limit a customization to users on a patron list ====
* Developer: Jason Robb(Southeast Kansas Library System)
* Purpose: Useful for making 'pseudo' permissions where the customization only affects certain users on a patron list. Avoids exposing usernames directly in your userJS sysprefs.
* Creation Date: 2024-08-19
* Status: Complete
* Intranet or OPAC?: Intranet
* Version: Developed on Koha 23.05
* Note: Requires a report to reference the patron list
IntranetUserJS
 var loggedUser = $("#logged-in-info-full .loggedinusername").text();
 var patronListReportNum = 1234; //Number of the report that pulls users on the patron list
 var patronListNum = 8; //Find the id of your patron list from the URL at Tools > Patron lists (/patron_lists/list.pl?patron_list_id=8)
 //Use report to see who's on a patron list
 $.getJSON("/cgi-bin/koha/svc/report?id=" + patronListReportNum + "&sql_params=" + patronListNum, function(data) {
 var staffUsers = JSON.stringify(data);
 //If logged in user is on the list, do a thing
 $.each(JSON.parse(staffUsers), function (key, value) {
 if(loggedUser.indexOf(value) > -1){
 //Whatever you want to happen for these users specifically goes here
 }
 });
 });
 
SQL
SELECT b.userid
FROM patron_list_patrons p
LEFT JOIN borrowers b USING (borrowernumber)
WHERE p.patron_list_id = <<List ID>>
==== Removes the "Item was not checked in" warning from checked-in items table when not really necessary ====
* Developer: George Williams (Northeast Kansas Library System / Next Search Catalog)
* Purpose: 
# Adds a line break between spans in that column
# Removes the "Item was not checked in" message from the Due date column on the Checked-in items table when it's not really necessary 
* Status: Completed
* Intranet or OPAC?: Intranet
* Version and date: 
** Created for Koha version Koha 24.05.03
** Creation date: 2024-10-04
* Breadcrumbs: Home > Circulation > Check in
* URL: /cgi-bin/koha/circ/returns.pl
* Notes: 
//Home > Circulation > Check in (/cgi-bin/koha/circ/returns.pl)
 //BEGIN remove "Item was not checked in" message when it's not really necessary
 $('#checkedintable .ci-duedate span').append('');
 $('#checkedintable .ci-duedate span.problem:contains("Item was not checked in")').parent().addClass('nsc_nco');
 $('#checkedintable .ci-duedate span.dmg').parent().removeClass('nsc_nco');
 $('#checkedintable .ci-duedate span.withdrawn').parent().removeClass('nsc_nco');
 $('#checkedintable .nsc_nco span.problem').hide();
==== Removes the "Not checked out" message on checked-in table (variation of the previous jQuery) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Removes the "Not checked out" message after the "Item was not checked in" warning from checked-in items table when not really necessary (variation of the previous jQuery)
* Status: Completed
* Intranet or OPAC?: Intranet
* Version and date: 
** Created for Koha version Koha 24.05.03
** Creation date: 2024-10-14
* Breadcrumbs: Home > Circulation > Check in
* URL: /cgi-bin/koha/circ/returns.pl
 //Remove confusing verbage for browses on check in screen (24.05)
 $('#circ_returns td.ci-duedate:contains("Not checked out") span:contains("Not checked out")').remove();
 //END Remove confusing verbage for browses on check in screen
==== Highlight damaged statuses on the Check In table (returns.pl) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Highlight damaged statuses on the Check In table (returns.pl)
* Status: Completed
* Intranet or OPAC?: Intranet
* Version and date: 
** Created for Koha version Koha 24.05.03
** Creation date: 2024-10-14
* Breadcrumbs: Home > Circulation > Check in
* URL: /cgi-bin/koha/circ/returns.pl
 //Highlight warning statuses on the table (returns.pl)
 $('#circ_returns #checkedintable span.dmg').addClass('label label-warning').wrap('');
==== Enhance the statuses of items on the detail.pl holdings table ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Enhance the statuses of items on the detail.pl holdings table
* Status: Completed
* Intranet or OPAC?: Intranet
* Version and date: 
** Created for Koha version Koha 24.05.03
** Creation date: 2024-10-14
* Notes: This will wrap the main item statuses in bootstrap labels of various colors for easier identification. It will also utilize font awesome icons to identify these different statuses.
 //Item Status Enhancement on detail.pl (v24.05)
 $('#holdings_table').on('draw.dt', function() {
 $('#holdings_table span:contains("Available")').addClass('available');
 $('#catalog_detail .shelvingloc:contains("Recently Returned")').each(function() {
 $(this).html($(this).html().replace(/\(Recently Returned\)/g, 'Recent Return'));
 });
 $('#catalog_detail .available').html('Available');
 $('#catalog_detail .lost,#catalog_detail .dmg,#catalog_detail .notforloan,#catalog_detail .wdn').each(function() {
 $(this).html(' '+ $(this).text() +'');
 });
 $('#catalog_detail .intransit').each(function() {
 $(this).html(' '+ $(this).text() +'');
 });
 $('#catalog_detail .waitingat').each(function() {
 $(this).html(' '+ $(this).text() +'');
 });
 $('#catalog_detail .heldfor,#catalog_detail .holdonitem').each(function() {
 $(this).html(' '+ $(this).text());
 });
 });
 //END Item Status Enhancement on detail.pl
==== Move surname to the end of the name fields when adding or editing a borrower ====
* Developer: George Williams (Northease Kansas Library System / Next Search Catalog)
* Purpose: re-orders patron name fields on memberentry.pl
* Status: Completed
* Intranet or OPAC?: 
* Version and date: 
** Created for Koha version Koha 24.11
** Creation date: 2025-01-21
* Breadcrumbs: Home > Patrons > Add patron > (categories.description)
* URL: /cgi-bin/koha/members/memberentry.pl?op=add_form&categorycode=(categories.categorycode)
$(document).ready(function(){
 
 //Reorders name fields - pushing surname below middle name - on patron update/entry page
 $('#memberentry_identity li #surname').parent().insertAfter($('#memberentry_identity li #middle_name').parent());
});
==== Set 245 indicator 1 based on data in 1xx fields in Marc21 ====
* Developer: George Williams (Northease Kansas Library System / Next Search Catalog)
* Purpose: Sets the first indicator on the 245 field to "1" if a 100$a, 110$a, 111$a, or 130$a is present in the record
* Status: Completed
* Intranet or OPAC?: Intranet
* Version and date: 
** Created for: Koha 24.05.06
** Creation date: 2025-02-04
* Breadcrumbs: Home > Cataloging > Editing _biblio.title etc_ (Record number _biblio.biblionumber_)
* URL: /cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[biblio.biblionumber]
//Home > Cataloging > Editing _biblio.title etc_ (Record number _biblio.biblionumber_)
//(/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[biblio.biblionumber])
 //Sets 245 indicator 1 when you remove the cursor from the 245$a input box
 //Sets to "1" if a 100$a, 110$a, 111$a, or 130$a is present in the record
 //Sets to "0" if no 1xx$a is present
 $('#cat_addbiblio [id^="tag_245"]').blur(function(){
 var onehundred = (0 || $('[id^="tag_100_subfield_a"]').val() || $('[id^="tag_110_subfield_a"]').val() || $('[id^="tag_111_subfield_a"]').val() || $('[id^="tag_130_subfield_a"]').val());
 if (onehundred == 0) { 
 $('#cat_addbiblio [name^="tag_245_indicator1"]').val('0'); 
 } else { 
 $('#cat_addbiblio [name^="tag_245_indicator1"]').val('1'); 
 } 
 });
==== Set 245 indicator 2 based on data in 245$a in Marc21====
* Developer: George Williams (Northease Kansas Library System / Next Search Catalog)
* Purpose: Sets the second indicator on the 245 field to 4 if 245$a starts with "The ", 3 if 245$a starts with "An ", 2 if 245$a starts with "A "
* Status: Completed
* Intranet or OPAC?: Intranet
* Version and date: 
** Created for: Koha 24.05.06
** Creation date: 2025-02-04
* Breadcrumbs: Home > Cataloging > Editing _biblio.title etc_ (Record number _biblio.biblionumber_)
* URL: /cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[biblio.biblionumber]
//Home > Cataloging > Editing TITLE (Record number XX)
//(/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[BIBLIONUMBER])
 //Sets 245 indicator 2 when you remove the cursor from the 245$a input box
 //Sets indicator 2 based on A, An, The values 
 $('#cat_addbiblio [id^="tag_245"]').blur(function(){
 var value = $(this).val();
 if (value.indexOf('The ') == 0) { 
 $('#cat_addbiblio [name^="tag_245_indicator2"]').val('4'); 
 } else if (value.indexOf('An ') == 0) { 
 $('#cat_addbiblio [name^="tag_245_indicator2"]').val('3'); 
 } else if (value.indexOf('A ') == 0) { 
 $('#cat_addbiblio [name^="tag_245_indicator2"]').val('2'); 
 } else { 
 $('#cat_addbiblio [name^="tag_245_indicator2"]').val(); 
 }
 });
===OPAC JQuery Statements===
==== Changing the logo in Koha’s OPAC ====
* Developer: Koustubha Kale (anantcorp.com)
* Purpose: Changing the logo in Koha’s OPAC
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any 
A jquery based script that can be used in “opacuserjs” syspref which overcomes the image size limitation of "opacsmallimage" syspref. This script allows you to put your own logo in place of the default Koha logo while it shifts the Koha logo, prepending it with text “Powered by :” and a link back to the koha-community.org site, at the bottom of the page. The script takes care to add it below any credits you might have added by using the “opaccredits” syspref.
 
var logo='http://www.anantcorp.com/images/resized/anant-logo.gif';
var bkgnd=$("#opac-main-search").css("background-color");
var frgnd=$("#moresearches").css("color");
$("#opac-main-search").find("h1").remove();
$("#opac-main-search").prepend("<a id='#libraryname' href='/cgi-bin/koha/opac-main.pl' style='float: left; padding: 0pt; display: inline; margin: 0em 1em 0.3em 0.1em;'><img src="+logo+" /></a>");
$("#fluid-offset").css({ "float":"left","width":"75%" });
if($(".ft").length != 0) {
$(".ft").after("Powered By :<a href='http://www.koha-community.org' style='text-decoration:none;' target='_blank' > <img src='/opac-tmpl/prog/images/koha-logo.gif' alt='Koha' ALIGN='ABSMIDDLE' style='background:"+bkgnd+";'/> </a>");
}
else {
$("div#bd").after("Powered By :<a href='http://www.koha-community.org' style='text-decoration:none;' target='_blank' > <img src='/opac-tmpl/prog/images/koha-logo.gif' alt='Koha' ALIGN='ABSMIDDLE' style='background:"+bkgnd+";'/> </a>");
}
 
On line number one of the script you can give link to your logo.
On line two you can set the background color for the transparent Koha logo image and on line three the color of the words “Powered by :” is set. I have tried to read in the values of Koha OPAC’s search block’s background and text color here but you can simply replace these with your favorite colors.
Don't forget to surround the code above in $(document).ready(function(){ and }); inside the "opacuserjs" preference.
==== Change the text of the OPAC login link ====
* Developer: Owen Leonard (Nelsonville Public Library)
* Purpose: Change the text of the OPAC login link
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any 
 
 $("#members a:contains('Log in to your account')").text("Log In");
 
==== Add AuthorAlerts.org links to the OPAC ====
* Developer: Kyle M Hall
* Purpose: Adds links to authoralerts.org to OPAC search results and details ( make sure to change YOUR_SITE_ID to your actual siteid )
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any 
 
 // add Author Alerts to search results
 $("span.author").each(function(){
 var author = $(this).text().trim();
 var gp = $(this).parent().parent();
 gp.children(".actions-menu").append('<a href="http://authoralerts.org/?YOUR_SITE_ID=7019&AuthorName=' + author + '"> Add author alert</a>');
 });
 // add Author Alerts to record details
 $( "span[property='author'] span[property='name']" ).each(function(){
 var author = $(this).text().trim();
 console.log( author );
 $("a.addtocart").parent().append('  <a href="http://authoralerts.org/?YOUR_SITE_ID=7019&AuthorName=' + author + '">   Add author alert</a>');
 });
 
==== Change the text of the OPAC login form ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Change the text of the Log in form on the right of the homepage
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any (prog and ccsr)
 
$(document).ready(function(){
 $("#auth legend:contains('Log in to your account')").text("Log in to your library account");
 $("#auth label[for='userid']").html("Library Card Number:");
 $("#auth label[for='password']").html("PIN:");
});
 
==== Change the text of the OPAC login form (Bootstrap) ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Change the text of the Log in form on the right of the homepage and the pop up box
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+ (bootstrap)
 
//relabel login boxes
 $("#auth label[for='userid']").html("Card number:");
 $("#auth label[for='password']").html("Last name:");
 $("#modalAuth label[for='muserid']").html("Card number:");
 $("#modalAuth label[for='mpassword']").html("Last name:");
 
==== Replaces text below login form for private OPAC's====
* Developer: Christopher Vella, CALYX: Information Essentials
* Purpose: Replaces the helper text below the login box on for private OPAC's.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.16+ 
 
 $(document).ready(function(){
 $("#nologininstructions").html("Add some html here");
 });
 
==== Rename 'Place Hold' in OPAC to 'Get It Now!' ====
* Developer: Owen Leonard (Nelsonville Public Library)
* Purpose: Change the 'Place Hold' text throuhgout the OPAC with 'Get it Now!'
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.2 
 
 $(document).ready(function(){
 var holdlinks = $("a:contains('Place Hold'),a:contains('Place hold')");
 $(holdlinks).text("Get It Now!");
 });
 $(window).load(function(){
 $("input[value='Place Hold']").attr("value","Get It Now!");
 });
 
==== Rename 'Browse Shelf' in OPAC to 'See Similar Items' ====
* Developer: Ian Walls (ByWater Solutions)
* Purpose: Change the 'Browse Shelf' text after the callnumber in opac-detail to 'See Similar Items'
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.4
 
 $(document).ready(function(){
 $("a:contains('Browse Shelf')").text("See Similar Items");
 });
 
==== Add a link to the header only if a patron is logged into the OPAC ====
* Developer: Galen Charlton
* Purpose: Adds a link to the OPAC masthead only if the patron is logged into the OPAC.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
* Note: This can be generalized to alter behavior or display when a patron is logged in. For this specific example, note that somebody viewing source can see the link's URL, so be careful if using this to present super-sekrit (sic) stuff only to logged-in patrons.
 
 if ($("#logout").length) {
 $("#moresearches").append(" | <a href=\"http://bursar.example.edu/\">Pay fines</a>");
 }
 
==== Change where the header logo link goes ====
* Developer: D Ruth Bavousett, ByWater Solutions
* Purpose: Reroute the link on the logo to someplace other than opac-main
* Status: Completed /
* Intranet or OPAC?: OPAC
* Version: 3.2+, but will probably work way, way back.
 
 $("#libraryname a").attr('href','http://your.link.here');
 
==== Remove the textual item type description from the OPAC holdings table ====
* Developer: Jared Camins-Esakov (ByWater Solutions)
* Purpose: Remove the textual item type description from the OPAC holdings table
* Status: Completed /
* Intranet or OPAC?: OPAC
* Version: 3.2+
* Programming notes: The magic number '3' is used instead of Node.TEXT_NODE because Internet Explorer apparently does not export that constant into the global namespace.
 
 $("#holdingst tbody tr td:nth-child(1)").contents().filter(function() { return this.nodeType == 3; }).remove();
 
==== Replace '--' with carriage returns in title notes on OPAC details ====
* Developer: D Ruth Bavousett, ByWater Solutions
* Purpose: formatting/layout hack for Title Notes section
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
 
 $("#descriptions .content_set").html($("#descriptions .content_set").html().replace(/--/g,''));
 
==== Force suggestions table in OPAC to show "Library Staff" as manager ====
* Developer: D Ruth Bavousett, ByWater Solutions
* Purpose: Library desires to not name names for who managed suggestions--"Library Staff" should be shown for all
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.4
 
 $('#suggestt tr').each(function() {
 $(this).find("td:nth-child(4)").html("Library Staff"); 
});
 
==== Change "Available for reference" note in search results to something more appropriate to ebooks ====
* Developer: Jared Camins-Esakov, ByWater Solutions
* Purpose: Change the text of the "Available for reference" note in OPAC search results to something more appropriate for ebooks, which may not actually be available as a physical book in the library at all.
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.2+
 
 $(".available b:contains('reference')").text("View e-resources online; If available in print, one or more copies may only be used in: ");
 
==== Hide 'Save Record' Box in OPAC ====
* Developer: Joy Nelson, ByWater Solutions
* Purpose: Remove the 'Save Record' box on the bib detail in the OPAC.
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.4+
 
$(document).ready(function(){
$("#export").remove();
});
 
==== Change Text in Drop Down list for 'Save Record' (3.4+) ====
* Developer: Joy Nelson, ByWater Solutions
* Purpose: Change Text in Drop Down list for 'Save Record' from BIBTEX to Endnote
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.4+
 
$('#export option[value="bibtex"]').text('EndNote');
 
==== Change Text in Drop Down list for 'Save Record' (3.14+) ====
* Developer: Nicole Engard, ByWater Solutions
* Purpose: Change Text in Drop Down list for 'Save Record' from BIBTEX to RefWorks
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
//change bibtex to refworks
$("#export a:contains('BIBTEX')").html(' RefWorks'); 
==== Break OPAC SearchForTitleIn out of dropdown ====
* Developer: Ian Walls, ByWater Solutions
* Purpose: Make the content in SearchForTitleIn always visible, instead of appearing only when the "more searches" button is clicked
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.4+
 
$("a#furthersearches").parent().hide();
$("#furtherm").attr("class","").attr("style","");
$("#furtherm div ul li").attr("style", "list-style:none");
 
==== Hiding a library from the list in the drop-down in the OPAC ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: This hides a library branch from the drop-down selection on the search main screen. You will need to identify the branch code and replace "CODE" with the appropriate code for the branch you wish to hide. 
* Status: Completed 
* Intranet or OPAC?: Intranet
* Version: 3.6+
 
$("#select_library option[value='branch:CODE']").remove();
==== Reorganize library groups in OPAC drop-down ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Purpose: Library groups are added to the OPAC drop-down in the order they appear in the database. You can reorganize the library groups using this code.
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 18.05
 
 var slv = $('#select_library option[value="group_value_1"]'); //create a variable from a value in the select_library drop-down
 slv.remove(); //remove it
 $(slv).insertAfter('#select_library option[value="group_value_2"]'); //add it after another value in the library drop-down
==== Move Navigation ====
* Developer: Elliott Davis (UT Tyler)
* Purpose: Move Navigation Menu Below OpacMainSearch
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: All
 
 $('#header-wrapper').append($('#navigation'));
 
==== Move List Dropdown ====
* Developer: Elliott Davis (UT Tyler)
* Purpose: Move lists dropdown to main menu
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: All
 
 $('#listsmenulink').appendTo('.main-menu > .last');
 
==== Opac Search Results Sort ====
* Developer: Elliott Davis (UT Tyler)
* Purpose: Change wording in call number sort 
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: All
 
 $("option[value='call_number_asc']").html("Call Number Ascending");
 $("option[value='call_number_dsc']").html("Call Number Descending");
 
==== Add a bookplate when cover images are not found ====
* Developer: Jared Camins-Esakov, C & P Bibliography Services
* Purpose: Replace the "No cover image" message on the OPAC with a custom bookplate
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: All
* Note: Replace "bookplate.jpg" in the script with the URL to the image you want to use
 
 $('.no-image').css('background-image','url(bookplate.jpg)');
 
==== Show nothing when cover images are not found ====
* Developer: Nicole C. Engard, ByWater Solutions; Galen Charlton, Equinox Open Library Initiative
* Purpose: Remove the "No cover image" message on the OPAC
* Status: Completed
* Updated: 2021-08-16
* Intranet or OPAC?: OPAC
* Version: All
 
$(window).on('load', function () {
 $('.no-image').remove();
});
 
This needs to be done upon the load event, not the ready event, as otherwise it can prevent the script that displays local cover images from finding the divs to attach the images to.
==== Alert patrons about exhausting their renewals early when they login to the OPAC ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Purpose: Adds an alert to the top of the OPAC only if the patron is logged into the OPAC.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
* Note: When the OPAC RenewalPeriodBase preference is set to the current date, patrons can accidently exhaust their renewals early. This code will place a prominent alert at the top of the OPAC upon patron login. This code is a modified version of Galen Charlton's code Add a link to the header only if a patron is logged into the OPAC
 
 if ($("#logout").length) {
 $("#members").prepend("ALERT - renewing your items early or clicking 'renew' more than once will reduce your total checkout time.");
 }
 
==== Move OPACResultsSidebar to the top ====
* Developer: Derryn Jones
* Purpose: Moves the OPACResultsSidebar to the top 
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any (Tested on 3.6 - 3.10)
 
 $("#facetcontainer.container").prepend($("#opacresultssidebar"));
 
==== Remove all links on SCO (Self-Checkout) ====
*Developer: Derryn Jones
*Creation Date: 2013-03-26
*Purpose: Removes all links on SCO page to stop people using the SCO as a browser (Very useful if you're using a kiosk with no back/forward buttons)
*Status: Completed
*Intranet or OPAC?: OPAC 
*Version: Any (Tested on 3.10)
if(/sco-main/.test(self.location.href))
{
$('a').removeAttr('href')
}
 
 
==== Hiding a library from the pickup location drop-down in the OPAC "Place Hold" screen ====
* Developer: George H. Williams, Latah County Library District
* Purpose: This hides a library branch from the pickup location drop-down in the "Place Hold" screen in the OPAC. This prevents patrons from having a hold delivered to the branch you specify unless that branch is their home library. Replace "BRANCHCODE" with the code for the branch you wish to remove from the drop-down.
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.8
$("#bibitemloop option[value='BRANCHCODE']").hide();
==== Hiding a library from the pickup location drop-down in the OPAC "Place Hold" screen (3.18+) ====
* Developer: David Roberts, PTFS Europe
* Purpose: This hides a library branch from the pickup location drop-down in the "Place Hold" screen in the OPAC. This prevents patrons from having a hold delivered to the branch you specify unless that branch is their home library. Replace "BRANCHCODE" with the code for the branch you wish to remove from the drop-down.
* Creation Date: (2015-02-10)
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.18+
$("[id^=branch] option[value='BRANCHCODE']").remove();
==== Hide the CART button ====
* Developer: Paul Landers - Texas Tech University Health Sciences Center
* Purpose: Hide the CART button.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
* Note: Hide the CART button.'''
 
$('#cmspan').hide();
 
==== Remove the Cart and corresponding links ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Creation Date: 2018-11-15
* Purpose: Removes the cart icon, label, menu, and the links in the search results and bib records.
* Status: Completed - NOTE that CSS is generally preferred -- see https://wiki.koha-community.org/wiki/HTML_%26_CSS_Library#CSS for solution that also hides Add to cart button in search results
* Intranet or OPAC?: OPAC
* Version: 18.05
 
$("#carticon").remove();
$(".cartlabel").remove();
$("#cartmenulink").remove();
$('[class ^="addtocart"]').remove();
 
==== Change Browse Authorities to say Search ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: The link to search the authorities says 'browse' but it's a search, so this changes it to be clearer.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
 
 $("a:contains('Browse by author or subject')").text("Search authorities");
 
==== Make the opac more multilingual ====
* Developer: Jonathan Druart, Gaetan Boisson, BibLibre
* Creation Date: (2013-06-06), updated 2013-06-18
* Purpose: The system preferences for customizing OPAC regions only allow for one language, so an opac with several languages will always show the same text here whatever the language selected by the user. This allows for switching to a different language when using the selector at the bottom of the screen. To achieve this, you will need to put each language in a separate div in the concerned system preference, each div will have a class named after the value the KohaOpacLanguage cookie will take when this language is selected. You will also need to add a bit of css so that all those divs are hidden by default. (Such as "div.en, div.ar-Arab {display:none;}"). If not language is set, the default is set to english, be sure to change this if your opac doesn't use this language, as it will be used when a user first land on the website.
* Status: Completed 
* Intranet or OPAC?: OPAC
* Version: 3.10.04
$(document).ready(function(){
var myLang = $('html').attr('lang');
$("div."+myLang).show();
});
 
On our first iteration we used the values in the cookie, here is the code for reference, which shows how to fetch the information from cookies, but the new version above is obviously much more simple and fool proof (you don't need to set a default value as it seems this attribute is always set).
$(document).ready(function(){
var url = 'https://raw.github.com/carhartl/jquery-cookie/master/jquery.cookie.js';
$.getScript( url, function(){
 var myLang = jQuery.cookie('KohaOpacLanguage');
 if(!myLang) myLang = "en";
 $("div."+myLang).show();
 });
});
 
==== Hide Location Column ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: This hides the location column in the holdings table in the OPAC.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10.x
 
//Hide Location Column
$("th#item_location").hide();
$("td.location").hide();
 
==== Hide Collection Column ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: This hides the collection column in the holdings table in the OPAC.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10.x
 
//Hide Collection Column
$("th#item_ccode").hide();
$("td.collection").hide();
 
==== Change "Quote of the Day" Label ====
* Developer: Galen Charlton, Equinox Software
* Purpose: This changes the text of the Quote of the Day label in the OPAC.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10.x+
 
 $('#daily-quote h1').text('Wisdom of the Day'); 
 
==== Hide Login Help ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Hide the login help text from the OPAC login page
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
 $("#nologininstructions").hide();
 
==== Change Login Help ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Change the login help text from the OPAC login page
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("#nologininstructions").html("Do not have a password yet?If you do not have a password yet, give us a call at XXX or email us at XXX.Do not have a library card? If you do not have a library card, stop by your local library to sign up. ");
 
==== Hide OPAC Login on Right ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Hide the login box on the main opac page
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.8+
 
 $("#login").hide();
 
==== Add Title Phrase to the simple search ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Adds Title Phrase to the simple search
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("#masthead_search option[value='ti']").after("<option value=\'ti,phr\'>Title Phrase</option>");
$("select[name='idx']:eq(0)").val("ti").attr("selected","selected");
$("select[name='idx']:eq(1)").val("ti,phr").attr("selected","selected");
 
==== Change 'my fines' to 'my charges' ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Change tab on patron's record from 'my fines' to 'my charges'
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("#menu [href='/cgi-bin/koha/opac-account.pl']").text('my charges');
 
==== Change all occurrences of the word 'Fines' to 'Charges' in My Account ====
* Developer: David Roberts, PTFS Europe
* Purpose: Change all occurrences of the word 'Fines' to 'Charges' in My Account
* Creation Date: 2015-03-05
* Status: Completed
* Intranet or OPAC?: OPAC
* Theme: BootStrap
* Version: 3.18
 
$("#menu ul > li > a:contains('your fines')").html('your charges');
$("#opac-user-views th:contains('Fines')").html('Charges');
$("#opac-user-views ul > li > a:contains('Fines')").text(function () {
 return $(this).text().replace("Fines", "Charges");
 });
 
==== Change "purchase suggestion" to "request for this item" ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Change tab on patron's record from 'my fines' to 'my charges'
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
 $('a[href="/cgi-bin/koha/opac-suggestions.pl?op=add"]').text('request for this item');
 
==== Hide purchase suggestion links for specific branches ====
* Developer: Lucas Gass
* Purpose: Hide unwanted purchase suggestion links depending on branchcode
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 20.05+
 
 if ( $('.loggedinusername').length ) {
 /* add branchcodes where purchase suggestion links are unwanted to the array branches_to_hide */
 var branches_to_hide = ['CPL' , 'MPL'];
 var this_user_branch = $('.loggedinusername').attr('data-branchcode');
 if( $.inArray (this_user_branch, branches_to_hide) !== -1) {
 $('#usermenu a[href*="/cgi-bin/koha/opac-suggestions.pl"]').parent().remove();
 }
 }
 
==== Hide "your purchase suggestions" button for specific patron categories ====
* Developer: Pablo López Liotti (based in preceding Lucas Gass work, thks to him!)
* Purpose: Hide unwanted purchase suggestions link in OPAC user's menu, according to patron categories.(It´s most required for university libraries to restrict purchase suggestions only for teachers, by example) 
 
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 20.05+ (19.xx to test)
 if ( $('.loggedinusername').length ) {
 /* add patrons category codes to hide "purchase suggestions" button in user´s menu */ 
 var category_to_hide = ['A','ST'];
 var this_user_category = $('.loggedinusername').attr('data-categorycode');
 
 if( $.inArray (this_user_category, category_to_hide) !== -1) {
 $('#usermenu a[href*="/cgi-bin/koha/opac-suggestions.pl"]').parent().remove();
 }
 }
==== Change privacy list items on 'my privacy' tab ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Change privacy list items on 'my privacy' tab
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
 $("li.privacy0").html("Forever - Keep my reading history until I choose to delete it.");
 $("li.privacy1").html("Default - Keep my reading history until the end of the current semester or summer or until I choose to delete it.");
 $("li.privacy2").html("Never - Delete my reading history immediately. Upon check-in, my name will not display and the item will never appear in my reading history.");
 
==== Hide branch from search pulldown ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Hide a branch from the search pull down
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("#select_library option[value='branch:BRANCHCODE']").hide();
 
==== Hide branch from search pulldown (alternative version) ====
* Developer: Ed Veal, ByWater Solutions, edited by Caroline Cyr La Rose, inLibro
* Purpose: Hide a branch from the search pull down
* Status: Completed
* Intranet or OPAC?: OPAC (this also works in Intranet)
* Version: 
 
$("#branchloop option[value='branch:BRANCHCODE']").hide();
 
==== Change comment pending text ====
* Developer: Ed Veal, ByWater Solutions
* Purpose: Change the text that appears when a comment is pending
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("#reviewf p").replaceWith("Your comment, once approved by a librarian, will be made public in the library’s web-based catalog. Your full name will be associated with your comment. The library respects the right of its users to express themselves but will not tolerate abusive behavior. Reviews may not include profanity, obscenities, spiteful remarks, personal information, URLs or email addresses.");
 
==== Hide Topic & Places Facets ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Removes the Current location column in Holdings table
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("li#su-geo_id").hide();
$("li#su-to_id").hide();
 
==== Automatically Expand Holding Libraries Facet On Search ====
* Developer: Carl Todd, Holyoke Community College; Joe Sikowitz, Fenway Library Organization
* Purpose: Automatically expands the holding libraries facet when the user executes a search from the masthead search box. This could be applied to any one facet that you want initially expanded when searching by changing the value field in the HTML.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.05
 
$("#searchform").append('<input type="hidden" name="expand" value="holdingbranch">');
 
==== Hide home link on home page (CCSR) ====
* Developer: Owen Leonard
* Purpose: Removes the link to Home from the CCSR opac homepage
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$("#opac-main #breadcrumbs").hide();
 
==== Hide home link on home page (Bootstrap) ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Removes the link to Home from the Bootstrap opac homepage
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
if (window.location.href.indexOf("/koha/opac-main.pl") > -1) {
$("ul.breadcrumb").remove();
}
 
==== Relabel Acquisitions Date Sort Options ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Changing the acquisition date sort options to read 'date added' instead
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+
 
$('#sort_by option[value="acqdate_dsc"]').text('Date added: Newest to oldest');
$('#sort_by option[value="acqdate_asc"]').text('Date added: Oldest to newest');
 
==== Relabel Holds as Requests ====
* Developer: Nicole C. Engard, ByWater Solutions with Owen Leonard (additions by Liz Rea, Catalyst IT)
* Purpose: This will change all occurrences of the word Holds in the OPAC to Request
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.12+
 
$("input[value='Place hold']").attr("value","Place Request");
$("a#ui-id-3:contains('Holds')").html('Requests');
$("input[value='Suspend all holds']").attr("value","Suspend all requests");
$("input[value='Resume all suspended holds']").attr("value","Resume all suspended requests");
$("input[value='Place Hold']").attr("value","Place Request");
var holdcount = $("#holdst caption .count").text();
$("#holdst caption").text("Requests " + holdcount);
$("a[href='#opac-user-holds']").text("Requests ");
var holdlinks = $("a:contains('Place Hold'),a:contains('Place hold')");
$(holdlinks).text("Request Item");
$("#opac-holds h3:contains('holds')").html("Confirm requests: ");
$("#opac-holds .priority span.label").html("Requests and priority:");
$("#opac-holds .hold-options label:contains('Hold not needed after:')").text("Request not needed after: ");
 
In the opaccredits, put: 
<script type="text/javascript">
$(document).ready(function () { $('.confirmjs_hold label').contents().filter(function () { return this.nodeType === 3; }).replaceWith(' Place a request for '); });
</script>
==== Open item specific links in a new tab ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: This will make links in the holdings table (urls on items) open in a new tab
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.12+
 
 $("td.url a").attr('target', '_blank');
 
==== Disable External Links on SCO ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: This assumes that the header is linked and that you have the 'powered by koha' link. Both links will be disabled with this jquery on the self check page.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
/* remove the ability to click links out of the self check */
if (window.location.href.indexOf("sco/sco-main.pl") > -1) {
$('#opacheader').bind('click', false);
$('#koha_url').bind('click', false);
}
 
==== Add Start Over Link Below Search Bar ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Adds a start over link right below the search bar
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
//Adds "Start over" to moresearches
$("#moresearches ul").prepend('<a href="/" >Start Over</a>');
 
==== Pre-fill the UserID fields with a library card prefix ====
* Developer: Aaron Sakovich
* Purpose: Pre-fills the User ID fields with a library card prefix or other value.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
* Theme: BootStrap
* Note: If your system uses a standard prefix for library cards, this can save your patrons a little bit of typing while also providing them a visual cue as to where to enter their card number when logging in to the OPAC. Note in the sample code below, the 7 digit prefix used is 1234567; this should be changed for your prefix or other value you'd like.
 
$(document).ready(function () {
 var userIDField = document.getElementById("userid");
 if ($('#userid').length > 0) {userIDField.value = "1234567";}
 var muserIDField = document.getElementById("muserid");
 if ($('#muserid').length > 0) {muserIDField.value = "1234567";}
});
 
==== Add a link to the more searches menu ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Adds link to the more searches menu
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
//add faq link to menu at top
$("#moresearches li:contains('Course reserves')").after("<a href='http://FAQLINK'>Library Catalog FAQ</a>");
 
==== Change more searches capitalization ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Changes more searches to title case
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
//capitalize more searches links
$("#moresearches a:contains('Course reserves')").html('Course Reserves');
$("#moresearches a:contains('Advanced search')").html('Advanced Search');
 
==== Fix Subject Search Links ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/CIN
* Purpose: Subject search links in records break if the subject contains parenthesis. This jquery strips the parenthesis from the url link, making the link usable again.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14
 
//Fix subject search by striping parenthesis from url links
$('#catalogue_detail_biblio a[href*="su:"]').attr('href', function(_,v){
 return v.replace(/(\w)(\(|\))(\w)/g,'$1 $3')
}).attr('href', function(_,v){
 return v.replace(/(\(|\))/g,)
});
//End fix subject search
 
==== Hide Marc & ISBD view from OPAC ====
* Developer: Lucas Gass, ByWater Solutions
* Purpose: Hide Marc & ISBD view from OPAC
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 17.05+
 
 $(".view a:contains('MARC view')").parent().hide();
 $(".view a:contains('ISBD view')").parent().hide();
 
==== Change URL in Holdings to Text ====
* Developer: Nicole C. Engard, ByWater Solutions
* Purpose: Make the URL in the item holdings table show as linked text instead of a long URL
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.14+
 
//change item url to say visit site
$("td.url a").text("Visit site"); 
 
==== Rename the Cart (multilang) ====
* Developer: Zeno Tajoli, an expand of A. Longoria, Texas State Law Library, work
* Purpose: Rename the Cart in the OPAC to My Books and use a folder icon and manage more than one languages
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.18 (only, modify for others versions)
* Note: YOu MUST use it OUTSIDE $(document).ready(function(){ ... });. Because it use global variables and strings override'''
var myLang = $('html').attr('lang');
if (myLang === 'en') {
 /* re-define the messages */
 MSG_BASKET_EMPTY = _("My Books is currently empty");
 MSG_RECORD_IN_BASKET = _("This item is already in My Books");
 MSG_RECORD_ADDED = _("This item has been added to My Books");
 MSG_RECORD_REMOVED = _("The item has been removed from My Books");
 MSG_NRECORDS_ADDED = _(" item(s) added to My Books");
 MSG_NRECORDS_IN_BASKET = _("already in My Books");
 MSG_NO_RECORD_ADDED = _("No item was added to My Books");
 MSG_CONFIRM_DEL_BASKET = _("Are you sure you want to empty My Books?");
 MSG_ITEM_IN_CART = _("Already in My Books");
 MSG_IN_YOUR_CART = _("Items in My Books: ");
 MSG_ITEM_NOT_IN_CART = _("Add to My Books");
 
 /* change the links in OPAC search results and details page */
 $('a.addtocart').each(function() {
 var msg = $(this).text();
 if(msg === 'Add to cart' || msg === 'Add to your cart')
 $(this).text(MSG_ITEM_NOT_IN_CART);
 else if (msg === 'In your cart')
 $(this).text(MSG_ITEM_IN_CART);
 });
 
 /* links in the item details page */
 $('a.incart').each(function() {
 var msg = $(this).text();
 if(msg === 'In your cart')
 $(this).text(MSG_ITEM_IN_CART);
 });
 /* Title in display of cart */
 $("#userbasket h2:contains('Your cart')").html('My Books');
 
 $("span.addto").on('click', function() {
 $("select#addto > option:contains('Cart')").html("My Books");
 });
 
 top_button_convert = function() {
 var basketcount = ;
 if($('#basketcount').text())
 basketcount = $('#basketcount').html();
 $("#cartmenulink").html(
 ' My Books' + basketcount + '');
 };
 
 top_button_convert(); // run once 
 
 $("a.addtocart").on('click', function() {
 top_button_convert(); // run on given clicks
 });
};
if (myLang === 'it-IT') {
 /* re-define the messages */
 MSG_BASKET_EMPTY = _("My Books è vuoto");
 MSG_RECORD_IN_BASKET = _("Questa copia è gia in My Books");
 MSG_RECORD_ADDED = _("Questa copia è stata aggiunta a My Books");
 MSG_RECORD_REMOVED = _("Questa copia è stata rimossa da My Books");
 MSG_NRECORDS_ADDED = _(" copia(e) aggiunta(e) a My Books");
 MSG_NRECORDS_IN_BASKET = _("già in My Books");
 MSG_NO_RECORD_ADDED = _("Nessuna copia aggiunta a My Books");
 MSG_CONFIRM_DEL_BASKET = _("Sei sicuro di svuotare My Books?");
 MSG_ITEM_IN_CART = _("Già in My Books");
 MSG_IN_YOUR_CART = _("Copia in My Books: ");
 MSG_ITEM_NOT_IN_CART = _("Aggiungi a My Books");
 
 /* change the links in OPAC search results and details page */
 $('a.addtocart').each(function() {
 var msg = $(this).text();
 if(msg === 'Aggiungi al carrello' || msg === 'Clicca per aggiungere al carrello')
 $(this).text(MSG_ITEM_NOT_IN_CART);
 else if (msg === 'Nel tuo carrello')
 $(this).text(MSG_ITEM_IN_CART);
 });
 
 /* links in the item details page */
 $('a.incart').each(function() {
 var msg = $(this).text();
 if(msg === 'Nel tuo carrello')
 $(this).text(MSG_ITEM_IN_CART);
 if(msg === 'Il tuo carrello')
 $(this).text('My Books');
 });
 
 $("#userbasket h2:contains('Il tuo carrello')").html('My Books');
 $("span.addto").on('click', function() {
 $("select#addto > option:contains('Cart')").html("My Books");
 });
 
 top_button_convert = function() {
 var basketcount = ;
 if($('#basketcount').text())
 basketcount = $('#basketcount').html();
 $("#cartmenulink").html(
 ' My Books' + basketcount + '');
 };
 top_button_convert(); // run once 
 
 $("a.addtocart").on('click', function() {
 top_button_convert(); // run on given clicks
 });
};
==== Rename the Cart ====
* Developer: A. Longoria, Texas State Law Library, expanding on code from the Brooklyn School of Law OPAC
* Purpose: Rename the Cart in the OPAC to My Books and use a folder icon instead of shopping cart.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 19.11
* Note: Renames the Cart to My Books in the OPAC and changes its icon. Started with code found at http://sara.brooklaw.edu'''
 
// Re-define the messages.
MSG_BASKET_EMPTY = _('My Books is currently empty');
MSG_RECORD_IN_BASKET = _('This item is already in My Books');
MSG_RECORD_ADDED = _('This item has been added to My Books');
MSG_RECORD_REMOVED = _('The item has been removed from My Books');
MSG_NRECORDS_ADDED = _(' item(s) added to My Books');
MSG_NRECORDS_IN_BASKET = _('already in My Books');
MSG_NO_RECORD_ADDED = _('No item was added to My Books');
MSG_CONFIRM_DEL_BASKET = _('Are you sure you want to empty My Books?');
MSG_ITEM_IN_CART = _('Already in My Books');
MSG_IN_YOUR_CART = _('Items in My Books: ');
MSG_ITEM_NOT_IN_CART = _('Add to My Books');
// Change the links on OPAC search results and details pages.
$('a.addtocart').each(function() {
 var $this = $(this);
 var msg = $.trim($this.text());
 if(msg === 'Add to cart' || msg === 'Add to your cart')
 $this.text(MSG_ITEM_NOT_IN_CART);
 else if (msg === 'In your cart')
 $this.text(MSG_ITEM_IN_CART);
});
// Links on the item details page.
$('a.incart').each(function() {
 var $this = $(this);
 var msg = $.trim($this.text());
 if(msg === 'In your cart')
 $this.text(MSG_ITEM_IN_CART);
});
$('container > h1:contains("Your Cart")').html('My Books');
$('span.addto').on('click', function() {
 $('select#addto > option:contains("Cart")').html('My Books');
});
top_button_convert = function() {
 var basketcount = ;
 if($.trim($('#basketcount').text()))
 basketcount = $('#basketcount').html();
 $('#cartmenulink').html(
' My Books' + basketcount + ''
 );
};
 
// Run once.
top_button_convert();
 
// Then run on given clicks.
$('a.addtocart').on('click', function() {
 top_button_convert();
});
 
==== Filter Courses ====
* Developer: Switch Consortium
* Purpose: Add pull down at the top of the course reserves list to select department/library and filter the list of courses
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.20
* Note: Assumes that you're using branches as the departments'''
 
//Drop down for course reserves
$('#course_reserves_table_filter').before('<label style="font-weight:bold; font-size:12px;">Select Reserves by Library: <select class="deptSearch"><option value="">All libraries</option><option value="YOUR BRANCHCODE">YOUR LIBRARY NAME</option></select></label>');
$(".deptSearch").change(function(){
 $('#course_reserves_table').DataTable().column(1).search(this.value); 
 $('#course_reserves_table').DataTable().draw();
});
 
==== Blank the Home library dropdown on self-registration====
* Developer: Jason Robb (SEKLS)
* Purpose: On self-registration, makes the first option in the Home library dropdown a blank so patrons are forced to choose a library rather than defaulting to the first library in the list.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.22
 
var0 = $('body').is("#opac-patron-registration.opac"); //Makes sure the change only happens on self-registration
if(var0 !=0) {
 $("#borrower_branchcode").prepend("<option value=></option>").val();
}
 
==== Autofill "Hold expires on" date when placing a request in the OPAC ====
* Developer: George Williams (NExpress)
* Purpose: Autofills the "Hold expires on date" with the date 1 year from today when patrons place a request in the OPAC. There is a corresponding piece of jQuery for the staff client in the intranet section. The future date can be modified by changing the values in the day, month, and year variables.
* Creation Date: 3/30/2017
* Status: Completed - Can cause errors around Leap Day when jQuery calculates a nonexistent date (like 2/29/20201)
* Intranet or OPAC?: Intranet
* Version: Developed on 3.16
//BEGIN Set newly placed holds in OPAC to expire after one year if not filled
 var holdtodate = new Date();
 var day = ("0" + holdtodate.getDate()).slice(-2);
 var month = ("0" + (holdtodate.getMonth() + 1)).slice(-2);
 var year = ("0" + (holdtodate.getFullYear() + 1)).slice(-4);
 var holdtill = (month) + "/" + (day) + "/" + (year);
 $('#hold-request-form #to').val(holdtill);
//END
==== Autofill "Hold expires on" date when placing a request in the OPAC ====
* Developer: Lucas Gass (Bywater Solutions)
* Purpose: Autofills the "Hold expires on date" with the date 1 year from today when placing a request from the OPAC. There is a corresponding piece of jQuery for the intranet in the intranet section. The future date can be modified by changing the values in the day, month, and year variables.
* Creation Date: 8/25/20
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 19.11
//BEGIN Set newly placed holds in staff client to expire after one year if not filled
$(document).ready(function() {
 if ( $('#opac-holds').length ) {
 $.getScript( "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" )
 .done(function( script, textStatus ) {
 $('.holddateto').val(moment().add(1, 'years').calendar());
 })
 .fail(function( jqxhr, settings, exception ) {
 console.log( 'Could not load MomentJS' );
 });
	} 
});
//END
==== Hide PayPal if patron owes less than $10.00 ====
* Developer: George Williams (NExpress)
* Purpose: Hides the PayPal option in the OPAC if the patron owes less than $10.00 and puts a note on the page saying that payments can't be accepted for less than that (this wouldn't prevent a patron from making a $2.00 payment on a fee of $25.00, but it does prevent someone who only owes $2.00 from making any payments via PayPal)
* Creation Date: 04/04/2017
* Status: Completed
* Intranet or OPAC?: OPAC
* Page: opac-account.pl (Your fines tab in patron account)
* Version: Developed on 16.11
//BEGIN Hide PayPal option if patron owes less than $10.00
 var sumvalue = parseInt($('#useraccount > form > table > tfoot > tr > td').html());
 if (sumvalue < 10){
 $("#useraccount .pay-online").hide();
 $("#useraccount > form").append("Online payments can only be accepted for amounts of $10.00 or more");
 }
==== Force patron to select SMS provider and enter SMS number before checkboxes can be checked ====
* Developer: George Williams (NExpress)
* Purpose: There is a bug in Koha 16.11 that breaks patron messaging if SMS checkboxes are checked but no SMS provider is selected. This jQuery attempts to fix this by 1) disabling the checkboxes and SMS number entry if no provider is selected 2) clearing the SMS number and all SMS checkboxes if the provider is removed 3) forcing the SMS number to 10 numeric characters with no punctuation or spaces 4) moving the SMS provider and SMS number above the messaging preferences table so it is more intuitive for patrons to enter that information first 5) and finally renaming the SMS labels from "SMS" to "Text message" because many patrons arent going to know what SMS means. There is corresponding jQuery for the staff client above
* Creation Date: 4/10/2017
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 16.11.05
* OPAC breadcrumbs: Home › PATRONNAME › Your messaging settings
//BEGIN Hides SMS number and all SMS checkboxes when page is loaded
 $("#sms1, #sms2, #sms4, #sms5, #sms6").attr("disabled","disabled");
 $("#SMSnumber").parent().hide();
 
//BEGIN Show SMS number if provider is not null and clear number and all SMS checkboxes if the provider is changed to null 
 $("body").on("mousemove change click keyup", function(){
 if($("#sms_provider_id").val() != ""){
 $("#SMSnumber").parent().show("slow");
 } else {
 $("#SMSnumber").parent().hide("slow");
 $("#SMSnumber").val("");
 $("#smsbuttons").hide();
 $("#sms1, #sms2, #sms4, #sms5, #sms6").attr("disabled", "disabled");
 $("#sms1, #sms2, #sms4, #sms5, #sms6").prop("checked", false);
 }
 });
 
//BEGIN Enable SMS checkboxes only if SMS number is 10 digits and force SMS number entry to numerals only - no punctuation, alphanumeric characters, or spaces
 $("#SMSnumber").attr('maxlength','10');
 $('#SMSnumber').keydown(function (e) {
 if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
 (e.keyCode == 65 && e.ctrlKey === true) ||
 (e.keyCode >= 35 && e.keyCode <= 40)) {
 return;
 }
 if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
 e.preventDefault();
 }
 });
 $("body").on("mousemove change click keyup", function(){
 if($("#SMSnumber").val().length == 10){
 $("#sms1, #sms2, #sms4, #sms5, #sms6").removeAttr("disabled");
 $("#smsbuttons").show("slow");
 } else {
 $("#sms1, #sms2, #sms4, #sms5, #sms6").attr("disabled", "disabled");
 $("#sms1, #sms2, #sms4, #sms5, #sms6").prop("checked", false);
 $("#smsbuttons").hide("slow");
 }
 });
//BEGIN Move SMS stuff above the table so that the first fields that need to be filled out are the first ones that patrons see
 $("#opac-messaging #usermessaging > form > fieldset.rows").insertBefore($("#opac-messaging #usermessaging > form > table"));
 $("#opac-messaging #usermessaging > form > fieldset.rows > ol:nth-child(3)").insertBefore($("#opac-messaging #usermessaging > form > fieldset.rows > ol:nth-child(2)"));
//BEGIN Rename SMS "Text messaging" for the sake of people who don't know what SMS stands for
 $('#opac-messaging label, #opac-messaging th').each(function() {
 var text = $(this).text();
 $(this).text(text.replace('SMS', 'Text message')); 
 });
	
==== Change the label on the "Note" column in the patron summary ====
* Developer: George Williams (NExpress)
* Purpose: Changes the label in the header on the "Note" column in the checkouts table on the patron's summary page from "Note" to "Report a problem"
* Creation Date: 10/23/2017
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 17.05
* OPAC breadcrumbs: Home › PATRONNAME › Your summary
//BEGIN rename "Note" to "Report a problem"
 $("#userdetails #checkoutst th:contains(Note)").html("Report a problem");
	
==== Sort the SMS providers drop-down ====
* Developer: George Williams (NExpress)
* Purpose: The SMS provider drop-down is sorted in the order the provider was added rather than alphabetically by provider name. This makes it difficult for patrons to find providers not added the the list in alphabetical order. This jquery sorts the list alphabetically leaving "Unknown" at the top and maintaining any provider already selected if the patron is editing their existing settings. Related to community bug 20439.
* Creation Date: 2018.05.07
* Status: Completed
* Intranet or OPAC?: OPAC (the code works the same way on OPAC or intranet pages)
* Version: Developed on 17.05.10
//BEGIN force SMS provider to sort alphabetically, put "Unknown" at top of list, and keep any pre-existing selection after sort is finished
 $("#sms_provider_id option:contains('Unknown')").text(' Unknown');
 $("#sms_provider_id").one( "click", function() {
 var preselected = $('#sms_provider_id option:selected').val();
 $("#sms_provider_id").html($('#sms_provider_id option').sort(function(x, y) {
 return $(x).text().toUpperCase() < $(y).text().toUpperCase() ? -1 : 1;
 }));
 $("#sms_provider_id").val(preselected);
 });
==== Using Course Reserves for Display management ====
* Developer: Ed Veal McKinney Public Library
* Creation Date 2018.09.09
* Purpose: Allow public libraries to use the Course Reserves module to manage ongoing/reacquiring displays. 
* Status: In progress
* Intranet or OPAC?: OPAC
* Version: Andy
 
// Turning Course Reserves into Display in the OPAC for public libraries EV
// No work has been done on the Staff side of things. So Course Reserves will still display there in its entirety.
// Changes terms in more searches navigation bar. 
	$("#moresearches [href='/cgi-bin/koha/opac-course-reserves.pl']").text('Displays');
// Changes term in Breadcrumbs
	$(".breadcrumb [href='/cgi-bin/koha/opac-course-reserves.pl']").html('Displays');
	
if (window.location.pathname == '/cgi-bin/koha/opac-course-reserves.pl') {
	$('.breadcrumb a:contains("Course reserves")').html($('.breadcrumb a:contains("Course reserves")').html().replace('Course reserves','Displays'));	
	}
if (window.location.pathname == '/cgi-bin/koha/opac-course-details.pl') {
	$('.breadcrumb a:contains("Course reserves for")').html($('.breadcrumb a:contains("Course reserves for")').html().replace('Course reserves for','Display for'));
	}
// Changes the Course Reserves heading1 on /cgi-bin/koha/opac-course-reserves.pl to simply say Displays.
	$("div.span12 > h1:contains('Courses')").html("Displays");
// Hides unused data from the Course Reserves Table on /cgi-bin/koha/opac-course-reserves.pl page.
	if (window.location.pathname == '/cgi-bin/koha/opac-course-reserves.pl') {
	$("table#course_reserves_table td:nth-child(2),th:nth-child(2)").hide();
	$("table#course_reserves_table td:nth-child(3),th:nth-child(3)").hide();
	$("table#course_reserves_table td:nth-child(4),th:nth-child(4)").hide();
	$("table#course_reserves_table td:nth-child(5),th:nth-child(5)").hide();
	$("table#course_reserves_table td:nth-child(6),th:nth-child(6)").hide();
	$("table#course_reserves_table td:nth-child(7),th:nth-child(7)").hide();
	}
// Hides unused data from the Course Items Table on /cgi-bin/koha/opac-course-details.pl page.
	if (window.location.pathname == '/cgi-bin/koha/opac-course-details.pl') {
	$("table#course-items-table td:nth-child(7),th:nth-child(7)").hide();
	}
// Hides the course details from the /cgi-bin/koha/opac-course-details.pl page.
	if (window.location.pathname == '/cgi-bin/koha/opac-course-details.pl') {
	$("div.rows").hide();
	}
// Changes the Course Reserves column to Display on the opac details page. 
	if (window.location.pathname == '/cgi-bin/koha/opac-detail.pl') {
	$("#item_coursereserves").text('Display');
	}
	if (window.location.pathname == '/cgi-bin/koha/opac-course-details.pl') {
	$('.span12 h2:contains("Course reserves for")').text($('.span12 h2:contains("Course reserves for")').text().replace('Course reserves for','Display for'));
	}
// End of Display jQuery
 
==== Move the news under the opacmainuserblock contents ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: This moves the "News" container under the contents of OpacMainUserBlock
* Creation Date: 2019-02-19
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 18.05.03
$( ".newscontainer" ).insertAfter( $( "#opacmainuserblock" ) );
$( "#rssnews-container" ).insertAfter( $( ".newscontainer" ) );
$( "#news-branch-select" ).insertBefore( $( ".newscontainer" ) );
==== Show local cover art instead of Google Books cover art if both are present ====
* Developer: A. Longoria, Texas State Law Library
* Purpose: If both the local cover art (OPACLocalCoverImages) and the Google Books cover art options (GoogleJackets) are enabled and both images are present, this hides the Google Books image.
* Creation Date: 2015-04-30
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 3.18 and still working as of 18.05.08
 // Hide Google Books cover art from the search results when local cover art is present.
 if (document.location.pathname === '/cgi-bin/koha/opac-search.pl') {
 // You have to wait until window onload event since that is when imgs are loaded.
 $(window).on('load', function () {
 $('span[id*=local-thumbnail]').find('img').each(function () {
 if ($(this)[0].naturalWidth > 1)
 $(this).parent().siblings('span').hide();
 });
 });
 }
 // Hide Google Books cover art when viewing a bib record when local cover art is present.
 if (document.location.pathname === '/cgi-bin/koha/opac-detail.pl') {
 $(window).on('load', function () {
 var localImage = $('#local-thumbnail-preview').find('img')[0];
 if (localImage && localImage.naturalWidth > 1) {
 $('#gbs-thumbnail-preview').hide();
 }
 });
 }
----
==== Automatically Hide a holdings dataTable column only if all cells are empty ====
* Developer: Pablo López Liotti
* Purpose: Hide empty columns of a holdings dataTable 
* Status: Completed
* Creation Date: 2019-05-16
* Intranet or OPAC?: OPAC and Intranet
* Version: 17.xx, 18.xx, 19.05
 
/* empty columns remove function */
$('#holdingst').each(function(a, tbl) {
 var currentTableRows = $(this).find("tr").length - 1;
 $(tbl).find('th').each(function(i) {
 var removeVal = 0;
 var currentTable = $(this).parents('table');
 var tds = currentTable.find('tr td:nth-child(' + (i + 1) + ')');
 tds.each(function(j) { if ($(this).text().trim() == ) removeVal++; });
 if (removeVal == currentTableRows) {
 $(this).hide();
 tds.hide();
 }
 });
}); 
/* function end */
 
==== Collapsible contents in bib record ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Purpose: Do you have really long content lists that push your holdings to the bottom of the bib record? Use this to collapse excessively long content lists by default and add a button to expand and collapse the list.
* Creation Date: 2019-06-06
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.05
 
if(window.location.href.indexOf("cgi-bin/koha/opac-detail.pl?biblionumber") > -1) {
 $(document).ready(function(){
 var countclass = $(".contentblock").length; //counts number of contentblocks
 if(countclass > 1){ //if more than one contentblock
 var expander = "Click to Expand +"; //create expansion button
 function tog(){$(document).find('.contentblock').slideToggle("slow")}; //create slide toggle function
 function typ(){ //change expansion button based on display of contentblocks
 if($(".contentblock").css('display') == 'block'){
 $("#expander").text("Click to Expand +");
 }else if($(".contentblock").css('display') == 'none'){
 $("#expander").text("Click to Collapse -");
 };
 };
 $("span:contains('Contents:')").append(expander); //add expansion button to page
 $(".contentblock").hide(); //hide contentblocks initially
 $("#expander").click(function(){ //execute the two functions when the expansion button is clicked
 typ(); 
 tog();
 });
 };
 });
}
 
==== Hide "Allow changes from" in list creation screen ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: Hide the possibility to choose who to allow to change the patron lists in the OPAC
* Creation Date: 2019-07-10
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.05
 
$("select#allow_changes_from").parent("li").hide();
 
==== Reset OPAC to homepage after interval ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Purpose: If you would like your OPAC to reset after a certain amount of time and have it return to your OPAC's homepage (or somewhere else)
* Creation Date: 2019-09-12
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.11
 
if(window.location.href.indexOf("abc.catalog.org") > -1){ //This conditional may be useful if you have different library URLs; if not, you can probably ignore it
	$(document).ready(function () {
		var myReset = setInterval(goHome, 300000); //Sets the timing interval to a number of milliseconds and then executes the goHome function at the end of that interval
		function goHome() { //Function executed above that sends the window to a certain URL; here the (fictional) homepage
			window.location.replace("https://abc.catalog.org");
		}
	});
}
 
==== Add-to or replace instructions on the new purchase suggestion form ====
* Developer: George H. Williams - Next Search Catalog/NEKLS
* Purpose: Add new text to the new purchase suggestion form (opac-suggestions.pl?op=add) or completely replace the existing text
* Creation Date: 2019-10-14
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.11
//OPAC > User tabs > Your purchase suggestions > New suggestion
 //BEGIN add text to existing description/instructions
 $('#opac-usersuggestions .maincontent h1:nth-child(1)').append('Adds text to heading.');
 $('#opac-usersuggestions .maincontent p:nth-child(2)').append('Adds text to paragraph one.');
 $('#opac-usersuggestions .maincontent p:nth-child(3)').append('Adds text to paragraph two.');
 //BEGIN replace text of existing description/instructions
 $('#opac-usersuggestions .maincontent h1:nth-child(1)').html('Replaces heading.');
 $('#opac-usersuggestions .maincontent p:nth-child(2)').html('Replaces paragraph one.');
 $('#opac-usersuggestions .maincontent p:nth-child(2)').html('Replaces paragraph two.');
==== Make author a required field in new suggestion form ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: this makes the author label red, adds the "Required" hint and makes the input field mandatory
* Creation Date: 2020-03-16
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 19.05 (works on master v. 19.12.00.040)
//Make author a required field
$( "#add_suggestion_form label[for='author']").addClass("required");
$( "#add_suggestion_form input#author").attr("required","required");
$( "#add_suggestion_form label[for='author']").parent("li").append("Required");
==== Change/Add to the text in the "Thank you" box after a user submits a personal detail change request ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: this changes/adds to the text in the "success" box
* Creation Date: 2020-03-16
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 19.05 (works on master v.19.12.00.040)
//Change the text after a user submits a personal information change request
$( "#update-submitted p").text("This text replaces the current text.");
$( "#update-submitted p").append("This text is added after the current text.");
==== Remove the 'New list' button on the Public lists tab in the OPAC ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: if patrons are not allowed to create public lists, it can be confusing to see a 'New list' button under the 'Public lists' tab in the user's account. this removes the button. the button is still available in the 'Your lists' tab
* Creation Date: 2020-03-16
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 19.05 (works on master v.19.12.00.040)
//Remove the 'New list' button in the 'Public lists' tab
$( "#publicshelves a.newshelf").remove();
==== Enhance CART shelving location on details page ====
* Developer: George Williams (NEKLS / Next search catalog)
* Purpose: Adds shelving location label to details page as needed, adds icon and changes cell color if shelving loction is CART
* Creation Date: 2020.08.02
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 19.11
* Page: opac-detail.pl
 //Remove empty shelving location spans
 $('#opac-detail .shelvingloc').each(function(){
 if( $(this).text().trim() === )
 $(this).remove();
 });
 //Add doublespace between home library and shelving location (optional - not necessary if OpacLocationOnDetail is not set to "on a separate column")
 $('#opac-detail .shelvingloc').prepend('Shelving location:');
 //BEGIN enhance "Recently returned" shelving location (change "Recently returned" to whatever your library uses as the description for CART)
 $('#opac-detail .shelvingloc:contains("Recently returned")').prepend(' ').parent().css('background','yellow');
	
==== Prompt patron to choose a pick up location for holds when their library isn't a choice ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: If the pick up location is turned off for a library, the pick up location defaults to the first library in the dropdown list when placing a hold. Patrons don't notice this, and items are inadvertently routed to the wrong library. This will detect if their library isn't in the list, and add a message to choose a new pick up location. The message isn't selectable, and the Confirm hold button is disabled until they make a choice. 
* Creation Date: 2020.11.02
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 19.11
* Page: opac-reserve.pl
//Reroute Patron Pick-up Locations
 if ( !$('#opac-holds select[name="branch"] option[value=' + $('#opac-holds #members span.loggedinusername').attr('data-branchcode') + ']').length ) {
 $('#opac-holds select[name="branch"]').prepend('<option value="NONE">BRANCH CLOSED - CHOOSE PICK UP LOCATION</option>').val('NONE').width('350px');
 $('#opac-holds select[name="branch"] option[value="NONE"]').prop('disabled', true);
 $('#opac-holds input.placehold').prop('disabled', true);
 $('#opac-holds select[name="branch"]').change(function() {
 $('#opac-holds input.placehold').prop('disabled', false);
 });
 }
//End Reroute
	
==== OPAC Enhanced Suspended Hold Listings ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Show suspended and delayed hold listings more clearly 
* Creation Date: 2021-03-12
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 20.05
/*Ribbon for Suspended Holds*/
.RibbonRowAdjust {
 height: 40px;
}
.SuspendRibbon, .DelayedRibbon {
 height: 20px;
 line-height: 20px;
 padding-left: 15px;
 position: absolute;
 left: -9px;
 top: 25px;
 text-transform: uppercase;
 color: white;
}
.SuspendRibbon:before, .SuspendRibbon:after, .DelayedRibbon:before, .DelayedRibbon:after {
 content: "";
 position: absolute;
}
.SuspendRibbon:before, .DelayedRibbon:before {
 height: 0;
 width: 0;
 top: -8.5px;
 left: 0.1px;
 border-bottom: 9px solid black;
 border-left: 9px solid transparent;
}
.SuspendRibbon:after, .DelayedRibbon:after {
 height: 0;
 width: 0;
 right: -14.5px;
 border-top: 10px solid transparent;
 border-bottom: 10px solid transparent;
}
.SuspendRibbon {
 width: 130px;
 background: #f54242;
}
.SuspendRibbon:after{
 border-left: 15px solid #f54242;
}
.DelayedRibbon {
 width: 160px;
 background: #f5ad42;
}
.DelayedRibbon:after{
 border-left: 15px solid #f5ad42;
}
	
 //Suspended Hold Enhancement
 $("#holdst button:contains('Resume')").parents("tr").children('td:nth-child(1)').css('position','relative').append(' Suspended');
 
 $(".reservedate").each(function() {
 var reserveDate = $(this).children("span").first().contents().filter(function() {
 return this.nodeType == 3;
 }).text();
 var fetchDate=new Date(reserveDate);
 var fetchDay=('0'+(fetchDate.getDate())).slice(-2);
 var fetchMonth=('0'+(fetchDate.getMonth()+1)).slice(-2);
 var fetchYear=fetchDate.getFullYear();
 reserveDate=fetchYear+fetchMonth+fetchDay;
 var reserveDateDisplayed=fetchMonth+'/'+fetchDay+'/'+fetchYear;
 fetchDate=new Date();
 fetchDay=('0'+(fetchDate.getDate())).slice(-2);
 fetchMonth=('0'+(fetchDate.getMonth()+1)).slice(-2);
 fetchYear=fetchDate.getFullYear();
 var todaysDate=fetchYear+fetchMonth+fetchDay;
 if (reserveDate > todaysDate) {
 $(this).parents("tr").children('td:nth-child(1)').css('position','relative').append(' After ' + reserveDateDisplayed + '');
 }
 });
 //End Suspended Hold Enhancement
==== OPAC Enhanced Suspended/Scheduled Hold Listings ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Show suspended, delayed and scheduled hold listings more clearly 
* Creation Date: 2024-01-13
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Developed on 23.05
/*Ribbon for Suspended Holds*/
.RibbonRowAdjust {
 height: 40px;
}
.SuspendRibbon, .DelayedRibbon {
 height: 20px;
 line-height: 20px;
 padding-left: 15px;
 position: absolute;
 left: -9px;
 top: 25px;
 text-transform: uppercase;
 color: white;
}
.SuspendRibbon:before, .SuspendRibbon:after, .DelayedRibbon:before, .DelayedRibbon:after {
 content: "";
 position: absolute;
}
.SuspendRibbon:before, .DelayedRibbon:before {
 height: 0;
 width: 0;
 top: -8.5px;
 left: 0.1px;
 border-bottom: 9px solid black;
 border-left: 9px solid transparent;
}
.SuspendRibbon:after, .DelayedRibbon:after {
 height: 0;
 width: 0;
 right: -14.5px;
 border-top: 10px solid transparent;
 border-bottom: 10px solid transparent;
}
.SuspendRibbon {
 width: 130px;
 background: #f54242;
}
.SuspendRibbon:after{
 border-left: 15px solid #f54242;
}
.DelayedRibbon {
 width: 160px;
 background: #f5ad42;
}
.DelayedRibbon:after{
 border-left: 15px solid #f5ad42;
}
	
 //Get Today's Date
 const date = new Date();
 let day = ('0'+(date.getDate())).slice(-2);
 let month = ('0'+(date.getMonth()+1)).slice(-2);
 let year = date.getFullYear();
 let GlobalCurrentDate = year+'-'+month+'-'+day;
 let GlobalCompareCurrentDate = year.toString()+month.toString()+day.toString();
 //END Get Today's Date
 //Suspended/Scheduled Hold Enhancement (v23.05)
 if ($('#opac-user').length) {
 //All Active Suspensions
 $('td.status span:contains("Suspended")').each(function() {
 $(this).closest('tr').children('td:nth-child(1)').css('position','relative').append(' Suspended');
 });
 //Delayed Suspensions
 $('td.status span:contains("Suspended")').parents('tr').each(function() {
 let SuspendUntilDate = $(this).find('span:contains("Suspended")').parent('td.status').contents().filter(function() {
 return this.nodeType === 3;
 }).text().trim();
 if (SuspendUntilDate) {
 $(this).find('span.SuspendRibbon').replaceWith(' After ' + SuspendUntilDate + '');
 }
 });
 //Scheduled Holds
 $('td.reservedate').each(function() {
 let DisplayReserveDate = new Date($(this).attr('data-order'));
 let reserveDay = ('0'+(DisplayReserveDate.getUTCDate())).slice(-2);
 let reserveMonth = ('0'+(DisplayReserveDate.getUTCMonth()+1)).slice(-2);
 let reserveYear = DisplayReserveDate.getUTCFullYear();
 let CompareReserveDate = reserveYear+reserveMonth+reserveDay;
 DisplayReserveDate = reserveMonth+'/'+reserveDay+'/'+reserveYear;
 if (CompareReserveDate > GlobalCompareCurrentDate) {
 $(this).parents("tr").children('td:nth-child(1)').css('position','relative').append(' After ' + DisplayReserveDate + '');
 }
 });
 }
 //END Suspended Hold Enhancement
==== OPAC Remove the trailing / from titles ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Remove the trailing / at the end of titles in search results if there is nothing after it on the same line (author/contributor) in OPAC
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Tested and working on 21.05
* Notes: We removed the redundant author and contributor info on the title line in results. Since the / is commonly included in marc data, it remains and is unnecessary. You can find similar code for the OPAC below. This example does not include the record detail page, but could easily encompass that page as well. Consult the XSLTs for removal of redundant info on these pages.
 //REMOVE trailing '/' from title in results*/ (v21.05)
 if ( $('#results,#opac-detail').length) {
 //$('.title_resp_stmt').remove(); This line is needed if you didn't remove it with the XSLT.
 $('.title').each( function() {
 var title_text = $(this).text().trim();
 var title_lastChar = title_text.slice(title_text.length-1);
 if ( title_lastChar == '/' ) {
 var new_text = title_text.slice(0, -2);
 $(this).text(new_text);
 }
 });
 }
 //END REMOVE trailing '/' from title in results*/
==== Remove the "Libraries" link on the OPAC ====
* Developer: Caroline Cyr La Rose, inLibro
* Purpose: Remove the "Libraries" link on the OPAC, which was added in 20.05
* Creation Date: 2022
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Tested and working on 21.05
* Notes: This link caused quite a stir in the libraries we support. Bug 27360 now makes it possible to remove specific libraries from this page (available in 21.11). But even then, single-library systems feel it's not necessary to have a whole page for this.
 //Remove "Libraries" link on OPAC's main page
 $("a#library_page").parent("li").remove();
==== Move the OPAC News to the Right Navigation Panel ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/Cooperative Information Network
* Purpose: Move the news to the side of the OPAC so it doesn't push main content off screen
* Creation Date: 2024
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Tested and working on 23.05.10 (.9 has a bug in the html layout)
 //Move news to side panel (v23.05)
 if ( $('#opac-main').length) {
 $('#opac-main div.order-md-2').insertAfter('div.maincontent').attr('id','OPACSidePanel'); //Remove after bug 36359 released (23.05.10)
 if(($('#opac-main #news').length > 0) || ($('#opac-main #user_summary').length > 0) || ($('#ulactioncontainer').length > 0)) {
 $('#opac-main #news').appendTo('#OPACSidePanel');
 } else {
 $('#opac-main #OPACSidePanel').remove();
 $('div.col-lg-9').removeClass('col-lg-9').addClass('col-lg-12');
 }
 }
 //END Move news to side panel
==== Enable MathJax for formula typesetting ====
* Developer: Alexander Wagner
* Creation Date: 2024-06-25
* Purpose: Load the MathJax library to properly display mathematical formulae within the OPAC pages (titles, abstracts etc.)
* Status: Completed / In progress
* Intranet or OPAC?: OPAC (but would work on Intranet as well)
* Version: Any
 
MathJax = {
 tex: {
 inlineMath: [['$', '$'], ['\\(', '\\)']]
 }
};
$.getScript('https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js');
 
==== Add a link to self checkout under OPAC login section ====
* Developer: Koha Community
* Purpose: Add a link to the built-in self checkout function to the intranet login screen
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any (But in recent versions of Koha, you can use HTML customizations to add links to the OPAC)
* 'Note: Don't forget to change the URL to match your OPAC!
$(document).ready(function(){
 $("#login .btn").parent().after("<a href=\"http://YOUR_KOHA_OPAC_URL/cgi-bin/koha/sco/sco-main.pl\" target=\"_blank\">Self-Checkout</a>");
});
=== Search-related customizations for the OPAC ===
==== Add additional searches to OPAC ====
* Developer: Jared Camins-Esakov
* Purpose: Adds additional searches to the OPAC Search type dropdown
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
* Note: Both indexes used here are custom. In order to use the Auction date index, MARC21 field 033$a would need to be indexed and linked to CCL search prefix 'adate:'. In order to use the Journal title index, MARC21 field 773$t would need to be indexed and linked to CCL search prefix 'Host-item:'.
 
 $("select[name='idx']").append("<option value='adate'>Auction date</option><option value='Host-item,wrdl'>Journal title</option>");
 
==== Add focus to OPAC Search ====
* Developer: Jared Camins-Esakov
* Purpose: The opac search didn't seem to get focus. This adds that functionality.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.2.x (afaik)
 
$("#transl1").focus();
 
==== Append text to the OPAC search results ====
* Developer: Owen Leonard (Nelsonville Public Library)
* Purpose: Append text to the OPAC search results. Useful if you want to promote an alternate means of finding results (interlibrary loan?) or point the user to more resources (chat with a librarian?).
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any 
 
 $(".searchresults").after("Not finding what you\'re looking for? Make a <a href=\"http://koha.example.org/cgi-bin/koha/opac-suggestions.pl\">purchase suggestion</a>");
 
==== Change "Library Catalog" to "Keyword" in OPAC main search ====
* Developer: Jared Camins-Esakov
* Purpose: Changes the string "Library Catalog" to "Keyword" in the OPAC main search.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: Any
 
 $("select[name='idx'] option:first").text('Keyword');
 
==== Scope Library in OPAC Main Search Based on URL ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Creation Date: 2018-11-29
* Purpose: Scopes the library that is searched in the main OPAC drop down based on characters from the URL. This is useful if you have library-specific URLs.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.05
 
 var origin = window.location.origin; //creates a variable from URL
 var schoolCode = origin.substring(8, 11); //creates another variable from a substring of origin
 if(schoolCode == 'foo'){$("#select_library").val('multibranchlimit-1')} //changes library drop down if condition is true
 else if(schoolCode == 'bar'){$("#select_library").val('multibranchlimit-2')};
 
==== Remove language selection fieldset from OPAC advanced Search ====
* Developer: Liz Rea
* Purpose: remove language selection fieldset from OPAC advanced search
* Status: Completed
* Intranet or OPAC?: OPAC 
* Version: tested 3.4 
 
$("#advsearch legend:contains('Language')").parent().hide();
 
==== Remove Subtype Limits from OPAC Advanced Search ====
* Developer: Nicole Engard
* Purpose: remove subtype selection fieldset from OPAC advanced search
* Status: Completed
* Intranet or OPAC?: OPAC 
* Version: tested 3.4 
 
$("#advsearch legend:contains('Subtype limits')").parent().hide();
 
==== Change Availability Display in Search Results ====
* Developer: Nick Clemens
* Purpose: Hide Library names/call numbers from availability and encourage user to click on title for details. If search is branch limited show only 'Owned by Library X'
* Status: Completed
* Intranet or OPAC?: OPAC 
* Version: tested 3.12 with XSLT 
 
 var limitexist = $("title").text().match(/'.*branch:([\w- ]*)( .*:.*)*'/);
 if(limitexist==null){
 $(".results_summary.availability > .label").text("Total Availability (Click title for details): ");
 $(".available").each( function(){
 $(this).text("Libraries with copies available ("+($(this).text().split('(').length-1)+") ");
 });
 }
 else{
 $(".results_summary.availability > .label").text("Owned by "+limitexist[1]+" - click on title for availability");
 $(".available").hide();
 $(".unavailable").hide();
 }
 
==== Add Date Slider to Search Facets ====
* Developer: Joe Sikowitz, Fenway Library Organization
* Purpose: Adds a date slider to search facets so results can be narrowed by date. This actually rewrites the URL to include a date range in the search string and resends.
* Creation Date: 2019-12-10
* Updated Date: 2020-11-11
* Status: Completed
* Intranet or OPAC?: OPAC 
* Version: 19.11
 
 function searchDates() {
//declare URL variables
 var url_idx, url_q, url_sb, yr, searchcat, doo, bgl, addto;
//get page URL
 var url = window.location.href;
//parse URL to get base
 var url_base = url.substring(0, url.indexOf("?"));
//parse URL on &
 var parts = url.split("&");
//init limits array and increment
 var limits = [];
 var i;
//go through each parsed part of the array and create variables and an array of limits
 for(i=0; i < parts.length; i++) {
	if(/idx=/.exec(parts[i])) {
 	 url_idx = /idx=(.*)/.exec(parts[i]);
	}
 else if(/q=/.exec(parts[i])) {
 url_q = /q=(.*)/.exec(parts[i]);
 }
 else if(/sort_by=/.exec(parts[i])) {
 url_sb = /sort_by=(.*)/.exec(parts[i]);
 }
 else if(/limit=/.exec(parts[i])) {
 let lim = /limit=(.*)/.exec(parts[i]);
 limits.push(lim[1]);
 }
	else if(/limit-yr=/.exec(parts[i])) {
 yr = /limit-yr=(.*)/.exec(parts[i]);
	}
 else if(/searchcat=/.exec(parts[i])) {
 searchcat = /searchcat=(.*)/.exec(parts[i]);
 }
 else if(/do=/.exec(parts[i])) {
 doo = /do=(.*)/.exec(parts[i]);
 }
 else if(/branch_group_limit=/.exec(parts[i])) {
 bgl = /branch_group_limit=(.*)/.exec(parts[i]);
 }
 else if(/addto=/.exec(parts[i])) {
 addto = /addto=(.*)/.exec(parts[i]);
 }
 }
 //get the dates from the slider
 var sd = $("#date1").text();
 var ed = $("#date2").text();
 //construct the new URL with the previous search criteria
 var newurl = url_base + "?";
 if(url_idx) {
 newurl += "idx=" + url_idx[1];
 }
 else {
 newurl += "idx=kw";
 }
 if(url_q) {
 newurl += "&q=" + url_q[1];
 }
 if(url_sb) {
 newurl += "&sort_by=" + url_sb[1];
 }
 if(searchcat) {
 newurl += "&searchcat=" + searchcat[1];
 }
 if(doo) {
 newurl += "&do=" + doo[1];
 }
 if(bgl) {
 newurl += "&branch_group_limit=" + bgl[1];
 }
 if(addto) {
 newurl += "&addto=" + addto[1];
 }
 if(limits) {
	let j;
	for(j=0; j < limits.length; j++) {
 if(limits[j].indexOf("yr") > -1) {
 continue;
 }
 else {
 newurl += "&limit=" + limits[j];
 }
 }
}
 //add the new years to the URL
 newurl += "&limit-yr=" + sd + "-" + ed;
 //go to the new URL
 window.location.href = newurl;
}
//comment below can be used for testing purposes
//document.getElementById("translControl1").value = url_idx[1] + " " + url_q[1] + " " + url_sb[1] + " " + limits[1] + " " + yr[1] + " " + searchcat[1] + " " + doo[1];
//construct date slider widget
if((window.location.href.indexOf("cgi-bin/koha/opac-search.pl") > -1) && (screen.width>768)){
	$(document).ready(function () {
		let d = new Date();
		let enddate = d.getFullYear();
		$("ul.menu-collapse").append("Date Range1700to" + enddate + "<button type='submit' onclick='searchDates()'>Add Date Range</button>");
		var updateSliderValue = function (event, ui) {$("#date1").text($("#slider").slider("values", 0)); $("#date2").text($("#slider").slider("values", 1));};
		$("#slider").slider({range:true, min: 1700, max: enddate, values: [1700, enddate], stop:updateSliderValue});
	});
}
 
==== Enhanced Search Facets for OPAC ====
* Developer: Christopher Brannon - Coeur d'Alene Public Library / Cooperative Information Network
* Purpose: Collapse and enhance the search facets, adding check boxes, making them responsive and cleaner
* Creation Date: 2020-04-01
* Status: Completed
* Intranet or OPAC?: OPAC 
* Version: 19.11
 
//Revamp Facets
 //Place headers around stray section titles so we can control these later.
 $('#facetcontainer #search-facets').children('ul').children('li').children('h3').wrap('<a class="viewSwitch" style="text-decoration: none; cursor: pointer;" />');
 
 //Add functionality to headers for visibility and collapsing/expanding sections, and show entire contents in section
 $('#facetcontainer #search-facets a.viewSwitch h3').prepend(' ');
 $('#facetcontainer #search-facets a.viewSwitch').parent().children('ul').wrap('');
 $('#facetcontainer div.contentsToggle').hide();
 $('#facetcontainer').find('li.moretoggle').remove();
 $('#facetcontainer .collapsible-facet').show().removeAttr('class').removeAttr('style');
 $("#facetcontainer a.viewSwitch").click(function() {
 $(this).parent().children('.contentsToggle').toggle('slow');
 if ($(this).find('i').hasClass('fa-caret-right')) {
 $(this).find('i').addClass('fa-caret-down').removeClass('fa-caret-right');
 } else {
 $(this).find('i').addClass('fa-caret-right').removeClass('fa-caret-down');
 }
 });
 
 //Rebuild and replace facets with improved facets with checkboxes
 $('#facetcontainer .facet-label a').removeAttr('title').css('text-decoration','none').attr('role','status').after(function() {
 	return $(this).clone().attr('role','label');
 });
 $('#facetcontainer a[role="status"]').html(' ');
 $('#facetcontainer a[role="label"]').replaceWith(function() { return this.innerHTML; });
 $('#facetcontainer a[title^="Remove facet"]').closest('li').contents().filter(function() {
 	return this.nodeType == 3 && this.nodeValue.trim();
 }).remove();
 $('#facetcontainer a[title^="Remove facet"]').css('text-decoration','none').each(function() {
 $(this).prependTo($(this).siblings('span'));
 });
 
 //Change facet checkbox to checked if in use
 $('#facetcontainer a[title^="Remove facet"]').html(' ');
 
 //Expand sections that have active facets
 $('#facetcontainer a[title^="Remove facet"]').closest('.contentsToggle').siblings('.viewSwitch').trigger('click');
 
 //Add spinner to show that Koha is doing something after click
 $('#facetcontainer a[title^="Remove facet"]').on('click', function() {
 $(this).find('i').removeClass('fa-check-square').addClass('fa-spinner fa-spin');
 });
 $('#facetcontainer a[role="status"]').on('click', function() {
 $(this).find('i').removeClass('fa-square-o').addClass('fa-spinner fa-spin');
 });
//End Revamp Facets
 
=== Enhanced content for the OPAC ===
==== Add direct export to RefWorks link to OPAC ====
* Developer: Jared Camins-Esakov, ByWater Solutions
* Purpose: Add a link to directly export a citation to RefWorks
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.2+
 
 function getParameterByName( name )
 {
 name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
 var regexS = "[\\?&]"+name+"=([^&#]*)";
 var regex = new RegExp( regexS );
 var results = regex.exec( window.location.href );
 if( results == null )
 return "";
 else
 return decodeURIComponent(results[1].replace(/\+/g, " "));
 }
 $(document).ready(function(){
 $("<a href='http://www.refworks.com/express/expressimport.asp?vendor=Koha&filter=RIS%20Format&encoding=65001&url=http%3A%2F%2F" + location.host + "%2Fcgi-bin%2Fkoha%2Fopac-export.pl%3Fop%3Dexport%26format%3Dris%26bib%3D" + getParameterByName('biblionumber') + "' target='RefWorksMain'>Export to RefWorks</a>").appendTo("#export");
 $("#userbasket #toolbar .download").parent().after("<a class='download' href='http://www.refworks.com/express/expressimport.asp?vendor=Koha&filter=RIS%20Format&encoding=65001&url=http%3A%2F%2F" + location.host + "%2Fcgi-bin%2Fkoha%2Fopac-downloadcart.pl%3Fformat%3Dris%26bib_list%3D" + encodeURIComponent(getParameterByName('bib_list')) + "' target='RefWorksMain'>Export to RefWorks</a>")
 $("#usershelves #toolbar .download").after("<a class='download tag_hides' href='http://www.refworks.com/express/expressimport.asp?vendor=Koha&filter=RIS%20Format&encoding=65001&url=http%3A%2F%2F" + location.host + "%2Fcgi-bin%2Fkoha%2Fopac-downloadshelf.pl%3Fformat%3Dris%26shelfid%3D" + encodeURIComponent(getParameterByName('viewshelf')) + "' target='RefWorksMain'>Export to RefWorks</a>");
 });
 
==== Add a link to map the publisher's location ====
* Developer: Jared Camins-Esakov, C & P Bibliography Services
* Purpose: Add a link to map the publisher's location.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: All
* Note: This particular implementation is for MARC21, and retrieves the location from an authority-controlled 751. In order to identify the correct 751, it looks for the relator code 'pup' (place of publication).
 
 $.get("/cgi-bin/koha/opac-export.pl",
 { bib: $("input[name='bib']").val(), format: "marcxml" },
 function(data){
 $(".publisher > span[class='label']:first").append("<a target='_blank' href='http://maps.google.com/maps?q=" + $(data).find("datafield[tag='751'] > subfield[code='4']:contains('pup')").parent().find("subfield[code='a']").text() + "'><img src='/opac-tmpl/prog/famfamfam/MP.png' alt='Show publisher on map' title='Show publisher on map' /></a>");
 }
 );
 
* Note: This particular implementation is for MARC21, and retrieves the location from the 260$a, then removes any trailing punctuation. For all but the most recent of books, this is likely to result in an inaccurate (or useless) map.
 
 $.get("/cgi-bin/koha/opac-export.pl",
 { bib: $("input[name='bib']").val(), format: "marcxml" },
 function(data){
 $(".publisher > span[class='label']:first").append("<a target='_blank' href='http://maps.google.com/maps?q=" + $(data).find("datafield[tag='260'] > subfield[code='a']").text().replace(/\W+$/, ) + "'><img src='/opac-tmpl/prog/famfamfam/MP.png' alt='Show publisher on map' title='Show publisher on map' /></a>");
 }
 );
 
==== Add links out to Wikipedia for authors ====
* Developer: Stefano Bargioni (Pontificia Università della Santa Croce)
* Creation Date: 2014-02-14
* Purpose: Add a link for each author to bring the user to a Wikipedia search
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: all (tested in 3.12)
 
var names = $('h5.author a').not('.authlink');
for (var i=0; i < names.length; i++) {
	var name_string = $(names[i]).text(); // mostly surname, name
	var fs = (name_string+', ').split(', ');
	var H = new Array;
	H.push(' ');
	H.push('<a target="_blank" href="https://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=');
	H.push(encodeURIComponent(fs[1]+' '+fs[0]));
	H.push('"><img src="https://upload.wikimedia.org/wikipedia/commons/b/b0/Wikipedia-favicon.png"/></a>');
	H.push('');
	$(names[i]).after(H.join());
};
 
* Developer: Jared Camins-Esakov, C & P Bibliography Services
* Purpose: Add a link for each author to bring the user to a Wikipedia search [obsolete]
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: before 3.12
 
 $("h5.author > a").each(function() {
 $("<a href='http://en.wikipedia.org/wiki/Special:Search?search=" + encodeURI($(this).text().replace(/\[.*\]/g, ).replace(/[\W\d]+$/, )) + "' title='Search for this person in Wikipedia'><img src='http://upload.wikimedia.org/wikipedia/commons/b/b0/Wikipedia-favicon.png'/></a>").insertAfter($(this));
 });
 
----
==== Add iDreamBooks.com Readometer to OPAC ====
* Developer: C & P Bibliography Services
* Purpose: Add a "Readometer" from iDreamBooks.com to the OPAC to show aggregated information about reviews of the book by professional critics.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.6+ with XSLT enabled for the OPAC details page
* Note: This is an updated version that offers better web browser compatibility. Anyone using the iFrame version originally posted should switch.
 var isbn = $(".isbn:last").text().split(" ")[1];
 if (isbn) {
 isbn = isbn.replace(/\W*$/, );
 if ($.browser.msie && parseInt($.browser.version, 10) >= 8 && window.XDomainRequest) {
 // Use Microsoft XDR for IE version 8 or above
 var xdr = new XDomainRequest();
 xdr.open("get", "http://idreambooks.com/newbooks/api.json?q="+encodeURIComponent(isbn)+"&key=8bf66516232d1b72f3e47df939653e1e");
 xdr.onload = function() {
 if (! typeof(json) == 'undefined') {
 json = 'json = '+xdr.responseText; // the string now looks like.. json = { ... };
 eval(json); // json is now a regular JSON object
 $(".title").append('<a href="'+json.book.detail_link+'" id="idreambooksreadometer"><img src="http://idreambooks.com/remotereadometer/'+isbn+'.jpg" alt="'+json.book.title+' by '+json.book.author+'" title="Rating based on reviews of '+json.book.title+'"></a>');
 }
 }
 xdr.send();
 } else {
 $.getJSON("http://idreambooks.com/newbooks/api.json?q="+encodeURIComponent(isbn)+"&key=8bf66516232d1b72f3e47df939653e1e", function(json){
 if (! typeof(json) == 'undefined') {
 $(".title").append('<a href="'+json.book.detail_link+'" id="idreambooksreadometer"><img src="http://idreambooks.com/remotereadometer/'+isbn+'.jpg" alt="'+json.book.title+' by '+json.book.author+'" title="Rating based on reviews of '+json.book.title+'"></a>');
 }
 });
 }
 }
You will also need the following line of CSS in your OPACUserCSS:
#idreambooksreadometer {
 float: right;
}
==== Add iDreamBooks.com reviews tab to OPAC (3.6-3.8) ====
* Developer: C & P Bibliography Services
* Purpose: Add a tab with snippets of reviews from iDreamBooks.com to the OPAC
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.6-3.8 with XSLT enabled for the OPAC details page (3.10 script below)
var isbn = $(".isbn:last").text().split(" ")[1];
if (isbn) {
 isbn = isbn.replace(/\W*$/, );
 if ($.browser.msie && parseInt($.browser.version, 10) >= 8 && window.XDomainRequest) {
 // Use Microsoft XDR for IE version 8 or above
 var xdr = new XDomainRequest();
 xdr.open("get", "http://idreambooks.com/newbooks/api.json?q="+encodeURIComponent(isbn)+"&key=8bf66516232d1b72f3e47df939653e1e");
 xdr.onload = function() {
 json = 'json = '+xdr.responseText; // the string now looks like.. json = { ... };
 eval(json); // json is now a regular JSON object
 parseIDBJSON(json); // parse using same function as for jQuery's success event
 }
 xdr.send();
 } else {
 $.getJSON("http://idreambooks.com/newbooks/api.json?q="+encodeURIComponent(isbn)+"&key=8bf66516232d1b72f3e47df939653e1e", function(json){
 parseIDBJSON(json);
 });
 }
}
// NOTE THAT THE CODE BELOW SHOULD NOT GO IN $(document).ready.
function parseIDBJSON( json ) {
 if(json.total_results > 0 && json.book.rating > 0){
 var isbn = $(".isbn:last").text().split(" ")[1];
 //build new tab for critic reviews
 $("#bibliodescriptions").append('<a id="seemoreidb">More book reviews at iDreamBooks.com</a>');
 
 $("#bibliodescriptions ul").tabs('add', '#idb_critic_reviews', 'Book reviews by critics ( '+json.book.review_count+' )');
 //append happy-sad cloud review
 $("#catalogue_detail_biblio").append("<a href='"+json.book.detail_link+"'><img src='"+json.book.to_read_or_not_small+"' alt='"+json.book.title+" by "+json.book.author+"' title='Rating based on reviews of "+json.book.title+"'>"+json.book.rating+"%</a> <a href='http://www.idreambooks.com/'>rating based on reviews at iDreamBooks.com</a>");
 //insert data into Book reviews tab
 $.each(json.book.critic_reviews, function(){
 $("#idb_review_snippets").append("<a href='"+this.review_link+"'>"+this.source+"</a>\"..."+this.snippet+"...\"Review date: "+this.review_date+"<a class='reviewlink' href='"+json.book.detail_link+"'>Review result: "+this.pos_or_neg+" <img src='"+this.smiley_or_sad_small+"' alt='iDreamBooks.com rating' title='"+this.pos_or_neg+"' /></a>");
 });
 $("#seemoreidb").attr('href', json.book.detail_link);
 }
}
You will also need the following CSS added to your OPACUserCSS syspref:
.review {
 margin-bottom: 20px;
}
a.idreambooksrating {
 font-size: 30px;
 color: #29ADE4;
 padding-left: 85px;
 line-height: 30px;
 text-decoration: none;
}
.idreambookslegend {
 font-size: small;
}
a.reviewlink,a.reviewlink:visited {
 text-decoration: none;
 color: black;
 font-weight: normal;
}
.idreambookssummary a {
 color: #707070;
 text-decoration: none;
}
.idreambookssummary img, .idbresult img {
 vertical-align: middle;
}
.idbresult {
 color: #29ADE4;
 text-align: center;
 margin: 0.5em;
 padding: 0.5em;
}
.idbresult a, .idbresult a:visited {
 text-decoration: none;
 color: #29ADE4;
}
.idbresult img {
 padding-right: 6px;
}
==== Add iDreamBooks.com reviews tab to OPAC (3.10+) ====
* Developer: C & P Bibliography Services
* Purpose: Add a tab with snippets of reviews from iDreamBooks.com to the OPAC
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.10+ with XSLT enabled for the OPAC details page (3.6-3.8 script above)
var isbn = $(".isbn:last").text().split(" ")[1];
if (isbn) {
 isbn = isbn.replace(/\W*$/, );
 if ($.browser.msie && parseInt($.browser.version, 10) >= 8 && window.XDomainRequest) {
 // Use Microsoft XDR for IE version 8 or above
 var xdr = new XDomainRequest();
 xdr.open("get", "http://idreambooks.com/newbooks/api.json?q="+encodeURIComponent(isbn)+"&key=8bf66516232d1b72f3e47df939653e1e");
 xdr.onload = function() {
 json = 'json = '+xdr.responseText; // the string now looks like.. json = { ... };
 eval(json); // json is now a regular JSON object
 parseIDBJSON(json); // parse using same function as for jQuery's success event
 }
 xdr.send();
 } else {
 $.getJSON("http://idreambooks.com/newbooks/api.json?q="+encodeURIComponent(isbn)+"&key=8bf66516232d1b72f3e47df939653e1e", function(json){
 parseIDBJSON(json);
 });
 }
}
function parseIDBJSON( json ) {
 if(json.total_results > 0 && json.book.rating > 0){
 var isbn = $(".isbn:last").text().split(" ")[1];
 //build new tab for critic reviews
 $("#bibliodescriptions").append('<a id="seemoreidb">More book reviews at iDreamBooks.com</a>');
 
 $("#bibliodescriptions").tabs('add', '#idb_critic_reviews', 'Book reviews by critics ( '+json.book.review_count+' )');
 //append happy-sad cloud review
 $("#catalogue_detail_biblio").append("<a href='"+json.book.detail_link+"'><img src='"+json.book.to_read_or_not_small+"' alt='"+json.book.title+" by "+json.book.author+"' title='Rating based on reviews of "+json.book.title+"'>"+json.book.rating+"%</a> <a href='http://www.idreambooks.com/'>rating based on reviews at iDreamBooks.com</a>");
 //insert data into Book reviews tab
 $.each(json.book.critic_reviews, function(){
 $("#idb_review_snippets").append("<a href='"+this.review_link+"'>"+this.source+"</a>\"..."+this.snippet+"...\"Review date: "+this.review_date+"<a class='reviewlink' href='"+json.book.detail_link+"'>Review result: "+this.pos_or_neg+" <img src='"+this.smiley_or_sad_small+"' alt='iDreamBooks.com rating' title='"+this.pos_or_neg+"' /></a>");
 });
 $("#seemoreidb").attr('href', json.book.detail_link);
 $("#tab_idb_critic_reviews").show();
 }
}
You will also need the following CSS added to your OPACUserCSS syspref:
.review {
 margin-bottom: 20px;
}
a.idreambooksrating {
 font-size: 30px;
 color: #29ADE4;
 padding-left: 85px;
 line-height: 30px;
 text-decoration: none;
}
.idreambookslegend {
 font-size: small;
}
a.reviewlink,a.reviewlink:visited {
 text-decoration: none;
 color: black;
 font-weight: normal;
}
.idreambookssummary a {
 color: #707070;
 text-decoration: none;
}
.idreambookssummary img, .idbresult img {
 vertical-align: middle;
}
.idbresult {
 color: #29ADE4;
 text-align: center;
 margin: 0.5em;
 padding: 0.5em;
}
.idbresult a, .idbresult a:visited {
 text-decoration: none;
 color: #29ADE4;
}
.idbresult img {
 padding-right: 6px;
}
==== Duplicate Novelist readalikes into the right sidebar on opac-detail.pl ====
* Developer: Jason Robb (SEKLS)
* Purpose: Creates a brief preview of Novelist content on the right sidebar in opac-detail.pl to lure patrons down the page for full content.
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 3.22 (Requires Novelist Select subscription)
* Note: I could only get this to work with two separate document.ready clauses. You can see the intended result in my OPAC.
//Wrap this in the first $(document).ready()
$("#NovelistSelect").clone().prop({ id: "NovSidebar"}).appendTo("#ulactioncontainer"); //Duplicates Novelist content and adds it to the right side of the page
//Wrap this in the second $(document).ready()
$(window).load(function() {
if ($(".NovSimilarTitles").length) {
 $("#NovSidebar h3").text("You might also like...");
 $("#NovSidebar").append("<a href='#NovelistSelect' name='#NovelistSelect' id='MoreBelow'>See more recommendations</a>");
 $('#MoreBelow').click(function(){
 $('html, body').animate({
 scrollTop: $( $.attr(this, 'href') ).offset().top
 }, 500);
 return false;
	});
	} else {
		$("#NovSidebar h3").hide();
		$("#NovelistSelect h3").hide();
	}
});
I adjusted some styles for a cleaner look. It hides much of the cloned content and formats what's left. The styles are somewhat specific to my OPAC so they'll likely need tweaked. This goes in the OPACUserCSS syspref.
#NovSidebar .NovSeriesInfo, #NovSidebar .NovSimilarSeries, #NovSidebar .NovSimilarAuthors, #NovSidebar .NovAppeals, #NovSidebar .NovGoodReads, #NovSidebar .NovLibraryAwareNewsletter, #NovSidebar .NoveResourceRecommendation, #NovSidebar .NovRelatedFeatures, #NovSidebar .NovLexileInfo, #NovSidebar em, .NovSimilarTitles > .NovSectionHeader, .NovSimilarTitles > .NovSectionBody > div {
	display: none;
	}
#NovSidebar > div {
 margin-bottom: -75px;
 }
#NovSidebar .NovSimilarTitles {
 margin-top: -30px;
 margin-bottom: 25px;
 overflow-y: hidden;
 padding-bottom: 0px;
 }
#MoreBelow {
 background: #fcb03f;
 color: white;
 display: block;
 float: right;
 font-size: medium;
 font-variant: unicase;
 font-weight: bolder;
 margin-right: -208px;
 margin-top: -145px;
 padding: 10px 0 10px 46px;
 transform: rotate(-90deg);
 width: 290px;
 transition: margin-top 0.5s ease;
	}
#MoreBelow:hover {
 margin-top: -135px;
	}
==== Add link to HathiTrust on results and details page if isbn or oclc number found and content in public domain ====
* Developer: Nick Clemens
* Purpose: Adds a link to free materials available from hathi trust
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 17.05
* Note: This could certainly be simplified, but this works :-)
$(document).ready(function(){
//add hathi to results
 if ($("#results").length) {
 $("input[name='biblionumber']").each(function(){
 var bnum = $(this).val();
 $.getJSON("/cgi-bin/koha/svc/report?id=400&sql_params=" + bnum, function(data) {
 $.each(data, function(index, value) {
 if( value[0] ){
 $.getJSON("https://catalog.hathitrust.org/api/volumes/brief/isbn/" + value[0] + ".json", function(data) {
 if( Object.keys(data.records).length ){
 var h_url = data.records[Object.keys(data.records)[0]].recordURL;
 var p_d = data.items[Object.keys(data.items)[0]].rightsCode;
 if( h_url.length > 0 && p_d == 'pd' ){
console.log($("#bib"+bnum).parent('tr').find('.results_summary.availability'));
 $("#bib"+bnum).closest('tr').find('.results_summary.availability').append('<a href="'+h_url+'">Access on HathiTrust</a>');
 }
 } 
 });
 } else {
 $.getJSON("/cgi-bin/koha/svc/report?id=398&sql_params=" + bnum, function(data) {
 $.each(data, function(index, value) {
 if( value[0] ){
 oclc_num = value[0].replace(/\D/g,);
 $.getJSON("https://catalog.hathitrust.org/api/volumes/brief/oclc/" + oclc_num + ".json", function(data) {
 if( Object.keys(data.records).length ){
 var h_url = data.records[Object.keys(data.records)[0]].recordURL;
 var p_d = data.items[Object.keys(data.items)[0]].rightsCode;
 if( h_url.length > 0 && p_d == 'pd' ){
 $(".record").append('<a href="'+h_url+'">Access on HathiTrust</a>');
 } 
 }
 });
 }
 });
 });
 }
 });
 });
 });
 }
 //add hathi link to details page
 if ($("#opac-detail").length) {
 var bnum = $("input[name='bib']").val();
 $.getJSON("/cgi-bin/koha/svc/report?id=400&sql_params=" + bnum, function(data) {
 $.each(data, function(index, value) {
 if( value[0] ){
 $.getJSON("https://catalog.hathitrust.org/api/volumes/brief/isbn/" + value[0] + ".json", function(data) {
 var h_url = data.records[Object.keys(data.records)[0]].recordURL;
 var p_d = data.items[Object.keys(data.items)[0]].rightsCode;
 if( h_url.length > 0 && p_d == 'pd' ){
 $(".record").append('<a href="'+h_url+'">Access on HathiTrust</a>');
 }
 
 });
 } else {
 $.getJSON("/cgi-bin/koha/svc/report?id=398&sql_params=" + bnum, function(data) {
 $.each(data, function(index, value) {
 if( value[0] ){
 oclc_num = value[0].replace(/\D/g,);
 $.getJSON("https://catalog.hathitrust.org/api/volumes/brief/oclc/" + oclc_num + ".json", function(data) {
 var h_url = data.records[Object.keys(data.records)[0]].recordURL;
 var p_d = data.items[Object.keys(data.items)[0]].rightsCode;
 if( h_url.length > 0 && p_d == 'pd' ){
 $(".record").append('<a href="'+h_url+'">Access on HathiTrust</a>');
 } 
 });
 }
 });
 });
 }
 });
 });
 }
});
==== Add database placards in search results based on keywords (v18.x) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds a placard link advertising a database in OPAC results based on preset keywords
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.x
* Notes: Fill kw_keywords with as many keywords as needed. Place in single quotes and separate with commas. Replace [LINK TO DATABASE], [LINK TO IMAGE] and [DESCRIPTION OF DATABASE].
//Placards
var kw_keywords = ['keyword1','keyword2'];
var kw_count = 0;
while (kw_count < kw_keywords.length) {
	if ( $('#results a').is(':contains(Results):contains(kw):contains('+kw_keywords[kw_count]+')') ) {
		$('div.searchresults tbody tr').eq(1).after('<a href="[LINK TO DATABASE]" target="_blank"><img src="[LINK TO IMAGE]" width="150" style="float: left; padding-right: 20px;">Looks like you are searching for [DESCRIPTION OF DATABASE].Click here to go to the database.</a>');
		kw_count = kw_keywords.length;
	} else {
		kw_count++;
	}
}
//End Placards
==== Add database placards in search results based on keywords (v19.x) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds a placard link advertising a database in OPAC results based on preset keywords
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 19.x
* Notes: This version addresses changes made to the structure of the breadcrumbs that is searched for the keywords in 19.05. Fill kw_keywords with as many keywords as needed. Place in single quotes and separate with commas. Replace [LINK TO DATABASE], [LINK TO IMAGE] and [DESCRIPTION OF DATABASE].
//Placards
var kw_keywords = ['keyword1','keyword2'];
var kw_count = 0;
while (kw_count < kw_keywords.length) {
	if ( $('#results a').is(':contains(Results):contains('+kw_keywords[kw_count]+')') && ($('#results a[title*="kw"]').length) ) {
		$('div.searchresults tbody tr').eq(1).after('<a href="[LINK TO DATABASE]" target="_blank"><img src="[LINK TO IMAGE]" width="150" style="float: left; padding-right: 20px;">Looks like you are searching for [DESCRIPTION OF DATABASE].Click here to go to the database.</a>');
		kw_count = kw_keywords.length;
	} else {
		kw_count++;
	}
}
//End Placards
==== Add database placards in search results based on keywords (v20.x) ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Adds a placard link advertising a database in OPAC results based on preset keywords
* Status: Completed
* Creation Date: 2021-04-01
* Intranet or OPAC?: OPAC
* Version: 20.x
* Notes: This version is not necessarily changed because of coding changes in 20.x. It might work in 19.x, but I have not tested it. Most of the changes are cosmetic and incorporating CSS adjustments and clearer instructions. Fill kw_keywords with as many keywords as needed. Place in single quotes and separate with commas. Replace LINK_TO_DATABASE, LINK_TO_IMAGE and DESCRIPTION_OF_CONTENT. Note that you can easily define which row the placard appears on with the placard_row variable. And there is a new placard_second_row variable for a second appearance.
/*Placards*/
.placard-cell {
 background-color: transparent!important;
}
.placard {
 position: relative;
 background-color: lightyellow;
 border: 1px solid black!important;
 border-radius: 7px;
 min-height: 150px;
 padding: 5px;
}
.placard-left {
 float: left;
 padding-right: 10px;
}
.placard-img {
 max-height: 150px;
}
 //Placards to show in results on opac-search.pl
 //This will create a new expression (iContains) that will be a case-insensitive version of Contains.
 jQuery.expr[':'].iContains = function(a, i, m) {
 return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
 };
 var placard_row = 2; //Use 0 to disable
 var placard_second_row = 12; //Use 0 to disable - must be at least 2 rows more than placard_row.
 var placard_count = 0;
 
 //Define each placard [[keywords],image path,content],...
 //Entire placard variable should be in the pattern of [[keywords for 1st placard],image path, description of content],[keywords for 2nd placard],image path, description of content],etc.]
 
 var placards = [
 [['keyword1','keyword2','keyword3','keyword4','keyword5'],'LINK_TO_IMAGE','<a href="LINK_TO_DATABASE">DESCRIPTION_OF_CONTENT</a>']];
	
 //Placard logic and placement
 if (placard_row > 0) {
 while (placard_count < placards.length) {
 var kw_count = 0;
 while (kw_count < placards[placard_count][0].length) {
 if ($('ul.breadcrumb a').is(':contains(Results):iContains('+placards[placard_count][0][kw_count]+')') && ($('ul.breadcrumb a[title*="You searched"]').length) ) {
 $('div.searchresults tbody tr').eq(placard_row - 1).before('<img src="'+placards[placard_count][1]+'">'+placards[placard_count][2]+'');
 if (($('div.searchresults tbody tr').length > placard_second_row) && (placard_second_row > 0) && (placard_second_row > placard_row+1)) {
 $('div.searchresults tbody tr').eq(placard_second_row - 1).before('<img src="'+placards[placard_count][1]+'">'+placards[placard_count][2]+'');
 }
 kw_count = placards[placard_count][0].length;
 } else {
 kw_count++;
 }
 }
 placard_count++;
 }
 }
 //END Placards to show in results on opac-search.pl
==== Enhance OverDrive or similar resource counts on OPAC results ====
* Developer: Christopher Brannon (Coeur d'Alene Public Library / Cooperative Information Network)
* Purpose: Turns the OverDrive (or other resource) counts on the results page into a placard to draw more attention to this resource
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 18.05
* Notes: The line with the DOMSubtreeModified reference was added to wait for the search to end before enhancing, in case there were no results.
//Enhance OverDrive results
$("body").on('DOMSubtreeModified', "#overdrive-results", function() {
$('#overdrive-results').css('padding-top','20px').wrap('');
$('#overdrive-banner td').prepend('<img src="[LINK TO IMAGE]" width="150" style="float: left; padding-right: 20px;">');
});
//End OverDrive
==== Enhance results from the Hoopla Plug-in ====
* Developer: George Williams (Northease Kansas Library System / Next Search Catalog) - modifys code created by Christopher Brannon
* Purpose: Turns the Hoopla results data into a placard to draw more attention to this resource
* Status: Completed
* Intranet or OPAC?: OPAC
* Version: 20.05
* Notes: Change the URL in #hoopla-banner to match the location of the banner you'd like to display
//Enhance Hoopla results
 jQuery(document).ready(checkContainer);
 function checkContainer() {
 if ($('#hoopla_results').is(':visible')) {
 $('#hoopla_results').css('padding-top', '20px').wrap('');
 $('#hoopla-banner td').prepend('<img src="https://www.idaho.gov/assets/business-74595c3f85cf8df2cfe25d62642662d5cecc67ddc505a845d1175d289992bbb9.jpg" style="float: left; padding-right: 20px; max-width: 400px; height: auto;">');
 $('#numresults').clone().appendTo('#userresults');
 $('#hoopla_results a').each(function() {
 var text = $(this).text();
 $(this).text(text.replace('results in Hoopla', 'results in Hoopla for this search'));
 });
 } else {
 setTimeout(checkContainer, 50); //wait 50 ms, then try again
 }
 }
=== Enhanced content for the Staff ===
==== Add ability to search authority records through ID ====
* Developer: Stefano Bargioni (Pontificia Università della Santa Croce) - 2013-12-06
* Purpose: Allow cataloguers to search authority records through ID
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: tested on Koha 3.12
 
if (location.pathname.indexOf('authorities/authorities-home.pl')>-1 || location.pathname.indexOf('authorities/detail.pl')>-1) {
	$('#breadcrumbs').before('<form action="detail.pl">Search by authority ID: <input size="8" name="authid"> <input value="Submit" type="submit" class="submit"></form>'); $('#authid').css('margin-left','200px');
}
 
==== Add VIAF autosuggest for new NAME authorities ====
* Developer: Stefano Bargioni (Pontificia Università della Santa Croce) - 2013-12-02
* Purpose: Allow cataloguers to search VIAF database while creating new NAME authorities
* Status: Completed
* Intranet or OPAC?: Intranet
* Version: tested on Koha 3.2, Koha 3.12, Koha 3.16, Koha 3.22
 
if (document.location.href.indexOf('_NAME') == document.location.href.length-5 || // match /cgi-bin/koha/authorities/authorities.pl?authtypecode=....._NAME
	document.location.href.indexOf('authorities/authorities.pl?authid=')>-1) {
	if (document.location.href.indexOf('authorities/authorities.pl?authid=')>-1) {
		var title = $('h1').text();
		if (title.indexOf('Name')!=title.length-4) return; // not available for non-NAME headings
	}
	function myUpperCase(s) {
		if (s.indexOf('nli')>-1) return 'NLI'+s.substr(3);
		return s.toUpperCase();
	}
	function autoComplete() {
		$('head').append('<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.19/themes/base/jquery.ui.all.css">');
		// Koha 3.12.x
		$('#authoritytabs').prepend('\
			\
				<label for="viaf">VIAF Autosuggest:</label> <input type="text" style="font-size:0.9em" id="viaf" size="80" title="digitare almeno i primi 3 caratteri di un nome">\
			\
		');
		// Koha 3.2
		$($('ul.toolbar')[0]).append('\
			\
				<label for="viaf">VIAF Autosuggest:</label> <input type="text" style="font-size:0.9em" id="viaf" size="80" title="digitare almeno i primi 3 caratteri di un nome">\
			\
		');
		$(function() {
			$( "#viaf" ).autocomplete({
				source: function( request, response ) {
					$.ajax({
						url: "http://viaf.org/viaf/AutoSuggest",
						dataType: "jsonp",
						data: {
							query: request.term
						},
						success: function( data ) {
							if (!data.result) return false;
							response( $.map( data.result, function( item ) {
								return {
									label: item.term,
									value: item.term,
									item: item
								}
							}));
						}
					});
				},
				minLength: 3,
				select: function( event, ui ) {
					$('#viaf_table').remove();
					var H = new Array;
					H.push('');
					H.push(''+ui.item.item.term);
					var viafid = ui.item.item.viafid;
					// VIAF permalink
					H.push('<a target="viaf" href="http://viaf.org/viaf/'+viafid+'"><img src="http://viaf.org/viaf/images/viaf-link.png" class="viaf_flag"></a>VIAF'+viafid);
					for (var i in ui.item.item) {
						var flag = '<img src="http://viaf.org/viaf/images/flags/'+myUpperCase(i)+'.png" class="viaf_flag">';
						if (i!='viafid' && i!='term') {
							if (myUpperCase(i)=='LC') {
								// LoC permalink
								H.push('<a target="loc" href="http://lccn.loc.gov/'+ui.item.item[i]+'">'+flag+'</a>'+myUpperCase(i)+''+ui.item.item[i]);
							}
							else {
								H.push(''+flag+''+myUpperCase(i)+''+ui.item.item[i]);
							}
						}
					}
					H.push('');
					$('#viaf').after(H.join());
					$('#viaf_table').css('margin-top','5px');
					$('.viaf_flag').css('border','0');
				},
				open: function() {$( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); $('ul li').css('list-style-type','none'); },
				close: function() {$( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );}
			});
		});
	}
	// load jquery-ui to get autocomplete method (for Koha without it)
	if (!jQuery.ui.version) {
		$.ajax({
			url: 'http://code.jquery.com/ui/1.11.1/jquery-ui.min.js',
			dataType: "script",
			success: autoComplete
		});
	}
	else { autoComplete() }
}
 
==== Change the default view on OPAC detail pages ====
* Developer: Owen Leonard
* Creation Date: 2012-10-19
* Purpose: to change the default view on OPAC or Intranet detail pages from holdings to, in this case, the title notes tab. The "1" indicates the number of the tab, starting with 0, so for title notes, you would need tab 1.
* Status: Completed
* Intranet or OPAC?: OPAC or Intranet
* Version:3.8.
 $('#bibliodescriptions > ul').tabs('select', 1);
In 3.10 use:
 $('#bibliodescriptions').tabs('select', 1);
In 3.12 use:
$('#bibliodescriptions').tabs({ active: 1 } );
===SCO JQuery Statements===
==== Hitting "Enter" key in the username field will jump focus to the password field instead of submitting form ====
* Developer: Kyle M Hall
* Purpose: To allow patrons to scan library cards into the login field
* Status: Completed
* Version: Any
 
$(document).ready(function(){
 $('#patronlogin').keypress(function(e){
 if (e.keyCode == 13){
 $('#patronpw').focus();
 return false;
 }
 }); 
});
 
====Change wording on the self-check patron login screen====
* Developer: Jesse Maseto
* Creation Date: 2017/01/10
* Purpose: Allows the library to edit the wording on self-check patron login screen
* Status: Completed
* Version: any
$(document).ready(function(){ 
$(".sco_entry label[for='patronlogin']").html("Barcode:");
$(".sco_entry label[for='patronpw']").html("PIN:");
});
====Self Checkout Overhaul====
* Developer: Christopher Brannon - Coeur d'Alene Public Library/Cooperative Information Network
* Creation Date: 2024/05/22
* Purpose: This will add a keypad for touchscreen entry, and fixes a few cosmetic things, making it a little more secure. Related CSS is included below.
* Status: Completed
* Version: 23.05
 //Refer to https://animate.style/ for animations available.
 $('head').append('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />');
 
 //Link Header to SCO, not Catalog
 $('#opacheader a').attr('href','/cgi-bin/koha/sco/sco-main.pl');
 // Patron Privacy (No last names) 
 $('#sco_main div.alert-info:contains("You are logged in as")').attr('id','WelcomeBanner');
 var Welcome = $('#WelcomeBanner').text();
 var NewWelcome = 'Welcome, ' + Welcome.split(' ').slice(5,6) + '!';
 $('#WelcomeBanner').text(NewWelcome);
 
 //Patron Privacy (Mask library card number)
 $('#patronid').clone().attr('type','password').insertAfter('#patronid').prev().remove();
 
//Patron Privacy (Remove redundant name / count) 
 $('#sco_main #loanTable caption').hide();
 
//Remove unwanted links and clutter
 $('#patronid, #barcode, label[for="barcode"]').parent('div').removeClass('col-3').removeClass('col').addClass('col-auto');
 $('#opaccredits, #koha_url').hide();
 $('img.mobileresize').unwrap();
 
 //Add on-screen keypad 
 $('#patronid').after('<img id="kpimg" src="YOUR KEYPAD IMAGE HERE">'); //You'll have to come up with a keypad graphic patrons can tap on to bring up the keypad.
 $('#kpimg').on('click', function() {
 $('#KeypadModal').modal('show');
 $('#KeypadModal').on('shown.bs.modal', function () {
 $('#infoCardNumber').focus();
 }); 
 });
 
 //On-screen keypad modal
 $('#mainform').append('<form id="form"><input id="kpbarcodeinput" type="password" /><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 1/3D/keycap_1_3d.png" alt="keycap: 1"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 2/3D/keycap_2_3d.png" alt="keycap: 2"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 3/3D/keycap_3_3d.png" alt="keycap: 3"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 4/3D/keycap_4_3d.png" alt="keycap: 4"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 5/3D/keycap_5_3d.png" alt="keycap: 5"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 6/3D/keycap_6_3d.png" alt="keycap: 6"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 7/3D/keycap_7_3d.png" alt="keycap: 7"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 8/3D/keycap_8_3d.png" alt="keycap: 8"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 9/3D/keycap_9_3d.png" alt="keycap: 9"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Left arrow/3D/left_arrow_3d.png" alt="keycap: Delete"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Keycap 0/3D/keycap_0_3d.png" alt="keycap: 0"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Cross mark button/3D/cross_mark_button_3d.png" alt="keycap: Cancel"><img loading="lazy" width="75px" height="75px" src="https://raw.githubusercontent.com/microsoft/fluentui-emoji/main/assets/Check mark button/3D/check_mark_button_3d.png" alt="keycap: Submit"></form>');
 $('#mainform .kpinput').on('click', function() {
 if ($(this).attr('inputData') !='cancel' && $(this).attr('inputData') != 'delete' && $(this).attr('inputData') != 'submit') {
 $('#kpbarcodeinput').val($('#kpbarcodeinput').val() + $(this).attr('inputData'));
 }
 });
 $('#mainform #kpdelete').on('click', function() {
 $('#kpbarcodeinput').val($('#kpbarcodeinput').val().slice(0,-1));
 });
 $('#mainform #kpcancel').on('click', function() {
 $('#kpbarcodeinput').val();
 $('#KeypadModal').modal('hide');
 });
 $('#mainform #kpsubmit').on('click', function() {
 $('#patronid').val($('#kpbarcodeinput').val());
 $('#KeypadModal').modal('hide');
 $('#mainform button.btn').click();
 });
 
//Add instructions for login
 $('label[for="patronid"]').text('Scan or type in your library card number:');
//Add spinner for login process 
$('.btn').attr('data-loading-text',' Searching').on('click', function() {
 var $this = $(this);
 $this.button('loading');
});
label[for=patronid], #patronid {
 display: inline-block;
}
#patronid {
 font-size: 24px;
 height: 32px;
 width: 150px;
}
#kpimg {
 position: relative;
 margin-top: -7px;
 margin-left: 4px;
 height: 30px;
 border: 1px solid #cccccc
}
.keypad {
 display: table; 
}
.kpmodal .modal-content {
 border: 2px solid #000000;
 background-color: #000000;
}
.kpgroup {
 display: table-row-group;
}
.kpspan {
 display: table-caption;
}
.kprow {
 display: table-row;
}
.kpcell {
 display: table-cell;
 text-align: center;
}
.kpmodal {
 width: 235px;
 left: calc(50% - 142px);
}
#kpbarcodeinput {
 font-size: 35px;
 width: 220px;
 margin: 5px 5px 0 5px;
 border: 2px solid #000000;
}
===Audio Alerts JQuery Selectors===
==== Returns screen 'problem messages ====
* Developer: Nick Clemens
* Purpose: Alter sound alert for checkin 'yellow' problem boxes
* Status: Completed
* Version: Any
 Please return item to:#circ_returns p.problem:contains('Please return item to:')
 Not checked out.#circ_returns p.problem:contains('Not checked out.')
 Local use recorded#circ_returns p.problem:contains('Local use recorded')
 Item was lost, now found.#circ_returns p.problem:contains(' Item was lost, now found.')
 A refund has been applied to the borrowing patron's account.#circ_returns p.problem:contains('A refund has been applied to the borrowing patron's account.')
 Any lost item fees for this item will remain on the patron's account.#circ_returns p.problem:contains('Any lost item fees for this item will remain on the patron's account.')
 Item is withdrawn.#circ_returns p.problem:contains('Item is withdrawn.')
 <Patron> is now debarred until <DATE> #circ_returns p.problem:contains('is now debarred until')
 Patron was earlier restricted until<DATE> #circ_returns p.problem:contains('Patron was earlier restricted until')
 Patron has an indefinite restriction.#circ_returns p.problem:contains('Patron has an indefinite restriction.')
==== Returns screen holds/transfer messages ====
* Developer: Nick Clemens
* Purpose: Alter sound alert for checkin holds boxes
* Status: Completed
* Version: Any
Waiting hold found #circ_returns #hold-found1
Hold needs transfer #circ_returns #transfer-needed
Transfer for hold#circ_returns #item-transfer
Local hold found #circ_returns #hold-found2
Return item to home library (per circ rules)#circ_returns #return1
==== Checkout screen messages ====
* Developer: Nick Clemens
* Purpose: Alter sound alert for checkin holds boxes
* Status: Completed
* Version: Any
Patron is expired #circ_circulation li:contains("Patron's card has expired.")
Patron is restricted #circ_circulation li:contains("Patron's account is restricted")
Patron owes fines #circ_circulation li:contains("Outstanding fees & charges")
Patron has overdues #circ_circulation li:contains("Patron has ITEMS OVERDUE")
Category:Tips_&_Tricks
Category:Resources
Category:Library