]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/result_common.js
Typo: visiblity -> visibility
[working/Evergreen.git] / Open-ILS / web / opac / skin / default / js / result_common.js
1
2 var recordsHandled = 0;
3 var recordsCache = [];
4 var lowHitCount = 4;
5
6 var resultFetchAllRecords = false;
7
8 /* set up the event handlers */
9 if( findCurrentPage() == MRESULT || findCurrentPage() == RRESULT ) {
10         G.evt.result.hitCountReceived.push(resultSetHitInfo);
11         G.evt.result.recordReceived.push(resultDisplayRecord, resultAddCopyCounts);
12         G.evt.result.copyCountsReceived.push(resultDisplayCopyCounts);
13         G.evt.result.allRecordsReceived.push(resultBuildCaches, resultDrawSubjects, 
14       resultDrawAuthors, resultDrawSeries, function(){unHideMe($('result_info_2'))});
15         attachEvt('result','lowHits',resultLowHits);
16         attachEvt('result','zeroHits',resultZeroHits);
17         attachEvt( "common", "locationUpdated", resultSBSubmit );
18         /* do this after we have ID's so the rank for mr pages will be correct */
19         attachEvt("result", "preCollectRecords", resultPaginate);
20 }
21
22 function resultSBSubmit(){searchBarSubmit();}
23
24 /* returns the last 'index' postion ocurring in this page */
25 function resultFinalPageIndex() {
26         if(getHitCount() < (getOffset() + getDisplayCount())) 
27                 return getHitCount() - 1;
28         return getOffset() + getDisplayCount() - 1;
29 }
30
31
32
33
34 /* generic search method */
35 function resultCollectSearchIds( type, method, handler ) {
36
37         var sort                = (getSort() == SORT_TYPE_REL) ? null : getSort(); 
38         var sortdir = (sort) ? ((getSortDir()) ? getSortDir() : SORT_DIR_ASC) : null;
39
40         var item_type;
41         var item_form;
42         var args = {};
43
44         if( type ) {
45                 args.searches = {};
46                 args.searches[getStype()] = {};
47                 var term = getTerm();
48                 if( term ) {
49                         term = term.replace(/'/g,' ');
50                         term = term.replace(/\\/g,' ');
51                         args.searches[getStype()].term = term;
52                 }
53
54                 var form = parseForm(getForm());
55                 item_type = form.item_type;
56                 item_form = form.item_form;
57
58         } else {
59                 args.searches = JSON2js(getSearches());
60                 item_type = (getItemType()) ? getItemType().split(/,/) : null;
61                 item_form = (getItemForm()) ? getItemForm().split(/,/) : null;
62         }
63
64         var limit = (resultFetchAllRecords) ? 1000 : getDisplayCount();
65
66         if( getOffset() > 0 ) {
67                 if( getHitCount() > 0 && (getOffset() + getDisplayCount()) > getHitCount() ) 
68                         limit = getHitCount() - getOffset();
69         }
70
71         args.org_unit = getLocation();
72         args.depth    = getDepth();
73         args.limit    = limit;
74         args.offset   = getOffset();
75         args.visibility_limit = 3000;
76
77         if(sort) args.sort = sort;
78         if(sortdir) args.sort_dir = sortdir;
79         if(item_type) args.item_type    = item_type;
80         if(item_form) args.item_form    = item_form;
81
82
83         if(getAudience()) args.audience  = getAudience().split(/,/);
84         if(getLitForm()) args.lit_form  = getLitForm().split(/,/);
85         if(getLanguage()) args.language = getLanguage().split(/,/);
86
87         //alert(js2JSON(args));
88
89         _debug('SEARCH: \n' + js2JSON(args) + '\n\n');
90         var req = new Request(method, args, 1);
91         req.callback(handler);
92         req.send();
93 }
94
95
96
97
98
99 /* set the search result info, number of hits, which results we're 
100         displaying, links to the next/prev pages, etc. */
101 function resultSetHitInfo() { 
102
103
104         /* tell the user where the results are coming from */
105         var baseorg = findOrgUnit(getLocation());
106         var depth = getDepth();
107         var mydepth = findOrgDepth(baseorg);
108         if( findOrgDepth(baseorg) != depth ) {
109                 var tmporg = baseorg;
110                 while( mydepth > depth ) {
111                         mydepth--;
112                         tmporg = findOrgUnit(tmporg.parent_ou());
113                 }
114                 unHideMe($('including_results_for'));
115                 $('including_results_location').appendChild(text(tmporg.name()));
116         }
117
118
119         try{searchTimer.stop()}catch(e){}
120
121         //if( findCurrentPage() == MRESULT ) {
122         if( findCurrentPage() == MRESULT || 
123
124                 (findCurrentPage() == RRESULT &&
125                         (
126                                 getRtype() == RTYPE_TITLE ||
127                                 getRtype() == RTYPE_AUTHOR ||
128                                 getRtype() == RTYPE_SUBJECT ||
129                                 getRtype() == RTYPE_SERIES ||
130                                 getRtype() == RTYPE_KEYWORD 
131                         )
132
133                 ) ) {
134
135                 if(getHitCount() <= lowHitCount && getTerm())
136                         runEvt('result', 'lowHits');
137         }
138
139         if(getHitCount() == 0) {
140                 runEvt('result', 'zeroHits');
141                 return;
142         }
143
144
145         var pages = getHitCount() / getDisplayCount();
146         if(pages % 1) pages = parseInt(pages) + 1;
147
148         
149
150         var cpage = (getOffset()/getDisplayCount()) + 1;
151
152         G.ui.result.current_page.appendChild(text(cpage));
153         G.ui.result.num_pages.appendChild(text(pages + ")")); /* the ) is dumb */
154
155         $('current_page2').appendChild(text(cpage));
156         $('num_pages2').appendChild(text(pages + ")")); /* the ) is dumb */
157
158         /* set the offsets */
159         var offsetEnd = getDisplayCount() + getOffset();  
160         if( getDisplayCount() > (getHitCount() - getOffset()))  
161                 offsetEnd = getHitCount();
162
163         G.ui.result.offset_end.appendChild(text(offsetEnd));
164         G.ui.result.offset_start.appendChild(text(getOffset() + 1));
165
166         $('offset_end2').appendChild(text(offsetEnd));
167         $('offset_start2').appendChild(text(getOffset() + 1));
168
169         G.ui.result.result_count.appendChild(text(getHitCount()));
170         unHideMe(G.ui.result.info);
171
172         $('result_count2').appendChild(text(getHitCount()));
173         unHideMe($('result_info_div2'));
174 }
175
176 function resultLowHits() {
177         showCanvas();
178         unHideMe($('result_low_hits'));
179         if(getHitCount() > 0)
180                 unHideMe($('result_low_hits_msg'));
181
182         var sreq = new Request(CHECK_SPELL, getTerm());
183         sreq.callback(resultSuggestSpelling);
184         sreq.send();
185
186         var words = getTerm().split(' ');
187         var word;
188         while( word = words.shift() ) {
189                 var areq = new Request(FETCH_CROSSREF, getStype(), getTerm() );
190                 areq.callback(resultLowHitXRef);
191                 areq.send();
192         }
193
194         if( !(getForm() == null || getForm() == 'all' || getForm() == "") ) {
195                 var a = {};
196                 a[PARAM_FORM] = "all";
197                 $('low_hits_remove_format_link').setAttribute('href',buildOPACLink(a));
198                 unHideMe($('low_hits_remove_format'));
199         }
200
201         resultSuggestSearchClass();
202
203         if(getTerm()) resultExpandSearch(); /* advanced search */
204 }
205
206 var lowHitsXRefLink;
207 var lowHitsXRefLinkParent;
208 function resultLowHitXRef(r) {
209         if(!lowHitsXRefLink){
210                 lowHitsXRefLinkParent = $('low_hits_xref_link').parentNode;
211                 lowHitsXRefLink = lowHitsXRefLinkParent.removeChild($('low_hits_xref_link'));
212         }
213         var res = r.getResultObject();
214         var arr = res.from;
215         arr.concat(res.also);
216         if(arr && arr.length > 0) {
217                 unHideMe($('low_hits_cross_ref'));
218                 var word;
219                 var c = 0;
220                 while( word = arr.shift() ) {
221                         if(c++ > 20) break;
222                         var a = {};
223                         a[PARAM_TERM] = word;
224                         var template = lowHitsXRefLink.cloneNode(true);
225                         template.setAttribute('href',buildOPACLink(a));
226                         template.appendChild(text(word));
227                         lowHitsXRefLinkParent.appendChild(template);
228                         lowHitsXRefLinkParent.appendChild(text(' '));
229                 }
230         }
231 }
232
233 function resultZeroHits() {
234         showCanvas();
235         unHideMe($('result_low_hits'));
236         unHideMe($('result_zero_hits_msg'));
237         //if(getTerm()) resultExpandSearch(); /* advanced search */
238 }
239
240 function resultExpandSearch() {
241         var top = findOrgDepth(globalOrgTree);
242         if(getDepth() == top) return;
243         unHideMe($('low_hits_expand_range'));
244         var par = $('low_hits_expand_link').parentNode;
245         var template = par.removeChild($('low_hits_expand_link'));
246
247         var bottom = getDepth();
248         while( top < bottom ) {
249                 var a = {};
250                 a[PARAM_DEPTH] = top;
251                 var temp = template.cloneNode(true);
252                 temp.appendChild(text(findOrgTypeFromDepth(top).opac_label()))
253                 temp.setAttribute('href',buildOPACLink(a));
254                 par.appendChild(temp);
255                 top++;
256         }
257 }
258
259 function resultSuggestSearchClass() {
260         var stype = getStype();
261         if(stype == STYPE_KEYWORD) return;
262         var a = {}; var ref;
263         unHideMe($('low_hits_search_type'));
264         if(stype != STYPE_TITLE) {
265                 ref = $('low_hits_title_search');
266                 unHideMe(ref);
267                 a[PARAM_STYPE] = STYPE_TITLE;
268                 ref.setAttribute('href',buildOPACLink(a));
269         }
270         if(stype != STYPE_AUTHOR) {
271                 ref = $('low_hits_author_search');
272                 unHideMe(ref);
273                 a[PARAM_STYPE] = STYPE_AUTHOR;
274                 ref.setAttribute('href',buildOPACLink(a));
275         }
276         if(stype != STYPE_SUBJECT) {
277                 ref = $('low_hits_subject_search');
278                 unHideMe(ref);
279                 a[PARAM_STYPE] = STYPE_SUBJECT;
280                 ref.setAttribute('href',buildOPACLink(a));
281         }
282         if(stype != STYPE_KEYWORD) {
283                 ref = $('low_hits_keyword_search');
284                 unHideMe(ref);
285                 a[PARAM_STYPE] = STYPE_KEYWORD;
286                 ref.setAttribute('href',buildOPACLink(a));
287         }
288         if(stype != STYPE_SERIES) {
289                 ref = $('low_hits_series_search');
290                 unHideMe(ref);
291                 a[PARAM_STYPE] = STYPE_SERIES;
292                 ref.setAttribute('href',buildOPACLink(a));
293         }
294 }
295
296 function resultSuggestSpelling(r) {
297         var res = r.getResultObject();
298         var phrase = getTerm();
299         var words = phrase.split(/ /);
300
301         var newterm = "";
302
303         for( var w = 0; w < words.length; w++ ) {
304                 var word = words[w];
305                 var blob = grep(res, function(i){return (i.word == word);});
306                 if( blob ) blob = blob[0];
307                 else continue;
308                 if( blob.word == word ) {
309                         if( blob.suggestions && blob.suggestions[0] ) {
310                                 newterm += " " + blob.suggestions[0];
311                                 unHideMe($('did_you_mean'));
312                         } else {
313                                 newterm += " " + word;
314                         }
315                 }
316         }
317
318         var arg = {};
319         arg[PARAM_TERM] = newterm;
320         $('spell_check_link').setAttribute('href', buildOPACLink(arg));
321         $('spell_check_link').appendChild(text(newterm));
322 }
323
324
325 function resultPaginate() {
326         var o = getOffset();
327
328         if( !(  ((o) + getDisplayCount()) >= getHitCount()) ) {
329
330                 var args = {};
331                 args[PARAM_OFFSET]      = o + getDisplayCount();
332                 args[PARAM_SORT]                = SORT;
333                 args[PARAM_SORT_DIR] = SORT_DIR;
334                 args[PARAM_RLIST]               = new CGI().param(PARAM_RLIST);
335
336                 G.ui.result.next_link.setAttribute("href", buildOPACLink(args)); 
337                 addCSSClass(G.ui.result.next_link, config.css.result.nav_active);
338
339                 $('next_link2').setAttribute("href", buildOPACLink(args)); 
340                 addCSSClass($('next_link2'), config.css.result.nav_active);
341
342                 args[PARAM_OFFSET] = getHitCount() - (getHitCount() % getDisplayCount());
343
344                 /* when hit count is divisible by display count, we have to adjust */
345                 if( getHitCount() % getDisplayCount() == 0 ) 
346                         args[PARAM_OFFSET] -= getDisplayCount();
347
348                 G.ui.result.end_link.setAttribute("href", buildOPACLink(args)); 
349                 addCSSClass(G.ui.result.end_link, config.css.result.nav_active);
350
351                 $('end_link2').setAttribute("href", buildOPACLink(args)); 
352                 addCSSClass($('end_link2'), config.css.result.nav_active);
353         }
354
355         if( o > 0 ) {
356
357                 var args = {};
358                 args[PARAM_SORT]                = SORT;
359                 args[PARAM_SORT_DIR] = SORT_DIR;
360                 args[PARAM_RLIST]               = new CGI().param(PARAM_RLIST);
361
362                 args[PARAM_OFFSET] = o - getDisplayCount();
363                 G.ui.result.prev_link.setAttribute( "href", buildOPACLink(args)); 
364                 addCSSClass(G.ui.result.prev_link, config.css.result.nav_active);
365
366                 $('prev_link2').setAttribute( "href", buildOPACLink(args)); 
367                 addCSSClass($('prev_link2'), config.css.result.nav_active);
368
369                 args[PARAM_OFFSET] = 0;
370                 G.ui.result.home_link.setAttribute( "href", buildOPACLink(args)); 
371                 addCSSClass(G.ui.result.home_link, config.css.result.nav_active);
372
373                 $('search_home_link2').setAttribute( "href", buildOPACLink(args)); 
374                 addCSSClass($('search_home_link2'), config.css.result.nav_active);
375         }
376
377         if(getDisplayCount() < getHitCount()) {
378                 unHideMe($('start_end_links_span'));
379                 unHideMe($('start_end_links_span2'));
380    }
381
382         showCanvas();
383         try{searchTimer.stop()}catch(e){}
384 }
385
386 function buildunAPISpan (span, type, id) {
387         var cgi = new CGI();
388         var d = new Date();
389
390         addCSSClass(span,'unapi-id');
391
392         span.setAttribute(
393                 'title',
394                 'tag:' + cgi.server_name + ',' +
395                         d.getFullYear() +
396                         ':' + type + '/' + id
397         );
398 }
399
400 /* display the record info in the record display table 'pos' is the 
401                 zero based position the record should have in the display table */
402 function resultDisplayRecord(rec, pos, is_mr) {
403
404         if(rec == null) rec = new mvr(); /* so the page won't die if there was an error */
405         recordsHandled++;
406         recordsCache.push(rec);
407
408         var r = table.rows[pos + 1];
409
410         
411         try {
412                 var rank = parseFloat(ranks[pos + getOffset()]);
413                 rank            = parseInt( rank * 100 );
414                 var relspan = $n(r, "relevancy_span");
415                 relspan.appendChild(text(rank));
416                 unHideMe(relspan.parentNode);
417         } catch(e){ }
418
419         var pic = $n(r, config.names.result.item_jacket);
420         pic.setAttribute("src", buildISBNSrc(cleanISBN(rec.isbn())));
421
422         var title_link = $n(r, config.names.result.item_title);
423         var author_link = $n(r, config.names.result.item_author);
424
425         if( is_mr )  {
426                 var onlyrec = onlyrecord[ getOffset() + pos ];
427                 if(onlyrec) {
428                         buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', onlyrec);
429
430                         var args = {};
431                         args.page = RDETAIL;
432                         args[PARAM_OFFSET] = 0;
433                         args[PARAM_RID] = onlyrec;
434                         args[PARAM_MRID] = rec.doc_id();
435                         pic.parentNode.setAttribute("href", buildOPACLink(args));
436                         title_link.setAttribute("href", buildOPACLink(args));
437                         title_link.appendChild(text(normalize(truncate(rec.title(), 65))));
438                         
439                 } else {
440                         buildunAPISpan($n(r,'unapi'), 'metabib-metarecord', rec.doc_id());
441
442                         buildTitleLink(rec, title_link); 
443                         var args = {};
444                         args.page = RRESULT;
445                         args[PARAM_OFFSET] = 0;
446                         args[PARAM_MRID] = rec.doc_id();
447                         pic.parentNode.setAttribute("href", buildOPACLink(args));
448                 }
449
450         } else {
451                 buildunAPISpan($n(r,'unapi'), 'biblio-record_entry', rec.doc_id());
452
453                 buildTitleDetailLink(rec, title_link); 
454                 var args = {};
455                 args.page = RDETAIL;
456                 args[PARAM_OFFSET] = 0;
457                 args[PARAM_RID] = rec.doc_id();
458                 pic.parentNode.setAttribute("href", buildOPACLink(args));
459
460                 unHideMe($n(r,'place_hold_span'));
461                 $n(r,'place_hold_link').setAttribute(
462                         'href','javascript:holdsDrawEditor({record:"'+rec.doc_id()+'",type:"T"});');
463         }
464
465         buildSearchLink(STYPE_AUTHOR, rec.author(), author_link);
466
467         if(! is_mr ) {
468         
469                 if(!isNull(rec.edition()))      {
470                         unHideMe( $n(r, "result_table_extra_span"));
471                         $n(r, "result_table_edition_span").appendChild( text( rec.edition()) );
472                 }
473                 if(!isNull(rec.pubdate())) {
474                         unHideMe( $n(r, "result_table_extra_span"));
475                         unHideMe($n(r, "result_table_pub_span"));
476                         $n(r, "result_table_pub_span").appendChild( text( rec.pubdate() ));
477                 }
478                 if(!isNull(rec.publisher()) ) {
479                         unHideMe( $n(r, "result_table_extra_span"));
480                         unHideMe($n(r, "result_table_pub_span"));
481                         $n(r, "result_table_pub_span").appendChild( text( " " + rec.publisher() ));
482                 }
483
484                 if(!isNull(rec.physical_description()) ) {
485                         unHideMe( $n(r, "result_table_extra_span"));
486                         var t = " " + rec.physical_description();
487                         //$n(r, "result_table_phys_span").appendChild( text(t.replace(/:.*/g,'')));
488                         $n(r, "result_table_phys_span").appendChild( text(t));
489                 }
490
491         }
492
493         resultBuildFormatIcons( r, rec, is_mr );
494
495         unHideMe(r);
496         
497         runEvt("result", "recordDrawn", rec.doc_id(), title_link);
498
499         /*
500         if(resultPageIsDone())  {
501                 runEvt('result', 'allRecordsReceived', recordsCache);
502         }
503         */
504 }
505
506 function _resultFindRec(id) {
507         for( var i = 0; i != recordsCache.length; i++ ) {
508                 var rec = recordsCache[i];
509                 if( rec && rec.doc_id() == id )
510                         return rec;
511         }
512         return null;
513 }
514
515
516 function resultBuildFormatIcons( row, rec, is_mr ) {
517
518         var ress = rec.types_of_resource();
519
520         for( var i in ress ) {
521
522                 var res = ress[i];
523                 if(!res) continue;
524
525                 var link = $n(row, res + "_link");
526                 link.title = res;
527                 var img = link.getElementsByTagName("img")[0];
528                 removeCSSClass( img, config.css.dim );
529
530                 var f = getForm();
531                 if( f != "all" ) {
532                         if( f == modsFormatToMARC(res) ) 
533                                 addCSSClass( img, "dim2_border");
534                 }
535
536                 var args = {};
537                 args[PARAM_OFFSET] = 0;
538
539                 if(is_mr) {
540                         args.page = RRESULT;
541                         args[PARAM_TFORM] = modsFormatToMARC(res);
542                         args[PARAM_MRID] = rec.doc_id();
543
544                 } else {
545                         args.page = RDETAIL
546                         args[PARAM_RID] = rec.doc_id();
547                 }
548
549                 link.setAttribute("href", buildOPACLink(args));
550
551         }
552 }
553
554
555 function resultPageIsDone(pos) {
556         return (recordsHandled == getDisplayCount() 
557                 || recordsHandled + getOffset() == getHitCount());
558 }
559
560 var resultCCHeaderApplied = false;
561
562 /* -------------------------------------------------------------------- */
563 /* dynamically add the copy count rows based on the org type 'countsrow' 
564         is the row into which we will add TD's to hold the copy counts 
565         This code generates copy count cells with an id of
566         'copy_count_cell_<depth>_<pagePosition>'  */
567 function resultAddCopyCounts(rec, pagePosition) {
568
569         var r = table.rows[pagePosition + 1];
570         var countsrow = $n(r, config.names.result.counts_row );
571         var ccell = $n(countsrow, config.names.result.count_cell);
572
573         var nodes = orgNodeTrail(findOrgUnit(getLocation()));
574         var node = nodes[0];
575         var type = findOrgType(node.ou_type());
576         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
577         ccell.title = type.opac_label();
578         //addCSSClass(ccell, config.css.result.cc_cell_even);
579
580         var lastcell = ccell;
581         var lastheadcell = null;
582
583         var cchead = null;
584         var ccheadcell = null;
585         if(!resultCCHeaderApplied) {
586                 ccrow = $('result_thead_row');
587                 ccheadcell =  ccrow.removeChild($n(ccrow, "result_thead_ccell"));
588                 var t = ccheadcell.cloneNode(true);
589                 lastheadcell = t;
590                 t.appendChild(text(type.opac_label()));
591                 ccrow.appendChild(t);
592                 resultCCHeaderApplied = true;
593         }
594
595         if(nodes[1]) {
596
597                 var x = 1;
598                 var d = findOrgDepth(nodes[1]);
599                 var d2 = findOrgDepth(nodes[nodes.length -1]);
600
601                 for( var i = d; i <= d2 ; i++ ) {
602         
603                         ccell = ccell.cloneNode(true);
604
605                         //if((i % 2)) removeCSSClass(ccell, "copy_count_cell_even");
606                         //else addCSSClass(ccell, "copy_count_cell_even");
607
608                         var node = nodes[x++];
609                         var type = findOrgType(node.ou_type());
610         
611                         ccell.id = "copy_count_cell_" + type.depth() + "_" + pagePosition;
612                         ccell.title = type.opac_label();
613                         countsrow.insertBefore(ccell, lastcell);
614                         lastcell = ccell;
615
616                         if(ccheadcell) {
617                                 var t = ccheadcell.cloneNode(true);
618                                 t.appendChild(text(type.opac_label()));
619                                 ccrow.insertBefore(t, lastheadcell);
620                                 lastheadcell = t;
621                         }
622                 }
623         }
624
625         unHideMe($("search_info_table"));
626 }
627
628 /* collect copy counts for a record using method 'methodName' */
629 function resultCollectCopyCounts(rec, pagePosition, methodName) {
630         if(rec == null || rec.doc_id() == null) return;
631         var req = new Request(methodName, getLocation(), rec.doc_id(), getForm() );
632         req.request.userdata = [ rec, pagePosition ];
633         req.callback(resultHandleCopyCounts);
634         req.send();
635 }
636
637 function resultHandleCopyCounts(r) {
638         runEvt('result', 'copyCountsReceived', r.userdata[0], r.userdata[1], r.getResultObject()); 
639 }
640
641
642 /* display the collected copy counts */
643 function resultDisplayCopyCounts(rec, pagePosition, copy_counts) {
644         if(copy_counts == null || rec == null) return;
645         var i = 0;
646         while(copy_counts[i] != null) {
647                 var cell = $("copy_count_cell_" + i +"_" + pagePosition);
648                 var cts = copy_counts[i];
649                 cell.appendChild(text(cts.available + " / " + cts.count));
650
651                 if(isXUL()) {
652                         /* here we style opac-invisible records for xul */
653
654                         if( cts.depth == 0 ) {
655                                 if(!cts.transcendant && !cts.unshadow) {
656                                         _debug("found an opac-shadowed record: " + rec.doc_id());
657                                         var row = cell.parentNode.parentNode.parentNode.parentNode.parentNode; 
658                                         if( cts.count == 0 ) 
659                                                 addCSSClass( row, 'no_copies' );
660                                         else 
661                                                 addCSSClass( row, 'shadowed' );
662                                 }
663                         }
664                 }
665                 i++;
666         }
667 }
668
669