• Resolved SWTechnologies

    (@swtechnologies)


    Attempting to use Ajax/jQuery for the first time and running into an issue where form submission isn’t being handled by my jQuery function (for a plugin I’m developing). Can’t for the life of me understand why!

    I have a plugin admin page which has a button (‘Add New’) … clicking the ‘Add New’ button changes the contents of another div on the page (loads a form consisting of two input fields and a submit button). I can get the contents of the div to display (clicking the ‘Add New’ button), but can’t get jQuery to handle the clicking of the form’s submit button.

    Here’s the code in the main plugin file which adds the submenu (‘Race Types’), enqueues the scripts (I have two separate script files) and builds the HTML page

    /* ******************************************************
     * Create the submenus for managing race report options *
     * ******************************************************/
    
    /* Adds the submenus for managing race report options */
    // Hook for adding admin menus
    function swt_race_reports_add_pages() {
    	global $raceTypesPage;
    	global $raceReportsPluginDir;
    
    	$raceReportsPluginDir = get_settings('home').'/wp-content/plugins/'.dirname(plugin_basename(__FILE__));
    
    	// add the new sub-menus
    	$raceTypesPage = add_submenu_page( "edit.php?post_type=swt_race_report", "Race Types", "Manage Types", "manage_options", "race_report_types", "swt_raceReports_manageReportTypes");
    
    	// add any required scripts for Race Type page
    	add_action( "admin_enqueue_scripts", 'swt_raceReports_admin_head' ); // general JavaScript for Race Report plugin
    	add_action( "admin_enqueue_scripts", 'swt_raceReports_raceType_scripts' ); // general JavaScript for Race Report plugin
    }
    add_action('admin_menu', 'swt_race_reports_add_pages');
    
    /* ******************************************************
     * All scripts for managing race report options 		*
     * ******************************************************/
    
    /* Adds to the page header for this plugin */
    function swt_raceReports_admin_head($hook) {
    	global $raceReportsPluginDir;
    	global $raceTypesPage;
    
    	if ($hook != $raceTypesPage) {
    		// we aren't on the $raceTypesPage, so skipout
    		return;
    	}
    
    	wp_enqueue_script('swt_raceReports_js', $raceReportsPluginDir . '/js/swt_raceReports.js');
    	wp_localize_script( 'swt_raceReports_js', 'swt_raceReports_pluginPath', array( 'plugin_dir' => $raceReportsPluginDir ) );
    	echo "<link rel='stylesheet' href='$raceReportsPluginDir/raceReports.css' type='text/css' />\n";
    }
    
    /* Adds the script for handling form submission */
    function swt_raceReports_raceType_scripts($hook) {
    	global $raceReportsPluginDir;
    	global $raceTypesPage;
    
    	if ($hook != $raceTypesPage) {
    		// we aren't on the $raceTypesPage, so skipout
    		return;
    	}
    
    	wp_enqueue_script('swt_raceReports_raceType_ajaxHandler', $raceReportsPluginDir . '/js/swt_raceTypes.js', array( 'jquery' ));
    }
    
    /* ******************************************************
     * All pages for managing race report options 			*
     * ******************************************************/
    
    function swt_raceReports_manageReportTypes() {
    	echo "<h1>Race Types</h1>";
    	echo "<section id='race_type_selection'>";
    		echo "<label for='selected_race_type'>Available Race Types</label>";
    		echo "<select name='selected_race_type'>";
    			echo "<option value='nothing'>No Race Types Exist</option>";
    		echo "</select>";
    		echo "<button type='button' class='button-primary' onclick='loadCreateNewRaceType()'>Add New</button>";
    	echo "</section>";
    	echo "<hr />";
    	echo "<section id='selected_race_type_section'>";
    		echo "<p>Please select a race type<p>";
    	echo "</section>";
    }

    On click of the ‘Add New’ button I’m calling the loadCreateNewRaceType() method which is stored in the file swt_raceReports.js. This script handles clicking of the ‘Add New’ button and displays a the contents read from a PHP file (swt_raceReport_raceTypeCreateForm.php)

    function  loadCreateNewRaceType() {
    	var xmlhttp;
    	if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
    		xmlhttp=new XMLHttpRequest();
    	}
    	else {// code for IE6, IE5
    		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    	}
    
    	xmlhttp.onreadystatechange=function() {
    		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
    			document.getElementById("selected_race_type_section").innerHTML=xmlhttp.responseText;
    		}
    	}
    	xmlhttp.open("GET",swt_raceReports_pluginPath.plugin_dir+"/swt_raceReport_raceTypeCreateForm.php",true);
    	xmlhttp.send();
    }

    Here’s the code for building the form that was loaded in the JS above … the code is stored in the swt_raceReport_raceTypeCreateForm.php file:

    echo "<h2>Create New Race Type</h2>";
    echo "<div id='failureMessage' class='statusMessage'><p>There was a problem creating your race type.</p></div>";
    echo "<form id='swt_createRaceTypeForm' action='' method='post'>";
    	echo "<p><label for='raceTypeName'>Race Type Name</label>: ";
    	echo "<input type='text' name='raceTypeName' placeholder='Name your race type' required='required' /></p>";
    	echo "<p><label for='parentRaceType'>Parent Race Type</label>: ";
    	echo "<select name='parentRaceType'>";
    		echo "<option value='noParentRaceType'>No Parent Type</option>";
    	echo "<p></select></p>";
    	echo "<p><input type='submit' name='swt_createRaceTypeButton' class='button-primary' value='Create Type'></p>";
    echo "</form>";

    Here’s the JS which I want called when the submit button in the swt_createRaceTypeForm form is clicked … this code is saved in a file called swt_raceTypes.js. For now I just want to display a test alert message to indicate this is working:

    jQuery(document).ready(function( $ ) {
    	alert('loading jQuery ready function');
    	$('#swt_createRaceTypeForm').submit(function(e) {
    		alert('test');
    		e.preventDefault();
    	});
    });

    Up until clicking of the form submit button, everything works as expected. When my page first loads (before anything is rendered), I see the “Loading jQuery ready function” alert popup, so I can confirm the script file is loaded (at this point the swt_createRaceTypeForm form isn’t displayed on the screen yet, that only happens once the ‘Add New’ button is pressed and the form gets displayed).

    Once the swt_createRaceTypeForm is displayed and the submit button is pressed, I’d expect the “Test” alert message to popup … instead the entire page is refreshing and I start all over (of course this is the default behaviour of a PHP form with an empty action … which is done on purpose since I’m expecting the jQuery statement to intercept the submit action). In addition to displaying the test alert message, e.preventDefault() should be preventing my page from reloading and it’s not.

    Any ideas, suggestions or help would be greatly appreciated.

Viewing 12 replies - 1 through 12 (of 12 total)
  • Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    Let’s see your page

    Thread Starter SWTechnologies

    (@swtechnologies)

    Hey Andrew, unfortunately the plugin is for the backend and requires users to be logged in with an admin account … so I’m not quite sure how you can actually play around with it (open to reasonable suggestions).

    Would screenshots suffice? If so, you can find a visual representation of the steps in question here: Screen Shots

    Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    Try to replicate your issue in a jsFiddle page https://jsfiddle.net/

    Thread Starter SWTechnologies

    (@swtechnologies)

    Hi Andrew … before I mock something up in jsFiddle I wanted to check if the problem was in my code or in my understanding of how jQuery works.

    I created a brand new admin page using the exact same code explained above, only this time I took out the first step of the process… instead of first clicking the ‘Add New’ button and displaying the form, I just display form right from the start. When the form’s submit button is clicked, .submit() in my jQuery code is actually hit and my ‘test’ alert message is popped up.

    So this isn’t a matter inability to understand and use jQuery, but my understanding of the ordering/loading/displaying of things.

    Is there an issue with jQuery if when you load the script but the DOM object (my form) isn’t currently on the page? My form only gets added to the page after I click the first button, yet the jQuery script was added prior to this (on initial page load).

    I’ve inspected my page and can see the js files there, so I know the jQuery code is there, just not sure why everything works when I display the form right on page load and click the submit button, but when I only display the form after clicking the ‘Add New’ button first, the exact same code is not being called.

    I’ll try and get something up using jsfiddle … at least this will determine if it’s a WordPress framework issue or my understanding of jQuery… just thought I’d share my findings prior to doing this incase there was some basic thing I was missing.

    Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    Is there an issue with jQuery if when you load the script but the DOM object (my form) isn’t currently on the page?

    Not if you’re using $(document).ready() – which you are. Unless you’re manipulating the DOM after it has loaded and adding an element in.

    Thread Starter SWTechnologies

    (@swtechnologies)

    If I’m understanding what you are saying correctly, I think I am doing that.

    On initial page loading, my jQuery script is loaded and the DOM does not contain my form (which is what the jQuery script is listening for). After the page loads (along with all it’s scripts), you click the ‘Add New’ button which will change the DOM to now include my form (which is what my jQuery script is listening for). I would expect jQuery to handle the clicking of the submit button on that form.

    Does this constitute changing the DOM after the fact? If so, does this mean I can only load my jQuery script only after I change the DOM and add my form in?

    Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    Does this constitute changing the DOM after the fact?

    Yes, but that shouldn’t affect your circumstances. Your jQuery is still listening out for the form to be submitted and so it won’t fire until it the “#swt_createRaceTypeForm” element has been found and submitted.

    Are you using your browser’s console log?

    Thread Starter SWTechnologies

    (@swtechnologies)

    OK, I think I’ve resolved the issue after some more Googling (I spent several hours yesterday, sometimes a little sleep helps sharpen your Google kung fu).

    I found a post (Click event is not firing after DOM changes in jQuery) which stated a similar problem and the following was proposed:

    Bind the event handler to the button’s click event using live() instead of click()

    So I changed my jQuery script as follows:

    jQuery(document).ready(function( $ ) {
    	alert('loading jQuery ready function');
    	$('#swt_createRaceTypeForm').live('submit', function(e) {
    		alert('test');
    		e.preventDefault();
    	});
    });

    Things are working now … do you see any issue or concerns with doing things this way (using .live)? I’m going to read the docs for .live() to get a full understanding of what’s happening, but for now it’s working ??

    Really appreciate your time Andrew, thanks so much!

    Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    No problems with that, you are using the live method as its intended purpose.

    Thread Starter SWTechnologies

    (@swtechnologies)

    Well I looked up .live and it indicates that as of jQuery 1.7, .live() has been deprecated and I should be using .on() … I’m running WordPress 3.8 which comes with jQuery 1.10.2 … so in theory .on() should be used in place of .live() … unfortunately the following jQuery is not working:

    jQuery(document).ready(function( $ ) {
    	$('#swt_createRaceTypeForm').on('submit', function(e) {
    		alert('test');
    		e.preventDefault();
    	});
    });

    I will switch it back to using .live(), but feel wrong doing so as it’s deprecated. Any thoughts/advise on .on()?

    Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    The guys at jQuery’s support forum really know what they’re on about – https://jquery.org/support/

    Thread Starter SWTechnologies

    (@swtechnologies)

    Good call, thanks Andrew

Viewing 12 replies - 1 through 12 (of 12 total)
  • The topic ‘jQuery .submit Not Being Called’ is closed to new replies.