How properly proccess jQuery AJAX in WordPress plugin - javascript

I'm trying to add ajax autosave to my settings page in plugin and made this code:
<?php
function cfgeo_settings_javascript() { ?>
<script type="text/javascript" >
(function($){
$(document).ready(function(){
$("input[id^='cf_geo_'], select[id^='cf_geo_'], textarea[id^='cf_geo_']").on("change keyup", function(){
var This = $(this),
name = This.attr("name"),
value = This.val(),
data = {};
data['action'] = 'cfgeo_settings';
data[name] = value;
console.log(data);
console.log(ajaxurl);
$.post(ajaxurl, data).done(function(returns){
console.log(returns);
});
});
});
}(window.jQuery));
</script> <?php
}
add_action( 'admin_footer', 'cfgeo_settings_javascript');
function cfgeo_settings_callback() {
global $wpdb; // this is how you get access to the database
var_dump($_POST);
if (isset($_POST)) {
// Do the saving
$front_page_elements = array();
$updates=array();
foreach($_POST as $key=>$val){
if($key != 'cfgeo_settings')
update_option($key, esc_attr($val));
}
echo 'true';
}
else
echo 'false';
wp_die(); // this is required to terminate immediately and return a proper response
}
add_action( 'wp_ajax_cfgeo_settings', 'cfgeo_settings_callback');
?>
I find problem that everytime I want to send this simple ajax request I get 0 what is realy enoying.
Here is Console Log when I try to made some change in select option box:
Object {action: "cfgeo_settings", cf_geo_enable_ssl: "true"}
admin.php?page=cf-geoplugin-settings:1733 /wp-admin/admin-ajax.php
admin.php?page=cf-geoplugin-settings:1736 0
What's wrong in my ajax call or PHP script?
I need to mention that both codes are in the one PHP file.

You should have to follow guideline of WordPress ajax method by this admin ajax reference. Please follow this.
https://codex.wordpress.org/AJAX_in_Plugins

Here is a working example with notes included in the comments, there are a lot of don't does in your code and this example addresses those concerns in the code comments.
https://gist.github.com/topdown/23070e48bfed00640bd190edaf6662dc

Related

wp_enqueue_script not working on AJAX called php file

