danh2000
4 Nov 2008, 12:13 AM
I've created a new data reader to consume a lightweight JSON format modelled on CSV. It basically avoids the repetition of property names in records so reduces bandwidth and response times.
Here's a basic example:
var Employee = Ext.data.Record.create([
{name: 'firstname'},
{name: 'job', mapping: 'occupation'}
]);
var myReader = new Ext.ux.data.JsonCsvReader({
totalProperty: "results",
root: "records",
id: "id"
}, Employee);
//dummy data
var recs1 = {
'results': 2,
'records': {
'cols': ['id','firstname','occupation'],
'rows': [
[1,'Bill','Gardener'],
[2,'Ben','Horticulturist']
]
}
};
//consume test
var readRecs1 = myReader.readRecords(recs1);
console.log(readRecs1);
console.log(readRecs1.records[0].get('job'));
console.log(readRecs1.records[1].get('firstname'));
There are a couple of posts on my blog if interested:
Ajax Data Transfer - XML, JSON or CSV (http://technomedia.co.uk/blog/2008/10/ajax-data-transfer-xml-json-csv/)
Ajax Data Transfer - JsonCsvReader for ExtJS (http://technomedia.co.uk/blog/2008/11/ajax-data-transfer-jsoncsvreader-for-extjs/)
And here's the code:
Ext.namespace('Ext.ux.data');
/**
* @description Data reader class to create an Array of Ext.data.Record objects from specialised block of JSON.
* @author <a href="dan.humphrey@technomedia.co.uk">Dan Humphrey</a>
* @class Ext.ux.data.JsonCsvReader
* @extends Ext.data.JsonReader
* @constructor
* @version 0.1
* @license Unlikely
* @param {Object} meta Metadata configuration options.
* @param {Object} recordType Either an Array of field definition objects as passed to Ext.data.Record.create, or an Ext.data.Record constructor created using Ext.data.Record.create.
*/
Ext.ux.data.JsonCsvReader = function(meta, recordType){
meta = meta || {};
Ext.ux.data.JsonCsvReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.ux.data.JsonCsvReader, Ext.data.JsonReader, {
/**
* @cfg {String} totalProperty Name of the property from which to retrieve the total number of records
* in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
* paged from the remote server.
*/
totalProperty: null,
/**
* @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
*/
successProperty: null,
/**
* @cfg {String} cols Name of the property from which to retrieve the columns.
*/
cols: 'cols',
/**
* @cfg {String} rows Name of the property from which to retrieve the rows.
*/
rows: 'rows',
/**
* @cfg {String} root Name of the property which contains the Array of row objects.
*/
root: null,
/**
* @cfg {String} id Name of the property within a row object that contains a record identifier value.
*/
id: null,
/**
* Create a data block containing Ext.data.Records from a Json object containing JsonCsv formatted data.
* @methodOf Ext.ux.data.JsonCsvReader
* @param {Object} o An object which contains an Array of row objects in the property specified
* in the config as 'root, and optionally a property, specified in the config as 'totalProperty'
* which contains the total size of the dataset.
* @return {Object} data A data block which is used by an Ext.data.Store object as
* a cache of Ext.data.Records.
*/
readRecords: function(o){
this.jsonData = o;
//dynamic meta
if (o.metaData) {
delete this.ef;
this.meta = o.metaData;
this.recordType = Ext.data.Record.create(o.metaData.fields);
this.onMetaChange(this.meta, this.recordType, o);
}
var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length;
var root = o;
if (s.root) {
try {
root = o[s.root] || o;
}
catch (e) {
root = o;
}
}
//extra accessors
var colsProp = s.cols ? s.cols : 'cols';
var rowsProp = s.rows ? s.rows : 'rows';
this.getCols = function(){
return root[colsProp];
};
this.getRows = function(){
return root[rowsProp];
};
if (s.totalProperty) {
this.getTotal = this.getJsonAccessor(s.totalProperty);
}
if (s.successProperty) {
this.getSuccess = this.getJsonAccessor(s.successProperty);
}
//default properties
var cols = this.getCols(), rows = this.getRows(), c = cols.length, r = rows.length, totalRecords = r, success = true, v;
var data = {}; // data block to pass to super
//override defualts
if (s.totalProperty) {
v = parseInt(this.getTotal(o), 10);
if (!isNaN(v)) {
totalRecords = v;
}
data[s.totalProperty] = totalRecords;
}
if (s.successProperty) {
v = this.getSuccess(o);
if (v === false || v === 'false') {
success = false;
}
data[s.successProperty] = success;
}
//loop through data and recreate normal JSON data for the superclass
var recs = [];
for (var iRow = 0; iRow < r; iRow++) {
var rec = {};
for (var iCol = 0; iCol < c; iCol++) {
rec[cols[iCol]] = rows[iRow][iCol];
}
recs.push(rec);
}
if (s.root) {
data[s.root] = recs;
}
else {
data = recs;
}
return Ext.ux.data.JsonCsvReader.superclass.readRecords.call(this, data);
}
});
Hope someone finds it useful.
Here's a basic example:
var Employee = Ext.data.Record.create([
{name: 'firstname'},
{name: 'job', mapping: 'occupation'}
]);
var myReader = new Ext.ux.data.JsonCsvReader({
totalProperty: "results",
root: "records",
id: "id"
}, Employee);
//dummy data
var recs1 = {
'results': 2,
'records': {
'cols': ['id','firstname','occupation'],
'rows': [
[1,'Bill','Gardener'],
[2,'Ben','Horticulturist']
]
}
};
//consume test
var readRecs1 = myReader.readRecords(recs1);
console.log(readRecs1);
console.log(readRecs1.records[0].get('job'));
console.log(readRecs1.records[1].get('firstname'));
There are a couple of posts on my blog if interested:
Ajax Data Transfer - XML, JSON or CSV (http://technomedia.co.uk/blog/2008/10/ajax-data-transfer-xml-json-csv/)
Ajax Data Transfer - JsonCsvReader for ExtJS (http://technomedia.co.uk/blog/2008/11/ajax-data-transfer-jsoncsvreader-for-extjs/)
And here's the code:
Ext.namespace('Ext.ux.data');
/**
* @description Data reader class to create an Array of Ext.data.Record objects from specialised block of JSON.
* @author <a href="dan.humphrey@technomedia.co.uk">Dan Humphrey</a>
* @class Ext.ux.data.JsonCsvReader
* @extends Ext.data.JsonReader
* @constructor
* @version 0.1
* @license Unlikely
* @param {Object} meta Metadata configuration options.
* @param {Object} recordType Either an Array of field definition objects as passed to Ext.data.Record.create, or an Ext.data.Record constructor created using Ext.data.Record.create.
*/
Ext.ux.data.JsonCsvReader = function(meta, recordType){
meta = meta || {};
Ext.ux.data.JsonCsvReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.ux.data.JsonCsvReader, Ext.data.JsonReader, {
/**
* @cfg {String} totalProperty Name of the property from which to retrieve the total number of records
* in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
* paged from the remote server.
*/
totalProperty: null,
/**
* @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
*/
successProperty: null,
/**
* @cfg {String} cols Name of the property from which to retrieve the columns.
*/
cols: 'cols',
/**
* @cfg {String} rows Name of the property from which to retrieve the rows.
*/
rows: 'rows',
/**
* @cfg {String} root Name of the property which contains the Array of row objects.
*/
root: null,
/**
* @cfg {String} id Name of the property within a row object that contains a record identifier value.
*/
id: null,
/**
* Create a data block containing Ext.data.Records from a Json object containing JsonCsv formatted data.
* @methodOf Ext.ux.data.JsonCsvReader
* @param {Object} o An object which contains an Array of row objects in the property specified
* in the config as 'root, and optionally a property, specified in the config as 'totalProperty'
* which contains the total size of the dataset.
* @return {Object} data A data block which is used by an Ext.data.Store object as
* a cache of Ext.data.Records.
*/
readRecords: function(o){
this.jsonData = o;
//dynamic meta
if (o.metaData) {
delete this.ef;
this.meta = o.metaData;
this.recordType = Ext.data.Record.create(o.metaData.fields);
this.onMetaChange(this.meta, this.recordType, o);
}
var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length;
var root = o;
if (s.root) {
try {
root = o[s.root] || o;
}
catch (e) {
root = o;
}
}
//extra accessors
var colsProp = s.cols ? s.cols : 'cols';
var rowsProp = s.rows ? s.rows : 'rows';
this.getCols = function(){
return root[colsProp];
};
this.getRows = function(){
return root[rowsProp];
};
if (s.totalProperty) {
this.getTotal = this.getJsonAccessor(s.totalProperty);
}
if (s.successProperty) {
this.getSuccess = this.getJsonAccessor(s.successProperty);
}
//default properties
var cols = this.getCols(), rows = this.getRows(), c = cols.length, r = rows.length, totalRecords = r, success = true, v;
var data = {}; // data block to pass to super
//override defualts
if (s.totalProperty) {
v = parseInt(this.getTotal(o), 10);
if (!isNaN(v)) {
totalRecords = v;
}
data[s.totalProperty] = totalRecords;
}
if (s.successProperty) {
v = this.getSuccess(o);
if (v === false || v === 'false') {
success = false;
}
data[s.successProperty] = success;
}
//loop through data and recreate normal JSON data for the superclass
var recs = [];
for (var iRow = 0; iRow < r; iRow++) {
var rec = {};
for (var iCol = 0; iCol < c; iCol++) {
rec[cols[iCol]] = rows[iRow][iCol];
}
recs.push(rec);
}
if (s.root) {
data[s.root] = recs;
}
else {
data = recs;
}
return Ext.ux.data.JsonCsvReader.superclass.readRecords.call(this, data);
}
});
Hope someone finds it useful.