Pretty straightforward example of expanding and collapsing all grouped rows by clicking on the Checkbox item.
See this code in action
// Sample JSON data for teammates, their department
// and compensation rate
var Teammates = [{
tmID: 1, Teammate:'Steve', Department:'Safety', Compensation_Rate:'30', Date_Change:'01/01/1999'},{
tmID: 2, Teammate:'Steve', Department:'IT', Compensation_Rate:'55', Date_Change:'05/07/2002'},{
tmID: 3, Teammate:'John', Department:'Sales', Compensation_Rate:'50', Date_Change:'03/05/2000'},{
tmID: 4, Teammate:'John', Department:'Executive', Compensation_Rate:'53', Date_Change:'05/10/2000'},{
tmID: 5, Teammate:'Matthew', Department:'Welding', Compensation_Rate:'55', Date_Change:'12/17/2002'
}];
// Create a Checkbox that will toggle between
// expanding and collapsing the grid items
ExpandCollapseAll = new Ext.form.Checkbox({
renderTo: Ext.getBody(),
boxLabel: 'Expand Results',
listeners: {
check: function(ctrl, val) {
if (val) {
RateGrid.view.expandAllGroups();
} else {
RateGrid.view.collapseAllGroups();
}
}
}
});
// A GridPanel using a GroupingView to display the data
// grouped by the teammate name
RateGrid = new Ext.grid.GridPanel({
renderTo: Ext.getBody(),
width: 400,
style: 'margin: 10px 10px 10px 10px',
height: 300,
store: new Ext.data.GroupingStore({
data: Teammates,
reader: new Ext.data.JsonReader({ id: 'tmID' },
Ext.data.Record.create([
{name: 'tmID', type: 'string'},
{name: 'Teammate', type: 'string'},
{name: 'Department', type: 'string'},
{name: 'Compensation_Rate', type: 'string'},
{name: 'Date_Change', type: 'string'}
])),
groupField: 'Teammate',
sortInfo: {field:'Date_Change', direction: 'ASC'}
}),
cm: new Ext.grid.ColumnModel([
{
id: 'Teammate',
dataIndex: 'Teammate',
hidden: true
},{
id: 'Department',
header: 'Department',
dataIndex: 'Department',
width: 150
},{
id: 'Compensation',
header: 'Rate',
dataIndex: 'Compensation_Rate',
width: 100
},{
id: 'DateChange',
header: 'Date',
dataIndex: 'Date_Change',
width: 100
}
]),
autoScroll: true,
autoExpandColumn: 'Department',
view: new Ext.grid.GroupingView({
showGroupName: false,
hideGroupedColumn: true,
startCollapsed: true,
groupTextTpl: '{text}'
})
});
I wanted to finally get rid of any usage of the JavaScript eval() function when parsing JSON returned from my components.
I went to JSON.org and noticed that there’s an updated json2.js file that should replace my old json.js file as well as two separate parsing engine files on the GitHub site:
Once again, I customized. I removed the existing JSON.parse() method from json2.js and replaced it with the function on json_parse_state.js, so all I need to do is
<script type="text/javascript" src="js/JSON.js"></script>
and the JSON.parse() method will now use the state engine code instead of eval().
Download custom JSON.js.
I’ve been using the AjaxCFC library for years. It’s my preferred way of integrating Javascript and ColdFusion via AJAX. I’ve even modified it from its original form so that my implementation was strictly for integration with jQuery, only returns JSON strings (ignoring WDDX and simple string), and can work with ColdSpring.
Now that I’m a heavy user of the Sencha ExtJS framework, I thought it would be useful to port the jQuery.ajaxCFC.js file over to an Ext.AjaxCFC.js file that extended the native Ext.data.Connection class and utilized the Ext.Ajax object.
Took me about half the day, but I finally got a working Ext.AjaxCFC.request() method that uses the same syntax as the $.AjaxCFC() method. For those familiar with the inner workings and code of the jQuery AjaxCFC class, this will look very familiar.
So now I can make AJAX calls using native ExtJS classes, access ColdSpring beans in my application’s bean factory, or connect directly to any CFC
Ext.AjaxCFCConnection = Ext.extend(Ext.data.Connection, {
data : null,
queryFormat : 'array',
factory : (typeof(__ajaxConfig) == 'undefined') ? null : __ajaxConfig.beanFactory,
timeout : (typeof(__ajaxConfig) == 'undefined') ? 30000 : __ajaxConfig.defaultTimeout,
url : __ajaxConfig.url,
bean : null,
request : function(arguments) {
var params = (typeof(arguments.data) == 'undefined') ? {} : arguments.data;
arguments.params = {};
arguments.params['C0-ID'] = (Math.floor(Math.random() * 10001) + "_" + new Date().getTime()).toString(),
arguments.params['method'] = 'init';
arguments.params['component'] = arguments.component;
arguments.params['bean'] = (typeof(arguments.bean) == 'undefined') ? this.bean : arguments.bean;
arguments.params['factory'] = this.factory;
arguments.params['C0-METHODNAME'] = arguments.method;
arguments.params['queryFormat'] = (typeof(arguments.queryFormat) == 'undefined') ? this.queryFormat : arguments.queryFormat;
arguments.params['C0-PARAM0'] = params;
arguments.url = this.url + '?method=' + arguments.params['method'];
arguments.method = 'POST';
arguments.failure = arguments.error;
arguments.timeout = this.timeout;
var ____success = arguments.success;
arguments.success = function(data) {
data = data.responseText.replace(/^\s*|\s*$/g, '');
if (data.substring(0,9) == '__json__:') {
data = Ext.util.JSON.decode(data.slice(9));
}
____success(data, this);
};
if ( params ) {
if (typeof params != 'string') {
arguments.params['C0-PARAM0'] = Ext.util.JSON.encode(params);
}
}
Ext.Ajax.request(arguments);
}
});
Ext.AjaxCFC = new Ext.AjaxCFCConnection();
// Include Ext.AjaxCFC code
<script type="text/javascript" src="js/Ext.AjaxCFC.js"></script>
// Default configuration properties for the ajaxCFC library
__ajaxConfig = {
'url':'/myApp/ajaxCFC/ajax.cfc',
'defaultTimeout':30000,
'beanFactory':'application.beanFactory'
};
// AjaxCFC call using Ext.data.Connection class
Ext.AjaxCFC.request({
bean: 'AColdSpringBean',
method: 'aMethod',
data: {
'id': 416198,
'first_name': 'Steve',
'last_name': 'Brownlee'
},
success: function(details, s){
DataStore.loadData(details);
},
error: function(results){
Ext.MessageBox.alert('Search Failed', 'An unexpected error occurred. Please try again.');
}
});
Several years ago, I designed and developed an application whose scope was far greater than the business folks imagined. Therefore, the timeline was far more compressed than I would have liked.
I cut a lot of corners in that project in order to get it out in time, but there was only one hack that has haunted me since I reluctantly pushed it into production: I returned a large HTML string from an AJAX call and inserted it directly into the DOM.
It was far easier, at the time, to simply loop through the highly complex query structures in my class and build the HTML structure there rather than build a JSON string and use a JavaScript parsing class to build the HTML on the browser.
Well, in a little twist of fate, there was an update scheduled for this application; and this time I had some extra time as the release date got pushed back a couple of weeks. Using that to my advantage, I finally was able to fine-tune that entire mechanism, including:
All in all, this particular section of the application now executes about 70% faster, is less resource intensive on the database, and is easier to use.
It’s a big monkey off my back. Not to mention that I always enjoy going back to code from previous projects and seeing how I can improve upon it since I’m always learning new tricks.