Displaying unique title and volume count on the Koha staff client – Part 2

In this followup to our previous post on upgrade-friendly way of displaying unique title and copies’ count on the staff client, we explore a few variant use-cases reported by our readers.

Last December when we posted about the nifty little trick of displaying unique title and volume count on the Koha staff client, we didn’t realize that so many people would find something to be so useful. We received quite a few comments from all over the world. In this post, we are going to try and look at some of these use-cases that people thought could use something like this. So, if you are reading this and haven’t read the original post, it may be helpful to read Part 1 first.

The questions we received were:

(a) what if we have multiple branches?
(b) How to show the stats for the user’s logged in branch only?
(c) How do we show the overall totals if we have multiple branches?

Recently, the library at Our Lady Queen of the Mission School, Salt Lake had started to catalog both their junior library as well as the senior library. So, they presented the perfect opportunity to showcase these 3 use-cases.

1. What if we have multiple branches?

This was a question that came from Hussein Al-Nasri from Egypt. Hussein had tried the code snippet, but since it was hard-coded to handle only one single branch (the first on in the list of the JSON data returned), it wasn’t showing him what he wanted – the data for each of his branches.

The solution
$(document).ready(function() {
  if ( $('#main_intranet-main').length ) {
  $.getJSON("https://qmsl-staff.l2c2.co.in/cgi-bin/koha/svc/report?id=1&annotated=1.", function(data) {
    if ( data.length ) {
      $('#news1').prepend('<div class="newsitem" id="mystats"><table class="table table-striped" style="width: 100%; background: none;"><thead><th colspan="3" style="text-align: center; font-weight: bold; padding: 8px; line-height: 1.42857143; vertical-align: middle; text-transform: uppercase;">Library Statistics</thead><tbody><tr id="mystatstb"><td><strong>Branch</strong></td><td><strong>Unique titles</strong></td><td><strong>Total Copies</strong></td></tr></tbody></table></div>');
      for ( var key in data ) {
        $('<tr id=\"tr'+ key + '"><td class="text-center">' + data[key].homebranch + '</td><td class="text-center">' + data[key].bibs + '</td><td class="text-center">' + data[key].items + '</td></tr>').insertAfter( $( '#mystatstb' ) );
      }
    }
  });
  }
});

2. How to show stats only for the logged in branch?

This came from Freddy Enrique Pelayo from Peru, South America. He left a comment on the blog post asking:

if the system were to have more than 2 branches, will the screen show information according to the branch the user logged in?

The solution
$(document).ready(function() {
  if ( $('#main_intranet-main').length ) {
  $.getJSON("https://qmsl-staff.l2c2.co.in/cgi-bin/koha/svc/report?id=1&annotated=1.", function(data) {
    if ( data.length ) {
      $('#news1').prepend('<div class="newsitem" id="mystats"><table class="table table-striped" style="width: 100%; background: none;"><thead><th colspan="3" style="text-align: center; font-weight: bold; padding: 8px; line-height: 1.42857143; vertical-align: middle; text-transform: uppercase;">Library Statistics</thead><tbody><tr id="mystatstb"><td><strong>Branch</strong></td><td><strong>Unique titles</strong></td><td><strong>Total Copies</strong></td></tr></tbody></table></div>');
      for ( var key in data ) {
        if ( $('#logged-in-branch-code').html() == data[key].homebranch ) {
          $('<tr id=\"tr'+ key + '"><td class="text-center">' + data[key].homebranch + '</td><td class="text-center">' + data[key].bibs + '</td><td class="text-center">' + data[key].items + '</td></tr>').insertAfter( $( '#mystatstb' ) );
        }
      }
    }
  });
  }
});

Explanation

The key line here is $('#logged-in-branch-code').html() == data[key].homebranch. Whenever an user logs into the Koha staff client, the hidden <span> element with the id logged-in-branch-code holds the code for the user’s logged in branch. In the above snippet, we simply introduce a check to see if the code matches the homebranch code in the JSON array. If it does, we show the value for that branch and not for the other branches.

3. How to show the total for all branches?

This scenario was pointed to by Dr. Apurba Jyoti Mazumdar, Assistant Librarian, Assam Univerity, Silchar, India.

The solution

$(document).ready(function() {
    if ( $('#main_intranet-main').length ) {
    $.getJSON("https://qmsl-staff.l2c2.co.in/cgi-bin/koha/svc/report?id=1&annotated=1.", function(data) {
        if ( data.length ) {
            $('#news1').prepend('<div class="newsitem" id="mystats"><table class="table table-striped" style="width: 100%; background: none;"><thead><th colspan="3" style="text-align: center; font-weight: bold; padding: 8px; line-height: 1.42857143; vertical-align: middle; text-transform: uppercase;">Library Statistics</thead><tbody><tr id="mystatstb"><td><strong>Branch</strong></td><td><strong>Unique titles</strong></td><td><strong>Total Copies</strong></td></tr></tbody></table></div>');
            var totalbibs = 0;
            var totalitems = 0;
            for ( var key in data ) {
                $('<tr id=\"tr'+ key + '"><td class="text-center">' + data[key].homebranch + '</td><td class="text-center">' + data[key].bibs + '</td><td class="text-center">' + data[key].items + '</td></tr>').insertAfter( $( '#mystatstb' ) );
                 totalbibs = totalbibs + parseInt(data[key].bibs);
                 totalitems = totalitems +  parseInt(data[key].items); 
            }
            $( '<tr><td><strong>TOTAL</strong></td><td class="text-center"><strong>' + totalbibs + '</strong></td><td  class="text-center"><strong>' + totalitems + '</strong></td></tr>' ).insertAfter(  $('#mystats tr:last')  ); 
        }
    });
    }
});

Conclusion

As you may have noticed, in this version, we added an extra check which ensured that we only display this grid of data *only if* any data is returned. We hope that by answering a few of your questions, this post is of some use to some of you.

Quicktip – Ordering the display of your custom patron fields

An easy-peasy way to order the display of Koha’s ExtendedPatronAttributes fields.

This is going to be a brief tutorial, ExtendedPatronAttributes provide the capability to add custom fields to Koha’s patron management e.g. if we wish to capture say Program enrolled or Roll No. or other demographic details that we may be required to maintain under (a) law of the land or (b) governing rules of our library, this feature of Koha is friend we need to take help of.

If you have just landed on this blog and have no idea what we are talking about, we suggest that you may like to first read this earlier post – Harnessing Koha’s ExtendedPatronAttributes (aka patron custom fields). And while you are here, you may also like to visit this article.

Ok! Enough backstory, now back on topic! 🙂 When we define new custom fields to Koha using Home › Administration › Patron attribute types, the key thing to remember here is that these are ordered and displayed using alphabetic ascending sorting order of the defined Patron attribute type code.

Which means, when we defined a list of custom fields to capture student registration details e.g. as given in the screenshot below, we want them to be displayed in the order of the codes are numbered in the blue circles i.e. Student code, Registration No. and Roll No. in that order respectively.

Instead what we get is this:

The Solution

We simply need to number our codes. The way to do this is simply to prefix them with a serial number. Here we chose to use 00_, 01_, 02_”. Of course, this also meant that we had to dump off our old codes and put in these as replacement.

Hint: Do this before you start using the defined fields while entering your patron records. While it can be done later, you need to know what you are doing if you don’t want to mess up your patron data.

You can see what we did below:

And as you can see below, we have the fields displayed exactly in the order we had wanted in the first place.

Quick Tip – What to avoid when adding news items to your Koha OPAC

Avoiding common errors while using Koha – setting the library name correctly for news.

The News tool available in the Home -> Tools -> Additional tools section of the Koha staff client allows us to publish news and updates across – (a) OPACs (b) staff client and (c) printed slips generated by the library.

Being a handy way to publish library related updates, librarians like to use it. However, there are a few things that we need to keep in mind when doing this. For starters, we should not be logged in into the staff client as Koha’s database administrator; we must be logged in either as a superlibrarian OR as a library staff user with access rights to the News tool. The next thing to understand is even more important – the “Display location” and “Library” drop-downs.

Earlier today, we received a ticket on our online helpdesk –

“We have written a new notice but nothing is displayed on the opac.”

