Quantcast
Channel: Koha Customizations – Koha Blog
Viewing all 32 articles
Browse latest View live

Customizing your Koha OPAC using YUI Grids

$
0
0

In a previous post I talked about YUI Grids and how we use them to structure Koha pages–all very abstract unless you’re interested in designing Koha pages.  But there are some opportunities to use the Grids techniques in OPAC customization.

Two OPAC system preferences, opacheader and OpacMainUserBlock, are good candidates for some Grids experiments. Both let us add our own HTML markup to the Koha OPAC design, and both are placed within the default page structure defined by the Grids framework. That should let us use our own structure of grids and units to create containers for our content.

Let’s start with opacheader, and the basic grid/unit example of two equal-width containers, or columns:

<div class="yui-g">
<div class="yui-u first">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p></div>

<div class="yui-u">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
</div>
</div>

Add that to your opacheader system pref and you’ll get this:

Click to enlarge screenshot

Click to enlarge screenshot

If that doesn’t look terribly thrilling (or even practical), think of it this way:

Click to view screenshot

Click to enlarge screenshot

Somewhat more practical, at least? And remember, you’ve got a selection of preset grids to choose from:

Quoted from the YUI Grids page

Customizing OpacMainUserBlock

OpacMainUserBlock is the place where it would be the most useful to leverage the Grids framework’s power. The main page of the OPAC is a blank slate for your library’s custom content. It would be great to be able to use the built-in grids system for laying out that content.

Let’s try the same sample markup from the previous example. Two easy and equal-width columns, right? Wrong:

Click to enlarge screenshot

Click to enlarge screenshot

What’s going on? That doesn’t make sense, does it? Well…It makes a certain amount of sense. We have to remember that when dealing with OpacMainUserBlock we’re already working within an existing grid:

The default structure of the OPAC main page, non-logged-in state

The default structure of the OPAC main page, non-logged-in state

The OPAC template for the main page defines a grid with a 75% block (“yui-u first” in the diagram above) and a 25% block (“yui-u”). That means that when we add markup to OpacMainUserBlock, we’re adding that markup within a <div class=”yui-ge first”>. The YUI Grids documentation tells us that if we want to nest grids we should do so by nesting <div class=”yui-g”> directly. Try this in OpacMainUserBlock:


<div class="yui-g first">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p></div>

<div class="yui-g">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
</div>

This is the result:

Click to enlarge screenshot

Click to enlarge screenshot

Better. Usable, anyway. But why did we get another 75%/25% split? We didn’t add a grid with the “yui-ge” class. To be honest, I’m not sure whether there is any way to avoid getting the 75%/25% split when we nest a grid here.  It seems that any time we nest a grid inside a “yui-ge” grid, we get another “yui-ge” grid. In other words, it’s turtles all the way down:

Click to view example

Click to view example

Not freedom, only some flexibility

It seems were left with very limited choices if we want to try to leverage YUI’s Grids system in the context of OpacMainUserBlock. If you’re content with a 75%/25% split, then you’re okay. Otherwise you’re on your own to define a content layout your own way.

If you want to use tables, I won’t tell.


Instant JavaScript testing with Firebug’s console

$
0
0

Firefox’s Firebug addon has a feature that isn’t obvious at first glance, but can be very useful. I think it’s particularly helpful when writing jQuery because jQuery can do so much in just a few lines. It’s perfect for testing in Firebug’s command line. When you first start Firebug you’ll see something like this:

Click to enlarge screenshot

Click to enlarge screenshot

If you haven’t enabled the Console, you’ll get a message telling you so. Enable the Console before proceeding. The Console says “Reload to activate window console” because you turned on Firebug after the page rendered. Reload the page to get the Console ready for action.

Most obvious is the big blank space, but below that is what we’re looking at today: the command line, prefixed with “>>>.” Type some JavaScript on the command line, hit enter, and Firebug will execute that JavaScript on the current page.  Try:

>>> alert("Hello World");

When you type that in and hit enter, your browser should pop up a JavaScript alert. The command line can be used to enter sequences of JavaScript too, so it doesn’t always have to fit on one line:

>>> var x = "Hello World";
>>> alert(x);

But the coolest part is that you can test all your jQuery stuff here. One of the trickiest parts of jQuery can be writing the right selector, targeting just the right element[s] on the page. Firebug’s command line makes it easy, because you can do all your testing without having to go back and forth between your OPAC page and the opacuserjs system preference in the staff client. Get your script just right in the command line, then save it when its finished. Let’s try something really basic:

>>> $("a").hide();

The result:

Click to enlarge screenshot

Click to enlarge screenshot

Firebug even lists the affected elements in the console. Click any of them and you’ll be shown that element in the HTML tab.

What if one line isn’t enough?  Click that little red button in the lower right corner of the screen (see the screenshot above) to expand the command line into a “command box.”

Click to enlarge screenshot

Click to enlarge screenshot

Now you’ve got plenty of room to write and test longer, more complex scripts. Just enter your JavaScript and click the “Run” button to execute it. One nice aspect of this feature is that what you enter in the command line stays intact even after you refresh the page.

For a practical example, let’s take a look back at my post on adding an additional search option to the OPAC’s detail page. Here’s the script we ended up with:

