dhtmlxGrid 1.2 Standard版自帶的YUI Calendar日期選擇器存在嚴重Bug:點擊「上/下月」翻頁圖標時,日期面板立即消失,導致無法選擇非當月日期。經代碼分析,根因在於detach事件處理邏輯:雙擊單元格彈出面板後,任意點擊(含翻月按鈕)均觸發detach關閉面板,且detach僅執行一次賦值邏輯。無奈源碼過長難以精準修補,決定拋棄YUI Calendar,替換為成熟穩定的popCalendar.js,經實測完美解決。
dhtmlxgrid_excell_calendar.js:調用popUpCalendar替換原YUI調用。popCalendar.js:在closeCalendar()中實現對Grid單元格的賦值,繞過detach機制。dhtmlxgrid_excell_calendar.jsfunction eXcell_calendar(cell) {
try {
this.cell = cell;
this.grid = this.cell.parentNode.grid;
} catch (er) {}
this.edit = function() {
var arPos = this.grid.getPosition(this.cell);
// 關鍵:調用popCalendar彈出面板
popUpCalendar(this.cell, this.cell, "yyyy-mm-dd", -1, -1);
this.cell._cediton = true;
this.val = this.cell.val;
}
this.getValue = function() {
if (this.cell.val) return this.cell.val;
return this.cell.innerHTML.toString()._dhx_trim();
}
}
eXcell_calendar.prototype = new eXcell;
eXcell_calendar.prototype.setValue = function(val) {
if (!val || val.toString()._dhx_trim() == "") val = "";
this.cell.val = val.toString();
if (this.cell.val == "NaN" || this.cell.val == "") {
this.cell.val = "";
this.cell.innerHTML = " ";
} else {
this.cell.innerHTML = this.cell.val;
}
}
popCalendar.js核心兩處closeCalendar()中添加賦值邏輯function closeCalendar() {
// ... 原有隱藏面板代碼 ...
// 關鍵:ctlToPlaceValue即為Grid單元格DOM元素
// 將用戶選擇的日期賦值到單元格的val屬性與innerHTML
ctlToPlaceValue.val = constructDate(dateSelected, monthSelected, yearSelected);
ctlToPlaceValue.innerHTML = ctlToPlaceValue.val;
// ... 原有清理代碼 ...
}
popUpCalendar()中修正左偏移計算function popUpCalendar(ctl, ctl2, format, x, y) {
// ... 原有代碼 ...
// 修正leftpos負值導致面板定位異常
leftpos < 0 ? leftpos = 0 : leftpos = leftpos;
crossobj.left = fixedX == -1 ? ctl.offsetLeft + leftpos : fixedX;
// ... 原有代碼 ...
}
detach事件在面板關閉時回填值,但detach在翻月點擊時誤觸發,導致面板過早關閉且值未回填。closeCalendar(),此時面板正常關閉,在該函數中直接賦值給ctlToPlaceValue(即Grid單元格),完美繞過detach機制。samples/calendar_grid.html演示頁。
<input type="date">或Flatpickr/Date-fns等輕量日期組件,避免重型Grid綁定特定日期庫。「不改核心、替換組件、在關閉鉤子賦值」——以旁門左道解正統之困,不失為維護舊系統的實用智慧。