Transforming a JavaScript script into a functional plugin

I've been working on converting my script into a plugin (code provided below), but I seem to be missing something. Can someone help me figure out where I went wrong? The page isn't showing any errors, so it's hard to pinpoint the issue.

;(function ($, window, document, undefined) {
    "use strict";

        var pluginName = "WHLightbox",
                defaults = {
                overlay: $('.portfolio-tile--overlay'),
            imageCell: $('.cell-image, .portfolio-tile--image')
        };

        $.extend(Plugin.prototype, {
            init: function() {
                this.events();
                this.buildImageData();
            },

            events: function() {
                var self = this;
                this.settings.imageCell.on('click tap', function(e) {
                    e.preventDefault();
                    e.stopPropagation();

                    // set up the overlay
                    // self._positionOverlay();
                    self._openOverlay();
                    self._preventScrolling();

                    // create the image slide
                    self._createImageSlide($(this));
                });

                $('.portfolio-tile--overlay--close').on('click tap', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    $('.portfolio-tile--overlay').removeClass('open');
                    $('html, body').removeClass('no-scroll');
                });

                $('.portfolio-tile--overlay--controls--prev, .portfolio-tile--overlay--controls--next').on('click tap', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                });

                $('.portfolio-tile--overlay--controls--prev').on('click tap', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    self.showPrev();
                });

                $('.portfolio-tile--overlay--controls--next').on('click tap', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    self.showNext();
                });
            },

            showPrev: function() {
                var index = this.currentImageIndex();

                if(index === 0) {
                    index = this.data.images.length;
                }

                this._createImageSlide(false, index-1);
            },

            showNext: function() {
                var index = this.currentImageIndex();

                if(index === this.data.images.length-1) {
                    index = -1; 
                }

                this._createImageSlide(false, index+1);
            },
            
            currentImageIndex: function() {
                if(this.settings.overlay.hasClass('open')) {
                    var imageUrl = $('.portfolio-tile--main-image').attr('src');

                    for(var i=0; i<this.data.images.length; i++) {
                        if(this.data.images[i].imageUrl === imageUrl) {
                            return i;
                        }
                    }
                } else {
                    return false;
                }
            },

            buildImageData: function() {
                var self = this,
                        i = 0;

                this.settings.imageCell.each(function() {
                    self.data.images[i] = {
                        imageUrl: self._getImagePath($(this))
                    }
                    i++;
                });
            },
            
            _createImageSlide: function($el, index) {
                var imagePath;
                if(!$el) {
                    imagePath = this.data.images[index].imageUrl;
                } else {
                    imagePath = this._getImagePath($el);
                }
                this.settings.overlay.find('.portfolio-tile--main-image').attr('src', imagePath);
            },

            _getImagePath: function($el) {
                var imagePath,
                        spanEl = $el.find('span.js-cell-image-background'),
                        imgEl = $el.find('img.cell-image__image');
                if(spanEl.length) {
                    imagePath = spanEl.css('backgroundImage');
                    imagePath = imagePath.replace('url(', '').replace(')', '');
                } else if(imgEl.length) {
                    imagePath = imgEl.attr('src');
                }

                return imagePath;
            },

            _openOverlay: function() {
                this.settings.overlay.addClass('open');
            },

            _preventScrolling: function() {
                $('html, body').addClass('no-scroll');
            },

            _reInitScrolling: function() {
                $('html, body').removeClass('no-scroll');
            },

            _closeOverlay: function() {
                this.settings.overlay.removeClass('open');
                this._reInitScrolling();
            }
        });

        $.fn[pluginName] = function(options) {
                return this.each(function() {

                        if (!$.data(this, "plugin_" + pluginName)) {
                                $.data(this, "plugin_" + pluginName, new Plugin(this, options));
                        }
                });
        };

})(jQuery, window, document);

Answer №1

Most likely:

let pluginName = "MyPlugin",
    settings = {
        backdrop: $('.background'),
        container: $('.content-container')
    };

At this moment, the code will execute during script interpretation, potentially before the DOM is fully loaded. This could result in settings.backdrop and settings.container not being detected. It would be advisable to transfer this logic to the init function.

There might be other issues that I cannot identify or test without access to the HTML structure. Typically, I'd leave this as a comment, but it's too detailed for that approach.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to redirect from login page to dashboard using AJAX with Flask backend

Using the post method for login, my ajax function successfully sends data to my flask backend server [confirmed by the response received]. However, after receiving the response from the backend, the ajax success handler fails to navigate/redirect to the da ...

Retrieving data from Dojo's JsonRest and storing it as an object variable

After reading this post on Stack Overflow about how to Remove String from JSON, I am looking to populate a Dojo Selectbox with JSON Data. However, I am facing an issue where I need to modify the JSON Data before passing it to the dijit.form.select Box. Th ...