$(document).ready(function(){
var orig = $("#catalogue_detail_biblio h1").remove("span").html();
var regexp = new RegExp ("<span>", "gi");
var title = orig.replace(regexp,"");
$("#further ul").append("<li><a>Paperbackswap.com</a></li>");
});

Copy that script and paste it right into the Firebug command line. Click “Run” and you’ll see the result right away. For testing purposes we don’t really need the “$(document).ready()” part, because we’re executing the script on an already-loaded page. But it seems to work either way.

It’s important to note that this feature of Firebug works on any site. You’re not interacting with the server on which the page is hosted, you’re just manipulating the HTML within your browser. If you want to test out some of the JavaScript tricks I’ve used in my posts here you don’t even need your own installation of Koha. You could test them on someone else’s OPAC.

Quick patron add?

$
0
0

Someone posted an enhancement request today requesting a change to the way the patron entry form is arranged in the Koha staff client. By default the patron entry form is pretty long, and the request asks that required fields be grouped at the top.

It seems like a reasonable request, but there’s a big disadvantage to trying to solve this problem with a template-only change: Libraries can customize which fields are mandatory when entering patrons. The system preference for that is  BorrowerMandatoryField (“borrower” being the term used in place of “patron” at the time of the preference’s creation).

What alternatives might there be to a template-only solution?

  1. Alter the script which generates the patron entry form so that any required fields (no matter which ones they are) are displayed at the top.
  2. Create a “quick-add” form which shows only required fields.
  3. Add a filter to the full patron entry form to toggle display of non-mandatory fields.

I like option two as a long-term solution, but option three could be implemented now with some custom JavaScript. Here’s a proof-of-concept script to show that using the markup which exists in the form now we can pull only required fields:


$(document).ready(function(){
var list = "<fieldset class="rows"><legend>Quick Add<ol>";
$("label.required").each(function(){
item = $(this).parent().html()
item = "<li>"+item+"</li>";
list += item;
});
list += "</ol></fieldset><fieldset class="action"><a href="/cgi-bin/koha/members/member.pl" class="cancel">Cancel</a></fieldset>";
$("#entryform").prepend(list);
});

Paste that into your intranetuserjs system preference or into Firebug’s command line to give it a try. Note that this solution assumes two things:

  1. You’ve already specified a patron category (by choosing one from the “new” menu).
  2. You’re adding patrons to the default branch for your logged-in user.

Of course the form could be customized to include these choices, but they’re probably safe assumptions for quick adds. A better implementation of this would probably allow you to toggle between either view: quick or standard.

Custom printed overdue postcards

$
0
0

My library has a long and complicated history of how to deal with overdue notifications. We’ve tried a few different forms of printed notices, and at one time we even tried to telephone each patron with overdues. After we switched to Koha we got a new option: sending overdue notices via email. Koha didn’t have a built-in notification system at the time, but the open nature of the application meant we could create our own scripted process to query the Koha database and get the information we needed.

The script, written by our director at the time, Stephen Hedges, queried the Koha database for patrons with overdues and did a few things at once with the results of this query:

  1. Send overdue notices via email.
  2. Create a file of overdues data for patrons without email.
  3. Restrict (“debar”) patrons with items overdue for more than 30 days.

