PDA

View Full Version : EditorGrid - blank dates cause an error when loading data



mystix
28 Feb 2007, 2:37 AM
Hi jack,

the EditorGrid throws an error when i try to load blank dates. i.e.


json_var = {date: ''}


i've already declared the DateField in the column model as such:


new $G(new $F.DateField({allowBlank:true, format:'dmy'}))

so i thought it should allow me to load blank dates into the datastore

FireBug turns up this error:


Date.monthNames[this.getMonth()] has no properties

traced to ext-all-debug.js (line 4668), which is this line:


eval(code.substring(0, code.length - 3) + ";}");

jack.slocum
28 Feb 2007, 9:40 AM
{date: ''} - an empty string is not a date and it is not in the format you declared - it should be an error (I am open to reconsidering though). An empty date should be null. Let me know if that corrects the problem.

mystix
28 Feb 2007, 9:49 AM
hi jack, i tried it with


json_var = {date:null};


and it throws the same error.


i'll continue debugging in the meantime to see where the problem is.

mystix
28 Feb 2007, 10:16 AM
just realised i forgot to mention the Ext build no. in all my posts. sorry bout that.

traced the problem down to line 9248 in ext-all-debug.js:


if(dateFormat){
if(dateFormat == "timestamp"){
return new Date(v*1000);
}
return Date.parseDate(v, dateFormat);
}
return new Date(Date.parse(v));

v is the Json object's date i'm trying to read, and dateFormat is the Reader's detected date format.

if the date is non-null & non-empty, the if(dateFormat) block gets executed.
otherwise, Date.parse is called on the empty / null date, like so:


return Date(Date.parse(null));

or

return Date(Date.parse(''));

both of which get evaluated to


return Date(NaN), which throws an error

which results in errors.

i'm thinking, if we configure a DateField (or any other field) to allow blanks, should we have to parse it while reading if the value we read in is already empty / null?

[EDIT] if not, perhaps some (pseudo)code like this should do the trick?


(v)? return new Date(Date.parse(v)) : (this.allowBlank)? v : 'throw some error here';

jack.slocum
28 Feb 2007, 10:21 AM
Does it throw the error with a date format specified?

Can you try this and let me know if it causes problems?

return v ? new Date(Date.parse(v)) : null;

mystix
28 Feb 2007, 10:26 AM
Does it throw the error with a date format specified?

Can you try this and let me know if it causes problems?

return v ? new Date(Date.parse(v)) : null;


haha, guess you beat me to it. thanks!

yep the suggested code works perfectly. however, i'd like to hear your thoughts on how you'd prefer to handle empty dates in the original json object?


[EDIT] btw, i've got a question on the GridView's handleWheel() behaviour, but i'm not sure where to post it?

jack.slocum
28 Feb 2007, 10:46 AM
Here is as good a spot as any.

jack.slocum
28 Feb 2007, 10:50 AM
This is what I actually put in the code. It's a little more thorough in it's error checking.


case "date":
cv = function(v){
if(!v){ // <--- no point continuing
return null;
}
if(v instanceof Date){
return v;
}
if(dateFormat){
if(dateFormat == "timestamp"){
return new Date(v*1000);
}
return Date.parseDate(v, dateFormat);
}
var parsed = Date.parse(v); // <-- handle bad parse as well
return parsed ? new Date(parsed) : null;
};
break;

mystix
28 Feb 2007, 6:51 PM
simple and thorough. sweet! thanks for the fix =)

now for the question on the handleWheel() function: i noticed you call a stopEvent() at the end of the handleWheel() function. this effectively cancels any wheel scroll for the entire page when the cursor is over a grid. is there any reason for doing so?


handleWheel : function(e){
var d = e.getWheelDelta();
this.scroller.dom.scrollTop -= d*22; // <-- what does this do?
this.lockedBody.dom.scrollTop = this.mainBody.dom.scrollTop = this.scroller.dom.scrollTop; // <-- and this?
e.stopEvent();
},


this is my scenario: i've got grids which are part of a long form on a page, so i wheel to scroll down the page. the moment my cursor hits a grid all scrolling stops and i'm forced to either use the keyboard to scroll, or else move the mouse to a spot outside any grid before i'm allowed to scroll again.

is the intended behavior? if it is then i'm ok, i'll just override the GridView's handleWheel() function. just thought i'd bring up the question first though.

jack.slocum
28 Feb 2007, 7:13 PM
The wheel handling is because you are not actually mousewheeling over the scrolling panel. The grid is absolute positioned in front of a panel with the scrollbars.

this.scroller.dom.scrollTop -= d*22; // updates the scrollbar position
// scrolls the locked and nonlocked bodies
this.lockedBody.dom.scrollTop = this.mainBody.dom.scrollTop = this.scroller.dom.scrollTop;

The reason for stopping the event is because when you scroll the grid and reach the end or top, the page starts scrolling. There were a few requests to stop this behavior and they seemed reasonable.

mystix
28 Feb 2007, 7:58 PM
thanks for enlightening. i was working with a grid that didn't fill it's container.
after adding enough rows to cause a scrollbar to appear, it definitely is a good idea to stop the scroll. =)

