🔧 Fix: إصلاح مشاكل JavaScript في التقويم الهجري

- إصلاح خطأ __libInput undefined
- إضافة معالجة أخطاء شاملة
- إصلاح أزرار التنقل (السابق/التالي)
- تحسين التحقق من توفر المكتبات
- إضافة error handling في جميع الدوال الحرجة
This commit is contained in:
Mohamed Eltayar 2025-08-29 01:50:15 +03:00
parent 10cfe1b601
commit 527b85e7f2
1 changed files with 182 additions and 74 deletions

View File

@ -34,68 +34,142 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
datepicker.DateWidget.include({
start: function () {
var self = this;
// ✅ FIX: Initialize __libInput if it doesn't exist
if (typeof this.__libInput === 'undefined') {
this.__libInput = 0;
}
this.$input = this.$('input.o_datepicker_input');
this.$input_hijri = this.$('input.o_hijri');
// ✅ إضافة بسيطة للـ placeholder للحقل الميلادي
// ✅ Add placeholder for Gregorian field
if (this.$input && this.$input.length && !this.$input.attr('placeholder')) {
this.$input.attr('placeholder', 'التاريخ الميلادي');
}
// Enhanced click handler with better UX
this.$input_hijri.click(function (e) {
e.preventDefault();
e.stopPropagation();
self.$input_hijri.calendarsPicker('show');
});
// ✅ Initialize Hijri calendar with safety checks
if (this.$input_hijri && this.$input_hijri.length) {
this._initHijriCalendar();
}
// Modern configuration with enhanced features
this.$input_hijri.calendarsPicker({
calendar: $.calendars.instance('islamic', this.options.locale || 'ar'),
dateFormat: 'M d, yyyy',
showAnim: 'slideDown', // Modern animation
showSpeed: 'fast',
showOnFocus: false,
closeOnDateSelect: true, // Better UX - close after selection
yearRange: 'c-100:c+50', // Extended year range
changeMonth: true,
changeYear: true,
showOtherMonths: true,
selectOtherMonths: true,
localNumbers: true, // Enable Arabic numerals
renderer: this._getModernRenderer(),
onSelect: this._convertDateToHijri.bind(this),
onShow: function() {
// Add modern CSS class for styling
$('.calendars-popup').addClass('hijri-modern-popup');
// ✅ FIX: Safe datetimepicker initialization
if (this.$el && this.$el.datetimepicker) {
this.__libInput++;
try {
this.$el.datetimepicker(this.options);
} catch (e) {
console.warn('Error initializing datetimepicker:', e);
} finally {
this.__libInput--;
}
});
}
this.__libInput++;
this.$el.datetimepicker(this.options);
this.__libInput--;
this._setReadonly(false);
// ✅ تأكد مرة أخيرة من الـ placeholder بعد تحميل datetimepicker
// ✅ Final check for placeholder and Hijri calendar
setTimeout(function() {
if (self.$input && self.$input.length && !self.$input.attr('placeholder')) {
self.$input.attr('placeholder', 'التاريخ الميلادي');
}
}, 50);
// Try to initialize Hijri calendar again if not done
if (typeof $ !== 'undefined' && $.calendars && self.$input_hijri &&
self.$input_hijri.length && !self.$input_hijri.hasClass('hasCalendarsPicker')) {
self._initHijriCalendar();
}
}, 200);
},
// ✅ Separate method for Hijri calendar initialization
_initHijriCalendar: function() {
var self = this;
// Check if jQuery Calendars library is available
if (typeof $ === 'undefined' || !$.calendars || !$.calendars.instance) {
console.warn('jQuery Calendars library not loaded yet. Will retry...');
return;
}
try {
// Enhanced click handler with better event handling
this.$input_hijri.off('click.hijri').on('click.hijri', function (e) {
e.preventDefault();
e.stopPropagation();
if (self.$input_hijri.hasClass('hasCalendarsPicker')) {
self.$input_hijri.calendarsPicker('show');
}
});
// ✅ Initialize calendar with fixed configuration
this.$input_hijri.calendarsPicker({
calendar: $.calendars.instance('islamic', this.options.locale || 'ar'),
dateFormat: 'M d, yyyy',
showAnim: 'slideDown',
showSpeed: 'fast',
showOnFocus: false,
closeOnDateSelect: true,
yearRange: 'c-100:c+50',
changeMonth: true,
changeYear: true,
showOtherMonths: true,
selectOtherMonths: true,
localNumbers: true,
renderer: this._getModernRenderer(),
onSelect: this._convertDateToHijri.bind(this),
onShow: function() {
// Add modern CSS class
$('.calendars-popup').addClass('hijri-modern-popup');
// ✅ FIX: Navigation buttons with proper symbols
setTimeout(function() {
// Fix previous button
$('.calendars-prev').each(function() {
$(this).html('').attr('title', 'الشهر السابق');
$(this).css({
'cursor': 'pointer',
'user-select': 'none',
'pointer-events': 'auto'
});
});
// Fix next button
$('.calendars-next').each(function() {
$(this).html('').attr('title', 'الشهر التالي');
$(this).css({
'cursor': 'pointer',
'user-select': 'none',
'pointer-events': 'auto'
});
});
}, 50);
}
});
console.log('Hijri calendar initialized successfully');
} catch (error) {
console.error('Error initializing Hijri calendar:', error);
}
},
/**
* Get modern renderer configuration for better styling
* Get modern renderer configuration with fixed navigation buttons
*/
_getModernRenderer: function() {
// Check if library is available
if (!$ || !$.calendarsPicker || !$.calendarsPicker.defaultRenderer) {
return {};
}
return $.extend({}, $.calendarsPicker.defaultRenderer, {
picker: '<div class="calendars">{months}</div>',
monthRow: '<div class="calendars-month-row">{months}</div>',
month: '<div class="calendars-month">' +
'<div class="calendars-month-header">' +
'<button type="button" class="calendars-nav calendars-prev" title="{prevText}">{prevText}</button>' +
'<button type="button" class="calendars-nav calendars-prev" title="الشهر السابق"></button>' +
'<div class="calendars-month-year">{monthHeader}</div>' +
'<button type="button" class="calendars-nav calendars-next" title="{nextText}">{nextText}</button>' +
'<button type="button" class="calendars-nav calendars-next" title="الشهر التالي"></button>' +
'</div>' +
'<table><thead>{weekHeader}</thead><tbody>{weeks}</tbody></table>' +
'</div>',
@ -121,41 +195,53 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
},
_convertGregorianToHijri: function (date) {
// Check if library is available
if (!$ || !$.calendars || !$.calendars.instance) {
return null;
}
var year, month, day, jd, formatted_date;
var calendar = $.calendars.instance('islamic');
var calendar;
if (date && !_.isUndefined(date)) {
date = moment(date).locale('en');
month = parseInt(date.format('M'));
day = parseInt(date.format('D'));
year = parseInt(date.format('YYYY'));
jd = $.calendars.instance('gregorian').toJD(year, month, day);
formatted_date = calendar.fromJD(jd);
var hijriMonth = calendar.formatDate('MM', formatted_date);
var hijriDate = calendar.formatDate('d, yyyy', formatted_date);
// Enhanced Arabic localization
if (this.options.locale === 'ar' || !this.options.locale) {
hijriDate = hijriDate.fromDigits();
// Find Arabic month name
var arabicMonth = _.find(hijriMonths, function (value, key) {
return key === hijriMonth;
});
hijriMonth = arabicMonth || hijriMonth;
try {
calendar = $.calendars.instance('islamic');
date = moment(date).locale('en');
month = parseInt(date.format('M'));
day = parseInt(date.format('D'));
year = parseInt(date.format('YYYY'));
jd = $.calendars.instance('gregorian').toJD(year, month, day);
formatted_date = calendar.fromJD(jd);
var hijriMonth = calendar.formatDate('MM', formatted_date);
var hijriDate = calendar.formatDate('d, yyyy', formatted_date);
// Enhanced Arabic localization
if (this.options.locale === 'ar' || !this.options.locale) {
hijriDate = hijriDate.fromDigits();
// Find Arabic month name
var arabicMonth = _.find(hijriMonths, function (value, key) {
return key === hijriMonth;
});
hijriMonth = arabicMonth || hijriMonth;
}
return _.str.sprintf("%s %s", hijriMonth, hijriDate);
} catch (error) {
console.error('Error converting Gregorian to Hijri:', error);
return null;
}
return _.str.sprintf("%s %s", hijriMonth, hijriDate);
}
return null;
},
_convertDateToHijri: function (date) {
if (!date || date.length === 0) {
if (!date || date.length === 0 || !$ || !$.calendars) {
return false;
}
// Prevent event bubbling for better UX
// Prevent event bubbling
$(document).off('click.calendars').on('click.calendars', '.calendars a', function (e) {
e.preventDefault();
e.stopImmediatePropagation();
@ -176,11 +262,13 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
this.setValue(this._parseClient(dateValue));
this.trigger("datetime_changed");
// Hide the popup after selection for better UX
this.$input_hijri.calendarsPicker('hide');
// Hide the popup after selection
if (this.$input_hijri && this.$input_hijri.hasClass('hasCalendarsPicker')) {
this.$input_hijri.calendarsPicker('hide');
}
} catch (error) {
console.warn('Hijri date conversion error:', error);
console.error('Hijri date conversion error:', error);
}
},
@ -194,10 +282,12 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
var hijri_value = parsed_date ? this._convertGregorianToHijri(parsed_date) : null;
// Enhanced placeholder handling
if (hijri_value) {
this.$input_hijri.val(hijri_value).removeClass('o_input_placeholder');
} else {
this.$input_hijri.val('').addClass('o_input_placeholder');
if (this.$input_hijri && this.$input_hijri.length) {
if (hijri_value) {
this.$input_hijri.val(hijri_value).removeClass('o_input_placeholder');
} else {
this.$input_hijri.val('').addClass('o_input_placeholder');
}
}
},
@ -205,14 +295,32 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
// Clean up event handlers
$(document).off('click.calendars');
if (this.$input_hijri && this.$input_hijri.hasClass('hasCalendarsPicker')) {
this.$input_hijri.calendarsPicker('destroy');
if (this.$input_hijri) {
this.$input_hijri.off('click.hijri');
if (this.$input_hijri.hasClass('hasCalendarsPicker')) {
try {
this.$input_hijri.calendarsPicker('destroy');
} catch (error) {
console.warn('Error destroying calendars picker:', error);
}
}
}
if (this.$el) {
if (this.$el && this.$el.datetimepicker) {
// ✅ FIX: Initialize __libInput if not exists
if (typeof this.__libInput === 'undefined') {
this.__libInput = 0;
}
this.__libInput++;
this.$el.datetimepicker('destroy');
this.__libInput--;
try {
this.$el.datetimepicker('destroy');
} catch (e) {
console.warn('Error destroying datetimepicker:', e);
} finally {
this.__libInput--;
}
}
},
@ -267,9 +375,9 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
});
// Enhanced integration with Odoo's form validation
if ($.validator) {
if ($ && $.validator) {
$.validator.addMethod('hijriDate', function(value, element) {
if (!value) return true;
if (!value || !$ || !$.calendars) return true;
try {
var calendar = $.calendars.instance('islamic');
@ -282,7 +390,7 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) {
}
// Global configuration for better performance
if ($.calendarsPicker) {
if ($ && $.calendarsPicker) {
$.calendarsPicker.setDefaults({
showSpeed: 'fast',
showAnim: 'slideDown',