|
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 |
} |