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