0f86acbbe3bae506aa166e1e5fb3e1ef6b3e9ddf
[plewww.git] / plekit / table / table.js
1 /* $Id$ */
2
3 var debug=false;
4
5 /* for debugging purposes */
6 function plc_timestamp () {
7   var now = new Date();
8   return now.getMinutes() + ':' + now.getSeconds() + '.' + now.getMilliseconds() ; 
9 }
10
11 function plc_message (message) {
12   console.log ( plc_timestamp() + ' : ' + message);
13 }
14
15 /* when a table gets paginated, displays context info */
16 function plekit_table_paginator (opts,table_id) {
17
18   if(!("currentPage" in opts)) { return; }
19     
20   var p = document.createElement('p');
21   var table=$(table_id);
22   var t = $(table_id+'-fdtablePaginaterWrapTop');
23   var b = $(table_id+'-fdtablePaginaterWrapBottom');
24
25   /* when there's no visible entry, the pagination code removes the wrappers */
26   if ( (!t) || (!b) ) return;
27
28   /* get how many entries are matching:
29      opts.visibleRows only holds the contents of the current page
30      so we store the number of matching entries in the table 'matching' attribute
31   */
32   var totalMatches = opts.totalRows;
33   var matching=table['matching'];
34   if (matching) totalMatches = matching;
35
36   var label;
37
38   var matches_text;
39   if (totalMatches != opts.totalRows) {
40     matches_text = totalMatches + "/" + opts.totalRows;
41   } else {
42     matches_text = opts.totalRows;
43   }
44   var first = ((opts.currentPage-1) * opts.rowsPerPage) +1;
45   var last = Math.min((opts.currentPage * opts.rowsPerPage),totalMatches);
46   var items_text = "Items [" + first + " - " + last + "] of " + matches_text;
47   var page_text = "Page " + opts.currentPage + " of " + Math.ceil(totalMatches / opts.rowsPerPage);
48   label = items_text + " -- " + page_text;
49
50   p.className = "paginationText";    
51   p.appendChild(document.createTextNode(label));
52
53   /*  t.insertBefore(p.cloneNode(true), t.firstChild); */
54   b.appendChild(p);
55 }
56
57
58 /* locates a table from its id and alters the classname to reflect new table size */
59 function plekit_pagesize_set (table_id,size_id,def_size) {
60   var table=document.getElementById(table_id);
61   var size_area=document.getElementById(size_id);
62   if ( ! size_area.value ) {
63     size_area.value=def_size;
64   }
65   var size=size_area.value;
66   table.className=table.className.replace(/paginate-\d+/,"paginate-"+size); 
67   tablePaginater.init(table_id);
68 }
69
70 function plekit_pagesize_reset(table_id, size_id, size) {
71   var table=document.getElementById(table_id);
72   var size_area=document.getElementById(size_id);
73   size_area.value=size;
74   table.className=table.className.replace(/paginate-\d+/,"paginate-"+size); 
75   tablePaginater.init(table_id);
76 }
77   
78 /* set or clear the ' invisibleRow' in the tr's classname, according to visible */
79 function plekit_table_row_visible (row,visible) {
80   var cn=row.className;
81   /* clear */
82   cn=cn.replace("invisibleRow","");
83   cn.strip();
84   if (! visible) cn += " invisibleRow";
85   row.className=cn;
86 }
87
88 // Working around MSIE...
89 if ('undefined' == typeof Node)
90     Node = { ELEMENT_NODE: 1, TEXT_NODE: 3 };
91
92 // Extract actual text from a DOM node (remove internal tags and so on)
93 function getInnerText(node) {
94         var result = '';
95         if (Node.TEXT_NODE == node.nodeType)
96                 return node.nodeValue;
97         if (Node.ELEMENT_NODE != node.nodeType)
98                 return '';
99         for (var index = 0; index < node.childNodes.length; ++index)
100                 result += getInnerText(node.childNodes.item(index));
101         return result;
102 } // getInnerText
103
104 // cache in the <tr> node the concatenation of the innerTexts of its cells
105 function plekit_tr_text (tr) {
106   // if cached, use it
107   if (tr['text_to_match']) return tr['text_to_match'];
108   // otherwise compute it
109   var text="";
110   var cells=tr.cells;
111   for (var i=0; i<cells.length; i++) 
112     text += getInnerText(cells[i]) + " ";
113   text = text.strip().toLowerCase();
114   tr['text_to_match'] = text;
115   return text;
116 }
117
118 var plekit_table_filter_timeout = null;
119 /* scan the table, and mark as visible 
120    the rows that match (either AND or OR the patterns) */
121 function plekit_table_filter(table_id,pattern_id,and_id) {
122   clearTimeout(plekit_table_filter_timeout);
123   plekit_table_filter_timeout = setTimeout(function() {
124                                              plekit_lazy_table_filter(table_id,pattern_id,and_id)
125                                            },
126                                            200);
127 }
128
129 function plekit_lazy_table_filter (table_id,pattern_id,and_id) {
130
131   if (debug) plc_message ('entering plekit_lazy_table_filter');
132
133   var table=$(table_id);
134   var css='#'+table_id+'>tbody';
135   var rows = $$(css)[0].rows;
136   var pattern_area = $(pattern_id);
137   var pattern_text = pattern_area.value;
138   var matching_entries=0;
139   var and_button=$(and_id);
140   var and_if_true=and_button.checked;
141
142   // canonicalize white spaces 
143   pattern_text = pattern_text.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/g,' ');
144   
145   if (pattern_text.indexOf ("&") != -1) {
146     pattern_text = pattern_text.replace(/&/," ");
147     pattern_area.value=pattern_text;
148     and_button.checked=true;
149     return;
150   } else if (pattern_text.indexOf ("|") != -1 ) {
151     pattern_text = pattern_text.replace(/\|/," ");
152     pattern_area.value=pattern_text;
153     and_button.checked=false;
154     return;
155   }
156     
157   var match_attempts=0;
158   var start=(new Date).getTime();
159
160   // if we're running with the same pattern
161   var previous_pattern=table['previous_pattern'];
162   var previous_mode=table['previous_mode'];
163   if ( (previous_pattern == pattern_text) && (previous_mode == and_if_true) ) {
164     return;
165   }
166
167   if (debug) plc_message ('inside plekit_lazy_table_filter');
168
169   var searches=new Array();
170   var patterns=new Array();
171   if (pattern_text.length > 0) {
172       // re compile all patterns 
173       var pattern_texts = pattern_text.strip().split(" ");
174       for (var i=0; i < pattern_texts.length; i++) {
175           // ignore case
176           searches[i]=pattern_texts[i].toLowerCase();
177           patterns[i]=new RegExp(pattern_texts[i],"i");
178       }
179   }
180
181   // scan rows, elaborate 'visible'
182   for (var row_index = 0; row_index < rows.length ; row_index++) {
183     var tr=rows[row_index];
184     var visible=false;
185     
186     /*empty pattern */
187     if (patterns.length == 0) {
188       visible=true;
189     } else if (and_if_true) {
190       /* AND mode: all patterns must match */
191       visible=true;
192       var against=plekit_tr_text (tr);
193       for (var search_index=0; search_index<searches.length; search_index++) {
194         var search=searches[search_index];
195         match_attempts++;
196         if ( against.search(search) < 0) {
197           visible=false;
198           break;          
199         }
200       }
201     } else {
202       /* OR mode: any match is good enough */
203       visible=false;
204       var against = plekit_tr_text(tr);
205       for (var search_index=0; search_index < searches.length; search_index++) {
206         var search=searches[search_index];
207         match_attempts++;
208         if (against.search(search) >= 0) {
209           visible=true;
210           break;
211         }
212       }
213     }
214
215     plekit_table_row_visible(tr,visible);
216     if (visible) matching_entries +=1;
217   }
218   // save for next run
219   table['previous_pattern']=pattern_text;
220   table['previous_mode']=and_if_true;
221   
222   var end=(new Date).getTime();
223   var match_ms=end-start;
224
225   if (debug) plc_message ('almost at end of plekit_lazy_table_filter');
226
227   // optimize useless calls to init, by comparing # of matching entries
228   var previous_matching=table['previous_matching'];
229   if (matching_entries == previous_matching) {
230     return;
231   }
232   
233   table['matching']=matching_entries;
234   table['match_attempts']=match_attempts;
235   tablePaginater.init(table_id);
236   var end2=(new Date).getTime();
237   var paginate_ms=end2-end;
238
239   if (debug) plc_message ('exiting plekit_lazy_table_filter with paginate_ms=' + paginate_ms);
240
241 }
242
243 function plekit_table_filter_reset (table_id, pattern_id,and_id) {
244   /* reset pattern */
245   document.getElementById(pattern_id).value="";
246   plekit_table_filter (table_id, pattern_id,and_id);
247 }