Call PHP function inside TinyMCE modal window on the WordPress backend - javascript

I am using a static .js file that is registered for a TinyMCE plugin. You click on the new button and it opens up the modal window, with a form in it, that I use to generate a Shortcode. The problem is that I need some of my form fields to be populated from PHP functions. I've been looking at articles on this for hours and haven't found a workable solution. Right now my php function is a Shortcode, so I need to adapt it to be a regular old function. But the big challenge is figuring out how to arrange this so that the .js file can take the function in the form. Here's the basic stuff. First, some chunks of the .js file:
(function(){
// creates the plugin
tinymce.create('tinymce.plugins.myshortcode', {
// creates control instances based on the control's id.
createControl : function(id, controlManager) {
if (id == 'myshortcode') {
// creates the button
var button = controlManager.createButton('myshortcode', {
title : 'My Shortcode', // title of the button
image : '../wp-content/plugins/my-shortcode/js/images/myshortcode.png', // path to the button's image
onclick : function() {
// triggers the thickbox
var width = jQuery(window).width(), H = jQuery(window).height(), W = ( 720 < width ) ? 720 : width;
W = W - 80;
H = H - 80;
tb_show( 'My Shortcode', '#TB_inline?width=' + W + '&height=' + H + '&inlineId=myshortcode-form' );
}
});
return button;
}
return null;
}
});
// registers the plugin.
tinymce.PluginManager.add('myshortcode', tinymce.plugins.myshortcode);
jQuery(function(){
var form = jQuery(' \
\
The HTML Web Form all goes in here.\
\
');
var table = form.find('table');
form.appendTo('body').hide();
form.find('#myshortcode-submit').click(function(){
var options = {
'att1' : '',
'att2' : '',
'att3' : '',
'att4' : '',
};
var shortcode = '[myshortcode';
for( var index in options) {
var value = table.find('#myshortcode-' + index).val();
if ( value !== options[index] && value != null )
shortcode += ' ' + index + '="' + value + '"';
}
shortcode += '] content here. [/myshortcode]';
tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode);
tb_remove();
});
});
})()
But in that spot where it says, "The HTML Web Form goes in here," I need to have a couple of fields that are generated based on PHP functions. I've only written one of the two so far, and as I said, it's currently written as a Shortcode, so I need to change it (not sure the best way to do that given the other big questions here). But here it is:
add_shortcode('rolescapsdropdown', 'sc_rolescapsdropdown');
function sc_rolescapsdropdown($attr) {
global $wp_roles;
$all_roles = $wp_roles->roles;
$editable_roles = apply_filters('editable_roles', $all_roles);
$user = new WP_User( 1 );
$capslist = $user->allcaps;
$dropdown = '<select multiple>';
foreach($editable_roles as $role=>$theroles){
$dropdown .= '<option value="'.$role.'">'.$role.'</option>';
}
foreach($capslist as $cap=>$caps){
if($cap !== 'administrator' && $cap !== 'level_0' && $cap !== 'level_1' && $cap !== 'level_2' && $cap !== 'level_3' && $cap !== 'level_4' && $cap !== 'level_5' && $cap !== 'level_6' && $cap !== 'level_7' && $cap !== 'level_8' && $cap !== 'level_9' && $cap !== 'level_10'){
$dropdown .= '<option value="'.$cap.'">'.$cap.'</option>';
}
}
$dropdown .= '</select>';
return $dropdown;
}
I'm hoping to avoid having to learn Ajax here. But I tried making the .js file a .php file and just wrapping the JavaScript in <script> tags, but then all the TinyMCE buttons disappeared, so apparently it won't let me use a .php file to register the plugin.
Update 1
One idea I have is to try to move the web form to a php file, and just have the .js file that registers the TMCE plugin call it up, but I wouldn't know if that would work, nor how to get the .js file to recognize the existence of the form in an external php file.
Update 2
Based on ScottA's help, here's how I'm trying to work this:
I've added this to my static .js file that has the form:
$.get( "ajax/test.php", function( data ) {
var options = data.options;
for(row in options) {
$("#option-list").append("<option value=" + options[row].value + ">" + options[row].name + "</option>");
// debug for unexpected results
console.log(data.options);
}
}, "json" );
I've created this test.php file in a subdirectory called "ajax":
function rolescapsdropdown() {
global $wp_roles;
$all_roles = $wp_roles->roles;
$editable_roles = apply_filters('editable_roles', $all_roles);
$user = new WP_User( 1 );
$capslist = $user->allcaps;
$all_options = $editable_roles . $capslist;
$all_options[]['value'] = $value;
$all_options[]['name'] = $name;
echo json_encode( array('options' => $all_options) );
}
And I added this HTML to the form in the static .js file:
<select id="option-list"></select>
What I'm getting is a blank modal window. None of the HTML is showing up at all when I include the $.get function.
Update 3
Still getting a blank modal window. I converted it back to a shortcode to see what it outputs. This...
add_shortcode('rolesdropdown', 'sc_rolesdropdown');
function sc_rolesdropdown() {
global $wp_roles;
$all_roles = $wp_roles->roles;
$editable_roles = apply_filters('editable_roles', $all_roles);
$user = new WP_User( 1 );
$capslist = $user->allcaps;
foreach ($editable_roles as $role=>$theroles){
$all_options = $role;
}
foreach ($capslist as $cap=>$caps){
$all_options .= $cap;
}
echo json_encode( array('options' => $all_options) );
}
outputs this on the page:
{"options":"trollswitch_themesedit_themesactivate_pluginsedit_pluginsedit_usersedit_filesmanage_optionsmoderate_commentsmanage_categoriesmanage_linksupload_filesimportunfiltered_htmledit_postsedit_others_postsedit_published_postspublish_postsedit_pagesreadlevel_10level_9level_8level_7level_6level_5level_4level_3level_2level_1level_0edit_others_pagesedit_published_pagespublish_pagesdelete_pagesdelete_others_pagesdelete_published_pagesdelete_postsdelete_others_postsdelete_published_postsdelete_private_postsedit_private_postsread_private_postsdelete_private_pagesedit_private_pagesread_private_pagesdelete_userscreate_usersunfiltered_uploadedit_dashboardupdate_pluginsdelete_pluginsinstall_pluginsupdate_themesinstall_themesupdate_corelist_usersremove_usersadd_userspromote_usersedit_theme_optionsdelete_themesexportbe_trollexec_phpedit_others_phpadministrator"}
But when in the modal window on the backend, the window is just blank when the $.get is calling the file with that function in it.

