]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/reports/oils_rpt_widget.js
changed name to .xml since the file must be valid xml for mod_xmlent to eat it
[Evergreen.git] / Open-ILS / web / reports / oils_rpt_widget.js
1 /* --------------------------------------------------------------------- 
2         Represents a set of values, an inputWidget collects data and a 
3         multi-select displays the data and allows the user to remove items
4         --------------------------------------------------------------------- */
5 function oilsRptSetWidget(args) {
6         this.node = args.node;
7         this.inputWidget = new args.inputWidget(args);
8         this.dest = elem('select',
9                 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
10 }
11
12 oilsRptSetWidget.prototype.draw = function() {
13
14         this.addButton = elem('input',{type:'submit',value:"Add"})
15         this.delButton = elem('input',{type:'submit',value:"Del"})
16
17         var obj = this;
18         this.addButton.onclick = function() {
19                 obj.addDisplayItems(obj.inputWidget.getDisplayValue());
20         }
21
22         this.delButton.onclick = function(){obj.removeSelected()};
23
24         removeChildren(this.node);
25         this.inputWidget.draw();
26         this.node.appendChild(elem('br'))
27         this.node.appendChild(this.addButton);
28         this.node.appendChild(this.delButton);
29         this.node.appendChild(elem('br'))
30         this.node.appendChild(this.dest);
31 }
32
33 oilsRptSetWidget.prototype.addDisplayItems = function(list) {
34         if( list.constructor != Array ) list = [list];
35         for(var i = 0; i < list.length; i++) {
36                 var item = list[i];
37
38                 /* no dupes */
39                 var exists = false;
40                 iterate(this.dest.options, 
41                         function(o){if(o.getAttribute('value') == item.value) {exists = true; return;}});
42                 if(exists) continue;
43
44                 _debug('Inserting SetWidget values ' + js2JSON(item));
45                 insertSelectorVal(this.dest, -1, item.label, this.objToStr(item.value));
46         }
47 }
48
49 oilsRptSetWidget.prototype.removeSelected = function() {
50         oilsDelSelectedItems(this.dest);
51 }
52
53 oilsRptSetWidget.prototype.getValue = function() {
54         var vals = [];
55         var obj = this;
56         iterate(this.dest, function(i){vals.push(obj.strToObj(i.getAttribute('value')))});
57         return vals;
58 }
59
60 oilsRptSetWidget.prototype.objToStr = function(obj) {
61         if( typeof obj == 'string' ) return obj;
62         //return ':'+obj.transform+':'+obj.params[0];
63         var str = ':'+obj.transform;
64         for( var i = 0; i < obj.params.length; i++ ) 
65                 str += ':' + obj.params[i];
66         _debug("objToStr(): built string " + str);
67         return str;
68
69 }
70
71 oilsRptSetWidget.prototype.strToObj = function(str) {
72         if( str.match(/^:.*/) ) {
73                 var parts = str.split(/:/);
74                 _debug("strToObj(): " + str + ' : ' + parts);
75                 parts.shift();
76                 var tform = parts.shift();
77                 //var tform = str.replace(/^:(.*):.*/,'$1');
78                 //var param = str.replace(/^:.*:(.*)/,'$1');
79                 return { transform : tform, params : parts };
80         }
81         return str;
82 }
83
84
85 /* --------------------------------------------------------------------- 
86         represents a widget that has start and end values.  start and end
87         are gathered from start/end widgets
88         --------------------------------------------------------------------- */
89 function oilsRptBetweenWidget(args) {
90         this.node = args.node;
91         this.startWidget = new args.startWidget(args);
92         this.endWidget = new args.endWidget(args);
93 }
94 oilsRptBetweenWidget.prototype.draw = function() {
95         removeChildren(this.node);
96         this.startWidget.draw();
97         this.node.appendChild(elem('hr'));
98         this.node.appendChild(elem('div',
99                 {style:'text-align:center;width:100%;font-weight:bold'},' - And - '));
100         this.node.appendChild(elem('hr'));
101         this.endWidget.draw();
102 }
103 oilsRptBetweenWidget.prototype.getValue = function() {
104         return [
105                 this.startWidget.getValue(),
106                 this.endWidget.getValue()
107         ];
108 }
109
110
111
112
113 /* --------------------------------------------------------------------- 
114         ATOMIC WIDGETS
115         --------------------------------------------------------------------- */
116
117
118 /* --------------------------------------------------------------------- 
119         Atomic text input widget
120         --------------------------------------------------------------------- */
121 function oilsRptTextWidget(args) {
122         this.node = args.node;
123         this.dest = elem('input',{type:'text',size:12});
124         oilsRptMonitorWidget(this.dest);
125 }
126 oilsRptTextWidget.prototype.draw = function() {
127         this.node.appendChild(this.dest);
128 }
129
130 /* returns the "real" value for the widget */
131 oilsRptTextWidget.prototype.getValue = function() {
132         return this.dest.value;
133 }
134
135 /* returns the label and "real" value for the widget */
136 oilsRptTextWidget.prototype.getDisplayValue = function() {
137         return { label : this.getValue(), value : this.getValue() };
138 }
139
140
141
142 /* --------------------------------------------------------------------- 
143         Atomic bool input widget
144         --------------------------------------------------------------------- */
145 function oilsRptBoolWidget(args) {
146         this.node = args.node;
147         this.selector = elem('select');
148         insertSelectorVal(this.selector, -1,'True','t');
149         insertSelectorVal(this.selector, -1,'False','f');
150 }
151
152 oilsRptBoolWidget.prototype.draw = function() {
153         this.node.appendChild(this.selector);
154 }
155
156 /* returns the "real" value for the widget */
157 oilsRptBoolWidget.prototype.getValue = function() {
158         return getSelectorVal(this.selector);
159 }
160
161 /* returns the label and "real" value for the widget */
162 oilsRptBoolWidget.prototype.getDisplayValue = function() {
163         var val = getSelectorVal(this.selector);
164         var label = 'True';
165         if (val == 'f') labal = 'False';
166         return { label : label, value : val };
167 }
168
169
170 /* If you monitor a text widget with this function, it 
171         will style the input differently to indicate the
172         field needs data.  If a regex is provided, it will
173         style the field differently until the data matches 
174         the regex.  The style comes from OILS_RPT_INVALID_DATA. */
175 function oilsRptMonitorWidget(input, regex) {
176         addCSSClass(input, OILS_RPT_INVALID_DATA);
177         var func = function() {
178                 var val = input.value;
179                 if(!val) {
180                         addCSSClass(input, OILS_RPT_INVALID_DATA);
181                 } else {
182                         if( regex ) {
183                                 if( val && val.match(regex) ) 
184                                         removeCSSClass(input, OILS_RPT_INVALID_DATA);
185                                 else
186                                         addCSSClass(input, OILS_RPT_INVALID_DATA);
187                         } else {
188                                 removeCSSClass(input, OILS_RPT_INVALID_DATA);
189                         }
190                 }
191         }
192
193         input.onkeyup = func;
194         input.onchange = func;
195 }
196
197
198
199
200 /* --------------------------------------------------------------------- 
201         Atomic calendar widget
202         --------------------------------------------------------------------- */
203 function oilsRptCalWidget(args) {
204         this.node = args.node;
205         this.calFormat = args.calFormat;
206         this.input = elem('input',{type:'text',size:12});
207
208         oilsRptMonitorWidget(this.input, args.regex);
209
210         if( args.inputSize ) {
211                 this.input.setAttribute('size',args.inputSize);
212                 this.input.setAttribute('maxlength',args.inputSize);
213         }
214 }
215
216 oilsRptCalWidget.prototype.draw = function() {
217         this.button = DOM.generic_calendar_button.cloneNode(true);
218         this.button.id = oilsNextId();
219         this.input.id = oilsNextId();
220
221         this.node.appendChild(this.button);
222         this.node.appendChild(this.input);
223         unHideMe(this.button);
224
225         _debug('making calendar widget with format ' + this.calFormat);
226
227         Calendar.setup({
228                 inputField      : this.input.id,
229                 ifFormat                : this.calFormat,
230                 button          : this.button.id,
231                 align                   : "Tl", 
232                 singleClick     : true
233         });
234 }
235
236 oilsRptCalWidget.prototype.getValue = function() {
237         return this.input.value;
238 }
239
240 oilsRptCalWidget.prototype.getDisplayValue = function() {
241         return { label : this.getValue(), value : this.getValue() };
242 }
243
244
245 /* --------------------------------------------------------------------- 
246         Atomic org widget
247         --------------------------------------------------------------------- */
248 function oilsRptOrgSelector(args) {
249         this.node = args.node;
250         this.selector = elem('select',
251                 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
252 }
253
254 oilsRptOrgSelector.prototype.draw = function(org) {
255         if(!org) org = globalOrgTree;
256         var opt = insertSelectorVal( this.selector, -1, 
257                 org.shortname(), org.id(), null, findOrgDepth(org) );
258         if( org.id() == oilsRptCurrentOrg )
259                 opt.selected = true;
260         
261         /* sometimes we need these choices 
262         if( !isTrue(findOrgType(org.ou_type()).can_have_vols()) )
263                 opt.disabled = true;
264                 */
265
266         if( org.children() ) {
267                 for( var c = 0; c < org.children().length; c++ )
268                         this.draw(org.children()[c]);
269         }
270         this.node.appendChild(this.selector);
271 }
272
273 oilsRptOrgSelector.prototype.getValue = function() {
274         var vals = [];
275         iterate(this.selector, /* XXX this.selector.options?? */
276                 function(o){
277                         if( o.selected )
278                                 vals.push(o.getAttribute('value'))
279                 }
280         );
281         return vals;
282 }
283
284 oilsRptOrgSelector.prototype.getDisplayValue = function() {
285         var vals = [];
286         iterate(this.selector,
287                 function(o){
288                         if( o.selected )
289                                 vals.push({ label : o.innerHTML, value : o.getAttribute('value')});
290                 }
291         );
292         return vals;
293 }
294
295
296 /* --------------------------------------------------------------------- 
297         Atomic age widget
298         --------------------------------------------------------------------- */
299 function oilsRptAgeWidget(args) {
300         this.node = args.node;
301         this.count = elem('select');
302         this.type = elem('select');
303 }
304
305 oilsRptAgeWidget.prototype.draw = function() {
306
307         //insertSelectorVal(this.count, -1, ' -- Select One -- ', '');
308         for( var i = 1; i < 25; i++ )
309                 insertSelectorVal(this.count, -1, i, i);
310
311         //insertSelectorVal(this.type, -1, ' -- Select One -- ', '');
312         insertSelectorVal(this.type, -1, 'Day(s)', 'days');
313         insertSelectorVal(this.type, -1, 'Month(s)', 'months');
314         insertSelectorVal(this.type, -1, 'Year(s)', 'years');
315         this.node.appendChild(this.count);
316         this.node.appendChild(this.type);
317 }
318
319 oilsRptAgeWidget.prototype.getValue = function() {
320         var count = getSelectorVal(this.count);
321         var type = getSelectorVal(this.type);
322         return count+''+type;
323 }
324
325 oilsRptAgeWidget.prototype.getDisplayValue = function() {
326         var val = { value : this.getValue() };
327         var label = getSelectorVal(this.count) + ' ';
328         for( var i = 0; i < this.type.options.length; i++ ) {
329                 var opt = this.type.options[i];
330                 if( opt.selected )
331                         label += opt.innerHTML;
332         }
333         val.label = label;
334         return val;
335 }
336
337
338
339 /* --------------------------------------------------------------------- 
340         Atomic substring picker
341         --------------------------------------------------------------------- */
342 function oilsRptSubstrWidget(args) {
343         this.node = args.node
344         this.data = elem('input',{type:'text',size:12})
345         this.offset = elem('input',{type:'text',size:5})
346         this.length = elem('input',{type:'text',size:5})
347 }
348
349 oilsRptSubstrWidget.prototype.draw = function() {
350         this.node.appendChild(text('string: '))
351         this.node.appendChild(this.data);
352         this.node.appendChild(elem('br'));
353         this.node.appendChild(text('offset: '))
354         this.node.appendChild(this.offset);
355         this.node.appendChild(elem('br'));
356         this.node.appendChild(text('length: '))
357         this.node.appendChild(this.length);
358 }
359
360 oilsRptSubstrWidget.prototype.getValue = function() {
361         return {
362                 transform : 'substring',
363                 params : [ this.data.value, this.offset.value, this.length.value ]
364         };
365 }
366
367 oilsRptSubstrWidget.prototype.getDisplayValue = function() {
368         return {
369                 label : this.data.value + ' : ' + this.offset.value + ' : ' + this.length.value,
370                 value : this.getValue()
371         };
372 }
373
374
375 /* --------------------------------------------------------------------- 
376         Atomic number picker
377         --------------------------------------------------------------------- */
378 function oilsRptNumberWidget(args) {
379         this.node = args.node;
380         this.size = args.size || 32;
381         this.start = args.start;
382         this.selector = elem('select');
383 }
384 oilsRptNumberWidget.prototype.draw = function() {
385         //insertSelectorVal(this.selector, -1, ' -- Select One -- ', '');
386         for( var i = this.start; i < (this.size + this.start); i++ )
387                 insertSelectorVal(this.selector, -1, i, i);
388         this.node.appendChild(this.selector);
389         var obj = this;
390 }
391
392 oilsRptNumberWidget.prototype.getValue = function() {
393         return getSelectorVal(this.selector);
394 }
395
396 oilsRptNumberWidget.prototype.getDisplayValue = function() {
397         return { label : this.getValue(), value : this.getValue() };
398 }
399
400
401 /* --------------------------------------------------------------------- 
402         Relative dates widget
403         -------------------------------------------------------------------- */
404
405 function oilsRptNullWidget(args) {
406     this.node = args.node;
407     this.type = args.type;
408 }
409 oilsRptNullWidget.prototype.draw = function() {}
410 oilsRptNullWidget.prototype.getValue = function() {
411     return null;
412 }
413
414 function oilsRptTemplateWidget(args) {
415     this.node = args.node;
416     this.value = args.value;
417 }
418 oilsRptTemplateWidget.prototype.draw = function() {
419     this.node.appendChild(text(''+this.value));
420 }
421
422 /* --------------------------------------------------------------------- 
423         Relative dates widget
424         -------------------------------------------------------------------- */
425 function oilsRptTruncPicker(args) {
426         this.node = args.node;
427         this.type = args.type;
428         this.realSpan = elem('span');
429         this.relSpan = elem('span');
430         hideMe(this.relSpan);
431         args.node = this.realSpan;
432         this.calWidget = new oilsRptCalWidget(args);
433         args.node = this.node;
434
435         this.selector = elem('select');
436         insertSelectorVal(this.selector,-1,'Real Date',1);
437         insertSelectorVal(this.selector,-1,'Relative Date',2);
438
439         this.numberPicker = 
440                 new oilsRptNumberWidget({node:this.relSpan,size:90,start:1});
441
442         this.label = 'Day(s)';
443         if(this.type == 'month') this.label = 'Month(s)';
444         if(this.type == 'quarter') this.label = 'Quarter(s)';
445         if(this.type == 'year') this.label = 'Year(s)';
446         if(this.type == 'date') this.label = 'Day(s)';
447 }
448
449 oilsRptTruncPicker.prototype.draw = function() {
450         this.node.appendChild(this.selector);
451         this.node.appendChild(this.realSpan);
452         this.node.appendChild(this.relSpan);
453         this.calWidget.draw();
454         this.numberPicker.draw();
455         this.relSpan.appendChild(text(this.label+' ago'));
456
457         var obj = this;
458         this.selector.onchange = function() {
459                 if( getSelectorVal(obj.selector) == 1 ) {
460                         unHideMe(obj.realSpan);
461                         hideMe(obj.relSpan);
462                 } else {
463                         unHideMe(obj.relSpan);
464                         hideMe(obj.realSpan);
465                 }
466         }
467 }
468
469 oilsRptTruncPicker.prototype.getValue = function() {
470         if( getSelectorVal(this.selector) == 2) {
471                 var val = this.numberPicker.getValue();
472                 var tform = 'relative_' + this.type;
473                 return { transform : tform, params : ['-'+val] };
474         }
475         return this.calWidget.getValue();
476 }
477
478 oilsRptTruncPicker.prototype.getDisplayValue = function() {
479         if( getSelectorVal(this.selector) == 2) {
480                 var num = this.numberPicker.getValue();
481                 return { label : num +' '+this.label+' ago', value : this.getValue() };
482         }
483         return this.calWidget.getDisplayValue();
484 }
485
486
487 /* --------------------------------------------------------------------- 
488         Atomic remote object picker
489         --------------------------------------------------------------------- */
490
491 function oilsRptRemoteWidget(args) {
492         this.node       = args.node;
493         this.class      = args.class;
494         this.field      = args.field;
495         this.column = args.column;
496         this.source = elem('select',
497                 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
498 }
499
500 oilsRptRemoteWidget.prototype.draw = function() {
501         var orgcol;
502         iterate(oilsIDL[this.class].fields,
503                 function(i) {
504                         if(i.type == 'link' && i.class == 'aou') 
505                                 orgcol = i.name;
506                 }
507         );
508
509         if(orgcol) _debug("found org column for remote widget: " + orgcol);
510
511         var orgs = [];
512         iterate(oilsRptMyOrgs,function(i){orgs.push(i.id());});
513         var req = new Request(OILS_RPT_MAGIC_FETCH, SESSION, {
514                 hint:this.class,
515                 org_column : orgcol,
516                 org : orgs
517         }); 
518
519         var obj = this;
520         this.node.appendChild(this.source);
521         req.callback(function(r){obj.render(r.getResultObject())});
522         req.send();
523 }
524
525 oilsRptRemoteWidget.prototype.render = function(objs) {
526         for( var i = 0; i < objs.length; i++ ) {
527                 var obj = objs[i];
528                 var label = obj[this.field.selector]();
529                 var value = obj[this.column]();
530                 _debug("inserted remote object "+label + ' : ' + value);
531                 insertSelectorVal(this.source, -1, label, value);
532         }
533 }
534
535 oilsRptRemoteWidget.prototype.getDisplayValue = function() {
536         var vals = [];
537         iterate(this.source,
538                 function(o){
539                         if( o.selected )
540                                 vals.push({ label : o.innerHTML, value : o.getAttribute('value')});
541                 }
542         );
543         return vals;
544 }
545
546 oilsRptRemoteWidget.prototype.getValue = function() {
547         var vals = [];
548         iterate(this.source,
549                 function(o){
550                         if( o.selected )
551                                 vals.push(o.getAttribute('value'))
552                 }
553         );
554         return vals;
555 }
556
557
558
559
560 /* --------------------------------------------------------------------- 
561         CUSTOM WIDGETS
562         --------------------------------------------------------------------- */
563
564 /* --------------------------------------------------------------------- 
565         custom my-orgs picker 
566         --------------------------------------------------------------------- */
567 function oilsRptMyOrgsWidget(node, orgid, maxorg) {
568         _debug('fetching my orgs with max org of ' + maxorg);
569         this.node = node;
570         this.orgid = orgid;
571         this.maxorg = maxorg || 1;
572         this.active = true;
573         if( maxorg < 1 ) {
574                 this.node.disabled = true;
575                 this.active = false;
576         }
577 }
578
579 oilsRptMyOrgsWidget.prototype.draw = function() {
580         if(!oilsRptMyOrgs) {
581                 var req = new Request(OILS_RPT_FETCH_ORG_FULL_PATH, this.orgid);
582                 var obj = this;
583                 req.callback(
584                         function(r) { obj.drawWidget(r.getResultObject()); }
585                 );
586                 req.send();
587         } else {
588                 this.drawWidget(oilsRptMyOrgs);
589         }
590 }
591
592 oilsRptMyOrgsWidget.prototype.drawWidget = function(orglist) {
593         var sel = this.node;
594         var started = false;
595         oilsRptMyOrgs = orglist;
596         for( var i = 0; i < orglist.length; i++ ) {
597                 var org = orglist[i];
598                 var opt = insertSelectorVal( this.node, -1, 
599                         org.name(), org.id(), null, findOrgDepth(org) );
600                 if( org.id() == this.orgid )
601                         opt.selected = true;
602                 if(!started) {
603                         if( org.id() == this.maxorg ) 
604                                 started = true;
605                         else opt.disabled = true;
606                 }
607         }
608 }
609
610 oilsRptMyOrgsWidget.prototype.getValue = function() {
611         return getSelectorVal(this.node);
612 }
613
614