I have been delving into the world of Javascript and AJAX. I am super close, but for some reason I do not think I am hooking into wordpress ajax functions right. I have poured through the docs and this and think it is 99% there.
Is what this app does is there is a list of items. Each one with a + button. Clicking the button pops up a confirm box, and if confirmed grabs the needed data to pass to the php. The php adds the item into mysql with wpdb->insert. It also does some changes if you buy.
The js works all the way up to the call, grabbing the right values etc. Testing the php separately works as well if I hard code the values it is supposed to grab from POST. So I KNOW both pieces run, I just can't get the js to call the ajax api right. Can someone please take a look at this and let me know how to hook these together so the ajax call actually runs the php?
Here is the code.
<?php
add_action( 'admin_footer', 'addItemAJAX_javascript' );
function addItemAJAX_javascript() {
$adminAJAX = admin_url('admin-ajax.php');
?>
<script type="text/javascript" language="JavaScript">
$(function() {
$( "input[name=btnAddItem]" )
.button()
.click(function( event ) {
event.preventDefault();
var confirmAction = confirm('Are you sure you want to add this item to your character?');
if (confirmAction==true) {
// build data for AJAX call
var cID = $('#hdnCharID').val();
cID = cID*1;
var charMoney = $('#hdnCharMoney').val();
var thisValue = $(this).val();
var iID = $(this).prev('input[id="hdnItemID"]').val()
iID = iID*1;
//Add or Buy Item
if (thisValue != "+") {
var buy = 1;
}
else {
var buy = 0;
}
var ajaxurl = <?php echo json_encode($adminAJAX); ?>;
console.log('cID = ' + cID);
console.log('charMoney = ' + charMoney);
console.log('thisValue = ' + thisValue);
console.log('iID = ' + iID);
console.log('buy = ' + buy);
console.log('ajaxurl = ' + ajaxurl);
var data = {
action: 'addItemAJAX',
charID: cID,
itemID: iID,
buyItem: buy
};
console.log('data = ' + data);
console.log(data);
//WP ajax call
$.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
}
else {
console.log('add item aborted');
}
});
});
</script>
<?php
};
addItemAJAX_javascript();
// PHP SIDE OF AJAX - Handeling Request //// AJAX PROCESSING /////////////////////////////////
add_action('wp_ajax_addItemAJAX', 'addItemAJAX_callback');
function addItemAJAX_callback() {
global $wpdb;
$charID = intval($_POST['charID']);
$itemID = intval($_POST['itemID']);
$buyItem = intval($_POST['buyItem']);
// //get item details
$getItemDetailsSQL = "
Select
fyxt_wp_db_fatcow.fyxt_items.idfyxt_items,
fyxt_wp_db_fatcow.fyxt_items.fyxt_item_name,
fyxt_wp_db_fatcow.fyxt_items.fyxt_item_description,
fyxt_wp_db_fatcow.fyxt_items.fyxt_item_cost,
fyxt_wp_db_fatcow.fyxt_items.fyxt_item_weight
From
fyxt_wp_db_fatcow.fyxt_items
Where
fyxt_wp_db_fatcow.fyxt_items.idfyxt_items = $itemID";
$getItemDetailsResults = $wpdb->get_row($getItemDetailsSQL);
$iID = $getItemDetailsResults->idfyxt_items;
$iName = $getItemDetailsResults->fyxt_item_name;
$iDesc = $getItemDetailsResults->fyxt_item_description;
$iCost = $getItemDetailsResults->fyxt_item_cost;
$iWeight = $getItemDetailsResults->fyxt_item_weight;
$charItemTable = fyxt_char_items;
$wpdb->insert(
$charItemTable,
array (
idfyxt_item => $iID,
idfyxt_character => $charID,
item_name => $iName,
item_desc => $iDesc,
item_cost => $iCost,
item_weight => $iWeight,
item_quant => 1,
equip => 0,
carried => 1
)
);
$wpdb->print_error();
$newItemAdded = $wpdb->insert_id;
//remove cash if item is bought
if ($buyItem == 1 ) {
$curCharMoneySQL =
"Select
fyxt_wp_db_fatcow.fyxt_characters.char_money
From
fyxt_wp_db_fatcow.fyxt_characters
Where
fyxt_wp_db_fatcow.fyxt_characters.idfyxt_character = $charID";
$curCharCash = $wpdb->get_var($curCharMoneySQL);
$wpdb->print_error();
$newCash = $curCharCash - $iCost;
$changeCashSQL = "
UPDATE fyxt_characters
SET
char_money = $newCash
WHERE
idfyxt_character = $charID";
$changeCash = $wpdb->query($changeCashSQL);
$wpdb->print_error();
}
$debugArray = Array();
array_push($debugArray,$charID, $itemID, $buyItem, $getItemDetailsSQL, $getItemDetailsResults,$newItemAdded, $newCash);
echo $debugArray ;
die();
}
?>
I am pretty sure it is 1 (or 2) of 2 things. I am not sure if I am hooking these functions to wordpress right. Or there might be issues with nested functions I have for the jQuery button. I doubt it is number 2 though because it seems to work... I just get a 0 back from the server without any database activity. Here is what the log says.
cID = 112 ?charID=112:538
charMoney = 9990 ?charID=112:539
thisValue = + ?charID=112:540
iID = 664 ?charID=112:541
buy = 0 ?charID=112:542
ajaxurl = http://localhost/nnnnnnnn.com/wp-admin/admin-ajax.php ?charID=112:543
data = [object Object] ?charID=112:550
Object {action: "addItemAJAX", charID: 112, itemID: 664, buyItem: 0} ?charID=112:551
XHR finished loading: "http://localhost/nnnnnnnn.com/wp-admin/admin-ajax.php". jquery-1.9.1.js:8526
send jquery-1.9.1.js:8526
jQuery.extend.ajax jquery-1.9.1.js:7978
jQuery.(anonymous function) jquery-1.9.1.js:7614
(anonymous function) ?charID=112:554
jQuery.event.dispatch jquery-1.9.1.js:3074
elemData.handle
Thank you very much for all of the help and suggestions!
First of all you need to add hooks in proper way
// For the users that are not logged in
add_action( 'wp_ajax_nopriv_addItemAJAX', 'addItemAJAX_callback' );
// For the users that are logged in:
add_action( 'wp_ajax_addItemAJAX', 'addItemAJAX_callback' );
// ajax handler
function addItemAJAX_callback()
{
// code goes here
// since $debugArray is an array, so
die(json_encode($debugArray)); // last line
}
One hook will work when user is logged in and another will work when user is not logged in (for any user). If you are making ajax request for logged in users then, wp_ajax_nopriv_ hook is required.
Keep your js/ajax code in a separate file in yourthemefolder/js/myAjaxScript.js and also keep following code in your functions.php file
add_action('wp_enqueue_scripts', 'my_load_scripts');
function my_load_scripts()
{
// for pluggin, you may use "plugin_dir_url( __FILE__ )"
wp_enqueue_script( 'my_ajax-script', get_stylesheet_directory_uri() . '/js/myAjaxScript.js', array('jquery') );
// Following code will let you use "ajaxObj.ajax_url" to get the
// ajax url (admin-ajax.php) in your my_ajax_scriptjs file
wp_localize_script(
'my_ajax-script', 'ajaxObj', array( 'ajax_url' => admin_url( 'admin-ajax.php' )
));
}
In your my_ajax_script.js file, you may code like this
var data = {
action: 'addItemAJAX_callback',
// ...
};
$.getJson(ajaxObj.ajax_url, data, function(response) {
// response is an object
// ...
});
Alos remember, when using ajax from admin panel, you don't need to use wp_localize_script, since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php.
I won't go through your code as it seems a bit hard to replicate (see SSCCE for this matter). But I'll outline how to work with Ajax and WordPress (from How to Use AJAX in a WordPress Shortcode?):
1) Enqueue and localize the JavaScript file.
Instead of enqueueing, we could print directly in the head or footer, but it's not good practice. And the localization will pass PHP values to JS in a clean fashion.
I'm assuming you're working with a theme, otherwise change get_stylesheet_directory_uri() to plugins_url().
add_action( 'wp_enqueue_scripts', 'enqueue_so_19721859' );
function enqueue_so_19721859()
{
# jQuery will be loaded as a dependency
## DO NOT use other version than the one bundled with WP
### Things will BREAK if you do so
wp_enqueue_script(
'my-handler',
get_stylesheet_directory_uri() . '/js/ajax.js',
array( 'jquery' )
);
# Here we send PHP values to JS
wp_localize_script(
'my-handler',
'my_handler',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ajaxnonce' => wp_create_nonce( 'my_ajax_validation' ) // <--- Security!
)
);
}
2) Ajax for logged and non-logged users
You gotta add a public Ajax callback too with no_priv_:
add_action('wp_ajax_addItemAJAX', 'addItemAJAX_callback');
add_action('wp_ajax_no_priv_addItemAJAX', 'addItemAJAX_callback');
3) Ajax Callback and Response
The Ajax callback has security checks and uses wp_send_json_* to handle the response:
function addItemAJAX_callback()
{
check_ajax_referer( 'my_ajax_validation', 'security' );
$my_thing = something();
if( !$my_thing )
wp_send_json_error( array( 'error' => __( 'Could not retrieve a post.' ) ) );
else
wp_send_json_success( $my_thing );
}
4) Finally, the script
It's essential to wrap all jQuery with noConflict mode.
You can pass whatever info you need through the localized object my_handler. We check 3 things from the response:
total failure: couldn't reach the callback or didn't pass security
partial failure: the callback was reached but returned json_error
success: proceed with your thing
jQuery( document ).ready( function( $ ) {
var data = {
action: 'addItemAJAX_callback',
security: my_handler.ajaxnonce
};
$( '#my-submit' ).click( function(e) {
e.preventDefault();
$.post(
my_handler.ajaxurl,
data,
function( response ) {
// ERROR HANDLING
if( !response.success ) {
// No data came back, maybe a security error
if( !response.data )
$( '#my-answer' ).html( 'AJAX ERROR: no response' );
else
$( '#my-answer' ).html( response.data.error );
}
else
$( '#my-answer' ).html( response.data );
}
);
});
});
Related
I'm trying to make an AJAX-Request within a Wordpress Plugin in frontend, after clicking a button. -> Actually it is a Widget. So I implemented the frontend via extending de WP_Widget Class. I don't know if this is worth knowing.
I always get a 400 bad Request and '0'.
I dont wanted to use JQuery, but i also tried and there I get a 500 Internal Server Error.
Now im really confused.
I really searched up and down the internet and every question in this forum (I know there are many similar questions - but nothing worked to me)
I'm so thankful if anyone can help me.
Main Plugin File:
function scriptloader(){
$scripturl = plugin_dir_url(__FILE__) . 'includes/public/script.js';
wp_enqueue_script('script-js', $scripturl, array( 'jquery' ));
$styleurl = plugin_dir_url(__FILE__) . 'includes/public/css/main.css';
wp_enqueue_style('script-js', $styleurl, [], null, false);
$js_variable = [
'ajax_url' => admin_url('admin-ajax.php'),
'ajax_nonce' => wp_create_nonce( 'ajax_public' ),
'mystring' => "LOL!"
];
wp_localize_script('script-js', 'phpwindowobject', $js_variable);
};
add_action( 'wp_enqueue_scripts', 'scriptloader');
function k_ajax_requester(){
$mystring = "SERVER ALIVE";
echo $mystring;
wp_die();
};
add_action('wp_ajax_k_ajax', 'k_ajax_requester');
add_action('wp_ajax_nopriv_k_ajax', 'k_ajax_requester');
There is a button in frontend.php which executes ajaxrequest() by clicking in
my script.js :
function ajaxrequest(){
var url = phpwindowobject.ajax_url;
var data = {action: "k_ajax",mystring: "K_AJAX"}
console.log("Data to send:")
console.log(data)
var xhrobj = new XMLHttpRequest;
xhrobj.open('POST', url, true);
xhrobj.setRequestHeader('Content-Type', 'text/html; charset=utf-8');
xhrobj.onreadystatechange = function()
{
if (this.readyState == 4)
{
if (this.status == 200)
{
if (this.responseText != null)
{
console.log('Request completed');
}
else console.log("Ajax error: No data received")
}
else console.log("Ajax error: " + xhrobj.statusText );
}
};
xhrobj.onload = function(){
var answer = (xhrobj.response);
console.log(answer);
}
xhrobj.send(data);
};
What do you think?
Thank you.
How to redirect previous page after redirect to previous page.
After form submission i am redirect form to thank you page but after sometimes i want redirect previous page.
Below is the code i am using
<script>
document.addEventListener( 'wpcf7mailsent', function( event ) {
//location = 'abc.com1/thank-you/';
if ( '17615' == event.detail.contactFormId ) {
}
else if( '19110' == event.detail.contactFormId ){
location = 'abc.com1/thank-you-broucher/';
}
else {
location = 'abc.com1/thank-you/';
}
}, false );
</script>
after location redirect i want again redirect to my first original page.
Anyone have idea then let me know
use history.back
window.history.back();
One of the problem with using js built in history.go(-1); is that the behaviour is based on your browser and not on your website structure.
If someone decide to access a website straight from a url or a bookmark, upon using history.go(-1); on landing, he would be redirected outside the website environment.
As you're using Wordpress
We can easily build a go back url function based on the current user url.
Anything that can be offloaded to server should be. Instead of using js here is a php alternative. The main advantage here is quartering the user to your website. Here is our get_backward_url() function.
add_action( 'init', 'get_backward_url' );
function get_backward_url() {
$scheme = $_SERVER['REQUEST_SCHEME'];
$request = $_SERVER['REQUEST_URI'];
$host = $_SERVER['HTTP_HOST'];
if ( str_contains( $request, '?' ) ) { //... case handling, urls with variables
$cleaner = substr( $request, 0, strpos( $request, '?' ) );
$request = $cleaner;
};
if ( str_ends_with( $request, '/' ) ) //... case handling, urls with/without end-slash
$worker = explode( '/', substr( $request, 1, -1 ) );
else
$worker = explode( '/', substr( $request, 1 ) );
array_pop( $worker );
if ( str_contains( $host, 'localhost' ) ) //... case handling, urls on local hosting
$href = esc_url( $scheme . '://' . $host . '/' . implode( '/', $worker ) . '/' );
else
$href = esc_url( $scheme . '://' . $host . implode( '/', $worker ) . '/' );
if ( ! is_home() && ! is_front_page() ) //... case handling, home or front page
return $href;
};
Then, anytime we need to use it in our template we can simply output it on the front end...
← go back
Happy coding!
You can do it several ways:
// Javascript directly in the href
Go Back
another way would be:
// onclick Method
Go back
Or as mentioned above my post
// windows method
javascript:window.history.back();
and for last you can create a function
<script>
function goBack() {
history.go(-1);
}
</script>
<button onclick="goBack()">Go Back</button>
If you want to have it done automatically you just need to use it in a function and add a setTimeout:
function goBackTimed() {
setTimeout(() => {
window.history.go(-1);
}, 3000);
}
Since your using WordPress, I would recommend doing this using the functions.php file and add a filter with a function for the redirect, but since you requested how to do this with javascript, you need to inspect your thank you page to grab the page-id-[ID-NUMBER] class it generates on the body tag your script above would need a condition to detect if the class is present on the body assuming this script is loaded on your entire site:
<script>
document.addEventListener( 'wpcf7mailsent', function( event ) {
//location = 'abc.com1/thank-you/';
if ( '17615' == event.detail.contactFormId ) {
}
else if( '19110' == event.detail.contactFormId ){
location = 'abc.com1/thank-you-broucher/';
}
else {
location = 'abc.com1/thank-you/';
}
}, false );
if (document.body.classList.contains('page-id-12345')) {
function goBack() {
history.go(-1);
}
window.setInterval(goBack, 3000);
}
</script>
I prefer history.go(); since you can go back even more than 1 page back for example history.go(-2); would go back 2 pages instead of one, this sometimes can be handy in certain cases.
Have a function that makes a change to taxonomy term via AJAX. This works great, except the content remains unchanged on window.location.reload(true) even though the change has been made. See the code and GIF below to understand.
This is an example that adds the button and reloads page on click
if ( 'publish' === $post->post_status && $post->post_type === 'campaigns' ) {
$text = (in_category( 'live') ? 'Activate' : 'Activate');
echo '<li>' . $text . '</li>';
}
So, is there another way that I can reload the page onClick that may help? Also, the post modified date is not updating, yet changes have been made to the post.
Thanks in advance for your help
EDIT -
I have already tried
location.href = location.href; and
document.location.reload();
ADDITIONAL INFO -
Function
add_action('wp_ajax_toggle_live', function(){
// Check ID is specified
if ( empty($_REQUEST['post']) ) {
die( __('No post ID specified.') );
}
// Load post
$post_id = (int) $_REQUEST['post'];
$post = get_post($post_id);
if (!$post) {
die( __('You attempted to edit an item that doesn’t exist. Perhaps it was deleted?') );
}
// Check permissions
$post_type_object = get_post_type_object($post->post_type);
if ( !current_user_can($post_type_object->cap->edit_post, $post_id) ) {
die( __('You are not allowed to edit this item.') );
}
// Load current categories
$terms = wp_get_post_terms($post_id, 'campaign_action', array('fields' => 'ids'));
// Add/remove Starred category
$live = get_term_by( 'live', 'campaign_action' );
$index = array_search($live, $terms);
if ($_REQUEST['value']) {
if ($index === false) {
$terms[] = $live;
}
} else {
if ($index !== false) {
unset($terms[$index]);
}
}
wp_set_object_terms( $post_id, 'live', 'campaign_action' );
die('1');
});
JS
function toggleLive(caller, post_id)
{
var $ = jQuery;
var $caller = $(caller);
var waitText = ". . .";
var liveText = ". . .";
var deactivateText = ". . .";
// Check there's no request in progress
if ($caller.text() == waitText) {
return false;
}
// Get the new value to set to
var value = ($caller.text() == liveText ? 1 : 0);
// Change the text to indicate waiting, without changing the width of the button
$caller.width($caller.width()).text(waitText);
// Ajax request
var data = {
action: "toggle_live",
post: post_id,
value: value
};
jQuery.post("<?php bloginfo( 'wpurl' ); ?>/wp-admin/admin-ajax.php", data, function(response)
{
if (response == "1") {
// Success
if (value) {
$caller.text(deactivateText);
} else {
$caller.text(liveText);
}
} else {
// Error
alert("Error: " + response);
// Reset the text
if (value) {
$caller.text(deactivateText);
} else {
$caller.text(liveText);
}
}
// Reset the width
$caller.width("auto");
});
// Prevent the link click happening
return false;
}
IT WORKS RIGHT ON PAGE THAT ISN'T SINGULAR
Is toggleLive the function that makes the AJAX request? You are calling reload immediately on click before changes are reflected on the backend. If you are using Jquery include your reload code in the complete callback function that indicates completion of your AJAX request.
Try using Live Query plug-in in jquery instead of live .
I was able to achieve this by setting return trueOrFalse(bool); in the JS and adding the permalink for the page into <a href=""> within the function.
I believe #cdoshi was correct in their answer, yet I was unable to achieve this. I am sure that a little further exploration would make this possible, yet my fix achieved what I wanted with little change to my code.
TL;DR: Not Dupe - Code first, scroll to bottom for problem.
Here is the link to the demo that I currently have.
In functions.php I localize my script first:
function ajaxurl(){
wp_enqueue_script( 'product-selector', get_template_directory_uri() . '/js/ajax.js', array( 'jquery' ) );
wp_localize_script( 'product-selector', 'MyAjax', array(
// URL to wp-admin/admin-ajax.php to process the request
'ajaxurl' => admin_url( 'admin-ajax.php' ),
// generate a nonce with a unique ID "myajax-post-comment-nonce"
// so that you can check it later when an AJAX request is sent
//'postCommentNonce' => wp_create_nonce( 'myajax-post-comment-nonce' ),
)
);
}
add_action('wp_head', 'ajaxurl');
And then for the script my ajax calls on I have:
function ajax_callback() {
global $wpdb; // this is how you get access to the database
// Declare our variable.
$cat = $_POST['cat'];
// Q the DB
$query = $wpdb->get_col( $wpdb->prepare(
"
SELECT meta_value
FROM $wpdb->postmeta
WHERE post_category=%s
", $cat
) );
header('Content-Type: application/json');
wp_send_json( json_encode( $query ) );
}
add_action( 'wp_ajax_nopriv_ajax-callback', 'ajax_callback' );
And finally for ajax.js I have:
$(document).ready(function(){
var back_end_script_url = MyAjax.ajaxurl;
$(function() {
var category_callback = function(data) {
console.log(data);
var adhesion_select = $('#adhesion');
var substrate_select = $('#substrate');
substrate_select.find('option').remove();
adhesion_select.find('option').remove();
for (var k in data) {
var option = $('<option />').val(k).html(data[k]);
adhesion_select.append(option);
}
};
var adhesion_callback = function(data) {
console.log(data);
var substrate_select = $('#substrate');
substrate_select.find('option').remove();
for (var k in data) {
var option = $('<option />').val(k).html(data[k]);
substrate_select.append(option);
}
};
var category_change = function() {
console.log('Category Changed');
var category = $(this).find(":selected").val();
var params = {
action: 'ajax-callback',
cat: category
};
console.log(params);
$.post(back_end_script_url, params, category_callback);
};
var adhesion_change = function() {
console.log('Adhesion Changed');
var adhesion = $(this).find(":selected").val();
var category = $('#cat').find(":selected").val();
var params = {
action: 'ajax-callback',
cat: category,
adhesion: adhesion
};
console.log(params);
$.post(back_end_script_url, params, adhesion_callback);
};
$('#cat').on('change', category_change);
$('#adhesion').on('change', adhesion_change);
});
});
So my problem is, if you look at the demo, the ajax only returns the number 0, not the data from the db.
I have read every related question on this problem on stack and wordpress exchanges, and tried all of them out, and my result is always the same.
I hired out the JS code, but the guy swears its on my end. I'm not sure if that's true or not, because I can't find any problem in my code.
Thanks for your help, Stack!
It seems that you are missing the "action" attribute in the params you are sending on the ajax call.
Your params object should be:
var params = {
action: "ajax-call",
cat: category
};
Hope this helps,
Regards,
Marcelo
I have a problem with my Yii Form-Submission via Ajax:
Everything worked fine on my local machine but on the Webserver I always get the error Alert...
The Ajax Error is thrown every time the function is called...
although the data is properly POST'ED and the function in the URL did what it should..
So basically everything works but the Ajax Error is thrown every time
SO here is my code:
function merge()
{
var productA = $('#Product_selected_product').val();
var productB = $('#product_dd').val();
<?php echo CHtml::ajax(
array(
'url'=>CController::createUrl('product/companyItems'),
'data'=>array('productA' => 'js:$(\'#Product_selected_product\').val()', 'productB' => 'js:$(\'#product_dd\').val()','checker' => 'erwin'),
'type'=>'post',
'dataType'=>'json',
'error'=>"function() { alert('ERROR'); }",
'success'=> "function(){window.location.href = '../product/'+productB+''}"
)
);
?>
return false;
}
The companyItems Action searches for entrys in a table with the ID of ProductA and replaces it with the ID of ProductB.
Controller Action : CompanyItems:
public function actionCompanyItems(){
if(isset($_POST['checker'])) {
$productA = $_POST['productA'];
$productB = $_POST['productB'];
$commandMerge = Yii::app()->db
->createCommand("UPDATE ebay SET product_id = :productB WHERE product_id=:productA")
->bindValues(array(':productB' => $productB ,':productA' => $productA))
->execute();
$commandDelete = Yii::app()->db
->createCommand("UPDATE product SET is_deleted = '1' WHERE id = :productA")
->bindValues(array(':productA' => $productA))
->execute();
}
I hope someone can help me....
Dave