0

I've come to the tail end of a module I'm creating for Magento 2 but I'm having trouble getting it to render on the screen. This code has worked on other sites in the past but there seems to be an issue stopping this one from working. The issue seems to be with my code "var popup = new jQuery.Popup(poOptions);" note being recognized as a constructor.

I read through a few similar posts (like this one WOW is not a constructor) but I can't seem to figure out what the issue is still

The jquery plugin I'm utilizing originates from https://github.com/Toddish/Popup, on our website page here https://76a8q06e6vrsbggs.mojostratus.io/catalog/product/view/id/44/s/2018-official-joules-vest/category/5/

The idea is you add some custom text in the field labeled "personalize", click the preview button, and a window opens up showing the custom text you had on the item. The link the code constructs works fine, its the actual popup that renders the image that is the issue. I'm adding the code that seems relevant to the situation, hope someone can help me out here this has been a headscratcher especially since it works a lot of times, but if you refresh enough it breaks and I don't understand why. Can anyone out there help me figure this out?

EDIT: I removed an additional jQuery Library call that seemed to be triggering some errors, having said that, it's still inconsistently working because sometimes I get the "(index):2025 Uncaught ReferenceError: jQuery is not defined" error.

 <script type="text/javascript">
        var liquifireArguments = [];
        /*-------------------------------
            POPUP.JS
            Simple Popup plugin for jQuery
            @author Todd Francis
            @version 2.2.3
        -------------------------------*/

        ;(function($, window){

            'use strict';

            /**
             * Popup jQuery method
             *
             * @param  {Object} settings
             * @return {Object}
             */
            $.fn.popup = function(settings){

                var selector = this.selector,
                    popup = new $.Popup(settings);

                $(document)
                    .on('click.popup', selector, function(e){

                        var content = settings && settings.content
                            ? settings.content
                            : $(this).attr('href');

                        e.preventDefault();

                        popup.open(content, undefined, this);

                    });

                return this.each(function(){


                    $(this)
                        .data('popup', popup);

                });

            };

            /**
             * Main Popup Class
             *
             * @param {Object} settings
             */
            $.Popup = function(settings)
            {

                var p = this,
                    defaults = {

                        // Markup
                        backClass : 'popup_back',
                        backOpacity : 0.7,
                        containerClass : 'popup_cont',
                        closeContent : '<div class="popup_close">&times;</div>',
                        markup : '<div class="popup"><div class="popup_content"/></div>',
                        contentClass : 'popup_content',
                        preloaderContent : '<p class="preloader">&nbsp;</p>',
                        activeClass : 'popup_active',
                        hideFlash : false,
                        speed : 200,
                        popupPlaceholderClass : 'popup_placeholder',
                        keepInlineChanges :  true,

                        // Content
                        modal : false,
                        content : null,
                        type : 'auto',
                        width : null,
                        height : null,

                        // Params
                        typeParam : 'pt',
                        widthParam : 'pw',
                        heightParam : 'ph',

                        // Callbacks
                        beforeOpen : function(type){},
                        afterOpen : function(){},
                        beforeClose : function(){},
                        afterClose : function(){},
                        error : function(){},
                        show : function($popup, $back){

                            var plugin = this;

                            // Center the popup
                            plugin.center();

                            // Animate in
                            $popup
                                .animate({opacity : 1}, plugin.o.speed, function(){
                                    // Call the open callback
                                    plugin.o.afterOpen.call(plugin);
                                });

                        },
                        replaced : function($popup, $back){

                            // Center the popup and call the open callback
                            this
                                .center()
                                .o.afterOpen.call(this);

                        },
                        hide : function($popup, $back){

                            if( $popup !== undefined ){

                                // Fade the popup out
                                $popup.animate({opacity : 0}, this.o.speed);

                            }

                        },
                        types : {
                            inline : function(content, callback){

                                var $content = $(content);

                                $content
                                    .addClass(p.o.popupPlaceholderClass);

                                // If we don't want to keep any inline changes,
                                // get a fresh copy now
                                if( !p.o.keepInlineChanges ){
                                    cachedContent = $content.html();
                                }

                                callback.call(this, $content.children());

                            },
                            image : function(content, callback){

                                var plugin = this;
                                var mw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)-100;
                                var mh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)-100;

                                var $image = $('<img />')
                                    .one('load', function(){

                                        var img = this;

                                        // Timeout for Webkit
                                        // As the width/height of the image is 0 initially
                                        setTimeout(function(){

                                            callback.call(plugin, img);

                                        }, 0);

                                    })
                                    .one('error', function(){

                                        p.o.error.call(p, content, 'image');

                                    })
                                    .attr('src', content)
                                    .css('max-width',mw)
                                    .css('max-height',mh)
                                    .each(function() {

                                        if( this.complete ){

                                            $(this).trigger('load');

                                        }

                                    });

                            },
                            external : function(content, callback){

                                var $frame = $('<iframe />')
                                    .attr({
                                        src : content,
                                        frameborder : 0,
                                        width : p.width,
                                        height : p.height
                                    });

                                callback.call(this, $frame);

                            },
                            html                    : function(content, callback){

                                callback.call(this, content);

                            },
                            jQuery                  : function(content, callback){

                                callback.call(this, content.html());

                            },
                            'function'              : function(content, callback){

                                callback.call(this, content.call(p));

                            },
                            ajax                    : function(content, callback){

                                $.ajax({
                                    url : content,
                                    success : function(data){
                                        callback.call(this, data);
                                    },
                                    error : function(data){
                                        p.o.error.call(p, content, 'ajax');
                                    }
                                });

                            }
                        }
                    },
                    imageTypes = ['png', 'jpg', 'gif'],
                    type,
                    cachedContent,
                    $back,
                    $pCont,
                    $close,
                    $preloader,
                    $p;

                p.ele = undefined;

                p.o = $.extend(true, {}, defaults, settings);

                /**
                 * Opens a new popup window
                 *
                 * @param  {string} content
                 * @param  {string} popupType
                 * @param  {Object} ele
                 * @return {void}
                 */
                p.open = function(content, popupType, ele){

                    // Get the content
                    content = ( content === undefined || content === '#' )
                        ? p.o.content
                        : content;

                    // If no content is set
                    if( content === null ){

                        p.o.error.call(p, content, type);
                        return false;

                    }

                    // Was an element passed in?
                    if( ele !== undefined ){

                        // Remove current active class
                        if( p.ele && p.o.activeClass ){

                            $(p.ele).removeClass(p.o.activeClass);

                        }

                        // Record the element
                        p.ele = ele;

                        // Add an active class
                        if( p.ele && p.o.activeClass ){

                            $(p.ele).addClass(p.o.activeClass);

                        }

                    }

                    // If we're not open already
                    if( $back === undefined ){

                        // Create back and fade in
                        $back = $('<div class="'+p.o.backClass+'"/>')
                            .appendTo($('body'))
                            .css('opacity', 0)
                            .animate({
                                opacity : p.o.backOpacity
                            }, p.o.speed);

                        // If modal isn't specified, bind click event
                        if( !p.o.modal ){

                            $back.one('click.popup', function(){
                                p.close();
                            });

                        }

                        // Should we hide the flash?
                        if( p.o.hideFlash ){

                            $('object, embed').css('visibility', 'hidden');

                        }

                        // Preloader
                        if( p.o.preloaderContent ){

                            $preloader = $(p.o.preloaderContent)
                                .appendTo($('body'));

                        }

                    }

                    // Get the popupType
                    popupType = getValue([popupType, p.o.type]);

                    // If it's at auto, guess a real type
                    popupType = ( popupType === 'auto' )
                        ? guessType(content)
                        : popupType;

                    // Cache the type to use globally
                    type = popupType;

                    // Do we have a width set?
                    p.width = ( p.o.width )
                        ? p.o.width
                        : null;

                    // Do we have a height set?
                    p.height = ( p.o.height )
                        ? p.o.height
                        : null;

                    // If it's not inline, jQuery or a function
                    // it might have params, and they are top priority
                    if( $.inArray(popupType, ['inline', 'jQuery', 'function']) === -1 ){

                        var paramType = getParameterByName(p.o.typeParam, content),
                            paramWidth = getParameterByName(p.o.widthParam, content),
                            paramHeight = getParameterByName(p.o.heightParam, content);

                        // Do we have an overriding paramter?
                        popupType = ( paramType !== null )
                            ? paramType
                            : popupType;

                        // Do we have an overriding width?
                        p.width = ( paramWidth !== null )
                            ? paramWidth
                            : p.width;

                        // Do we have an overriding height?
                        p.height = ( paramHeight !== null )
                            ? paramHeight
                            : p.height;
                    }

                    // Callback
                    p.o.beforeOpen.call(p, popupType);

                    // Show the content based
                    if( p.o.types[popupType] ){

                        p.o.types[popupType].call(p, content, showContent);

                    }else{

                        p.o.types.ajax.call(p, content, showContent);

                    }

                };

                /**
                 * Return the correct value to be used
                 *
                 * @param  {array} items
                 * @return {mixed}
                 */
                function getValue(items){

                    var finalValue;

                    $.each(items, function(i, value){

                        if( value ){
                            finalValue = value;
                            return false;
                        }

                    });

                    return finalValue;

                }

                /**
                 * Guess the type of content to show
                 *
                 * @param  {string|Object|function} content
                 * @return {string}
                 */
                function guessType(content){

                    if( typeof content === 'function' ){

                        return 'function';

                    } else if( content instanceof $ ){

                        return 'jQuery';

                    } else if( content.substr(0, 1) === '#' || content.substr(0, 1) === '.' ){

                        return 'inline';

                    } else if( $.inArray(content.substr(content.length - 3), imageTypes) !== -1 ) {

                        return 'image';

                    } else if( content.substr(0, 4) === 'http' ) {

                        return 'external';

                    }else{

                        return 'ajax';

                    }

                }

                /**
                 * Shows the content
                 *
                 * @param  {string} content
                 * @return {void}
                 */
                function showContent(content){

                    // Do we have a preloader?
                    if( $preloader ){

                        // If so, hide!
                        $preloader.fadeOut('fast', function(){

                            $(this).remove();

                        });

                    }

                    // Presume we're replacing
                    var replacing = true;

                    // If we're not open already
                    if( $pCont === undefined ){

                        // We're not replacing!
                        replacing = false;

                        // Create the container
                        $pCont = $('<div class="'+p.o.containerClass+'">');

                        // Add in the popup markup
                        $p = $(p.o.markup)
                            .appendTo($pCont);

                        // Add in the close button
                        $close = $(p.o.closeContent)
                            .one('click', function(){

                                p.close();

                            })
                            .appendTo($pCont);

                        // Bind the resize event
                        $(window).resize(p.center);

                        // Append the container to the body
                        // and set the opacity
                        $pCont
                            .appendTo($('body'))
                            .css('opacity', 0);

                    }

                    // Get the actual content element
                    var $pContent = $('.'+p.o.contentClass, $pCont);

                    // Do we have a set width/height?
                    if( p.width ){

                        $pContent.css('width', p.width, 10);

                    }else{

                        $pContent.css('width', '');
                        var mw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)-100;
                        $pContent.css('max-width', mw);
                    }

                    if( p.height ){

                        $pContent.css('height', p.height, 10);

                    }else{

                        $pContent.css('height', '');
                        var mh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)-100;
                        $pContent.css('max-height', mh);

                    }

                    // Put the content in place!
                    if( $p.hasClass(p.o.contentClass) ){

                        $p
                            .html(content);

                    }else{

                        $p
                            .find('.'+p.o.contentClass)
                            .html(content);

                    }

                    // Callbacks!
                    if( !replacing ){

                        p.o.show.call(p, $pCont, $back);

                    }else{

                        p.o.replaced.call(p, $pCont, $back);

                    }

                }

                /**
                 * Close the popup
                 *
                 * @return {Object}
                 */
                p.close = function(){

                    p.o.beforeClose.call(p);

                    // If we got some inline content, cache it
                    // so we can put it back
                    if(
                        type === 'inline' &&
                        p.o.keepInlineChanges
                    ){
                        cachedContent = $('.'+p.o.contentClass).html();
                    }

                    if( $back !== undefined ){

                        // Fade out the back
                        $back.animate({opacity : 0}, p.o.speed, function(){

                            // Clean up after ourselves
                            p.cleanUp();

                        });

                    }

                    // Call the hide callback
                    p.o.hide.call(p, $pCont, $back);

                    return p;

                };

                /**
                 * Clean up the popup
                 *
                 * @return {Object}
                 */
                p.cleanUp = function(){

                    $back
                        .add($pCont)
                        .remove();

                    $pCont = $back = undefined;

                    // Unbind the resize event
                    $(window).unbind('resize', p.center);

                    // Did we hide the flash?
                    if( p.o.hideFlash ){

                        $('object, embed').css('visibility', 'visible');

                    }

                    // Remove active class if we can
                    if( p.ele && p.o.activeClass ){

                        $(p.ele).removeClass(p.o.activeClass);

                    }

                    var $popupPlaceholder = $('.'+p.o.popupPlaceholderClass);

                    // If we got inline content
                    // put it back
                    if(
                        type == 'inline' &&
                        $popupPlaceholder.length
                    ){
                        $popupPlaceholder
                            .html(cachedContent)
                            .removeClass(p.o.popupPlaceholderClass);
                    }

                    type = null;

                    // Call the afterClose callback
                    p.o.afterClose.call(p);

                    return p;

                };

                /**
                 * Centers the popup
                 *
                 * @return {Object}
                 */
                p.center = function(){

                    $pCont.css(p.getCenter());

                    // Only need force for IE6
                    $back.css({
                        height : document.documentElement.clientHeight
                    });

                    return p;

                };

                /**
                 * Get the center co-ordinates
                 *
                 * Returns the top/left co-ordinates to
                 * put the popup in the center
                 *
                 * @return {Object} top/left keys
                 */
                p.getCenter = function(){

                    var pW = $pCont.children().outerWidth(true),
                        pH = $pCont.children().outerHeight(true),
                        wW = document.documentElement.clientWidth,
                        wH = document.documentElement.clientHeight;

                    return {
                        top : wH * 0.5 - pH * 0.5,
                        left : wW * 0.5 - pW * 0.5
                    };

                };

                /**
                 * Get parameters by name
                 * @param  {string} name
                 * @return {null|string} null if not found
                 */
                function getParameterByName(name, url){

                    var match = new RegExp('[?&]'+name+'=([^&]*)')
                        .exec(url);

                    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

                }

            };

        }(jQuery, window));
    </script>

        /*optionId = InputId Of Personalization field*/

        var personalizedField = document.getElementsByClassName('product-custom-option')[0].id;
        //!TODO: String/VAR TO ARRAY
        // console.log('personalizedField: ' + personalizedField);

        arguments = {optionId:personalizedField, argument:'<?= $liquifire_argument ?>'};
        // console.log("arguments: " + arguments);
        liquifireArguments.push(arguments);

        jQuery( document ).ready(function(){
            function lpiEncode(str) {
                var encoded = str;
                encoded = encoded.replace(/&/g, "U0026amp;");
                encoded = encoded.replace(/'/g, "U0027");
                encoded = encoded.replace(/\(/g, "U0026lp;");
                encoded = encoded.replace(/\)/g, "U0026rp;");
                encoded = encoded.replace(/\[/g, "U005B");
                encoded = encoded.replace(/\]/g, "U005D");
                encoded = encoded.replace(/\`/g, "U0060");
                encoded = encoded.replace(/\+/g, "%2b");
                return encoded;
            }
            jQuery('#product-options-wrapper').append('<div class="lp-box"><button type="button" title="Preview" class="button" id="liquifire-preview"><span><span>Preview</span></span></button></div>');
            jQuery('#liquifire-preview').click(function(){
                //jQuery('.mousetrap').addClass('liquidpixels');
                var liquifireUrl = 'https://urm.liquifire.com/urm';
                var liquifireChain = '<?= $image_chain ?>';
                var imageUrl = liquifireUrl + '?';
                // console.log("liquifireUrl: " + liquifireUrl);
                // console.log("liquifireChain: " + liquifireChain);
                // console.log("imageUrl: " + imageUrl);

                jQuery.each(liquifireArguments, function(){
                    optionValue = document.getElementById(this.optionId).value;
                    if( optionValue !== ''){
                        var argument = this.argument;

                        if(liquifireArguments.indexOf(this) === 0){
                            imageUrl += 'set=';
                        }else{
                            imageUrl += ',';
                        }
                        // Add variable and value
                        imageUrl += argument + '[' + lpiEncode(optionValue) + ']';
                    }
                });

                if(document.getElementById('select_label_color')) {
                    lpcolor = document.getElementById('select_label_color').textContent.toLowerCase();
                    if( lpcolor !== ''){
                        imageUrl += ',selColor[' + lpcolor + '.jpg]';
                    }
                }

                // Zoom Url
                zoomUrl = imageUrl + '&call=url[file:' + liquifireChain + ']&scale=size[1000]&sink';
                // console.log('zoomUrl: '+ zoomUrl);

                // Add image chain
                imageUrl += '&call=url[file:' + liquifireChain + ']&scale=size[900]&sink';
                // console.log('imageUrl: '+ imageUrl);

                var poOptions = { type : 'image' };
                var popup = new jQuery.Popup(poOptions);



                popup.open(zoomUrl);
            });

        });


    </script>
Brendan Jackson
  • 305
  • 1
  • 3
  • 13
  • Can't be certain yet, but I'm going to attempt to adjust how Magento 2 loads jQuery to fix the issue https://magento.stackexchange.com/questions/154643/magento2-referenceerror-jquery-is-not-defined – Brendan Jackson Feb 19 '20 at 18:02

1 Answers1

0

This seems to be a relatively common Magento 2 issue for custom modules. There are a number of solutions out there that may be better than this one, having said that, the one I found here https://www.offset101.com/magento-2-x-fix-uncaught-referenceerror-jquery-not-definedanonymous-function-javascript-message/ was the most straight forward.

Wrapping my code in the below require function did the trick.

require(['jquery'],function($){

    $(document).ready(function(){

       alert('YOUR JS HERE');

    });

});
Brendan Jackson
  • 305
  • 1
  • 3
  • 13