0

I'm trying to override a widget variable using mixin , but I get the following error Uncaught TypeError: target.extend is not a function

the original file is

define([
 "underscore",
 "jquery",
 "knockout",
 'amShopbyTopFilters',
 "productListToolbarForm",
 "amShopbyFilterAbstract",
 "Magento_PageCache/js/page-cache"
], function (_, ,ドル ko, amShopbyTopFilters) {
 'use strict';
 $.widget('mage.amShopbyAjax', {
 prevCall: false,
 $shopbyOverlay: null,
 cached: [],
 memorizeData: [],
 blockToolbarProcessing: false,
 swatchesTooltip: '.swatch-option-tooltip',
 filterTooltip: '.amshopby-filter-tooltip',
 response: null,
 cacheKey: null,
 startAjax: false,
 isCategorySingleSelect: 0,
 nodes: {
 loader: $('<div id="amasty-shopby-overlay" class="amshopby-overlay-block">' +
 '<span class="amshopby-loader"></span></div>')
 },
 selectors: {
 products_wrapper: '#amasty-shopby-product-list, .search.results',
 top_nav: '.amasty-catalog-topnav',
 products: '.products.wrapper',
 overlay: '#amasty-shopby-overlay',
 top_navigation: '.catalog-topnav .block.filter',
 js_init: '[data-am-js="js-init"]',
 title_head: '#page-title-heading'
 },
 _create: function () {
 var self = this;
 $(function () {
 self.initWidget();
 if (typeof window.history.replaceState === "function") {
 window.history.replaceState({url: document.URL}, document.title);
 setTimeout(function () {
 /*
 Timeout is a workaround for iPhone
 Reproduce scenario is following:
 1. Open category
 2. Use pagination
 3. Click on product
 4. Press "Back"
 Result: Ajax loads the same content right after regular page load
 */
 window.onpopstate = function (e) {
 if (e.state) {
 if ($.mage.amShopbyApplyFilters) {
 $.mage.amShopbyApplyFilters.prototype.showButtonClick = true;
 }
 self.callAjax(e.state.url, []);
 self.$shopbyOverlay.show();
 }
 };
 }, 0)
 }
 });
 },
 initWidget: function () {
 var self = this,
 swatchesTooltip = $(self.swatchesTooltip),
 filterTooltip = $(self.filterTooltip);
 $(document).on('baseCategory', function (event, eventData) {
 self.currentCategoryId = eventData;
 });
 $(document).on('amshopby:submit_filters', function (event, eventData) {
 var data = eventData.data,
 clearUrl = self.options.clearUrl,
 isSorting = eventData.isSorting,
 pushState = !self.options.submitByClick;
 if (typeof data.clearUrl !== 'undefined') {
 clearUrl = data.clearUrl;
 delete data.clearUrl;
 }
 if (self.prevCall) {
 self.prevCall.abort();
 }
 var dataAndUrl = data.slice(0);
 dataAndUrl.push(clearUrl ? clearUrl : self.options.clearUrl);
 var cacheKey = JSON.stringify(dataAndUrl);
 $.mage.amShopbyAjax.prototype.cacheKey = cacheKey;
 if (self.cached[cacheKey]) {
 var response = self.cached[cacheKey];
 if (pushState || isSorting) {
 if (response.newClearUrl
 && response.newClearUrl.indexOf('?p=') == -1
 && response.newClearUrl.indexOf('&p=') == -1
 ) {
 self.options.clearUrl = response.newClearUrl;
 }
 window.history.pushState({url: response.url}, '', response.url);
 self.reloadHtml(response);
 self.initAjax();
 } else if ($.mage.amShopbyApplyFilters) {
 $.mage.amShopbyApplyFilters.prototype.showButtonCounter(
 response.productsCount
 );
 }
 return;
 }
 self.prevCall = self.callAjax(clearUrl, data, pushState, cacheKey, isSorting);
 });
 $(document).on('touchstart touchmove scroll', function () {
 if (swatchesTooltip) {
 swatchesTooltip.hide();
 filterTooltip.trigger('mouseleave');
 }
 });
 $(document).on('amshopby:reload_html', function (event, eventData) {
 self.reloadHtml(eventData.response);
 });
 filterTooltip.on('tap', function () {
 $(this).trigger('mouseenter');
 });
 self.initAjax();
 },
 callAjax: function (clearUrl, data, pushState, cacheKey, isSorting) {
 var self = this;
 if (pushState || isSorting) {
 this.$shopbyOverlay.show();
 }
 data.every(function (item, key) {
 if (item.name.indexOf('[cat]') != -1) {
 if (item.value == self.options.currentCategoryId) {
 data.splice(key, 1);
 } else {
 item.value.split(',').filter(function (element) {
 return element != self.options.currentCategoryId
 }).join(',');
 }
 return false;
 }
 return true;
 });
 data.push({name: 'shopbyAjax', value: 1});
 data = this.addMemorizeData(data);
 $.mage.amShopbyAjax.prototype.startAjax = true;
 if (!clearUrl) {
 clearUrl = self.options.clearUrl;
 }
 clearUrl = clearUrl.replace(/amp;/g, '');
 self.clearUrl = clearUrl;
 return $.ajax({
 url: clearUrl,
 data: data,
 cache: true,
 success: function (response) {
 try {
 $.mage.amShopbyAjax.prototype.startAjax = false;
 response = JSON.parse(response);
 if (response.isDisplayModePage) {
 throw new Error();
 }
 if (cacheKey) {
 self.cached[cacheKey] = response;
 }
 $.mage.amShopbyAjax.prototype.response = response;
 if (response.newClearUrl
 && (response.newClearUrl.indexOf('?p=') == -1 && response.newClearUrl.indexOf('&p=') == -1)) {
 self.options.clearUrl = response.newClearUrl;
 }
 if (pushState || ($.mage.amShopbyApplyFilters && $.mage.amShopbyApplyFilters.prototype.showButtonClick) || isSorting) {
 window.history.pushState({url: response.url}, '', response.url);
 }
 if (self.options.submitByClick !== 1 || isSorting) {
 self.reloadHtml(response);
 }
 if ($.mage.amShopbyApplyFilters && $.mage.amShopbyApplyFilters.prototype.showButtonClick) {
 $.mage.amShopbyApplyFilters.prototype.showButtonClick = false;
 $.mage.amShopbyAjax.prototype.response = false;
 self.reloadHtml(response);
 }
 if ($.mage.amShopbyApplyFilters) {
 $.mage.amShopbyApplyFilters.prototype.showButtonCounter(response.productsCount);
 }
 $(document).trigger('amshopby:ajax_filter_applied');
 } catch (e) {
 var url = self.clearUrl ? self.clearUrl : self.options.clearUrl;
 window.location = (this.url.indexOf('shopbyAjax') == -1) ? this.url : url;
 }
 },
 error: function (response) {
 try {
 if (response.getAllResponseHeaders() != '') {
 self.options.clearUrl ? window.location = self.options.clearUrl : location.reload();
 }
 } catch (e) {
 window.location = (this.url.indexOf('shopbyAjax') == -1) ? this.url : self.options.clearUrl;
 }
 },
 always: function () {
 if (self.$shopbyOverlay) {
 self.$shopbyOverlay.hide();
 }
 }
 });
 },
 addMemorizeData: function (data) {
 if (this.memorizeData) {
 $.each(this.memorizeData, function (key, param) {
 var current = this.filterDataByProp(data, param, 'name');
 if (_.isUndefined(current)) {
 data.push({ name: param.name, value: param.value });
 } else {
 current.value = param.value;
 }
 }.bind(this));
 }
 return data;
 },
 filterDataByProp: function (data, param, prop) {
 return data.find(function (obj) {
 return obj[prop] === param[prop];
 });
 },
 reloadHtml: function (data) {
 var selectSidebarNavigation = '.sidebar.sidebar-main .block.filter',
 selectTopNavigation = selectSidebarNavigation + '.amshopby-all-top-filters-append-left',
 selectMainNavigation = '',
 $productsWrapper = this.getProductBlock();
 this.options.currentCategoryId = data.currentCategoryId
 ? data.currentCategoryId
 : this.options.currentCategoryId;
 if ($(selectTopNavigation).first().length > 0) {
 selectMainNavigation = selectTopNavigation; //if all filters are top
 } else if ($(selectSidebarNavigation).first().length > 0) {
 selectMainNavigation = selectSidebarNavigation;
 }
 $('.am_shopby_apply_filters').remove();
 if (!selectMainNavigation) {
 if ($('.sidebar.sidebar-main').first().length) {
 $('.sidebar.sidebar-main').first().prepend("<div class='block filter'></div>");
 selectMainNavigation = selectSidebarNavigation;
 } else {
 selectMainNavigation = '.block.filter';
 }
 }
 $(selectMainNavigation).first().replaceWith(data.navigation);
 $(selectMainNavigation).first().trigger('contentUpdated');
 //top nav already exist into categoryProducts
 if (!data.categoryProducts || data.categoryProducts.indexOf('amasty-catalog-topnav') == -1) {
 $(this.selectors.top_navigation).first().replaceWith(data.navigationTop);
 $(this.selectors.top_navigation).first().trigger('contentUpdated');
 }
 var mainContent = data.categoryProducts || data.cmsPageData;
 if (mainContent) {
 $productsWrapper.replaceWith(mainContent);
 // we should reinitialize element - because it was replaced and removed
 $productsWrapper = this.getProductBlock();
 try {
 if (typeof $.fn.applyBindings !== 'undefined') {
 ko.cleanNode($productsWrapper)
 $productsWrapper.applyBindings();
 }
 $productsWrapper.trigger('contentUpdated');
 } catch (e) {
 //do nothing. error with third party extension
 }
 }
 $(this.selectors.title_head).closest('.page-title-wrapper').replaceWith(data.h1);
 $(this.selectors.title_head).trigger('contentUpdated');
 this.replaceBlock('.breadcrumbs', 'breadcrumbs', data);
 this.replaceBlock('.switcher-currency', 'currency', data);
 this.replaceBlock('.switcher-language', 'store', data);
 this.replaceBlock('.switcher-store', 'store_switcher', data);
 this.replaceCategoryView(data);
 if (data.behaviour) {
 this.updateMultipleWishlist(data.behaviour);
 }
 $(window).trigger('google-tag');
 mediaCheck({
 media: '(max-width: 768px)',
 entry: function () {
 amShopbyTopFilters.moveTopFiltersToSidebar();
 if (selectMainNavigation == selectTopNavigation
 && $(selectSidebarNavigation + ':not(.amshopby-all-top-filters-append-left)').length != 0) {
 $(selectSidebarNavigation).first().remove();
 }
 },
 exit: function () {
 amShopbyTopFilters.removeTopFiltersFromSidebar();
 }
 });
 var swatchesTooltip = $('.swatch-option-tooltip');
 if (swatchesTooltip.length) {
 swatchesTooltip.hide();
 }
 if (this.$shopbyOverlay) {
 this.$shopbyOverlay.hide();
 }
 var productList = $(this.selectors.products_wrapper).last();
 this.scrollUp();
 $('.amshopby-filters-bottom-cms').remove();
 productList.append(data.bottomCmsBlock);
 $(this.selectors.js_init).first().replaceWith(data.js_init);
 $(this.selectors.js_init).first().trigger('contentUpdated');
 this.afterChangeContentExternal(productList);
 this.initAjax();
 },
 /**
 * @public
 * @return {Object}
 */
 getProductBlock: function () {
 var $productsWrapper = $(this.selectors.products_wrapper).last();
 if ($productsWrapper.parent('.search.results').length) {
 $productsWrapper = $productsWrapper.parent('.search.results');
 }
 return $productsWrapper;
 },
 scrollUp: function () {
 var productList = $(this.selectors.products_wrapper).last(),
 topNavBlock = $(this.selectors.top_nav);
 if (this.options.scrollUp && productList.length) {
 $(document).scrollTop(this.options.scrollUp === 1
 ? (topNavBlock.length ? topNavBlock.offset().top : productList.offset().top)
 : 0);
 }
 },
 afterChangeContentExternal: function (productList) {
 //compatibility with Amasty Scroll extension
 $(document).trigger('amscroll_refresh');
 //fix issue with wrong form key
 productList.formKey();
 //porto theme compatibility
 var lazyImg = $("img.porto-lazyload:not(.porto-lazyload-loaded)");
 if (lazyImg.length && typeof $.fn.lazyload == 'function') {
 lazyImg.lazyload({effect:"fadeIn"});
 }
 if ($('head').html().indexOf('Infortis') > -1) {
 $(document).trigger('last-swatch-found');
 }
 },
 updateMultipleWishlist: function (data) {
 $('#popup-tmpl').remove();
 $('#split-btn-tmpl').remove();
 $('#form-tmpl-multiple').replaceWith(data);
 $('body').off('click', '[data-post-new-wishlist]');
 require('uiRegistry').remove('multipleWishlist');
 $('.page-wrapper').trigger('contentUpdated');
 },
 replaceBlock: function (blockClass, dataName, data) {
 $(blockClass).replaceWith(data[dataName]);
 $(blockClass).trigger('contentUpdated');
 },
 replaceCategoryView: function (data) {
 var imageElement = $(".category-image"),
 descrElement = $(".category-description");
 if (data.image) {
 if (imageElement.length !== 0) {
 imageElement.replaceWith(data.image);
 } else {
 imageElement.prependTo("column.main");
 }
 } else {
 imageElement.remove();
 }
 if (data.description) {
 if (descrElement.length !== 0) {
 descrElement.replaceWith(data.description);
 } else {
 if (imageElement.length !== 0) {
 $(data.description).insertAfter(imageElement.selector);
 } else {
 descrElement.prependTo("column.main");
 }
 }
 } else {
 descrElement.remove();
 }
 $('title').html(data.title);
 if (data.categoryData) {
 var categoryViewSelector = ".category-view";
 if ($(categoryViewSelector).length === 0) {
 $('<div class="category-view"></div>').insertAfter('.page.messages');
 }
 $(categoryViewSelector).replaceWith(data.categoryData);
 }
 },
 generateOverlayElement: function () {
 var selectors = this.selectors,
 productListContainer = $(selectors.products_wrapper
 .replace(',', ' ' + selectors.products + ',') + ' ' + selectors.products);
 if (!$(this.selectors.overlay).length) {
 productListContainer.append(this.nodes.loader);
 }
 this.$shopbyOverlay = $(this.selectors.overlay);
 },
 initAjax: function () {
 var self = this;
 this.generateOverlayElement();
 if ($.mage.productListToolbarForm) {
 //change page limit
 $.mage.productListToolbarForm.prototype.changeUrl = function (paramName, paramValue, defaultValue) {
 // Workaround to prevent double method call
 if (self.blockToolbarProcessing) {
 return;
 }
 self.blockToolbarProcessing = true;
 setTimeout(function () {
 self.blockToolbarProcessing = false;
 }, 300);
 var decode = window.decodeURIComponent,
 urlPaths = this.options.url.split('?'),
 urlParams = urlPaths[1] ? urlPaths[1].split('&') : [],
 paramData = {},
 currentPage = this.getCurrentPage ? this.getCurrentPage() : '1',
 newPage;
 for (var i = 0; i < urlParams.length; i++) {
 var parameters = urlParams[i].split('=');
 paramData[decode(parameters[0])] = parameters[1] !== undefined
 ? decode(parameters[1].replace(/\+/g, '%20'))
 : '';
 }
 if (currentPage > 1 && paramName === this.options.limit) {
 newPage = Math.floor(this.getCurrentLimit() * (currentPage - 1) / paramValue) + 1;
 if (newPage > 1) {
 paramData[this.options.page] = newPage;
 } else {
 delete paramData[this.options.page];
 }
 }
 paramData[paramName] = paramValue;
 if (paramValue == defaultValue) {
 delete paramData[paramName];
 }
 if (self.options.isMemorizerAllowed) {
 self.memorizeData.push({name: paramName, value: paramValue});
 }
 self.options.clearUrl = self.getNewClearUrl(
 paramName,
 paramData[paramName] ? paramData[paramName] : '',
 paramData[this.options.page]
 );
 //add ajax call
 $.mage.amShopbyFilterAbstract.prototype.prepareTriggerAjax(null, null, null, true);
 };
 }
 //change page number
 $(".toolbar .pages a").unbind('click').bind('click', function (e) {
 var newUrl = $(this).prop('href'),
 updatedUrl = null,
 urlPaths = newUrl.split('?'),
 urlParams = urlPaths[1] ? urlPaths[1].split('&') : [];
 for (var i = 0; i < urlParams.length; i++) {
 if (urlParams[i].indexOf("p=") === 0) {
 var pageParam = urlParams[i].split('=');
 updatedUrl = self.getNewClearUrl(pageParam[0], pageParam[1] > 1 ? pageParam[1] : '');
 break;
 }
 }
 if (!updatedUrl) {
 updatedUrl = this.href;
 }
 updatedUrl = updatedUrl.replace('amp;', '');
 $.mage.amShopbyFilterAbstract.prototype.prepareTriggerAjax(document, updatedUrl, false, true);
 $(document).scrollTop($(self.selectors.products_wrapper).offset().top);
 e.stopPropagation();
 e.preventDefault();
 });
 },
 //Update url after change page size or current page.
 getNewClearUrl: function (key, value, page) {
 var url = new URL(window.location.href),
 params = new window.URLSearchParams(url.search);
 if (value !== '') {
 params.set(key, value);
 } else {
 params.delete(key);
 }
 if (page) {
 params.set('p', page);
 } else if (key !== 'p') {
 params.delete('p');
 }
 url.search = params;
 return window.decodeURIComponent(url.toString());
 }
 });
 return $.mage.amShopbyAjax;
});

my mixin file is

define([
 "underscore",
 "jquery",
 "knockout",
 'amShopbyTopFilters',
 "productListToolbarForm",
 "amShopbyFilterAbstract",
 "Magento_PageCache/js/page-cache"
], function (_, ,ドル ko, amShopbyTopFilters) {
 'use strict';
 var loaderUrl = $("#loaderUrl").val();
 return function (target) {
 target.nodes.loader = $('<div id="amasty-shopby-overlay" class="amshopby-overlay-block">' +
 '<img src="'+loaderUrl+'" alt="Loading..."></div>');
 }
});
asked Dec 21, 2022 at 10:18

3 Answers 3

2

Replace your code with the following:

define(['jquery'], function ($) {
 'use strict';
 var amShopbyAjaxWidgetMixin = {
 nodes: {
 loader: $('<div id="amasty-shopby-overlay" class="amshopby-overlay-block">' +
 '<img src="'+loaderUrl+'" alt="Loading..."></div>')
 }
 };
 return function (targetWidget) {
 $.widget('mage.amShopbyAjax', targetWidget, amShopbyAjaxWidgetMixin); // the widget alias should be like for the target widget
 return $.mage.amShopbyAjax; // the widget by parent alias should be returned
 };
});

You can read more about how to use mixin from the official document: https://developer.adobe.com/commerce/frontend-core/javascript/mixins/

