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