Using jQuery to locate and substitute specific text

Here's a snippet of HTML code I'm working with for posts that have a sneak peek followed by a "Read more" button to reveal additional content. The issue arises when trying to dynamically remove the "[...]" from only the post where the button is c ...

The CORS policy specified in next.config.js does not appear to be taking effect for the API request

I am currently working on a Next.js application with the following structure: . ├── next.config.js └── src / └── app/ ├── page.tsx └── getYoutubeTranscript/ └── getYoutubeTranscript.tsx T ...

Tips for concealing passwords and email addresses in URLs within an Express application

http://localhost:3000/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e297918790dd878f838b8edf838081a2858f838b8ecc818d8f">[email protected]</a>&pass=abc123 what is the best way to conceal email addresses and ...

Font Family Not Recognized in React Native

Encountering an unusual issue while working with React Native. In my button.js file, I have the following code: import Icon from "react-native-vector-icons/MaterialIcons"; const icon = (Icon name="menu size={20} color="green"/>); render() return( ...

Angular's ng-submit directive does not use the most up-to-date scope available

I'm currently learning Angular and have been struggling with a particular issue. I have created a form to edit user details. Upon page load, I make an AJAX call to fetch the data of the selected user and populate the scope with the values. Initially, ...

Execute the function that has been passed through a data attribute

I am attempting to execute a function using its name, which is passed through a data attribute in the HTML. I have made an attempt with the code below: HTML: <div class="generic-select" data-help-on-shown="genericFunction" > </div> ...

A guide on trimming content with v-if in Vue.js

Recently, I attempted to trim the response value within a Vue condition. I require this functionality to apply the condition when the value is null or empty. <li v-if="item[0].otrodl4.trim() == ''" class="progress-step"> ...

Calculating "Time passed" utilizing a predefined timestamp. ("2012-03-27 16:01:48 CEST")

Is there a way to automatically convert the timestamp "2012-03-27 16:01:48 CEST" into "1 hour and 22 minutes since" with time zone management? I'm unable to modify the original timestamp format, which will remain as "2012-03-27 16:01:48 CEST" or simil ...

Default modal overlay closure malfunctioning; encountering errors when manually managed through jQuery

A custom overlay has been designed and implemented. <div class="overlay modal" id="11"> <div class="background-overlay"></div> <div class="description"> <div class="hidden-xs"> <img src=' ...

Guide to executing API PATCH request on the server for a system that approves outings?

I have developed a system for approving outings using the MERN Stack. I wrote code to change the leave status to "Approved", but the changes are not saved when I refresh the page. The PATCH request works fine through Postman. Mongoose Schema Snippet for l ...

"Utilize an HTML file open dialog box to gain access to the server's

Is it feasible to implement a file open dialog box that displays files and directories from the server's file system? In my web application, there is a need for users to select a file that resides on the server. Are there any plugins available for th ...

Encountering Err_Connection_Refused while working with MVC WebAPI 2 and AngularJS

Seeking guidance on WebAPI, AngularJS, and .NET Authentication, I am currently following a tutorial mentioned HERE. The tutorial is brief (~under 10 mins), but I encountered an error stating Failed to load resource: net::ERR_CONNECTION_REFUSED. Typically, ...

What is the best method for closing the open portion of an accordion menu?

I'm experimenting with creating a collapsible accordion feature, but I'm facing a challenge in figuring out how to close the currently open accordion pane. The accordion functions smoothly when expanding sections, but I'm stuck on how to col ...

Is there a way to individually invoke a function on every element within a webpage?

Every element in my database is accompanied by a distinct thumbnail for display purposes. To cater to user preferences, I have included a dropdown menu that triggers the display of different forms based on their selection through a function. However, my cu ...

Understanding how to read a JSON response when the dataType is specifically set to JSONP

I am attempting to send a JSONP request for cross-domain functionality. The issue is that my server does not support JSONP requests and interprets them as regular JSON, responding with an object: {result: 1} Below is the AJAX request I have made: jQuery. ...

What is the recommended depth in the call stack to utilize the await keyword for an asynchronous function?

My knowledge of async functions in TypeScript/React is fairly basic. I have two API calls that need to be made, and I am using async functions to call them from my UI. It's crucial for these calls to have completed before rendering the component corre ...

Is there a way to transform an HTML canvas into a tangible photograph?

I am currently working on converting HTML content into a real image on the client's side. After conducting research on canvas2base64, canvas2base64, and html2base64 on Stack Overflow, I have found that the generated images are always based on base64 c ...

Using the value immediately set by useState is not allowed

I'm facing a dilemma regarding react's useState and I'm unsure of how to resolve it. Here's some context: I have a registration form with field validation triggered onBlur. The validation works perfectly when I blur individual fields, ...