Search

Learning JQuery - a Poet Laureate Browser.

I'm probably the last developer in the web-verse to learn jQuery.  I prefer to use raw JavaScript, partly because I think that is best in a teaching context and partly because I don't write enough JavaScript to warrant learning a new and large API. However I'm doing more XQuery/Javscript coding in my current work and a couple of the plugins look very useful. 

In particular, a time slider will be needed for my Gloucester Road history project, so as an exercise I wrote a Poet Laureate browser using a time-slider based on the  RangeSlider from the  jQuery UI Tools.

British Poet Laureate in 1946

Here I use an XQuery script to retrieve the table of Poet Laureates from Wikipedia which is transformed into multiple tables, one of each poet, with the start and end years of their tenure.  The script takes one parameter, a year.  A RangeSlider is configured with a function which shows only the Poet Laureate in that year. The slider is initialized to the supplied year.

XQuery



declare default element namespace  "http://www.w3.org/1999/xhtml";
declare option exist:serialize "method=xhtml media-type=text/html omit-xml-declaration=no indent=yes 
        doctype-public=-//W3C//DTD XHTML 1.0 Transitional//EN
        doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";

let $year := xs:integer(request:get-parameter("year",1900)) 
let $page := doc("http://en.wikipedia.org/wiki/Poet_Laureate_of_the_United_Kingdom")
let $table := $page//table[3]
let $poets := 
  <div id="poets">
    {for $poet in subsequence($table/tr,2)
     let $start := $poet/td[5]/a[1]/string()
     let $next := ($poet/following-sibling::tr)[1]
     let $end := 
         if (exists($next))
         then $next/td[5]/a[1]/string()
         else ()
     return
       <table start="{$start}" end="{$end}" style="display:none" >
         {for $th at $i in $table/tr[1]/th
          let $info := $poet/td[$i]/(* except element(br))
          return
             <tr>
              <th>{$th/string()}</th>
              <td>{$info}</td>
              </tr>
         }
       </table>
    }  
  </div>
return
<html>
   <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <base href="http://en.wikipedia.org/"/> 
        <title>British Poet Laureates</title>    
        <link type="text/css" href="http://webapps.kitwallace.me/exist/rest/db/css/ui-lightness/jquery-ui-1.8.12.custom.css" rel="stylesheet" />    
        <script type="text/javascript" src="http://webapps.kitwallace.me/exist/rest/db/jscript/jquery-1.5.1.min.js"></script>
        <script type="text/javascript" src="http://webapps.kitwallace.me/exist/rest/db/jscript/jquery-ui-1.8.12.custom.min.js"></script>
        <script type="text/javascript" src="http://webapps.kitwallace.me/exist/rest/db/apps/jquery/laureate.js"> </script>
   </head>
   <body>
       <h2>British Poet Laureate in the year <input type="text" id="year" value="{$year}"/></h2>
       <div id="slider"/>   
       {$poets}
   </body>
</html


A default element namespace is used here because both the Wikpedia page and the output are in the xhtml namespace.

The HTML base is set in the generated html so that the copied relative links from the Wikipedia page remain relative to Wikipedia.

The JavaScript / jQuery :



$(document).ready(function() {
    var year =  $('#year').val();
    $('#slider').slider({
         value: year,
         min: 1600,
         max: 2011,
         slide: function (event, ui) {selectPoet(ui.value)}
      });
    selectPoet(year);
});

function selectPoet(year) {
   $('#year').val(year);
   $('#poets table').each(function (index) {
         if ($(this).attr('start') <= year && 
            ($(this).attr('end') == '' || $(this).attr('end') > year) )
            $(this).show();
         else 
            $(this).hide();
        }
    )
};


As always, I have trouble deciding where to place functionality - in the server-side script or in the client.  I also have a problem with the best way to include attributes in the HTML to be used by jQuery.  Here I have added  attributes start and end to table but this makes the XHTML invalid.  I tried putting them in a different namespace, which works but the XHTML is still invalid.  I would be interested to discover the recommended way to solve this problem.

Still a lot to learn but jQuery and XQuery make good companions.

 

 

A nicely written up start :-)

Regarding your start and end attributes issue, I think you only need one of these values, as its part of a sequential list in this instance. You could then encode the value in either the id attribute, or perhaps even use RDFa so that you have valid markup.

Another option would be to use an AJAX get request in combination with the Sliders 'slidechanged' event, so that the date is sent to the server and an XML or JSON fragment (eXist now has a JSON serializer) is returned, from this you could update the DOM.

Hi Adam, thanks for the feedback.

An AJAX call per slider update would be pretty heavy, and would require the Wikipedia page to be cached no big deal since its hardly fast-moving data but added complexity.

Dropping the end year would be possible - it's one of those server-side/client side issues but it wouldn't solve the general problem of where to put data. In the past I've generated JavaScript arrays but its cleaner to keep all the data together. jQuery has the meta-data plugin http://plugins.jquery.com/project/metadata to unpack JSON structures stored in HTML attributes like class or title and the data-* attributes of HTML5 might be another route. Personally I'm tempted to use attributes in a custom namespace which seems clean even if it throws HTML validation errors.

Well perhaps it -is- better to create valid XHTML so I took the metadata route. This means generating the table with a JSON class name:

<table style="display:none" class="{{ start: {$start}, end: {$end} }}">

(doubled { to get a real { in XQuery )
and then retrieving the data with :

range = $(this).metadata();
if ( range.start <= year && etc.

http://webapps.kitwallace.me/exist/rest/db/apps/jquery/laureate2.xq?year=1946

Not too painful after all!