function formatNumber(n) { var l = n.length, m = l % 3, c = (l - m) / 3, v = ((m > 0) ? n.substr(0, m) : ''), z; for (z=0;z '; } 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' : '/>'); } Component.Form.Element.prototype.draw = function () { var e = this.getElement(); if (!e) return; var s = this.getTag(); if (this.hasContents) s += ''; 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 = ''; } //---------------------------------------------------------------------------------------------- // 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 += ''; else s = ''; e.innerHTML = this.getTag() + s + ''; 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;ymx) mx = x; if (y>my) my = y; } this.rows = my+1; this.cols = mx+1; for (y=0;y'; if (hp||hps) { s += ' '; s += ''; } s += '
'; e.innerHTML = s; } Component.Listing.prototype.getHeaders = function () { var s = ''; var lId = -1, x, y, rc = (this.rClass != '' ? (" class='" + this.rClass + "'") : ""); for (y=0;y'; s += ''; for (x=0;x' : ''); } 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 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 ' '; } Component.Listing.Spacer.prototype.getTitle = function() { return ' '; } //---------------------------------------------------------------------------------------------- // 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 '' + this.getContents(d) + ''; } Component.Listing.Field.prototype.getTitle = function() { var s = ''; return s + ''; } //---------------------------------------------------------------------------------------------- // 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 += ''; else if (p.error) s += ''; else if (p.data.length == 0) s += ''; else { var rc, i; rc = (this.component.rClass != '' ? (" class='" + this.component.rClass + "'") : ""); for (i=0;i'; s += ''; for (x=0;x' : ''); } } } e.innerHTML = s + '
' + this.component.loadingText + '
' + this.component.errorText + '
' + this.component.notFoundText + '
'; } //---------------------------------------------------------------------------------------------- // 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 ''; }