You say you don't want to learn AJAX, but you should not be afraid. jQuery's $.get() function makes it very easy to get and process data from an external file. If your PHP functions reside in a separate file, you could make the $.get() call to that file and populate the form in the same jQuery function.
Your jQuery could be as simple as:
$.get( "ajax/test.php", function( data ) {
$( ".result" ).html( data );
});
Say your file, test.php returned a JSON array, or even plain text based off parameters you pass in the URL (ie: "ajax/test.php?userid=1&get=name") you could use jQuery to populate the form.
Your jQuery:
$.get( "ajax/test.php?userid=1&get=name", function( data ) {
$( "#myform input.firstname").val( data.firstname );
$( "#myform input.lastname").val( data.lastname );
}, "json" );
test.php could look like:
<?php
// your function to retrieve the data from the database, a file, etc.
echo json_encode(array(
"firstname" => "Burt",
"lastname" => "Bartigan"
));
?>
You say you don't want to use AJAX, but that's the easiest way you will solve this problem.
More information on $.get();
More information on PHP json functions
-- EDIT --
To answer your comment below:
your php:
$all_options[]['value'] = $value;
$all_options[]['name'] = $name;
// or however you can best get it
// from the database into an array
echo json_encode( array('options' => $all_optoins) );
your jQuery:
$.get( "ajax/test.php", function( data ) {
var options = data.options;
for(row in options) {
// append will place this inside the <select> HTML element
$("#option-list").append("<option value=" + options[row].value + ">" + options[row].name + "</option>");
// debug for unexpected results?
console.log(data.options);
}
}, "json" );
your HTML:
<select id="option-list"></select>

I just had the same issue and this is how I solved it. First, we need to pass some PHP values to the JavaScript file. As wp_localize_script cannot be used (we're not enqueueing the script), we'll print it directly in admin_head:
foreach( array('post.php','post-new.php') as $hook )
add_action( "admin_head-$hook", 'admin_head_js_vars' );
/**
* Localize Script
*/
function admin_head_js_vars()
{
$img = plugins_url( '/js/images/myshortcode.png', __FILE__ );
?>
<!-- TinyMCE Shortcode Plugin -->
<script type='text/javascript'>
var b5f_mce_config = {
'tb_title': '<?php _e('Roles Shortcode'); ?>',
'button_img': '<?php echo $img; ?>',
'ajax_url': '<?php echo admin_url( 'admin-ajax.php')?>',
'ajax_nonce': '<?php echo wp_create_nonce( '_nonce_tinymce_shortcode' ); ?>'
};
</script>
<!-- TinyMCE Shortcode Plugin -->
<?php
}
With this, the button creation looks like:
title: b5f_mce_config.tb_title, // title of the button
image: b5f_mce_config.button_img, // path to the button's image
Now, we'll add an Ajax action:
add_action( 'wp_ajax_b5f_tinymce_shortcode', 'b5f_tinymce_shortcode' );
function b5f_tinymce_shortcode()
{
$do_check = check_ajax_referer( '_nonce_tinymce_shortcode', 'security', false );
if( !$do_check )
echo 'error';
else
include_once 'my-form.php';
exit();
}
Back to JS (noting that my example is based on this):
jQuery(function($)
{
/* Used in Ajax and Callback */
var table;
/**
* Get the ThickBox contents wit Ajax
*/
var data_alt = {
action: 'b5f_tinymce_shortcode',
security: b5f_mce_config.ajax_nonce
};
$.post(
b5f_mce_config.ajax_url,
data_alt,
function( response )
{
if( 'error' == response )
{
$('<div id="mygallery-form"><h1 style="color:#c00;padding:100px 0;width:100%;text-align:center">Ajax error</h1></div>')
.appendTo('body').hide();
}
else
{
form = $(response);
table = form.find('table');
form.appendTo('body').hide();
form.find('#mygallery-submit').click(b5f_submit_gallery);
}
}
);
/**
* Callback for submit click
*/
function b5f_submit_gallery()
{
// Options defined in admin_head
var shortcode = '[my_shortcode]';
// inserts the shortcode into the active editor
tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode);
// closes Thickbox
tb_remove();
}
});
Finally, the file myform.php, included with Ajax, can contain any WordPress functions:
<?php
/**
* Used by Ajax
*/
?>
<div id="mygallery-form">
<?php echo site_url(); ?>
</div>

Related

Wordpress - JS to select only the current user i clicked to follow

I'm using "User Follow System" plugin, and i would like to know how to make this js select only one user of the current user i clicked to follow.
I am showing a list of followers and following using get_users in foreach loop.
The problem I am facing is when i click on the follow link for one user, the loading images for all users show up and all the follow links get toggled. $(‘.follow-links a’).toggle();
When i asked the plugin owner he said: Sounds like you may just need to adjust the selector used in the JS to target only the one you clicked on. This was originally built with only one user’s links displayed on the page.
But sorry, I failed to figure it out!
jQuery(document).ready(function($) {
/*******************************
follow / unfollow a user
*******************************/
$( '.follow-links a' ).on('click', function(e) {
e.preventDefault();
var $this = $(this);
if( pwuf_vars.logged_in != 'undefined' && pwuf_vars.logged_in != 'true' ) {
alert( pwuf_vars.login_required );
return;
}
var data = {
action: $this.hasClass('follow') ? 'follow' : 'unfollow',
user_id: $this.data('user-id'),
follow_id: $this.data('follow-id'),
nonce: pwuf_vars.nonce
};
$('img.pwuf-ajax').show();
$.post( pwuf_vars.ajaxurl, data, function(response) {
if( response == 'success' ) {
$('.follow-links a').toggle();
} else {
alert( pwuf_vars.processing_error );
}
$('img.pwuf-ajax').hide();
} );
});
});
display-function.php
<?php
/**
* Retrieves the follow / unfollow links
*
* #access public
* #since 1.0
* #param int $user_id - the ID of the user to display follow / unfollow links for
* #return string
*/
function pwuf_get_follow_unfollow_links( $follow_id = null ) {
global $user_ID;
if( empty( $follow_id ) )
return;
if( ! is_user_logged_in() )
return;
if ( $follow_id == $user_ID )
return;
ob_start(); ?>
<div class="follow-links">
<?php if ( pwuf_is_following( $user_ID, $follow_id ) ) { ?>
<span><span>Following</span>
Follow
<?php } else { ?>
Follow
<span><span>Following</span>
<?php } ?>
<img src="<?php echo PWUF_FOLLOW_URL; ?>/images/loading.svg" class="pwuf-ajax" style="display:none;"/>
</div>
<?php
return ob_get_clean();
}
The line $('.follow-links a').toggle() is toggling every follow link because the query selector doesn't specify a single child. The call of the toggle method is applied to every child found.
Just replace $('.follow-links a').toggle() with $this.toggle().

