pz2.js:
[pazpar2-moved-to-github.git] / js / pz2.js
1 /*
2 ** $Id: pz2.js,v 1.14 2007-05-16 07:53:32 jakub Exp $
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     //for convenience
29     __myself = this;
30
31     //supported pazpar2's protocol version
32     __myself.suppProtoVer = '1';
33     __myself.pz2String = "search.pz2";
34     __myself.stylesheet = paramArray.detailstylesheet || null;
35
36     //load stylesheet if required in async mode
37     if( __myself.stylesheet ) {
38         var request = new pzHttpRequest( __myself.stylesheet );
39         request.get(
40                 {},
41                 function ( doc ) {
42                     __myself.xslDoc = doc;
43                 }
44         );
45     }
46
47     // at least one callback required
48     if ( !paramArray )
49         throw new Error("An array with parameters has to be suplied when instantiating a class");
50     
51     __myself.errorHandler = paramArray.errorhandler || null;
52     
53     // function callbacks
54     __myself.statCallback = paramArray.onstat || null;
55     __myself.showCallback = paramArray.onshow || null;
56     __myself.termlistCallback = paramArray.onterm || null;
57     __myself.recordCallback = paramArray.onrecord || null;
58     __myself.bytargetCallback = paramArray.onbytarget || null;
59     __myself.resetCallback = paramArray.onreset || null;
60
61     // termlist keys
62     __myself.termKeys = paramArray.termlist || "subject";
63     
64     // some configurational stuff
65     __myself.keepAlive = 50000;
66
67     __myself.sessionID = null;
68     __myself.initStatusOK = false;
69     __myself.pingStatusOK = false;
70     __myself.searchStatusOK = false;
71
72     if ( paramArray.keepAlive < __myself.keepAlive )
73         __myself.keepAlive = paramArray.keepAlive;
74
75     // for sorting
76     __myself.currentSort = "relevance";
77     // where are we?
78     __myself.currentStart = 0;
79     __myself.currentNum = 20;
80
81     // last full record retrieved
82     __myself.currRecID = null;
83     // current query
84     __myself.currQuery = null;
85
86     //timers
87     __myself.statTime = paramArray.stattime || 2000;
88     __myself.statTimer = null;
89     __myself.termTime = paramArray.termtime || 1000;
90     __myself.termTimer = null;
91     __myself.showTime = paramArray.showtime || 1000;
92     __myself.showTimer = null;
93     __myself.showFastCount = 4;
94     __myself.bytargetTime = paramArray.bytargettime || 1000;
95     __myself.bytargetTimer = null;
96
97     //useful?
98     __myself.dumpFactor = 500;
99     __myself.showCounter = 0;
100     __myself.termCounter = 0;
101
102     // active clients, updated by stat and show
103     // might be an issue since bytarget will poll accordingly
104     __myself.activeClients = 1;
105     
106     // auto init session?
107     if (paramArray.autoInit !== false)
108         __myself.init();
109 };
110 pz2.prototype = {
111     reset: function ()
112     {
113         __myself.sessionID = null;
114         __myself.initStatusOK = false;
115         __myself.pingStatusOK = false;
116         __myself.searchStatusOK = false;
117
118         clearTimeout(__myself.statTimer);
119         clearTimeout(__myself.showTimer);
120         clearTimeout(__myself.termTimer);
121         clearTimeout(__myself.bytargetTimer);
122             
123         if ( __myself.resetCallback )
124                 __myself.resetCallback();
125     },
126     init: function ( sessionId ) 
127     {
128         __myself.reset();
129         if ( sessionId != undefined ) {
130             __myself.initStatusOK = true;
131             __myself.sessionID = sessionId;
132             __myself.ping();
133
134         } else {
135             var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
136             request.get(
137                 { "command": "init" },
138                 function(data) {
139                     if ( data.getElementsByTagName("status")[0].childNodes[0].nodeValue == "OK" ) {
140                         if ( data.getElementsByTagName("protocol")[0].childNodes[0].nodeValue != __myself.suppProtoVer )
141                             throw new Error("Server's protocol not supported by the client");
142                         __myself.initStatusOK = true;
143                         __myself.sessionID = data.getElementsByTagName("session")[0].childNodes[0].nodeValue;
144                         setTimeout("__myself.ping()", __myself.keepAlive);
145                     }
146                     else
147                         // if it gets here the http return code was 200 (pz2 errors are 417)
148                         // but the response was invalid, it should never occur
149                         setTimeout("__myself.init()", 1000);
150                 }
151             );
152         }
153     },
154     // no need to ping explicitly
155     ping: function () 
156     {
157         if( !__myself.initStatusOK )
158             return;
159             // session is not initialized code here
160         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
161         request.get(
162             { "command": "ping", "session": __myself.sessionID },
163             function(data) {
164                 if ( data.getElementsByTagName("status")[0].childNodes[0].nodeValue == "OK" ) {
165                     __myself.pingStatusOK = true;
166                     setTimeout("__myself.ping()", __myself.keepAlive);
167                 }
168                 else
169                     // if it gets here the http return code was 200 (pz2 errors are 417)
170                     // but the response was invalid, it should never occur
171                     setTimeout("__myself.ping()", 1000);
172             }
173         );
174     },
175     search: function (query, num, sort, filter)
176     {
177         clearTimeout(__myself.statTimer);
178         clearTimeout(__myself.showTimer);
179         clearTimeout(__myself.termTimer);
180         clearTimeout(__myself.bytargetTimer);
181         
182         __myself.showCounter = 0;
183         __myself.termCounter = 0;
184         
185         if( !__myself.initStatusOK )
186             return;
187         
188         if( query !== undefined )
189             __myself.currQuery = query;
190         else
191             throw new Error("You need to supply query to the search command");
192
193         if( filter !== undefined )
194             var searchParams = { "command": "search", "session": __myself.sessionID, "query": __myself.currQuery, "filter": filter };
195         else
196             var searchParams = { "command": "search", "session": __myself.sessionID, "query": __myself.currQuery };
197         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
198         request.get(
199             searchParams,
200             function(data) {
201                 if ( data.getElementsByTagName("status")[0].childNodes[0].nodeValue == "OK" ) {
202                     __myself.searchStatusOK = true;
203                     //piggyback search
204                     __myself.show(0, num, sort);
205                     if ( __myself.statCallback )
206                         __myself.statTimer = setTimeout("__myself.stat()", __myself.statTime / 2);
207                     if ( __myself.termlistCallback )
208                         //__myself.termlist();
209                         __myself.termTimer = setTimeout("__myself.termlist()", __myself.termTime / 2);
210                     if ( __myself.bytargetCallback )
211                         __myself.bytargetTimer = setTimeout("__myself.bytarget()", __myself.bytargetTime / 2);
212                 }
213                 else
214                     // if it gets here the http return code was 200 (pz2 errors are 417)
215                     // but the response was invalid, it should never occur
216                     setTimeout("__myself.search(__myself.currQuery)", 1000);
217             }
218         );
219     },
220     stat: function()
221     {
222         if( !__myself.searchStatusOK )
223             return;
224         // if called explicitly takes precedence
225         clearTimeout(__myself.statTimer);
226         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
227         request.get(
228             { "command": "stat", "session": __myself.sessionID },
229             function(data) {
230                 if ( data.getElementsByTagName("stat") ) {
231                     var activeClients = Number( data.getElementsByTagName("activeclients")[0].childNodes[0].nodeValue );
232                     __myself.activeClients = activeClients;
233                     var stat = {
234                     "activeclients": activeClients,
235                     "hits": Number( data.getElementsByTagName("hits")[0].childNodes[0].nodeValue ),
236                     "records": Number( data.getElementsByTagName("records")[0].childNodes[0].nodeValue ),
237                     "clients": Number( data.getElementsByTagName("clients")[0].childNodes[0].nodeValue ),
238                     "initializing": Number( data.getElementsByTagName("initializing")[0].childNodes[0].nodeValue ),
239                     "searching": Number( data.getElementsByTagName("searching")[0].childNodes[0].nodeValue ),
240                     "presenting": Number( data.getElementsByTagName("presenting")[0].childNodes[0].nodeValue ),
241                     "idle": Number( data.getElementsByTagName("idle")[0].childNodes[0].nodeValue ),
242                     "failed": Number( data.getElementsByTagName("failed")[0].childNodes[0].nodeValue ),
243                     "error": Number( data.getElementsByTagName("error")[0].childNodes[0].nodeValue )
244                     };
245                     __myself.statCallback(stat);
246                     if (activeClients > 0)
247                         __myself.statTimer = setTimeout("__myself.stat()", __myself.statTime); 
248                 }
249                 else
250                     // if it gets here the http return code was 200 (pz2 errors are 417)
251                     // but the response was invalid, it should never occur
252                     __myself.statTimer = setTimeout("__myself.stat()", __myself.statTime / 4);
253             }
254         );
255     },
256     show: function(start, num, sort)
257     {
258         if( !__myself.searchStatusOK )
259             return;
260         // if called explicitly takes precedence
261         clearTimeout(__myself.showTimer);
262         
263         if( sort !== undefined )
264             __myself.currentSort = sort;
265         if( start !== undefined )
266             __myself.currentStart = Number( start );
267         if( num !== undefined )
268             __myself.currentNum = Number( num );
269         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
270         var context = this;
271         request.get(
272             { "command": "show", "session": __myself.sessionID, "start": __myself.currentStart,
273               "num": __myself.currentNum, "sort": __myself.currentSort, "block": 1 },
274             function(data) {
275                 if ( data.getElementsByTagName("status")[0].childNodes[0].nodeValue == "OK" ) {
276                     // first parse the status data send along with records
277                     // this is strictly bound to the format
278                     var activeClients = Number( data.getElementsByTagName("activeclients")[0].childNodes[0].nodeValue );
279                     var show = {
280                     "activeclients": activeClients,
281                     "merged": Number( data.getElementsByTagName("merged")[0].childNodes[0].nodeValue ),
282                     "total": Number( data.getElementsByTagName("total")[0].childNodes[0].nodeValue ),
283                     "start": Number( data.getElementsByTagName("start")[0].childNodes[0].nodeValue ),
284                     "num": Number( data.getElementsByTagName("num")[0].childNodes[0].nodeValue ),
285                     "hits": []
286                     };
287                     // parse all the first-level nodes for all <hit> tags
288                     var hits = data.getElementsByTagName("hit");
289                     var hit = new Array();
290                     for (i = 0; i < hits.length; i++) {
291                         show.hits[i] = new Array();
292                         show.hits[i]['location'] = new Array();
293                         for ( j = 0; j < hits[i].childNodes.length; j++) {
294                             var locCount = 0;
295                             if ( hits[i].childNodes[j].nodeType == Node.ELEMENT_NODE ) {
296                                 if (hits[i].childNodes[j].nodeName == 'location') {
297                                     var locNode = hits[i].childNodes[j];
298                                     var id = locNode.getAttribute('id');
299                                     show.hits[i]['location'][id] = {
300                                         "id": locNode.getAttribute("id"),
301                                         "name": locNode.getAttribute("name")
302                                     };
303                                 }
304                                 else {
305                                     var nodeName = hits[i].childNodes[j].nodeName;
306                                     var nodeText = hits[i].childNodes[j].firstChild.nodeValue;
307                                     show.hits[i][nodeName] = nodeText;
308                                 }
309                             }
310                         }
311                     }
312                     __myself.showCallback(show);
313                     __myself.showCounter++;
314                     var delay = __myself.showTime;
315                     if (__myself.showCounter > __myself.showFastCount)
316                             delay *= 2;
317                     if (activeClients > 0)
318                         __myself.showTimer = setTimeout("__myself.show()", delay);
319                 }
320                 else
321                     // if it gets here the http return code was 200 (pz2 errors are 417)
322                     // but the response was invalid, it should never occur
323                     __myself.showTimer = setTimeout("__myself.show()", __myself.showTime / 4);
324             }
325         );
326     },
327     record: function(id)
328     {
329         if( !__myself.searchStatusOK )
330             return;
331
332         if( id !== undefined )
333             __myself.currRecID = id;
334         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
335         request.get(
336             { "command": "record", "session": __myself.sessionID, "id": __myself.currRecID },
337             function(data) {
338                 var recordNode;
339                 var record = new Array();
340                 if ( recordNode = data.getElementsByTagName("record")[0] ) {
341                     // if stylesheet was fetched do not parse the response
342                     if ( __myself.xslDoc ) {
343                         record['xmlDoc'] = data;
344                         record['xslDoc'] = __myself.xslDoc;
345                     } else {
346                         for ( i = 0; i < recordNode.childNodes.length; i++) {
347                             if ( recordNode.childNodes[i].nodeType == Node.ELEMENT_NODE ) {
348                                 var nodeName = recordNode.childNodes[i].nodeName;
349                                 var nodeText = recordNode.childNodes[i].firstChild.nodeValue;
350                                 record[nodeName] = nodeText;                            
351                             }
352                         }
353                         // the location is hard coded
354                         var locationNodes = recordNode.getElementsByTagName("location");
355                         record["location"] = new Array();
356                         for ( i = 0; i < locationNodes.length; i++ ) {
357                             record["location"][i] = {
358                                 "id": locationNodes[i].getAttribute("id"),
359                                 "name": locationNodes[i].getAttribute("name")
360                             };
361                             for ( j = 0; j < locationNodes[i].childNodes.length; j++) {
362                                 if ( locationNodes[i].childNodes[j].nodeType == Node.ELEMENT_NODE ) {
363                                     var nodeName = locationNodes[i].childNodes[j].nodeName;
364                                     var nodeText;
365                                     if (locationNodes[i].childNodes[j].firstChild)
366                                             nodeText = locationNodes[i].childNodes[j].firstChild.nodeValue;
367                                     else
368                                             nodeText = '';
369                                     record["location"][i][nodeName] = nodeText;                            
370                                 }
371                             }
372                         }
373                     }
374                     __myself.recordCallback(record);
375                 }
376                 else
377                     // if it gets here the http return code was 200 (pz2 errors are 417)
378                     // but the response was invalid, it should never occur
379                     setTimeout("__myself.record(__myself.currRecID)", 1000);
380             }
381         );
382     },
383     termlist: function()
384     {
385         if( !__myself.searchStatusOK )
386             return;
387         // if called explicitly takes precedence
388         clearTimeout(__myself.termTimer);
389         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
390         request.get(
391             { "command": "termlist", "session": __myself.sessionID, "name": __myself.termKeys },
392             function(data) {
393                 if ( data.getElementsByTagName("termlist") ) {
394                     var termList = { "activeclients": Number( data.getElementsByTagName("activeclients")[0].childNodes[0].nodeValue ) };
395                     var termLists = data.getElementsByTagName("list");
396                     //for each termlist
397                     for (i = 0; i < termLists.length; i++) {
398                         var listName = termLists[i].getAttribute('name');
399                         termList[listName] = new Array();
400                         var terms = termLists[i].getElementsByTagName('term');
401                         //for each term in the list
402                         for (j = 0; j < terms.length; j++) { 
403                             var term = {
404                                 "name": terms[j].getElementsByTagName("name")[0].childNodes[0].nodeValue,
405                                 "freq": terms[j].getElementsByTagName("frequency")[0].childNodes[0].nodeValue
406                             };
407
408                             var termIdNode = terms[j].getElementsByTagName("id");
409                             if(terms[j].getElementsByTagName("id").length)
410                                 term["id"] = termIdNode[0].childNodes[0].nodeValue;
411
412                             termList[listName][j] = term;
413                         }
414                     }
415
416                     __myself.termlistCallback(termList);
417                     __myself.termCounter++;
418                     if (termList["activeclients"] > 0)
419                         __myself.termTimer = setTimeout("__myself.termlist()", (__myself.termTime + __myself.termCounter*__myself.dumpFactor)); 
420                 }
421                 else
422                     // if it gets here the http return code was 200 (pz2 errors are 417)
423                     // but the response was invalid, it should never occur
424                     __myself.termTimer = setTimeout("__myself.termlist()", __myself.termTime / 4); 
425             }
426         );
427
428     },
429     bytarget: function()
430     {
431         if( !__myself.searchStatusOK )
432             return;
433         // if called explicitly takes precedence
434         clearTimeout(__myself.bytargetTimer);
435         var request = new pzHttpRequest(__myself.pz2String, __myself.errorHandler);
436         request.get(
437             { "command": "bytarget", "session": __myself.sessionID },
438             function(data) {
439                 if ( data.getElementsByTagName("status")[0].childNodes[0].nodeValue == "OK" ) {
440                     var targetNodes = data.getElementsByTagName("target");
441                     var bytarget = new Array();
442                     for ( i = 0; i < targetNodes.length; i++) {
443                         bytarget[i] = new Array();
444                         for( j = 0; j < targetNodes[i].childNodes.length; j++ ) {
445                             if ( targetNodes[i].childNodes[j].nodeType == Node.ELEMENT_NODE ) {
446                                 var nodeName = targetNodes[i].childNodes[j].nodeName;
447                                 var nodeText = targetNodes[i].childNodes[j].firstChild.nodeValue;
448                                 bytarget[i][nodeName] = nodeText;
449                             }
450                         }
451                     }
452                     __myself.bytargetCallback(bytarget);
453                     if ( __myself.activeClients > 0 )
454                         __myself.bytargetTimer = setTimeout("__myself.bytarget()", __myself.bytargetTime);
455                 }
456                 else
457                     // if it gets here the http return code was 200 (pz2 errors are 417)
458                     // but the response was invalid, it should never occur
459                     __myself.bytargetTimer = setTimeout("__myself.bytarget()", __myself.bytargetTime / 4);
460             }
461         );
462     },
463     // just for testing, probably shouldn't be here
464     showNext: function(page)
465     {
466         var step = page || 1;
467         __myself.show( ( step * __myself.currentNum ) + __myself.currentStart );     
468     },
469     showPrev: function(page)
470     {
471         if (__myself.currentStart == 0 )
472             return false;
473         var step = page || 1;
474         var newStart = __myself.currentStart - (step * __myself.currentNum );
475         __myself.show( newStart > 0 ? newStart : 0 );
476     },
477     showPage: function(pageNum)
478     {
479         //var page = pageNum || 1;
480         __myself.show(pageNum * __myself.currentNum);
481     }
482 };
483
484 /*
485 *********************************************************************************
486 ** AJAX HELPER CLASS ************************************************************
487 *********************************************************************************
488 */
489 var pzHttpRequest = function ( url, errorHandler ) {
490         this.request = null;
491         this.url = url;
492         this.errorHandler = errorHandler || null;
493         
494         if ( window.XMLHttpRequest ) {
495             this.request = new XMLHttpRequest();
496         } else if ( window.ActiveXObject ) {
497             try {
498                 this.request = new ActiveXObject( 'Msxml2.XMLHTTP' );
499             } catch (err) {
500                 this.request = new ActiveXObject( 'Microsoft.XMLHTTP' );
501             }
502         }
503 };
504
505 pzHttpRequest.prototype = 
506 {
507     get: function ( params, callback ) 
508     {
509         this.callback = callback;
510         
511         var paramArr = new Array();
512         for ( var key in params ) {
513             paramArr.push(key + '=' + escape(params[key]));
514         }
515
516         var context = this;
517         this.request.open( 'GET', this.url+'?'+paramArr.join('&'), true );
518         this.request.onreadystatechange = function () {
519             context._handleResponse();
520         }
521         this.request.send();
522     },
523
524     _handleResponse: function ()
525     {
526         if ( this.request.readyState == 4 ) {
527             if ( this.request.status == 200 ) {
528                 this.callback( this.request.responseXML );
529             }
530             // pz errors
531             else if ( this.request.status == 417 ) {
532                 var errMsg = this.request.responseXML.getElementsByTagName("error")[0].childNodes[0].nodeValue;
533                 var errCode = this.request.responseXML.getElementsByTagName("error")[0].getAttribute("code");
534             
535                 var err = new Error(errMsg);
536                 err.code = errCode;
537             
538                 if (this.errorHandler) {
539                     this.errorHandler(err);
540                 }
541                 else {
542                     throw err;
543                 }
544             }
545             else {
546                 var err = new Error("XMLHttpRequest error. STATUS: " 
547                             + this.request.status + " STATUS TEXT: " 
548                             + this.request.statusText );
549                 err.code = 'HTTP';
550                 
551                 if (this.errorHandler) {
552                     this.errorHandler(err);
553                 }
554                 else {
555                     throw err;
556                 }
557             }
558         }
559     }
560 };
561
562 /*
563 *********************************************************************************
564 ** QUERY CLASS ******************************************************************
565 *********************************************************************************
566 */
567 var pzQuery = function()
568 {
569     this.simpleQuery = '';
570     this.singleFilter = null;
571     this.advTerms = new Array();
572     this.filterHash = new Array();
573     this.numTerms = 0;
574     this.filterNums = 0;
575 };
576 pzQuery.prototype = {
577     reset: function()
578     {
579         this.simpleQuery = '';
580         this.advTerms = new Array();
581         this.simpleFilter = null;
582         this.numTerms = 0;
583     },
584     addTerm: function(field, value)
585     {
586         var term = {"field": field, "value": value};
587         this.advTerms[this.numTerms] = term;
588         this.numTerms++;
589     },
590     getTermValueByIdx: function(index)
591     {
592         return this.advTerms[index].value;
593     },
594     getTermFieldByIdx: function(index)
595     {
596         return this.advTerms[index].field;
597     },
598     /* semicolon separated list of terms for given field*/
599     getTermsByField: function(field)
600     {
601         var terms = '';
602         for(var i = 0; i < this.advTerms.length; i++)
603         {
604             if( this.advTerms[i].field == field )
605                 terms = terms + this.queryHas[i].value + ';';
606         }
607         return terms;
608     },
609     addTermsFromList: function(inputString, field)
610     {
611         var inputArr = inputString.split(';');
612         for(var i=0; i < inputArr.length; i++)
613         {
614             if(inputArr[i].length < 3) continue;
615             this.advTerms[this.numTerms] = {"field": field, "value": inputArr[i] };
616             this.numTerms++;
617         }
618     },
619     removeTermByIdx: function(index)
620     {
621         this.advTerms.splice(index, 1);
622         this.numTerms--;
623     },
624     toCCL: function()
625     {   
626         var ccl = '';
627         if( this.simpleQuery != '')
628             ccl = '"'+this.simpleQuery+'"';
629         for(var i = 0; i < this.advTerms.length; i++)
630         {
631             if (ccl != '') ccl = ccl + ' and ';
632             ccl = ccl + this.advTerms[i].field+'="'+this.advTerms[i].value+'"';
633         }
634         return ccl;
635     },
636     addFilter: function(name, value)
637     {
638         var filter = {"name": name, "id": value };
639         this.filterHash[this.filterHash.length] = filter;
640         this.filterNums++
641         return  this.filterHash.length - 1;
642     },
643     setFilter: function(name, value)
644     {
645         this.filterHash = new Array();
646         this.filterNums = 0;
647         this.addFilter(name, value);
648     },
649     getFilter: function(index)
650     {
651         return this.filterHash[index].id;
652     },
653     getFilterName: function(index)
654     {
655         return this.filterHash[index].name;
656     },
657     removeFilter: function(index)
658     {
659         delete this.filterHash[index];
660         this.filterNums--;
661     },
662     clearFilter: function()
663     {
664         this.filterHash = new Array();
665         this.filterNums = 0;
666     },
667     getFilterString: function()
668     {
669         //temporary
670         if( this.singleFilter != null ) {
671             return 'pz:id='+this.singleFilter.id;
672         } 
673         else if( this.filterNums <= 0 ) {
674             return undefined;
675         }
676
677         var filter = 'pz:id=';
678         for(var i = 0; i < this.filterHash.length; i++)
679         {
680             if (this.filterHash[i] == undefined) continue;
681             if (filter > 'pz:id=') filter = filter + '|';            
682             filter += this.filterHash[i].id; 
683         }
684         return filter;
685     },
686     totalLength: function()
687     {
688         var simpleLength = this.simpleQuery != '' ? 1 : 0;
689         return this.advTerms.length + simpleLength;
690     },
691     clearSingleFilter: function()
692     {
693         this.singleFilter = null;
694     },
695     setSingleFilter: function(name, value)
696     {
697         this.singleFilter = {"name": name, "id": value };
698     },
699     getSingleFilterName: function()
700     {
701         return this.singleFilter.name;
702     }
703 }
704
705 }