In Koha 3, some of this work can be taken over by new built-in notification functionality. With the Overdue notice/status triggers feature we can define when overdue notices should be sent to patrons and when patrons should be restricted for their overdues (taking care of #3 above).

The drawback to Koha 3’s Notices feature is that it doesn’t give you much help when it comes to printed overdue notices. Koha will send an email notice to any patron who has an email address in their patron record (taking care of  #1 above). For patrons without email, Koha collects all of their overdue notices into a single email which is sent to the Koha administrator. Presumably the idea is that the messages can be printed out and mailed by hand.

Unfortunately this won’t work for us: We don’t want to send letters. It’s too much manual labor to stuff envelopes and stick stamps.  We want to send post cards. They’re cheaper. Of course for privacy reasons (not to mention space constraints) we can’t print out a list of a patron’s overdue items on a postcard. We want to send them a generic reminder which includes our web address (for online renewals) and phone numbers to our branches. So even with improvements in Koha 3 we need to do some work to take care of #2 from the list of tasks performed by the old overdues script.

Let’s take a look at how the old script worked. It began by performing this query:

SELECT issues.borrowernumber, firstname, surname, streetaddress, physstreet, city, zipcode, emailaddress
FROM issues, borrowers
WHERE returndate IS NULL
AND TO_DAYS( NOW( ) ) - TO_DAYS( date_due )
BETWEEN 8 AND 30
AND issues.borrowernumber = borrowers.borrowernumber
AND gonenoaddress &lt; 1
AND borrowers.categorycode != &#039;HB&#039; ORDER BY issues.borrowernumber

It limited the query to items which were between 8 and 30 days overdue, where the "gonenoaddress" flag was unset (less than one, meaning in this case zero), and where the patron didn't have the 'HB' categorycode (our "homebound" category for home-delivery patrons).

As far as printed notices are concerned, the purpose of the old script was to create a CSV file containing the name and address of each patron with overdues.  Since we're going to send a non-personalized postcard to each patron, we don't want the output to include any other personal details. Here's what the results looked like:

“name” “address1” “address2” “city” “zipcode”
“John Smith” “1 Main Street” “” “Nelsonville OH” “45764”

In updating this for Koha 3 we can make that query a little bit more portable by having it check whether the patron in question has a category that requires overdue notices:

SELECT issues.borrowernumber, borrowers.firstname, borrowers.surname, borrowers.address, borrowers.address2, borrowers.city, borrowers.zipcode
FROM issues, borrowers, categories
WHERE issues.returndate IS NULL
AND TO_DAYS( NOW( ) ) - TO_DAYS( issues.date_due )
BETWEEN 8 AND 30
AND issues.borrowernumber = borrowers.borrowernumber
AND borrowers.gonenoaddress &lt; 1
AND borrowers.categorycode = categories.categorycode AND categories.overduenoticerequired = 1
AND borrowers.email IS NOT NULL
AND borrowers.email != &#039;&#039;
ORDER BY borrowers.surname,borrowers.firstname

I've added a check that categories.overduenoticerequired is 1, which eliminates the need to hard-code the ‘HB’ patron category. I’ve also added a check to make sure the patron email address field isn’t empty (the old script performed that check elsewhere).

Since I’m more comfortable in PHP than Perl, I use a PHP script to query MySQL and format the results to be saved as a CSV file just like the old script did.

Taking it to the Post Office

We’ve successfully pulled the data we need. What next? We use an online service called Click2Mail, a “trusted and accredited partner to the United States Postal Service.” Click2Mail allows us to define a custom postcard template with our own personalized message. We can then upload our CSV file containing the name and address information for each patron with overdues. The service parses that CSV file, prints one postcard for each patron, and delivers it to the USPS for delivery. Click2Mail even checks your mailing addresses for possible errors and lets you review them.

Their cost estimator puts the cost of sending 100 single-sided postcards at about $30. Considering the time, effort, and cost of stuffing and stamping 100 letters, Click2Mail seems to be a great value.

Customizing the staff client login logo

$
0
0

A Koha user (from Tanzania!) asked today on the Koha mailing list, “I need some help on how to customize the staff client login page/replace koha logo with a new one.” I haven’t heard this request before, so it’s a good opportunity to investigate.

If this were the OPAC we could use a system preference, opacsmallimage, to change the logo. We don’t have that option in the staff client, so we’ll have to see if we can use the available customization options to accomplish the same thing.

Our first stop, as usual, is FireBug. I opened up the staff client to examine how the default Koha logo is displayed on the login form. Using the Inspect tool I highlight the logo and view the results in the FireBug HTML inspector window:

FireBug details for the login logo anchor tag

The logo is constructed by nesting a link (“anchor”) tag (<a>) inside a top-level heading tag (<h1>). The above screenshot shows the HTML and style details for the <a>, here are the results for the <h1>:

FireBug details for the login logo heading tag

From this we can collect all the CSS information we need to control the display of the login logo:

#login h1 a {
border-bottom:medium none;
display:block;
height:74px;
text-indent:-1000px;
}

#login h1 {
background:url("../../img/koha-logo.gif") no-repeat scroll center top transparent;
margin-bottom:0.5em;
margin-top:0;
}

The staff client logo is displayed using an image-replacement technique similar to the one used to display the Koha logo in the OPAC. The style of the anchor tag sets an explicit height which matches the logo image, and it sets a negative text-indent property which moves the text contents of the tag off the screen. These two properties create a blank space inside the anchor tag in which to display the logo.

The style of the heading tag does the work of displaying the logo. The background property points to the URL of the logo image. In the default case this is an image file on the Koha server’s file system. The URL doesn’t have to be a relative one, though. It can be a full URL pointing to anywhere on the internet.

Customizing the logo CSS

In order to change the image we need to make very simple changes to two CSS properties:

  1. The background-image of the <h1> tag.
  2. The height of the <a> tag.

Let’s use as an example the logo on the Athens County Public Libraries site. I can right-click the image in Firefox and choose “View image” to find the details I need. The location bar shows the URL I need, and the title bar shows the dimensions of the image. I just need to note the height.

Since we only need to change two properties, our custom CSS is simpler than the original. We only need to specify the properties which we need to override:

#login h1 a {
height:71px;
}

#login h1 {
background:url("https://www.myacpl.org/sites/all/themes/npl/logo.png") no-repeat scroll center top transparent;
}

Applying the custom CSS

We’ve got our custom CSS, now what do we do with it? We don’t have an opacsmallimage preference for the staff client, and we don’t even have an option like OPACUserCSS. We do have a couple of options which will work.

intranetcolorstylesheet

If you have access to your Koha server’s file system you can add a stylesheet there and tell Koha to apply it in addition to the default staff client stylesheet. For example, you could create a new CSS file called custom.css and save it alongside staff-global.css and the other staff client CSS files. Then you can specify that filename, custom.css, in the intranetcolorstylesheet system preference.

intranetuserjs

If you don’t have access to your Koha server’s file system, there’s a way to insert custom CSS into your staff client pages, but it’s a bit of a hack. Lacking an “intranetusercss” preference we’re going to hijack an existing preference, intranetuserjs, to do the job for us.

When you insert custom JavaScript into the intranetuserjs preference, Koha detects this and adds it to the header of each staff client page, wrapped in the appropriate <script> tags:


// 


Since Koha automatically wraps the intranetuserjs content in opening and closing <script> tags, we’ll have to do a little bit of roundabout coding to embed a <style> block:


//


/* Custom styles here */


// 

Let’s run down what’s happening here. Lines 1 and 2 have been inserted automatically by Koha in order to properly embed the custom JavaScript it expects from the intranetuserjs preference. Line 3 is the first line of the contents of intranetuserjs. Lines 4 and 5 we have added manually to close the automatically-embedded <script> tag. With the script tag closed we can go on to add just about any HTML we want, really, but this is all inside the <head> of the HTML document, so few things would be valid.

Lines 6, 7, and 8 show the <style> tag we’re adding. This is where we’re going to put our custom CSS. Lines 9, 10, and 11 are the last lines of our custom intranetuserjs. Knowing that Koha wants to close the <script> tag it opened on line 1, we have to re-open a new <script> tag so that when Koha closes it we’ll have valid markup.

Putting it all together, here’s what the contents of our intranetuserjs preference will be:

// ]]>



/* Custom styles here */
#login h1 a {
height:71px;
}
#login h1 {
background:url("https://www.example.com/images/logo.png") no-repeat scroll center top transparent;
}


// <![CDATA[

If all goes well, this is what you should see when you log out and look at your login screen:

id=”attachment_633″ align=”aligncenter” width=”300″ caption=”Customized login form”

Note: I’ve published a quick addendum to this post which covers using jQuery to change the URL to which the logo links

Customizing the staff client login logo: Addendum

$
0
0

I left something out of my post on Customizing the staff client login logo that I wanted to be sure to add: Once you’ve changed the logo you may want to change where it links to as well. By default it links to the Koha web site (or the deprecated version if your installation is an older one). We can use a little snippet of jQuery to change that link.

Using jQuery to change the URL to which the staff client logo links

$("#login h1 a").attr("href","https://www.myacpl.org");

That looks for an <a> tag inside an <h1> inside <div id="login">, which is specific enough to only catch the login form. This snippet goes inside your intranetuserjs system preference. Assuming the only thing you’ve added to intranetuserjs is the code I covered in the previous post, this would be the revised version:

