简体   繁体   中英

jQuery plugin event listeners not firing or binding

I'm creating a web application that utilizes popups. I'm using the same popups on several pages, but with various differences between pages. This is all controlled through JavaScript (jQuery).

So, I decided to create a jQuery plugin to make those changes easily. The problem is that the listeners I created in the plugin definition aren't firing on click or even being shown as bound to those elements in the inspector. I'm not sure what the problem is, because it should be no different than binding events through functions.

Here's my code:

(function($) {


    // Plugin Definition
    $.fn.popup = function(options){
        console.log("Popup Initializing");

        // Override default settings with instance settings
        var settings = $.extend({}, $.fn.popup.defaults, options);
        console.log("Settings merged");

        // Saving objects passed into function
        var els = this;



        console.log("Attaching Edit Event Listener");
        // EDIT
        //alert(settings.contentSelector + " " + settings.editButtonSelector);
        $("#content").on("click", ".table .edit", function() {
            console.log("Edit button clicked");
            settings.isEdit = true; settings.isAdd = false;
            row = $(this).parent();
            header = row.siblings(settings.tableHeaderRowSelector);
            headerCells = header.children();
            titleCell = row.children(":first").text();

            $(settings.popupHeaderSelector).html("Editing '" + titleCell + "'");    // set header
            $(settings.popupOriginalIdSelector).val(row.children().eq(0).html());
            $(settings.popupSubmitSelector).html("Update");                         // set submit button text

            // Generate and write form DOM to page
            if (settings.autoGeneratePopupForm){
                formContent = generateFormContent(headerCells, row);         // Generate form inputs
                optionsCurrentValues = formContent[1];                  // Grab current option input values
                $(settings.popupContentSelector).html(formContent);     // write form contents to DOM

                // set options to correct current settings
                $.each(optionsCurrentValues, function(index, value) {
                    $("select[name='"+index+"']").val(value);
                });
            }

            showPopup();
            focusFirstEl();
        });


        console.log("Adding Add Event Listener");
        // ADD
        $(settings.contentSelector).on("click", settings.addButtonSelector, function() {
            console.log("Add button clicked");
            settings.isAdd = true; settings.isEdit = false;
            headerCells = $(this).siblings();
            row = $(this).parent().next(".row").children().not(".icon");


            $(settings.popupHeaderSelector).html("Add New " + dataType);    // set header
            $(settings.popupSubmitSelector).html("Add " + dataType);        // set submit button text

            // Generate and write form DOM to page
            if (settings.autoGeneratePopupForm){
                formContent = generateFormContent(headerCells, row);         // Generate form inputs
                $(settings.popupContentSelector).html(formContent);          // write form contents to DOM
            }

            showPopup();
            focusFirstEl();
        });



        console.log("Adding Cancel Event Listener");
        // CANCEL
        $(settings.popupCancelSelector).click(function() {
            hidePopup();
        });


        console.log("Adding User Enter Submission Prevention");
        // PREVENT ENTER SUBMIT
        $(settings.popupSelector + " form").keydown(function(event) {
            var keycode = (event.keyCode ? event.keyCode : event.which);
            if(keycode == '13') {
                event.preventDefault();
                return false;
            }
        });


        console.log("Finished Initializing");
        console.log("");
        console.log(settings);
        // Ensures chainability
        return this;
    };


    /**
        Generates form inputs based on the passed parameters.
        @param headerRow the header row of the associated DOM table.
                         Must be from PHP generated DOM. See ImgsrcUI->printTable
        @param contentRow the row of the associated DOM table to generate
                          the form inputs from.  Must be from PHP generated DOM
                          See ImgsrcUI->printTable
        @returns an array.  1st index is of generated form DOM, 2nd index is of current values of the inputs
    */
    function generateFormContent(headerCells, contentRow){
        formContent = "";       // Empty string filled with generated DOM

        contentRow.children().not(".icon").each(function(index) {
            inputType = headerCells.eq(index).attr("data-inputtype");     // Get type of input this cell should be
            inputLabel = headerCells.eq(index).attr("data-inputlabel");   // Get the text for the label for this cell
            cellVal = settings.isEdit == true ? $(this).text() : "";      // Get current value of cell
            name = inputLabel.replace(/ /g,'');                           // Removed spaces from input label to generate the name attr for the input
            optionsCurrentValues = {};     // assoc array of input name and value so that it can be set after applied to DOM

            switch (inputType){
                case "text":
                formContent += '<label>'+inputLabel+'</label> <input name="new'+name+'" type="'+inputType+'" value="'+cellVal+'">'
                break;

                case "select":
                options = headerCells.eq(index).attr("data-selectoptions"); // get string version of var name 
                options = eval(options); // assign that var value to options
                formContent += '<label>'+inputLabel+'</label> <select name="new'+name+'" id="">'+options+'</select>';
                optionsCurrentValues["new"+name] = cellVal;
                break;

                case "textarea":
                formContent += '<label>'+inputLabel+'</label> <textarea name="new'+name+'" ></textarea>';
                break;
            }
        });

        return [formContent, optionsCurrentValues];
    }

    // Shows the popup and darkens the background
    function showPopup(){
        $(settings.darkenBackgroundSelector).show();
        $(settings.popupSelector).show();
    };

    // Hides the popup and lightens the background
    function hidePopup(){
        $(settings.darkenBackgroundSelector).hide();
        $(settings.popupSelector).hide();
    }

    // Puts focus on the first form element in the popup
    function focusFirstEl() {
        //$(popupSelector+" form").children(":first").focus();
        $(settings.popupSelector + " form :input:visible:enabled:first").focus();
    };

    // Default Settings
    $.fn.popup.defaults = {
        autoGeneratePopupForm: false,               // If true, the contents of the popup will be overwritten with a generated form inputs based on the data you click "edit" on.  If false, no content is overwritten.
        dataType: "data",                       // The name of the data type (Ex "Users", "Albums").  Used in the header of the popup

        // General Selectors
        darkenBackgroundSelector: "#darken-page",   // The selector to darken the page behind the popup
        contentSelector: "#content",                // The selector for the main content area

        // DOM Table Selectors
        tableHeaderRowSelector: ".heading",
        editButtonSelector: ".table .edit",
        addButtonSelector: ".table .heading .add",

        // Popup Selectors
        popupSelector: ".popup.edit",
        //popupContentSelector: this.popupSelector + " .content",
        popupHeaderSelector: this.popupSelector + " .header p",
        popupOriginalIdSelector: this.popupSelector + " #originalId",
        popupSubmitSelector: this.popupSelector + " .footer .submit",
        popupCancelSelector: this.popupSelector + " .cancel",

        // Utility options.  Don't change.
        isEdit: false,
        isAdd: false,
    };
    $.fn.popup.defaults.popupContentSelector = $.fn.popup.defaults.popupSelector + " .content";
    $.fn.popup.defaults.popupHeaderSelector = $.fn.popup.defaults.popupSelector + " .header p";
    $.fn.popup.defaults.popupOriginalIdSelector = $.fn.popup.defaults.popupSelector + " #originalId";
    $.fn.popup.defaults.popupSubmitSelector = $.fn.popup.defaults.popupSelector + " .footer .submit";
    $.fn.popup.defaults.popupCancelSelector = $.fn.popup.defaults.popupSelector + " .cancel";

}(jQuery));

and I'm calling it on the page like so:

 $("html").popup({
    autoGeneratePopupForm: true,
    dataType: "User"
 });

Any ideas? Thanks in advance.

Somehow, I overlooked a simple issue.

Since my JS wasn't within a $(document).ready(function() {}); , it was running as soon as the <script> tag was encountered, which was before the DOM was rendered on the page.

Therefore, the JS was trying to bind to elements that didn't yet exist on the page.

Hope this helps anyone that stumbles upon this issue. Always make sure the DOM you're manipulating is actually on the page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM