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) {
7 this.seedValue = args.value;
8 this.inputWidget = new args.inputWidget(args);
9 this.readonly = Boolean(args.readonly);
10 this.asyncInput = args.async;
11 this.dest = elem('select',
12 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
13 this.dest.disabled = this.readonly;
16 oilsRptSetWidget.prototype.draw = function() {
18 this.addButton = elem('input',{type:'submit',value:"Add"})
19 this.delButton = elem('input',{type:'submit',value:"Del"})
20 this.addButton.disabled = this.readonly;
21 this.delButton.disabled = this.readonly;
24 this.addButton.onclick = function() {
25 obj.addDisplayItems(obj.inputWidget.getDisplayValue());
26 if (obj.inputWidget instanceof oilsRptTextWidget) {
28 obj.inputWidget.dest.value = '';
32 this.delButton.onclick = function(){obj.removeSelected()};
34 removeChildren(this.node);
37 var post_draw = function() {
38 if (this_.seedValue && this_.seedValue.length) {
39 if (this_.inputWidget instanceof oilsRptTextWidget) {
40 // add each seed value to the input widget, then
41 // propagate the value into our multiselect.
42 // when done, clear the value from the text widget.
43 dojo.forEach(this_.seedValue, function(val) {
44 this_.inputWidget.dest.value = val;
45 this_.addButton.onclick();
47 this_.inputWidget.dest.value = '';
50 this_.addButton.onclick();
55 this.inputWidget.draw(null, post_draw);
56 this.node.appendChild(elem('br'))
57 this.node.appendChild(this.addButton);
58 this.node.appendChild(this.delButton);
59 this.node.appendChild(elem('br'))
60 this.node.appendChild(this.dest);
62 if (!this.asyncInput) post_draw();
66 oilsRptSetWidget.prototype.addDisplayItems = function(list) {
67 if( list.constructor != Array ) list = [list];
68 for(var i = 0; i < list.length; i++) {
73 iterate(this.dest.options,
74 function(o){if(o.getAttribute('value') == item.value) {exists = true; return;}});
77 _debug('Inserting SetWidget values ' + js2JSON(item));
78 insertSelectorVal(this.dest, -1, item.label, this.objToStr(item.value));
82 oilsRptSetWidget.prototype.removeSelected = function() {
83 oilsDelSelectedItems(this.dest);
86 oilsRptSetWidget.prototype.getValue = function() {
89 iterate(this.dest, function(i){vals.push(obj.strToObj(i.getAttribute('value')))});
93 oilsRptSetWidget.prototype.objToStr = function(obj) {
94 if( typeof obj == 'string' ) return obj;
95 //return ':'+obj.transform+':'+obj.params[0];
96 var str = ':'+obj.transform;
97 for( var i = 0; i < obj.params.length; i++ )
98 str += ':' + obj.params[i];
99 _debug("objToStr(): built string " + str);
104 oilsRptSetWidget.prototype.strToObj = function(str) {
105 if( str.match(/^:.*/) ) {
106 var parts = str.split(/:/);
107 _debug("strToObj(): " + str + ' : ' + parts);
109 var tform = parts.shift();
110 //var tform = str.replace(/^:(.*):.*/,'$1');
111 //var param = str.replace(/^:.*:(.*)/,'$1');
112 return { transform : tform, params : parts };
118 /* ---------------------------------------------------------------------
119 represents a widget that has start and end values. start and end
120 are gathered from start/end widgets
121 --------------------------------------------------------------------- */
122 function oilsRptBetweenWidget(args) {
123 this.node = args.node;
124 var seedValue = args.value;
125 if (seedValue) args.value = seedValue[0];
126 this.startWidget = new args.startWidget(args);
127 if (seedValue) args.value = seedValue[1];
128 this.endWidget = new args.endWidget(args);
130 oilsRptBetweenWidget.prototype.draw = function() {
131 removeChildren(this.node);
132 this.startWidget.draw();
133 this.node.appendChild(elem('hr'));
134 this.node.appendChild(elem('div',
135 {style:'text-align:center;width:100%;font-weight:bold'},' - And - '));
136 this.node.appendChild(elem('hr'));
137 this.endWidget.draw();
139 oilsRptBetweenWidget.prototype.getValue = function() {
141 this.startWidget.getValue(),
142 this.endWidget.getValue()
149 /* ---------------------------------------------------------------------
151 --------------------------------------------------------------------- */
154 /* ---------------------------------------------------------------------
155 Atomic text input widget
156 --------------------------------------------------------------------- */
157 function oilsRptTextWidget(args) {
158 this.node = args.node;
159 this.seedValue = args.value;
160 this.dest = elem('input',{type:'text',size:12});
161 this.dest.disabled = Boolean(args.readonly);
162 oilsRptMonitorWidget(this.dest);
164 oilsRptTextWidget.prototype.draw = function() {
165 this.node.appendChild(this.dest);
166 if (this.seedValue) {
167 this.dest.value = this.seedValue;
168 this.dest.onchange(); // validation
172 /* returns the "real" value for the widget */
173 oilsRptTextWidget.prototype.getValue = function() {
174 return this.dest.value;
177 /* returns the label and "real" value for the widget */
178 oilsRptTextWidget.prototype.getDisplayValue = function() {
179 return { label : this.getValue(), value : this.getValue() };
184 /* ---------------------------------------------------------------------
185 Atomic bool input widget
186 --------------------------------------------------------------------- */
187 function oilsRptBoolWidget(args) {
188 this.node = args.node;
189 this.seedValue = args.value;
190 this.selector = elem('select');
191 insertSelectorVal(this.selector, -1,'True','t');
192 insertSelectorVal(this.selector, -1,'False','f');
193 this.selector.disabled = Boolean(args.readonly);
196 oilsRptBoolWidget.prototype.draw = function() {
197 this.node.appendChild(this.selector);
199 setSelector(this.selector, this.seedValue);
202 /* returns the "real" value for the widget */
203 oilsRptBoolWidget.prototype.getValue = function() {
204 return getSelectorVal(this.selector);
207 /* returns the label and "real" value for the widget */
208 oilsRptBoolWidget.prototype.getDisplayValue = function() {
209 var val = getSelectorVal(this.selector);
211 if (val == 'f') labal = 'False';
212 return { label : label, value : val };
216 /* If you monitor a text widget with this function, it
217 will style the input differently to indicate the
218 field needs data. If a regex is provided, it will
219 style the field differently until the data matches
220 the regex. The style comes from OILS_RPT_INVALID_DATA. */
221 function oilsRptMonitorWidget(input, regex) {
222 addCSSClass(input, OILS_RPT_INVALID_DATA);
223 var func = function() {
224 var val = input.value;
226 addCSSClass(input, OILS_RPT_INVALID_DATA);
229 if( val && val.match(regex) )
230 removeCSSClass(input, OILS_RPT_INVALID_DATA);
232 addCSSClass(input, OILS_RPT_INVALID_DATA);
234 removeCSSClass(input, OILS_RPT_INVALID_DATA);
239 input.onkeyup = func;
240 input.onchange = func;
246 /* ---------------------------------------------------------------------
247 Atomic calendar widget
248 --------------------------------------------------------------------- */
249 function oilsRptCalWidget(args) {
250 this.node = args.node;
251 this.calFormat = args.calFormat;
252 this.input = elem('input',{type:'text',size:12});
253 this.seedValue = args.value;
254 this.input.disabled = Boolean(args.readonly);
256 oilsRptMonitorWidget(this.input, args.regex);
258 if( args.inputSize ) {
259 this.input.setAttribute('size',args.inputSize);
260 this.input.setAttribute('maxlength',args.inputSize);
264 oilsRptCalWidget.prototype.draw = function() {
265 this.button = DOM.generic_calendar_button.cloneNode(true);
266 this.button.id = oilsNextId();
267 this.input.id = oilsNextId();
269 this.node.appendChild(this.button);
270 this.node.appendChild(this.input);
271 unHideMe(this.button);
273 _debug('making calendar widget with format ' + this.calFormat);
276 inputField : this.input.id,
277 ifFormat : this.calFormat,
278 button : this.button.id,
283 if (this.seedValue) {
284 this.input.value = this.seedValue;
285 this.input.onchange(); // validation
289 oilsRptCalWidget.prototype.getValue = function() {
290 return this.input.value;
293 oilsRptCalWidget.prototype.getDisplayValue = function() {
294 return { label : this.getValue(), value : this.getValue() };
298 /* ---------------------------------------------------------------------
300 --------------------------------------------------------------------- */
301 function oilsRptOrgSelector(args) {
302 this.node = args.node;
303 this.seedValue = args.value;
304 this.selector = elem('select',
305 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
306 this.selector.disabled = Boolean(args.readonly);
309 oilsRptOrgSelector.prototype.draw = function(org) {
310 if(!org) org = globalOrgTree;
311 var opt = insertSelectorVal( this.selector, -1,
312 org.shortname(), org.id(), null, findOrgDepth(org) );
313 if( org.id() == oilsRptCurrentOrg && !this.seedValue)
316 /* sometimes we need these choices
317 if( !isTrue(findOrgType(org.ou_type()).can_have_vols()) )
321 if( org.children() ) {
322 for( var c = 0; c < org.children().length; c++ )
323 this.draw(org.children()[c]);
325 this.node.appendChild(this.selector);
327 if (this.seedValue) {
328 if (dojo.isArray(this.seedValue)) {
329 for (var i = 0; i < this.selector.options.length; i++) {
330 var opt = this.selector.options[i];
331 if (this.seedValue.indexOf(opt.value) > -1)
335 setSelector(this.selector, this.seedValue);
340 oilsRptOrgSelector.prototype.getValue = function() {
342 iterate(this.selector, /* XXX this.selector.options?? */
345 vals.push(o.getAttribute('value'))
351 oilsRptOrgSelector.prototype.getDisplayValue = function() {
353 iterate(this.selector,
356 vals.push({ label : o.innerHTML, value : o.getAttribute('value')});
363 /* ---------------------------------------------------------------------
365 --------------------------------------------------------------------- */
366 function oilsRptAgeWidget(args) {
367 this.node = args.node;
368 this.seedValue = args.value;
369 this.count = elem('select');
370 this.type = elem('select');
371 this.count.disabled = Boolean(args.readonly);
372 this.type.disabled = Boolean(args.readonly);
375 oilsRptAgeWidget.prototype.draw = function() {
377 //insertSelectorVal(this.count, -1, ' -- Select One -- ', '');
378 for( var i = 1; i < 25; i++ )
379 insertSelectorVal(this.count, -1, i, i);
381 //insertSelectorVal(this.type, -1, ' -- Select One -- ', '');
382 insertSelectorVal(this.type, -1, rpt_strings.WIDGET_DAYS, 'days');
383 insertSelectorVal(this.type, -1, rpt_strings.WIDGET_MONTHS, 'months');
384 insertSelectorVal(this.type, -1, rpt_strings.WIDGET_YEARS, 'years');
385 this.node.appendChild(this.count);
386 this.node.appendChild(this.type);
388 if (this.seedValue) {
390 var count = this.seedValue.match(/(\d+)([^\d]+)/)[1];
391 var type = this.seedValue.match(/(\d+)([^\d]+)/)[2];
392 setSelector(this.count, count);
393 setSelector(this.type, type);
397 oilsRptAgeWidget.prototype.getValue = function() {
398 var count = getSelectorVal(this.count);
399 var type = getSelectorVal(this.type);
400 return count+''+type;
403 oilsRptAgeWidget.prototype.getDisplayValue = function() {
404 var val = { value : this.getValue() };
405 var label = getSelectorVal(this.count) + ' ';
406 for( var i = 0; i < this.type.options.length; i++ ) {
407 var opt = this.type.options[i];
409 label += opt.innerHTML;
417 /* ---------------------------------------------------------------------
418 Atomic substring picker
419 --------------------------------------------------------------------- */
420 function oilsRptSubstrWidget(args) {
421 this.node = args.node
422 this.seedValue = args.value;
423 this.data = elem('input',{type:'text',size:12})
424 this.offset = elem('input',{type:'text',size:5})
425 this.length = elem('input',{type:'text',size:5})
426 this.offset.disabled = Boolean(args.readonly);
427 this.length.disabled = Boolean(args.readonly);
430 oilsRptSubstrWidget.prototype.draw = function() {
431 this.node.appendChild(text('string: '))
432 this.node.appendChild(this.data);
433 this.node.appendChild(elem('br'));
434 this.node.appendChild(text('offset: '))
435 this.node.appendChild(this.offset);
436 this.node.appendChild(elem('br'));
437 this.node.appendChild(text('length: '))
438 this.node.appendChild(this.length);
440 if (this.seedValue) {
441 // TODO: unested; substring currently not supported.
442 this.data.value = this.seedValue[0];
443 this.offset.value = this.seedValue[1];
444 this.length.value = this.seedValue[2];
448 oilsRptSubstrWidget.prototype.getValue = function() {
450 transform : 'substring',
451 params : [ this.data.value, this.offset.value, this.length.value ]
455 oilsRptSubstrWidget.prototype.getDisplayValue = function() {
457 label : this.data.value + ' : ' + this.offset.value + ' : ' + this.length.value,
458 value : this.getValue()
463 /* ---------------------------------------------------------------------
465 --------------------------------------------------------------------- */
466 function oilsRptNumberWidget(args) {
467 this.node = args.node;
468 this.seedValue = args.value;
469 this.size = args.size || 32;
470 this.start = args.start;
471 this.selector = elem('select');
472 this.selector.disabled = Boolean(args.readonly);
474 oilsRptNumberWidget.prototype.draw = function() {
475 //insertSelectorVal(this.selector, -1, ' -- Select One -- ', '');
476 for( var i = this.start; i < (this.size + this.start); i++ )
477 insertSelectorVal(this.selector, -1, i, i);
478 this.node.appendChild(this.selector);
482 setSelector(this.selector, this.seedValue);
485 oilsRptNumberWidget.prototype.getValue = function() {
486 return getSelectorVal(this.selector);
489 oilsRptNumberWidget.prototype.getDisplayValue = function() {
490 return { label : this.getValue(), value : this.getValue() };
493 function oilsRptNullWidget(args) {
494 this.node = args.node;
495 this.type = args.type;
497 oilsRptNullWidget.prototype.draw = function() {}
498 oilsRptNullWidget.prototype.getValue = function() {
502 function oilsRptTemplateWidget(args) {
503 this.node = args.node;
504 this.value = args.value;
506 oilsRptTemplateWidget.prototype.draw = function() {
507 this.node.appendChild(text(''+this.value));
510 /* ---------------------------------------------------------------------
511 Relative dates widget
512 -------------------------------------------------------------------- */
513 function oilsRptTruncPicker(args) {
514 this.node = args.node;
515 this.type = args.type;
516 this.seedValue = args.value;
517 this.realSpan = elem('span');
518 this.relSpan = elem('span');
519 hideMe(this.relSpan);
520 args.node = this.realSpan;
521 this.calWidget = new oilsRptCalWidget(args);
522 args.node = this.node;
524 this.selector = elem('select');
525 insertSelectorVal(this.selector,-1,rpt_strings.WIDGET_REAL_DATE,1);
526 insertSelectorVal(this.selector,-1,rpt_strings.WIDGET_RELATIVE_DATE,2);
527 this.selector.disabled = Boolean(args.readonly);
530 new oilsRptNumberWidget(
531 {node:this.relSpan,size:90,start:1,readonly:args.readonly});
533 this.label = 'Day(s)';
534 if(this.type == 'month') this.label = rpt_strings.WIDGET_MONTHS;
535 if(this.type == 'quarter') this.label = rpt_strings.WIDGET_QUARTERS;
536 if(this.type == 'year') this.label = rpt_strings.WIDGET_YEARS;
537 if(this.type == 'date') this.label = rpt_strings.WIDGET_DAYS;
540 oilsRptTruncPicker.prototype.draw = function() {
541 this.node.appendChild(this.selector);
542 this.node.appendChild(this.realSpan);
543 this.node.appendChild(this.relSpan);
544 this.calWidget.draw();
545 this.numberPicker.draw();
546 this.relSpan.appendChild(text(this.label+' ago'));
549 this.selector.onchange = function() {
550 if( getSelectorVal(obj.selector) == 1 ) {
551 unHideMe(obj.realSpan);
554 unHideMe(obj.relSpan);
555 hideMe(obj.realSpan);
559 if (seed = this.seedValue) {
560 if (typeof seed == 'string') {
561 this.calWidget.value = seed;
563 // relative date transform
564 if (seed.transform.match(/relative/)) {
565 setSelector(this.selector, 2)
566 setSelector(this.numberPicker.selector,
567 Math.abs(seed.params[0]));
568 unHideMe(this.relSpan);
569 hideMe(this.realSpan);
575 oilsRptTruncPicker.prototype.getValue = function() {
576 if( getSelectorVal(this.selector) == 2) {
577 var val = this.numberPicker.getValue();
578 var tform = 'relative_' + this.type;
579 return { transform : tform, params : ['-'+val] };
581 return this.calWidget.getValue();
584 oilsRptTruncPicker.prototype.getDisplayValue = function() {
585 if( getSelectorVal(this.selector) == 2) {
586 var num = this.numberPicker.getValue();
587 return { label : num +' '+this.label+' ago', value : this.getValue() };
589 return this.calWidget.getDisplayValue();
593 /* ---------------------------------------------------------------------
594 Atomic remote object picker
595 --------------------------------------------------------------------- */
597 function oilsRptRemoteWidget(args) {
598 this.node = args.node;
599 this.class = args.class;
600 this.field = args.field;
601 this.column = args.column;
602 this.seedValue = args.value;
603 this.source = elem('select',
604 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
605 this.source.disabled = Boolean(args.readonly);
608 // selected is unused
609 oilsRptRemoteWidget.prototype.draw = function(selected, callback) {
611 iterate(oilsIDL[this.class].fields,
613 if(i.type == 'link' && i.class == 'aou')
618 if(orgcol) _debug("found org column for remote widget: " + orgcol);
621 iterate(oilsRptMyOrgs,function(i){orgs.push(i.id());});
622 var req = new Request(OILS_RPT_MAGIC_FETCH, SESSION, {
629 this.node.appendChild(this.source);
630 req.callback(function(r){
631 // render selects values from seed data if necessary
632 obj.render(r.getResultObject());
634 // presence of a callback suggests there is a container widget
635 // (e.g. SetWidget) for tracking our values. Callback lets
636 // the container extract the selected values, then we deselect
637 // in the input widget (us) since it's redundant.
639 dojo.forEach(obj.source.options, function(o) {
647 oilsRptRemoteWidget.prototype.render = function(objs) {
648 var selector = this.field.selector;
651 if (a[selector]() > b[selector]())
656 for( var i = 0; i < objs.length; i++ ) {
658 var label = obj[this.field.selector]();
659 var value = obj[this.column]();
660 _debug("inserted remote object "+label + ' : ' + value);
661 var opt = insertSelectorVal(this.source, -1, label, value);
662 if (this.seedValue && (
663 this.seedValue.indexOf(Number(value)) > -1
664 || this.seedValue.indexOf(''+value) > -1
671 oilsRptRemoteWidget.prototype.getDisplayValue = function() {
676 vals.push({ label : o.innerHTML, value : o.getAttribute('value')});
682 oilsRptRemoteWidget.prototype.getValue = function() {
687 vals.push(o.getAttribute('value'))
696 /* ---------------------------------------------------------------------
698 --------------------------------------------------------------------- */
700 /* ---------------------------------------------------------------------
701 custom my-orgs picker
702 --------------------------------------------------------------------- */
703 function oilsRptMyOrgsWidget(node, orgid, maxorg) {
704 _debug('fetching my orgs with max org of ' + maxorg);
707 this.maxorg = maxorg || 1;
710 this.node.disabled = true;
715 oilsRptMyOrgsWidget.prototype.draw = function() {
717 var req = new Request(OILS_RPT_FETCH_ORG_FULL_PATH, this.orgid);
720 function(r) { obj.drawWidget(r.getResultObject()); }
724 this.drawWidget(oilsRptMyOrgs);
728 oilsRptMyOrgsWidget.prototype.drawWidget = function(orglist) {
731 oilsRptMyOrgs = orglist;
732 for( var i = 0; i < orglist.length; i++ ) {
733 var org = orglist[i];
734 var opt = insertSelectorVal( this.node, -1,
735 org.name(), org.id(), null, findOrgDepth(org) );
736 if( org.id() == this.orgid )
739 if( org.id() == this.maxorg )
741 else opt.disabled = true;
746 oilsRptMyOrgsWidget.prototype.getValue = function() {
747 return getSelectorVal(this.node);