Blog

 6 minute read.

Yer Basic One-Liner

Tony Hammond

Tony Hammond – 2008 October 14

In Handle

one-line-alert-small0.jpg

Here’s your basic one-line handle client (all of it) for the browser:

OpenHandle.Util().getHandleData("10.1038/nature05826", function(data) { alert(OpenHandle.Util().helloWorld(data)); });

Can’t see how to make that much shorter (bar tossing spaces). But here’s one attempt (shorter though now it’s not strictly a one-liner):

var u = OpenHandle.Util();
u.getHandleData("10.1038/nature05826", function(_) { alert(u.helloWorld(_)); });

Here I’ve used two utility convenience methods from the OpenHandle client library:

OpenHandle.Util().getHandleData(handle, callback, [server])
OpenHandle.Util().helloWorld(JSON)

You will though need to include a couple of libraries: openhandle.js and jquery.js. (Note that the getHandleData() method supplied in the openhandle.js library uses jQuery. Feel free to overwrite that.) A complete working document can thus be implemented as:

<html>
<head>
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.2.6.js"></script>
<script type="text/javascript" src="http://openhandle.googlecode.com/files/openhandle-0.2.3.js"></script>
<script type="text/javascript">
jQuery().ready(function() { /* action when body content is loaded */
var u = OpenHandle.Util(); u.getHandleData("10.1038/nature05826", function(_) { alert(u.helloWorld(_)); });
});
</script>
</head>
<body>
Boo!
</body>
</html>

Let me know if this doesn’t work for you. I’ve tried to test this and seems to function OK but sure as the sun rises I ain’t no JS ninja.

Of course, we normally want to do more than just dump the values. So, given that it’s pretty straightforward to grab and to manipulate a handle’s data values over the Web, how can we put this into practice?

Let’s consider a couple of Crossref use cases.

(Disclaimer: These examples are not intended as being in any way a replacement for the existing Crossref services but merely show how those services could be implemented on the client side. These illustrations will be useful for new bespoke services accessing other data elements that may be registered with the DOI.)

Single Resolution

Here is how one could implement the regular URL redirect service from the client:

var handle = "10.1038/nature05826";
var callback = function(json) {
  var hv = new OpenHandle.Handle(json).getValuesByType(URL')[0];
  var url = new OpenHandle.HandleValue(hv).getData();
  // alert("Redirecting to " + url);
  window.location = url;
};
OpenHandle.Util().getHandleData(handle, callback);

The getValuesByType(‘URL')[0] call returns the first handle value of type ‘URL’. The next line just parses this value as a handle value object and gets the data field, i.e. the URL itself.

Note here that this client can show the URL that the user will be redirected to. With normal DOI resolution the resolution takes place on the proxy server (dx.doi.org) and the URL is not available to the user - until they are so redirected. In fact, the user may never get to see the URL stored in the handle value if this is the head of a redirect chain.

To recap, Crossref DOIs are not resolved by the user to URLs - rather, they invoke a service on the server which returns a content page.

Multiple Resolution

Let’s now take a look at a case of Crossref multiple resolution. This code uses the getValues() method to return all values:

var handle = "10.1130/B25510.1";
var callback = function(json) {
  var s = "";
  var hv = (new OpenHandle.Handle(json)).getValues();
  for (var i = 0; i < hv.length; i++) {
    var v = new OpenHandle.HandleValue(hv[i]);
    s += v.getType() + ": " + v.getData();
  }
  alert(s);
};
OpenHandle.Util().getHandleData(handle, callback);

which yields

700050: 200508231619480000
HS_ADMIN: [object Object]
URL.0: http://www.gsajournals.org/gsaonline/?request=get-abstract&doi=10%2E1130%2FB25510%2E1
URL.1: http://bulletin.geoscienceworld.org/cgi/doi/10.1130/B25510.1
CR-LR: <MR><LI label="GeoScienceWorld" resource="URL.1" /><LI label="Geological Society of America" resource="URL.0" />

Oops! Too much information. This includes types such as ‘700050’ and ‘HS_ADMIN’ which are used by the Crossref application, and not intended for the end user. Maybe we should just limit it to the URL types with getValuesByType('URL'):

getValuesByType(URL'):

var handle = "10.1130/B25510.1";
var callback = function(json) {
  var s = "";
  var hv = (new OpenHandle.Handle(json)).getValuesByType(‘URL');
  for (var i = 0; i < hv.length; i++) {
    var v = new OpenHandle.HandleValue(hv[i]);
    s += v.getType() + ": " + v.getData();
  }
  alert(s);
};
OpenHandle.Util().getHandleData(handle, callback);

which yields

URL.0: http://www.gsajournals.org/gsaonline/?request=get-abstract&doi=10%2E1130%2FB25510%2E1
URL.1: http://bulletin.geoscienceworld.org/cgi/doi/10.1130/B25510.1

_(By the way, the previous example shows the unregulated state of handle types. We have everything but the kitchen sink in this one example:

  • simple types, both well-known (‘URL’) and opaque (‘700050’)
    • compound, or namespaced, types with various hierarchy delimiters: dot (‘URL.0’, ‘URL.1’), underscore (‘HS_ADMIN’), and hyphen (‘CR-LR’)

    Well, they’re all in there now so we gotta deal with that, but generally one would probably have preferred well-known types and where namespaces are used the usual dot notation as this is a) familiar to programmers, and b) supported by the handle client library code. The underscore is used in the handle RFCs for system types so that can be viewed as a sort of inline namespacing. Seems to be no obvious excuse for hyphens though.)

    Back to the example we can see that the first URL goes to a Crossref service which we can dispense with since this example is to be run client side. That leaves us with the two actual URL targets. But how to differentiate those for a user choice? That’s where that other type ‘CR-LR’ comes in which provides an XML fragment that relates label to type. There are obviously many ways to support resource labelling - this is just the method used by Crossref.

    Let’s parse out the XML fragment for labels and resources and save those in an object keyed on resource:

var labels = {};
var hv_ = (new OpenHandle.Handle(json)).getValuesByType(CR-LR')[0];
var v = new OpenHandle.HandleValue(hv_);
var xml = v.getData();
var li = xml.match(/<li [^\>]* \/>/ig);
for (var i = 0; i < li.length; i++) {
  var a = li[i].match(/label=\"([^\"]+)\"
resource=\"([^\"]+)\"/i);
  labels[a[2]] = a[1];
}

Now we’ll also need to build a similar object for the URLs:

var urls = {};
var hv = (new OpenHandle.Handle(json)).getValuesByType(URL');
for (var i = 0; i < hv.length; i++) {
  var v = new OpenHandle.HandleValue(hv[i]);
  urls[v.getType()] = v.getData();
}

And now with both these objects we can build a set of labelled links as:

var s = "";
for (item in labels) {
  s += "<a href=\"" + urls[item] + "\">" + labels[item] + "</a>";
}
alert(s);

to yield

<a href="http://bulletin.geoscienceworld.org/cgi/doi/10.1130/B25510.1">GeoScienceWorld</a>
<a href="http://www.gsajournals.org/gsaonline/?request=get-abstract&doi=10%2E1130%2FB25510%2E1"gt;Geological Society of America</a>

How to build a page with those labelled links is now a simple exercise. (The actual Crossref service for doi:10.1130/B25510.1 returns a page with labelled links, logos, and metadata pulled from the Crossref database.)

Next Steps

The aim of this work has been to show that getting access to handle data values and manipulating those values in the browser can be fairly straightforward. How additional values get to be added to DOIs (or other handles) and what those values refer to is another matter, but services to access such values do not need to be centralized. User-generated services are also a possibility.

Further reading

Page owner: Tony Hammond   |   Last updated 2008-October-14