2

I'm trying to get all the data from Algolia so fro that I need to use instantsearch.js file of Algolia and also need to use algoliaBundle.min.js file but when I tried to copy this file then it gives me an error

Uncaught TypeError: Cannot read property '$' of undefined
at instantsearch.js:4
at Object.execCb (require.js:1650)
at Module.check (require.js:866)
at Module. (require.js:1113)
at require.js:132
at require.js:1156
at each (require.js:57)
at Module.emit (require.js:1155)
at Module.check (require.js:917)
at Module. (require.js:1113)

My code is

requirejs(['TM_OrderSearch/js/internals/algoliaBundle.min','Magento_Catalog/js/price-utils','jquery',
    'Magento_Ui/js/modal/modal'], function(algoliaBundle, priceUtils, $,
                                           modal) {
    algoliaBundle.$ (function ($) {

        /** We have nothing to do here if instantsearch is not enabled **/
        if (!algoliaConfig.instant.enabled || !(algoliaConfig.isSearchPage || !algoliaConfig.autocomplete.enabled)) {
            return;
        }

        if (!algoliaConfig.autocomplete.enabled && $(algoliaConfig.autocomplete.selector).length == 0) {
            return;
        }

        if ($(algoliaConfig.instant.selector).length <= 0) {
            throw '[Algolia] Invalid instant-search selector: ' + algoliaConfig.instant.selector;
        }

        if (algoliaConfig.autocomplete.enabled && $(algoliaConfig.instant.selector).find(algoliaConfig.autocomplete.selector).length > 0) {
            throw '[Algolia] You can\'t have a search input matching "' + algoliaConfig.autocomplete.selector +
            '" inside you instant selector "' + algoliaConfig.instant.selector + '"';
        }

        var findAutocomplete = algoliaConfig.autocomplete.enabled && $(algoliaConfig.instant.selector).find('#algolia-autocomplete-container').length > 0;
        if (findAutocomplete) {
            $(algoliaConfig.instant.selector).find('#algolia-autocomplete-container').remove();
        }

        /** BC of old hooks **/
        if (typeof algoliaHookBeforeInstantsearchInit === 'function') {
            algolia.registerHook('beforeInstantsearchInit', algoliaHookBeforeInstantsearchInit);
        }

        if (typeof algoliaHookBeforeWidgetInitialization === 'function') {
            algolia.registerHook('beforeWidgetInitialization', algoliaHookBeforeWidgetInitialization);
        }

        if (typeof algoliaHookBeforeInstantsearchStart === 'function') {
            algolia.registerHook('beforeInstantsearchStart', algoliaHookBeforeInstantsearchStart);
        }

        if (typeof algoliaHookAfterInstantsearchStart === 'function') {
            algolia.registerHook('afterInstantsearchStart', algoliaHookAfterInstantsearchStart);
        }

        /**
         * Setup wrapper
         *
         * For templating is used Hogan library
         * Docs: http://twitter.github.io/hogan.js/
         **/
        var wrapperTemplate = algoliaBundle.Hogan.compile($('#instant_wrapper_template').html());
        var instant_selector = !algoliaConfig.autocomplete.enabled ? algoliaConfig.autocomplete.selector : "#instant-search-bar";

        var div = document.createElement('div');
        $(div).addClass('algolia-instant-results-wrapper');

        $(algoliaConfig.instant.selector).addClass('algolia-instant-replaced-content');
        $(algoliaConfig.instant.selector).wrap(div);

        $('.algolia-instant-results-wrapper').append('<div class="algolia-instant-selector-results"></div>');
        $('.algolia-instant-selector-results').html(wrapperTemplate.render({
            second_bar: algoliaConfig.autocomplete.enabled,
            findAutocomplete: findAutocomplete,
            config: algoliaConfig.instant,
            translations: algoliaConfig.translations
        })).show();

        /**
         * Initialise instant search
         * For rendering instant search page is used Algolia's instantsearch.js library
         * Docs: https://community.algolia.com/instantsearch.js/
         **/

        var ruleContexts = ['']; // Empty context to keep BC for already create rules in dashboard
        if (algoliaConfig.request.categoryId.length > 0) {
            ruleContexts.push('magento-category-' + algoliaConfig.request.categoryId);
        }

        if (algoliaConfig.request.landingPageId.length > 0) {
            ruleContexts.push('magento-landingpage-' + algoliaConfig.request.landingPageId);
        }

        var instantsearchOptions = {
            appId: algoliaConfig.applicationId,
            apiKey: algoliaConfig.apiKey,
            indexName: algoliaConfig.indexName + '_products',
            searchParameters: {
                hitsPerPage: algoliaConfig.hitsPerPage,
                ruleContexts: ruleContexts
            },
            searchFunction: function(helper) {
                if (helper.state.query === '' && !algoliaConfig.isSearchPage) {
                    $('.algolia-instant-replaced-content').show();
                    $('.algolia-instant-selector-results').hide();
                } else {
                    helper.search();
                    $('.algolia-instant-replaced-content').hide();
                    $('.algolia-instant-selector-results').show();
                }
            },
            routing : window.routing,
        };

        if (algoliaConfig.request.path.length > 0 && window.location.hash.indexOf('categories.level0') === -1) {
            if (algoliaConfig.areCategoriesInFacets === false) {
                instantsearchOptions.searchParameters['facetsRefinements'] = { };
                instantsearchOptions.searchParameters['facetsRefinements']['categories.level' + algoliaConfig.request.level] = [algoliaConfig.request.path];
            } else {
                instantsearchOptions.searchParameters['hierarchicalFacetsRefinements'] = {
                    'categories.level0': [algoliaConfig.request.path]
                }
            }
        }

        instantsearchOptions = algolia.triggerHooks('beforeInstantsearchInit', instantsearchOptions, algoliaBundle);

        var search = algoliaBundle.instantsearch(instantsearchOptions);

        search.client.addAlgoliaAgent('Magento2 integration (' + algoliaConfig.extensionVersion + ')');

        /** Prepare sorting indicies data */
        algoliaConfig.sortingIndices.unshift({
            name: algoliaConfig.indexName + '_products',
            label: algoliaConfig.translations.relevance
        });

        /** Setup attributes for current refinements widget **/
        var attributes = [];
        $.each(algoliaConfig.facets, function (i, facet) {
            var name = facet.attribute;

            if (name === 'categories') {
                name = 'categories.level0';
            }

            if (name === 'price') {
                name = facet.attribute + algoliaConfig.priceKey
            }

            attributes.push({
                name: name,
                label: facet.label ? facet.label : facet.attribute
            });
        });

        var allWidgetConfiguration = {
            infiniteHits: {},
            hits: {},
            custom: [
                /**
                 * Custom widget - this widget is used to refine results for search page or catalog page
                 * Docs: https://community.algolia.com/instantsearch.js/v2/guides/custom-widget.html
                 **/
                {
                    getConfiguration: function () {
                        if (algoliaConfig.request.query.length > 0 && location.hash.length < 1) {
                            return {query: algoliaConfig.request.query}
                        }
                        return {};
                    },
                    init: function (data) {
                        var page = data.helper.state.page;

                        if (algoliaConfig.request.refinementKey.length > 0) {
                            data.helper.toggleRefine(algoliaConfig.request.refinementKey, algoliaConfig.request.refinementValue);
                        }

                        if (algoliaConfig.isCategoryPage) {
                            data.helper.addNumericRefinement('visibility_catalog', '=', 1);
                        }
                        else {
                            data.helper.addNumericRefinement('visibility_search', '=', 1);
                        }

                        data.helper.setPage(page);
                    },
                    render: function (data) {
                        if (!algoliaConfig.isSearchPage) {
                            if (data.results.query.length === 0) {
                                $('.algolia-instant-replaced-content').show();
                                $('.algolia-instant-selector-results').hide();
                            }
                            else {
                                $('.algolia-instant-replaced-content').hide();
                                $('.algolia-instant-selector-results').show();
                            }
                        }
                    }
                },
                /**
                 * Custom widget - Suggestions
                 * This widget renders suggestion queries which might be interesting for your customer
                 * Docs: https://community.algolia.com/instantsearch.js/v2/guides/custom-widget.html
                 **/
                {
                    suggestions: [],
                    init: function () {
                        if (algoliaConfig.showSuggestionsOnNoResultsPage) {
                            var $this = this;
                            $.each(algoliaConfig.popularQueries.slice(0, Math.min(4, algoliaConfig.popularQueries.length)), function (i, query) {
                                query = $('<div>').html(query).text(); //xss
                                $this.suggestions.push('<a href="' + algoliaConfig.baseUrl + '/catalogsearch/result/?q=' + encodeURIComponent(query) + '">' + query + '</a>');
                            });
                        }
                    },
                    render: function (data) {
                        if (data.results.hits.length === 0) {
                            var content = '<div class="no-results">';
                            content += '<div><b>' + algoliaConfig.translations.noProducts + ' "' + $("<div>").text(data.results.query).html() + '</b>"</div>';
                            content += '<div class="popular-searches">';

                            if (algoliaConfig.showSuggestionsOnNoResultsPage && this.suggestions.length > 0) {
                                content += '<div>' + algoliaConfig.translations.popularQueries + '</div>' + this.suggestions.join(', ');
                            }

                            content += '</div>';
                            content += algoliaConfig.translations.or + ' <a href="' + algoliaConfig.baseUrl + '/catalogsearch/result/?q=__empty__">' + algoliaConfig.translations.seeAll + '</a>'

                            content += '</div>';

                            $('#instant-search-results-container').html(content);
                        }
                    }
                }
            ],
            /**
             * Search box
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/searchBox.html
             **/
            searchBox: {
                container: instant_selector,
                placeholder: algoliaConfig.translations.searchFor
            },
            /**
             * Stats
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/stats.html
             **/
            stats: {
                container: '#algolia-stats',
                templates: {
                    body: $('#instant-stats-template').html()
                },
                transformData: function (data) {
                    data.first = data.page * data.hitsPerPage + 1;
                    data.last = Math.min(data.page * data.hitsPerPage + data.hitsPerPage, data.nbHits);
                    data.seconds = data.processingTimeMS / 1000;

                    data.translations = window.algoliaConfig.translations;

                    return data;
                }
            },
            /**
             * Sorting
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/sortBySelector.html
             **/
            sortBySelector: {
                container: '#algolia-sorts',
                indices: algoliaConfig.sortingIndices,
                cssClass: 'form-control'
            },
            /**
             * Widget name: Current refinements
             * Widget displays all filters and refinements applied on query. It also let your customer to clear them one by one
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/currentRefinedValues.html
             **/
            currentRefinedValues: {
                container: '#current-refinements',
                cssClasses: {
                    root: 'facet'
                },
                templates: {
                    header: '<div class="name">' + algoliaConfig.translations.selectedFilters + '</div>',
                    clearAll: algoliaConfig.translations.clearAll,
                    item: $('#current-refinements-template').html()
                },
                attributes: attributes,
                onlyListedAttributes: true
            }
        };

        if (algoliaConfig.instant.infiniteScrollEnabled === true) {
            /**
             * Products' infinite hits
             * This widget renders all products into result page
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/infiniteHits.html
             **/
            allWidgetConfiguration.infiniteHits = {
                container: '#instant-search-results-container',
                templates: {
                    item: $('#instant-hit-template').html()
                },
                transformData: {
                    item: function (hit) {
                        hit = transformHit(hit, algoliaConfig.priceKey, search.helper);
                        hit.isAddToCartEnabled = algoliaConfig.instant.isAddToCartEnabled;

                        hit.algoliaConfig = window.algoliaConfig;

                        hit.__position = hit.__hitIndex + 1;

                        return hit;
                    }
                },
                showMoreLabel: algoliaConfig.translations.showMore,
                escapeHits: true
            };

            delete allWidgetConfiguration.hits;
        } else {
            /**
             * Products' hits
             * This widget renders all products into result page
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/hits.html
             **/
            allWidgetConfiguration.hits = {
                container: '#instant-search-results-container',
                templates: {
                    item: $('#instant-hit-template').html()
                },
                transformData: {
                    item: function (hit) {
                        hit = transformHit(hit, algoliaConfig.priceKey, search.helper);
                        hit.isAddToCartEnabled = algoliaConfig.instant.isAddToCartEnabled;

                        hit.algoliaConfig = window.algoliaConfig;

                        var state = search.helper.state;
                        hit.__position = (state.page * state.hitsPerPage) + hit.__hitIndex + 1;

                        return hit;
                    }
                }
            };

            /**
             * Pagination
             * Docs: https://community.algolia.com/instantsearch.js/v2/widgets/pagination.html
             **/
            allWidgetConfiguration.pagination = {
                container: '#instant-search-pagination-container',
                cssClass: 'algolia-pagination',
                showFirstLast: false,
                maxPages: 1000,
                labels: {
                    previous: algoliaConfig.translations.previousPage,
                    next: algoliaConfig.translations.nextPage
                },
                scrollTo: 'body'
            };

            delete allWidgetConfiguration.infiniteHits;
        }

        /**
         * Here are specified custom attributes widgets which require special code to run properly
         * Custom widgets can be added to this object like [attributeName]: function(facet, templates)
         * Function must return instantsearch.widget object
         * Docs: https://community.algolia.com/instantsearch.js/v2/widgets.html
         **/
        var customAttributeFacet = {
            categories: function (facet, templates) {
                var hierarchical_levels = [];
                for (var l = 0; l < 10; l++)
                    hierarchical_levels.push('categories.level' + l.toString());

                var hierarchicalMenuParams = {
                    container: facet.wrapper.appendChild(createISWidgetContainer(facet.attribute)),
                    attributes: hierarchical_levels,
                    separator: ' /// ',
                    alwaysGetRootLevel: true,
                    limit: algoliaConfig.maxValuesPerFacet,
                    templates: templates,
                    sortBy: ['name:asc'],
                    cssClasses: {
                        list: 'hierarchical',
                        root: 'facet hierarchical'
                    }
                };

                hierarchicalMenuParams.templates.item = '' +
                    '<div class="ais-hierearchical-link-wrapper">' +
                    '<a class="{{cssClasses.link}}" href="{{url}}">{{label}}' +
                    '{{#isRefined}}<span class="cross-circle"></span>{{/isRefined}}' +
                    '<span class="{{cssClasses.count}}">{{#helpers.formatNumber}}{{count}}{{/helpers.formatNumber}}</span></a>' +
                    '</div>';

                return ['hierarchicalMenu', hierarchicalMenuParams];
            }
        };

        /** Add all facet widgets to instantsearch object **/

        window.getFacetWidget = function (facet, templates) {

            if (facet.type === 'priceRanges') {
                delete templates.item;

                return ['priceRanges', {
                    container: facet.wrapper.appendChild(createISWidgetContainer(facet.attribute)),
                    attributeName: facet.attribute,
                    labels: {
                        currency: algoliaConfig.currencySymbol,
                        separator: algoliaConfig.translations.to,
                        button: algoliaConfig.translations.go
                    },
                    templates: templates,
                    cssClasses: {
                        root: 'facet conjunctive'
                    }
                }];
            }

            if (facet.type === 'conjunctive') {
                var refinementListOptions = {
                    container: facet.wrapper.appendChild(createISWidgetContainer(facet.attribute)),
                    attributeName: facet.attribute,
                    limit: algoliaConfig.maxValuesPerFacet,
                    operator: 'and',
                    templates: templates,
                    sortBy: ['count:desc', 'name:asc'],
                    cssClasses: {
                        root: 'facet conjunctive'
                    }
                };

                refinementListOptions = addSearchForFacetValues(facet, refinementListOptions);

                return ['refinementList', refinementListOptions];
            }

            if (facet.type === 'disjunctive') {
                var refinementListOptions = {
                    container: facet.wrapper.appendChild(createISWidgetContainer(facet.attribute)),
                    attributeName: facet.attribute,
                    limit: algoliaConfig.maxValuesPerFacet,
                    operator: 'or',
                    templates: templates,
                    sortBy: ['count:desc', 'name:asc'],
                    cssClasses: {
                        root: 'facet disjunctive'
                    }
                };

                refinementListOptions = addSearchForFacetValues(facet, refinementListOptions);

                return ['refinementList', refinementListOptions];
            }

            if (facet.type === 'slider') {
                delete templates.item;

                return ['rangeSlider', {
                    container: facet.wrapper.appendChild(createISWidgetContainer(facet.attribute)),
                    attributeName: facet.attribute,
                    templates: templates,
                    cssClasses: {
                        root: 'facet slider'
                    },
                    tooltips: {
                        format: function (formattedValue) {
                            return facet.attribute.match(/price/) === null ?
                                parseInt(formattedValue) :
                                priceUtils.formatPrice(formattedValue, algoliaConfig.priceFormat);
                        }
                    }
                }];
            }
        };

        var wrapper = document.getElementById('instant-search-facets-container');
        $.each(algoliaConfig.facets, function (i, facet) {

            if (facet.attribute.indexOf("price") !== -1)
                facet.attribute = facet.attribute + algoliaConfig.priceKey;

            facet.wrapper = wrapper;

            var templates = {
                header: '<div class="name">' + (facet.label ? facet.label : facet.attribute) + '</div>',
                item: $('#refinements-lists-item-template').html()
            };

            var widgetInfo = customAttributeFacet[facet.attribute] !== undefined ?
                customAttributeFacet[facet.attribute](facet, templates) :
                getFacetWidget(facet, templates);

            var widgetType = widgetInfo[0],
                widgetConfig = widgetInfo[1];

            if (typeof allWidgetConfiguration[widgetType] === 'undefined') {
                allWidgetConfiguration[widgetType] = [widgetConfig];
            } else {
                allWidgetConfiguration[widgetType].push(widgetConfig);
            }
        });

        if (algoliaConfig.analytics.enabled) {
            if (typeof algoliaAnalyticsPushFunction !== 'function') {
                var algoliaAnalyticsPushFunction = function (formattedParameters, state, results) {
                    var trackedUrl = '/catalogsearch/result/?q=' + state.query + '&' + formattedParameters + '&numberOfHits=' + results.nbHits;

                    // Universal Analytics
                    if (typeof window.ga !== 'undefined') {
                        window.ga('set', 'page', trackedUrl);
                        window.ga('send', 'pageView');
                    }
                };
            }

            allWidgetConfiguration['analytics'] = {
                pushFunction: algoliaAnalyticsPushFunction,
                delay: algoliaConfig.analytics.delay,
                triggerOnUIInteraction: algoliaConfig.analytics.triggerOnUiInteraction,
                pushInitialSearch: algoliaConfig.analytics.pushInitialSearch
            };
        }

        // Banner from query rules
        var bannerWrapper = document.getElementById('algolia-banner');
        if (bannerWrapper !== null) {
            var widgetConfig = {
                templates: {
                    allItems: function(config) {
                        if (config && config.userData) {
                            var userData = config.userData;
                            var banners = userData.map(function(userDataObj) {
                                return userDataObj.banner;
                            });
                            return banners.join('');
                        }
                        return '';
                    },
                    empty: function(query) {
                        return '';
                    }
                },
                container: bannerWrapper,
            };

            if (typeof allWidgetConfiguration['hits'] === 'undefined') {
                allWidgetConfiguration['hits'] = [widgetConfig];
            } else {
                var currentHits = allWidgetConfiguration['hits'];
                allWidgetConfiguration['hits'] = [currentHits, widgetConfig];
            }
        }

        allWidgetConfiguration = algolia.triggerHooks('beforeWidgetInitialization', allWidgetConfiguration, algoliaBundle);

        $.each(allWidgetConfiguration, function (widgetType, widgetConfig) {
            if (Array.isArray(widgetConfig) === true) {
                $.each (widgetConfig, function (i, widgetConfig) {
                    addWidget(search, widgetType, widgetConfig);
                });
            } else {
                addWidget(search, widgetType, widgetConfig);
            }
        });

        var isStarted = false;
        function startInstantSearch() {
            if(isStarted === true) {
                return;
            }

            search = algolia.triggerHooks('beforeInstantsearchStart', search, algoliaBundle);

            search.start();

            search = algolia.triggerHooks('afterInstantsearchStart', search, algoliaBundle);

            var instant_search_bar = $(instant_selector);
            if (instant_search_bar.is(":focus") === false) {
                focusInstantSearchBar(search, instant_search_bar);
            }

            if (algoliaConfig.autocomplete.enabled) {
                $('#search_mini_form').addClass('search-page');
            }

            $(document).on('click', '.ais-hierarchical-menu--link, .ais-refinement-list--checkbox', function () {
                focusInstantSearchBar(search, instant_search_bar);
            });

            isStarted = true;
        }

        /** Initialise searching **/
        startInstantSearch();
    });

    function addWidget(search, type, config) {
        if (type === 'custom') {
            search.addWidget(config);

            return;
        }

        search.addWidget(algoliaBundle.instantsearch.widgets[type](config));
    }

    function addSearchForFacetValues(facet, options) {
        if (facet.searchable === '1') {
            options['searchForFacetValues'] = {
                placeholder: algoliaConfig.translations.searchForFacetValuesPlaceholder,
                templates: {
                    noResults: '<div class="sffv-no-results">' + algoliaConfig.translations.noResults + '</div>'
                }
            };
        }

        return options;
    }
});

while as you can see TM_OrderSearch/js/internals/algoliaBundle.min in the require js this is my custom address of the algoliaBundle.min. I also includejquery` in the above code but the erro still appears what is the Problem and how can I solve this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.