From 23459a1364b42137a2710ec036dc529a12173775 Mon Sep 17 00:00:00 2001 From: Mohamed Eltayar <152964073+maltayyar2@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:26:23 +0300 Subject: [PATCH] enhance_search --- .../static/src/js/list_search.js | 365 +++++++++++------- 1 file changed, 230 insertions(+), 135 deletions(-) diff --git a/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js b/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js index 3692451f0..c10d98af9 100644 --- a/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js +++ b/odex25_base/fims_general_search_tree_view/static/src/js/list_search.js @@ -162,7 +162,6 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { }).then(function() { return self.update({}, {reload: false}); }).then(function() { - // ✅ الإضافة البسيطة الوحيدة: إعادة Focus بعد الـ reload setTimeout(function() { if (self.renderer && self.renderer.$) { var $input = self.renderer.$('.oe_search_input'); @@ -170,7 +169,7 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { $input.focus(); } } - }, 100); // تأخير بسيط للتأكد من اكتمال الـ rendering + }, 100); }).finally(function() { if (self.renderer) { self.renderer.$('.oe_search_loading').hide(); @@ -348,38 +347,47 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { }); ListRenderer.include({ - events: _.extend({}, ListRenderer.prototype.events, { - 'keyup .oe_search_input': '_onCustomSearchKeyUp', - 'input .oe_search_input': '_onCustomSearchInput', - 'click .oe_clear_search': '_onCustomClearSearch', - 'keydown .oe_search_input': '_onCustomSearchKeyDown' - }), + // **إزالة events من class definition لتجنب التعارضات** + // سيتم ربط events programmatically عند الحاجة فقط init: function() { this._super.apply(this, arguments); this._searchTimer = null; this._customSearchReady = false; this._lastInputValue = ''; + this._customEventsbound = false; // تجنب double binding }, _renderView: function () { var self = this; return this._super.apply(this, arguments).then(function (result) { - if (self._shouldAddSearchBox()) { - self._addCustomSearchBox(); - self._customSearchReady = true; - self._restoreSearchState(); - } + // تأخير قليل للتأكد من DOM readiness + setTimeout(function() { + try { + if (self._shouldAddSearchBox()) { + self._addCustomSearchBox(); + self._bindCustomEvents(); + self._customSearchReady = true; + self._restoreSearchState(); + } + } catch (error) { + console.error('FIMS Search: Error in _renderView:', error); + } + }, 50); // تأخير أكبر قليلاً للاستقرار return result; }); }, _restoreSearchState: function() { - var controller = this.getParent(); - if (controller && controller._customSearchState) { + try { + var controller = this.getParent(); + if (!controller || !controller._customSearchState) { + return; + } + var state = controller._customSearchState; - if (state.value) { + if (state.value && this.$('.oe_search_input').length) { var $input = this.$('.oe_search_input'); $input.val(state.value); var length = state.value.length; @@ -396,151 +404,238 @@ odoo.define('fims_general_search_tree_view.list_search', function (require) { .removeClass('text-danger') .show(); } + } catch (error) { + console.error('FIMS Search: Error in _restoreSearchState:', error); } }, _shouldAddSearchBox: function() { - // التحقق من المتطلبات الأساسية - if (!this.arch || - this.arch.tag !== 'tree' || - !this.$el || - !this.$el.hasClass('o_list_view') || - this.$el.find('.oe_search_container').length > 0) { + try { + // **فحوصات الأمان الأساسية** + if (!this.arch || + this.arch.tag !== 'tree' || + !this.$el || + !this.$el.length || + !this.$el.hasClass('o_list_view') || + this.$el.find('.oe_search_container').length > 0) { + return false; + } + + // **الحل النهائي المؤكد: فحص hasSelectors** + // embedded tree views: hasSelectors = false أو undefined + // standalone tree views: hasSelectors = true + + if (this.hasSelectors === false) { + console.log('FIMS Search: Hidden - embedded tree view (hasSelectors = false)'); + return false; + } + + // **فحوصات إضافية للأمان:** + + // فحص DOM structure كـ backup + if (this.$el.closest('.o_form_view').length > 0) { + console.log('FIMS Search: Hidden - inside form view'); + return false; + } + + // فحص field widget + if (this.$el.closest('.o_field_widget').length > 0) { + console.log('FIMS Search: Hidden - inside field widget'); + return false; + } + + console.log('FIMS Search: Shown - standalone tree view (hasSelectors:', this.hasSelectors, ')'); + return true; + + } catch (error) { + console.error('FIMS Search: Error in _shouldAddSearchBox:', error); return false; } - - // **الحل النهائي البسيط والمؤكد 100%:** - - // فحص 1: إذا كان داخل form view، فهو embedded - if (this.$el.closest('.o_form_view').length > 0) { - return false; - } - - // فحص 2: إذا كان داخل field widget، فهو embedded - if (this.$el.closest('.o_field_widget').length > 0) { - return false; - } - - // فحص 3: إذا كان داخل notebook page، فهو embedded - if (this.$el.closest('.tab-pane').length > 0) { - return false; - } - - // إذا وصل هنا، فهو standalone tree view - return true; }, _addCustomSearchBox: function() { - var controller = this.getParent(); - var savedValue = ''; - var savedCount = 0; - var isFiltered = false; - - if (controller && controller._customSearchState) { - savedValue = controller._customSearchState.value || ''; - savedCount = controller._customSearchState.filteredCount || 0; - isFiltered = controller._customSearchState.isFiltered || false; - } - - var countText = isFiltered ? - _t('عدد السجلات: ') + savedCount : ''; - - var html = - '
' + - '' + - '' + - '' + - countText + - '' + - '' + - '
'; - - this.$el.prepend($(html)); - this._lastInputValue = savedValue; - - if (savedValue) { - var $input = this.$('.oe_search_input'); - $input.focus(); - var length = savedValue.length; - if ($input[0] && $input[0].setSelectionRange) { - setTimeout(function() { - $input[0].setSelectionRange(length, length); - }, 0); + try { + // **التحقق من DOM validity** + if (!this.$el || !this.$el.length) { + console.warn('FIMS Search: Invalid DOM element'); + return; } + + var controller = this.getParent(); + var savedValue = ''; + var savedCount = 0; + var isFiltered = false; + + if (controller && controller._customSearchState) { + savedValue = controller._customSearchState.value || ''; + savedCount = controller._customSearchState.filteredCount || 0; + isFiltered = controller._customSearchState.isFiltered || false; + } + + var countText = isFiltered ? + _t('عدد السجلات: ') + savedCount : ''; + + var html = + '
' + + '' + + '' + + '' + + countText + + '' + + '' + + '
'; + + this.$el.prepend($(html)); + this._lastInputValue = savedValue; + + if (savedValue) { + var $input = this.$('.oe_search_input'); + $input.focus(); + var length = savedValue.length; + if ($input[0] && $input[0].setSelectionRange) { + setTimeout(function() { + $input[0].setSelectionRange(length, length); + }, 0); + } + } + } catch (error) { + console.error('FIMS Search: Error in _addCustomSearchBox:', error); } }, + + // **ربط Events programmatically** + _bindCustomEvents: function() { + if (this._customEventsbound) { + return; // تجنب double binding + } + + try { + var self = this; + + // bind events to the search container + this.$el.on('keyup', '.oe_search_input', function(e) { + self._onCustomSearchKeyUp(e); + }); + + this.$el.on('input', '.oe_search_input', function(e) { + self._onCustomSearchInput(e); + }); + + this.$el.on('click', '.oe_clear_search', function(e) { + self._onCustomClearSearch(e); + }); + + this.$el.on('keydown', '.oe_search_input', function(e) { + self._onCustomSearchKeyDown(e); + }); + + this._customEventsbound = true; + } catch (error) { + console.error('FIMS Search: Error binding events:', error); + } + }, + + // **تنظيف Events عند destroy** + destroy: function() { + if (this._customEventsbound) { + this.$el.off('keyup', '.oe_search_input'); + this.$el.off('input', '.oe_search_input'); + this.$el.off('click', '.oe_clear_search'); + this.$el.off('keydown', '.oe_search_input'); + } + this._super.apply(this, arguments); + }, _onCustomSearchInput: function(e) { - var currentValue = $(e.currentTarget).val(); - var hasValue = !!currentValue.trim(); - - if (currentValue === this._lastInputValue) return; - - this._lastInputValue = currentValue; - this.$('.oe_clear_search').toggle(hasValue); - - if (!hasValue) { - this.$('.oe_search_count').hide(); + try { + var currentValue = $(e.currentTarget).val(); + var hasValue = !!currentValue.trim(); + + if (currentValue === this._lastInputValue) return; + + this._lastInputValue = currentValue; + this.$('.oe_clear_search').toggle(hasValue); + + if (!hasValue) { + this.$('.oe_search_count').hide(); + } + } catch (error) { + console.error('FIMS Search: Error in _onCustomSearchInput:', error); } }, _onCustomSearchKeyUp: function(e) { - var self = this; - var value = $(e.currentTarget).val().trim(); - var ignoreKeys = [13, 27, 16, 17, 18, 91, 93, 37, 38, 39, 40, - 33, 34, 35, 36, 9, 20, 144, 145, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123]; - - if (ignoreKeys.indexOf(e.which) !== -1) return; - if (value === this._lastSearchValue) return; - - this._lastSearchValue = value; - - if (this._searchTimer) { - clearTimeout(this._searchTimer); - } - - this._searchTimer = setTimeout(function() { - if (self.getParent() && self.getParent()._handleCustomSearch) { - self.getParent()._handleCustomSearch(value); - } - }, 500); - }, - - _onCustomSearchKeyDown: function(e) { - if (e.which === 13) { - e.preventDefault(); + try { + var self = this; + var value = $(e.currentTarget).val().trim(); + var ignoreKeys = [13, 27, 16, 17, 18, 91, 93, 37, 38, 39, 40, + 33, 34, 35, 36, 9, 20, 144, 145, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123]; + + if (ignoreKeys.indexOf(e.which) !== -1) return; + if (value === this._lastSearchValue) return; + + this._lastSearchValue = value; + if (this._searchTimer) { clearTimeout(this._searchTimer); } - var value = $(e.currentTarget).val().trim(); - if (this.getParent() && this.getParent()._handleCustomSearch) { - this.getParent()._handleCustomSearch(value); + + this._searchTimer = setTimeout(function() { + var parent = self.getParent(); + if (parent && parent._handleCustomSearch) { + parent._handleCustomSearch(value); + } + }, 500); + } catch (error) { + console.error('FIMS Search: Error in _onCustomSearchKeyUp:', error); + } + }, + + _onCustomSearchKeyDown: function(e) { + try { + if (e.which === 13) { + e.preventDefault(); + if (this._searchTimer) { + clearTimeout(this._searchTimer); + } + var value = $(e.currentTarget).val().trim(); + var parent = this.getParent(); + if (parent && parent._handleCustomSearch) { + parent._handleCustomSearch(value); + } + } else if (e.which === 27) { + e.preventDefault(); + this._onCustomClearSearch(); } - } else if (e.which === 27) { - e.preventDefault(); - this._onCustomClearSearch(); + } catch (error) { + console.error('FIMS Search: Error in _onCustomSearchKeyDown:', error); } }, _onCustomClearSearch: function() { - this.$('.oe_search_input').val('').focus(); - this.$('.oe_clear_search').hide(); - this.$('.oe_search_count').hide(); - this._lastInputValue = ''; - this._lastSearchValue = ''; - - if (this.getParent() && this.getParent()._clearCustomSearch) { - this.getParent()._clearCustomSearch(); + try { + this.$('.oe_search_input').val('').focus(); + this.$('.oe_clear_search').hide(); + this.$('.oe_search_count').hide(); + this._lastInputValue = ''; + this._lastSearchValue = ''; + + var parent = this.getParent(); + if (parent && parent._clearCustomSearch) { + parent._clearCustomSearch(); + } + } catch (error) { + console.error('FIMS Search: Error in _onCustomClearSearch:', error); } } });