$(document).ready(function(){
$(“#login h1 a”).attr(“href”,”https://www.myacpl.org”);
});
// ]]>


// <![CDATA[
//

Showing item type counts on the checkout screen

$
0
0

Does your library limit your patrons to a certain number of checkouts for certain item types? At the Athens County Public Libraries, for instance, we limit patrons to 10 audio books, 10 music CDs, 10 videos, and 5 DVDs at a time. If a patron tries to check out more than 5 DVDs, Koha will show a warning. But what if you want to be able to tell at a glance how many a patron has?

This functionality was available to us in our 2.x installation, but when we upgraded to 3.0 our support company at the time told us it wasn’t a customization they would support. This wasn’t a feature we were willing to give up, so I set out to duplicate it using the tools available to me: system preferences and JavaScript.

Information there for the taking

All the information we need can be found on the patron checkout screen, we just need to figure out how to get it. The page lists all the items checked out to the patron, and it shows the item type for each:

List of items checked out on the checkout screen

With this available to us we can use jQuery to count each instance of each item type. We need to build a count for each item type in our system, so the script isn’t very portable. It looks for table cells (“<td>“) containing the description of each of our item types:


var itypes = {'circ': 0, 'avid': 0, 'avbk': 0, 'avmu': 0, 'advd':0 };
$("#issuest td:contains('Circulating')").each(function(){
itypes["circ"]++;
});
$("#issuest td:contains('Videos')").each(function(){
itypes["avid"]++;
});
$("#issuest td:contains('DVDs')").each(function(){
itypes["advd"]++;
});
$("#issuest td:contains('Audio Books')").each(function(){
itypes["avbk"]++;
});
$("#issuest td:contains('Music CDs')").each(function(){
itypes["avmu"]++;
});

The script starts by setting up an array of all my item types (“circ,” “avid,” etc.) and giving each a value of zero. Then the script looks for instances of each item type description on the page,  “Circulating,” “Videos,” etc., using jQuery’s :contains selector. Each time it finds an instance of one of those text strings the script increments the count for that item type. At the end of the process the script will have the count for each item type.

Displaying the counts on the page

In order to show the item type counts on the page we need to lay some groundwork by adding some markup. I want to add the count information right after the “Checking out to…” heading, so I’ll find that element’s ID using FireBug and jQuery’s after() function:


$("#circ_circulation_issue label[for='barcode']").after( ... );

The HTML I’m going to add is the default state, so it shows a zero count for everything:


<p style="margin-top:1em">
<span id="avmuout">0</span> Music CDs out, <span id="avmuok">10</span> More Allowed
</p>
<p>
<span id="avbkout">0</span> Audio Books out, <span id="avbkok">10</span> More Allowed
</p>
<p>
<span id="avidout">0</span> Videos out, <span id="avidok">10</span> More Allowed
</p>
<p style="margin-bottom:1em">
<span id="advdout">0</span> DVDs out, <span id="advdok">5</span> More Allowed
</p>

I’ve  included unique IDs for the “count” spans so that I can easily update them with my script:


$("#avidout").html(String(itypes["avid"]));
$("#advdout").html(String(itypes["advd"]));
$("#avbkout").html(String(itypes["avbk"]));
$("#avmuout").html(String(itypes["avmu"]));

$("#avidok").html( 10 - itypes["avid"] );
$("#advdok").html( 5 - itypes["advd"] );
$("#avbkok").html( 10 - itypes["avbk"] );
$("#avmuok").html( 10 - itypes["avmu"] );

In the first of the two sections above I take the count I got earlier, itypes['avid'] and set the content of the corresponding <span> using the html() function. I also want to show how many more the patron can check out, so I subtract the count from the limits I’ve set in my Koha installation.

If you have patrons who have exceeded their checkout limit you’ll see a problem: The page will tell you they’re allowed to check out a negative number more items. We can correct the script to accommodate:


$("#avidok").html((10-itypes["avid"] &gt; 0) ? 10-itypes["avid"] : 0);
$("#advdok").html((5-itypes["advd"] &gt; 0) ? 5-itypes["advd"] : 0);
$("#avbkok").html((10-itypes["avbk"] &gt; 0) ? 10-itypes["avbk"] : 0);
$("#avmuok").html((10-itypes["avmu"] &gt; 0) ? 10-itypes["avmu"] : 0);

Final version

Here’s what the results look like:

The final version includes proper escaping of the HTML content and wraps the whole process into a function (“itemTypeCount”). This function will be called on page load only if jQuery finds that the table of checkouts, which has an ID “issuest” is being displayed. The whole script goes into Koha’s intranetuserjs system preference.


function itemTypeCount(){
$("#circ_circulation_issue label[for='barcode']").after("<p style="margin-top:1em" class="icount"><span id="avmuout">0</span> Music CDs out, <span id="avmuok">10</span> More Allowed</p> <p class="icount"><span id="avbkout">0</span> Audio Books out, <span id="avbkok">10</span> More Allowed</p> <p class="icount"><span id="avidout">0</span> Videos out, <span id="avidok">10</span> More Allowed</p> <p style="margin-bottom:1em" class="icount"><span id="advdout">0</span> DVDs out, <span id="advdok">5</span> More Allowed</p>");

var itypes = {'circ': 0, 'avid': 0, 'avbk': 0, 'avmu': 0, 'advd':0 };
$("#issuest td:contains('Circulating')").each(function(){
itypes["circ"]++;
});
$("#issuest td:contains('Videos')").each(function(){
itypes["avid"]++;
});
$("#issuest td:contains('DVD')").each(function(){
itypes["advd"]++;
});
$("#issuest td:contains('Audio Books')").each(function(){
itypes["avbk"]++;
});
$("#issuest td:contains('Music CDs')").each(function(){
itypes["avmu"]++;
});
$("#avidout").html(String(itypes["avid"]));
$("#advdout").html(String(itypes["advd"]));
$("#avbkout").html(String(itypes["avbk"]));
$("#avmuout").html(String(itypes["avmu"]));
$("#avidok").html((10-itypes["avid"] &gt; 0) ? 10-itypes["avid"] : 0);
$("#advdok").html((5-itypes["advd"] &gt; 0) ? 5-itypes["advd"] : 0);
$("#avbkok").html((10-itypes["avbk"] &gt; 0) ? 10-itypes["avbk"] : 0);
$("#avmuok").html((10-itypes["avmu"] &gt; 0) ? 10-itypes["avmu"] : 0);
}
$(document).ready(function(){
if(document.getElementById("issuest")){
itemTypeCount();
}
});

Caveats

This system works very well for my library, but it comes with a few caveats:

It requires that you hard-code, in the script, handling for each of your Koha item types.

Besides being tedious, it also requires that you modify the script each time you change your item types.

It requires that you hard-code the correct item type limits.

Also tedious, and requires that you modify the script each time you change your circulation rules.

It creates a potential collision with both call numbers and titles.

If my item type description is “DVD” and my call number includes the text “DVD” as well I’ll get an inaccurate count. If my item type description is “Audio Books” and a patron has checked out a print book entitled Audio Books for long trips I’ll get an inaccurate count.

For us the disadvantages are not unwieldy and the collision problem has never caused a problem. The advantage we get is being able to tell at a glance whether the patron is going to be able to check out that stack of DVDs or whether we need to ask them to put some back. Better to ask them to pick their favorites up front rather than after we’ve already checked out some of them.

Cart and Lists buttons revisited

$
0
0

It’s been almost three years since I wrote Colorizing the Cart and Lists buttons. My conclusion then was that we needed a fairly complex combination of markup, CSS, and background images to create the appearance of the buttons.

This works fairly well in Firefox, Safari, and Chrome. Unfortunately, it fails not only in Internet Explorer 6, 7, and 8, but all versions of Opera too. For the time being, our more-complex process gives the desired result to a wider audience.

The time has come for the simpler version. My patch for Koha bug 7584, “Update cart and lists buttons style using CSS3 features” has just appeared in Koha’s master branch, the development version which precedes an official release.

What has changed? Firefox, Safari, and Chrome have had updates since then, which has at the very least expanded the number of users of those browsers who are on a more recent version. Opera, one of the holdbacks in 2009, now supports the features required. Internet Explorer 6, 7, and 8 still linger of course, but Internet Explorer 9 is available now. IE9 offers better support for the features we need.

For me what has changed is that I now think that Koha should be a little more aggressive about taking advantage of the features of up to date browsers even if that means the experience isn’t the same for users of older browsers.

The new style

Let’s take a look at the revised markup. Where the previous version needed a lot of extra elements (<i>, <span>, etc) the new version doesn’t:


<a href="#">Cart</a>

<a id="listsmenulink" href="#">Lists</a>

I’ll quote the relevant declarations from the CSS. First, both buttons are assigned rounded corners:


#cartmenulink, #listsmenulink {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}

Notice the variations: “-webkit-border-radius” is specific to Chrome and Safari. “-moz-border-radius” is specific to Mozilla-based browsers like Firefox. When we specify a single value like “5px” the value is applied equally to all four corners. You can also specify different values:


#cartmenulink, #listsmenulink {
-webkit-border-radius: 4px 15px 4px 15px;
-moz-border-radius: 4px 15px 4px 15px;
border-radius: 4px 15px 4px 15px;
}

