Line 0
Link Here
|
|
|
1 |
/* |
2 |
* pz2.js - pazpar2's javascript client library. |
3 |
* Copyright (C) 2006-2013 Index Data. |
4 |
* |
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. |
9 |
* |
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 |
* |
15 |
* You should have received a copy of the GNU General Public License |
16 |
* along with this program; if not, write to the Free Software |
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 |
*/ |
19 |
|
20 |
//since explorer is flawed |
21 |
if (!window['Node']) { |
22 |
window.Node = new Object(); |
23 |
Node.ELEMENT_NODE = 1; |
24 |
Node.ATTRIBUTE_NODE = 2; |
25 |
Node.TEXT_NODE = 3; |
26 |
Node.CDATA_SECTION_NODE = 4; |
27 |
Node.ENTITY_REFERENCE_NODE = 5; |
28 |
Node.ENTITY_NODE = 6; |
29 |
Node.PROCESSING_INSTRUCTION_NODE = 7; |
30 |
Node.COMMENT_NODE = 8; |
31 |
Node.DOCUMENT_NODE = 9; |
32 |
Node.DOCUMENT_TYPE_NODE = 10; |
33 |
Node.DOCUMENT_FRAGMENT_NODE = 11; |
34 |
Node.NOTATION_NODE = 12; |
35 |
} |
36 |
|
37 |
// prevent execution of more than once |
38 |
if(typeof window.pz2 == "undefined") { |
39 |
window.undefined = window.undefined; |
40 |
|
41 |
var pz2 = function ( paramArray ) |
42 |
{ |
43 |
|
44 |
// at least one callback required |
45 |
if ( !paramArray ) |
46 |
throw new Error("Pz2.js: Array with parameters has to be supplied."); |
47 |
|
48 |
//supported pazpar2's protocol version |
49 |
this.suppProtoVer = '1'; |
50 |
if (typeof paramArray.pazpar2path != "undefined") |
51 |
this.pz2String = paramArray.pazpar2path; |
52 |
else |
53 |
this.pz2String = "/pazpar2/search.pz2"; |
54 |
this.useSessions = true; |
55 |
|
56 |
this.stylesheet = paramArray.detailstylesheet || null; |
57 |
//load stylesheet if required in async mode |
58 |
if( this.stylesheet ) { |
59 |
var context = this; |
60 |
var request = new pzHttpRequest( this.stylesheet ); |
61 |
request.get( {}, function ( doc ) { context.xslDoc = doc; } ); |
62 |
} |
63 |
|
64 |
this.errorHandler = paramArray.errorhandler || null; |
65 |
this.showResponseType = paramArray.showResponseType || "xml"; |
66 |
|
67 |
// function callbacks |
68 |
this.initCallback = paramArray.oninit || null; |
69 |
this.statCallback = paramArray.onstat || null; |
70 |
this.showCallback = paramArray.onshow || null; |
71 |
this.termlistCallback = paramArray.onterm || null; |
72 |
this.recordCallback = paramArray.onrecord || null; |
73 |
this.bytargetCallback = paramArray.onbytarget || null; |
74 |
this.resetCallback = paramArray.onreset || null; |
75 |
|
76 |
// termlist keys |
77 |
this.termKeys = paramArray.termlist || "subject"; |
78 |
|
79 |
// some configurational stuff |
80 |
this.keepAlive = 50000; |
81 |
|
82 |
if ( paramArray.keepAlive < this.keepAlive ) |
83 |
this.keepAlive = paramArray.keepAlive; |
84 |
|
85 |
this.sessionID = paramArray.sessionId || null; |
86 |
this.serviceId = paramArray.serviceId || null; |
87 |
this.initStatusOK = false; |
88 |
this.pingStatusOK = false; |
89 |
this.searchStatusOK = false; |
90 |
|
91 |
// for sorting |
92 |
this.currentSort = "relevance"; |
93 |
|
94 |
// where are we? |
95 |
this.currentStart = 0; |
96 |
// currentNum can be overwritten in show |
97 |
this.currentNum = 20; |
98 |
|
99 |
// last full record retrieved |
100 |
this.currRecID = null; |
101 |
|
102 |
// current query |
103 |
this.currQuery = null; |
104 |
|
105 |
//current raw record offset |
106 |
this.currRecOffset = null; |
107 |
|
108 |
//timers |
109 |
this.pingTimer = null; |
110 |
this.statTime = paramArray.stattime || 1000; |
111 |
this.statTimer = null; |
112 |
this.termTime = paramArray.termtime || 1000; |
113 |
this.termTimer = null; |
114 |
this.showTime = paramArray.showtime || 1000; |
115 |
this.showTimer = null; |
116 |
this.showFastCount = 4; |
117 |
this.bytargetTime = paramArray.bytargettime || 1000; |
118 |
this.bytargetTimer = null; |
119 |
this.recordTime = paramArray.recordtime || 500; |
120 |
this.recordTimer = null; |
121 |
|
122 |
// counters for each command and applied delay |
123 |
this.dumpFactor = 500; |
124 |
this.showCounter = 0; |
125 |
this.termCounter = 0; |
126 |
this.statCounter = 0; |
127 |
this.bytargetCounter = 0; |
128 |
this.recordCounter = 0; |
129 |
|
130 |
// active clients, updated by stat and show |
131 |
// might be an issue since bytarget will poll accordingly |
132 |
this.activeClients = 1; |
133 |
|
134 |
// if in proxy mode no need to init |
135 |
if (paramArray.usesessions != undefined) { |
136 |
this.useSessions = paramArray.usesessions; |
137 |
this.initStatusOK = true; |
138 |
} |
139 |
// else, auto init session or wait for a user init? |
140 |
if (this.useSessions && paramArray.autoInit !== false) { |
141 |
this.init(this.sessionID, this.serviceId); |
142 |
} |
143 |
// Version parameter |
144 |
this.version = paramArray.version || null; |
145 |
}; |
146 |
|
147 |
pz2.prototype = |
148 |
{ |
149 |
//error handler for async error throws |
150 |
throwError: function (errMsg, errCode) |
151 |
{ |
152 |
var err = new Error(errMsg); |
153 |
if (errCode) err.code = errCode; |
154 |
|
155 |
if (this.errorHandler) { |
156 |
this.errorHandler(err); |
157 |
} |
158 |
else { |
159 |
throw err; |
160 |
} |
161 |
}, |
162 |
|
163 |
// stop activity by clearing tiemouts |
164 |
stop: function () |
165 |
{ |
166 |
clearTimeout(this.statTimer); |
167 |
clearTimeout(this.showTimer); |
168 |
clearTimeout(this.termTimer); |
169 |
clearTimeout(this.bytargetTimer); |
170 |
}, |
171 |
|
172 |
// reset status variables |
173 |
reset: function () |
174 |
{ |
175 |
if ( this.useSessions ) { |
176 |
this.sessionID = null; |
177 |
this.initStatusOK = false; |
178 |
this.pingStatusOK = false; |
179 |
clearTimeout(this.pingTimer); |
180 |
} |
181 |
this.searchStatusOK = false; |
182 |
this.stop(); |
183 |
|
184 |
if ( this.resetCallback ) |
185 |
this.resetCallback(); |
186 |
}, |
187 |
|
188 |
init: function (sessionId, serviceId) |
189 |
{ |
190 |
this.reset(); |
191 |
|
192 |
// session id as a param |
193 |
if (sessionId && this.useSessions ) { |
194 |
this.initStatusOK = true; |
195 |
this.sessionID = sessionId; |
196 |
this.ping(); |
197 |
// old school direct pazpar2 init |
198 |
} else if (this.useSessions) { |
199 |
var context = this; |
200 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
201 |
var opts = {'command' : 'init'}; |
202 |
if (serviceId) opts.service = serviceId; |
203 |
request.safeGet( |
204 |
opts, |
205 |
function(data) { |
206 |
if ( data.getElementsByTagName("status")[0] |
207 |
.childNodes[0].nodeValue == "OK" ) { |
208 |
if ( data.getElementsByTagName("protocol")[0] |
209 |
.childNodes[0].nodeValue |
210 |
!= context.suppProtoVer ) |
211 |
throw new Error( |
212 |
"Server's protocol not supported by the client" |
213 |
); |
214 |
context.initStatusOK = true; |
215 |
context.sessionID = |
216 |
data.getElementsByTagName("session")[0] |
217 |
.childNodes[0].nodeValue; |
218 |
if (data.getElementsByTagName("keepAlive").length > 0) { |
219 |
context.keepAlive = data.getElementsByTagName("keepAlive")[0].childNodes[0].nodeValue; |
220 |
} |
221 |
context.pingTimer = |
222 |
setTimeout( |
223 |
function () { |
224 |
context.ping(); |
225 |
}, |
226 |
context.keepAlive |
227 |
); |
228 |
if ( context.initCallback ) |
229 |
context.initCallback(); |
230 |
} |
231 |
else |
232 |
context.throwError('Init failed. Malformed WS resonse.', |
233 |
110); |
234 |
} |
235 |
); |
236 |
// when through proxy no need to init |
237 |
} else { |
238 |
this.initStatusOK = true; |
239 |
} |
240 |
}, |
241 |
// no need to ping explicitly |
242 |
ping: function () |
243 |
{ |
244 |
// pinging only makes sense when using pazpar2 directly |
245 |
if( !this.initStatusOK || !this.useSessions ) |
246 |
throw new Error( |
247 |
'Pz2.js: Ping not allowed (proxy mode) or session not initialized.' |
248 |
); |
249 |
var context = this; |
250 |
|
251 |
clearTimeout(context.pingTimer); |
252 |
|
253 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
254 |
request.safeGet( |
255 |
{ "command": "ping", "session": this.sessionID, "windowid" : window.name }, |
256 |
function(data) { |
257 |
if ( data.getElementsByTagName("status")[0] |
258 |
.childNodes[0].nodeValue == "OK" ) { |
259 |
context.pingStatusOK = true; |
260 |
context.pingTimer = |
261 |
setTimeout( |
262 |
function () { |
263 |
context.ping(); |
264 |
}, |
265 |
context.keepAlive |
266 |
); |
267 |
} |
268 |
else |
269 |
context.throwError('Ping failed. Malformed WS resonse.', |
270 |
111); |
271 |
} |
272 |
); |
273 |
}, |
274 |
search: function (query, num, sort, filter, showfrom, addParamsArr) |
275 |
{ |
276 |
clearTimeout(this.statTimer); |
277 |
clearTimeout(this.showTimer); |
278 |
clearTimeout(this.termTimer); |
279 |
clearTimeout(this.bytargetTimer); |
280 |
|
281 |
this.showCounter = 0; |
282 |
this.termCounter = 0; |
283 |
this.bytargetCounter = 0; |
284 |
this.statCounter = 0; |
285 |
this.activeClients = 1; |
286 |
|
287 |
// no proxy mode |
288 |
if( !this.initStatusOK ) |
289 |
throw new Error('Pz2.js: session not initialized.'); |
290 |
|
291 |
if( query !== undefined ) |
292 |
this.currQuery = query; |
293 |
else |
294 |
throw new Error("Pz2.js: no query supplied to the search command."); |
295 |
|
296 |
if ( showfrom !== undefined ) |
297 |
var start = showfrom; |
298 |
else |
299 |
var start = 0; |
300 |
|
301 |
var searchParams = { |
302 |
"command": "search", |
303 |
"query": this.currQuery, |
304 |
"session": this.sessionID, |
305 |
"windowid" : window.name |
306 |
}; |
307 |
|
308 |
if( sort !== undefined ) { |
309 |
this.currentSort = sort; |
310 |
searchParams["sort"] = sort; |
311 |
} |
312 |
if (filter !== undefined) |
313 |
searchParams["filter"] = filter; |
314 |
|
315 |
// copy additional parmeters, do not overwrite |
316 |
if (addParamsArr != undefined) { |
317 |
for (var prop in addParamsArr) { |
318 |
if (!searchParams.hasOwnProperty(prop)) |
319 |
searchParams[prop] = addParamsArr[prop]; |
320 |
} |
321 |
} |
322 |
|
323 |
var context = this; |
324 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
325 |
request.safeGet( |
326 |
searchParams, |
327 |
function(data) { |
328 |
if ( data.getElementsByTagName("status")[0] |
329 |
.childNodes[0].nodeValue == "OK" ) { |
330 |
context.searchStatusOK = true; |
331 |
//piggyback search |
332 |
context.show(start, num, sort); |
333 |
if (context.statCallback) |
334 |
context.stat(); |
335 |
if (context.termlistCallback) |
336 |
context.termlist(); |
337 |
if (context.bytargetCallback) |
338 |
context.bytarget(); |
339 |
} |
340 |
else |
341 |
context.throwError('Search failed. Malformed WS resonse.', |
342 |
112); |
343 |
} |
344 |
); |
345 |
}, |
346 |
stat: function() |
347 |
{ |
348 |
if( !this.initStatusOK ) |
349 |
throw new Error('Pz2.js: session not initialized.'); |
350 |
|
351 |
// if called explicitly takes precedence |
352 |
clearTimeout(this.statTimer); |
353 |
|
354 |
var context = this; |
355 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
356 |
request.safeGet( |
357 |
{ "command": "stat", "session": this.sessionID, "windowid" : window.name }, |
358 |
function(data) { |
359 |
if ( data.getElementsByTagName("stat") ) { |
360 |
var activeClients = |
361 |
Number( data.getElementsByTagName("activeclients")[0] |
362 |
.childNodes[0].nodeValue ); |
363 |
context.activeClients = activeClients; |
364 |
|
365 |
var stat = Element_parseChildNodes(data.documentElement); |
366 |
|
367 |
context.statCounter++; |
368 |
var delay = context.statTime |
369 |
+ context.statCounter * context.dumpFactor; |
370 |
|
371 |
if ( activeClients > 0 ) |
372 |
context.statTimer = |
373 |
setTimeout( |
374 |
function () { |
375 |
context.stat(); |
376 |
}, |
377 |
delay |
378 |
); |
379 |
context.statCallback(stat); |
380 |
} |
381 |
else |
382 |
context.throwError('Stat failed. Malformed WS resonse.', |
383 |
113); |
384 |
} |
385 |
); |
386 |
}, |
387 |
show: function(start, num, sort, query_state) |
388 |
{ |
389 |
if( !this.searchStatusOK && this.useSessions ) |
390 |
throw new Error( |
391 |
'Pz2.js: show command has to be preceded with a search command.' |
392 |
); |
393 |
|
394 |
// if called explicitly takes precedence |
395 |
clearTimeout(this.showTimer); |
396 |
|
397 |
if( sort !== undefined ) |
398 |
this.currentSort = sort; |
399 |
if( start !== undefined ) |
400 |
this.currentStart = Number( start ); |
401 |
if( num !== undefined ) |
402 |
this.currentNum = Number( num ); |
403 |
|
404 |
var context = this; |
405 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
406 |
var requestParameters = |
407 |
{ |
408 |
"command": "show", |
409 |
"session": this.sessionID, |
410 |
"start": this.currentStart, |
411 |
"num": this.currentNum, |
412 |
"sort": this.currentSort, |
413 |
"block": 1, |
414 |
"type": this.showResponseType, |
415 |
"windowid" : window.name |
416 |
}; |
417 |
if (query_state) |
418 |
requestParameters["query-state"] = query_state; |
419 |
if (this.version && this.version > 0) |
420 |
requestParameters["version"] = this.version; |
421 |
request.safeGet( |
422 |
requestParameters, |
423 |
function(data, type) { |
424 |
var show = null; |
425 |
var activeClients = 0; |
426 |
if (type === "json") { |
427 |
show = {}; |
428 |
activeClients = Number(data.activeclients[0]); |
429 |
show.activeclients = activeClients; |
430 |
show.merged = Number(data.merged[0]); |
431 |
show.total = Number(data.total[0]); |
432 |
show.start = Number(data.start[0]); |
433 |
show.num = Number(data.num[0]); |
434 |
show.hits = data.hit; |
435 |
} else if (data.getElementsByTagName("status")[0] |
436 |
.childNodes[0].nodeValue == "OK") { |
437 |
// first parse the status data send along with records |
438 |
// this is strictly bound to the format |
439 |
activeClients = |
440 |
Number(data.getElementsByTagName("activeclients")[0] |
441 |
.childNodes[0].nodeValue); |
442 |
show = { |
443 |
"activeclients": activeClients, |
444 |
"merged": |
445 |
Number( data.getElementsByTagName("merged")[0] |
446 |
.childNodes[0].nodeValue ), |
447 |
"total": |
448 |
Number( data.getElementsByTagName("total")[0] |
449 |
.childNodes[0].nodeValue ), |
450 |
"start": |
451 |
Number( data.getElementsByTagName("start")[0] |
452 |
.childNodes[0].nodeValue ), |
453 |
"num": |
454 |
Number( data.getElementsByTagName("num")[0] |
455 |
.childNodes[0].nodeValue ), |
456 |
"hits": [] |
457 |
}; |
458 |
// parse all the first-level nodes for all <hit> tags |
459 |
var hits = data.getElementsByTagName("hit"); |
460 |
for (i = 0; i < hits.length; i++) |
461 |
show.hits[i] = Element_parseChildNodes(hits[i]); |
462 |
} else { |
463 |
context.throwError('Show failed. Malformed WS resonse.', |
464 |
114); |
465 |
}; |
466 |
|
467 |
var approxNode = data.getElementsByTagName("approximation"); |
468 |
if (approxNode && approxNode[0] && approxNode[0].childNodes[0] && approxNode[0].childNodes[0].nodeValue) |
469 |
show['approximation'] = |
470 |
Number( approxNode[0].childNodes[0].nodeValue); |
471 |
|
472 |
|
473 |
data.getElementsByTagName("") |
474 |
context.activeClients = activeClients; |
475 |
context.showCounter++; |
476 |
var delay = context.showTime; |
477 |
if (context.showCounter > context.showFastCount) |
478 |
delay += context.showCounter * context.dumpFactor; |
479 |
if ( activeClients > 0 ) |
480 |
context.showTimer = setTimeout( |
481 |
function () { |
482 |
context.show(); |
483 |
}, |
484 |
delay); |
485 |
context.showCallback(show); |
486 |
} |
487 |
); |
488 |
}, |
489 |
record: function(id, offset, syntax, handler) |
490 |
{ |
491 |
// we may call record with no previous search if in proxy mode |
492 |
if(!this.searchStatusOK && this.useSessions) |
493 |
throw new Error( |
494 |
'Pz2.js: record command has to be preceded with a search command.' |
495 |
); |
496 |
|
497 |
if( id !== undefined ) |
498 |
this.currRecID = id; |
499 |
|
500 |
var recordParams = { |
501 |
"command": "record", |
502 |
"session": this.sessionID, |
503 |
"id": this.currRecID, |
504 |
"windowid" : window.name |
505 |
}; |
506 |
|
507 |
this.currRecOffset = null; |
508 |
if (offset != undefined) { |
509 |
recordParams["offset"] = offset; |
510 |
this.currRecOffset = offset; |
511 |
} |
512 |
|
513 |
if (syntax != undefined) |
514 |
recordParams['syntax'] = syntax; |
515 |
|
516 |
//overwrite default callback id needed |
517 |
var callback = this.recordCallback; |
518 |
var args = undefined; |
519 |
if (handler != undefined) { |
520 |
callback = handler['callback']; |
521 |
args = handler['args']; |
522 |
} |
523 |
|
524 |
var context = this; |
525 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
526 |
|
527 |
request.safeGet( |
528 |
recordParams, |
529 |
function(data) { |
530 |
var recordNode; |
531 |
var record; |
532 |
//raw record |
533 |
if (context.currRecOffset !== null) { |
534 |
record = new Array(); |
535 |
record['xmlDoc'] = data; |
536 |
record['offset'] = context.currRecOffset; |
537 |
callback(record, args); |
538 |
//pz2 record |
539 |
} else if ( recordNode = |
540 |
data.getElementsByTagName("record")[0] ) { |
541 |
// if stylesheet was fetched do not parse the response |
542 |
if ( context.xslDoc ) { |
543 |
record = new Array(); |
544 |
record['xmlDoc'] = data; |
545 |
record['xslDoc'] = context.xslDoc; |
546 |
record['recid'] = |
547 |
recordNode.getElementsByTagName("recid")[0] |
548 |
.firstChild.nodeValue; |
549 |
//parse record |
550 |
} else { |
551 |
record = Element_parseChildNodes(recordNode); |
552 |
} |
553 |
var activeClients = |
554 |
Number( data.getElementsByTagName("activeclients")[0] |
555 |
.childNodes[0].nodeValue ); |
556 |
context.activeClients = activeClients; |
557 |
context.recordCounter++; |
558 |
var delay = context.recordTime + context.recordCounter * context.dumpFactor; |
559 |
if ( activeClients > 0 ) |
560 |
context.recordTimer = |
561 |
setTimeout ( |
562 |
function() { |
563 |
context.record(id, offset, syntax, handler); |
564 |
}, |
565 |
delay |
566 |
); |
567 |
callback(record, args); |
568 |
} |
569 |
else |
570 |
context.throwError('Record failed. Malformed WS resonse.', |
571 |
115); |
572 |
} |
573 |
); |
574 |
}, |
575 |
|
576 |
termlist: function() |
577 |
{ |
578 |
if( !this.searchStatusOK && this.useSessions ) |
579 |
throw new Error( |
580 |
'Pz2.js: termlist command has to be preceded with a search command.' |
581 |
); |
582 |
|
583 |
// if called explicitly takes precedence |
584 |
clearTimeout(this.termTimer); |
585 |
|
586 |
var context = this; |
587 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
588 |
request.safeGet( |
589 |
{ |
590 |
"command": "termlist", |
591 |
"session": this.sessionID, |
592 |
"name": this.termKeys, |
593 |
"windowid" : window.name, |
594 |
"version" : this.version |
595 |
|
596 |
}, |
597 |
function(data) { |
598 |
if ( data.getElementsByTagName("termlist") ) { |
599 |
var activeClients = |
600 |
Number( data.getElementsByTagName("activeclients")[0] |
601 |
.childNodes[0].nodeValue ); |
602 |
context.activeClients = activeClients; |
603 |
var termList = { "activeclients": activeClients }; |
604 |
var termLists = data.getElementsByTagName("list"); |
605 |
//for each termlist |
606 |
for (i = 0; i < termLists.length; i++) { |
607 |
var listName = termLists[i].getAttribute('name'); |
608 |
termList[listName] = new Array(); |
609 |
var terms = termLists[i].getElementsByTagName('term'); |
610 |
//for each term in the list |
611 |
for (j = 0; j < terms.length; j++) { |
612 |
var term = { |
613 |
"name": |
614 |
(terms[j].getElementsByTagName("name")[0] |
615 |
.childNodes.length |
616 |
? terms[j].getElementsByTagName("name")[0] |
617 |
.childNodes[0].nodeValue |
618 |
: 'ERROR'), |
619 |
"freq": |
620 |
terms[j] |
621 |
.getElementsByTagName("frequency")[0] |
622 |
.childNodes[0].nodeValue || 'ERROR' |
623 |
}; |
624 |
|
625 |
// Only for xtargets: id, records, filtered |
626 |
var termIdNode = |
627 |
terms[j].getElementsByTagName("id"); |
628 |
if(terms[j].getElementsByTagName("id").length) |
629 |
term["id"] = |
630 |
termIdNode[0].childNodes[0].nodeValue; |
631 |
termList[listName][j] = term; |
632 |
|
633 |
var recordsNode = terms[j].getElementsByTagName("records"); |
634 |
if (recordsNode && recordsNode.length) |
635 |
term["records"] = recordsNode[0].childNodes[0].nodeValue; |
636 |
|
637 |
var filteredNode = terms[j].getElementsByTagName("filtered"); |
638 |
if (filteredNode && filteredNode.length) |
639 |
term["filtered"] = filteredNode[0].childNodes[0].nodeValue; |
640 |
|
641 |
} |
642 |
} |
643 |
|
644 |
context.termCounter++; |
645 |
var delay = context.termTime |
646 |
+ context.termCounter * context.dumpFactor; |
647 |
if ( activeClients > 0 ) |
648 |
context.termTimer = |
649 |
setTimeout( |
650 |
function () { |
651 |
context.termlist(); |
652 |
}, |
653 |
delay |
654 |
); |
655 |
|
656 |
context.termlistCallback(termList); |
657 |
} |
658 |
else |
659 |
context.throwError('Termlist failed. Malformed WS resonse.', |
660 |
116); |
661 |
} |
662 |
); |
663 |
|
664 |
}, |
665 |
bytarget: function() |
666 |
{ |
667 |
if( !this.initStatusOK && this.useSessions ) |
668 |
throw new Error( |
669 |
'Pz2.js: bytarget command has to be preceded with a search command.' |
670 |
); |
671 |
|
672 |
// no need to continue |
673 |
if( !this.searchStatusOK ) |
674 |
return; |
675 |
|
676 |
// if called explicitly takes precedence |
677 |
clearTimeout(this.bytargetTimer); |
678 |
|
679 |
var context = this; |
680 |
var request = new pzHttpRequest(this.pz2String, this.errorHandler); |
681 |
request.safeGet( |
682 |
{ |
683 |
"command": "bytarget", |
684 |
"session": this.sessionID, |
685 |
"block": 1, |
686 |
"windowid" : window.name, |
687 |
"version" : this.version |
688 |
}, |
689 |
function(data) { |
690 |
if ( data.getElementsByTagName("status")[0] |
691 |
.childNodes[0].nodeValue == "OK" ) { |
692 |
var targetNodes = data.getElementsByTagName("target"); |
693 |
var bytarget = new Array(); |
694 |
for ( i = 0; i < targetNodes.length; i++) { |
695 |
bytarget[i] = new Array(); |
696 |
for( j = 0; j < targetNodes[i].childNodes.length; j++ ) { |
697 |
if ( targetNodes[i].childNodes[j].nodeType |
698 |
== Node.ELEMENT_NODE ) { |
699 |
var nodeName = |
700 |
targetNodes[i].childNodes[j].nodeName; |
701 |
if (targetNodes[i].childNodes[j].firstChild != null) |
702 |
{ |
703 |
var nodeText = targetNodes[i].childNodes[j] |
704 |
.firstChild.nodeValue; |
705 |
bytarget[i][nodeName] = nodeText; |
706 |
} |
707 |
else { |
708 |
bytarget[i][nodeName] = ""; |
709 |
} |
710 |
|
711 |
|
712 |
} |
713 |
} |
714 |
if (bytarget[i]["state"]=="Client_Disconnected") { |
715 |
bytarget[i]["hits"] = "Error"; |
716 |
} else if (bytarget[i]["state"]=="Client_Error") { |
717 |
bytarget[i]["hits"] = "Error"; |
718 |
} else if (bytarget[i]["state"]=="Client_Working") { |
719 |
bytarget[i]["hits"] = "..."; |
720 |
} |
721 |
if (bytarget[i].diagnostic == "1") { |
722 |
bytarget[i].diagnostic = "Permanent system error"; |
723 |
} else if (bytarget[i].diagnostic == "2") { |
724 |
bytarget[i].diagnostic = "Temporary system error"; |
725 |
} |
726 |
var targetsSuggestions = targetNodes[i].getElementsByTagName("suggestions"); |
727 |
if (targetsSuggestions != undefined && targetsSuggestions.length>0) { |
728 |
var suggestions = targetsSuggestions[0]; |
729 |
bytarget[i]["suggestions"] = Element_parseChildNodes(suggestions); |
730 |
} |
731 |
} |
732 |
|
733 |
context.bytargetCounter++; |
734 |
var delay = context.bytargetTime |
735 |
+ context.bytargetCounter * context.dumpFactor; |
736 |
if ( context.activeClients > 0 ) |
737 |
context.bytargetTimer = |
738 |
setTimeout( |
739 |
function () { |
740 |
context.bytarget(); |
741 |
}, |
742 |
delay |
743 |
); |
744 |
|
745 |
context.bytargetCallback(bytarget); |
746 |
} |
747 |
else |
748 |
context.throwError('Bytarget failed. Malformed WS resonse.', |
749 |
117); |
750 |
} |
751 |
); |
752 |
}, |
753 |
|
754 |
// just for testing, probably shouldn't be here |
755 |
showNext: function(page) |
756 |
{ |
757 |
var step = page || 1; |
758 |
this.show( ( step * this.currentNum ) + this.currentStart ); |
759 |
}, |
760 |
|
761 |
showPrev: function(page) |
762 |
{ |
763 |
if (this.currentStart == 0 ) |
764 |
return false; |
765 |
var step = page || 1; |
766 |
var newStart = this.currentStart - (step * this.currentNum ); |
767 |
this.show( newStart > 0 ? newStart : 0 ); |
768 |
}, |
769 |
|
770 |
showPage: function(pageNum) |
771 |
{ |
772 |
//var page = pageNum || 1; |
773 |
this.show(pageNum * this.currentNum); |
774 |
} |
775 |
}; |
776 |
|
777 |
/* |
778 |
******************************************************************************** |
779 |
** AJAX HELPER CLASS *********************************************************** |
780 |
******************************************************************************** |
781 |
*/ |
782 |
var pzHttpRequest = function ( url, errorHandler ) { |
783 |
this.maxUrlLength = 2048; |
784 |
this.request = null; |
785 |
this.url = url; |
786 |
this.errorHandler = errorHandler || null; |
787 |
this.async = true; |
788 |
this.requestHeaders = {}; |
789 |
|
790 |
if ( window.XMLHttpRequest ) { |
791 |
this.request = new XMLHttpRequest(); |
792 |
} else if ( window.ActiveXObject ) { |
793 |
try { |
794 |
this.request = new ActiveXObject( 'Msxml2.XMLHTTP' ); |
795 |
} catch (err) { |
796 |
this.request = new ActiveXObject( 'Microsoft.XMLHTTP' ); |
797 |
} |
798 |
} |
799 |
}; |
800 |
|
801 |
|
802 |
pzHttpRequest.prototype = |
803 |
{ |
804 |
safeGet: function ( params, callback ) |
805 |
{ |
806 |
var encodedParams = this.encodeParams(params); |
807 |
var url = this._urlAppendParams(encodedParams); |
808 |
if (url.length >= this.maxUrlLength) { |
809 |
this.requestHeaders["Content-Type"] |
810 |
= "application/x-www-form-urlencoded"; |
811 |
this._send( 'POST', this.url, encodedParams, callback ); |
812 |
} else { |
813 |
this._send( 'GET', url, '', callback ); |
814 |
} |
815 |
}, |
816 |
|
817 |
get: function ( params, callback ) |
818 |
{ |
819 |
this._send( 'GET', this._urlAppendParams(this.encodeParams(params)), |
820 |
'', callback ); |
821 |
}, |
822 |
|
823 |
post: function ( params, data, callback ) |
824 |
{ |
825 |
this._send( 'POST', this._urlAppendParams(this.encodeParams(params)), |
826 |
data, callback ); |
827 |
}, |
828 |
|
829 |
load: function () |
830 |
{ |
831 |
this.async = false; |
832 |
this.request.open( 'GET', this.url, this.async ); |
833 |
this.request.send(''); |
834 |
if ( this.request.status == 200 ) |
835 |
return this.request.responseXML; |
836 |
}, |
837 |
|
838 |
encodeParams: function (params) |
839 |
{ |
840 |
var sep = ""; |
841 |
var encoded = ""; |
842 |
for (var key in params) { |
843 |
if (params[key] != null) { |
844 |
encoded += sep + key + '=' + encodeURIComponent(params[key]); |
845 |
sep = '&'; |
846 |
} |
847 |
} |
848 |
return encoded; |
849 |
}, |
850 |
|
851 |
_send: function ( type, url, data, callback) |
852 |
{ |
853 |
var context = this; |
854 |
this.callback = callback; |
855 |
this.async = true; |
856 |
this.request.open( type, url, this.async ); |
857 |
for (var key in this.requestHeaders) |
858 |
this.request.setRequestHeader(key, this.requestHeaders[key]); |
859 |
this.request.onreadystatechange = function () { |
860 |
context._handleResponse(url); /// url used ONLY for error reporting |
861 |
} |
862 |
this.request.send(data); |
863 |
}, |
864 |
|
865 |
_urlAppendParams: function (encodedParams) |
866 |
{ |
867 |
if (encodedParams) |
868 |
return this.url + "?" + encodedParams; |
869 |
else |
870 |
return this.url; |
871 |
}, |
872 |
|
873 |
_handleResponse: function (savedUrlForErrorReporting) |
874 |
{ |
875 |
if ( this.request.readyState == 4 ) { |
876 |
// pick up appplication errors first |
877 |
var errNode = null; |
878 |
if (this.request.responseXML && |
879 |
(errNode = this.request.responseXML.documentElement) |
880 |
&& errNode.nodeName == 'error') { |
881 |
var errMsg = errNode.getAttribute("msg"); |
882 |
var errCode = errNode.getAttribute("code"); |
883 |
var errAddInfo = ''; |
884 |
if (errNode.childNodes.length) |
885 |
errAddInfo = ': ' + errNode.childNodes[0].nodeValue; |
886 |
|
887 |
var err = new Error(errMsg + errAddInfo); |
888 |
err.code = errCode; |
889 |
|
890 |
if (this.errorHandler) { |
891 |
this.errorHandler(err); |
892 |
} |
893 |
else { |
894 |
throw err; |
895 |
} |
896 |
} else if (this.request.status == 200 && |
897 |
this.request.responseXML == null) { |
898 |
if (this.request.responseText != null) { |
899 |
//assume JSON |
900 |
|
901 |
var json = null; |
902 |
var text = this.request.responseText; |
903 |
if (typeof window.JSON == "undefined") |
904 |
json = eval("(" + text + ")"); |
905 |
else { |
906 |
try { |
907 |
json = JSON.parse(text); |
908 |
} |
909 |
catch (e) { |
910 |
// Safari: eval will fail as well. Considering trying JSON2 (non-native implementation) instead |
911 |
/* DEBUG only works in mk2-mobile |
912 |
if (document.getElementById("log")) |
913 |
document.getElementById("log").innerHTML = "" + e + " " + length + ": " + text; |
914 |
*/ |
915 |
try { |
916 |
json = eval("(" + text + ")"); |
917 |
} |
918 |
catch (e) { |
919 |
/* DEBUG only works in mk2-mobile |
920 |
if (document.getElementById("log")) |
921 |
document.getElementById("log").innerHTML = "" + e + " " + length + ": " + text; |
922 |
*/ |
923 |
} |
924 |
} |
925 |
} |
926 |
this.callback(json, "json"); |
927 |
} else { |
928 |
var err = new Error("XML response is empty but no error " + |
929 |
"for " + savedUrlForErrorReporting); |
930 |
err.code = -1; |
931 |
if (this.errorHandler) { |
932 |
this.errorHandler(err); |
933 |
} else { |
934 |
throw err; |
935 |
} |
936 |
} |
937 |
} else if (this.request.status == 200) { |
938 |
this.callback(this.request.responseXML); |
939 |
} else { |
940 |
var err = new Error("HTTP response not OK: " |
941 |
+ this.request.status + " - " |
942 |
+ this.request.statusText ); |
943 |
err.code = '00' + this.request.status; |
944 |
if (this.errorHandler) { |
945 |
this.errorHandler(err); |
946 |
} |
947 |
else { |
948 |
throw err; |
949 |
} |
950 |
} |
951 |
} |
952 |
} |
953 |
}; |
954 |
|
955 |
/* |
956 |
******************************************************************************** |
957 |
** XML HELPER FUNCTIONS ******************************************************** |
958 |
******************************************************************************** |
959 |
*/ |
960 |
|
961 |
// DOMDocument |
962 |
|
963 |
if ( window.ActiveXObject) { |
964 |
var DOMDoc = document; |
965 |
} else { |
966 |
var DOMDoc = Document.prototype; |
967 |
} |
968 |
|
969 |
DOMDoc.newXmlDoc = function ( root ) |
970 |
{ |
971 |
var doc; |
972 |
|
973 |
if (document.implementation && document.implementation.createDocument) { |
974 |
doc = document.implementation.createDocument('', root, null); |
975 |
} else if ( window.ActiveXObject ) { |
976 |
doc = new ActiveXObject("MSXML2.DOMDocument"); |
977 |
doc.loadXML('<' + root + '/>'); |
978 |
} else { |
979 |
throw new Error ('No XML support in this browser'); |
980 |
} |
981 |
|
982 |
return doc; |
983 |
} |
984 |
|
985 |
|
986 |
DOMDoc.parseXmlFromString = function ( xmlString ) |
987 |
{ |
988 |
var doc; |
989 |
|
990 |
if ( window.DOMParser ) { |
991 |
var parser = new DOMParser(); |
992 |
doc = parser.parseFromString( xmlString, "text/xml"); |
993 |
} else if ( window.ActiveXObject ) { |
994 |
doc = new ActiveXObject("MSXML2.DOMDocument"); |
995 |
doc.loadXML( xmlString ); |
996 |
} else { |
997 |
throw new Error ("No XML parsing support in this browser."); |
998 |
} |
999 |
|
1000 |
return doc; |
1001 |
} |
1002 |
|
1003 |
DOMDoc.transformToDoc = function (xmlDoc, xslDoc) |
1004 |
{ |
1005 |
if ( window.XSLTProcessor ) { |
1006 |
var proc = new XSLTProcessor(); |
1007 |
proc.importStylesheet( xslDoc ); |
1008 |
return proc.transformToDocument(xmlDoc); |
1009 |
} else if ( window.ActiveXObject ) { |
1010 |
return document.parseXmlFromString(xmlDoc.transformNode(xslDoc)); |
1011 |
} else { |
1012 |
alert( 'Unable to perform XSLT transformation in this browser' ); |
1013 |
} |
1014 |
} |
1015 |
|
1016 |
// DOMElement |
1017 |
|
1018 |
Element_removeFromDoc = function (DOM_Element) |
1019 |
{ |
1020 |
DOM_Element.parentNode.removeChild(DOM_Element); |
1021 |
} |
1022 |
|
1023 |
Element_emptyChildren = function (DOM_Element) |
1024 |
{ |
1025 |
while( DOM_Element.firstChild ) { |
1026 |
DOM_Element.removeChild( DOM_Element.firstChild ) |
1027 |
} |
1028 |
} |
1029 |
|
1030 |
Element_appendTransformResult = function ( DOM_Element, xmlDoc, xslDoc ) |
1031 |
{ |
1032 |
if ( window.XSLTProcessor ) { |
1033 |
var proc = new XSLTProcessor(); |
1034 |
proc.importStylesheet( xslDoc ); |
1035 |
var docFrag = false; |
1036 |
docFrag = proc.transformToFragment( xmlDoc, DOM_Element.ownerDocument ); |
1037 |
DOM_Element.appendChild(docFrag); |
1038 |
} else if ( window.ActiveXObject ) { |
1039 |
DOM_Element.innerHTML = xmlDoc.transformNode( xslDoc ); |
1040 |
} else { |
1041 |
alert( 'Unable to perform XSLT transformation in this browser' ); |
1042 |
} |
1043 |
} |
1044 |
|
1045 |
Element_appendTextNode = function (DOM_Element, tagName, textContent ) |
1046 |
{ |
1047 |
var node = DOM_Element.ownerDocument.createElement(tagName); |
1048 |
var text = DOM_Element.ownerDocument.createTextNode(textContent); |
1049 |
|
1050 |
DOM_Element.appendChild(node); |
1051 |
node.appendChild(text); |
1052 |
|
1053 |
return node; |
1054 |
} |
1055 |
|
1056 |
Element_setTextContent = function ( DOM_Element, textContent ) |
1057 |
{ |
1058 |
if (typeof DOM_Element.textContent !== "undefined") { |
1059 |
DOM_Element.textContent = textContent; |
1060 |
} else if (typeof DOM_Element.innerText !== "undefined" ) { |
1061 |
DOM_Element.innerText = textContent; |
1062 |
} else { |
1063 |
throw new Error("Cannot set text content of the node, no such method."); |
1064 |
} |
1065 |
} |
1066 |
|
1067 |
Element_getTextContent = function (DOM_Element) |
1068 |
{ |
1069 |
if ( typeof DOM_Element.textContent != 'undefined' ) { |
1070 |
return DOM_Element.textContent; |
1071 |
} else if (typeof DOM_Element.text != 'undefined') { |
1072 |
return DOM_Element.text; |
1073 |
} else { |
1074 |
throw new Error("Cannot get text content of the node, no such method."); |
1075 |
} |
1076 |
} |
1077 |
|
1078 |
Element_parseChildNodes = function (node) |
1079 |
{ |
1080 |
var parsed = {}; |
1081 |
var hasChildElems = false; |
1082 |
var textContent = ''; |
1083 |
|
1084 |
if (node.hasChildNodes()) { |
1085 |
var children = node.childNodes; |
1086 |
for (var i = 0; i < children.length; i++) { |
1087 |
var child = children[i]; |
1088 |
switch (child.nodeType) { |
1089 |
case Node.ELEMENT_NODE: |
1090 |
hasChildElems = true; |
1091 |
var nodeName = child.nodeName; |
1092 |
if (!(nodeName in parsed)) |
1093 |
parsed[nodeName] = []; |
1094 |
parsed[nodeName].push(Element_parseChildNodes(child)); |
1095 |
break; |
1096 |
case Node.TEXT_NODE: |
1097 |
textContent += child.nodeValue; |
1098 |
break; |
1099 |
case Node.CDATA_SECTION_NODE: |
1100 |
textContent += child.nodeValue; |
1101 |
break; |
1102 |
} |
1103 |
} |
1104 |
} |
1105 |
|
1106 |
var attrs = node.attributes; |
1107 |
for (var i = 0; i < attrs.length; i++) { |
1108 |
hasChildElems = true; |
1109 |
var attrName = '@' + attrs[i].nodeName; |
1110 |
var attrValue = attrs[i].nodeValue; |
1111 |
parsed[attrName] = attrValue; |
1112 |
} |
1113 |
|
1114 |
// if no nested elements/attrs set value to text |
1115 |
if (hasChildElems) |
1116 |
parsed['#text'] = textContent; |
1117 |
else |
1118 |
parsed = textContent; |
1119 |
|
1120 |
return parsed; |
1121 |
} |
1122 |
|
1123 |
/* do not remove trailing bracket */ |
1124 |
} |