When we cross-checked, we found that to be true. So we checked the new notice to find out what may be the problem. And sure enough it was exactly what we had expected had happened. The notice / news was set to display on the OPAC of client-partner’s defined library branch, instead of being set to “All libraries”.

Now you may ask how can this be wrong??? Well, up until an user logs in via the OPAC, the “library (branch)” is *NOT* set as Koha has no way of knowing which branch (since a Koha instance can cater to multiple library branches of an organisation) of the library the user is looking at at the moment. The notices / news would have showed up *if* the user had logged in into *that* defined branch in this case.

So, the logic to keep in mind while publishing a news item on the OPAC – select a specific branch for display *ONLY* if you want the notice to be branch specific, otherwise, keep it generic as “All libraries”.

Once this was corrected, the news defined showed up just fine as can be seen below.

Koha and the “magic” of XSLT – Part 2 : Show accession no. in OPAC results page

How to add 952$p (typically the accession no.) to your OPAC’s Results page display.

About 6 months back, we had posted about “Koha and the “magic” of XSLT : displaying new MARC fields on the OPAC“. This post can be thought of as its Part 2 as it introduces a couple of new concepts – (a) looping through a list of repeatable values and (b) punctuating these values for correct display. If XSLT or Koha with XSLT sound like something you are hearing for the first time, we strongly suggest that you first read the Part 1 first (see above).

The Backstory

Our tutorial style blog posts are usually the result of addressing some sort of user demand. In this case, this post came about because of Mr. Kalipada Jana, Librarian at Basanti Devi College, Kolkata. Yesterday he had filed a ticket on our helpdesk saying that he would like accession number(s) attached to each bibliographic record to be displayed on the OPAC results page. This is something that Koha does not do by default. But having seen such a display elsewhere he wanted to have the same.

The default Results page

chrome_2017-11-28_22-58-45

What the user wanted

chrome_2017-11-28_22-57-56

The Process