Why ajax request isn't sending all the data?

I'm working in a ecommerce with wordpresss and woocommerce, im adding to the shop page and category pages buttons that display the sizes for each product. with this code inside the theme function:
function woocommerce_variable_add_to_carts() {
global $product, $post;
$variations = $product->get_available_variations();
$product_sku = $product->get_sku();
$out = '<ul class="iconic-was-swatches iconic-was-swatches--loop iconic-was-swatches--text-swatch iconic-was-swatches--square">';
foreach ($variations as $key => $value) {
if (!empty($value['attributes'])) {
foreach ($value['attributes'] as $attr_key => $attr_value) {
$out .= '<li><a id="'.esc_attr($post->ID).'" data-quantity="1" data-product_id="'.esc_attr($post->ID).'" data-product_sku="'.$product_sku.'" class="iconic-was-swatch iconic-was-swatch--follow iconic-was-swatch--text-swatch add_to_cart_button">';
$out .= $attr_value . '</a></li>';
}
}
}
$out .= '</ul>';
echo $out;
}
add_action('woocommerce_before_shop_loop_item_title', 'woocommerce_variable_add_to_carts');
The idea is that when the users click in one of those sizes buttons the product is added to the cart directly in that page (shop page, category page). I made a custom endpoint to solve that from the answer provided here. I call the ajax function in the js file that Contains this:
$('.add_to_cart_button').on('click',function(){
jQuery.ajax({
url: WC_VARIATION_ADD_TO_CART.ajax_url,
type: "POST",
data: {
action : "customAdd_to_cart",
product_id : "697",
variation_id : "707",
quantity : 1,
variation : {
size : "s",
color: "pink"
}
},
success: function(){
alert('Ajax Success ');
}
});
});
(i'm using a specific product_id and variation_id for testing) then i add the callback function in the themes function page to add the products to the cart :
function customAddToCart() {
ob_start();
try {
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $data['product_id'] ) );
$quantity = empty( $data['quantity'] ) ? 1 : wc_stock_amount( $data['quantity'] );
$variation_id = isset( $data['variation_id'] ) ? absint( $data['variation_id'] ) : '';
$variations = $variation_id ? (array) get_variation_data_from_variation_id( $variation_id ) : null;
$product_status = get_post_status( $product_id );
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data );
if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) && 'publish' === $product_status ) {
do_action( 'woocommerce_ajax_added_to_cart', $product_id );
$res = getCartFragments();
} else {
$res = array(
'error' => true
);
}
return $res;
} catch (Exception $e) {
return new WP_Error('add_to_cart_error', $e->getMessage(), array('status' => 500));
}
}
add_action( 'wp_ajax_nopriv_woocommerce_add_variation_to_cart', 'customAddToCart' );
all this seems to work fine because doesn't give any error in console but the problems is that the variation Size in not added with the product that is selected just add the product. I dont know why this is happening, i even add an alert in the ajax success function
alert('Ajax Success ');
and that alert is displayed but the data it seems is not been sending like it should.
i want to know what i'm missing in any of this codes or it could be the js file and his location or i need to send another value in the a> builded in the first function above. i have try a lot things but the behavior still the same.
A quick scan over your code and I've noticed that the action you are calling with ajax is not correct. It should be woocommerce_add_variation_to_cart not customAdd_to_cart. Also it is common practice to use wp_send_json (or the more specific wp_send_json_success and wp_send_json_error functions) at the end of your ajax callback function so that you get a readable and sensible response in jQuery. Check out the following link if you have not used it before:
https://codex.wordpress.org/Function_Reference/wp_send_json
Hope this helps.

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.

Save advert click to database using PHP, then open link

I am creating a WordPress widget that shows and advert. When the advert is clicked I want to record the clicks with some detail.
The database table is already created and entries can be saved correctly using the function f1_add_advert_click($advert_id) in save-advert-click.php, which resides in the same directory as the Widget's PHP that I want to call it from (the plugin's root directory).
Requirements:
link will be on a piece of text, just a plain a href
a visitor should see the target link when he hovers his cursor over the link, not appended by a parameter for the next page
no 'middle' page that registers the click then redirects onto the target page. Just straight from the origin to the target.
secure: the advert ID is passed on to the f1_add_advert_click function and then inserted into the database. I would like to be sure that it's the correct ID (not something a visitor could change).
there can be multiple instances of this Widget on a page
I have seen and tried a lot of examples on Stackoverflow, but either I don't get it or the situation there is different from mine. Would gladly appreciate a well commented code example that works in my situation. Please be aware that I am not a seasoned programmer, especially 'green' when it comes to JavaScript and jQuery.
From what I have read on the web I think I should be using AJAX to first register the click, then send the browser to the target page. Not sure if I have to use onclick or not, based on the bottom answer of this post.
Have put in about four hours so far on this part. Now asking for help. Not much code to show, because I deleted everything that didn't work.
This is what I have currently got within the widget function of the plugin (left out the regular php showing title and so on):
<script type="text/javascript">
function myAjax() {
$.ajax({
type: "POST",
url: './wp-content/plugins/facilitaire-advert-widget/save-advert-click.php',
data:{action:'call_this'},
success:function(html) {
alert(html);
}
});
}
</script>
Followed by the link and the click action
<p>Link of Advert
Then these are my contents for save-advert-click.php
// check for action signal
if($_POST['action'] == 'call_this') {
f1_add_advert_click ();
}
/**
* Records a click event in the database
*/
function f1_add_advert_click ()
{
$advert_id = random_int(1,300); // change to $clicked_advert_id later
$user_ip = get_user_ip();
global $wpdb;
$table_name = $wpdb->prefix . 'f1_advert_clicks';
$wpdb->insert( $table_name, array(
'advert_id'=> $advert_id,
'user_agent'=> $_SERVER['HTTP_USER_AGENT'],
'ip_address'=> $user_ip
),
array(
'%d',
'%s',
'%s'
)
);
}
/**
* Get user IP
*/
function get_user_ip()
{
$client = #$_SERVER['HTTP_CLIENT_IP'];
$forward = #$_SERVER['HTTP_X_FORWARDED_FOR'];
$remote = $_SERVER['REMOTE_ADDR'];
if ( filter_var($client, FILTER_VALIDATE_IP) ) {
$ip = $client;
} elseif ( filter_var($forward, FILTER_VALIDATE_IP) ) {
$ip = $forward;
} else {
$ip = $remote;
}
return $ip;
}
UPDATE WITH SOLUTION
Thanks to #mplungjan's suggestion I updated my code to the following, working code. Please note some differences with #mplungjan's code, because I had to make some adjustments to make it work in WordPress.
contents of bottom part of show-advert.php
<script>
jQuery(function() {
jQuery(".advertLink").on("click",function(e) {
e.preventDefault(); // stop the link unless it has a target _blank or similar
var href = this.href;
var id= <?php echo $advert_id; ?>;
jQuery.post("<?php echo get_home_url(); ?>/wp-content/plugins/facilitaire-advert-widget/save-advert-click.php",
{ "action":"register_click", "advert_id":id },
function() {
location=href;
}
);
});
});
</script>
Link of Advert<br />
<?php
Then in the top part of save-advert-click.php I have
<?php
// check for action signal
if($_POST['action'] == 'register_click') {
f1_add_advert_click( $_POST["advert_id"] );
}
/**
* Records a click event in the database
*/
function f1_add_advert_click ( $advert_id )
{
$user_ip = get_user_ip();
// need to load WordPress to be able to access the database
define( 'SHORTINIT', true );
require_once( '../../../wp-load.php' ); // localhost needs this, production can have require_once( $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php' );
global $wpdb;
$table_name = $wpdb->prefix . 'f1_advert_clicks';
$wpdb->insert( $table_name, array(
'advert_id'=> $advert_id,
'user_agent'=> $_SERVER['HTTP_USER_AGENT'],
'ip_address'=> $user_ip
),
array(
'%d',
'%s',
'%s'
)
);
}
You will want to do something like
$(function() {
$(".advertLink").on("click",function(e) {
e.preventDefault(); // stop the link unless it has a target _blank or similar
var href = this.href;
var id=this.id; // or $(this).data("advertid") if you have data-advertid="advert1" on the link
$.post("./wp-content/plugins/facilitaire-advert-widget/save-advert-click.php",
{ "action":"call_this", "advert_ID":id },
function() {
location=href; // or window.open
}
);
});
});
using
Link of Advert

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

Categories

Resources