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