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