]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/reports/oils_rpt_builder.js
fixed tab opening to contain navigation and print buttons
[working/Evergreen.git] / Open-ILS / web / reports / oils_rpt_builder.js
1 /** initializes reports, some basid display settings, 
2   * grabs and builds the IDL tree
3   */
4 function oilsInitReportBuilder() {
5         if(!oilsInitReports()) return false;
6         oilsReportBuilderReset();
7         DOM.oils_rpt_table.onclick = 
8                 function(){hideMe(DOM.oils_rpt_column_editor)};
9         oilsDrawRptTree(
10                 function() { 
11                         hideMe(DOM.oils_rpt_tree_loading); 
12                         unHideMe(DOM.oils_rpt_table); 
13                         oilsRptBuilderDrawClone(new CGI().param('ct'));
14                 }
15         );
16
17         DOM.oils_rpt_builder_save_template.onclick = oilsReportBuilderSave;
18 }
19
20 function oilsRptBuilderDrawClone(templateId) {
21         if(!templateId) return;
22         unHideMe(DOM.oils_rpt_builder_cloning);
23
24         oilsRptFetchTemplate(templateId,
25                 function(template) { oilsRptBuilderDrawClone2(template);}
26         );
27 }
28
29
30 function oilsRptBuilderDrawClone2(template) {
31         appendClear( DOM.oils_rpt_build_cloning_name, template.name() );
32         DOM.oils_rpt_builder_new_name.value = template.name();
33         DOM.oils_rpt_builder_new_desc.value = template.description();
34
35         _debug(formatJSON(template.data()));
36
37         /* manually shove data into the display selectors */
38         var def = JSON2js(template.data());
39
40         var table = def.from.table;
41         var node;
42         for( var i in oilsIDL ) {
43                 node = oilsIDL[i];
44                 if( node.table == table ) {
45                         setSelector(DOM.oils_rpt_builder_type_selector, node.name);
46                         DOM.oils_rpt_builder_type_selector.onchange();
47                         break;
48                 }
49         }
50
51         iterate(def.select,
52                 function(item) {
53                         oilsAddRptDisplayItem(item.path, item.alias, item.column.transform)});
54
55         iterate(def.where,
56                 function(item) {
57                         oilsAddRptFilterItem(item.path, item.column.transform, oilsRptObjectKeys(item.condition)[0])});
58
59         iterate(def.having,
60                 function(item) {
61                         oilsAddRptHavingItem(item.path, item.column.transform, oilsRptObjectKeys(item.condition)[0])});
62
63         oilsRpt.setTemplate(template);
64         oilsRpt.templateObject = null; /* simplify debugging */
65 }
66
67 function oilsReportBuilderReset() {
68         var n = (oilsRpt) ? oilsRpt.name : "";
69         oilsRpt = new oilsReport();
70         oilsRpt.name = n;
71         oilsRptDisplaySelector  = DOM.oils_rpt_display_selector;
72         oilsRptFilterSelector   = DOM.oils_rpt_filter_selector;
73         oilsRptHavingSelector   = DOM.oils_rpt_agg_filter_selector;
74         removeChildren(oilsRptDisplaySelector);
75         removeChildren(oilsRptFilterSelector);
76         removeChildren(oilsRptHavingSelector);
77         //removeChildren(oilsRptOrderBySelector);
78         oilsRptResetParams();
79 }
80
81 function oilsReportBuilderSave() {
82
83         var tmpl = new rt();
84         tmpl.name(DOM.oils_rpt_builder_new_name.value);
85         tmpl.description(DOM.oils_rpt_builder_new_desc.value);
86         tmpl.owner(USER.id());
87         tmpl.folder(new CGI().param('folder'));
88         tmpl.data(js2JSON(oilsRpt.def));
89
90         if(!confirm('Name : '+tmpl.name() + '\nDescription: ' + tmpl.description()+'\nSave Template?'))
91                 return;
92
93         debugFMObject(tmpl);
94         //return; /* XXX */
95
96         var req = new Request(OILS_RPT_CREATE_TEMPLATE, SESSION, tmpl);
97         req.request.alertEvent = false;
98         req.callback(
99                 function(r) {
100                         var res = r.getResultObject();
101                         if(checkILSEvent(res)) {
102                                 alertILSEvent(res);
103                         } else {
104                                 if( res && res != '0' ) {
105                                         oilsRptAlertSuccess();
106                                         _l('oils_rpt.xhtml');
107                                 } 
108                         }
109                 }
110         );
111         
112         req.send();
113 }
114
115
116
117 /* adds an item to the display window */
118 function oilsAddRptDisplayItem(path, name, tform, params) {
119         if( ! oilsAddSelectorItem(oilsRptDisplaySelector, path, name) ) 
120                 return;
121
122         /* add the selected columns to the report output */
123         name = (name) ? name : oilsRptPathCol(path);
124         if( !tform ) tform = 'Bare';
125
126         var aggregate = oilsRptGetIsAgg(tform);
127
128         /* add this item to the select blob */
129         var sel = {
130                 relation: hex_md5(oilsRptPathRel(path)), 
131                 path : path,
132                 alias: name,
133                 column: { transform: tform, colname: oilsRptPathCol(path) }
134         };
135
136         if( params ) sel.column.params = params;
137         oilsRptAddSelectList(sel, tform);
138         mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
139         oilsRptDebug();
140 }
141
142 function oilsRptAddSelectList(obj, tform) {
143         if(!oilsRptGetIsAgg(tform)) {
144                 var select = [];
145                 var added = false;
146                 for( var i = 0; i < oilsRpt.def.select.length; i++ ) {
147                         var item = oilsRpt.def.select[i];
148
149                         /* shove the item in question in front of the first agg tform */
150                         if( !added && oilsRptGetIsAgg( item.column.transform ) ) {
151                                 select.push(obj);
152                                 added = true;
153                         }
154                         select.push(item);
155                 }
156
157                 /* if there is no existing agg tfrom to 
158                         insert in front of, add me on the end */
159                 if(!added) select.push(obj);
160
161                 oilsRpt.def.select = select;
162
163                 if( added ) {
164                         /* re-draw the select display to get the order correct */
165                         var sel = oilsRptDisplaySelector;
166                         while( sel.options.length > 0 ) sel.options[0] = null;
167                         iterate(oilsRpt.def.select,
168                                 function(item) {
169                                         _debug('re-inserting display item ' + item.path);
170                                         oilsAddSelectorItem(oilsRptDisplaySelector, item.path, item.alias) });
171                 }
172
173         } else {
174                 /* shove agg transforms onto the end */
175                 oilsRpt.def.select.push(obj);
176         }
177 }
178
179
180
181 function oilsRptGetIsAgg(tform) {
182         return OILS_RPT_TRANSFORMS[tform].aggregate;
183 }
184
185 /* takes a column path and builds a from-clause object for the path */
186 function oilsRptBuildFromClause(path) {
187
188         /* the path is the full path (relation) from the source 
189                 object to the column in question (e.g. au-home_ou-aou-name)*/
190         var parts = path.split(/-/);
191
192         /* the final from clause */
193         var obj = {}; 
194
195         /* reference to the current position in the from clause */
196         var tobj = obj; 
197
198         var newpath = "";
199
200         /* walk the path, fleshing the from clause as we go */
201         for( var i = 0; i < parts.length; i += 2 ) {
202
203                 var cls = parts[i]; /* class name (id) */
204                 var col = parts[i+1]; /* column name */
205
206                 /* a "node" is a class description from the IDL, it 
207                         contains relevant info, plus a list of "fields",
208                         or column objects */
209                 var node = oilsIDL[cls];
210                 var pkey = oilsRptFindField(node, node.pkey);
211
212                 /* a "field" is a parsed version of a column from the IDL,
213                         contains datatype, column name, etc. */
214                 var field = oilsRptFindField(node, col);
215
216                 /* re-construct the path as we go so 
217                         we know what all we've seen thus far */
218                 newpath = (newpath) ? newpath + '-'+ cls : cls;
219
220                 /* extract relevant info */
221                 tobj.table = node.table;
222                 tobj.path = newpath;
223                 tobj.alias = hex_md5(newpath);
224
225                 _debug('field type is ' + field.type);
226                 if( i == (parts.length - 2) ) break;
227
228                 /* we still have columns left in the path, keep adding join's */
229                 var path_col = col;
230                 if(field.reltype != 'has_a')
231                         col = pkey.name + '-' + col;
232
233                 tobj.join = {};
234                 tobj = tobj.join;
235
236                 tobj[col] = {};
237                 tobj = tobj[col];
238                 if( field.type == 'link' ) {
239                         tobj.key = field.key;
240                         if( field.reltype == 'has_many' || field.reltype == 'might_have' )
241                                 tobj.type = 'left';
242                 }
243
244                 newpath = newpath + '-'+ path_col;
245         }
246
247         _debug("built 'from' clause: path="+path+"\n"+formatJSON(js2JSON(obj)));
248         return obj;
249 }
250
251 function oilsMoveUpDisplayItems() {
252         var sel = oilsRptDisplaySelector;
253         var idx = sel.selectedIndex;
254         if( idx == 0 ) return;
255         var opt = sel.options[idx];
256         sel.options[idx] = null;
257         idx--;
258         var val = opt.getAttribute('value');
259         insertSelectorVal(sel, idx, opt.innerHTML, val);
260         sel.options[idx].selected = true;
261
262         var arr = oilsRpt.def.select;
263         for( var i = 0; i < arr.length; i++ ) {
264                 if( arr[i].path == val ) {
265                         var other = arr[i-1];
266                         arr[i-1] = arr[i];
267                         arr[i] = other;
268                         break;
269                 }
270         }
271         oilsRptDebug();
272 }
273
274 function oilsMoveDownDisplayItems() {
275         var sel = oilsRptDisplaySelector;
276         var idx = sel.selectedIndex;
277         if( idx == sel.options.length - 1 ) return;
278         var opt = sel.options[idx];
279         sel.options[idx] = null;
280         idx++;
281         var val = opt.getAttribute('value');
282         insertSelectorVal(sel, idx, opt.innerHTML, val);
283         sel.options[idx].selected = true;
284
285         var arr = oilsRpt.def.select;
286         for( var i = 0; i < arr.length; i++ ) {
287                 if( arr[i].path == val ) {
288                         var other = arr[i+1];
289                         arr[i+1] = arr[i];
290                         arr[i] = other;
291                         break;
292                 }
293         }
294         oilsRptDebug();
295 }
296
297
298 /* removes a specific item from the display window */
299 /*
300 function oilsDelDisplayItem(val) {
301         oilsDelSelectorItem(oilsRptDisplaySelector, val);
302 }
303 */
304
305 /* removes selected items from the display window */
306 function oilsDelSelectedDisplayItems() {
307         var list = oilsDelSelectedItems(oilsRptDisplaySelector);
308
309         _debug('deleting list: ' + list);
310
311         /* remove the de-selected columns from the report output */
312         oilsRpt.def.select = grep( oilsRpt.def.select, 
313                 function(i) {
314                         for( var j = 0; j < list.length; j++ ) {
315                                 var d = list[j]; /* path */
316                                 var col = i.column;
317
318                                 _debug('in delete, looking at list = '+d+' : col = ' + 
319                                         col.colname + ' : relation = ' + i.relation + ' : encoded = ' + hex_md5(oilsRptPathRel(d)) );
320
321                                 if( hex_md5(oilsRptPathRel(d)) == i.relation && oilsRptPathCol(d) == col.colname ) {
322                                         return false;
323                                 }
324                         }
325                         return true;
326                 }
327         );
328
329         if(!oilsRpt.def.select) oilsRpt.def.select = [];
330         oilsRptPruneFromList(list);
331         oilsRptDebug();
332 }
333
334 function oilsRptPruneFromList(pathlist) {
335
336         for( var j = 0; j < pathlist.length; j++ ) {
337                 /* if there are no items left in the "select", "where", or "having" clauses 
338                         for the given relation, trim this relation from the "from" clause */
339                 var path = pathlist[j];
340                 var encrel = hex_md5(oilsRptPathRel(path));
341
342                 debug('seeing if we can prune from clause with relation = ' + encrel +' : path = ' + path);
343
344                 var func = function(i){ return (i.relation == hex_md5(oilsRptPathRel(path))); };
345
346                 if(     !grep(oilsRpt.def.select, func) && 
347                                 !grep(oilsRpt.def.where, func) && 
348                                 !grep(oilsRpt.def.having, func) ) {
349
350                         debug('looks like we can prune ' + path);
351
352                         oilsRptPruneFromClause(oilsRptPathRel(pathlist[j]));
353                 }
354         }
355 }
356
357
358 /* for each item in the path list, remove the associated data
359         from the "from" clause */
360
361 function oilsRptPruneFromClause(relation, node) {
362
363         var keys = oilsRptObjectKeys(node);
364         _debug("trying to remove relation: " + relation+'\n\tthis object has keys: '+keys);
365
366         if(!node) node = oilsRpt.def.from.join;
367         if(!node) return false;
368
369         for( var i in node ) {
370                 var child_node = node[i];
371                 _debug("\tanalyzing child node: "+child_node.path);
372
373                 // first, descend into the tree, and prune leaves 
374                 if( child_node.join ) {
375
376                         oilsRptPruneFromClause(relation, child_node.join); 
377                         var join_keys = oilsRptObjectKeys(child_node.join);
378                         _debug("\tchild has a sub-join for items : ["+ join_keys+"]");
379
380                         if(join_keys.length == 0) {
381                                 _debug("\tdeleting join for object "+i);
382                                 delete child_node.join;
383                         }
384                 }
385
386                 if( !child_node.join ) {
387
388                         _debug("\tchild node has no sub-join, seeing if we should delete it");
389
390                         var from_alias = child_node.alias;
391                         var func = function(n){ return (n.relation == from_alias)};
392         
393                         if(     !grep(oilsRpt.def.select, func) &&
394                                         !grep(oilsRpt.def.where, func) &&
395                                         !grep(oilsRpt.def.having, func) ) {
396         
397                                 /* we are not used by any other clauses */
398                                 _debug("\tdeleting node with relation: "+ from_alias);
399                                 delete node[i];
400                                 return true;
401                         }
402                 }
403         }
404
405         return false;
406 }
407
408 function oilsRptMkFilterTags(path, tform, filter) {
409         var name = oilsRptMakeLabel(path);
410         if(tform) name += ' ('+tform+')';
411         name += ' "' + filter + '"';
412         var epath = path + ':'+filter+':';
413         if(tform) epath += tform;
414
415         return [ name, epath ];
416 }
417
418
419 function oilsAddRptFilterItem(path, tform, filter) {
420         _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
421
422         var name = oilsRptMkFilterTags(path, tform, filter);
423         var epath = name[1];
424         name = name[0];
425
426         if( ! oilsAddSelectorItem(oilsRptFilterSelector, epath, name) )
427                 return;
428
429         var where = {
430                 relation: hex_md5(oilsRptPathRel(path)), 
431                 path : path,
432                 column:   { transform: tform, colname: oilsRptPathCol(path) },
433                 condition : {}
434         };
435         if( filter == 'is' || filter == 'is not' )
436                 where.condition[filter] = null;
437         else where.condition[filter] = oilsRptNextParam();
438
439         switch(tform) {
440                 case 'substring' : where.column.params = oilsRptNextParam();
441         }
442
443         oilsRpt.def.where.push(where);
444         mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
445         oilsRptDebug();
446 }
447
448
449 function oilsAddRptHavingItem(path, tform, filter) {
450         _debug("Adding filter item for "+path+" tform="+tform+" filter="+filter);
451
452         var name = oilsRptMkFilterTags(path, tform, filter);
453         var epath = name[1];
454         name = name[0];
455
456         if( ! oilsAddSelectorItem(oilsRptHavingSelector, epath, name) )
457                 return;
458
459         var having = {
460                 relation: hex_md5(oilsRptPathRel(path)), 
461                 path : path,
462                 column:   { transform: tform, colname: oilsRptPathCol(path) },
463                 condition : {}
464         };
465         if( filter == 'is' || filter == 'is not' )
466                 having.condition[filter] = null;
467         else having.condition[filter] = oilsRptNextParam();
468
469         switch(tform) {
470                 case 'substring' : having.column.params = oilsRptNextParam();
471         }
472
473         oilsRpt.def.having.push(having);
474         mergeObjects( oilsRpt.def.from, oilsRptBuildFromClause(path));
475         oilsRptDebug();
476 }
477
478
479
480 function oilsDelSelectedFilterItems() {
481         _oilsDelSelectedFilterItems('where');
482 }
483 function oilsDelSelectedAggFilterItems() {
484         _oilsDelSelectedFilterItems('having');
485 }
486
487 function _oilsDelSelectedFilterItems(type) {
488
489         /* the values in this list are formed:  <path>:<operation>:<transform> */
490         var list = oilsDelSelectedItems(oilsRptFilterSelector);
491
492         _debug("deleting filter items " + list);
493
494         for( var i = 0; i < list.length; i++ ) {
495                 var enc_path = list[i];
496                 var data = oilsRptParseFilterEncPath(enc_path);
497
498                 _debug("trimming filter items with enc_path = " + enc_path);
499                 _debug(data.path);
500                 _debug(data.operation);
501                 _debug(data.tform);
502                 _debug(data.tform);
503                 _debug(type);
504                 _debug('---------------------');
505
506                 oilsRpt.def[type] = grep( 
507                         oilsRpt.def[type],
508                         function(f) { 
509                                 return ! oilsRptFilterDataMatches( 
510                                         f, data.path, data.operation, data.tform );
511                         }
512                 );
513         }
514
515         if(!oilsRpt.def[type]) oilsRpt.def[type] = [];
516         oilsRptPruneFromList(list);
517         oilsRptDebug();
518 }
519
520 function oilsRptParseFilterEncPath(item) {
521         return {
522                 path:           item.replace(/:.*/,''),
523                 operation:      item.replace(/.*:(.*):.*/,'$1'),
524                 tform:  item.replace(/.*?:.*?:(.*)/,'$1')
525         };
526 }
527
528
529 function oilsRptFilterDataMatches(filter, path, operation, tform) {
530         var rel = hex_md5(oilsRptPathRel(path));
531         var col = oilsRptPathCol(path);
532
533         /*
534         _debug("oilsRptFilterDataMatches(): " + col + " : " + rel + " : " + tform + " : " + operation);
535         _debug("oilsRptFilterDataMatches(): " + filter.column.colname + " : " + filter.relation + " : " + 
536                 filter.column.transform + " : " + oilsRptObjectKeys(filter.condition)[0]);
537         _debug("------------------");
538         */
539
540         if(     col == filter.column.colname &&
541                         rel == filter.relation &&       
542                         tform == filter.column.transform &&
543                         operation == oilsRptObjectKeys(filter.condition)[0] ) return true;
544
545         return false;
546 }
547
548 /*
549 function oilsRptFilterGrep(flist, filter) {
550
551         for( var j = 0; j < flist.length; j++ ) {
552
553                 var fil = flist[j];
554                 var col = filter.column;
555                 var frel = hex_md5(oilsRptPathRel(fil.path));
556                 var fcol = oilsRptPathCol(fil.path);
557
558                 var op = oilsRptObjectKeys(filter.condition)[0];
559
560                 if(     frel == filter.relation && 
561                                 fcol == col.colname && 
562                                 fil.operation == op &&
563                                 fil.tform == col.transform ) {
564                                 return false;
565                 }
566         }
567         return true;
568 }
569 */
570
571 /* adds an item to the display window */
572 function oilsAddRptAggFilterItem(val) {
573         oilsAddSelectorItem(oilsRptHavingFilterSelector, val);
574 }
575
576 /* removes a specific item from the display window */
577 function oilsDelAggFilterItem(val) {
578         oilsDelSelectorItem(oilsRptHavingFilterSelector, val);
579 }
580
581
582
583 /*
584 function ___oilsDelSelectedAggFilterItems() {
585         var list = oilsDelSelectedItems(oilsRptHavingFilterSelector);
586         oilsRpt.def.having = grep( oilsRpt.def.having, 
587                 function(i) {
588                         for( var j = 0; j < list.length; j++ ) {
589                                 var d = list[j];
590                                 var col = i.column;
591
592                                 if( typeof col != 'string' ) 
593                                         for( var c in col ) col = col[c];
594
595                                 if( typeof col != 'string' ) col = col[0];
596
597                                 if( oilsRptPathRel(d) == i.relation && oilsRptPathCol(d) == col ) {
598                                 */
599                                 //      var param = (i.alias) ? i.alias.match(/::P\d*/) : null;
600                                         /*
601                                         if( param ) delete oilsRpt.params[param];
602                                         return false;
603                                 }
604                         }
605                         return true;
606                 }
607         );
608
609         if(!oilsRpt.def.having) oilsRpt.def.having = [];
610         oilsRptPruneFromList(list);
611         oilsRptDebug();
612 }
613 */
614
615
616 /* adds an item to the display window */
617 function oilsAddSelectorItem(sel, val, name) {
618         name = (name) ? name : oilsRptMakeLabel(val);
619         for( var i = 0; i < sel.options.length; i++ ) {
620                 var opt = sel.options[i];
621                 if( opt.value == val ) return false;
622         }
623         var opt = insertSelectorVal( sel, -1, name, val );
624         opt.setAttribute('title', name);
625         return true;
626 }
627
628
629 /* removes a specific item from the display window */
630 function oilsDelSelectorItem(sel, val) {
631         var opts = sel.options;
632         for( var i = 0; i < opts.length; i++ ) {
633                 var opt = opts[i];
634                 if( opt.value == val )  {
635                         if( i == opts.length - 1 ) 
636                                 opts[i] = null;
637                         else opts[i] = opts[i+1];
638                         return;
639                 }
640         }
641 }
642
643 /* removes selected items from the display window */
644 function oilsDelSelectedItems(sel) {
645         var list = getSelectedList(sel);
646         for( var i = 0; i < list.length; i++ ) 
647                 oilsDelSelectorItem(sel, list[i]);
648         return list;
649 }
650
651
652 /* hides the different field editor tabs */
653 function oilsRptHideEditorDivs() {
654         hideMe(DOM.oils_rpt_tform_div);
655         hideMe(DOM.oils_rpt_filter_div);
656         hideMe(DOM.oils_rpt_agg_filter_div);
657         hideMe(DOM.oils_rpt_order_by_div);
658
659         removeCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
660         removeCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
661         removeCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
662 }
663
664
665 /**
666   This draws the 3-tabbed window containing the transform,
667   filter, and aggregate filter picker window
668   */
669 function oilsRptDrawDataWindow(path) {
670         var col = oilsRptPathCol(path);
671         var cls = oilsRptPathClass(path);
672         var field = oilsRptFindField(oilsIDL[cls], col);
673
674         appendClear(DOM.oils_rpt_editor_window_label, text(oilsRptMakeLabel(path)));
675         appendClear(DOM.oils_rpt_editor_window_datatype, text(field.datatype));
676
677         _debug("setting update data window for column "+col+' on class '+cls);
678
679         var div = DOM.oils_rpt_column_editor;
680         /* set a preliminary top position so the page won't bounce around */
681
682
683         /* XXX */
684         //div.setAttribute('style','top:'+oilsMouseX+'px');
685
686         /* unhide the div so we can determine the dimensions */
687         unHideMe(div);
688
689         /* don't let them see the floating div until the position is fully determined */
690         div.style.visibility='hidden'; 
691
692         oilsRptDrawTransformWindow(path, col, cls, field);
693         oilsRptDrawFilterWindow(path, col, cls, field);
694         oilsRptDrawHavingWindow(path, col, cls, field);
695         //oilsRptDrawOrderByWindow(path, col, cls, field);
696
697         //buildFloatingDiv(div, 600);
698
699         //window.scrollTo(0,0);
700         window.scrollTo(0, 60);
701
702         /* now let them see it */
703         div.style.visibility='visible';
704         oilsRptSetDataWindowActions(div);
705 }
706
707
708 function oilsRptSetDataWindowActions(div) {
709         /* give the tab links behavior */
710
711
712         DOM.oils_rpt_tform_tab.onclick = 
713                 function(){
714                         oilsRptHideEditorDivs();
715                         unHideMe(DOM.oils_rpt_tform_div)
716                         addCSSClass(DOM.oils_rpt_tform_tab.parentNode, 'oils_rpt_tab_picker_selected');
717                 };
718
719         DOM.oils_rpt_filter_tab.onclick = 
720                 function(){
721                         oilsRptHideEditorDivs();
722                         unHideMe(DOM.oils_rpt_filter_div)
723                         addCSSClass(DOM.oils_rpt_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
724                 };
725         DOM.oils_rpt_agg_filter_tab.onclick = 
726                 function(){
727                         oilsRptHideEditorDivs();
728                         unHideMe(DOM.oils_rpt_agg_filter_div)
729                         addCSSClass(DOM.oils_rpt_agg_filter_tab.parentNode, 'oils_rpt_tab_picker_selected');
730                 };
731
732         /*
733         DOM.oils_rpt_order_by_tab.onclick = 
734                 function(){
735                         oilsRptHideEditorDivs();
736                         oilsRptDrawOrderByWindow();
737                         unHideMe(DOM.oils_rpt_order_by_div);
738                         };
739                         */
740
741         DOM.oils_rpt_tform_tab.onclick();
742         DOM.oils_rpt_column_editor_close_button.onclick = function(){hideMe(div);};
743 }
744
745
746 function oilsRptDrawFilterWindow(path, col, cls, field) {
747
748         var tformPicker = new oilsRptTformPicker( {     
749                         node : DOM.oils_rpt_filter_tform_table,
750                         datatype : field.datatype,
751                         non_aggregate : true
752                 }
753         );
754
755         var filterPicker = new oilsRptFilterPicker({
756                         node : DOM.oils_rpt_filter_op_table,
757                         datatype : field.datatype
758                 }
759         );
760
761         DOM.oils_rpt_filter_submit.onclick = function() {
762                 oilsAddRptFilterItem(
763                         path, tformPicker.getSelected(), filterPicker.getSelected());
764         }
765 }
766
767
768 function oilsRptDrawHavingWindow(path, col, cls, field) {
769         var tformPicker = new oilsRptTformPicker( {     
770                         node : DOM.oils_rpt_agg_filter_tform_table,
771                         datatype : field.datatype,
772                         aggregate : true
773                 }
774         );
775
776         var filterPicker = new oilsRptFilterPicker({
777                         node : DOM.oils_rpt_agg_filter_op_table,
778                         datatype : field.datatype
779                 }
780         );
781
782         DOM.oils_rpt_agg_filter_submit.onclick = function() {
783                 oilsAddRptHavingItem(
784                         path, tformPicker.getSelected(), filterPicker.getSelected());
785         }
786 }
787
788 /* draws the transform window */
789 function oilsRptDrawTransformWindow(path, col, cls, field) {
790         DOM.oils_rpt_tform_label_input.value = oilsRptMakeLabel(path);
791         var dtype = field.datatype;
792
793         var tformPicker = new oilsRptTformPicker( {     
794                         node : DOM.oils_rpt_tform_table,
795                         datatype : field.datatype,
796                         non_aggregate : true,
797                         aggregate : true
798                 }
799         );
800
801         DOM.oils_rpt_tform_submit.onclick = 
802                 function(){ 
803                         oilsAddRptDisplayItem(path, 
804                                 DOM.oils_rpt_tform_label_input.value, tformPicker.getSelected() );
805                 };
806
807         DOM.oils_rpt_tform_label_input.focus();
808         DOM.oils_rpt_tform_label_input.select();
809
810         _debug("Building transform window for datatype "+dtype);
811 }
812
813
814 //function oilsRptDrawOrderByWindow(path, col, cls, field) {
815 function oilsRptDrawOrderByWindow() {
816         var sel = DOM.oils_rpt_order_by_selector;
817         removeChildren(sel);
818         DOM.oils_rpt_order_by_submit.onclick = function() {
819                 oilsRptAddOrderBy(getSelectorVal(sel));
820         }
821
822         var cols = oilsRpt.def.select;
823         for( var i = 0; i < cols.length; i++ ) {
824                 var obj = cols[i];
825                 insertSelectorVal(sel, -1, obj.alias, obj.path);
826         }
827 }
828
829 function oilsRptAddOrderBy(path) {
830         var rel = hex_md5(oilsRptPathRel(path));
831         var order_by = oilsRpt.def.order_by;
832
833         /* if this item is already in the order by remove it and overwrite it */
834         order_by = grep(oilsRpt.def.order_by, 
835                 function(i) {return (i.path != path)});
836         
837         if(!order_by) order_by = [];
838
839         /* find the column definition in the select blob */
840         var obj = grep(oilsRpt.def.select,
841                 function(i) {return (i.path == path)});
842         
843         if(!obj) return;
844         obj = obj[0];
845         
846         order_by.push({ 
847                 relation : obj.relation, 
848                 column : obj.column,
849                 direction : getSelectorVal(DOM.oils_rpt_order_by_dir)
850         });
851
852         oilsRpt.def.order_by = order_by;
853         oilsRptDebug();
854 }
855
856
857