Koha stores it holdings item identification in MARC21 tag 952$p. The user here was using this field to store the individually unique accession numbers of their items in holdings. Now a bibliographic record may quite easily have multiple copies with separate accession numbers. So the XSLT snipped we needed must do the following:

  1. Handle looping over to display repeated 952$p (when there were multiple copies of the same book.
  2. Separate the accn nos. with “commas” if there where multiple copies of a book and after the final accession number terminate the line with a period instead of a comma. And if there was only a single copy, then instead of comma use a period.
  3. .

  4. Suppress this accession no. display for bibliographic records that do not have any holdings.

The code

<!-- L2C2 - 2017-11-28 adding accn no to results page 952$p -->
<xsl:if test="marc:datafield[@tag=952]/marc:subfield[@code='p']">
<span class="results_summary accn_no">
<span class="label">Accession number(s): </span>
    <xsl:for-each select="marc:datafield[@tag=952]">
        <xsl:value-of select="marc:subfield[@code='p']"/>
        <xsl:choose>
            <xsl:when test="position()=last()">
                <xsl:text>.</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>, </xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</span>
</xsl:if>

In the first line (not the comment) we check if the MARC record has a 952$p field and sub-tag. If it does only then the rest of the code is executed. This is what helps us to suppress this new display for records without any accession numbers in its 952$p. The next couple of lines push out the necessary HTML code since the record has at least one accession number i.e. 952$p. In the subsequent two lines immediately after, we set up two loops. The first one loops through all the 952 (holdings) field in the bib record, while the inner loop looks up the $p sub-field. The inner most bit i.e. <xsl:choose><xsl:when test="position()=last()"> handled the punctuation. First if it checks if the currect MARCXML 952$p sub-node is the last one, if so it places a period and terminates the line. Otherwise, it places a comma as punctuation between the multiple accession numbers.

This code was added into the custom file which we named as MARC21slim2OPACResults-bdcl.xsl. This file is same as the default MARC21slim2OPACResults.xsl file, the only addition being the snippet given above. In order to get Koha to start using our file instead of the default, we placed the full path of our new file into the OPAC system preference – OPACXSLTResultsDisplay.

See it in action

If you want to see this XSLT in action, click here.

Managing patrons with same permanent & local address

Setting your borrower’s local address same as their permanent address with just a single click during patron entry into Koha ILS.

Often folks when unable to find some nifty feature that was present in their erstwhile LMS but not there in Koha, is found to be exclaiming – “But we can’t do that with Koha!”. Well, we have news for you – Koha is open source and that means, you can build / modify the parts that you need or are missing. But you do not know how to do that. Well… *that* is not really Koha’s problem. But fear not, if you are willing and have the aptitude for poking around code you can do it too. There are plenty of open access resources that show you how to do so, just waiting for you to pick up and start working on your skills. After all, it is said:

If you give a hungry man a fish, you feed him for a day, but if you teach him how to fish, you feed him for a lifetime.

Why this post

At L2C2 Technologies, we work with a lot of academic libraries where they need to record both the permanent as well as local address of their students. Koha allows for recording more than a single address for a patron since donkey’s years. If you look at the schema of the borrowers table in the Koha database, you will see that there are fields to record both the primary address as well as alternate address. These two set of fields fit nicely into our permanent and local address requirement.

2017-06-19_01

However, the library staff often complain that it is useless extra work to re-enter the same data over in both set of fields as many users often have one and the same address for both. As a result, we are sometimes asked how to cut down this extra work. In this post, we are going to share one of the ways by which you too can do the same, should you need to do this.

Choosing our tools

All we use are snippets of JavaScript, jquery and css to achieve our objective. All of which go in into the Koha database as part of the IntranetUserJS system preference. We do not touch any template file or change any underlying PERL code. This way our tweak is guaranteed to survive Koha version upgrades without any further effort on our part.

The steps… as easy as 1-2-3

Since we do not want to re-type the same information, the only option is to copy it from first set of fields and that what we do by adding a checkbox HTML form input element. We give this checkbox the id copypermaddress and insert this into the DOM just before the first li element belonging to the parent fieldset memberentry_address on the Add Patron screen.

$('<li><input type="checkbox" name="copypermaddress" id="copypermaddress" value=""><label for="copypermaddress">Same as permanent address:</label><div class="hint">Click to copy permanent address data</div></li>').insertBefore(' #memberentry_address > ol > li:first-child ');

While the above insertion gets us the following screen, it still does not do anything i.e. if you clicked the checkbox, nothing would happen yet. In the next step we cover that.

2017-06-19_02

So we add a listener that will wait for state-change of the checkbox. In plain English, that means it will detect when a user clicks that checkbox and then based on whether it was selected or unchecked, appropriate action would be taken. And that exactly what happens below. The first part goes into action if the checkbox was checked and the part coming after the else kicks in when it is unchecked. In the first instance we copy over the values from the permanent address field and in the second part we undo the copy and blank out the local address fields.

$(document).ready(function(){
$('#copypermaddress').change(function() {
  if(this.checked) {
    $('#B_address').val($('#address').val());
    $('#B_address2').val($('#address2').val());
    $('#B_city').val($('#city').val());
    $('#B_state').val($('#state').val());
    $('#B_zipcode').val($('#zipcode').val());
    $('#B_country').val($('#country').val());
  } else {
    $('#B_address').val('');
    $('#B_address2').val('');
    $('#B_city').val('');
    $('#B_state').val('West Bengal');
    $('#B_zipcode').val('');
    $('#B_country').val('India');
  }
});
});

In the two following screenshots we get to see how exactly this works. In the first one, only the permanent address has been added. While in the second screenshot, we see how the data has been copied over when the checkbox is clicked.

2017-06-19_03

2017-06-19_04

References

  1. .insertBefore()http://api.jquery.com/insertbefore/
  2. :first-child Selectorhttps://api.jquery.com/first-child-selector/
  3. .change()https://api.jquery.com/change/
  4. .val()http://api.jquery.com/val/
  5. Koha DB Schema – http://schema.koha-community.org/master/

JQuery quicktip : Using Patron Attribute fields without double rowed textarea boxes

A JQuery quick tip for Koha ILS

Often we are have clients who want to capture additional data for their patrons. For schools and colleges, this typically includes demographic details, roll numbers, program enrolled etc. The Koha-friendly way to do is by using Extended Patron Attributes aka custom fields for patron data.`

2017-06-17_03-30-18

The thing about these patron attribute fields is that if these are expecting textual data input, Koha uses the textarea HTML element for them. Which is fine, except the textarea elements are sized to 2 rows by default. This something that confuses some users who expect to see an input element instead. So, we decided to adopt a middle way solution – to reduce the textarea element’s rows attribute from 2 to 1.

JQuery to the rescue

As always we turn to trusty jquery which makes this something ridiculously easy thing to do. Here is the code snippet:

$(document).ready(function(){
  if ($('#pat_memberentrygen').length) {
    var tareas = $('textarea[id^=patron_attr_]');
    for (var i=0; i < tareas.length; i++) {
      var t = $(tareas[i]);
      var tarea_reset_rows = t.attr('rows',1);
    }
  }
});

We plug that code into our IntranetUserJS system preference and we are good to go! 🙂 The screenshot below shows the change it brings to the patron data entry UI.

2017-06-17_03-31-01

Code explained

In the first line (i.e. the one starting with if) we check if we are actually on the patron member entry page. Next we create a JS array of only the textarea element on *that* page, *which* have an id that begins with patron_attr_. And finally we loop through that array and change the rows attribute of each textarea fields whose reference is stored in the array.

Harnessing Koha’s ExtendedPatronAttributes (aka patron custom fields)

Custom fields that make it possible to fit KohaILS to any type of library user category.

During from my frequent interactions with Indian Koha users over the last several years, one thing stands out rather starkly. There is surprisingly little understanding or use of the capabilities offered via Extended Patron Attributes. Since Koha ILS was written originally for public libraries (in fact public library consortia), its default patron data structures too are somewhat aligned with public libraries’ patron information capture.

When put to use in academic libraries e.g. K12 schools or colleges, the default patron information schema does not address the obvious need to capture data points like – programme enrolled, registration / roll numbers / class / sections details and in case of K12 schools – parent / guardian name and contact information etc. Many Koha users from the Indian sub-continent either (a) work their way around these issues without fully addressing their needs OR (b) often resort to direct editing of the koha.borrowers table schema, adding new custom fields and modifying the template files (.tmpl or .tt files) along with the Perl scripts that drive these templates.

The second approach is particularly problematic, as it means the modifications are usually hardcoded into scripts and templates. This is problematic is because doing so prevents the user from the benefit of seamless upgrades to their Koha. It means they have to do the whole “rinse-and-repeat” cycle everytime they upgrade their Koha, if they want their changes to persist. This makes Koha upgrades a costly, laborious, time-consuming process and error prone process.

Enter ExtendedPatronAttributes

According to the Koha manual –

“Patron attributes can be used to define custom fields to associate with your patron records. In order to enable the use of custom fields you need to set the ExtendedPatronAttributes system preference.”

About 10 years back, as Koha was finally moving out of version 2.x and moving into Koha 3.x, several new and exciting features were coming on to their own in Koha. One of this was the ability to easily handle custom fields for our patron records aka patron attributes. Around May 2008, my friend Galen Charlton, then with LibLime, wrote a (rather) large chunk of the code that brought in the support for custom fields to patron records. The ExtendedPatronAttributes system preference was the outcome and custom fields were here to stay.

Flash forward to present day

Recently we have been working with the Senior section library of Don Bosco School in Calcutta. Being a school library they needed to additionally support the following fields in their patron record (a) Class (b) Section (c) Roll No. (d) Parent / Guardian information i.e. name, contact info, relationship with student. Of course, we used defined these custom fields as patron attributes that were applicable only for their student patron category. In this blogpost, I will try to share just how easy and painless this is.

Step #1 : Enable ExtendedPatronAttributes syspref

This *is* the very first step and unless you enable this syspref, no matter what you do to define your custom fields (aka patron attributes), nothing would be visible.

Step #2 : Defining the Patron Attributes

In our case, we had two sets of information to be handled i.e. the student’s (a) academic details and (b) parent / guardian information. So we defined ST_CLASS, ST_SECTION and ST_ROLLNO patron attributes for the first part and ST_PNAME, ST_PRELATN and ST_PCONT as attributes for the second part.

2017-05-16_03-44-10

To make things easier for the library personnel (and reduce human error in the process), we pre-defined the values available to ST_CLASS, ST_SECTION and ST_PRELATN as authorised values.

2017-05-15_19-34-06

We also defined the PA_CLASS authorised value with the following two values : (a) ADETAILS (for academic details) and (b) GDETAILS (for guardian information).

2017-05-16_03-50-36

Step #3 : PA_CLASS – the secret sauce!

The Koha manual barely touches on this little nugget otherwise known as the PA_CLASS authorised value category. Before we proceed, just remember that in Koha Authorised value and Authority value mean two completely different things. Here we are talking about the former. If you have ever done any programming or done anything online, you must have used a drop-down / picklist to select a value. Well in Koha, authorised values are simply another name for picklists. These are defined as a category with the options added it. To the end-user, authorised values are presented as select drop-down HTML form element.

Now coming to PA_CLASS (or Patron Attribute Class), the first thing to remember is that by default Koha does not even define the PA_CLASS authorised value category. Rather it is left to the user to define it. There is a reason why it is not defined by default, not every library is going to used ExtendedPatronAttribute and unless you use it, PA_CLASS has no use. In our case, we have defined it and allotted it two values – ADETAILS and GDETAILS for now.

By allotting our custom fields (patron attributes) to either of these two PA_CLASS values allows us to logically group our two sets of information. By default, once done it looks like this:

2017-05-16_01-49-10

Order! Order! Order!

While chaos defines us, in life it is order that we look for, especially when we are attempting to present or capture information. So while the “Additional attributes and identifiers” grouping at the end of the page is adequate it is not ordered in the most logic flow with respect to the overall patron information form. Lucky for us, Koha has supported JQuery for donkey’s years. And JQuery provides us with a very nifty method .detach(). As the documentation says:

The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.

blog-epa

By detaching the PA_CLASS grouped fieldsets from the DOM and by storing these into variables one at a time, we are now ready to insert them exactly where we want these fieldsets to be placed in the overall form. And that is exactly what we did.

epa-full

Conclusion

This way we did not touch the templates or the underlying business logic of KohaILS. All our definitions are stored in the database. As a result, we can now perform IN-SITU upgrades of Koha without worrying if we will break our forms if we upgraded.

Switching content language on Koha OPAC with user interface locale switching

How to display custom content in the user’s own language on the OPAC.

Last week Mr. Ahmad Nasser from the Future University of Egypt reached out for a bit of help. The Koha OPAC provides certain sections / blocks on the OPAC e.g. OpacNav, OpacNavBottom, OpacNavBottom and OpacMainUserBlock etc. where libraries can add custom content / instructions / links / widgets to aid and inform their users better about their library and its services. Nasser’s case was interesting since he needed to cater to a bi-lingual readership where some users may prefer to read the information presented in Arabic rather than in English.

Development of language was the greatest break through of human technology. It helps us to communicate. But the same language when it is not the same for a group of people can create problem. How do a Bengali communicate with a Tamil, a Malayali with an Assamese when they do not understand the others’ language and they do not happen to speak English the global lingua-franca? Sort of like this line from this famous song pictured on Raj Kapoor in his super hit 1955 super hit –  Shree 420 that goes “mera joota hain Japani, yeh patloon engleesthani, saar pe topi russi….” (‘My shoes are Japanese, these pants are from England, the red hat on my head is Russian…’) – indeed how do we cater to this diversity!

trans_raj
Still image copyright: Shemaroo Videos

When it comes to a software like say Koha, the answer lies in localization – a process which allows a software to present information to its users in their own language of choice.

Koha’s user interface (UI) locale switching allows for users to switch the user interface language e.g. from default English to say Chinese (Taiwanese) or Hindi (India) as long as the language pack exists for Koha. However, this switching is not designed to tackle switching the language of the content in these custom blocks which we mentioned in the previous paragraphs.

Nasser wanted a way to display the content of say OpacMainUserBlock in Arabic when the user switched the user interface to Arabic and back in English when another user wanted to use the default language (i.e. english). This post highlights one ways by which Koha administrators / librarians can let their users a way to see the content in the language of their choice rather than an arbitrary default language or even worse a mish-mash of two or more languages.

This case is relevant to libraries in India as well, with our multitude of languages – 22 official languages at the last count – How do we serve content in English to our top 10 – 15% population, at the same time how do we address the rest of our population who are literate in their own language, all who may be some day be using Koha. Our records may be in the local regional language, but how about the added custom content? This solution works by looking at present locale[1] selected the user on the Koha OPAC.

The Solution

As I’ve mentioned this is not the only way to solve this problem. But it is probably the simplest *and* the cleanest one. And it does so by using three things:

  • The selected locale language of the Koha OPAC
  • One line of custom CSS placed into OpacUserCSS system preference
  • Exactly 3 lines of Javascript added to OpacUserJS system preference

In this blog post, we’re only looking at managing the OpacMainUserBlock – the central block on the OPAC, but the solution can be applied to every other blocks that access custom HTML markup – including OpacHeader, OpacCredits  as well as on “Koha as CMS” pages etc.

If you have never setup multiple language support on Koha, you can read up – “Installation of additional languages for OPAC and INTRANET staff client” and familiarize yourself first.

The Demo

I’ve set up a multiple language demo Koha installation with the following languages aside from the default English:

(a) Arabic (ar-Arab)
(b) Czech (cs-CZ)
(c) German (de-DE)
(d) Hindi (hi)
(e) Slovak (sk-SK)
(f) Chinese (Taiwanese: zh-Hans-TW)

The URL is https://demo-opac.l2c2academy.co.in/cgi-bin/koha/opac-main.pl where you can see this working in action. As you change the selected language and right click to see source code of the page, you will notice that the “lang” attribute of the “html” element changes to the language codes given inside the parentheses above. Below is a snapshot of 6 of the 7 languages as rendered in the HTML source once you change the language.

trans_all_src

Hint: That lang attribute is our locale identifier and it changes every time we select a different language. Try it out on the demo and see it for yourself.

Since this depends on using CSS to toggle the visibility of our local language content we are going to define a disabled class in our OpacUserCSS system preference like this:

/* disabled class */

.disabled {
   display: none;
}

In this example we will use a <div> element like given below:

<div class="en disabled">

 your local language content goes here

</div>

However we can use this technique on *any* HTML element whose visibility can be toggled by accessing its display CSS property [2]. We will need to add two extra classes to our HTML element – the first one class will be named as our lang attribute and the second class will be the disabled class. We’ll need to repeat this definition for each language that we want to deal with.

For your reference here is a listing of my OpacMainUserBlock for this example, please download and study it in order to understand the process better.

NOTE: For this example, I’ve selected a single paragraph from the entry on “Wikipedia” from the Arabic, Czech, German, English, Hindi, Slovak and Chinese Wikipedia.

Once, our custom HTML is in place, we will need a way to toggle their visibility (CSS display property) based on the user selected language locale via the lang attribute. For this we’ll use the following JQuery snippet in our OpacUserJS system preference:

$(document).ready(function() {

  var selectedlang = $('html')[0].lang;

  var buildClassString = ".".concat(selectedlang);

  $(buildClassString).removeClass('disabled');

});

The first line finds out the lang attribute of our <html> element. In the next line we build a string to hold the selector for the class (since classes are notified in JQuery selectors using a dot in front of the class name). And finally, in the third line, we remove the disabled class from the content whose language class matches the lang attribute. By removing the class from the element, we automatically cause its display CSS property to become visible.

What really happens behind the scenes

The custom HTML markup is first loaded with its visibility turned off. Once the page is loaded the document.ready() JQuery call looks up the current language selected and removes the display: none; CSS style from the element by removing the disabled class. As a result, the element and the content it is designated to display becomes visible. This whole cycle is repeated when we select another language. Thus, we are now able to provide our users with custom HTML markup and content based on the language they selected.

Reference

[1] “Locale (computer software) – Wikipedia, the free encyclopedia

[2] “CSS/Properties/display – W3C Wiki

Gotcha! GoogleIndicTransliteration may not work if your Internet connection is slow!

Cross domain scripts may fail to load over slow links, reducing functionality and impacting user experience.

Indian libraries on Koha ILS often use the GoogleIndicTransliteration setting to provide Indian language search support to the OPAC search. The feature works by having your Koha sending a request to the Google’s servers to dynamically load the API code into the OPAC page and execute it, so that it is ready to translate what you type into the language you have selected for transliteration into. So basically you must have an active Internet connection on the system from which you are using the OPAC if you want transliteration to work. However as it turns out, that may not exactly be enough!

Yesterday Sujan Saha messaged me asking if the GoogleIndicTransliteration setting was somehow missed out during setup of a particular OPAC instance. The screenshot collage above shows what he expected (on the left) versus what he got (on the right). Nope! the setting was very much there, so what was the case?

Turns out he was trying to access the OPAC over a particularly slow (that day) Vodafone 3G connection. So, while rest of Koha would load and execute even over the slow link, Google transliteration didn’t, in fact, it vanished from his screen. Since it is JavaScript, the best way to debug it is to turn to the console on your browser.

NOTE: If you are on Google Chrome, you can find it under More tools -> Developer tools option on the menu.

In this case, the console clearly shows the following warnings:

kaboom

So basically a slow network link combined with a couple of cross origin parser blocking script (the Transliteration API code) is the reason why he saw no option for transliteration.

Quod erat demonstrandum!

Hiding “Authority search” and “Tag cloud” search options on Koha OPAC using CSS.

CSS one-liner to hide Authority search & Tag cloud options on the Koha OPAC.

Client partners not using authority files and tag cloud features of Koha, often insist that we remove the options – “Authority seach” and “Tag cloud” from the OPAC. Now, if we look at the DOM (Document Object Model) of the OPAC main page, we will see that these searches are located inside a <div> element named moresearches.

<div id="moresearches">
  <ul>
    <li>
      <a href="/cgi-bin/koha/opac-search.pl">Advanced search</a>
    </li>
    <li>
      <a href="/cgi-bin/koha/opac-authorities-home.pl">Authority search</a>
    </li>
    <li>
      <a href="/cgi-bin/koha/opac-tags.pl">Tag cloud</a>
    </li>
  </ul>
</div>

The other important thing to note here is the CSS (Cascading stylesheet) rules for the div,li elements and the li:after pseudo class [1].

div {
    display: block;
}
#moresearches li {
    display: inline;
}
#moresearches li:after {
    content: " | ";
}

Note: That li:after is what adds the ” | ” (pipe) separator between the options.

So, we are going to “hide” them and we will mainly use the CSS3 :nth-child() pseudo class selector to do this.

CSS3 :nth-child simplified

If you want a formal definition, go ahead and read this CSS/Selectors/pseudo-classes/:nth-child from the W3C (World Wide Web Consortium) wiki.

Let us see if it is better understood with an actual example! In our case, we can see that our <ul> (unordered list) element has 03 (three) <li> (list item) child elements. The nth-child is a counter that starts from 1 (one). Thus, nth-child(2) signifies the second “child” element. Here this would point to the second <li> i.e. the “Authority search”. Thus n in nth-child is simply a way to refer to a specific child.

The term “selector” is simply a rule / ruleset (i.e. code) that helps us to latch on to a particular element (or its content) by using either it’s (a) name; (b) id; (c) class, (d) contents, (e) position OR a combination of these or other attributes, and then do whatever we want to do with it. When selectors are used with CSS, we are usually talking about styling them.

Hint: making an element (or group of elements) in your DOM invisible (as in this case) will also be considered as styling.

The solution

While we can write the ruleset in a single line, here we have broken it up into two lines for better readability and understanding.

#moresearches > ul > li:nth-child(n+2) { display: none; }

#moresearches > ul > li:after { display: none; }

n by itself references the first child element. The notation n+2 in this case means select the other two <li> elements *after* the first one i.e. “Advanced search”. Once selected we set then to display: none;. This turns off their visibility while still retaining this elements in the DOM. The second line is more cosmetic in nature and turns off the visibility of the li:after pseudo class so that there is no dangling “|” displayed after Advanced search.

References

[1] http://www.w3schools.com/css/css_pseudo_classes.asp