DateField Issues with ExtJs 2.1

August 1, 2008

I ran into an interesting problem tonight while working on one of my projects that just so happens to use a little bit of the ExtJs SDK. I had dropped an Ext.form.DateField onto a regular old HTML form for a bit of polish. When I started testing I began to notice strange behaviors when leaving the field (onBlur), or even when bringing up the date selector. The date would change at random!!

After a bit of searching on the Ext forums I did find a couple of posts that indicated that this is a known issue, and that it has been fixed in the current Subversion build. In the meantime they did offer up a script you could include AFTER your Ext includes that would correct the issue in the current build (2.1). Below is a copy of that code for anyone who may be looking for it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
 * @file Special hotfix patch released by mystix on Ext development team
 * to fix known issues with the DateField class. Next release may see the
 * need to remove this.
 */
 
// private
Date.createParser = function(format) {
  var funcName = "parse" + Date.parseFunctions.count++;
  var regexNum = Date.parseRegexes.length;
  var currentGroup = 1;
  Date.parseFunctions[format] = funcName;
 
  var code = "Date." + funcName + " = function(input){\n"
      + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, ms = -1, o, z, u, v;\n"
      + "input = String(input);var d = new Date();\n"
      + "y = d.getFullYear();\n"
      + "m = d.getMonth();\n"
      + "d = d.getDate();\n"
      + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
      + "if (results && results.length > 0) {";
  var regex = "";
 
  var special = false;
  var ch = '';
  for (var i = 0; i < format.length; ++i) {
      ch = format.charAt(i);
      if (!special && ch == "\\") {
          special = true;
      }
      else if (special) {
          special = false;
          regex += String.escape(ch);
      }
      else {
          var obj = Date.formatCodeToRegex(ch, currentGroup);
          currentGroup += obj.g;
          regex += obj.s;
          if (obj.g && obj.c) {
              code += obj.c;
          }
      }
  }
 
  code += "if (u){\n"
      + "v = new Date(u * 1000);\n" // give top priority to UNIX time
      + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0){\n"
      + "v = new Date(y, m, d, h, i, s, ms);\n"
      + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0){\n"
      + "v = new Date(y, m, d, h, i, s);\n"
      + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0){\n"
      + "v = new Date(y, m, d, h, i);\n"
      + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0){\n"
      + "v = new Date(y, m, d, h);\n"
      + "}else if (y >= 0 && m >= 0 && d > 0){\n"
      + "v = new Date(y, m, d);\n"
      + "}else if (y >= 0 && m >= 0){\n"
      + "v = new Date(y, m);\n"
      + "}else if (y >= 0){\n"
      + "v = new Date(y);\n"
      + "}\n}\nreturn (v && (z || o))?" // favour UTC offset over GMT offset
      +     " (Ext.type(z) == 'number' ? v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - z) :" // reset to UTC, then add offset
      +         " v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn))) : v;\n" // reset to GMT, then add offset
      + "}";
 
  Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");
  eval(code);
};
 
// private
Ext.apply(Date.parseCodes, {
    j: {
        g:1,
        c:"d = parseInt(results[{0}], 10);\n",
        s:"(\\d{1,2})" // day of month without leading zeroes (1 - 31)
    },
    M: function() {
        for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); // get localised short month names
        return Ext.applyIf({
            s:"(" + a.join("|") + ")"
        }, Date.formatCodeToRegex("F"));
    },
    n: {
        g:1,
        c:"m = parseInt(results[{0}], 10) - 1;\n",
        s:"(\\d{1,2})" // month number without leading zeros (1 - 12)
    },
    o: function() {
        return Date.formatCodeToRegex("Y");
    },
    g: function() {
        return Date.formatCodeToRegex("G");
    },
    h: function() {
        return Date.formatCodeToRegex("H");
    },
    P: {
      g:1,
      c:[
          "o = results[{0}];",
          "var sn = o.substring(0,1);", // get + / - sign
          "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);", // get hours (performs minutes-to-hour conversion also, just in case)
          "var mn = o.substring(4,6) % 60;", // get minutes
          "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" // -12hrs <= GMT offset <= 14hrs
      ].join("\n"),
      s: "([+\-]\\d{2}:\\d{2})" // GMT offset in hrs and mins (with colon separator)
    }
});
 
// private
Date.formatCodeToRegex = function(character, currentGroup) {
    // Note: currentGroup - position in regex result array (see notes for Date.parseCodes above)
    var p = Date.parseCodes[character];
 
    if (p) {
      p = Ext.type(p) == 'function'? p() : p;
      Date.parseCodes[character] = p; // reassign function result to prevent repeated execution
    }
 
    return p? Ext.applyIf({
      c: p.c? String.format(p.c, currentGroup || "{0}") : p.c
    }, p) : {
        g:0,
        c:null,
        s:Ext.escapeRe(character) // treat unrecognised characters as literals
    }
};
 
Date.prototype.getGMTOffset = function(colon) {
    return (this.getTimezoneOffset() > 0 ? "-" : "+")
        + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
        + (colon ? ":" : "")
        + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
};

Related Posts

Leave a Reply




CAPTCHA image