I've got a complicated little problem here.
I'm building a WordPress plugin where I select a "parent" post (of a custom type that I made called 'step') and then an AJAX function shows a new select bar with all of the children of that parent. I do this by outputting the new and elements in the PHP file that's called in the AJAX function. This works, but now I want to repeat the process to run a function from the same JQuery file when this new outputted element is added to the page. (See Javascript code)
Main php plugin file (in a folder within the plugin directory):
<?php
/*
Plugin Name: n8jadams Step by Step Plugin (WIP)
Plugin URI:
Description:
Author: Nathan James Adams
Author URI: http://nathanjamesadams.com
Version: 0.0.1a
*/
//Exit if accessed directly
if(!defined('ABSPATH')) {
exit;
}
//My custom post type, it works fine
require_once(plugin_dir_path(__FILE__).'n8jadams-step-funnel-cpt.php');
require_once(plugin_dir_path(__FILE__).'n8jadams-ajax.php');
//Add my javascript
function n8jadams_init_javascript() {
wp_register_script('n8jadams_javascript', plugin_dir_url(__FILE__).'n8jadams-scripts.js', array('jquery'),'1.1', false);
wp_enqueue_script('n8jadams_javascript');
}
add_action('wp_enqueue_scripts', 'n8jadams_init_javascript');
//Adds a plugin menu to the wordpress sidebar
function n8jadams_add_plugin_menu() {
add_menu_page('', 'Steps Settings', 4, 'steps-settings', 'n8jadams_steps_settings', '');
}
add_action('admin_menu', 'n8jadams_add_plugin_menu');
//The actual function for the menu page
function n8jadams_steps_settings() {
//Access the database and the tables we want
global $wpdb;
$posts = $wpdb->prefix.'posts';
//Get the user id
$user = wp_get_current_user();
$userid = $user->ID;
//Initialize javascript (it works here!)
n8jadams_init_javascript();
/* Get all the parents */
$parentsquery = "
SELECT `ID`, `post_title`
FROM $posts
WHERE `post_author` = $userid
AND `post_parent` = 0
AND `post_status` = 'publish'
AND `post_type` = 'step'
";
$parentsarray = $wpdb->get_results($parentsquery);
?>
<h4>My Forms:</h4>
<select id="parentselect">
<option id="-1"> - Select Your Step Form - </option>
<?php
//output the parents
for($i=0;$i<sizeof($parentsarray);$i++) {
echo '<option id="'.$parentsarray[$i]->ID.'">'.$parentsarray[$i]->post_title.'</option>';
}
?>
</select>
<div id="displayChildren"></div>
<?php
}
?>
Javascript (n8jadams-scripts.js):
(function($){
$('#parentselect').change(function(s) {
var thisID = s.target[s.target.selectedIndex].id;
var outputDisplay = document.getElementById('displayChildren');
if(thisID != '-1') {
$.ajax({
type: 'POST',
url: 'admin-ajax.php',
data: {
action: 'n8jadams_get_children',
id: thisID
},
success: function(response){
if(response == "") {
outputDisplay.textContent = "This form has no children. Add them in the sidebar menu of this step form.";
} else {
outputDisplay.innerHTML = response;
}
},
error: function(errorThrown) {
alert(errorThrown);
}
});
} else {
outputDisplay.textContent = '';
}
});
// I want this function to work
/*
$('#childselect').change(function(t) {
console.log("test");
});
*/
})(jQuery);
PHP file called by AJAX (n8jadams-ajax.php):
<?php
function n8jadams_get_children() {
//Get the id of the parent
$parent_post_id = $_POST['id'];
//Sanitize the input (Added after question was answered)
$parent_post_id = preg_replace("/[^0-9]/","",$parent_post_id);
//Access database
global $wpdb;
$posts = $wpdb->prefix.'posts';
$user = wp_get_current_user();
$userid = $user->ID;
$childrenquery = "
SELECT `ID`, `post_title`,`post_content`
FROM $posts
WHERE `post_parent` = $parent_post_id
AND `post_status` = 'publish'
AND `post_type` = 'step'
AND `post_author` = $userid
";
//Retrieve the children associated with this parent
$childrenarray = $wpdb->get_results($childrenquery);
//Initialize Javascript (it doesn't work here!)
n8jadams_init_javascript();
if(!empty($childrenarray)) { ?>
<h4>My Steps:</h4>
<select id="childselect">
<option id="-1"> - Select Your Step - </option>
<?php
//output the children of the parent
for($i=0;$i<sizeof($childrenarray);$i++) {
echo '<option id="'.$childrenarray[$i]->ID.'">'.$childrenarray[$i]->post_title.'</option>';
} ?>
</select>
<?php wp_die();
}
}
add_action('wp_ajax_n8jadams_get_children', 'n8jadams_get_children');
add_action('wp_ajax_nopriv_n8jadams_get_children', 'n8jadams_get_children');
?>
Screenshot of Plugin Menu
I cannot figure out why my javascript file isn't working in the PHP file that's called by AJAX. Maybe the vast wisdom of the StackOverflow can help me. Thanks for the help in advance. :)
You are hooking into wp_enqueue_scripts, which is only run for the frontend of Wordpress (the part the average visitor sees). If you want to load a script into wp-admin, the backend of Wordpress, use the admin_enqueue_scripts action.
Since this code does not work in /wp-admin/, you don't need to use admin_enqueue_scripts. I guess the whole problem would be that you are attaching a handler to $('#childselect'), while no such element exists on the page at that time. Use deferring with $(..).on(..):
$(document).on('change', '#childselect', function(e) {
//Black magic
});
Side note: As already mentioned in the comments, the following part contains an unsanitised variable which will allow an attacker to perform sql injections.
$childrenquery = "
SELECT `ID`, `post_title`,`post_content`
FROM $posts
WHERE `post_parent` = $parent_post_id
AND `post_status` = 'publish'
AND `post_type` = 'step'
AND `post_author` = $userid
";
Use WP_Query if at all possible. If this is only used from the backend of Wordpress, don't use wp_ajax_nopriv_*, because users that are not logged in into your site have no right to use that anyway.