mystix
20 Mar 2007, 8:46 PM
[EDIT]
hi jack, here's some more for the [a3r4] bug list. first the sample code:
<html>
<head>
<title>Test Grid</title>
<link rel='stylesheet' href='./css/ext/css/ext-all.css'>
<script src='./js/ext/yui-utilities.js'></script>
<script src='./js/ext/ext-yui-adapter.js'></script>
<script src='./js/ext/ext-all-debug.js'></script>
<script>
Ext.onReady(function() {
var $F = Ext.form;
var $G = Ext.grid.GridEditor;
var grid, chargeRecord, cm, ds;
var testJson = {
testdata:[
{sno:'1',testdate:'02/03/2007',testval:'',testval2:'goodbye earth'},
{sno:'2',testdate:null,testval:'3',testval2:'hello world'}
]
};

// create ColumnModel
cm = new Ext.grid.ColumnModel([
{header: 'Test Date (dd/mm/yyyy)', dataIndex: 'testdate', renderer: function(v) {
return (v)? v.dateFormat('d/m/Y') : '';
}, editor: new $G(new $F.DateField({allowBlank: true, format:'d/m/Y'})), width: 160},
{header: 'Test Value', dataIndex: 'testval', editor: new $G(new $F.NumberField({allowBlank: true})), width: 160},
{header: 'Test Value 2', dataIndex: 'testval2', editor: new $G(new $F.TextField({allowBlank: true})), width: 300}
]);
cm.defaultSortable = true;

// create Record - defines the fields that are present in a Record, and optionally maps the fields to specific fields in the datastore
// (the allowed types are: auto, string, int, float, bool, date)
testRecord = Ext.data.Record.create([
{name: 'sno', type: 'int'},
{name: 'testdate', type: 'date'},
{name: 'testval', type: 'int'},
{name: 'testval2', type: 'string'}
]);

// create DataStore
ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(testJson),
reader: new Ext.data.JsonReader({root: 'testdata', id: 'sno'}, testRecord)
});
ds.load();

// create EditorGrid
grid = new Ext.grid.EditorGrid('testgrid', {
ds: ds, // datasource
cm: cm, // column model
enableColLock: false // don't lock columns
});
grid.render();
});
</script>
</head>
<body>
<div id='testgrid' ></div>
</body>
</html>
[Bug 1] The sample code when loaded in FF2.0.0.2, Opera 9.10 and IE6 produces the following results (despite specifying allowBlank: true in both the DateField and NumberField configs. intuitively, perhaps the DataField should somehow take this into consideration when performing the fieldtype checks?):
- [1st row, "Test Value" column] shows "NaN" on page load for all 3 browsers
- [2nd row, "Test Date" column] shows "null" when commencing edit on Opera 9.10 and IE6

changing DataField.js line 52 to
cv = function(v){ return (v.length > 0)? parseInt(String(v).replace(/[\$,%]/g, ""), 10) : ''; };and line 64 to
return '';solves the problem

strange thing is, isNaN(v) returns false when v is the empty string, so it can't be used on line 52.

fix for "float" check on line 55:
cv = function(v){ return (v.length > 0)? parseFloat(String(v).replace(/[\$,%]/g, "")) : ''; };


[Bug 2] Comment out the first line of the json variable in the sample above i.e.
// {sno:'1',testdate:'02/03/2007',testval:'',testval2:'goodbye earth'},refresh the page, then perform the following steps:
1) click once on the cell containing the no. '3'
2) press enter to start editing
3) change the value to 31
4) press Enter to finish complete the edit
5) press Tab once
you'll notice the left-most cell is now highlighted, instead of the cell in the "Test Value 2" column. This happens on FF2.0.0.2, IE6 and Opera 9.10
- when there is only 1 row in the grid
- and when the cell's contents have been changed
It's a non-biggie bug though.

jack.slocum
20 Mar 2007, 11:59 PM
This is what I added:


cv = function(v){
return v !== undefined && v !== null && v !== '' ?
parseInt(String(v).replace(stripRe, ""), 10) : '';
};
break;

All the checks (instead of length check) are required since the incoming value may not be a string and can be undefined.

I did the float as well. The stripRe is the same regular expression but I recently moved it outside the function so it's defined once instead of on every parse.

Bug 2 should be fixed as well.

mystix
21 Mar 2007, 12:53 AM
great! will check back with you again once the next rev is out.

good to see you around on the forums again. u were missing for about a week! :D

jack.slocum
21 Mar 2007, 1:05 AM
Hey, I only missed 1 day! :)

Unfortunately I can no longer keep pace with the forum and answer in every thread it seems. I missed one day, and I had 3 1/2 pages of new posts in alpha discussion alone. :shock:

mystix
21 Mar 2007, 2:54 AM
i guess the 3.5 pages pushed your posts out of sight :oops:

perhaps your other admins could help move help requests / clarifications etc to another forum? and leave this to enhancements / bugs / feature requests / development work?

jack.slocum
21 Mar 2007, 4:52 AM
Well, this one is really supposed to be the catch all for Alpha stuff. It probably needs to be split up.