XQuery/Navigating Collections
Appearance
< XQuery
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 XHTML 1.0 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;