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) {
64 if(window.ActiveXObject) content = node.text;
65 else content = node.textContent;
72 var all_slots = dojo.query('*[type^="opac/slot-data"]', this.root);
73 var default_datatype = this.default_datatype;
76 dojo.forEach(all_slots, function(s){
77 // marcxml-uris does not include copies, which avoids timeouts
78 // with bib records that have hundreds or thousands of copies
79 var current_datatype = default_datatype;
81 if (s.getAttribute('datatype')) {
82 current_datatype = s.getAttribute('datatype');
83 } else if (s.getAttribute('type').indexOf('+') > -1) {
84 current_datatype = s.getAttribute('type').split('+').reverse()[0];
87 if (!slots[current_datatype]) slots[current_datatype] = [];
88 slots[current_datatype].push(s);
92 for (var datatype in slots) {
95 var BT = args.renderer;
96 var process_record = function (bib) {
97 dojo.forEach(args.slot_list, function (slot) {
98 var debug = slot.getAttribute('debug') == 'true';
101 var joiner = slot.getAttribute('join') || ' ';
102 var item_limit = parseInt(slot.getAttribute('limit'));
103 var item_offset = parseInt(slot.getAttribute('offset')) || 0;
105 var pre_render_callbacks = dojo.query( '*[type="opac/call-back+pre-render"]', slot );
106 var post_render_callbacks = dojo.query( '*[type="opac/call-back+post-render"]', slot );
107 var pre_query_callbacks = dojo.query( '*[type="opac/call-back+pre-query"]', slot );
108 var post_query_callbacks = dojo.query( '*[type="opac/call-back+post-query"]', slot );
110 // Do pre-query stuff
111 dojo.forEach(pre_query_callbacks, function (cb) {
112 try { (new Function( 'BT', 'slotXML', 'slot', decodeURIComponent(cb.innerHTML) ))(BT,bib,slot) } catch (e) {/*meh*/}
115 var query = slot.getAttribute('query');
116 var xml_root = bib.documentElement || bib;
118 // Opera (as of 11.01) fails with quotes in queries
119 if (dojo.isOpera) query = query.replace(/"|'/g, '');
121 var item_list = dojo.query(
123 xml_root // Make Opera work by querying from the root element
127 if (debug) alert('BibTemplate debug -- item list limit/offset requested: ' + item_limit + '/' + item_offset);
128 if (item_list.length) item_list = BT.subsetNL(item_list, item_offset, item_offset + item_limit);
131 // Do post-query stuff
132 dojo.forEach(post_query_callbacks, function (cb) {
133 try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', decodeURIComponent(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
136 if (!item_list.length) return;
138 // Do pre-render stuff
139 dojo.forEach(pre_render_callbacks, function (cb) {
140 try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', decodeURIComponent(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
143 var templated = slot.getAttribute('templated') == 'true';
144 if (debug) alert('BibTemplate debug -- slot ' + (templated ? 'is' : 'is not') + ' templated');
146 if (debug) alert('BibTemplate debug -- slot template innerHTML:\n' + slot.innerHTML);
147 var template_values = {};
148 var template_value_count = 0;
151 '*[type="opac/template-value"]',
153 ).orphan().forEach(function(x) {
154 var name = x.getAttribute('name');
155 var value = (new Function( 'item_list', 'BT', 'slotXML', 'slot', decodeURIComponent(x.innerHTML) ))(item_list,BT,bib,slot);
156 if (name && (value || value == '')) {
157 template_values[name] = value;
158 template_value_count++;
162 if (debug) alert('BibTemplate debug -- template values:\n' + dojo.toJson( template_values ));
163 if (template_value_count > 0) {
166 dojo.string.substitute(
167 decodeURIComponent(slot.innerHTML),
174 var handler_node = dojo.query( '*[type="opac/slot-format"]', slot )[0];
175 if (handler_node) slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item', dojox.xml.parser.textContent(handler_node) || handler_node.innerHTML);
176 else slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item','return dojox.xml.parser.textContent(item) || item.innerHTML;');
178 if (item_list.length) {
179 var content = dojo.map(item_list, dojo.partial(slot_handler,item_list,BT,bib,slot)).join(joiner);
181 if (handler_node) handler_node.parentNode.replaceChild( dojo.doc.createTextNode( content ), handler_node );
183 dojo.attr(slot, "innerHTML", content);
187 delete(slot_handler);
189 // Do post-render stuff
190 dojo.forEach(post_render_callbacks, function (cb) {
191 try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', decodeURIComponent(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
196 alert('BibTemplate Error: ' + e + '\n' + dojo.toJson(e));
204 process_record(BT.xml);
210 uri = 'tag:evergreen-opac:' + BT.mode + '/' + BT.record;
211 if (BT.subObjectLimit) {
212 uri += '[' + BT.subObjectLimit;
213 if (BT.subObjectOffset)
214 uri += ',' + BT.subObjectOffset;
217 uri += '/' + BT.org_unit;
218 if (BT.depth || BT.depth == '0') uri += '/' + BT.depth;
222 url: '/opac/extras/unapi?id=' + uri + '&format=' + args.dtype + '&locale=' + BT.locale,
230 })({ slot_list : slots[datatype].reverse(), dtype : datatype, renderer : this });
239 dojo._hasResource["openils.FeedTemplate"] = true;
240 dojo.provide("openils.FeedTemplate");
241 dojo.declare('openils.FeedTemplate', null, {
243 constructor : function(kwargs) {
244 this.place = kwargs.place;
245 this.empty = kwargs.empty;
246 this.root = kwargs.root;
247 this.xml = kwargs.xml;
248 this.feed_uri = kwargs.uri;
249 this.item_query = kwargs.query;
250 this.sync = kwargs.sync == true;
251 this.preventCache = kwargs.preventCache == true;
252 this.nodelay = kwargs.delay == false;
253 this.reverseSort = kwargs.reverseSort == true;
254 this.relativePosition = 'last';
255 if (this.reverseSort) this.relativePosition = 'first';
257 this.horizon = new Date().getTime();
258 var horiz = parseInt(this.root.getAttribute('horizon'));
260 if (isNaN(horiz) || this.horizon >= horiz)
261 this.root.setAttribute('horizon', this.horizon);
263 if (this.nodelay) this.render();
266 render : function () {
269 var process_feed = function (xmldoc) {
270 if (parseInt(me.horizon) >= parseInt(me.root.getAttribute('horizon'))) {
271 if (me.empty == true) dojo.empty(me.place);
272 me.root.setAttribute('horizon', this.horizon);
273 dojo.query( me.item_query, xmldoc ).forEach(
275 var template = me.root.cloneNode(true);
276 dojo.place( template, me.place, me.relativePosition );
277 new openils.BibTemplate({ delay : false, xml : item, root : template });
284 process_feed(this.xml);
290 preventCache: me.preventCache,