PDA

View Full Version : [FIXED-282][3.0.2] GridFilter plugins: date filter choke on null date



mynameisyoda
2 Oct 2009, 2:53 AM
Ext version tested:


Ext 3.0.2



Adapter used:


ext


css used:


only default ext-all.css


Browser versions tested against:


FF3 (firebug 1.3.0.10 installed)


Operating System:


Mac OS X
WinXP Pro

Description:


Using GridFilter plugin on date time column with null value throw exception on non object.



Test Case:



<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Custom Grid Filters</title>

<!-- ** CSS ** -->
<!-- base library -->
<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" />

<!-- overrides to base library -->
<link rel="stylesheet" type="text/css" href="ux/gridfilters/css/GridFilters.css" />
<link rel="stylesheet" type="text/css" href="ux/gridfilters/css/RangeMenu.css" />


<!-- ** Javascript ** -->
<!-- ExtJS library: base/adapter -->
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>

<!-- ExtJS library: all widgets -->
<script type="text/javascript" src="../ext-all.js"></script>

<!-- overrides to base library -->

<!-- extensions -->
<script type="text/javascript" src="ux/gridfilters/menu/RangeMenu.js"></script>
<script type="text/javascript" src="ux/gridfilters/menu/ListMenu.js"></script>

<script type="text/javascript" src="ux/gridfilters/GridFilters.js"></script>
<script type="text/javascript" src="ux/gridfilters/filter/Filter.js"></script>
<script type="text/javascript" src="ux/gridfilters/filter/StringFilter.js"></script>
<script type="text/javascript" src="ux/gridfilters/filter/DateFilter.js"></script>
<script type="text/javascript" src="ux/gridfilters/filter/ListFilter.js"></script>
<script type="text/javascript" src="ux/gridfilters/filter/NumericFilter.js"></script>
<script type="text/javascript" src="ux/gridfilters/filter/BooleanFilter.js"></script>

<!-- page specific -->
<script type="text/javascript">
/*!
* Ext JS Library 3.0.2
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.onReady(function(){


Ext.QuickTips.init();


// for this demo configure local and remote urls for demo purposes
var url = {
local: 'grid-filter.json' // static data file
};

// configure whether filter query is encoded or not (initially)
var encode = false;

// configure whether filtering is performed locally or remotely (initially)
var local = true;

store = new Ext.data.JsonStore({
// store configs
autoDestroy: true,
url: (local ? url.local : url.remote),
remoteSort: false,
sortInfo: {
field: 'company',
direction: 'ASC'
},
storeId: 'myStore',

// reader configs
idProperty: 'id',
root: 'data',
totalProperty: 'total',
fields: [{
name: 'id'
}, {
name: 'company'
}, {
name: 'price',
type: 'float'
}, {
name: 'date',
type: 'date',
dateFormat: 'Y-m-d H:i:s'
}, {
name: 'visible',
type: 'boolean'
}, {
name: 'size'
}]
});

var filters = new Ext.ux.grid.GridFilters({
// encode and local configuration options defined previously for easier reuse
encode: encode, // json encode the filter query
local: local, // defaults to false (remote filtering)
filters: [{
type: 'numeric',
dataIndex: 'id'
}, {
type: 'string',
dataIndex: 'company',
disabled: true
}, {
type: 'numeric',
dataIndex: 'price'
}, {
type: 'date',
dataIndex: 'date'
}, {
type: 'list',
dataIndex: 'size',
options: ['small', 'medium', 'large', 'extra large'],
phpMode: true
}, {
type: 'boolean',
dataIndex: 'visible'
}]
});

// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {

var columns = [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}];

return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};

var grid = new Ext.grid.GridPanel({
border: false,
store: store,
colModel: new Ext.grid.ColumnModel({
columns: [{
dataIndex: 'id',
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'company',
header: 'Company',
id: 'company',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'price',
header: 'Price',
filter: {
//type: 'numeric' // specify type here or in store fields config
}
}, {
dataIndex: 'size',
header: 'Size',
filter: {
type: 'list',
options: ['small', 'medium', 'large', 'extra large']
//,phpMode: true
}
}, {
dataIndex: 'date',
header: 'Date',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
filter: {
//type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'visible',
header: 'Visible',
filter: {
//type: 'boolean' // specify type here or in store fields config
}
}]
}),
loadMask: true,
plugins: [filters],
autoExpandColumn: 'company',
listeners: {
render: {
fn: function(){
store.load({
params: {
start: 0,
limit: 50
}
});
}
}
},
bbar: new Ext.Toolbar({
plugins: [filters]
})
});

// add some buttons to bottom toolbar just for demonstration purposes
grid.getBottomToolbar().add([
'->',
{
text: 'Clear Filter Data',
handler: function () {
grid.filters.clearFilters();
}
}
]);

var win = new Ext.Window({
title: 'Grid Filters Example',
height: 400,
width: 700,
layout: 'fit',
items: grid
}).show();

});
</script>

</head>
<body>
<div id="grid-example" style="margin: 10px;"></div>

</body>
</html>

Steps to reproduce the problem:


save the code into examples directory
save in the same directory the json data attached (unzipped)
filter on the Date column with a date from the collection displayed


The result that was expected:


only the filtered date show on the result
date with null value doesnt show on the result


The result that occurs instead:


in Firebug throw exception
record.get(this.dataIndex).clearTime is not a function
val = record.get(this.dataIndex).clearTime(true).getTime();
http://xxx.zzz.com/js/extjs/ux/gridfilters/filter/DateFilter.js
Line 290



Possible fix:



Ext.override(Ext.ux.grid.filter.DateFilter, {
validateRecord : function (record) {
var key,
pickerValue;
var val = record.get(this.dataIndex);

if(!val) return false;

val = val.clearTime(true).getTime();

for (key in this.fields) {
if (this.fields[key].checked) {
pickerValue = this.getFieldValue(key).clearTime(true).getTime();
if (key == 'before' && pickerValue <= val) {
return false;
}
if (key == 'after' && pickerValue >= val) {
return false;
}
if (key == 'on' && pickerValue != val) {
return false;
}
}
}
return true;
}
});

Condor
2 Oct 2009, 3:21 AM
I would prefer:

if(!Ext.isDate(val)) return false;

mynameisyoda
2 Oct 2009, 7:07 AM
I would prefer:

if(!Ext.isDate(val)) return false;

Off course I agree...

Ubi maior minor cessat...

evant
5 Oct 2009, 7:28 PM
Fix applied to svn in rev #5456 for patch release 3.0.3.