Submit form with AJAX and PHP without page reload - javascript

I have "add to favorite" feature in my wordpress project, I am using <form> to submit the feature. Each time I click on add to fav button it works, but the page is always reloaded which is annoying so I decided to use AJAX, but I can not connect it with my PHP file.
This is PHP file, where I wrote function for the feature
if (! function_exists('favorite_button_icon')) {
function favorite_button_icon() {
echo apply_filters( 'favorite_button_icon', get_the_favorite_button_icon() );
}
}
if (! function_exists('get_the_favorite_button_icon')) {
function get_the_favorite_button_icon() {
$output = '';
$action = $currentPath; // window.location.href
$name = is_favorite() ? 'remove_favorite' : 'add_favorite';
$class = 'favorite-button-pro' . ( is_favorite() ? ' favorite' : '' );
$icon = is_favorite() ? 'Added' : 'Add';
$output .= '<form method="post" id="favorite_user_post"
class="favorite_user_post" action="'. $action .'">';
$output .= '<button id="submit-favorite" type="submit" name="'. $name .'"
value="'. get_the_ID() .'" class="'. $class .'">';
$output .= $icon;
$output .= '</button></form>';
return apply_filters( 'get_the_favorite_button_icon', $output );
}
}
And I am just calling that function in html
<div class="add-to-favorites-option" >
<?php favorite_button_icon() ?>
</div>
Everything above works, but as I said, page is being reloaded.
This is my attempt to use AJAX
jQuery('#favorite_user_post').submit(function (e) {
e.preventDefault();
var form = jQuery(this);
var url = form.attr('action');
jQuery.ajax({
type: 'POST',
url: url,
data: form.serialize(),
success: function (data) {
console.log(data);
},
error: function () {
console.log('Fail');
},
});
});
I get absolutely no fire on submit, am I missing something?

You need to use the wp_ajax_ hook: https://developer.wordpress.org/reference/hooks/wp_ajax_action/
Simple example below:
You PHP code to process the ajax request:
add_action( 'wp_ajax_my_action', 'my_action' );
function my_action() {
// code that captures your ajax POST request
wp_die(); // this is required to terminate immediately and return a proper response
}
Your Ajax call:
jQuery('#favorite_user_post').submit(function (e) {
e.preventDefault();
var form = jQuery(this);
// note the added "my_action" to tell the server what function to fire (my be a better way to append this to your form data)
var url = form.attr('action') + "&=my_action";
jQuery.ajax({
type: 'POST',
url: url,
data: form.serialize(),
success: function (data) {
console.log(data);
},
error: function () {
console.log('Fail');
},
});
});

Related

Run php file via jquery call in Wordpress

So I wish to replicate the following functionality in wordpress. Jquery calls a php file, which itself queries a mysql table, and returns the result encapsulated within an tag. How do I go about achieving this?:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
....
function initialize() {
....
feedData();
}
$(document).ready(function () { initialize(); });
function feedData() {
$(document).ready(function () {
$.ajax({
cache: false,
type: "POST",
async: false,
url: "page-gotw-search.php",
data:{"action=showcountries"},
success: function (data) {
$('#CountryList').append(data);
},
error: function (data, status, error) {
console.log(data);
console.log(status);
console.log(error);
}
});
});
}
</script>
<body>
<div style="width: 800px">
<div style="float: left">
<select id="CountryList" onchange="getRegion()" size="20"></select>
<select id="RegionList" size="20" onchange="getMap()"></select>
</div>
<div id="cityList" style="float: right"></div>
</div>
</body>
</html>
page-gotw-search.php
<?php
include_once("pdo_mysql.php");
pdo_connect("localhost","root","");
pdo_select_db("wpdb");
$action=$_POST["action"];
if($action=="showcountries"){
$showcountry = pdo_query("Select distinct meta_value from wp_usermeta where meta_key =?, pdo_real_escape_string('country_registration')");
if (!$showcountry) {
$message = 'Invalid query: ' . pdo_error() . "\n";
$message .= 'Whole query: ' . $showcountry;
die($message);
}else{
foreach($showcountry as $row){
echo '<option value=".$row[country_code].">.$row[country_name].</option>';
}
}
}
else if($action=="showregions"){
$country_id= $_POST["country_id"];
$showregion = pdo_query("Select region_code, region_name from regiontbl
WHERE country_id=?", pdo_real_escape_string($country_id));
if (!$showregion) {
$message = 'Invalid query: ' . pdo_error() . "\n";
$message .= 'Whole query: ' . $regionquery;
die($message);
}else{
foreach($showregion as $row){
echo '<option value=".$row[region_code].">.$row[region_name].</option>';
}
}
}
?>
Looks like you want to implement ajax into the wordpress.
I have a simple way to do this. Follow below given steps to use ajax calls in wordpress
add some code in footer.php
jQuery(‘#clickerid').change(function(){
var your_id = jQuery(‘#get_val').val();
var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
jQuery.ajax({
cache: false,
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php'); ?>',
data: ‘id='+ id + '&action=get_id',
success: function(data)
{
jQuery(‘#id').html(data);
}
});
});
Then use this ajax call into the functions.php
add_action( 'wp_ajax_get_your_action', 'prefix_ajax_get_your_action' );
add_action( 'wp_ajax_nopriv_get_your_action', 'prefix_ajax_get_your_action' );
function prefix_ajax_get_costofcare() {
// Do your php code used in ajax call and return it.
}
Ajax calls works via admin-ajax.php which is build in functionality provided by wordpress

How to disable link after first click and allow user to vote only if logged in

i am working on a plugin in wordpress to vote up a post or vote down using ajax.
Everything is working fine but the problem is am not able to disable the onclick eventhandler after first click so whenever someone voting a post , he can add vote multiple times. I want to ignore that so i should be able to vote only once. If i click on vote up then the voteup anchor tag should be disable and votedown anchor tag should be enable. At the same time if i click on the votedown anchor tag then votedown should be disable and voteup should be enable. Also i want to enable the voting feature only if the user is logged in the wordrpess.
I have a function to show a popup if the user is not logged in.
i.e login_open();
If user is not logged in and try to vote up then this function should execute login_open();
Otherwise user should be able to vote or downvote only once ..
Here is my code //
php
//Defining Base Paths
define('VOTEUPURL', WP_PLUGIN_URL."/".dirname( plugin_basename( __FILE__ ) ) );
define('VOTEUPPATH', WP_PLUGIN_DIR."/".dirname( plugin_basename( __FILE__ ) ) );
//Enqueue Script for the Admin Ajax and Cutom Js File
function voteme_enqueuescripts()
{
wp_enqueue_script('voteme', VOTEUPURL.'/js/voteup.js', array('jquery'));
wp_localize_script( 'voteme', 'votemeajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
wp_localize_script( 'votedown', 'votedownajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}
add_action('wp_enqueue_scripts', voteme_enqueuescripts);
//Adding Vote up links to all the posts.
function voteme_getvotelink(){
$votemelink = "";
$post_ID = get_the_ID();
$votemecount = get_post_meta($post_ID, '_votemecount', true) != '' ? get_post_meta($post_ID, '_votemecount', true) : '0';
$link = $votemecount.' '.'Vote Up'.'';
$link .=' '.'Vote Down'.'';
$votemelink = '<div id="voteme-'.$post_ID.'">';
$votemelink .= '<span>'.$link.'</span>';
$votemelink .= '</div>';
return $votemelink;
}
//Function to get the count
function get_current_vote_count(){
$voteup_count = "";
$post_ID = get_the_ID();
$votemecount = get_post_meta($post_ID, '_votemecount', true) != '' ? get_post_meta($post_ID, '_votemecount', true) : '0';
$votelink = '<span class="vote_count">'. $votemecount .'</span>';
return $votelink;
die($votelink);
}
//Add Vote Function
function voteme_addvote()
{
$results = '';
global $wpdb;
$post_ID = $_POST['postid'];
$votemecount = get_post_meta($post_ID, '_votemecount', true) != '' ? get_post_meta($post_ID, '_votemecount', true) : '0';
$votemecountNew = $votemecount + 1;
update_post_meta($post_ID, '_votemecount', $votemecountNew);
$results.=$votemecountNew;
// Return the String
die($results);
}
// creating Ajax call of ADD VOTE for WordPress
add_action( 'wp_ajax_nopriv_voteme_addvote', 'voteme_addvote' );
add_action( 'wp_ajax_voteme_addvote', 'voteme_addvote' );
//Add Vote Function
function voteme_downvote()
{
$results = '';
global $wpdb;
$post_ID = $_POST['postid'];
$votemecount = get_post_meta($post_ID, '_votemecount', true) != '' ? get_post_meta($post_ID, '_votemecount', true) : '0';
$votemecountNew = $votemecount - 1;
update_post_meta($post_ID, '_votemecount', $votemecountNew);
$results.= $votemecountNew;
// Return the String
die($results);
}
// creating Ajax call of DOWN VOTE for WordPress
add_action( 'wp_ajax_nopriv_voteme_downvote', 'voteme_downvote' );
add_action( 'wp_ajax_voteme_downvote', 'voteme_downvote' );
//Javascript and Ajax Calls
function votemeaddvote(postId)
{
jQuery.ajax({
type: 'POST',
url: votemeajax.ajaxurl,
data: {
action: 'voteme_addvote',
postid: postId
},
success:function(data, textStatus, XMLHttpRequest){
var vote_count_id = jQuery('.vote_count');
jQuery(vote_count_id).html('');
jQuery('.vote_count').append(data);
var thisr = jQuery('.voter button:first-child')
thisr.disable = true;
// add any additional logic here
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
}
function votemedownvote(postId)
{
jQuery.ajax({
type: 'POST',
url: votemeajax.ajaxurl,
data: {
action: 'voteme_downvote',
postid: postId
},
success:function(data, textStatus, XMLHttpRequest){
var vote_count_id = jQuery('.vote_count');
jQuery(vote_count_id).html('');
jQuery('.vote_count').append(data);
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
}
//HTML For Adding Votes
<div class="voter">
<a onclick="votemeaddvote(<?php echo $post_ID; ?>);">VoteUp</a>
<a onclick="votemedownvote(<?php echo $post_ID; ?>)">Vote Down</a>
</div>
Simplely using .one() instead of .on()
Try something like this,
$(".voter a:last-child").one( "click", function() {
console.log("click");
var data = $(this).data();
console.log(data);
votemedownvote(data.id);
});
So what you could do is change some of your code
Change the html to this:
<div class="voter">
<a data-id="<?php echo $post_ID; ?>">VoteUp</a>
<a data-id="<?php echo $post_ID; ?>">Vote Down</a>
</div>
And change your javascript like this since you are using jquery:
$(".voter a").on( "click", function() {
console.log("click");
var data = $(this).data();
console.log(data);
votemeupvote(data.id);
$(this).off();
});
So var data get has the post id in json form to be sent.
Using "this" you are able to target this specific element and turn its on click off. I removed your on embedded click events because usually you want to bootstrap those triggers so you can turn them off, which was your problem.
You can do this by using jquery .on and .off methods.
Edit: Forgot to add your function call. I added it. I will also add how your votedown can work:
$(".voter a:last-child").on( "click", function() {
console.log("click");
var data = $(this).data();
console.log(data);
votemedownvote(data.id);
$(this).off();
});
Edit 2: Oh and I forgot to mention that this is only good for the front end. So in the backend you need someway to track if the person voted or not, maybe a table with user id, post id and voted true or false. That way you can track it when the ajax call comes and have php update the database.
Fiddle

How to define an element with a a sql row id usng JSON encoded data

I'm using jQuery AJAX to process form data, the PHP side of it should delete two files on the server and then the SQL row in the database (for the id that was sent to it). The element containing the SQL row should then change color, move up, delete and the next SQL rows move into its place. The animation stuff occurs in the beforeSend and success functions of the ajax callback.
This script is not working, when user clicks button, the page url changes to that of the php script but the item and files do not get deleted either on the server or in the database. Nor does any of the animation occur.
This is my first time using jQuery ajax, I think there is a problem with how I define the element during the call back. Any help would be great:
js
$("document").ready(function(){
$(".delform").submit(function(){
data = $(this).serialize() + "&" + $.param(data);
if (confirm("Are you sure you want to delete this listing?")) {
$.ajax({
type: "POST",
dataType: "json",
url: "delete_list.php",
data: data,
beforeSend: function() {
$( "#" + data["idc"] ).animate({'backgroundColor':'#fb6c6c'},600);
},
success: function() {
$( "#" + data["idc"] ).slideUp(600,function() {
$( "#" + data["idc"] ).remove();
});
}
});
return false;
}
});
});
php
if (isset($_POST["id"]))
{
$idc = $_POST["id"];
if (isset($_POST["ad_link"]) && !empty($_POST["ad_link"]))
{
$ad_linkd=$_POST["ad_link"];
unlink($ad_linkd);
}
if (isset($_POST["listing_img"]) && !empty($_POST["listing_img"]))
{
$listing_imgd=$_POST["listing_img"];
unlink($listing_imgd);
}
try {
require('../dbcon2.php');
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "DELETE FROM listings WHERE id = $idc";
$conn->exec($sql);
}
catch (PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
echo json_encode($idc);
}
html
<div id="record-<?php echo $id; ?>">
*bunch of stuff*
<form method="post" class="delform">
<input name="id" type="hidden" id="id" value="<?php echo $id; ?>" />
<input name="ad_link" type="hidden" id="ad_link" value="<?php echo $ad_link; ?>" />
<input name="listing_img" type="hidden" id="listing_img" value="<?php echo $listing_img; ?>" />
<button type="submit">Delete</button>
</form>
</div>
You should fix your php code like this
try {
require('../dbcon2.php');
// It's better, if you will going to use MySQL DB, use the class designed to connect with it.
$conn = mysqli_connect("Servername", "usernameDB", "PasswordDB", "NameDB");
$sql = "DELETE FROM listings WHERE id = $idc";
mysqli_query($conn, $sql);
// you have to create a asociative array for a better control
$data = array("success" => true, "idc" => $idc);
// and you have to encode the data and also exit the code.
exit(json_encode($data));
} catch (Exception $e) {
// you have to create a asociative array for a better control
$data = array("success" => false, "sentence" => $sql, "error" => $e.getMessage());
// and you have to encode the data and also exit the code.
exit(json_encode($data));
}
Now in you JS code Ajax change to this.
$.ajax({
type: "POST",
dataType: "json",
url: "delete_list.php",
data: data,
beforeSend: function() {
$( "#" + data["idc"] ).animate({'backgroundColor':'#fb6c6c'},600);
},
success: function(response) {
// the variable response is the data returned from 'delete_list.php' the JSON
// now validate if the data returned run well
if (response.success) {
$( "#" + response.idc ).slideUp(600,function() {
$( "#" + response.idc ).remove();
});
} else {
console.log("An error has ocurred: sentence: " + response.sentence + "error: " + response.error);
}
},
// add a handler to error cases.
error: function() {
alert("An Error has ocurred contacting with the server. Sorry");
}
});

PHP Ajax returning HTML twice

I have a PHP/Ajax function that returns a list of countries with the given characters in a textbox. Ofcourse Ajax updates this list everytime the textbox gets edited.
Index.PHP calls all the other files, classes and HTML. But when the textbox gets updated, Ajax sends a POST variable to index.PHP because this is where the Search.PHP file with the class name SearchEngine gets called. But because he sends this to the index.php everything keeps getting reloaded and the HTML will be returned twice.
Index.php
<?php
require_once("cgi_bin/connection.php");
require_once("Database_Handler.Class.php");
require_once("HTML_Page.Class.php");
require_once("search.php");
$hostname_conn = "localhost";
$database_conn = "ajax";
$username_conn = "root";
$password_conn = "";
$db = new DatabaseHandler();
$conn = $db->openConnection($hostname_conn, $username_conn, $password_conn, $database_conn);
$IndexPage = new page();
echo $IndexPage->render();
$SearchEngine = new SearchEngine($conn);
?>
Please ignore the poor and unsecure database connection. I am currently transforming all my code to PDO and refining it but that is for later.
Search.PHP
<?php
class SearchEngine{
private $html;
public function __construct($conn){
$this->html = '<li class="result">
<h3>NameReplace</h3>
<a target="_blank" href="ULRReplace"></a>
</li>';
if (isset($_POST["query"])) {
$search_string = $_POST['query'];
}
//$search_string = mysql_real_escape_string($search_string);
if (strlen($search_string) >= 1 && $search_string !== ' ') {
$query = 'SELECT * FROM country WHERE name LIKE "%' . $search_string . '%"';
$result = $conn->prepare($query);
$result->execute();
$result_array = $result->fetchAll();
foreach ($result_array as $result) {
$display_name = preg_replace("/" . $search_string . "/i", "<b>" . $search_string . "</b>", $result['name']);
$display_url = 'sadf';
$output = str_replace('NameReplace', $display_name, $this->html);
$output = str_replace('ULRReplace', $display_url, $output);
echo($output);
}
}
}
}
?>
And as final the Javascript
$(document).ready(function() {
function search() {
var query_value = $('input#search').val();
$('b#search-string').html(query_value);
if(query_value !== ''){
$.ajax({
type: "POST",
url: "index.php", //Referring to index.php because this is where the class SearchEngine is called
data: { query: query_value },
cache: false,
success: function(html){
$("ul#results").html(html);
}
});
}
return false;
}
$("input#search").keyup(function() {
clearTimeout($.data(this, 'timer'));
var search_string = $(this).val();
if (search_string == '') {
$("ul#results").fadeOut();
$('h4#results-text').fadeOut();
}
else {
$("ul#results").fadeIn();
$('h4#results-text').fadeIn();
$(this).data('timer', setTimeout(search, 100));
};
});
});
note: HTML is being returned from the "page" class called inside Index.php
How do i not let everything get called twice?
Thank you,
EDIT: A new file was suggested where i direct the ajax url to AutoComplete.php
AutoComplete.PHP
Please explain what should be in the file and why. I am clueless.
Basically, just add a parameter to your Ajax call to tell the index.php its being called by Ajax, and then wrap an if-statement around the two lines that print out your actual index page:
if(!isset($_REQUEST['calledByAjax']))
{
$IndexPage = new page();
echo $IndexPage->render();
}
and in your Ajax call:
data: { query: query_value, calledByAjax: 'true' },
Or make another php page, like ajaxsearch.php that's the same as your index.php but lacking those two lines, and call that in your Ajax call.
First thing (this is a sample, not tested yet)
autocomplete.php
<?php
$search_string = $_POST['query'];
$query = 'SELECT * FROM country WHERE name LIKE "%' . $search_string . '%"';
$result = $conn->prepare($query);
$result->execute();
$result_array = $result->fetchAll();
foreach ($result_array as $result) {
$display_name = preg_replace("/" . $search_string . "/i", "<b>" . $search_string . "</b>", $result['name']);
$display_url = 'sadf';
$output = str_replace('NameReplace', $display_name, $this->html);
$output = str_replace('ULRReplace', $display_url, $output);
}
echo($output);
?>
autocomplete.js
function search() {
var query_value = $('input#search').val();
$('b#search-string').html(query_value);
if(query_value !== ''){
$.ajax({
type: "POST",
url: "autocomplete.php", //Here change the script for a separated file
data: { query: query_value },
cache: false,
success: function(html){
$("ul#results").html(html);
}
});
}
return false;
}
$("input#search").keyup(function() {
clearTimeout($.data(this, 'timer'));
var search_string = $(this).val();
if (search_string == '') {
$("ul#results").fadeOut();
$('h4#results-text').fadeOut();
} else {
$("ul#results").fadeIn();
$('h4#results-text').fadeIn();
search(); // call the function without setTimeout
}
});
});
Have luck :)

PHP function on JS Click?

I have a button that will copy a link to the clipboard but it has been shortened using bit.ly. At the minute I have it so that it creates the bit.ly link on page load which seems a bit messy so I just wondered how I can make it only do it when it copies to the clipboard?
var client = new ZeroClipboard( document.getElementById("copy-link"), {
moviePath: "ZeroClipboard.swf"
} );
client.on( "load", function(client) {
// alert( "movie is loaded" );
client.on( "complete", function(client, args) {
// `this` is the element that was clicked
$.gritter.add({
// (string | mandatory) the heading of the notification
title: 'Link Copied',
// (string | mandatory) the text inside the notification
text: 'Link has been copied to your clipboard'
});
$('[data-toggle="dropdown"]').parent().removeClass('open');
} );
} );
This is my PHP
<?php
$url = Router::url(null, true);
if ($this->UserAuth->isLogged()) {
$url .= '?shareref=' . $var['User']['id'] . '';
}
$shortlink = bitly_v3_shorten($url, 'bit.ly');
?>
JQuery Ajax will be your best option: http://api.jquery.com/jquery.ajax/ - Create it so that it runs the PHP when you click the button.
Javascript can be like this
// Java script
jQuery("copyButton").click(function() {
jQuery.ajax({
type : "post",
dataType : "json",
url : 'urlshortener.php',
success: function(response) {
if(response.type == "success") {
var shorturl = response.short;
}
}
});
});
PHP looks like this, maybe its good to be protect it by XHTTP referees etc..
// PHP
$url = Router::url(null, true);
if ($this->UserAuth->isLogged()) {
$url .= '?shareref=' . $var['User']['id'] . '';
}
$shortlink = bitly_v3_shorten($url, 'bit.ly');
$result['type']= "success";
$result['short'] = $url;
$result = json_encode($result);
echo $result;
die();

Categories

Resources