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