I have a Magento 2.3.3 site and when a tab or accordion link is clicked the page scrolls to top of content. How can I prevent this?
The filter tabs on the left (desktop only) http://designacake.co.uk/bakeware
The accordion at the bottom of the product section: http://designacake.co.uk/katy-sue-designs-mould-creative-cake-system-easy-fabric-puff
Thank you.
Solved! Go to Solution.
Try this code in the mixin instead:
define(["jquery"], function($) { return function(widget) { $.widget("mage.collapsible", widget, { _create: function() { this.storage = $.localStorage; this.icons = false; if (typeof this.options.icons === "string") { this.options.icons = $.parseJSON(this.options.icons); } this._processPanels(); this._processState(); this._refresh(); if (this.options.icons.header && this.options.icons.activeHeader) { this._createIcons(); this.icons = true; } this._bind("click"); this._trigger("created"); } }); return $.mage.collapsible; }; });
The solution to this was to overwrite view.phtml in a custom theme /Magento_LayeredNavigation/templates/layer/view.phtml
Collapsible elements need the following arguments:
{ "accordion": { "openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false, "animate":{"duration":"200"} } }
For reference, my view.phtml is:
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ ?> <?php /** * Category layered navigation * * @var $block \Magento\LayeredNavigation\Block\Navigation */ ?> <?php if ($block->canShowBlock()) : ?> <div class="block filter" id="layered-filter-block" data-mage-init=' { "collapsible": { "openedState": "active", "collapsible": true, "active": false, "collateral": { "openedState": "filter-active", "element": "body" } } }'> <?php $filtered = count($block->getLayer()->getState()->getFilters()) ?> <div class="block-title filter-title" data-count="<?= /* @noEscape */ $filtered ?>"> <strong data-role="title"><?= $block->escapeHtml(__('Shop By')); ?></strong> </div> <div class="block-content filter-content"> <?= $block->getChildHtml('state') ?> <?php if ($block->getLayer()->getState()->getFilters()) : ?> <div class="block-actions filter-actions"> <a href="<?= $block->escapeUrl($block->getClearUrl()) ?>" class="action clear filter-clear"> <span><?= $block->escapeHtml(__('Clear All')) ?></span> </a> </div> <?php endif; ?> <?php $wrapOptions = false; ?> <?php foreach ($block->getFilters() as $filter) : ?> <!-- Attribute the filter title as a class of the filter title --> <!-- Currently used to hide Brand filter on Ves Brand pages --> <?php $filtertitle = $filter->getName(); $filtertitle = strtolower($filtertitle); $filtertitle = preg_replace("/[\s_]/", "-", $filtertitle); ?> <?php if ($filter->getItemsCount()) : ?> <?php if (!$wrapOptions) : ?> <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?= $block->escapeHtml(__('Shopping Options')) ?></strong> <div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init=' { "accordion": { "openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false, "animate":{"duration":"200"} } }'> <?php $wrapOptions = true; endif; ?> <div data-role="collapsible" class="filter-options-item <?php echo $filtertitle; ?>"> <div data-role="title" class="filter-options-title"><?= $block->escapeHtml(__($filter->getName())) ?></div> <div data-role="content" class="filter-options-content"><?= /* @noEscape */ $block->getChildBlock('renderer')->render($filter) ?></div> </div> <?php endif; ?> <?php endforeach; ?> <?php if ($wrapOptions) : ?> </div> <?php else : ?> <script> require([ 'jquery' ], function ($) { $('#layered-filter-block').addClass('filter-no-options'); }); </script> <?php endif; ?> </div> </div> <?php endif; ?>
Having the same issue. (using tabs, accordions, or drop down selectors it seems) Anyone? M2.3.3
To do this we have to create requirejs-config.js under app/design/frontend/<VendorName>/<ThemeName>/requirejs-config.js
and add below content
var config = { config: { mixins: { 'mage/collapsible': { 'js/mage/collapsible-mixin': true } } } };
add file app/design/frontend/<VendorName>/<ThemeName>/web/js/mage/collapsible-mixin.js and add below content
define([ 'jquery', ], function ($) { var hideProps = {}, showProps = {}; hideProps.height = 'hide'; showProps.height = 'show'; return function (widget) { $.widget('mage.collapsible', widget, { options: { scrollTo: false }, _create: function () { this.storage = $.localStorage; this.icons = false; if (typeof this.options.icons === 'string') { this.options.icons = $.parseJSON(this.options.icons); } this._processPanels(); this._processState(); this._refresh(); if (this.options.icons.header && this.options.icons.activeHeader) { this._createIcons(); this.icons = true; } if (this.options.scrollTo) { this.element.on('dimensionsChanged', function (e) { if (e.target && e.target.classList.contains('active')) { this._scrollToTopIfVisible(e.target); } }.bind(this)); } this._bind('click'); this._trigger('created'); }, }); return $.mage.collapsible; }; });
Later,
Deploy: php bin/magento s:up && php bin/magento s:s:d -f
That's it.
Enjoy !!
By implementing the above code it stopped clicking on all other collapsible/toggle widgets. For example, it is stopped expanding for the discount code section and the summary section on the cart page. Also, it is stopped expanding on checkout page right sidebar.
Try this code in the mixin instead:
define(["jquery"], function($) { return function(widget) { $.widget("mage.collapsible", widget, { _create: function() { this.storage = $.localStorage; this.icons = false; if (typeof this.options.icons === "string") { this.options.icons = $.parseJSON(this.options.icons); } this._processPanels(); this._processState(); this._refresh(); if (this.options.icons.header && this.options.icons.activeHeader) { this._createIcons(); this.icons = true; } this._bind("click"); this._trigger("created"); } }); return $.mage.collapsible; }; });
This works for me along with the requirejs-config.js under app/design/frontend/<VendorName>/<ThemeName>/requirejs-config.js
Thank you very much!
The solution to this was to overwrite view.phtml in a custom theme /Magento_LayeredNavigation/templates/layer/view.phtml
Collapsible elements need the following arguments:
{ "accordion": { "openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false, "animate":{"duration":"200"} } }
For reference, my view.phtml is:
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ ?> <?php /** * Category layered navigation * * @var $block \Magento\LayeredNavigation\Block\Navigation */ ?> <?php if ($block->canShowBlock()) : ?> <div class="block filter" id="layered-filter-block" data-mage-init=' { "collapsible": { "openedState": "active", "collapsible": true, "active": false, "collateral": { "openedState": "filter-active", "element": "body" } } }'> <?php $filtered = count($block->getLayer()->getState()->getFilters()) ?> <div class="block-title filter-title" data-count="<?= /* @noEscape */ $filtered ?>"> <strong data-role="title"><?= $block->escapeHtml(__('Shop By')); ?></strong> </div> <div class="block-content filter-content"> <?= $block->getChildHtml('state') ?> <?php if ($block->getLayer()->getState()->getFilters()) : ?> <div class="block-actions filter-actions"> <a href="<?= $block->escapeUrl($block->getClearUrl()) ?>" class="action clear filter-clear"> <span><?= $block->escapeHtml(__('Clear All')) ?></span> </a> </div> <?php endif; ?> <?php $wrapOptions = false; ?> <?php foreach ($block->getFilters() as $filter) : ?> <!-- Attribute the filter title as a class of the filter title --> <!-- Currently used to hide Brand filter on Ves Brand pages --> <?php $filtertitle = $filter->getName(); $filtertitle = strtolower($filtertitle); $filtertitle = preg_replace("/[\s_]/", "-", $filtertitle); ?> <?php if ($filter->getItemsCount()) : ?> <?php if (!$wrapOptions) : ?> <strong role="heading" aria-level="2" class="block-subtitle filter-subtitle"><?= $block->escapeHtml(__('Shopping Options')) ?></strong> <div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init=' { "accordion": { "openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false, "animate":{"duration":"200"} } }'> <?php $wrapOptions = true; endif; ?> <div data-role="collapsible" class="filter-options-item <?php echo $filtertitle; ?>"> <div data-role="title" class="filter-options-title"><?= $block->escapeHtml(__($filter->getName())) ?></div> <div data-role="content" class="filter-options-content"><?= /* @noEscape */ $block->getChildBlock('renderer')->render($filter) ?></div> </div> <?php endif; ?> <?php endforeach; ?> <?php if ($wrapOptions) : ?> </div> <?php else : ?> <script> require([ 'jquery' ], function ($) { $('#layered-filter-block').addClass('filter-no-options'); }); </script> <?php endif; ?> </div> </div> <?php endif; ?>