[FIX] website_sale_aplicoop: prevent grid destruction on event listener attachment
The _attachEventListeners() function was cloning the products-grid element without its children (cloneNode(false)) to remove duplicate event listeners. This destroyed all loaded products every time the function was called. Solution: Use a flag (_delegationListenersAttached) to prevent adding duplicate event listeners instead of cloning and replacing the grid node. This fixes the issue where products would disappear ~1-2 seconds after page load.
This commit is contained in:
parent
b15e9bc977
commit
b07b7dc671
6 changed files with 521 additions and 218 deletions
|
|
@ -473,6 +473,14 @@
|
|||
<div class="col-md-7">
|
||||
<!-- CRITICAL: This input is NOT inside a form to prevent Odoo from transforming it -->
|
||||
<!-- It must remain a pure HTML input element for realtime_search.js to detect value changes -->
|
||||
<!-- TODO: Re-add clear button wrapper after fixing initialization issues
|
||||
<div style="position: relative;">
|
||||
<input type="text" id="realtime-search-input" class="form-control realtime-search-box search-input-styled" placeholder="Search products..." autocomplete="off" style="padding-right: 40px;" />
|
||||
<button type="button" id="clear-search-btn" class="btn btn-link" style="position: absolute; right: 5px; top: 50%; transform: translateY(-50%); padding: 0; width: 30px; height: 30px; display: none; color: #6c757d; text-decoration: none; font-size: 1.5rem; line-height: 1;" aria-label="Clear search" title="Clear search">
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
-->
|
||||
<input type="text" id="realtime-search-input" class="form-control realtime-search-box search-input-styled" placeholder="Search products..." autocomplete="off" />
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
|
|
@ -551,7 +559,18 @@
|
|||
<t t-call="website_sale_aplicoop.eskaera_shop_products" />
|
||||
</div>
|
||||
|
||||
<!-- Infinite scroll container -->
|
||||
<!-- Data attributes for infinite scroll configuration (ALWAYS present for JavaScript) -->
|
||||
<div id="eskaera-config"
|
||||
t-attf-data-order-id="{{ group_order.id }}"
|
||||
t-attf-data-search="{{ search_query }}"
|
||||
t-attf-data-category="{{ selected_category }}"
|
||||
t-attf-data-per-page="{{ per_page }}"
|
||||
t-attf-data-current-page="{{ current_page }}"
|
||||
t-attf-data-has-next="{{ 'true' if has_next else 'false' }}"
|
||||
class="d-none">
|
||||
</div>
|
||||
|
||||
<!-- Infinite scroll container (only if enabled and has more pages) -->
|
||||
<t t-if="lazy_loading_enabled and has_next">
|
||||
<div id="infinite-scroll-container" class="row mt-4">
|
||||
<div class="col-12 text-center">
|
||||
|
|
@ -578,17 +597,6 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Data attributes for infinite scroll configuration -->
|
||||
<div id="eskaera-config"
|
||||
t-attf-data-order-id="{{ group_order.id }}"
|
||||
t-attf-data-search="{{ search_query }}"
|
||||
t-attf-data-category="{{ selected_category }}"
|
||||
t-attf-data-per-page="{{ per_page }}"
|
||||
t-attf-data-current-page="{{ current_page }}"
|
||||
t-attf-data-has-next="{{ 'true' if has_next else 'false' }}"
|
||||
class="d-none">
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
|
|
@ -657,19 +665,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scripts (in dependency order) -->
|
||||
<!-- Load i18n_manager first - fetches translations from server -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/i18n_manager.js" />
|
||||
<!-- Keep legacy helpers for backwards compatibility -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/i18n_helpers.js" />
|
||||
<!-- Main shop functionality (depends on i18nManager) -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/website_sale.js" />
|
||||
<!-- UI enhancements -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/checkout_labels.js" />
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/home_delivery.js" />
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/realtime_search.js" />
|
||||
<!-- Infinite scroll for lazy loading products -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/infinite_scroll.js" />
|
||||
<!-- Scripts are loaded from web.assets_frontend in __manifest__.py
|
||||
(i18n_manager, i18n_helpers, website_sale, checkout_labels,
|
||||
home_delivery, realtime_search, infinite_scroll) -->
|
||||
|
||||
<!-- Initialize tooltips using native title attribute -->
|
||||
<script type="text/javascript">
|
||||
|
|
@ -1004,17 +1002,8 @@
|
|||
console.log('[LABELS] Initialized from server:', window.groupOrderShop.labels);
|
||||
})();
|
||||
</script>
|
||||
<!-- Scripts (in dependency order) -->
|
||||
<!-- Load i18n_manager first - fetches translations from server -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/i18n_manager.js" />
|
||||
<!-- Keep legacy helpers for backwards compatibility -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/i18n_helpers.js" />
|
||||
<!-- Main shop functionality (depends on i18nManager) -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/website_sale.js" />
|
||||
<!-- UI enhancements -->
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/checkout_labels.js" />
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/home_delivery.js" />
|
||||
<script type="text/javascript" src="/website_sale_aplicoop/static/src/js/checkout_summary.js" />
|
||||
<!-- Scripts are loaded from web.assets_frontend in __manifest__.py -->
|
||||
<!-- (i18n_manager, i18n_helpers, website_sale, checkout_labels, home_delivery, checkout_summary) -->
|
||||
<script type="text/javascript">
|
||||
// Auto-load cart from localStorage when accessing checkout directly
|
||||
(function() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue