Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-2026

Datebox always displays the current year when blurred if format = "MM.yyyy"

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Normal
    • Resolution: Fixed
    • Affects Version/s: 7.0.0, 6.5.4, 6.5.5
    • Fix Version/s: 7.0.0
    • Component/s: General
    • Security Level: Jimmy
    • Labels:

      Description

      1. Pick a date with year other than the current year
      2. After close the calendar control, the year changes to the current year.

      test.zul
      <datebox format="MM.yyyy"/>
      

      Workaround:

      workaround.zul
      <zk>
      	<script><![CDATA[
      		zk.afterLoad('zul.db', function() {
      			function _parseTextToArray(txt, fmt) {
      				if (fmt.indexOf('\'') > -1) //Bug ZK-1341: 'long+medium' format with single quote in zh_TW locale failed to parse AM/PM
      					fmt = fmt.replace(/'/g, '');
      				var ts = [], mindex = fmt.indexOf("MMM"), eindex = fmt.indexOf("EE"),
      					fmtlen = fmt.length, ary = [],
      					//mmindex = mindex + 3,
      					aa = fmt.indexOf('a'),
      					tlen = txt.replace(/[^.]/g, '').length,
      					flen = fmt.replace(/[^.]/g, '').length;
      					
      					
      				for (var i = 0, k = 0, j = txt.length; k < j; i++, k++) {
      					var c = txt.charAt(k),
      						f = fmtlen > i ? fmt.charAt(i) : "";
      					if (c.match(/\d/)) {
      						ary.push(c);
      					} else if ((mindex >= 0 && mindex <= i /*&& mmindex >= i location French will lose last char */)
      					|| (eindex >= 0 && eindex <= i) || (aa > -1 && aa <= i)) {
      						if (c.match(/\w/)) {
      							ary.push(c);
      						} else {
      							if (c.charCodeAt(0) < 128 && (c.charCodeAt(0) != 46 ||
      										tlen == flen || f.charCodeAt(0) == 46)) {
      								if (ary.length) {
      									ts.push(ary.join(""));
      									ary = [];
      								}
      							} else
      								ary.push(c);
      						}
      					} else if (ary.length) {
      						if (txt.charAt(k-1).match(/\d/))
      							while (f == fmt.charAt(i-1) && f) {
      								f = fmt.charAt(++i);
      							}
      						ts.push(ary.join(""));
      						ary = [];
      					} else if (c.match(/\w/))
      						return; //failed
      				}
      				if (ary.length) ts.push(ary.join(""));
      				return ts;
      			}
      			function _parseInt(v) {
      				return parseInt(v, 10);
      			}
      
      			var _date = {};
      			zk.override(zk.fmt.Date, _date, {
      				parseDate: function(txt, fmt, strict, refval, localizedSymbols) {
      					if (!fmt) fmt = "yyyy/MM/dd";
      					refval = refval || zUtl.today(fmt);
      					
      					localizedSymbols = localizedSymbols || {
      						DOW_1ST: zk.DOW_1ST,
      							ERA: zk.ERA,    
      						 YDELTA: zk.YDELTA,
      						   SDOW: zk.SDOW,
      						  S2DOW: zk.S2DOW,
      						   FDOW: zk.FDOW,
      						   SMON: zk.SMON,
      						  S2MON: zk.S2MON,
      						   FMON: zk.FMON,
      							APM: zk.APM
      					};
      					var y = refval.getFullYear(),
      						m = refval.getMonth(),
      						d = refval.getDate(), dFound,
      						hr = refval.getHours(),
      						min = refval.getMinutes(),
      						sec = refval.getSeconds(),
      						msec = refval.getMilliseconds(),
      						aa = fmt.indexOf('a'),
      						hasAM = aa > -1,
      						hasHour1 = hasAM && (fmt.indexOf('h') > -1 || fmt.indexOf('K') > -1),
      						isAM,
      						ts = _parseTextToArray(txt, fmt),
      						isNumber = !isNaN(txt);
      
      					if (!ts || !ts.length) return;
      					for (var i = 0, j = 0, offs = 0, fl = fmt.length; j < fl; ++j) {
      						var cc = fmt.charAt(j);
      						if ((cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')) {
      							var len = 1, k;
      							for (k = j; ++k < fl; ++len)
      								if (fmt.charAt(k) != cc)
      									break;
      
      							var nosep, nv; //no separator
      							if (k < fl) {
      								var c2 = fmt.charAt(k);
      								nosep = c2 == 'y' || c2 == 'M' || c2 == 'd' || c2 == 'E';
      							}
      							
      							// Fix for 'MM.yyyy' issue
      							var token = (nosep && isNumber) ? ts[0].substring(j - offs, k - offs) : ts[i++];
      							switch (cc) {
      							case 'y':
      								// ZK-1985:	token's length is less than the expected if has the parse error  
      								if (token && (token.length < len))
      									return;
      								
      								if (nosep) {
      									if (len <= 3) len = 2;
      									if (token && token.length > len) {
      										ts[--i] = token.substring(len);
      										token = token.substring(0, len);
      									}
      								}
      								
      								// ZK-1985:	token contains non-digital word if has the parse error
      								if (token && token.match(/.*\D.*/))
      									return;
      
      								if (!isNaN(nv = _parseInt(token))) {
      									y = Math.min(nv, 200000); // Bug B50-3288904: js year limit
      									if (y < 100) y += y > 29 ? 1900 : 2000;
      								}
      								break;
      							case 'M':
      								var mon = token ? token.toLowerCase() : '',
      									isNumber0 = !isNaN(token);
      								if (!mon) break; 
      								if (!isNumber0 && token) {
      									for (var index = localizedSymbols.SMON.length, brkswch; --index >= 0;) {
      										var smon = localizedSymbols.SMON[index].toLowerCase();
      										if (mon.startsWith(smon)) {
      											token = localizedSymbols.SMON[index];
      											m = index;
      											brkswch = true;
      											break; // shall break to switch level: B50-3314513
      										}
      									}
      									if (brkswch)
      										break;
      								}
      								if (len == 3 && token) {
      									if (nosep)
      										token = _parseToken(token, ts, --i, token.length);//token.length: the length of French month is 4
      									if (isNaN(nv = _parseInt(token)))
      										return; // failed, B50-3314513
      									m = nv - 1;
      								} else if (len <= 2) {
      									if (nosep && token && token.length > 2) {//Bug 2560497 : if no separator, token must be assigned.
      										ts[--i] = token.substring(2);
      										token = token.substring(0, 2);
      									}
      									if (isNaN(nv = _parseInt(token)))
      										return; // failed, B50-3314513
      									m = nv - 1;
      								} else {
      									for (var l = 0;; ++l) {
      										if (l == 12) return; //failed
      										if (len == 3) {
      											if (localizedSymbols.SMON[l] == token) {
      												m = l;
      												break;
      											}
      										} else {
      											if (token && localizedSymbols.FMON[l].startsWith(token)) {
      												m = l;
      												break;
      											}
      										}
      									}
      								}
      								if (m > 11 /*|| m < 0 accept 0 since it is a common-yet-acceptable error*/) //restrict since user might input year for month
      									return;//failed
      								break;
      							case 'E':
      								if (nosep)
      									_parseToken(token, ts, --i, len);
      								break;
      							case 'd':
      								// ZK-1985:	token's length is less than expected if has the parse error
      								if (token && (token.length < len))
      									return;
      								
      								if (nosep)
      									token = _parseToken(token, ts, --i, len);
      								
      								// ZK-1985:	token contains non-digital word if has the parse error
      								if (token && token.match(/.*\D.*/))
      									return;
      								
      								if (!isNaN(nv = _parseInt(token))) {
      									d = nv;
      									dFound = true;
      									if (d < 0 || d > 31) //restrict since user might input year for day (ok to allow 0 and 31 for easy entry)
      										return; //failed
      								}
      								break;
      							case 'H':
      							case 'h':
      							case 'K':
      							case 'k':
      								// ZK-1985:	token's length is less than expected if has the parse error
      								if (token && (token.length < len))
      									return;
      								
      								if (hasHour1 ? (cc == 'H' || cc == 'k'): (cc == 'h' || cc == 'K'))
      									break;
      								if (nosep)
      									token = _parseToken(token, ts, --i, len);
      								
      								// ZK-1985:	token contains non-digital word if has the parse error
      								if (token && token.match(/.*\D.*/))
      									return;
      								
      								if (!isNaN(nv = _parseInt(token)))
      									hr = (cc == 'h' && nv == 12) || (cc == 'k' && nv == 24) ? 
      										0 : cc == 'K' ? nv % 12 : nv;
      								break;
      							case 'm':
      							case 's':
      							case 'S':
      								// ZK-1985:	token's length is less than expected if has the parse error
      								if (token && (token.length < len))
      									return;
      								
      								if (nosep)
      									token = _parseToken(token, ts, --i, len);
      								
      								// ZK-1985:	token contains non-digital word if has the parse error
      								if (token && token.match(/.*\D.*/))
      									return;
      								
      								if (!isNaN(nv = _parseInt(token))) {
      									if (cc == 'm') min = nv;
      									else if (cc == 's') sec = nv;
      									else msec = nv;
      								}
      								break;
      							case 'a':
      								if (!hasHour1)
      									break;
      								if (!token) return; //failed
      								isAM = token.startsWith(localizedSymbols.APM[0]);
      								break
      							//default: ignored
      							}
      							j = k - 1;
      						} else offs++;
      					}
      
      					if (hasHour1 && isAM === false)
      						hr += 12;
      					var dt;
      					if (m == 1 && d == 29 && localizedSymbols.YDELTA) {
      						dt = new LeapDay(y - localizedSymbols.YDELTA, m, d, hr, min, sec, msec);
      						dt.setOffset(localizedSymbols.YDELTA);
      					} else {
      						dt = new Date(y, m, d, hr, min, sec, msec);
      					}
      					if (!dFound && dt.getMonth() != m)
      						dt = new Date(y, m + 1, 0, hr, min, sec, msec); //last date of m
      					if (strict) {
      						if (dt.getFullYear() != y || dt.getMonth() != m || dt.getDate() != d ||
      							dt.getHours() != hr || dt.getMinutes() != min || dt.getSeconds() != sec) //ignore msec (safer though not accurate)
      							return; //failed
      
      						txt = txt.trim();
      						txt = _ckDate(localizedSymbols.FDOW, txt);
      						txt = _ckDate(localizedSymbols.SDOW, txt);
      						txt = _ckDate(localizedSymbols.S2DOW, txt);
      						txt = _ckDate(localizedSymbols.FMON, txt);
      						txt = _ckDate(localizedSymbols.SMON, txt);
      						txt = _ckDate(localizedSymbols.S2MON, txt);
      						txt = _ckDate(localizedSymbols.APM, txt);
      						for (var j = txt.length; j--;) {
      							var cc = txt.charAt(j);
      							if ((cc > '9' || cc < '0') && fmt.indexOf(cc) < 0)
      								return; //failed
      						}
      					}
      					return +dt == +refval ? refval: dt;
      						//we have to use getTime() since dt == refVal always false
      				}
      			});
      		});
      	]]></script>
      	<datebox format="MM.yyyy"/>
      </zk>
      

        Attachments

          Activity

            People

            Assignee:
            RaymondChao RaymondChao
            Reporter:
            neillee neillee
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: