1 /* ---------------------------------------------------------------------------
2 * Copyright (C) 2009 Equinox Software, Inc.
3 * Mike Rylander <miker@esilibrary.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * ---------------------------------------------------------------------------
17 if(!dojo._hasResource["openils.BibTemplate"]) {
19 dojo.require('DojoSRF');
20 dojo.require('dojox.xml.parser');
21 dojo.require('dojo.string');
22 dojo._hasResource["openils.BibTemplate"] = true;
23 dojo.provide("openils.BibTemplate");
24 dojo.declare('openils.BibTemplate', null, {
26 constructor : function(kwargs) {
27 this.root = kwargs.root;
28 this.subObjectLimit = kwargs.subObjectLimit;
29 this.subObjectOffset = kwargs.subObjectOffset;
30 this.tagURI = kwargs.tagURI;
31 this.xml = kwargs.xml;
32 this.record = kwargs.record;
33 this.org_unit = kwargs.org_unit || '-';
34 this.depth = kwargs.depth;
35 this.sync = kwargs.sync == true;
36 this.locale = kwargs.locale || OpenSRF.locale || 'en-US';
37 this.nodelay = kwargs.delay == false;
39 if (this.xml && this.xml instanceof String)
40 this.xml = dojox.xml.parser.parse(this.xml);
42 this.mode = 'biblio-record_entry';
43 this.default_datatype = 'marcxml-uris';
44 if (kwargs.metarecord) {
45 this.record = kwargs.metarecord;
46 this.mode = 'metabib-metarecord';
47 this.default_datatype = 'mods';
50 if (this.nodelay) this.render();
53 subsetNL : function (old_nl, start, end) {
54 var new_nl = new dojo.NodeList();
55 for (var i = start; i < end && i < old_nl.length; i++) {
56 new_nl.push(old_nl[i]);
61 textContent : function (node) {
63 if (node instanceof HTMLElement) return node.innerText || node.textContent;
64 return dojox.xml.parser.textContent(node);
71 var all_slots = dojo.query('*[type^="opac/slot-data"]', this.root);
72 var default_datatype = this.default_datatype;
75 dojo.forEach(all_slots, function(s){
76 // marcxml-uris does not include copies, which avoids timeouts
77 // with bib records that have hundreds or thousands of copies
78 var current_datatype = default_datatype;
80 if (s.getAttribute('datatype')) {
81 current_datatype = s.getAttribute('datatype');
82 } else if (s.getAttribute('type').indexOf('+') > -1) {
83 current_datatype = s.getAttribute('type').split('+').reverse()[0];
86 if (!slots[current_datatype]) slots[current_datatype] = [];
87 slots[current_datatype].push(s);
91 for (var datatype in slots) {
94 var BT = args.renderer;
95 var process_record = function (bib) {
96 dojo.forEach(args.slot_list, function (slot) {
97 var debug = slot.getAttribute('debug') == 'true';
100 var joiner = slot.getAttribute('join') || ' ';
101 var item_limit = parseInt(slot.getAttribute('limit'));
102 var item_offset = parseInt(slot.getAttribute('offset')) || 0;
104 var pre_render_callbacks = dojo.query( '*[type="opac/call-back+pre-render"]', slot );
105 var post_render_callbacks = dojo.query( '*[type="opac/call-back+post-render"]', slot );
106 var pre_query_callbacks = dojo.query( '*[type="opac/call-back+pre-query"]', slot );
107 var post_query_callbacks = dojo.query( '*[type="opac/call-back+post-query"]', slot );
109 // Do pre-query stuff
110 dojo.forEach(pre_query_callbacks, function (cb) {
111 try { (new Function( 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(BT,bib,slot) } catch (e) {/*meh*/}
114 var item_list = dojo.query(
115 slot.getAttribute('query'),
120 if (debug) alert('BibTemplate debug -- item list limit/offset requested: ' + item_limit + '/' + item_offset);
121 if (item_list.length) item_list = BT.subsetNL(item_list, item_offset, item_offset + item_limit);
124 // Do post-query stuff
125 dojo.forEach(post_query_callbacks, function (cb) {
126 try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
129 if (!item_list.length) return;
131 // Do pre-render stuff
132 dojo.forEach(pre_render_callbacks, function (cb) {
133 try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
136 var templated = slot.getAttribute('templated') == 'true';
137 if (debug) alert('BibTemplate debug -- slot ' + (templated ? 'is' : 'is not') + ' templated');
139 if (debug) alert('BibTemplate debug -- slot template innerHTML:\n' + slot.innerHTML);
140 var template_values = {};
141 var template_value_count = 0;
144 '*[type="opac/template-value"]',
146 ).orphan().forEach(function(x) {
147 var name = x.getAttribute('name');
148 var value = (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(x.innerHTML) ))(item_list,BT,bib,slot);
149 if (name && (value || value == '')) {
150 template_values[name] = value;
151 template_value_count++;
155 if (debug) alert('BibTemplate debug -- template values:\n' + dojo.toJson( template_values ));
156 if (template_value_count > 0) slot.innerHTML = dojo.string.substitute( unescape(slot.innerHTML), template_values );
159 var handler_node = dojo.query( '*[type="opac/slot-format"]', slot )[0];
160 if (handler_node) slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item', dojox.xml.parser.textContent(handler_node) || handler_node.innerHTML);
161 else slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item','return dojox.xml.parser.textContent(item) || item.innerHTML;');
163 if (item_list.length) {
164 var content = dojo.map(item_list, dojo.partial(slot_handler,item_list,BT,bib,slot)).join(joiner);
166 if (handler_node) handler_node.parentNode.replaceChild( dojo.doc.createTextNode( content ), handler_node );
168 slot.innerHTML = content;
172 delete(slot_handler);
174 // Do post-render stuff
175 dojo.forEach(post_render_callbacks, function (cb) {
176 try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
181 alert('BibTemplate Error: ' + e + '\n' + dojo.toJson(e));
189 process_record(BT.xml);
195 uri = 'tag:evergreen-opac:' + BT.mode + '/' + BT.record;
196 if (BT.subObjectLimit) {
197 uri += '[' + BT.subObjectLimit;
198 if (BT.subObjectOffset)
199 uri += ',' + BT.subObjectOffset;
202 uri += '/' + BT.org_unit;
203 if (BT.depth || BT.depth == '0') uri += '/' + BT.depth;
207 url: '/opac/extras/unapi?id=' + uri + '&format=' + args.dtype + '&locale=' + BT.locale,
215 })({ slot_list : slots[datatype].reverse(), dtype : datatype, renderer : this });
224 dojo._hasResource["openils.FeedTemplate"] = true;
225 dojo.provide("openils.FeedTemplate");
226 dojo.declare('openils.FeedTemplate', null, {
228 constructor : function(kwargs) {
229 this.place = kwargs.place;
230 this.root = kwargs.root;
231 this.xml = kwargs.xml;
232 this.feed_uri = kwargs.uri;
233 this.item_query = kwargs.query;
234 this.sync = kwargs.sync == true;
235 this.preventCache = kwargs.preventCache == true;
236 this.nodelay = kwargs.delay == false;
237 this.reverseSort = kwargs.reverseSort == true;
238 this.relativePosition = 'last';
239 if (this.reverseSort) this.relativePosition = 'first';
241 if (this.nodelay) this.render();
244 render : function () {
246 var process_feed = function (xmldoc) {
247 dojo.query( me.item_query, xmldoc ).forEach(
249 var template = me.root.cloneNode(true);
250 dojo.place( template, me.place, me.relativePosition );
251 new openils.BibTemplate({ delay : false, xml : item, root : template });
257 process_feed(this.xml);
263 preventCache: me.preventCache,