The values are applied clockwise starting with the upper left-hand corner.

Background Gradients

The other primary aspect of the buttons are their background colors. Previously we used a transparent image to give the button background a gradient. With CSS3 we can specify the gradient values right in our CSS. The easiest way to accomplish this is using the Ultimate CSS Gradient Generator.

A web-based tool for designing CSS gradients

With the CSS Gradient Generator you can use the visual tools for creating a gradient and the CSS will be generated for you. It generates CSS declarations specific to several major browser versions including Internet Explorer. There is even an option to upload a gradient image and have the Generator automatically match the colors.

Here’s the gradient CSS for the Cart button:


#cartmenulink {
background: #98CB58; /* Old browsers */
background: url("../../images/cart.gif"),-moz-linear-gradient(top, #d5eaba 0%, #b7db8a 50%, #98cb59 100%); /* FF3.6+ */
background: url("../../images/cart.gif"),-webkit-gradient(linear, left top, left bottom, color-stop(0%,#d5eaba), color-stop(50%,#b7db8a), color-stop(100%,#98cb59)); /* Chrome,Safari4+ */
background: url("../../images/cart.gif"),-webkit-linear-gradient(top, #d5eaba 0%,#b7db8a 50%,#98cb59 100%); /* Chrome10+,Safari5.1+ */
background: url("../../images/cart.gif"),-o-linear-gradient(top, #d5eaba 0%,#b7db8a 50%,#98cb59 100%); /* Opera 11.10+ */
background: url("../../images/cart.gif"),-ms-linear-gradient(top, #d5eaba 0%,#b7db8a 50%,#98cb59 100%); /* IE10+ */
background: url("../../images/cart.gif"),linear-gradient(top, #d5eaba 0%,#b7db8a 50%,#98cb59 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d5eaba', endColorstr='#98cb59',GradientType=0 ); /* IE6-9 */

}

Eight lines of CSS each doing the same thing for different browsers, starting with a solid background color for browsers which don’t support CSS3. This is the same kind of code which will be generated by the CSS Gradient Generator with one exception: The OPAC CSS also includes a background image for the Cart button in order to display the little cart icon.

There’s more to the styling of the buttons than rounded corners and background-gradients, but nothing which we haven’t seen before. Fire up Firebug (or your favorite browser’s DOM inspection tool) and inspect the buttons for more information.

What have we gained?

Just looking at the HTML markup it would seem we’ve gained a lot of efficiency over the <span>-heavy buttons in the older version. But the multiple lines of CSS more than make up for it. What advantages does the new design offer? Importantly, flexibility. We don’t have to create custom-colored 24-bit transparent images when changing the background color of the search bar. We can make all our changes, including changes to the Cart icon, right in the CSS. Border color, border radius, background-color (or gradient), it’s now 100% CSS and can be affected by a custom stylesheet or by changes to the OPACUserCSS system preference.

This change is going to require some revisions if your library has existing CSS customizations to these areas of the OPAC, but I think going forward these changes are going to prove to be beneficial to those seeking to customize their OPAC’s appearance.


Customizing the display of online resources like eBooks

$
0
0

The Athens County Public Libraries are members of the Ohio eBook Project Ohio Digital Library, a consortium of libraries who contribute to and share access to a collection of eBooks and other downloadable material through OverDrive. In order to make these resources more discoverable by our patrons we add MARC records for these titles to Koha.

When we started doing this we felt that it was important for the patrons to be able to tell very easily that the title they saw in search results was an electronic resource they could download. We already have many records in our catalog for web sites. We were concerned that these two types of resources would be difficult to distinguish.

Electronic resource in search results

An electronic resource in default OPAC search results

Since Koha gives us the ability to inject custom JavaScript into our OPAC, a JS-based solution seemed like the best option. The goal was to be able to use JS to examine each search result and look for a clue that any particular result was an Ohio eBook Project record. Luckily all the OEP records have something in common: A URL (stored in the MARC 856u) beginning with “http://ohdbks.” Here’s the JavaScript I came up with:

$("#userresults").ready(function(){
$("#userresults table td").each(function(i){
td = $(this);
var ohdbks_link = td.find("a[href^='http://ohdbks']");
var linkc = ohdbks_link.parent();
var ohdbks_link = ohdbks_link.attr("href");
if(ohdbks_link){
$("td:eq("+i+") span.availability,td:eq("+i+") span.actions").hide();
linkc.html('<a class="ebook" href="'+ohdbks_link+'">Check the Ohio e-Book Project for availability</a>');
}
});
});

Stepping through this code:

  1. The script is triggered when #userresults is ready.
  2. We loop through each td within the table inside #userresults, storing the index of each iteration as i.
  3. The matched td is stored as a variable for easy reference.
  4. The script finds an anchor tag which matches the string we’re looking for and stores that in a variable.
  5. We want to refer later to the <a> tag’s parent container, so we use jQuery’s parent() to store that as linkc.
  6. We pull the href attribute value for the previously select <a> tag.
  7. If an href was found…
  8. …hide the availability and “actions” (“Place hold,” “Add to cart”, etc.) elements which we don’t consider relevant to e-resource records.
  9. Replace the contents of the original anchor tag’s container with new html which uses the previously-saved href attribute but changes the text of the link and adds a special CSS class.

We chose to label each eBook link “Check the Ohio Digital Library for availability” because Koha has no way of knowing whether a particular title is checked out. The link is styled by CSS added to Koha’s OPACUserCSS system preference:

a.ebook {
background: url("https://www.myacpl.org/files/image/opac-results-download-ebook.png") no-repeat scroll 5px 5px transparent;
border: 1px solid #8BC45C;
border-radius: 5px 5px 5px 5px;
font-size: 135%;
font-weight: bold;
line-height: 175%;
padding: 4px 4px 4px 25px;
text-decoration: none;
}

The result:

Electronic resource in customized search results

An electronic resource in customized OPAC search results

Electronic resource detail page

When the patron clicks to view more information about one of those electronic resource titles they come to a detail page which presents additional opportunities to simplify the display for this type of record.

Since this kind of title is available only through the Ohio Digital Library web site we don’t actually have any local holdings, but when we add MARC records for these resources we include a dummy item to which we can attach some additional information. One reason for this is to be able to have a searchable collection code attached to each record. But showing holdings information to the patron isn’t very useful because none of it is relevant:

Holdings information displayed by default for electronic resources

Holdings information displayed by default for electronic resources

Another aspect of the detail page which is less than ideal is that the link to the Ohio Digital Library is pretty well hidden in the other details about the title like publisher, subject headings, etc. We again turned to JavaScript to solve both of these problems at once:

$("span.online_resources").ready(function(){
var ohdbks_link = $("span.online_resources a[href^='http://ohdbks']").attr("href");
if(ohdbks_link){
$("#holdings").html('<a href="'+ohdbks_link+'"><img src="https://www.myacpl.org/files/image/opac-download-ebook.png" alt="Check the Ohio e-Book Project for availability" /></a>');
}
});

This code is very similar to what we used on the search results page, but a little simpler.

  1. Again we trigger this function when this particular area of the page (“span.online_resources”) has completed loading.
  2. We find the link to the Ohio eBook Project download page and store the href attribute.
  3. If an href was found…
  4. Replace the holdings table (identified by the ID #holdings) with an image which links to the OEP download page.

In four lines of JavaScript both goals are accomplished: The meaningless holdings table is gone, and a prominent link is added to the Ohio eBook Project download page for the title the patron is looking at.

Here’s the result:

A customized link to the electronic resource download page

A customized link to the electronic resource download page

A quick Firebug tip for editing CSS

$
0
0

I’ve talked before about Firebug’s inspector tool for examinating the markup of a page and its associated style. When you inspect a particular element in the markup you can see the CSS rules that have been applied to it. But what if the styles applied to an element change based on user interaction? How do you “catch” the style of a hover interaction, or of an element which has focus?

For instance: In the Koha staff client there is a global style for the color of a link when you hover your cursor over it.

Koha link color on hover

This color is defined in the staff client’s main CSS file, staff-global.css:

a:hover, a:active {
color : #538200;
text-decoration: none;
}

However, if you use Firebug’s inspector to examine a link you won’t see that CSS:

Inspecting a link in the staff client

That’s because the Firebug inspector isn’t showing you the “hover” state of the link–at least not unless you’re mouse cursor is hovering over the link at the time:

Inspecting the link on hover

But what if we want to use Firebug’s Style tab to live-edit the CSS of the hover state? As soon as we move our mouse away from the link the hover state disappears from the style pane, so we can’t edit it. Luckily Firebug has an option built in for “activating” three different interaction states: Hover, Active, and Focus:

Firebug Style tab interaction options

By selecting “:hover” we can “pin” the hover state to keep it activated so that we can inspect and change it:

Edit the hover style in Firebug

We can test the “focus” option by inspecting the style of any standard text input in Koha, for example the barcode field on the check-in page:

Inspecting an element's :focus state in Firebug

This lets us see that there is a CSS rule defining a default border style for <input> and <textarea>

input:focus, textarea:focus {
border-color: #538200;
border-radius: 4px;
border-style: solid;
}

And from there we can customize away:

input:focus {
border-top: 5px solid #EF5959;
border-bottom: 5px solid #FF975F;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#EF5959), to(#FF975F));
background-image: -webkit-linear-gradient(#EF5959, #FF975F);
background-image: -moz-linear-gradient(#EF5959, #FF975F),
-moz-linear-gradient(#EF5959, #FF975F);
background-image: -o-linear-gradient(#EF5959, #FF975F),
-o-linear-gradient(#EF5959, #FF975F);
background-image: linear-gradient(#EF5959, #FF975F),
linear-gradient(#EF5959, #FF975F);
-moz-background-size:5px 100%;
background-size:5px 100%;
background-position:0 0, 100% 0;
background-repeat:no-repeat;
border-width: 5px 0;
padding: 5px;
}

A custom input border

Get an OPAC QR Code feature early

$
0
0

Coming in Koha version 19.11 in November is a new QR code feature in the OPAC. You’ll be able to turn on a system preference to enable the display of a QR code on the OPAC’s bibliographic detail page. The user can scan this QR code with their smartphone and get the URL of the page they’re viewing. This feature is detailed in Bug 23566, Continue on device – with QR codes.

Screenshot showing QR Code feature

What if you don’t want to wait for you next upgrade to get this feature? It can be added entirely via Koha’s custom CSS and JavaScript system preferences!

Add this to your OPACUserCSS system preference:

a.show_qrcode {
 padding-left:35px;
 background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALAgMAAADUwp+1AAAACVBMVEUzban//8z///8fhy3sAAAAK0lEQVR42mNgUGBg0BJawKAkpACmGQQYGKaGRgBpEJ+BQUmgA0gDFSkxAAB3qQUjA3ioDgAAAABJRU5ErkJggg==) no-repeat scroll 11px center transparent
}
#qrcode {
 padding:1em;
}

Add this to the OPACUserJS system preference:

jQuery.cachedScript = function( url, options ) {
    // https://api.jquery.com/jQuery.getScript/
    // Allow user to set any option except for dataType, cache, and url
    options = $.extend( options || {}, {
        dataType: "script",
        cache: true,
        url: url
    });
    // Use $.ajax() since it is more flexible than $.getScript
    // Return the jqXHR object so we can chain callbacks
    return jQuery.ajax( options );
};

$(document).ready(function(){
    if( $("#opac-detail").length &gt; 0 ){ // Run this JS only on the bibliographic detail page
        $.cachedScript( "https://cdn.jsdelivr.net/npm/kjua@0.6.0/dist/kjua.min.js" ).done(function( script, textStatus ) {
            // If the QR Code-generating JS library loads successfully, add the code to the page
            $("#action").append("<li><a class=\"show_qrcode\" href=\"#\">Send to device</a><div id=\"qrcode\" class=\"hidden\"></div></li>");
            var qrcode = kjua({
                ecLevel: "H",
                render: "canvas",
                rounded: 100,
                size: 150,
                text: location.href,
            });
            if (qrcode) {
                document.getElementById("qrcode").appendChild( qrcode );
            }
        });
        // Add the click handler for the new "Send to device" menu item
        $("body").on("click", ".show_qrcode", function(){
            var qrcodeImg = $("#qrcode");
            if( qrcodeImg.hasClass("hidden") ){
                qrcodeImg.removeClass("hidden");
            } else {
                qrcodeImg.addClass("hidden");
            }
        });

    }
});

That’s it! Open a bibliographic detail page in the OPAC and you should see a “Send to device” link in the sidebar menu.

Screenshot showing QR Code feature via customization

Scan the QR code with a smartphone to confirm that the code is working correctly:

Screenshot showing how the iPhone camera captures a QR code with a link

Interface Test: Editing from the additem table

$
0
0

One of the custom reports I’ve been using recently is one that shows me the most expensive items in the catalog. I’m not trying to figure out which book to sneak out under my coat, I’m trying to find data-entry errors which might cause problems for the patrons.

You lost that paperback? That’ll be $4399.00.

The trouble is, once I’m cruising through this report making corrections I’m quickly frustrated by the interface for adding items.additem-interface

The list of items is in its own container with the css property “overflow:auto” so that if it exceeds the constraints of the container it’s in it will display scrollbars. It always displays scrollbars. You have to scroll to the right to see the item’s replacement price, then back to the left to find the Edit link. And it’s hard to be sure you clicked the Edit link in the correct row, because once you’re at the Edit link you can’t see the price anymore!

What if we could access the Edit and Delete functions from anywhere in the row? Inspired by WordPress’s inline edit menu I worked up this example:

additem-inline-edit

Try navigating anywhere in the table of item details and clicking a table cell. You’ll see Edit/Delete links appear for that row. Implementing this change would allow the user to jump to the Edit or Delete functionality from anywhere in the table eliminating the need to scroll back and forth for the static links.

The advantage to the method used in this example is that it’s simple: no generating tooltips or modal dialogs, just a simple append of the Edit|Delete links to the table cell which gets clicked.


$("td").click(function(event){
var $tgt = $(event.target);
if($tgt.is("a")||$tgt.is(":first-child")||$tgt.is(":nth-child(2)")){ return true; } else {
var rowid = $(this).parent().attr("id");
num_rowid = rowid.replace("row","");
$(".linktools").remove();
$(this).append("<span class="linktools"><a>Edit</a> | <a>Delete</a></span>");
}
});

The disadvantage to the resulting UI is that it could suggest to the user that clicking Edit or Delete will edit or delete just the contents of that cell, which is of course incorrect. It wouldn’t be good for a librarian to expect a click on “Delete” to delete, for instance, only the value contained in the replacementprice field and find that the entire item had been deleted.

I’m not sure how to mitigate that confusion while retaining the script’s simplicity.

Update: Here’s an alternate, slightly more verbose version.

Viewing all 32 articles
Browse latest View live


Latest Images