answered Dec 21, 2022 at 19:50
1

Try this

define([
 'jquery'
], function ($) {
 'use strict';
 var mixin = {
 nodes: {
 loader: $('<div id="amasty-shopby-overlay" class="amshopby-overlay-block">' +
 '<img src="'+$("#loaderUrl").val()+'" alt="Loading..."></div>');
 },
 };
 return function (target) {
 $.widget('mage.amShopbyAjax', target, mixin);
 return $.mage.amShopbyAjax;
 };
})
answered Dec 21, 2022 at 16:03
1
  • Thank you. I fixed it Commented Dec 22, 2022 at 14:27
0
define([
 "underscore",
 "jquery",
 "knockout",
 'amShopbyTopFilters',
 "productListToolbarForm",
 "amShopbyFilterAbstract",
 "Magento_PageCache/js/page-cache"
], function (_, ,ドル ko, amShopbyTopFilters) {
 'use strict';
 var loaderUrl = window.TEMPLATE_URL;
 return function (widget) {
 $.widget('mage.amShopbyAjax', widget, {
 nodes: {
 loader: $('<div id="amasty-shopby-overlay" class="amshopby-overlay-block">' +
 '<img src="'+loaderUrl+'/images/loader-1.gif" alt="Loading..."></div>')
 }
 });
 return $.mage.amShopbyAjax;
 }
});
answered Dec 22, 2022 at 14:27
1
  • Your code have redundant dependencies and redundant code. Take a look at my answer for the optimized code. Commented Dec 22, 2022 at 16:26

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.