function formatNumber(number) { let n = number || 0; var l = n.length, m = l % 3, c = (l - m) / 3, v = ((m > 0) ? n.substr(0, m) : ''), z; for (z=0;z<c;z++) { if (v != "") v += ','; v += n.substr(m+(z*3), 3); } return v; } //-------------------------------------------------------------------------------------- // ARRAY EXTENSION //-------------------------------------------------------------------------------------- Array_search = function (value) { var found=null; if (value != null) for (var i in this) { if (this[i]==value) { found=i; break; } } return found; } //-------------------------------------------------------------------------------------- // HASHTABLE IMPLEMENTATION //-------------------------------------------------------------------------------------- function Hashtable() { this.clear = Hashtable_clear; this.containsKey = Hashtable_containsKey; this.containsValue = Hashtable_containsValue; this.get = Hashtable_get; this.isEmpty = Hashtable_isEmpty; this.keys = Hashtable_keys; this.put = Hashtable_put; this.remove = Hashtable_remove; this.size = Hashtable_size; this.toString = Hashtable_toString; this.values = Hashtable_values; this.hashtable = new Array(); } function Hashtable_clear() { this.hashtable = new Array(); } function Hashtable_get(key) { return this.hashtable[key]; } function Hashtable_isEmpty() { return (parseInt(this.size())==0) ? true:false; } function Hashtable_containsKey(key) { var exists=false; for (var i in this.hashtable) { if (i==key&&this.hashtable[i]!=null) { exists=true; break; } } return exists; } function Hashtable_containsValue(value) { var contains=false; if (value!=null) for (var i in this.hashtable) { if (this.hashtable[i]==value) { contains=true; break; } } return contains; } function Hashtable_keys() { var keys=new Array(); for (var i in this.hashtable) { if(this.hashtable[i]!=null) keys.push(i); } return keys; } function Hashtable_put(key,value) { if (key==null||value==null) throw "NullPointerException {"+key+"},{"+value+"}"; else this.hashtable[key]=value; } function Hashtable_remove(key) { var rtn=this.hashtable[key]; this.hashtable[key]=null; return rtn; } function Hashtable_size() { var size=0; for (var i in this.hashtable) { if (this.hashtable[i]!=null) size++; } return size; } function Hashtable_toString() { var result=""; for (var i in this.hashtable) { if (this.hashtable[i]!=null) result+="{"+i+"},{"+this.hashtable[i]+"}\n"; } return result; } function Hashtable_values() { var values=new Array(); for (var i in this.hashtable) { if (this.hashtable[i]!=null) values.push(this.hashtable[i]); } return values; } //---------------------------------------------------------------------------------------------- // COMPONENTS //---------------------------------------------------------------------------------------------- Component = function(isBlock) { if (typeof isBlock == "undefined") return; this.id = ++Component.lId; Component.list[this.id] = this; this.slots = new Hashtable(); this.events = new Hashtable(); this.children = new Hashtable(); this.visible = false; this.isBlock = isBlock; this.newSlot('show'); this.newSlot('hide'); this.newSlot('drawAll'); this.newSlot('draw'); this.newEvent('Show', true); this.newEvent('Hide', true); this.bindEvent('Show','drawAll'); } Component.list = new Array(); Component.lId = -1; Component.prototype.setVisible = function(v) { this.visible=v; var i,k=this.children.keys(); for (i=0;i<k.length;i++) this.children.get(k[i]).setVisible(v); } Component.prototype.draw = function() { } Component.prototype.drawAll = function() { if (!this.visible) return; var i,k=this.children.keys(); this.draw(); for (i=0;i<k.length;i++) this.children.get(k[i]).drawAll(); } Component.prototype.show = function() { this.setVisible(true); this.onShow(); } Component.prototype.hide = function() { this.setVisible(false); this.onHide(); } Component.prototype.getDocID = function() { return "cmpid" + this.id; } Component.prototype.getElement = function() { return document.getElementById(this.getDocID()); } Component.prototype.jsCode = function() { return "Component.list[" + this.id + "]"; } Component.prototype.html = function(cl) { return (this.isBlock ? '<div' : '<span') + ' id="' + this.getDocID() + '"' + (typeof cl == "undefined" ? "" : (' class="' + cl + '"')) + '> </' + (this.isBlock ? 'div' : 'span') + '>'; } Component.prototype.newSlot = function(name) { if (this.slots.containsKey(name)) return; var s = new Component.Slot(name,this); this.slots.put(name, s); } Component.prototype.newEvent = function(name, propagate) { if (this.events.containsKey(name)) return; var e = new Component.Event(name, propagate); this.events.put(name, e); var f = function() { this.triggerEvent(name,arguments); }; eval("this.on"+name+'=f'); } Component.prototype.bindEvent = function(eName,sName,cmp) { var e = this.events.get(eName), c = (cmp ? cmp : this), s = c.slots.get(sName); if (!(e && s)) return; e.bind(s); } Component.prototype.detachEvent = function(eName,sName,cmp) { var e = this.events.get(eName), c = (cmp ? cmp : this), s = c.slots.get(sName); if (!(e && s)) return; e.detach(s); } Component.prototype.triggerEvent = function(eName,args) { var e = this.events.get(eName); if (!e) return; var i, n = new Array(); for (i=0;i<args.length;i++) n.push('args[' + i + ']'); eval('e.trigger(' + n.join(',') + ')'); if (!e.propagate) return; var k=this.children.keys(); for (i=0;i<k.length;i++) this.children.get(k[i]).triggerEvent(eName, args); } Component.prototype.addChild = function(cmp) { if (!cmp || cmp.id == this.id) return; cmp.setVisible(this.visible); this.children.put(cmp.id, cmp); this.drawAll(); } Component.prototype.removeChild = function(cmp) { if (!cmp || cmp.id == this.id || !this.children.containsKey(cmp.id)) return; this.children.remove(cmp.id); cmp.setVisible(false); this.drawAll(); } Component.prototype.hasChild = function(cmp) { if (!cmp) return false; return this.children.containsKey(cmp.id); } Component.Slot = function (name, component) { this.name = name; this.component = component; this.id = ++Component.Slot.lId; } Component.Slot.lId = -1; Component.Slot.prototype.call = function() { var i, n = new Array(); for (i=0;i<arguments.length;i++) n.push('arguments[' + i + ']'); eval('this.component.'+this.name+'('+n.join(',')+')'); } Component.Event = function (name, propagate) { this.name = name; this.propagate = propagate; this.bindings = new Hashtable(); } Component.Event.prototype.bind = function(slot) { if (!this.bindings.containsKey(slot.id)) this.bindings.put(slot.id, slot); } Component.Event.prototype.detach = function(slot) { if (this.bindings.containsKey(slot.id)) this.bindings.remove(slot.id); } Component.Event.prototype.trigger = function() { var i, n = new Array(); for (i=0;i<arguments.length;i++) n.push('arguments[' + i + ']'); var k = this.bindings.keys(), s = n.join(','); for (i=0;i<k.length;i++) eval('this.bindings.get('+k[i]+').call('+s+')'); } //---------------------------------------------------------------------------------------------- // TIMER COMPONENT //---------------------------------------------------------------------------------------------- Component.Timer = function(miliseconds,repeat) { if (typeof miliseconds == 'undefined') return; Component.apply(this, [false]); this.miliseconds = miliseconds; this.repeat = repeat; this.timer = null; this.lastAt = 0; this.pausedAt = 0; this.locked = false; this.running = false; this.newEvent('Tick'); } Component.Timer.prototype = new Component; Component.Timer.prototype.start = function() { while (this.locked) ; this.locked = true; if (!this.running) { this.running = true; this.lastAt = new Date().getTime(); eval(this.getCode()); } this.locked = false; } Component.Timer.prototype.stop = function() { while (this.locked) ; this.locked = true; if (this.running) { clearTimeout(this.timer); this.lastAt = this.pausedAt = 0; this.running = false; } this.locked = false; } Component.Timer.prototype.restart = function() { while (this.locked) ; this.locked = true; if (this.running) { clearTimeout(this.timer); this.pausedAt = 0; } else this.running = true; this.lastAt = new Date().getTime(); eval(this.getCode()); this.locked = false; } Component.Timer.prototype.pause = function () { while (this.locked) ; this.locked = true; if (this.running) { if (this.pausedAt == 0) { this.pausedAt = new Date().getTime(); if (this.timer) clearTimeout(this.timer); } else { eval(this.getCode()); this.pausedAt = 0; } } this.locked = false; } Component.Timer.prototype.tick = function() { while (this.locked) ; this.locked = true; var re; if (re=(this.running && !this.pausedAt)) { if (this.repeat) { eval(this.getCode()); this.lastAt = new Date().getTime(); } else { this.running = false; this.timer = null; this.lastAt = 0; } } this.locked = false; if (re) this.onTick(); } Component.Timer.prototype.getCode = function() { return this.jsCode() + '.timer=setTimeout("' + this.jsCode() + '.tick()", ' + (this.pausedAt ? (this.miliseconds - this.pausedAt + this.lastAt) : this.miliseconds) + ")"; } //---------------------------------------------------------------------------------------------- // AJAX COMPONENT //---------------------------------------------------------------------------------------------- Component.Ajax = function(callName) { if (typeof callName == 'undefined') return; Component.apply(this, [false]); this.callName = callName; this.newEvent('Returned'); } Component.Ajax.prototype = new Component; Component.Ajax.prototype.call = function() { eval('Array.prototype.push.apply(arguments,[function(d){'+this.jsCode()+'.onReturned(d)}])'); rpc_doCall(this.callName, arguments); } //---------------------------------------------------------------------------------------------- // FORM ELEMENT COMPONENT //---------------------------------------------------------------------------------------------- Component.Form = {} Component.Form.Element = function(type, hasContents) { if (typeof type == "undefined") return; Component.apply(this, [false]); this.type = type; this.hasContents = hasContents; this.attributes = new Hashtable(); this.htmlEvents = new Array(); this.value = null; this.htmlElement = null; this.setAttribute('name', this.getDocID() + 'f'); this.setAttribute('id', this.getDocID() + 'f'); this.newSlot('hideElement'); this.bindEvent('Hide', 'hideElement'); this.addHTMLEvent('MouseOver'); this.addHTMLEvent('MouseOut'); } Component.Form.Element.prototype = new Component; Component.Form.Element.prototype.addChild = function () { } Component.Form.Element.prototype.hideElement = function () { this.htmlElement = null; } Component.Form.Element.prototype.setAttribute = function (name,def) { this.attributes.put(name.toLowerCase(), def); this.drawAll(); } Component.Form.Element.prototype.addHTMLEvent = function (name) { this.htmlEvents.push(name); this.newEvent(name); this.drawAll(); } Component.Form.Element.prototype.getTag = function () { var s = '<' + this.type; var k = this.attributes.keys(); for (var a in k) { var av = this.attributes.get(k[a]); if (av == '') continue; s += ' ' + k[a] + '="' + av + '"'; } var jc = this.jsCode(); for (var ei in this.htmlEvents) { var ev = this.htmlEvents[ei]; s += ' on' + ev.toLowerCase() + '="' + jc + '.on' + ev + '(event)"'; } return s + (this.hasContents ? '>' : '/>'); } Component.Form.Element.prototype.draw = function () { var e = this.getElement(); if (!e) return; var s = this.getTag(); if (this.hasContents) s += '</' + this.type + '>'; e.innerHTML = s; this.htmlElement = document.getElementById(this.attributes.get('id')); this.updateValue(); } Component.Form.Element.prototype.updateValue = function (nv) { if (typeof nv != "undefined") this.value = nv; if (this.htmlElement) this.htmlElement.value = this.value; } //---------------------------------------------------------------------------------------------- // LABEL COMPONENT //---------------------------------------------------------------------------------------------- Component.Form.Label = function(target, text, key) { if (typeof target == "undefined") return; Component.apply(this, [false]); this.target = target; this.text = text; this.key = key; } Component.Form.Label.prototype = new Component; Component.Form.Label.prototype.addChild = function () { } Component.Form.Label.prototype.draw = function () { var e = this.getElement(); if (!e) return; e.innerHTML = '<label for="' + this.target.getDocID() + 'f"' + (this.key ? (' key="' + this.key + '"') : '') + '>' + this.text + '</label>'; } //---------------------------------------------------------------------------------------------- // TEXT INPUT COMPONENT //---------------------------------------------------------------------------------------------- Component.Form.Text = function (defValue) { if (typeof defValue == 'undefined') return; Component.Form.Element.apply(this, ['input type="text"', false]); var ev = ['Click', 'KeyUp', 'KeyDown', 'KeyPress', 'Paste']; this.newSlot('textEvent'); for (var i in ev) { this.addHTMLEvent(ev[i]); this.bindEvent(ev[i], 'textEvent'); } this.timer = new Component.Timer(500, false); this.newSlot('timeout'); this.timer.bindEvent('Tick', 'timeout', this); this.oldValue = this.value = defValue; this.newEvent('TextChanged'); } Component.Form.Text.prototype = new Component.Form.Element; Component.Form.Text.prototype.textEvent = function() { if (this.htmlElement) this.value = this.htmlElement.value; this.timer.restart(); } Component.Form.Text.prototype.timeout = function() { if (this.htmlElement) this.value = this.htmlElement.value; if (this.value != this.oldValue) { this.oldValue = this.value; this.onTextChanged(this.value); } } Component.Form.Text.prototype.setSize = function (sz) { this.setAttribute('size', (typeof sz == 'undefined') ? '' : sz); } Component.Form.Text.prototype.setMaxLength = function (ml) { if (typeof ml != "undefined" && this.value.length > ml) { this.timer.stop(); this.value = this.value.substr(0, ml); } this.setAttribute('maxlength', (typeof ml == 'undefined') ? '' : ml); } //---------------------------------------------------------------------------------------------- // CHECKBOX COMPONENT //---------------------------------------------------------------------------------------------- Component.Form.Checkbox = function (value,name) { if (typeof value == 'undefined') return; Component.Form.Element.apply(this, ['input type="checkbox"', false]); this.newSlot('check'); this.addHTMLEvent('Click'); this.bindEvent('Click', 'check'); this.newEvent('Checked'); this.newEvent('Unchecked'); this.value = value; this.checked = false; this.setAttribute('name', this.group = name); } Component.Form.Checkbox.prototype = new Component.Form.Element; Component.Form.Checkbox.prototype.check = function(evt) { this.checked = !this.checked; if (typeof evt == "undefined") this.drawAll(); if (this.checked) { this.attributes.put('checked', 'checked'); this.onChecked(this.value, this.group); } else { this.attributes.remove('checked'); this.onUnchecked(this.value, this.group); } } //---------------------------------------------------------------------------------------------- // RADIO BUTTON COMPONENT //---------------------------------------------------------------------------------------------- Component.Form.Radio = function (value,name) { if (typeof value == 'undefined') return; Component.Form.Element.apply(this, ['input type="radio"', false]); this.newSlot('check'); this.addHTMLEvent('Click'); this.bindEvent('Click', 'check'); this.newEvent('Checked'); this.newEvent('Unchecked'); this.value = value; this.checked = false; this.setAttribute('name', this.group = name); with (Component.Form.Radio.groups) { if (!get(name)) put(name, new Array()); get(name).push(this); } } Component.Form.Radio.prototype = new Component.Form.Element; Component.Form.Radio.groups = new Hashtable(); Component.Form.Radio.prototype.check = function(evt) { var k = Component.Form.Radio.groups.keys(); for (var i in k) { var c = Component.Form.Radio.groups.get(k[i]); if (c.id != this.id && c.checked) { c.checked = false; c.attributes.put('checked', ''); if (typeof evt == "undefined") c.drawAll(); c.onUnchecked(c.group, c.value); break; } } this.checked = true; this.attributes.put('checked', 'checked'); if (typeof evt == "undefined") this.drawAll(); this.onChecked(this.value, this.group); } //---------------------------------------------------------------------------------------------- // DROP-DOWN COMPONENT //---------------------------------------------------------------------------------------------- Component.Form.DropDown = function (emptyValue,emptyLabel) { if (typeof emptyValue == 'undefined') return; Component.Form.Element.apply(this, ['select', true]); this.newSlot('htmlSelect'); this.addHTMLEvent('Change'); this.bindEvent('Change', 'htmlSelect'); this.newEvent('Selected'); this.options = new Array(); this.byValue = new Hashtable(); if (typeof emptyValue != 'string') emptyValue = emptyValue.toString(); this.emptyValue = emptyValue; this.emptyLabel = emptyLabel; this.selected = emptyValue; } Component.Form.DropDown.prototype = new Component.Form.Element; Component.Form.DropDown.prototype.clearOptions = function(redraw) { this.byValue.clear(); this.options = new Array(); this.selected = this.emptyValue; } Component.Form.DropDown.prototype.appendOption = function(value,text) { if (typeof value != 'string') value = value.toString(); if (this.byValue.containsKey(value)) return; this.options.push([value, text]); this.byValue.put(value, this.options.length - 1); if (this.selected == this.emptyValue) this.selected = value; } Component.Form.DropDown.prototype.finalize = function() { this.drawAll(); this.onSelected(this.selected); } Component.Form.DropDown.prototype.htmlSelect = function() { if (this.htmlElement) { var se = this.htmlElement.selectedIndex; this.selected = this.htmlElement.options[se].value; } this.onSelected(this.selected); } Component.Form.DropDown.prototype.select = function(v) { if (typeof v != 'string') v = v.toString(); if (!this.options.length || ! this.byValue.containsKey(v) || this.selected == v) return; this.selected = v; this.drawAll(); this.onSelected(this.selected); } Component.Form.DropDown.prototype.updateValue = function() { } Component.Form.DropDown.prototype.draw = function() { var e = this.getElement(); if (!e) return; var s = ''; if (this.options.length) for (var i in this.options) s += '<option value="' + this.options[i][0] + '"' + (this.selected == this.options[i][0] ? ' selected="selected"' : '') + '>' + this.options[i][1] + '</option>'; else s = '<option value="' + this.emptyValue + '">' + this.emptyLabel + '</option>'; e.innerHTML = this.getTag() + s + '</select>'; this.htmlElement = document.getElementById(this.attributes.get('id')); } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT //---------------------------------------------------------------------------------------------- Component.Listing = function(rpcName, updateFreq, dataType, cl, rClass, hClass) { if (typeof rpcName == 'undefined') return; Component.apply(this, [false]); this.pageCtrl = null; this.searchCtrl = null; this.pageSzCtrl = null; this.dataCache = new Component.Listing.DataCache(this, rpcName, updateFreq, dataType); this.addChild(this.dataCache); this.fields = new Hashtable(); this.fLayout = { }; this.rows = 0; this.cols = 0; this.mClass = cl; this.rClass = (rClass ? rClass : ''); this.hClass = (hClass ? hClass : ''); this.finalized = false; this.sortField = -1; this.sortDir = false; this.notFoundText = Component.Listing.notFoundText; this.loadingText = Component.Listing.loadingText; this.errorText = Component.Listing.errorText; } Component.Listing.prototype = new Component; Component.Listing.prototype.setPageController = function(c,itg) { if (this.pageCtrl) // FIXME, should detach the old controller return; this.pageCtrl = c; this.pageCtrl.bindEvent('PageChanged', 'pageChanged', this.dataCache); if (itg) this.addChild(this.pageCtrl); this.dataCache.pageChanged(this.pageCtrl.currentPage); } Component.Listing.prototype.setPageSizeController = function(c,itg) { if (this.pageSzCtrl) // FIXME, should detach the old controller return; this.pageSzCtrl = c; this.pageSzCtrl.bindEvent('PageSizeChanged', 'pageSizeChanged', this.dataCache); if (itg) this.addChild(this.pageSzCtrl); this.dataCache.pageSizeChanged(this.pageSzCtrl.currentSize); } Component.Listing.prototype.setSearchController = function(c,itg) { if (this.searchCtrl) // FIXME, should detach the old controller return; this.searchCtrl = c; this.searchCtrl.bindEvent('SearchChanged', 'searchChanged', this.dataCache); if (itg) this.addChild(this.searchCtrl); this.dataCache.searchChanged(this.searchCtrl.getParameter()); } Component.Listing.prototype.addField = function(fld) { var x,y,xe=fld.x+fld.width,ye=fld.y+fld.height; for (y=fld.y;y<ye;y++) for (x=fld.x;x<xe;x++) if (this.fLayout[x+'_'+y]) return; this.fields[fld.id] = fld; fld.component = this; if (fld.sortable) { if (! this.dataCache.sortField) this.dataCache.sortField = fld; fld.bindEvent('Click', 'sortChanged', this.dataCache); } for (y=fld.y;y<ye;y++) for (x=fld.x;x<xe;x++) this.fLayout[x+'_'+y] = fld; } Component.Listing.prototype.finalizeLayout = function() { var mx = 0, my = 0, x, y; for (var c in this.fLayout) { var cs=c.split('_'); x=parseInt(cs[0],10); y=parseInt(cs[1],10); if (x>mx) mx = x; if (y>my) my = y; } this.rows = my+1; this.cols = mx+1; for (y=0;y<this.rows;y++) for (x=0;x<this.cols;x++) if (!this.fLayout[x+'_'+y]) this.fLayout[x+'_'+y] = new Component.Listing.Spacer(x,y); this.finalized = true; } Component.Listing.prototype.setMaxPage = function (v) { if (this.pageCtrl) this.pageCtrl.changeMaxPage(v); } Component.Listing.prototype.draw = function () { var e = this.getElement(); if (!e) return; // Draw the listing's header including placeholders for the controllers if that is necessary var s = ''; var hp = this.hasChild(this.pageCtrl), hs = this.hasChild(this.searchCtrl), hps = this.hasChild(this.pageSzCtrl), hh = (hp||hs||hps); if (hh) { s += '<table class="' + this.hClass + '">'; if (hp||hps) { s += '<tr><td style="width:50%;text-align:center"'; if (hp) s += ' id="' + this.pageCtrl.getDocID() + '"'; s += '> </td><td style="width:50%;text-align:center"'; if (hps) s += ' id="' + this.pageSzCtrl.getDocID() + '"'; s += '> </td></tr>'; } if (hs) s += '<tr><td style="text-align:center" id="' + this.searchCtrl.getDocID() + '"' + ((hp||hps)?' colspan="2"' : '') + '> </td></tr>'; s += '</td></tr></table>'; } s += '<div id="' + this.id + 'data"></div>'; e.innerHTML = s; } Component.Listing.prototype.getHeaders = function () { var s = '<table class="'+this.mClass+'">'; var lId = -1, x, y, rc = (this.rClass != '' ? (" class='" + this.rClass + "'") : ""); for (y=0;y<this.rows;y++) { if (y == 0) s += '<tr><td><table'+rc+'>'; s += '<tr>'; for (x=0;x<this.cols;x++) { var f = this.fLayout[x+'_'+y]; if (f.id == lId || y != f.y) continue; lId = f.id; s += f.getTitle(); } s += '</tr>' + ((y == this.rows - 1) ? '</table></td></tr>' : ''); } return s; } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - PAGE CONTROLLER //---------------------------------------------------------------------------------------------- Component.Listing.PageController = function(text) { if (typeof text == 'undefined') return; Component.apply(this, [false]); this.text = text; this.maxPage = 0; this.addChild(this.select = new Component.Form.DropDown('', '-')); this.newSlot('selected'); this.select.bindEvent('Selected','selected',this); this.newSlot('changePage'); this.newSlot('changeMaxPage'); this.newEvent('PageChanged'); } Component.Listing.PageController.prototype = new Component; Component.Listing.PageController.prototype.selected = function(v) { this.changePage(parseInt(v,10)); } Component.Listing.PageController.prototype.changePage = function(np) { var op = this.currentPage; this.currentPage = (np > this.maxPage) ? this.maxPage : np; if (op != this.currentPage) { this.select.select(this.currentPage); this.onPageChanged(this.currentPage); } this.drawAll(); } Component.Listing.PageController.prototype.changeMaxPage = function(nmp) { var omp = this.maxPage, ocp = this.currentPage; this.maxPage = nmp; if (omp != nmp) { var i; this.select.clearOptions(); for (i=0;i<nmp+1;i++) this.select.appendOption(i, i+1); this.changePage(this.currentPage); if (this.currentPage == ocp) this.drawAll(); } } Component.Listing.PageController.prototype.draw = function() { var e = this.getElement(), id = this.getDocID(); if (!e) return; var m, s2; if (this.maxPage <= 0) { m = 1; s2 = '1'; } else { m = (this.maxPage + 1); s2 = this.select.html(); } var s = this.text.replace(/__MP__/, m.toString()); e.innerHTML = s.replace(/__CP__/, s2); } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - PAGE SIZE CONTROLLER //---------------------------------------------------------------------------------------------- Component.Listing.PageSizeController = function(text, minVal, maxVal, increment) { if (typeof text == 'undefined') return; Component.apply(this, [false]); this.text = text; this.currentSize = minVal; this.addChild(this.select = new Component.Form.DropDown('', '-')); for (var i=minVal;i<=maxVal;i+=increment) this.select.appendOption(i, i); this.newSlot('selected'); this.select.bindEvent('Selected','selected',this); this.newSlot('changePageSize'); this.newEvent('PageSizeChanged'); } Component.Listing.PageSizeController.prototype = new Component; Component.Listing.PageSizeController.prototype.selected = function(v) { this.changePageSize(parseInt(v,10)); } Component.Listing.PageSizeController.prototype.changePageSize = function(nps) { var os = this.currentSize; this.currentSize = nps; if (os != this.currentSize) { this.select.select(this.currentSize); this.onPageSizeChanged(this.currentSize); } this.drawAll(); } Component.Listing.PageSizeController.prototype.draw = function() { var e = this.getElement(), id = this.getDocID(); if (!e) return; e.innerHTML = this.text.replace(/__PS__/, this.select.html()); } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - SEARCH CONTROLLER //---------------------------------------------------------------------------------------------- Component.Listing.SearchController = function(text) { if (typeof text == 'undefined') return; Component.apply(this, [false]); this.newSlot('textChanged'); this.addChild(this.textField = new Component.Form.Text('')); this.textField.bindEvent('TextChanged', 'textChanged', this); this.text = text; this.newSlot('modeChanged'); this.modes = new Array(); this.mode = -1; this.newEvent('SearchChanged'); } Component.Listing.SearchController.prototype = new Component; Component.Listing.SearchController.prototype.addMode = function (value, text) { if (typeof this.modes[value] != "undefined") return; var c = new Component.Form.Radio(value, this.getDocID() + 'mode'); c.bindEvent('Checked', 'modeChanged', this); this.addChild(c); var c2 = new Component.Form.Label(c, text); this.addChild(c2); this.modes[value] = [c,c2]; } Component.Listing.SearchController.prototype.setText = function (text) { if (text == this.textField.value) return; this.textField.updateValue(text); this.onSearchChanged(this.mode + '!' + text); } Component.Listing.SearchController.prototype.setMode = function (mode) { if (typeof this.modes[mode] == "undefined" || this.mode == mode) return; this.modes[mode][0].check(); } Component.Listing.SearchController.prototype.draw = function () { var e = this.getElement(), id = this.getDocID(); if (!e) return; var s, s2, cd; s = this.text.replace(/__TF__/, this.textField.html()); if (this.modes.length > 1) { s2 = new Array(); for (var i in this.modes) s2.push(this.modes[i][0].html() + this.modes[i][1].html() + ' '); s = s.replace(/__MS__/, s2.join(' ')); } e.innerHTML = s; } Component.Listing.SearchController.prototype.textChanged = function (text) { this.onSearchChanged(this.mode + '!' + text); } Component.Listing.SearchController.prototype.modeChanged = function (mode) { this.onSearchChanged((this.mode=mode) + '!' + this.textField.value); } Component.Listing.SearchController.prototype.getParameter = function () { return this.mode + '!' + this.textField.value; } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - SPACERS //---------------------------------------------------------------------------------------------- Component.Listing.Spacer = function (x,y,fClass) { if (typeof x == 'undefined') return; Component.apply(this, [true]); this.fClass = fClass ? fClass : ''; this.attrCode = null; this.x = x; this.y = y; this.width = this.height = 1; this.sortable = false; this.component = null; this.newEvent('Click'); } Component.Listing.Spacer.prototype = new Component; Component.Listing.Spacer.prototype.getAttributes = function() { if (typeof this.attrCode == 'string') return this.attrCode; var s = ''; if (this.fClass != '') s += ' class="' + this.fClass + '"'; return (this.attrCode = s); } Component.Listing.Spacer.prototype.getData = function() { return '<td' + this.getAttributes() + '> </td>'; } Component.Listing.Spacer.prototype.getTitle = function() { return '<th' + this.getAttributes() + '> </th>'; } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - FIELDS //---------------------------------------------------------------------------------------------- Component.Listing.Field = function (name,sortable,dataField,x,y,w,h,fClass) { if (typeof name == 'undefined') return; Component.Listing.Spacer.apply(this, [x,y,fClass]); this.name = name; this.sortable = sortable; this.dataField = dataField; this.width = w; this.height = h; } Component.Listing.Field.prototype = new Component.Listing.Spacer; Component.Listing.Field.prototype.getAttributes = function() { if (typeof this.attrCode == 'string') return this.attrCode; var s = ''; if (this.fClass != '') s += ' class="' + this.fClass + '"'; if (this.width != 1) s += ' colspan="' + this.width + '"'; if (this.height != 1) s += ' rowspan="' + this.height + '"'; return (this.attrCode = s); } Component.Listing.Field.prototype.getContents = function(d) { var v; eval('v=d.' + this.dataField); if (typeof v != 'string') v = v.toString(); return v; } Component.Listing.Field.prototype.getData = function(d) { return '<td' + this.getAttributes() + '>' + this.getContents(d) + '</td>'; } Component.Listing.Field.prototype.getTitle = function() { var s = '<th' + this.getAttributes(); var srt = (this.sortable && this.component.dataCache.sortField && this.component.dataCache.sortField.id == this.id); if (this.sortable) s += ' onClick="' + this.jsCode() + '.onClick(Component.list[' + this.id + '])"'; s += '>'; if (srt) s += '<b>'; s += this.name; if (srt) s += '</b><img src="' + staticurl + '/beta5/pics/' + (this.component.dataCache.sortDir ? "up" : "down") + '_' + color + '.gif" alt="' + (this.component.dataCache.sortDir ? "up" : "down") + '"/>'; return s + '</th>'; } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - DATA CACHE //---------------------------------------------------------------------------------------------- Component.Listing.DataCache = function (comp, rpcName, updateFreq, dataType) { Component.apply(this, [false]); this.newSlot('pageChanged'); this.newSlot('pageSizeChanged'); this.newSlot('searchChanged'); this.newSlot('sortChanged'); this.newSlot('pageLoaded'); this.newSlot('checkUpdate'); this.newSlot('initDisplay'); this.newSlot('stopDisplay'); this.newEvent('SettingsChanged'); this.newEvent('Loaded'); this.rpcName = rpcName; this.dataType = dataType; this.component = comp; this.sortField = null; this.sortDir = false; this.searchParam = ''; this.perPage = 10; this.page = 0; this.current = ""; this.cache = new Hashtable(); this.timer = new Component.Timer(updateFreq * 1000, true); this.bindEvent('Hide', 'stop', this.timer); this.bindEvent('Loaded', 'drawAll'); this.bindEvent('SettingsChanged', 'checkUpdate'); this.bindEvent('SettingsChanged', 'drawAll'); this.bindEvent('Show', 'initDisplay'); this.timer.bindEvent('Tick', 'checkUpdate', this); } Component.Listing.DataCache.prototype = new Component; Component.Listing.DataCache.prototype.pageChanged = function (n) { this.page = n; this.onSettingsChanged(); } Component.Listing.DataCache.prototype.pageSizeChanged = function (n) { this.perPage = n; this.onSettingsChanged(); } Component.Listing.DataCache.prototype.searchChanged = function (p) { this.searchParam = p; this.onSettingsChanged(); } Component.Listing.DataCache.prototype.sortChanged = function (col) { if (this.sortField && col.id == this.sortField.id) this.sortDir = ! this.sortDir; else this.sortField = col; this.onSettingsChanged(); } Component.Listing.DataCache.prototype.pageLoaded = function (id) { if (this.current != id) return; this.drawAll(); this.onLoaded(); } Component.Listing.DataCache.prototype.checkUpdate = function () { if (!this.visible) return; var nid = this.page+'#'+this.perPage+'#'+(this.sortField?this.sortField.dataField:'')+'#'+(this.sortDir?1:0)+'#'+this.searchParam; var ne; if (this.cache.containsKey(nid)) ne = this.cache.get(nid); else { ne = new Component.Listing.DataCache.Page(this, nid); ne.bindEvent('Loaded', 'pageLoaded', this); this.cache.put(nid, ne); } this.current = nid; ne.checkUpdate(); } Component.Listing.DataCache.prototype.initDisplay = function () { if (this.timer.running) return; this.timer.start(); this.onSettingsChanged(); } Component.Listing.DataCache.prototype.draw = function () { var e = document.getElementById(this.component.id + 'data'); if (!(e && this.cache.containsKey(this.current))) return; var s = this.component.getHeaders(); var p = this.cache.get(this.current); if (p.loading) s += '<tr><td style="text-align:center;padding:10px 0px 10px 0px;">' + this.component.loadingText + '</td></tr>'; else if (p.error) s += '<tr><td style="text-align:center;padding:10px 0px 10px 0px;">' + this.component.errorText + '</td></tr>'; else if (p.data.length == 0) s += '<tr><td style="text-align:center;padding:10px 0px 10px 0px;">' + this.component.notFoundText + '</td></tr>'; else { var rc, i; rc = (this.component.rClass != '' ? (" class='" + this.component.rClass + "'") : ""); for (i=0;i<p.data.length;i++) { var lId = -1, x, y; for (y=0;y<this.component.rows;y++) { if (y == 0) s += '<tr><td style="margin:0px;padding:0px"><table'+rc+'>'; s += '<tr' + p.data[i].getRowStyle() + '>'; for (x=0;x<this.component.cols;x++) { var f = this.component.fLayout[x+'_'+y]; if (f.id == lId || y != f.y) continue; lId = f.id; s += f.getData(p.data[i]); } s += '</tr>' + ((y == this.component.rows - 1) ? '</table></td></tr>' : ''); } } } e.innerHTML = s + '</table>'; } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - DATA CACHE PAGE //---------------------------------------------------------------------------------------------- Component.Listing.DataCache.Page = function (cache, param) { Component.apply(this, [false]); this.newSlot('dataReceived'); this.newEvent('Loaded'); this.cache = cache; this.param = param; this.loading = true; this.md5 = ""; this.error = false; this.data = new Array(); this.call = new Component.Ajax(this.cache.rpcName); this.call.bindEvent('Returned', 'dataReceived', this); } Component.Listing.DataCache.Page.prototype = new Component; Component.Listing.DataCache.Page.prototype.checkUpdate = function () { this.loading = true; this.call.call(this.param, this.md5); } Component.Listing.DataCache.Page.prototype.dataReceived = function (data) { if (data == "") { this.error = true; this.data = new Array(); } else if (data.indexOf("KEEP#") == 0) this.cache.component.setMaxPage(parseInt(data.substr(5), 10) - 1); else { var dataArr = data.split('\n'); var a = dataArr.shift().split('#'); this.md5 = a.shift(); this.cache.component.setMaxPage(parseInt(a.shift(), 10) - 1); this.data = new Array(); this.error = false; while (dataArr.length > 0) { var e = new this.cache.dataType (this.cache, this); e.parse(dataArr); this.data.push(e); } } this.loading = false; this.onLoaded(this.param); } //---------------------------------------------------------------------------------------------- // LISTING COMPONENT - GENERIC DATA //---------------------------------------------------------------------------------------------- Component.Listing.Data = function (cache, page) { if (typeof cache == "undefined") return; Component.apply(this, [false]); this.cache = cache; this.page = page; } Component.Listing.Data.prototype = new Component; Component.Listing.Data.prototype.parse = function (data) { alert("Listing using elemnts without a parse() method\n" + "Skipping line: " + data.shift()); } Component.Listing.Data.prototype.getRowStyle = function () { return ''; }