From 6154c2cc34984132e384e88a76bd129cb84a839e Mon Sep 17 00:00:00 2001 From: Mohamed Eltayar <152964073+maltayyar2@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:13:32 +0300 Subject: [PATCH] Fix: Hijri datepicker calendar not hiding on outside click (#4694) * Fix hijri datepicker calendar not hiding on outside click * Improve list renderer outside click handling for hijri calendar * Update CSS z-index for better hijri calendar popup handling --- .../static/src/js/list_renderer.js | 15 ++--- .../static/src/js/web_hijri_date.js | 64 ++++++++++++------- .../static/src/scss/web_hijri_date.scss | 3 +- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/odex25_base/web_hijri_datepicker/static/src/js/list_renderer.js b/odex25_base/web_hijri_datepicker/static/src/js/list_renderer.js index c1b2d5f89..72dd522ad 100644 --- a/odex25_base/web_hijri_datepicker/static/src/js/list_renderer.js +++ b/odex25_base/web_hijri_datepicker/static/src/js/list_renderer.js @@ -92,12 +92,7 @@ odoo.define('web_hijri_datepicker.ListRenderer', function (require) { } var $td = $('', { class: tdClassName, tabindex: -1 }); - // We register modifiers on the element so that it gets the correct - // modifiers classes (for styling) var modifiers = this._registerModifiers(node, record, $td, _.pick(options, 'mode')); - // If the invisible modifiers is true, the element is left empty. - // Indeed, if the modifiers was to change the whole cell would be - // rerendered anyway. if (modifiers.invisible && !(options && options.renderInvisible)) { return $td; } @@ -124,7 +119,6 @@ odoo.define('web_hijri_datepicker.ListRenderer', function (require) { }; var formattedValue = formatter(value, field, formatOptions); - // فقط إضافة التاريخ الهجري إذا كان الـ widget هو hijri_date أو hijri_datetime if (_.contains(['date', 'datetime'], field.type) && (node.attrs.widget === 'hijri_date' || node.attrs.widget === 'hijri_datetime')) { if (formattedValue) { @@ -157,10 +151,15 @@ odoo.define('web_hijri_datepicker.ListRenderer', function (require) { }, _onWindowClicked: function (event) { - if ($(event.target).hasClass('calendars-highlight')) { + var $target = $(event.target); + if ($target.hasClass('calendars-highlight') || + $target.closest('.calendars-popup').length || + $target.closest('.calendars').length || + $target.hasClass('o_hijri') || + $target.closest('.o_hijri').length) { return; } this._super.apply(this, arguments); } }); -}); +}); \ No newline at end of file diff --git a/odex25_base/web_hijri_datepicker/static/src/js/web_hijri_date.js b/odex25_base/web_hijri_datepicker/static/src/js/web_hijri_date.js index 320637660..eb7b56acd 100644 --- a/odex25_base/web_hijri_datepicker/static/src/js/web_hijri_date.js +++ b/odex25_base/web_hijri_datepicker/static/src/js/web_hijri_date.js @@ -31,7 +31,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { }); } - // إنشاء HijriDateWidget مخصص للتواريخ الهجرية var HijriDateWidget = datepicker.DateWidget.extend({ template: 'web_hijri.datepicker', @@ -40,11 +39,9 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { this.$input = this.$('input.o_datepicker_input'); this.$input_hijri = this.$('input.o_hijri'); - // تحديد اللغة var locale = this.options.locale || 'en'; var userLang = (odoo.session_info && odoo.session_info.user_context && odoo.session_info.user_context.lang) || 'en_US'; - // تحديد placeholders حسب اللغة var gregorianPlaceholder, hijriPlaceholder; if (locale === 'ar' || userLang.startsWith('ar')) { gregorianPlaceholder = 'التاريخ الميلادي'; @@ -54,35 +51,33 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { hijriPlaceholder = 'Hijri Date'; } - // حفظ placeholders للاستخدام لاحقاً this.gregorianPlaceholder = gregorianPlaceholder; this.hijriPlaceholder = hijriPlaceholder; - // تطبيق placeholder للتاريخ الهجري this.$input_hijri.attr('placeholder', hijriPlaceholder); this.$input_hijri.click(function (e) { e.preventDefault(); self.$input_hijri.calendarsPicker('show'); }); + this.$input_hijri.calendarsPicker({ calendar: $.calendars.instance('islamic', this.options.locale), dateFormat: 'M d, yyyy', - closeOnDateSelect: false, onSelect: this._convertDateToHijri.bind(this), + onClose: function() { + self._removeOutsideClickHandler(); + } }); - // تهيئة datetimepicker this.__libInput++; this.$el.datetimepicker(this.options); this.__libInput--; - // تطبيق placeholder للتاريخ الميلادي بعد تهيئة datetimepicker setTimeout(function() { self.$input.attr('placeholder', gregorianPlaceholder); }, 0); - // إعادة تطبيق placeholder عند فقدان التركيز this.$input.on('blur', function() { if (!$(this).val()) { $(this).attr('placeholder', gregorianPlaceholder); @@ -90,11 +85,44 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { }); this._setReadonly(false); + this._setupOutsideClickHandler(); + }, + + _setupOutsideClickHandler: function() { + var self = this; + this._outsideClickHandler = function(e) { + var $target = $(e.target); + if (!$target.closest('.calendars-popup').length && + !$target.closest('.o_hijri').length && + !$target.hasClass('o_hijri') && + !$target.closest('.calendars').length) { + self._hideHijriCalendar(); + } + }; + + this._keydownHandler = function(e) { + if (e.keyCode === 27) { + self._hideHijriCalendar(); + } + }; + + $(document).on('click.hijri_calendar', this._outsideClickHandler); + $(document).on('keydown.hijri_calendar', this._keydownHandler); + }, + + _removeOutsideClickHandler: function() { + $(document).off('click.hijri_calendar'); + $(document).off('keydown.hijri_calendar'); + }, + + _hideHijriCalendar: function() { + if (this.$input_hijri && this.$input_hijri.calendarsPicker) { + this.$input_hijri.calendarsPicker('hide'); + } }, changeDatetime: function () { this._super.apply(this, arguments); - // إعادة تطبيق placeholder بعد تغيير التاريخ if (this.gregorianPlaceholder && !this.$input.val()) { this.$input.attr('placeholder', this.gregorianPlaceholder); } @@ -128,16 +156,12 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { if (!date || date.length === 0) { return false; } - $(document).on('click', '.calendars a', function (e) { - e.preventDefault(); - e.stopImmediatePropagation(); - return false; - }); var jd = $.calendars.instance('islamic').toJD(parseInt(date[0].year()), parseInt(date[0].month()), parseInt(date[0].day())); var formatted_date = $.calendars.instance('gregorian').fromJD(jd); var date_value = moment(time.str_to_date(formatted_date)).add(1, 'days'); this.setValue(this._parseClient(date_value)); this.trigger("datetime_changed"); + this._hideHijriCalendar(); }, _parseDate: function (v) { @@ -150,7 +174,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { var hijri_value = parsed_date ? this._convertGregorianToHijri(parsed_date) : null; this.$input_hijri.val(hijri_value); - // إعادة تطبيق placeholders عند مسح القيم if (!value && this.gregorianPlaceholder) { this.$input.attr('placeholder', this.gregorianPlaceholder); } @@ -160,11 +183,13 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { }, destroy: function () { + this._removeOutsideClickHandler(); if (this.$el) { this.__libInput++; this.$el.datetimepicker('destroy'); this.__libInput--; } + this._super.apply(this, arguments); }, _onInputClicked: function (e) { @@ -178,7 +203,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { }, }); - // إنشاء FieldHijriDate للتواريخ مع التقويم الهجري var FieldHijriDate = FieldDate.extend({ _makeDatePicker: function () { return new HijriDateWidget(this, this.datepickerOptions); @@ -197,7 +221,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { var parsed_date = this.value ? this.datewidget._parseDate(this.value) : ''; var hijri_value = parsed_date ? this.datewidget._convertGregorianToHijri(parsed_date) : ''; - // إضافة labels توضيحية في وضع القراءة فقط var userLang = (odoo.session_info && odoo.session_info.user_context && odoo.session_info.user_context.lang) || 'en_US'; var gregorianLabel = userLang.startsWith('ar') ? 'التاريخ الميلادي: ' : 'Gregorian Date: '; var hijriLabel = userLang.startsWith('ar') ? 'التاريخ الهجري: ' : 'Hijri Date: '; @@ -216,7 +239,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { }, }); - // إنشاء FieldHijriDateTime للتواريخ والأوقات مع التقويم الهجري var FieldHijriDateTime = FieldDateTime.extend({ _makeDatePicker: function () { return new HijriDateWidget(this, this.datepickerOptions); @@ -235,7 +257,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { var parsed_date = this.value ? this.datewidget._parseDate(this.value) : ''; var hijri_value = parsed_date ? this.datewidget._convertGregorianToHijri(parsed_date) : ''; - // إضافة labels توضيحية في وضع القراءة فقط var userLang = (odoo.session_info && odoo.session_info.user_context && odoo.session_info.user_context.lang) || 'en_US'; var gregorianLabel = userLang.startsWith('ar') ? 'التاريخ الميلادي: ' : 'Gregorian Date: '; var hijriLabel = userLang.startsWith('ar') ? 'التاريخ الهجري: ' : 'Hijri Date: '; @@ -254,7 +275,6 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { }, }); - // تسجيل الحقول الجديدة في registry registry.add('hijri_date', FieldHijriDate); registry.add('hijri_datetime', FieldHijriDateTime); @@ -263,4 +283,4 @@ odoo.define('web_hijri_datepicker.datepicker', function (require) { FieldHijriDate: FieldHijriDate, FieldHijriDateTime: FieldHijriDateTime, }; -}); +}); \ No newline at end of file diff --git a/odex25_base/web_hijri_datepicker/static/src/scss/web_hijri_date.scss b/odex25_base/web_hijri_datepicker/static/src/scss/web_hijri_date.scss index 9f9e63bc6..573587e81 100644 --- a/odex25_base/web_hijri_datepicker/static/src/scss/web_hijri_date.scss +++ b/odex25_base/web_hijri_datepicker/static/src/scss/web_hijri_date.scss @@ -1,5 +1,5 @@ .calendars-popup { - z-index: 99999 !important; + z-index: 9999 !important; position: absolute !important; & > .calendars { min-width: 225px; @@ -27,7 +27,6 @@ } } } - } } }