Author: spadkins
Date: Tue Sep 1 12:50:17 2009
New Revision: 13245
Modified:
p5ee/trunk/App-Widget-ExtJS/Makefile.PL
p5ee/trunk/App-Widget-ExtJS/htdocs/App/ext-addon.js
p5ee/trunk/App-Widget-ExtJS/lib/App/SessionObject/ExtJS/Store.pm
p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS.pm
p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm
Log:
next generation of ExtJS::DataTable. does Ajax/paging/filtering/sorting
Modified: p5ee/trunk/App-Widget-ExtJS/Makefile.PL
==============================================================================
--- p5ee/trunk/App-Widget-ExtJS/Makefile.PL (original)
+++ p5ee/trunk/App-Widget-ExtJS/Makefile.PL Tue Sep 1 12:50:17 2009
@@ -25,6 +25,7 @@
install ::
@\$(MOD_INSTALL) htdocs "\$(PREFIX)/htdocs"
+ @\$(MOD_INSTALL) cgi-bin "\$(PREFIX)/cgi-bin"
EOF
}
Modified: p5ee/trunk/App-Widget-ExtJS/htdocs/App/ext-addon.js
==============================================================================
--- p5ee/trunk/App-Widget-ExtJS/htdocs/App/ext-addon.js (original)
+++ p5ee/trunk/App-Widget-ExtJS/htdocs/App/ext-addon.js Tue Sep 1 12:50:17 2009
@@ -1,250 +1,852 @@
-/*
- * Ext JS Library 2.0.1
- * Copyright(c) 2006-2008, Ext JS, LLC.
- * [email protected]
- *
- * http://extjs.com/license
- */
-
-Ext.grid.GroupSummary = function(config){
- Ext.apply(this, config);
-};
-
-Ext.extend(Ext.grid.GroupSummary, Ext.util.Observable, {
- init : function(grid){
- this.grid = grid;
- this.cm = grid.getColumnModel();
- this.view = grid.getView();
-
- var v = this.view;
- v.doGroupEnd = this.doGroupEnd.createDelegate(this);
-
- v.afterMethod('onColumnWidthUpdated', this.doWidth, this);
- v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
- v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);
- v.afterMethod('onUpdate', this.doUpdate, this);
- v.afterMethod('onRemove', this.doRemove, this);
-
- if(!this.rowTpl){
- this.rowTpl = new Ext.Template(
- '<div class="x-grid3-summary-row" style="{tstyle}">',
- '<table class="x-grid3-summary-table" border="0"
cellspacing="0" cellpadding="0" style="{tstyle}">',
- '<tbody><tr>{cells}</tr></tbody>',
- '</table></div>'
- );
- this.rowTpl.disableFormats = true;
- }
- this.rowTpl.compile();
-
- if(!this.cellTpl){
- this.cellTpl = new Ext.Template(
- '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}"
style="{style}">',
- '<div class="x-grid3-cell-inner x-grid3-col-{id}"
unselectable="on">{value}</div>',
- "</td>"
- );
- this.cellTpl.disableFormats = true;
- }
- this.cellTpl.compile();
- },
-
- toggleSummaries : function(visible){
- var el = this.grid.getGridEl();
- if(el){
- if(visible === undefined){
- visible = el.hasClass('x-grid-hide-summary');
- }
- el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');
- }
- },
-
- renderSummary : function(o, cs){
- cs = cs || this.view.getColumnData();
- var cfg = this.cm.config;
-
- var buf = [], c, p = {}, cf, last = cs.length-1;
- for(var i = 0, len = cs.length; i < len; i++){
- c = cs[i];
- cf = cfg[i];
- p.id = c.id;
- p.style = c.style;
- p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ?
'x-grid3-cell-last ' : '');
- if(cf.summaryType || cf.summaryRenderer){
- p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name],
p, o);
- }else{
- p.value = '';
- }
- if(p.value == undefined || p.value === "") p.value = " ";
- buf[buf.length] = this.cellTpl.apply(p);
- }
-
- return this.rowTpl.apply({
- tstyle: 'width:'+this.view.getTotalWidth()+';',
- cells: buf.join('')
- });
- },
-
- calculate : function(rs, cs){
- var data = {}, r, c, cfg = this.cm.config, cf;
- for(var j = 0, jlen = rs.length; j < jlen; j++){
- r = rs[j];
- for(var i = 0, len = cs.length; i < len; i++){
- c = cs[i];
- cf = cfg[i];
- if(cf.summaryType){
- data[c.name] =
Ext.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r,
c.name, data);
- }
- }
- }
- return data;
- },
-
- doGroupEnd : function(buf, g, cs, ds, colCount){
- var data = this.calculate(g.rs, cs);
- buf.push('</div>', this.renderSummary({data: data}, cs), '</div>');
- },
-
- doWidth : function(col, w, tw){
- var gs = this.view.getGroups(), s;
- for(var i = 0, len = gs.length; i < len; i++){
- s = gs[i].childNodes[2];
- s.style.width = tw;
- s.firstChild.style.width = tw;
- s.firstChild.rows[0].childNodes[col].style.width = w;
- }
- },
-
- doAllWidths : function(ws, tw){
- var gs = this.view.getGroups(), s, cells, wlen = ws.length;
- for(var i = 0, len = gs.length; i < len; i++){
- s = gs[i].childNodes[2];
- s.style.width = tw;
- s.firstChild.style.width = tw;
- cells = s.firstChild.rows[0].childNodes;
- for(var j = 0; j < wlen; j++){
- cells[j].style.width = ws[j];
- }
- }
- },
-
- doHidden : function(col, hidden, tw){
- var gs = this.view.getGroups(), s, display = hidden ? 'none' : '';
- for(var i = 0, len = gs.length; i < len; i++){
- s = gs[i].childNodes[2];
- s.style.width = tw;
- s.firstChild.style.width = tw;
- s.firstChild.rows[0].childNodes[col].style.display = display;
- }
- },
-
- // Note: requires that all (or the first) record in the
- // group share the same group value. Returns false if the group
- // could not be found.
- refreshSummary : function(groupValue){
- return this.refreshSummaryById(this.view.getGroupId(groupValue));
- },
-
- getSummaryNode : function(gid){
- var g = Ext.fly(gid, '_gsummary');
- if(g){
- return g.down('.x-grid3-summary-row', true);
- }
- return null;
- },
-
- refreshSummaryById : function(gid){
- var g = document.getElementById(gid);
- if(!g){
- return false;
- }
- var rs = [];
- this.grid.store.each(function(r){
- if(r._groupId == gid){
- rs[rs.length] = r;
- }
- });
- var cs = this.view.getColumnData();
- var data = this.calculate(rs, cs);
- var markup = this.renderSummary({data: data}, cs);
-
- var existing = this.getSummaryNode(gid);
- if(existing){
- g.removeChild(existing);
- }
- Ext.DomHelper.append(g, markup);
- return true;
- },
-
- doUpdate : function(ds, record){
- this.refreshSummaryById(record._groupId);
- },
-
- doRemove : function(ds, record, index, isUpdate){
- if(!isUpdate){
- this.refreshSummaryById(record._groupId);
- }
- },
-
- showSummaryMsg : function(groupValue, msg){
- var gid = this.view.getGroupId(groupValue);
- var node = this.getSummaryNode(gid);
- if(node){
- node.innerHTML = '<div class="x-grid3-summary-msg">' + msg +
'</div>';
- }
- }
-});
-
-Ext.grid.GroupSummary.Calculations = {
- 'sum' : function(v, record, field){
- return v + (record.data[field]||0);
- },
-
- 'count' : function(v, record, field, data){
- return data[field+'count'] ? ++data[field+'count'] :
(data[field+'count'] = 1);
- },
-
- 'max' : function(v, record, field, data){
- var v = record.data[field];
- var max = data[field+'max'] === undefined ? (data[field+'max'] = v) :
data[field+'max'];
- return v > max ? (data[field+'max'] = v) : max;
- },
-
- 'min' : function(v, record, field, data){
- var v = record.data[field];
- var min = data[field+'min'] === undefined ? (data[field+'min'] = v) :
data[field+'min'];
- return v < min ? (data[field+'min'] = v) : min;
- },
-
- 'average' : function(v, record, field, data){
- var c = data[field+'count'] ? ++data[field+'count'] :
(data[field+'count'] = 1);
- var t = (data[field+'total'] = ((data[field+'total']||0) +
(record.data[field]||0)));
- return t === 0 ? 0 : t / c;
- }
-}
-
-Ext.grid.HybridSummary = Ext.extend(Ext.grid.GroupSummary, {
- calculate : function(rs, cs){
- var gcol = this.view.getGroupField();
- var gvalue = rs[0].data[gcol];
- var gdata = this.getSummaryData(gvalue);
- return gdata || Ext.grid.HybridSummary.superclass.calculate.call(this,
rs, cs);
- },
-
- updateSummaryData : function(groupValue, data, skipRefresh){
- var json = this.grid.store.reader.jsonData;
- if(!json.summaryData){
- json.summaryData = {};
- }
- json.summaryData[groupValue] = data;
- if(!skipRefresh){
- this.refreshSummary(groupValue);
- }
- },
-
- getSummaryData : function(groupValue){
- var json = this.grid.store.reader.jsonData;
- if(json && json.summaryData){
- return json.summaryData[groupValue];
+
+// *******************************************************************
+// * ext-addon.js
+// *******************************************************************
+
+if (!Ext.app) {
+ Ext.app = new Object();
+}
+
+// *******************************************************************
+// * app.init() - Autodetect deployment values
+// * The app.options object is initially populated with values by the
+// * application. However, we can auto-detect other values and fill
+// * them in if they have not been supplied.
+// *******************************************************************
+
+// Example: http://localhost/1.0.4/members/app/edit.html?x=1&y=2
+// (a web page)
+// urlFull = http://localhost/1.0.4/members/app/edit.html?x=1&y=2
+// urlBase = http://localhost/1.0.4/members/app/edit.html
+// urlParams = ?x=1&y=2
+// urlDir = http://localhost/1.0.4/members/app
+// urlFile = edit.html
+// appName = edit
+// urlDocRoot = http://localhost/1.0.4 (a guess)
+// urlScriptRoot = http://localhost/cgi-bin/1.0.4 (a guess)
+// urlDocDir = http://localhost/1.0.4/members/app (same as
urlDir)
+// urlScriptDir = http://localhost/cgi-bin/1.0.4/members/app (add cgi-bin)
+
+// Example: http://localhost/cgi-bin/1.0.4/members/app/edit?x=1&y=2
+// (a cgi program)
+// urlFull = http://localhost/cgi-bin/1.0.4/members/app/edit?x=1&y=2
+// urlBase = http://localhost/cgi-bin/1.0.4/members/app/edit
+// urlParams = ?x=1&y=2
+// urlDir = http://localhost/cgi-bin/1.0.4/members/app
+// urlFile = edit.html
+// appName = edit
+// urlDocRoot = http://localhost/1.0.4 (a guess)
+// urlScriptRoot = http://localhost/cgi-bin/1.0.4 (a guess)
+// urlScriptDir = http://localhost/cgi-bin/1.0.4/members/app (same as
urlDir)
+// urlDocDir = http://localhost/1.0.4/members/app (remove cgi-bin)
+
+Ext.app.init = function () {
+ var appName, urlFull, urlBase, urlDir, urlFile, urlParams;
+ var urlDocRoot, urlScriptRoot, urlDocDir, urlScriptDir;
+ var pos, pos2;
+
+ // augment the deployment values with values we can autodetect
+ // Do some sanity checks
+ if (!Ext.app.options) {
+ Ext.app.options = new Object();
+ }
+ var options = Ext.app.options;
+
+ if (!Ext.app.conf) {
+ Ext.app.conf = new Object();
+ }
+ if (!Ext.app.conf.global) {
+ Ext.app.conf.global = new Object();
+ }
+
+ // if (options.urlDocRoot == null) {
+ // alert("ERROR: options.urlDocRoot not set\nDefine 'var options = {
urlDocRoot : 'value' }; in your app deployment values");
+ // }
+ // if (options.urlScriptRoot == null) {
+ // alert("ERROR: options.urlScriptRoot not set\nDefine 'var options =
{ urlScriptRoot : 'value' }; in your app deployment values");
+ // }
+
+ // This parsing is (or should be) 100% JavaScript 1.0 (!) compatible
+
+ urlFull = document.location.href;
+
+ pos = urlFull.lastIndexOf("?");
+ if (pos > 0) {
+ urlParams = urlFull.substring(pos, urlFull.length);
+ urlBase = urlFull.substring(0, pos);
+ }
+ else {
+ urlParams = "";
+ urlBase = urlFull;
+ }
+ pos = urlBase.lastIndexOf("/");
+ if (pos > 0 && pos < urlBase.length - 1) {
+ urlFile = urlBase.substring(pos+1, urlBase.length);
+ urlDir = urlBase.substring(0, pos);
+ }
+ else {
+ urlFile = "";
+ urlDir = urlBase;
+ }
+ pos = urlFile.lastIndexOf(".");
+ if (pos > 0) {
+ appName = urlFile.substring(0, pos);
+ }
+ else if (urlFile) {
+ appName = urlFile;
+ }
+ else {
+ appName = "main";
+ }
+
+ pos = urlDir.lastIndexOf("/cgi-bin/");
+ if (pos >= 0) {
+ var part1 = urlFull.substring(0, pos);
+ var part2 = urlFull.substring(pos+8, urlFull.length);
+ urlDocDir = part1 + part2;
+ urlScriptDir = urlDir;
+ }
+ else { // no "/cgi-bin/"
+ urlDocDir = urlDir;
+ pos = urlDir.indexOf("http");
+ if (pos == 0) {
+ pos = urlDir.indexOf("/",9);
+ urlScriptDir = urlDir.substring(0,pos) + "/cgi-bin" +
urlDir.substring(pos,urlDir.length);
+ }
+ else {
+ urlScriptDir = "/cgi-bin" + urlDir;
+ }
+ }
+
+ pos = urlDocDir.indexOf("http");
+ if (pos == 0) {
+ pos = urlDocDir.indexOf("/",9);
+ pos2 = urlDocDir.indexOf("/",pos+1);
+ urlDocRoot = urlDocDir.substring(0,pos2);
+ urlScriptRoot = urlDocDir.substring(0,pos) + "/cgi-bin" +
urlDocDir.substring(pos,pos2);
+
+ // alert("urlDocRoot = " + urlDocRoot + "\n" +
+ // "urlScriptRoot = " + urlScriptRoot + "\n" +
+ // "urlDocDir = " + urlDocDir + "\n" +
+ // "urlScriptDir = " + urlScriptDir + "\n" +
+ // "pos = " + pos + "; pos2 = " + pos2);
+ }
+ else {
+ pos = urlDocDir.indexOf("/",1);
+ urlDocRoot = urlDocDir.substring(0,pos);
+ urlScriptRoot = "/cgi-bin" + urlDocDir.substring(0,pos);
+ }
+
+ if (options.urlFull == null) options.urlFull = urlFull;
+ if (options.urlBase == null) options.urlBase = urlBase;
+ if (options.urlDir == null) options.urlDir = urlDir;
+ if (options.urlFile == null) options.urlFile = urlFile;
+ if (options.urlParams == null) options.urlParams = urlParams;
+ if (options.urlDocRoot == null) options.urlDocRoot = urlDocRoot;
+ if (options.urlScriptRoot == null) options.urlScriptRoot = urlScriptRoot;
+ if (options.urlDocDir == null) options.urlDocDir = urlDocDir;
+ if (options.urlScriptDir == null) options.urlScriptDir = urlScriptDir;
+ if (options.appName == null) options.appName = appName;
+
+ // Only during development time would you allow the person
+ // at the browser to overwrite your deployment values.
+ // To enable this, set options.urlConfigOK = 1.
+ // alert("urlConfigOK=" + options.urlConfigOK);
+ if (options.urlConfigOK != null && options.urlConfigOK != 0) {
+ urlParams = options.urlParams;
+ if (urlParams != "") {
+ // get rid of leading "?"
+ urlParams = urlParams.substring(1,urlParams.length);
+ }
+ var urlParamAssignment, urlParam, urlParamValue;
+ // I might need to do some unescaping here. We'll see.
+ while (urlParams != "") {
+ pos = urlParams.indexOf("&");
+ if (pos > 0) {
+ urlParamAssignment = urlParams.substring(0,pos);
+ urlParams = urlParams.substring(pos+1,urlParams.length);
+ }
+ else {
+ urlParamAssignment = urlParams;
+ urlParams = "";
+ }
+ pos = urlParamAssignment.indexOf("=");
+ if (pos > 0) {
+ urlParam = urlParamAssignment.substring(0,pos);
+ urlParamValue =
urlParamAssignment.substring(pos+1,urlParamAssignment.length);
+ }
+ else {
+ urlParam = urlParamAssignmen;
+ urlParamValue = 1;
+ }
+ options[urlParam] = urlParamValue;
+ // alert("urlConfig: " + urlParam + "=" + urlParamValue);
+ }
+ }
+
+ // These values have wide cross-browser support.
+ // They are useful for determining what JavaScript features/bugs are
supported.
+ // navigator.userAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1;
en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2
+ // navigator.appCodeName: Mozilla
+ // navigator.appName: Netscape
+ // navigator.appVersion: 5.0 (Windows; en-US)
+ if (options.userAgent == null) options.userAgent =
navigator.userAgent;
+ if (options.appCodeName == null) options.appCodeName =
navigator.appCodeName;
+ if (options.appName == null) options.appName =
navigator.appName;
+ if (options.appVersion == null) options.appVersion =
navigator.appVersion;
+
+ // These are (or should be) derived from the above 4 "standard" values
+ if (options.browserVersion == null) options.browserVersion =
parseInt(navigator.appVersion);
+ if (options.lang == null) options.lang = 'en';
+ if (options.langx == null) options.langx = 'en-US';
+
+ // These must have some default value if they are not set already
+ if (options.theme == null) options.theme = 'js-app';
+
+ Ext.app.context = new Ext.app.Context();
+}
+
+Ext.app.Context = function () {
+ this.session = new Object();
+ this.cache = new Object();
+ this.cache["SessionObject"] = new Object();
+ this.precache = new Object();
+
+ this.service = function (serviceType, serviceName, codedConf) {
+ // alert("context.service(" + serviceType + "," + serviceName + "," +
codedConf + ")");
+ var s;
+ if (this.cache[serviceType] != null &&
+ this.cache[serviceType][serviceName] != null) {
+ s = this.cache[serviceType][serviceName];
+ }
+ else {
+ if (!codedConf && serviceName != "default") {
+ //alert("context.service(" + serviceType + "," + serviceName +
") not cached and no codedConf given");
+ }
+ // get the precache values
+ var precacheValues;
+ if (this.precache[serviceType] != null) {
+ if (this.precache[serviceType][serviceName] != null) {
+ precacheValues = this.precache[serviceType][serviceName];
+ }
+ }
+ // get the serviceConf
+ var serviceConf;
+ if (appConf[serviceType]) {
+ if (appConf[serviceType][serviceName] != null) {
+ serviceConf = appConf[serviceType][serviceName];
+ }
+ }
+ // alert("service(" + serviceType + "," + serviceName + "," +
codedConf + ") : conf=" + serviceConf);
+ if (!serviceConf && codedConf) {
+ serviceConf = codedConf;
+ }
+
+ // get the serviceTypeConf
+ var serviceTypeName, serviceTypeType, serviceTypeConf;
+ if (serviceConf != null) {
+ serviceTypeName = serviceConf.serviceType;
+ }
+ if (serviceTypeName == null) {
+ serviceTypeName = "default";
+ }
+ serviceTypeType = serviceType + "Type";
+ if (appConf[serviceTypeType] != null) {
+ if (appConf[serviceTypeType][serviceTypeName] != null) {
+ serviceTypeConf =
appConf[serviceTypeType][serviceTypeName];
+ }
+ }
+
+ // get serviceClass
+ var serviceClass;
+ if (serviceConf != null && serviceConf.serviceClass != null) {
+ serviceClass = serviceConf.serviceClass;
+ }
+ else if (serviceTypeConf != null && serviceTypeConf.serviceClass
!= null) {
+ serviceClass = serviceTypeConf.serviceClass;
+ }
+ else {
+ serviceClass = serviceType;
+ }
+
+ // construct an instance of the class
+ var serviceConstructor = 'var s = new ' + serviceClass + '();';
+ // alert(serviceConstructor);
+ eval(serviceConstructor);
+
+ // initialize some standard attributes
+ if (precacheValues) {
+ this.copyObject(precacheValues, s);
+ }
+ this.copyObject(serviceConf, s);
+ this.copyObject(serviceTypeConf, s);
+ s.serviceName = serviceName;
+ s.serviceType = serviceType;
+ s.serviceClass = serviceClass;
+ if (this.cache[serviceType] == null) {
+ this.cache[serviceType] = new Object();
+ }
+ this.cache[serviceType][serviceName] = s;
+
+ if (s.initService) {
+ s.initService();
+ }
+ s.init();
+ }
+ return(s);
+ }
+
+ this.repository = function (serviceName,conf) {
+ return(this.service("Repository",serviceName,conf));
+ }
+
+ this.sessionObject = function (serviceName,conf) {
+ return(this.service("SessionObject",serviceName,conf));
+ }
+
+ this.valueDomain = function (serviceName,conf) {
+ return(this.service("ValueDomain",serviceName,conf));
+ }
+
+ this.widget = function (serviceName,conf) {
+ return(this.service("SessionObject",serviceName,conf));
+ }
+
+ this.getValue = function (serviceName, attrib, valueDefault, setDefault) {
+ var s, container, value, pos;
+ if (serviceName) {
+ if (typeof serviceName == "string") {
+ if (!attrib) {
+ pos = serviceName.lastIndexOf("-");
+ if (pos >= 0) {
+ attrib =
serviceName.substring(pos+1,serviceName.length);
+ serviceName = serviceName.substring(0,pos);
+ }
+ else {
+ attrib = serviceName;
+ serviceName = "default";
+ }
+ }
+ s = this.cache["SessionObject"][serviceName];
+ if (!s && this.precache["SessionObject"] != null &&
+ this.precache["SessionObject"][serviceName] != null)
{
+ s = this.precache["SessionObject"][serviceName];
+ }
+ if (!s) {
+ return(null);
+ }
+ }
+ else {
+ s = serviceName;
+ }
+ value = s[attrib];
+ }
+ if (value == null && valueDefault != null) {
+ value = valueDefault;
+ if (setDefault) s[attrib] = value;
+ }
+ return(value);
+ }
+
+ this.setValue = function (serviceName, attrib, value) {
+ var s, container, value, pos;
+ var changed = 0;
+ if (serviceName) {
+ if (typeof serviceName == "string") {
+ if (!attrib) {
+ pos = serviceName.lastIndexOf("-");
+ if (pos >= 0) {
+ attrib =
serviceName.substring(pos+1,serviceName.length);
+ serviceName = serviceName.substring(0,pos);
+ }
+ else {
+ attrib = serviceName;
+ serviceName = "default";
+ }
+ }
+ s = this.cache["SessionObject"][serviceName];
+ if (!s) {
+ if (this.precache["SessionObject"] == null) {
+ this.precache["SessionObject"] = new Object();
+ }
+ if (this.precache["SessionObject"][serviceName] == null) {
+ this.precache["SessionObject"][serviceName] = new
Object();
+ }
+ s = this.precache["SessionObject"][serviceName];
+ }
+ }
+ else {
+ s = serviceName;
+ }
+ if (s[attrib] != value) {
+ s[attrib] = value;
+ changed = 1;
+ }
+ }
+ return(changed);
+ }
+
+ this.getValues = function (serviceName, attrib, valueDefault, setDefault) {
+ // alert(this + ".getValue(" + serviceName + ", " + attrib + ", " +
valueDefault + ", " + setDefault + ")");
+ var value = this.getValue(serviceName, attrib, valueDefault,
setDefault);
+ if (value == null) {
+ value = "";
+ }
+ return(value.split(","));
+ }
+
+ this.setValues = function (serviceName, attrib, values) {
+ if (typeof(values) == "Array") {
+ return(this.setValue(serviceName, attrib, values.join(",")));
+ }
+ else {
+ return(this.setValue(serviceName, attrib, values));
+ }
+ }
+
+ this.getDOMValue = function (name) {
+ var value;
+ var elem = this.getElementByName(name);
+ if (elem) {
+ var i;
+ if (elem.value != null) {
+ value = elem.value;
+ }
+ else if (elem.type == "select-one") {
+ value = elem.options[elem.selectedIndex].value;
+ }
+ else if (elem.type == "select-multiple") {
+ for (i = 0; i < elem.options.length; i++) {
+ if (elem.options[i].selected) {
+ if (value == null) { value = elem.options[i].value; }
+ else { value += "," +
elem.options[i].value; }
+ }
+ }
+ }
+ }
+ return(value);
+ }
+
+ this.setDOMValue = function (name, value) {
+ var elem = this.getElementByName(name);
+ // alert("setDOMValue(" + name + "," + value + ") [" + elem + "]");
+ var changed = 0;
+ if (elem) {
+ var i;
+ var type = elem.type;
+ if (type == null) {
+ // do nothing
+ }
+ else if (type == "select-one") {
+ // It seems that IE and DOM1 allow elem.value = value
+ // for a "select-one" element, but NS4+ and even Firefox
+ // don't seem to allow this.
+ if (elem.options[elem.selectedIndex].value != value) {
+ elem.options[elem.selectedIndex].selected = false;
+ for (i = 0; i < elem.options.length; i++) {
+ if (elem.options[i].value == value) {
+ if (elem.options[i].selected != true) {
+ elem.options[i].selected = true;
+ changed = 1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ else if (type == "select-multiple") {
+ var values;
+ if (value == null) {
+ values = [];
+ }
+ else {
+ values = value.split(",");
+ }
+ // set up a hash of the values to be set (comma-sep in "value")
+ var valuesToBeSet = new Object();
+ for (i = 0; i < values.length; i++) {
+ valuesToBeSet[values[i]] = 1;
+ }
+ for (i = 0; i < elem.options.length; i++) {
+ if (elem.options[i].selected) {
+ if (! valuesToBeSet[elem.options[i].value]) {
+ elem.options[i].selected = false;
+ changed = 1;
+ }
+ }
+ else {
+ if (valuesToBeSet[elem.options[i].value]) {
+ elem.options[i].selected = true;
+ changed = 1;
+ }
+ }
+ }
+ }
+ else if (type == "hidden" ||
+ type == "text" ||
+ type == "textarea" ||
+ type == "radio" ||
+ type == "checkbox" ||
+ type == "file" ||
+ type == "image" ||
+ type == "password" ||
+ type == "reset" ||
+ type == "submit" ||
+ type == "button") {
+ if (elem.value != value) {
+ elem.value = value;
+ changed = 1;
+ }
+ }
+ }
+ return(changed);
+ }
+}
+
+Ext.app.init();
+
+// *******************************************************************
+// CLASS: Service
+// *******************************************************************
+Ext.app.Service = function () {
+ this.html = html;
+ function html () {
+ var html = '[' + this.serviceType + '(' + this.serviceName + ') : ' +
this.serviceClass + ']';
+ return(html);
+ }
+ this.write = write;
+ function write () {
+ document.write(this.html());
+ }
+ this.init = init;
+ function init () {
+ // do nothing (available for overriding in a subclass)
+ }
+}
+
+// *******************************************************************
+// CLASS: SessionObject
+// *******************************************************************
+Ext.app.SessionObject = function () {
+
+ // this.init = init;
+ // function init () {
+ // }
+
+ this.container = container;
+ function container (serviceName) {
+ if (serviceName == null) {
+ serviceName = this.serviceName;
+ }
+ var containerServiceName;
+ if (serviceName != "default") {
+ var pos = serviceName.lastIndexOf("-");
+ if (pos <= 0) {
+ containerServiceName = "default";
+ }
+ else {
+ containerServiceName = serviceName.substring(0, pos);
+ }
+ }
+ return(containerServiceName);
+ }
+
+ // not sure if anyone needs this. it is provided in parallel to the
container() function
+ this.containerAttrib = containerAttrib;
+ function containerAttrib (serviceName) {
+ if (serviceName == null) {
+ serviceName = this.serviceName;
+ }
+ var containerAttribName;
+ if (serviceName != "default") {
+ var pos = serviceName.lastIndexOf("-");
+ if (pos <= 0) {
+ containerAttribName = "serviceName";
+ }
+ else {
+ containerAttribName = serviceName.substring(pos+1,
serviceName.length);
+ }
+ }
+ return(containerAttribName);
+ }
+
+ // This is a tricky area for compatibility between IE and Firefox,
particularly
+ // when it comes to arriving at the page via the "Back" button.
+ this.initDefaultValue = initDefaultValue;
+ function initDefaultValue () {
+ var currentValue = context.getValue(this.serviceName); // get if
from the session
+ if (currentValue == null) { // if not...
+ currentValue = context.getDOMValue(this.serviceName); // try
getting from the DOM
+ if (currentValue != null) { // if so
(i.e. "Back" button) ...
+ context.setValue(this.serviceName, null, currentValue); //
set it in the session
+ }
+ }
+ if (currentValue == null) { //
otherwise ...
+ if (this["default"] != null) {
+ context.setValue(this.serviceName, null, this["default"]);
+ }
+ else {
+ context.setValue(this.serviceName, null, "");
+ }
+ }
+ }
+
+ this.validateCurrentValues = validateCurrentValues;
+ function validateCurrentValues () {
+ var values, validatedValues;
+ if (this.controlWidget || this.validate) {
+ values = context.getValue(this.serviceName); // get as a single
string
+ validatedValues = this.validateValues(values);
+ this.setCurrentValue(validatedValues); // set as a single string
+ }
+ }
+
+ this.validateValues = validateValues;
+ function validateValues (values) {
+ var initialValues;
+ var i, value, validValues, valueIsValid, validationPattern;
+ var possibleValues, wantarray;
+ possibleValues = this.getValues();
+ // alert(this.serviceName + ".validateValues(" + values + ") : [" +
typeof(values) + "]");
+ if (typeof(values) == "Array") {
+ initialValues = values;
+ wantarray = 1;
+ }
+ else if (possibleValues != null) {
+ if (values == "") {
+ initialValues = [];
+ }
+ else {
+ initialValues = values.split(",");
+ }
+ wantarray = 0;
+ }
+ else {
+ initialValues = new Array();
+ initialValues[0] = values;
+ wantarray = 0;
+ }
+ // begin keeping a list of the *valid* values
+ validValues = new Array();
+ // they might be validated by an enumerated list...
+ if (possibleValues && possibleValues.length > 0) {
+ // make a set of the valid values
+ valueIsValid = new Object();
+ for (i = 0; i < possibleValues.length; i++) {
+ valueIsValid[possibleValues[i]] = 1;
+ }
+ // check each possible value for inclusion in the set
+ for (i = 0; i < initialValues.length; i++) {
+ if (valueIsValid[initialValues[i]]) {
+ validValues.push(initialValues[i]);
+ // alert(this.serviceName + ".validateValues() : " +
initialValues[i] + " is valid");
+ }
+ }
+ // alert(this.serviceName + ".validateValues() : valid.len=" +
validValues.length + " possible.len=" + possibleValues.length);
+ if (validValues.length == 0 && ! this.nullable &&
possibleValues.length > 0) {
+ validValues[0] = possibleValues[0];
+ // alert(this.serviceName + ".validateValues() : setting
value=" + validValues[0]);
+ }
+ }
+ // they might be validated by a regular expression ...
+ else if (this.validate) {
+ validationPattern = this.validate;
+ validValues = new Array();
+ for (v = 0; v < initialValues.length; v++) {
+ value = initialValues[v];
+ if (value.match(validationPattern) != null) {
+ validValues.push(value);
+ }
+ }
+ if (validValues.length == 0 && ! this.nullable && this["default"])
{
+ validValues[0] = this["default"];
+ }
+ }
+ else {
+ validValues = initialValues;
+ if (validValues.length == 0 && ! this.nullable && this["default"])
{
+ validValues[0] = this["default"];
+ }
+ }
+ if (wantarray) {
+ return(validValues);
+ }
+ else {
+ return(validValues.join(","));
+ }
+ }
+
+ this.getCurrentValue = getCurrentValue;
+ function getCurrentValue () {
+ return(context.getValue(this.serviceName));
+ }
+
+ this.setCurrentValue = setCurrentValue;
+ function setCurrentValue (value) {
+ if (this.validate) {
+ value = this.validateValues(value);
+ }
+ var changed = context.setValue(this.serviceName, null, value);
+ return(changed);
+ }
+
+ this.getCurrentValues = getCurrentValues;
+ function getCurrentValues () {
+ var value = this.getCurrentValue();
+ if (value == null || value == "") {
+ return(new Array());
+ }
+ else {
+ return(value.split(","));
+ }
+ }
+
+ this.setCurrentValues = setCurrentValues;
+ function setCurrentValues (values) {
+ this.setCurrentValue(values.join(","));
+ }
+
+ this.getValues = getValues;
+ function getValues () {
+ var values = this.values;
+ var controlValue, controlValueOptions;
+ if (values == null && this.domain) {
+ var domain = context.service("ValueDomain", this.domain);
+ values = domain.getValues();
+ }
+ if (values == null && this.controlWidget && this.controlValueOptions) {
+ controlValueOptions = this.controlValueOptions;
+ controlValue = context.getValue(this.controlWidget);
+ if (controlValueOptions[controlValue] &&
controlValueOptions[controlValue].values) {
+ values = controlValueOptions[controlValue].values;
+ }
+ else if (controlValueOptions["default"] &&
controlValueOptions["default"].values) {
+ values = controlValueOptions["default"].values;
+ }
+ else {
+ values = this.values;
+ }
+ }
+ if (values == null) {
+ values = new Array();
+ }
+ return(values);
+ }
+
+ this.getLabels = getLabels;
+ function getLabels () {
+ var labels = this.labels;
+ var controlValue, controlValueOptions;
+ if (labels == null && this.domain) {
+ var domain = context.service("ValueDomain", this.domain);
+ labels = domain.getLabels();
+ }
+ if (labels == null && this.controlWidget && this.controlValueOptions) {
+ controlValueOptions = this.controlValueOptions;
+ controlValue = context.getValue(this.controlWidget);
+ if (controlValueOptions[controlValue] &&
controlValueOptions[controlValue].labels) {
+ labels = controlValueOptions[controlValue].labels;
+ }
+ else if (controlValueOptions["default"] &&
controlValueOptions["default"].labels) {
+ labels = controlValueOptions["default"].labels;
+ }
+ else {
+ labels = this.labels;
+ }
}
- return null;
+ if (labels == null) {
+ labels = new Object();
+ }
+ return(labels);
}
-});
\ No newline at end of file
+
+ this.handleEvent = handleEvent;
+ function handleEvent (thisServiceName, eventServiceName, eventName,
eventArgs) {
+ var containerServiceName = this.container(thisServiceName);
+ var argString;
+ if (eventArgs == null) {
+ argString = "null";
+ }
+ else {
+ var i;
+ argString = "";
+ for (i = 0; i < eventArgs.length; i++) {
+ argString += (i == 0) ? "[" : ",";
+ argString += eventArgs[i];
+ }
+ argString += "]";
+ }
+ var handled;
+ if (containerServiceName) {
+ var s = context.service("SessionObject", containerServiceName);
+ handled = s.handleEvent(containerServiceName, eventServiceName,
eventName, eventArgs);
+ }
+ else if (eventName == "change") { // ignore change events that are
not otherwise handled
+ handled = 1;
+ }
+ else {
+ context.log("handleEvent(" + thisServiceName + "," +
eventServiceName + "," +
+ eventName + "," + argString + ") : Event not handled\n");
+ handled = 0;
+ }
+ return(handled);
+ }
+
+ this.getId = getId;
+ function getId (withAttrib) {
+ var id = this.serviceName;
+ // id.replace(/\./g,"-");
+ if (withAttrib != null && withAttrib) {
+ id = ' id="' + id + '"';
+ }
+ return(id);
+ }
+}
+Ext.app.SessionObject.prototype = new Ext.app.Service();
+
+// *******************************************************************
+// CLASS: ValueDomain
+// *******************************************************************
+Ext.app.ValueDomain = function () {
+
+ this.getLabels = getLabels;
+ function getLabels () {
+ var labels = this.labels;
+ if (labels == null) {
+ labels = new Object();
+ }
+ return(labels);
+ }
+
+ this.getValues = getValues;
+ function getValues () {
+ var values = this.values;
+ var labels, key;
+ if (values == null) {
+ values = new Array();
+ labels = this.labels;
+ if (labels != null) {
+ for (key in labels) {
+ values.push(key);
+ }
+ values.sort();
+ }
+ }
+ return(values);
+ }
+}
+Ext.app.ValueDomain.prototype = new Ext.app.Service();
+
+// *******************************************************************
+// CLASS: Repository
+// *******************************************************************
+Ext.app.Repository = function () {
+
+ this.sort = sort;
+ function sort (rows, sortKeys, sortType, sortDir) {
+ var sortedRows = rows;
+ return(sortedRows);
+ }
+}
+Ext.app.Repository.prototype = new Ext.app.Service();
+
Modified: p5ee/trunk/App-Widget-ExtJS/lib/App/SessionObject/ExtJS/Store.pm
==============================================================================
--- p5ee/trunk/App-Widget-ExtJS/lib/App/SessionObject/ExtJS/Store.pm
(original)
+++ p5ee/trunk/App-Widget-ExtJS/lib/App/SessionObject/ExtJS/Store.pm Tue Sep
1 12:50:17 2009
@@ -39,7 +39,7 @@
}
my $start = $context->so_get("start") || 0;
- my $limit = $context->so_get("limit") || 25;
+ my $limit = $context->so_get("limit");
my $options = { startrow => $start+1, endrow => $start+$limit };
if ($sort) {
my $sort_spec = $sort;
Modified: p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS.pm
==============================================================================
--- p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS.pm (original)
+++ p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS.pm Tue Sep 1 12:50:17 2009
@@ -327,6 +327,12 @@
$response->include("javascript", $js);
$response->include("javascript", "$html_url_dir/App/ext-addon.js");
$response->include("javascript", "$html_url_dir/App/ext-app.js");
+ my $js_additional = <<EOF;
+<script type="text/javascript">
+Ext.BLANK_IMAGE_URL = '$html_url_dir/$version/resources/images/default/s.gif';
+</script>
+EOF
+ $response->include("javascript", $js_additional);
}
&App::sub_exit() if ($App::trace);
Modified: p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm
==============================================================================
--- p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm
(original)
+++ p5ee/trunk/App-Widget-ExtJS/lib/App/Widget/ExtJS/DataTable.pm Tue Sep
1 12:50:17 2009
@@ -50,6 +50,28 @@
$self->{keycolidx} = \...@keycolidx if ($#keycolidx ==
$#$primary_key);
}
}
+
+ my $filterable = $self->{filterable};
+ my $lock_columns = $self->{lock_columns};
+ my $context = $self->{context};
+ my $options = $context->{options};
+ my $html_url_dir = $options->{html_url_dir} || "";
+ my $ext_extension_dir = $options->{ext_extension_dir} || "/App";
+
+ my ($response, $js, $css);
+ if ($lock_columns || $filterable) {
+ $response = $context->response() if (!$response);
+ $css = "${html_url_dir}${ext_extension_dir}/Ext.ux.ColumnLock.css";
+ $js = "${html_url_dir}${ext_extension_dir}/Ext.ux.ColumnLock.js";
+ if (!$response->is_included("javascript", $js)) {
+ $response->include("css", $css);
+ $response->include("javascript", $js);
+ }
+ $js =
"${html_url_dir}${ext_extension_dir}/Ext.ux.grid.LockingGridHeaderFilters.js";
+ if (!$response->is_included("javascript", $js)) {
+ $response->include("javascript", $js);
+ }
+ }
}
sub repository {
@@ -237,8 +259,8 @@
my $order_by = $self->{order_by} || $self->{ordercols}; #
ordercols is deprecated in favor of order_by
my $group_by = $self->{group_by};
my $direction = $self->{direction} || $self->{directions} || {}; #
directions is deprecated in favor of direction
- $startrow = $self->get("startrow", 1, 1);
- $maxrows = $self->get("maxrows", 20, 1);
+ $startrow = $self->get("startrow", 1, 1);
+ $maxrows = $self->get("maxrows");
$endrow = ($maxrows != 0) ? ($startrow + $maxrows - 1) : 0;
if ($App::DEBUG && $self->{context}->dbg(1)) {
@@ -284,22 +306,30 @@
$value = "" if (!defined $value);
my $table = $self->{table} || "unknown";
+ my $scrollable = $self->{scrollable};
+ my $sortable = $self->{sortable};
+ my $filterable = $self->{filterable};
+ my $editable = $self->{editable};
+
+ my $lock_columns = $self->{lock_columns};
+
my $rep = $self->repository();
my $tabledef = $rep->get_table_def($table);
- my $data = $self->get_data();
- my $js_data = $self->serialize_as_javascript($data);
-
my $columns = $self->get_columns();
+ my $columns_list = join(",", @$columns);
my $column_data_defs = [];
my $column_display_defs = [];
- my ($column_data_def, $column_display_def, $label);
- foreach my $column (@$columns) {
- $column_data_def = { name => $column };
+ my ($column_data_def, $column_display_def, $label, $column);
+ for (my $i = 0; $i <= $#$columns; $i++) {
+ $column = $columns->[$i];
+ $column_data_def = { name => $column, mapping => $i };
push(@$column_data_defs, $column_data_def);
$label = $tabledef->{column}{$column}{label} || $column;
$label =~ s/<br>//g;
- $column_display_def = { header => $label, sortable => "true", width =>
100, dataIndex => $column };
+ $column_display_def = { header => $label, width => 100, dataIndex =>
$column };
+ $column_display_def->{sortable} = "true" if ($sortable);
+ $column_display_def->{filter} = {xtype => "textfield"} if
($filterable);
push(@$column_display_defs, $column_display_def);
}
my $js_column_data_defs =
$self->serialize_as_javascript($column_data_defs);
@@ -314,7 +344,78 @@
$table_label = ucfirst($table_label);
}
- my $html = <<EOF;
+ my ($html);
+
+ if ($scrollable) {
+ my $context = $self->{context};
+ my $options = $context->{options};
+
+ my $order_by = $self->{order_by};
+ $order_by = join(",", @$order_by) if (ref($order_by) eq "ARRAY");
+ my $order_by_js = $order_by ? ", order_by: '$order_by'" : "";
+
+ my $script_url_dir = $options->{script_url_dir} || die "The parameter
'script_url_dir' must be set in the option file";
+ my $script_url = "$script_url_dir/App/app-ext-repository";
+ my $pagesize = 100;
+
+ my (@plugins);
+ my $plugins_js = "";
+ if ($filterable || $lock_columns) {
+ push(@plugins, "Ext.ux.grid.LockingGridHeaderFilters");
+ }
+ $plugins_js .= "\n plugins: [new " . join("(), new ", @plugins)
. "()],";
+
+ $html = <<EOF;
+<script type="text/javascript">
+Ext.onReady(function(){
+
+ // create the data store
+ var dataStore = new Ext.data.JsonStore({
+ id: '$name-store',
+ fields: $js_column_data_defs,
+ root: 'data',
+ totalProperty: 'totalCount',
+ remoteSort: true,
+ proxy: new Ext.data.HttpProxy({ url: '$script_url', method: 'POST' }),
+ baseParams: {table: '$table', columns: '$columns_list'$order_by_js}
+ });
+
+ var pagingBar = new Ext.PagingToolbar({
+ pageSize: $pagesize,
+ store: dataStore,
+ displayInfo: true,
+ displayMsg: 'Displaying records {0} - {1} of {2}',
+ emptyMsg: 'No data to display'
+ });
+
+ // create the Grid
+ var grid = new Ext.grid.GridPanel({
+ id: '$name-grid',
+ store: dataStore,$plugins_js
+ columns: $js_column_display_defs,
+ stripeRows: true,
+ frame: true,
+ // stateful: true,
+ height: $height,
+ width: $width,
+ title: '$table_label',
+ bbar: pagingBar
+ });
+
+ grid.render('$name');
+ dataStore.load({params: {start: 0, limit: $pagesize}});
+
+ grid.getSelectionModel().selectFirstRow();
+});
+</script>
+<div id="$name"></div>
+EOF
+ }
+ else {
+ my $data = $self->get_data();
+ my $js_data = $self->serialize_as_javascript($data);
+
+ $html = <<EOF;
<script type="text/javascript">
Ext.onReady(function(){
@@ -347,6 +448,7 @@
</script>
<div id="$name"></div>
EOF
+ }
&App::sub_exit("<html...>") if ($App::trace);
return($html);