Trying to load a response sheet from php in the same page

I'm trying to load a response from the php onto the same page. My Client side html looks like this.
<p>
<script type="text/javascript">// <![CDATA[
function sendForm() {
var dataSend = "?ClientName=" + $("#ClientName").val();
$.post("AddClient.php", dataSend, function(data) {
$("#responseDiv").html(data);
});
// ]]></script>
</p>
<div id="responseDiv"> </div>
<form action="AddClient.php" onsubmit="sendForm()">
<h1>Client Wizard <span>Please fill all the texts in the fields.</span></h1>
<label> <span>Client Name :</span> <input id="ClientName" type="text" name="ClientName" /> </label> <span> </span> <input class="button" type="Submit" value="Send" />
</form>
My Server side php looks like this:
<?php
$dbhost='127.0.0.1';
$dbuser='name';
$dbpass='password';
$dbname='dbname';
$conn=mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$conn)
{
die('Could not connect:'.mysqli_connect_error());
}
$client=$_REQUEST["ClientName"];
$retval=mysqli_query($conn,"INSERT into client (clientid,clientname) VALUES (NULL,'$client')");
if(!$retval)
{
die('Could not add client:'.mysql_error());
}
$display_string="<h1>Client Added Successfully</h1>";
echo $display_string;
mysqli_close($conn);
?>
Unfortunately not only is the response being shown in anew html page, Its not accepting any name typed in the form. When I check the sql table the Column has a blank entry under it. I have not been able to figure out where I'm going wrong. Any help would be really appreciated.
All right. Your code have some room for improvement, but it's not an endless thing.
I saw somebody mention sanitization and validation. Alright, we got that. We can go in details here
This is how I will restructure your code using some improvements made by Samuel Cook (thank you!) and added a lot more.
index.html
<p>
<script type="text/javascript">// <![CDATA[
function sendForm() {
var dataSend = {clientName: $('#clientName').val()}
$.post("AddClient.php", dataSend, function(data) {
$('#responseDiv').html(data);
});
return false;
}
//]]>
</script>
</p>
<div id="responseDiv"></div>
<form action="AddClient.php" onsubmit="sendForm(); return false;">
<h1>Client Wizard <span>Please fill all the texts in the fields.</span></h1>
<label><span>Client Name :</span><input id="clientName" type="text" name="clientName"/><span></span><input type="submit" class="button" value="Send"></label>
</form>
Notice change in an input id and input name - it's now start with a lower case and now clientName instead of ClientName. It's look a little bit polished to my aesthetic eye.
You should take note on onsubmit attribute, especially return false. Because you don't prevent default form behavior you get a redirect, and in my case and probably your too, I've got two entries in my table with a empty field for one.
Nice. Let's go to server-side.
addClient.php
<?php
$dbhost = '127.0.0.1';
$dbuser = 'root';
$dbpass = '123';
$dbname = 'dbname';
$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
if (!$conn) {
die('Could not connect: ' . mysqli_connect_error());
}
$client=$_REQUEST["clientName"];
$client = filter_var($client, FILTER_SANITIZE_STRING);
if (isset($client)) {
$stmt = $conn->prepare("INSERT into client(clientid, clientname) VALUES (NULL, ?)");
$stmt->bind_param('s', $client);
$stmt->execute();
}
if (!$stmt) {
die('Could not add client:' . $conn->error);
}
$display_string = "<h1>Client $client Added Successfully</h1>";
echo $display_string;
mysqli_close($conn);
?>
That is going on here. We are using PHP filters to sanitize our incoming from somewhere string.
Next, we check if that variable $client even exist (you remember that twice sended form xhr? Double security check!)
Here comes a fun part - to protect our selves even more, we start using prepared mySQL statements. There is no way someone could SQL inject you somehow.
And just check for any errors and display it. Here you go. I've tested it on my machine, so it works.
Forms default behavior is to redirect to the page given in the action attribute (and if it's empty, it refreshes the current page). If you want it to make a request without redirecting to another page, you need to use Javascript to intercept the request.
Here's an example in jQuery:
$('form').on('submit', function(e) {
e.preventDefault(); // This stops the form from doing it's normal behavior
var formData = $(this).serializeArray(); // https://api.jquery.com/serializeArray/
// http://api.jquery.com/jquery.ajax/
$.ajax($(this).attr('action'), {
data: formData,
success: function() {
// Show something on success response (200)
}, error: function() {
// Show something on error response
}, complete: function() {
// success or error is done
}
});
}
Would recommend having a beforeSend state where the user can't hit the submit button more than once (spinner, disabled button, etc.).
First off, you have a syntax error on your sendForm function. It's missing the closing bracket:
function sendForm() {
//...
}
Next, You need to stop the form from submitting to a new page. Using your onsubmit function you can stop this. In order to do so, return false in your function:
function sendForm() {
//...
return false;
}
Next, you aren't actually sending any POST data to your PHP page. Your second argument of your .post method shouldn't be a query string, but rather an object (I've commented out your line of code):
function sendForm() {
var dataSend = {ClientName:$("#ClientName").val()}
//var dataSend = "?ClientName=" + $("#ClientName").val();
$.post("AddClient.php", dataSend, function(data) {
$("#responseDiv").html(data);
});
return false;
}
Lastly, you have got to sanitize your data before you insert it into a database. You're leaving yourself open to a lot of vulnerabilities by not properly escaping your data.
You're almost there, your code just need a few tweaks!

How to execute the code inside javascript confirm box

I have a JavaScript confirm box and i have some MySQL insert query code to be executed at some condition. This is how my code look like:
<?php
$id = $_POST['id'];
$name= $_POST['name'];
$query = mysql_query("select * from table where id='$id'");
$count = mysql_num_rows($query );
if($count!=0)
{
?>
<script type="text/javascript">
if (confirm("This seems to be Duplicate. Do you want to continue ?") == true)
{
//Execute/Insert into table as how it is given below
}
else
{
//Dont execute/insert into table but close the window
}
</script>
<?php
}
else
{
$queryinsert = mysql_query("INSERT INTO table(id,name) VALUES('$id','$name')");
}
?>
You can't execute MySQL or PHP command inside javascript, what you can do instead is to make a PHP function that you can call by Ajax. The best way is by using jQuery or by redirecting the page with your PHP function in URL.
<script type="text/javascript">
if (confirm("This seems to be Duplicate. Do you want to continue ?"))
{
$.ajax({
url: 'your_path_to_php_function.php',
type: 'POST', // Or any HTTP method you like
data: {data: 'any_external_data'}
})
.done(function( data ) {
// do_something()
});
}
else
{
window.location = 'your_url?yourspecialtag=true'
}
</script>
You're mixing serverside and clientside scrips. This won't work. You have to use AJAX, which are asynchronous server-client/client-server requests. I recommend jQuery, which is JavaScript which easily handles lot of things, including AJAX.
Run this if user confirms action
$.post("phpscript.php", {action: true})
Php file:
if ($_POST['action'] === TRUE) {
<your code here>
}

There is no alert when submitting a form using ajaxForm plugin

How can I have an alert that the form has been submitted successfully? I have already tried to look at the page of the plugin still come up empty handed.
This is the code I have tried so far maybe there is something wrong with my syntax:
<script type="text/javascript">
$(document).ready(function(){
$('#f1').ajaxForm({
success: function(){
alert("Form successfully submitted");
}
});
});
</script>
The code above works and successfully inserted all the data in the forms but the alert that suppose to appear after successfully submitted the form is missing for some reason.
This is the script that the form uses when submitting:
<?php
$title=$_REQUEST['articletitle'];
$articlemore=$_REQUEST['editor1'];
include "connection.php";
if (isset($_FILES['image']) && $_FILES['image']['size'] > 0)
{
$type=$_FILES['image']['type'];
// Temporary file name stored on the server
$tmpName = $_FILES['image']['tmp_name'];
// Read the file
$fp = fopen($tmpName, 'r');
$data = fread($fp, filesize($tmpName));
$data = addslashes($data);
fclose($fp);
$query = "INSERT INTO blog(articletitle, articleimage, articlemore) VALUES ('$title', '$data', '$articlemore')";
$results = mysqli_query($link, $query);
if(!$results)
{
echo "Saving Post Failed";
}
else
{
echo "You have a new Post!";
}
}//end if that checks if there is an image
else
{
echo "No image selected/uploaded";
}
// Close our MySQL Link
mysqli_close($link);
?>
Here is the Syntax
// wait for the DOM to be loaded
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#myForm').ajaxForm(function() {
alert("Thank you for your comment!");
});
});
I hope this will help you
Change this:
$('#f1').ajaxForm({
to
$('#f1').ajaxForm(function(){

php array to external page using jquery

I have a php page to creates a multi-dimentional array called $results.
I would like to:
catch submit of a form button
override default behavior of the submit using jQuery
copy and process $results on separate php using $.post
I have this which is not currently working and am not sure why?:
<form id='download_to_excel' method="post">
<input type="image" name="submit" value="submit" id='xls_download_button' src='images/common/buttons/download.png'>
</form>
<?php
$json_results = json_encode($results);
?>
<script type='text/javascript'>
$(document).ready(function(){
alert($json_results);
$("#xls_download_button").click(function(e){
alert('clicked');
e.preventDefault();
download_xls();
});
function download_xls(){
$.post('./libs/common/export_data_to_excel.php', {json_data : json_results};
}
});
</script>
When selecting the xls_download_button, the alert() never fires nor does any data get passed to export_data_to_excel.php
The export_data_to_excel.php file has the following:
<?php
$results = json_decode($_POST['json_data']);
#include the export-xls.class.php file
require_once('export-xls.class.php');
$date = date('Y-m-d');
$filename = "contacts_search_$date.xls"; // The file name you want any resulting file to be called.
#create an instance of the class
$xls = new ExportXLS($filename, $results);
#lets set some headers for top of the spreadsheet
$header = "Searched Contact Results"; // single first col text
$xls->addHeader($header);
#add blank line
$header = null;
$xls->addHeader($header);
$header = null;
$row = null;
foreach($results as $outer){
// header row
foreach($outer as $key => $value){
$header[] = $key;
}
// Data Rows
foreach($outer as $key => $value){
$row[] = $value;
}
$xls->addRow($header);//add header to xls body
$header = null;
$xls->addRow($row); //add data to xls body
$row = null;
}
# You can return the xls as a variable to use with;
# $sheet = $xls->returnSheet();
#
# OR
#
# You can send the sheet directly to the browser as a file
#
$xls->sendFile();
?>
I do know that the $json_results does display proper JSON encoded values when echoed. But from there are not sure why the rest of the javascript does not run; the alerts never fire nor does the JSON data get passed?
Can you see why this isn't working?
Your PHP-supplied json is not stored as a javascript variable in your js.
$(document).ready(function(){
var json_results = <?php echo $json_results; ?>;
...
This code shouldn't run:
function download_xls(){
$.post('./libs/common/export_data_to_excel.php', {json_data : json_results};
}
It is invalid (the ; doesn't belong there). Try this code:
function download_xls(){
$.post('./libs/common/export_data_to_excel.php', {json_data : json_results});
}
Right now you are just setting a php variable called $results you need to transfear it to you javascript.
<script type="text/javascript">
// set javascript variable from php
var $results = "<?php echo json_decode($json_data); ?>";
</script>
For sure you have an error in your javascript code (you were not closing the parenthesis after $.post), should be:
$(document).ready(function() {
alert($json_results);
$("#xls_download_button").click(function(e) {
alert('clicked');
e.preventDefault();
download_xls();
});
function download_xls() {
$.post('./libs/common/export_data_to_excel.php', {
json_data: json_results
});
}
});
Then you should assign your JSON to a javascript variable inside document.ready
$(document).ready(function() {
var json_results = <?php echo($json_results);?>;
You can't pass a PHP variable to the JavaScript like that: there live in totally different worlds. Use Ajax to get the JSON data from JS.

Categories

Resources