Jump to content

XQuery/Navigating Collections

From Wikibooks, open books for an open world

Motivation

[edit | edit source]

You want to browse collections using an HTML web page and narrow your choices as you type.

Method

[edit | edit source]

We will first create a server-side script that takes a single parameter. This is the collection path that the user is entering into an input field in a web page. With each character the user types the list of possible sub-collections is narrowed.

There are three parts to this script: 1) the server side XQuery script 2) the HTML form 3) the JavaScript file that implements the JavaScript with AJAX functions.

Sample Server-Side Script

[edit | edit source]

get-child-collections.xq

[edit | edit source]
xquery version "1.0";   declare function local:substring-before-last-slash($arg as xs:string?) as xs:string { if (matches($arg, '/'))  then replace($arg,'^(.*)/.*','$1') (: by default matching is eager :)  else ''  }; (: if we don't get any value then use the root collection :) let $collection := request:get-parameter("collection", '') let $parent := local:substring-before-last-slash($collection) let $leaf := substring-after($collection, concat($parent, '/')) let $sub-collections := xmldb:get-child-collections($parent) return <div class="results">{  if (count($sub-collections) = 0)  then   <h1>There are no subcollections of {$collection}</h1>  else  <div class="selections">{  for $child in $sub-collections  let $child-path := concat($parent, '/', $child)  order by $child  return  if (starts-with($child, $leaf))  then  <div class="selection"><a href="browse-collection.xq?collection={$child-path}/">{$child}</a></div>  else ()  }</div> }</div> 

browse-collection.xq

[edit | edit source]
xquery version "1.0"; declare option exist:serialize "method=xhtml media-type=text/html omit-xml-declaration=no indent=yes   doctype-public=-//W3C//DTD&#160;XHTML&#160;1.0&#160;Transitional//EN  doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"; let $title := "Browse Collections (AJAX)" let $collection := request:get-parameter("collection", '/db/') return <html xmlns="http://www.w3.org/1999/xhtml" >  <head>  <title>{$title}</title>  <script type="text/javascript" src="ajax-collection.js"/>  <style type="text/css">  td {{background-color: #efe; font-size:14px;}}  th {{background-color: #ded; text-align: right; padding:3px; font-size:12px;}}  </style>   </head>  <body onload="getList();">  <h1>{$title}</h1>  <p>{$collection}</p>  <form onsubmit="getList(); return false" action="get">  <span>  <label for="collection">Collection:</label>   <input type="text" size="50" name="collection" id="collection" title="collection"  onkeyup="getList();" onfocus="getList();" value="{$collection}"/>  </span>  </form>  <!-- this is where the results are placed -->  <div id="results"/>  </body> </html> 

ajax-collection.js

[edit | edit source]
function updateList() {  if (http.readyState == 4) {  var divlist = document.getElementById('results');  divlist.innerHTML = http.responseText;  isWorking = false;  } }   function getList() {  if (!isWorking && http) {  var collectionid = document.getElementById("collection").value;  http.open("GET", "get-child-collections.xq?collection=" + collectionid);  http.onreadystatechange = updateList;   // this sets the call-back function to be invoked when a response from the HTTP request is returned  isWorking = true;  http.send(null);  } }   function getHTTPObject() {  var xmlhttp;  /*@cc_on  @if (@_jscript_version >= 5)  try {  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");  } catch (e) {  try {  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  } catch (E) {  xmlhttp = false;  }  }  @else  xmlhttp = false;  @end @*/  if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {  try {  xmlhttp = new XMLHttpRequest();  xmlhttp.overrideMimeType("text/xml");   } catch (e) {  xmlhttp = false;  }  }  return xmlhttp; }   var http = getHTTPObject(); // create the HTTP Object var isWorking = false;