/
angularjs-library-services.html
193 lines (186 loc) · 24.4 KB
/
angularjs-library-services.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<meta name="dcterms.date" content="2014-07-11">
<title>Exposing library services with AngularJS</title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; }
code > span.dt { color: #902000; }
code > span.dv { color: #40a070; }
code > span.bn { color: #40a070; }
code > span.fl { color: #40a070; }
code > span.ch { color: #4070a0; }
code > span.st { color: #4070a0; }
code > span.co { color: #60a0b0; font-style: italic; }
code > span.ot { color: #007020; }
code > span.al { color: #ff0000; font-weight: bold; }
code > span.fu { color: #06287e; }
code > span.er { color: #ff0000; font-weight: bold; }
</style>
<link rel="stylesheet" href="code4lib.css">
</head>
<body>
<header>
<p id="issueDesignation">2014-07-11</p>
<h1 class="title">Exposing library services with AngularJS</h1>
<div class="abstract">
<p><p>This article provides an introduction to the JavaScript framework AngularJS and specific AngularJS modules for accessing library services. It shows how information such as search suggestions, additional links, and availability can be embedded in any website. The ease of reuse may encourage more libraries to expose their services via standard APIs to allow usage in different context.</p></p>
</div>
<div class="author">
by
Jakob Voß
and
Moritz Horn
</div>
</header>
<h1 id="introduction">Introduction</h1>
<p>The demand to open up library systems through web services has been known for years <span class="citation" data-cites="Breeding2009">(Breeding 2009)</span>. In particular, service-oriented architecture (SOA) promised to better allow a continuous evolution of library automation and to better connect with external systems. Nevertheless current library systems are rarely built of loosely coupled parts that could be used independently. This reliance on monolithic systems results in a lack of open APIs to library services.</p>
<h2 id="library-services-and-apis">Library services and APIs</h2>
<p>Services provided by a library or similar institution should be easy to use by anyone and in any form. Most services, however, can only be used in the fixed context of a particular user interface (UI). If a service is also accessible via application programming interface (API), its functionality can be integrated and used in other applications too. Unfortunately the need to expose services via open APIs is less obvious than UIs.</p>
<p>User interfaces are curated and revised by usability studies and user experience (UX) at best. In other instances the UI is simply judged with common sense by normal library staff and management. APIs on the other hand, cannot simply be viewed, used, and judged by anyone. Unlike the UI, an API is not a final application to make use of a service, but the basis for creation of service applications: Without APIs, applications are difficult to build and services can only be provided in limited form. Without applications, however, it is difficult to justify the need for an API.</p>
<p>To give an example, most library systems lack an API to query current availability of documents held by the library. As long as information about current availability was only displayed in local library OPACs there was little motivation to create a public API for this purpose. With the need to display availability information in discovery interfaces such as VuFind, the Document Availability Information API (DAIA) was created at Gemeinsamer Bibliotheksverbund (GBV) <span class="citation" data-cites="DAIA">(Voß and Reh 2014)</span>. But little interest was shown by other libraries and system vendors as long as they did not require the API for internal use. The full benefit of an open API is not revealed until different applications by different parties make use of it. This article will demonstrate a possible strategy to increase visibility and use of library APIs by providing client modules that facilitate the creation of applications by third parties.<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> The modules are based on the JavaScript framework <a href="https://angularjs.org/">AngularJS</a> which is getting more and more popular among developers of web applications. The general strategy is illustrated in the following diagram:</p>
<figure>
<img src="layers.png" alt="From library service to web application" /><figcaption>From library service to web application</figcaption>
</figure>
<h1 id="angularjs">AngularJS</h1>
<p><a href="https://angularjs.org/">AngularJS</a> is a web application framework that aims to enhance the functionality of JavaScript. The framework is designed to support modularization on multiple levels. Functionality of applications is broken into parts that can be tested and reused independently.</p>
<p>Application logic is first grouped in <em>modules</em>, each included with an HTML <code><script></code> tag. Some popular modules are listed at the unofficial directory <a href="http://ngmodules.org/">http://ngmodules.org/</a>. Modules may build on each other and define <em>directives</em>. These directives can be used in the form of custom HTML tags and attributes (“declarative HTML”). The core AngularJS module contains directives for basic programming syntax in HTML, such as conditionals (<code>ng-if</code>) and loops (<code>ng-repeat</code>), among others. This extension of HTML is further enriched by a template syntax with AngularJS <em>expressions</em> written in curly brackets (<code>{{...}}</code>). The most common use of these expression is to dynamically display variables in HTML templates. In contrast to most other template systems, variables are bound two-way: the display is updated automatically when a variable is changed, and changes of the HTML document (e.g. by input forms) are reflected in the JavaScript variables. To avoid name collision and to better separate functionality of different directives, variables belong to <em>scopes</em> that act like namespaces in other programming languages.</p>
<p>The following example illustrates the use of AngularJS with scope variables, templates, and directives:<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a></p>
<pre class="sourceCode html"><code class="sourceCode html"><span class="kw"><html</span><span class="ot"> ng-app=</span><span class="st">"myApp"</span><span class="kw">></span>
<span class="kw"><head></span>
<span class="kw"><script</span><span class="ot"> src=</span><span class="st">"angular.min.js"</span><span class="kw">></script></span>
<span class="kw"><script></span>
<span class="ot">angular</span>.<span class="fu">module</span>(<span class="st">'myApp'</span>, []);
<span class="kw">function</span> <span class="fu">MyController</span>($scope) {
<span class="ot">$scope</span>.<span class="fu">books</span> = [
{ <span class="dt">title</span>: <span class="st">"One Thousand and One Nights"</span> },
{ <span class="dt">title</span>: <span class="st">"Where the Wild Things Are"</span>, <span class="dt">author</span>: <span class="st">"Sendak"</span> },
{ <span class="dt">title</span>: <span class="st">"The Hobbit"</span>, <span class="dt">author</span>: <span class="st">"Tolkien"</span> },
];
}
<<span class="ot">/script></span>
<span class="ot"> </head</span>>
<body ng-controller=<span class="st">"MyController"</span>>
<ul ng-repeat=<span class="st">"b in books | orderBy:'title'"</span>>
<li>
<i>{{<span class="ot">b</span>.<span class="fu">title</span>}}<<span class="ot">/i></span>
<span class="ot"> <span ng-if="b.author">by {{b.author}}</span</span>>
<<span class="ot">/li></span>
<span class="ot"> </ul</span>>
<<span class="ot">/body></span>
<span class="ot"></html</span>></code></pre>
<p>The example consists of an application module “myApp”. This module defines a controller “MyController” to set a list of three bibliographic items in the variable “books” of a given scope. The controller is later used in the HTML body to display a sorted list of books with an HTML template. The template makes use of standard AngularJS directives (<code>ng-repeat</code>, <code>ng-if</code>) and expressions (<code>| orderBy:'title'</code>, <code>b.title</code>, <code>b.author</code>). The application logic to create such a list could also be packed in a new directive to be used a as “widget” in multiple places.</p>
<h1 id="modules-for-embedding-library-services">Modules for embedding library services</h1>
<p>The practical embedding of library services in websites with AngularJS is illustrated in the following two examples. Both are available as AngularJS modules for easy reuse: the <em>ng-suggest</em> module provides access to search suggestions and links <span class="citation" data-cites="ngsuggest">(Voß and Horn 2014a)</span> and the <em>ng-daia</em> module provides access to availability information <span class="citation" data-cites="ngdaia">(Voß and Horn 2014b)</span>. Both modules are hosted at public git repositories with API documentation, examples, and downloads (<a href="https://gbv.github.io/ng-suggest/">https://gbv.github.io/ng-suggest/</a> and <a href="https://gbv.github.io/ng-daia/">https://gbv.github.io/ng-daia/</a>).</p>
<h2 id="suggestions-with-ng-suggest">Suggestions with ng-suggest</h2>
<p>The OpenSearch standard for search engines includes a specification for how to query search suggestions and autocomplete services via HTTP <span class="citation" data-cites="Clinton2006">(Clinton 2006)</span>. Suggestion services are provided by many search applications as “typeahead”. The method can also be used for instance by recommendation services <span class="citation" data-cites="Voss2008">(Voß 2008)</span> and to support tagging with controlled vocabularies <span class="citation" data-cites="Nagaya2011">(Nagaya et al. 2011)</span>.</p>
<figure>
<img src="typeahead.jpg" alt="Typeahead via OpenSearch Suggestions" /><figcaption>Typeahead via OpenSearch Suggestions</figcaption>
</figure>
<p>The OpenSearch Suggestions specification defines a query response as JSON array with at least two elements (query string and a list of search completions):</p>
<pre><code>[
"Moz",
["mozilla","mozilla firefox","mozart","mozilla thunderbird",...]
]</code></pre>
<p>Optional elements can include descriptions and URLs for each search completion. While processing of this simple format is not very complex, it still requires JavaScript skills to make use of a suggestion service. <em>ng-suggest</em> simplifies the embedding to two HTML statements. The following example code adds Wikipedia typeahead features to an input form element:</p>
<pre class="sourceCode html"><code class="sourceCode html"><span class="kw"><html</span><span class="ot"> ng-app=</span><span class="st">"myApp"</span><span class="kw">></span>
<span class="kw"><head></span>
<span class="kw"><script</span><span class="ot"> src=</span><span class="st">"angular.min.js"</span><span class="kw">></script></span>
<span class="kw"><script</span><span class="ot"> src=</span><span class="st">"ui-bootstrap-tpls.min.js"</span><span class="kw">></script></span>
<span class="kw"><script</span><span class="ot"> src=</span><span class="st">"ng-suggest.min.js"</span><span class="kw">></script></span>
<span class="kw"><script></span>
<span class="ot">angular</span>.<span class="fu">module</span>(<span class="st">'myApp'</span>, [<span class="st">'ui.bootstrap'</span>,<span class="st">'ngSuggest'</span>]);
<span class="kw">function</span> <span class="fu">MyController</span>($scope) {
<span class="ot">$scope</span>.<span class="fu">api</span> = <span class="st">"https://en.wikipedia.org/w/api.php?action=opensearch"</span>
+ <span class="st">"&limit=10&namespace=0&format=json&search="</span>;
<span class="ot">$scope</span>.<span class="fu">selectItem</span> = <span class="kw">function</span>(item) {
<span class="ot">$scope</span>.<span class="fu">item</span> = item;
};
};
<<span class="ot">/script></span>
<span class="ot"> <link href="bootstrap.min.css" rel="stylesheet" /</span>>
<<span class="ot">/head></span>
<span class="ot"> <body ng-controller="MyController"></span>
<span class="ot"> <input style="width:400px" class="form-control"</span>
<span class="ot"> typeahead-on-select="selectItem</span><span class="fl">(</span><span class="ot">$item</span><span class="fl">)</span><span class="ot">"</span>
<span class="ot"> ng-model="input"</span>
<span class="ot"> suggest-typeahead="api" jsonp=1</span>
<span class="ot"> placeholder="Search Wikipedia" /</span>>
<div ng-<span class="kw">if</span>=<span class="st">"item"</span>>{{<span class="ot">item</span>.<span class="fu">label</span>}}<<span class="ot">/div></span>
<span class="ot"> </body</span>>
<<span class="ot">/html></span></code></pre>
<p>The resulting HTML page would look like this:</p>
<figure>
<img src="suggest_wikipedia_en.png" alt="Suggest Wikipedia articles with ng-suggest" /><figcaption>Suggest Wikipedia articles with ng-suggest</figcaption>
</figure>
<p>Similar suggestions can be provided for any Open Search Suggestions service by just changing the service’s base URL. Among other features, responses can be embedded as simple lists (SeeAlso recommender services, for instance related documents and related publications), and other JSON response formats can be mapped to suggestions format.</p>
<h2 id="availability-with-ng-daia">Availability with ng-daia</h2>
<p>The <a href="http://purl.org/NET/DAIA">DAIA specification</a> defines a data model and an HTTP API for accessing information about the current availability of documents <span class="citation" data-cites="DAIA">(Voß and Reh 2014)</span>. In contrast to complex internal library system APIs, such as NCIP and SLNP, DAIA was designed to be used openly. The aim of DAIA is to provide a way for libraries to allow open and easy-to-use access to holdings information from their catalogs. This, in turn, enables the inclusion of document availability information in external applications and websites (catalogs, reference management, e-learning platforms, etc.). Among other formats, DAIA provides availability information in JSON, the first choice for web applications written in JavaScript.</p>
<p>The AngularJS module <em>ng-daia</em> implements client code to execute and process a DAIA query and to display holding information in convenient form. Below is an example of the HTML integration:</p>
<pre class="sourceCode html"><code class="sourceCode html"><span class="kw"><html</span><span class="ot"> ng-app=</span><span class="st">"myApp"</span><span class="kw">></span>
<span class="kw"><head></span>
<span class="kw"><script</span><span class="ot"> src=</span><span class="st">"angular.min.js"</span><span class="kw">></script></span>
<span class="kw"><script</span><span class="ot"> src=</span><span class="st">"ng-daia.min.js"</span><span class="kw">></script></span>
<span class="kw"><script></span><span class="ot">angular</span>.<span class="fu">module</span>(<span class="st">'myApp'</span>, [<span class="st">'ngDAIA'</span>]);<<span class="ot">/script></span>
<span class="ot"> <link href="ng-daia.css" rel="stylesheet" /</span>>
<<span class="ot">/head></span>
<span class="ot"> <body></span>
<span class="ot"> <div daia-api="http://daia.gbv.de/</span><span class="st">" </span>
daia-id=<span class="st">"opac-de-ma9:ppn:685460711"</span>>
<<span class="ot">/div></span>
<span class="ot"> </body</span>>
<<span class="ot">/html></span></code></pre>
<p>The <em>ng-daia</em> module provides a directive (<code>daia-api</code>) to query a DAIA service with a given document identifier (<code>daia-id</code>). The recieved DAIA response is then fed to a customizable AngularJS template, resulting in the following display:</p>
<figure>
<img src="ngdaia_full.png" alt="Full availability view with ng-daia default template" /><figcaption>Full availability view with ng-daia default template</figcaption>
</figure>
<p>The full availability view as implemented in the default templates of <em>ng-daia</em> reflects the nested structure of DAIA data model, consisting of an outer layer for institutional and general document information, and specific information for each document holding <span class="citation" data-cites="DAIA">(Voß and Reh 2014)</span>. The default template of directive <code>ng-api</code> uses another directive for the display of a holding item (<code>daia-item</code>) and its item template can be customized as well. Another directive is provided for most compact display (<code>daia-simple</code>, see figure 5). DAIA Simple is a flattened, aggregated form of availability information that covers typical use cases, such as short display in a result list (see section 6.1 of the <a href="http://purl.org/NET/DAIA">DAIA specification</a>). The <em>ng-daia</em> module includes functions to transform from full DAIA to DAIA simple as well.</p>
<figure>
<img src="ngdaia_simple.png" alt="Minimal availability view with daia-simple" /><figcaption>Minimal availability view with daia-simple</figcaption>
</figure>
<p>All templates included in <em>ng-daia</em> can be customized with CSS. Localization for display in other languages is already supported with the popular module <a href="https://angular-translate.github.io/">angular-translate</a> <span class="citation" data-cites="angular-translate">(Precht 2014)</span>. Thanks to two-way binding of AngularJS variables, a simple statement such as <code>$scope.language = 'de'</code> can be enough to update the full availability display in another language.</p>
<h1 id="conclusions">Conclusions</h1>
<p>Despite efforts to open up library systems via standard APIs, for instance the ILS-DI recommendations <span class="citation" data-cites="ilsdi">(ILS Discovery Interface Task Force 2008)</span>, the support of library services via open APIs is rather low. If APIs exist (e.g. NCIP), they are often complex, vendor-specific, or available only for internal use. One reason for the lack of open APIs may be the invisibility of benefits and usage examples. The examples given in this article demonstrate how library services (e.g. search suggestions, recommendations, document availability) can be used easily once they have been made available via standardized APIs (e.g. Open Search Suggestions and DAIA).</p>
<p>The simple integration into web applications also requires client modules like <em>ng-suggest</em> and <em>ng-daia</em> for AngularJS. Modules for other standard APIs relevant to libraries, such as OpenSearch and SRU for search <span class="citation" data-cites="Hammond2010">(Hammond 2010)</span> and PAIA for patron account interaction <span class="citation" data-cites="PAIA">(Voß 2014)</span>, shouldn’t be hard to implement.<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> Most importantly, these client modules only have to be implemented once instead of having to build both server and client implementation for each particular library system. With a set of AngularJS modules for the basic library services (search, availability, patron account) it should even be possible to create a custom OPAC interface in less than a hundred lines of HTML and JavaScript.</p>
<p>Even if AngularJS is not the framework of your choice, it makes sense to provide client modules to your APIs, as illustrated in figure 1. Libraries should not only expose their services via openly specified APIs but also provide client libraries to facilitate the integration of these services into web applications. To minimize the work of doing so, one should build on standardized APIs independent from particular library systems. We hope to motivate more library developers in doing so.<a href="#fn4" class="footnoteRef" id="fnref4"><sup>4</sup></a></p>
<div class="references">
<h1>References</h1>
<p>Breeding M. 2009. Opening up Library Systems through Web Services and SOA: Hype or Reality? American Library Association.</p>
<p>Clinton D. 2006. OpenSearch Suggestions. Available from: <a href="http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions">http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions</a></p>
<p>Hammond T. 2010. nature.com OpenSearch: A Case Study in OpenSearch and SRU Integration. D-Lib Magazine [Internet] 16. Available from: <a href="http://dlib.org/dlib/july10/hammond/07hammond.html">http://dlib.org/dlib/july10/hammond/07hammond.html</a></p>
<p>Hoskins J ed. 2014. AngularJS Modules. [Internet]. Available from: <a href="http://ngmodules.org/">http://ngmodules.org/</a></p>
<p>ILS Discovery Interface Task Force ed. 2008. Technical Recommendation. Digital Library Federation. Available from: <a href="http://old.diglib.org/architectures/ilsdi/">http://old.diglib.org/architectures/ilsdi/</a></p>
<p>Nagaya S, Hayashi Y, Otani S, Itabashi K. 2011. Controlled Terms or Free Terms? A JavaScript Library to Utilize Subject Headings and Thesauri on the Web. code4lib journal [Internet]. Available from: <a href="http://journal.code4lib.org/articles/5994">http://journal.code4lib.org/articles/5994</a></p>
<p>Precht P. 2014. angular translate. [Internet]. Available from: <a href="http://angular-translate.github.io/">http://angular-translate.github.io/</a></p>
<p>Voß J, Horn M. 2014a. ng-suggest. [Internet]. Available from: <a href="http://gbv.github.io/ng-suggest/">http://gbv.github.io/ng-suggest/</a></p>
<p>Voß J, Horn M. 2014b. ng-daia. [Internet]. Available from: <a href="http://gbv.github.io/ng-daia/">http://gbv.github.io/ng-daia/</a></p>
<p>Voß J, Reh U. 2014. Document Availability Information API (DAIA). Available from: <a href="http://purl.org/NET/DAIA">http://purl.org/NET/DAIA</a></p>
<p>Voß J. 2008. SeeAlso: A Simple Linkserver Protocol. Ariadne [Internet]. Available from: <a href="http://www.ariadne.ac.uk/issue57/voss/">http://www.ariadne.ac.uk/issue57/voss/</a></p>
<p>Voß J. 2014. Patrons Account Information API (PAIA). Available from: <a href="http://gbv.github.com/paia/">http://gbv.github.com/paia/</a></p>
</div>
<section class="footnotes">
<h1>Endnotes</h1>
<ol>
<li id="fn1"><p>This article is based on the assumption that libraries actually want to facilitate the use of their servics. In some cases this assumption might be wrong.<a href="#fnref1">↩</a></p></li>
<li id="fn2"><p>All examples are available also as part of the article’s code repository at <a href="https://github.com/jakobib/angularjs2014/">https://github.com/jakobib/angularjs2014/</a>.<a href="#fnref2">↩</a></p></li>
<li id="fn3"><p>We are currently working on the module <em>ng-skos</em> (<a href="https://github.com/gbv/ng-skos">https://github.com/gbv/ng-skos</a>) to interact with authority files and simple knowledge organisation systems.<a href="#fnref3">↩</a></p></li>
<li id="fn4"><p>One can also ask the vendor of library systems to implement standardized APIs to the core functionality of its product, but this requires some pressure by libraries as customers.<a href="#fnref4">↩</a></p></li>
</ol>
</section>
<h1>About the Authors</h1>
<p><em>Jakob Voß</em> works in research and development at the head office of the Common Library Network (Gemeinsamer Bibliotheksverbund, GBV) in Göttingen.</p>
<p><em>Moritz Horn</em> studies information management at the University of Applied Sciences and Arts in Hanover.</p>
</body>
</html>