I'm trying to learn php and WP developing. My goal is to mark posts done/read on button click. I found this great ajax tutorial plugin. Here is the link of the tutorial, and for the plugin. I have successfully manage to edit the plugin form my needs. On click it checks if there is already that id in the array, if it is it deletes that element from the array. If there is not id in the array, or the array is empty it adds post id into the array. Afterwards the array is updated into db.
Here is the code for the button, that is added after the post content:
public function rml_button( $content ) {
$rml_post_id = get_the_id();
// Show read me later link only when user is logged in
if( is_user_logged_in() && get_post_type() == post ) {
if( get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ) !== null ) {
$value = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true );
}
if( $value ) {
if (in_array($rml_post_id, $value)) {
$html .= 'DONE';
$content .= $html;
}
else {
$html .= 'MARK AS DONE';
$content .= $html;
}
}
else {
$html .= 'MARK AS DONE';
$content .= $html;
}
}
return $content;
}
Here is the code for updating the db:
public function read_me_later() {
check_ajax_referer( 'rml-nonce', 'security' );
$rml_post_id = $_POST['post_id'];
$echo = array();
if( get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ) !== null ) {
$value = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true );
}
if( $value ) {
if (in_array($rml_post_id, $value)) {
foreach (array_keys($value, $rml_post_id, true) as $key) {
unset($value[$key]);
}
$echo = $value;
}
else {
$echo = $value;
array_push( $echo, $rml_post_id );
}
}
else {
$echo = array( $rml_post_id );
}
update_user_meta( wp_get_current_user()->ID, 'rml_post_ids', $echo );
// Always die in functions echoing Ajax content
die();
}
Finally, here is the .js for the ajax call:
jQuery(document).ready( function(){
jQuery('#content').on('click', 'a.rml_bttn', function(e) {
e.preventDefault();
var rml_post_id = jQuery(this).data( 'id' );
jQuery.ajax({
url : rml_obj.ajax_url,
type : 'post',
data : {
action : 'read_me_later',
security : rml_obj.check_nonce,
post_id : rml_post_id
},
success : function( response ) {
jQuery('.rml_contents').html(response);
}
});
//jQuery(this).hide();
});
});
What I cannot figure out, and sorry if it is a stupid question, is how to change button text after the ajax? From "MARK AS DONE" to "DONE" and vice versa. How to call this function rml_button(), inside read_me_later() so that button text will be changed after the db update.
Thank you.
Added if else statements inside ajax success function to be able to change a tag text from MARK AS DONE to DONE and vice versa.
Try:
jQuery(document).ready( function(){
jQuery('#content').on('click', 'a.rml_bttn', function(e) {
e.preventDefault();
var rml_post_id = jQuery(this).data( 'id' );
var ts = jQuery(this);
jQuery.ajax({
url : rml_obj.ajax_url,
type : 'post',
data : {
action : 'read_me_later',
security : rml_obj.check_nonce,
post_id : rml_post_id
},
success : function( response ) {
if(ts.html()=="DONE") { ts.html("MARK AS DONE"); } // ts.html()=="DONE" - maybe changed based on response
else { ts.html("DONE"); }
jQuery('.rml_contents').html(response);
}
});
//jQuery(this).hide();
});
});
Related
I have stored CSV files in a local folder. And i am displaying the names of the files in the local folder in the form of a list on the frontend dynamically.
FILE NAME LISTING
$path = "uploads/";
$files = scandir($path);
foreach($files as $file) {
if ($file[0] != '.') $nothidden[] = $file;
}
for ($x=0;$x<count($nothidden);$x++){
?><li class="active"><a><?php ${'file'.$x} = $nothidden[$x]; echo $nothidden[$x]; ?></a></li><br/>
<?php
}
I am able to display the csv file in tabular form one at a time statically.
CSV FILE TABLE
$value = 'file.csv';
$target='uploads/'.basename($value);
echo "<table id='toggle-vis'>\n\n";
$f = fopen($target, "r");
while (($line = fgetcsv($f)) !== false) {
echo "<tr>";
foreach ($line as $cell) {
echo "<td>" . htmlspecialchars($cell) . "</td>";
}
echo "</tr>\n";
}
fclose($f);
echo "\n</table>"
What i want is to display is the table of a csv file from the local directory when clicked on the particular name of the file in the list displayed. And when the other file name on the list is clicked, the previous table should be removed and the data from the clicked file should populate the table.
Any help please?
This is a very quickly written example - it works for me as a test but you will need to look at it carefully to make suitable edits to suit your final needs and environment.
The ajax function is invoked when an a within the list is clicked. The code looks at the event and uses the event.target to intercept the innerHTML for the a - that is the filename sent as a parameter ( via ajax ) to the php script. The PHP script checks that the method is POST and that there is a filename in the POST array - if it is OK then will process that file and send back the csv data. This could be edited so that only the filename rather than the full filepath is sent so that users do not know the actual filepaths used on your system!
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_POST['filename'] ) ){
$filename=filter_input( INPUT_POST, 'filename', FILTER_SANITIZE_STRING );
if( $filename && realpath( $filename ) ){
ob_clean();
$hndl=fopen( $filename, 'r' );
$html=array();
$html[]="<table id='toggle-vis'>";
while ( ( $line = fgetcsv( $hndl ) ) !== false ){
$html[]="<tr>";
foreach( $line as $cell )$html[]="<td>$cell</td>";
$html[]="</tr>";
}
$html[]="</table>";
fclose( $hndl );
header( 'Content-Type: text/html' );
exit( implode( PHP_EOL, $html ) );
}
}
?>
<!doctype html>
<html>
<head>
<title>csv manipulations</title>
<script>
/*
basic ajax function
*/
function ajax(m,u,p,c,o){
/*
Method,Url,Params,Callback,Options
*/
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if( xhr.readyState==4 && xhr.status==200 )c.call( this, xhr.response, o, xhr.getAllResponseHeaders() );
};
var params=[];
for( var n in p )params.push( n+'='+p[ n ] );
switch( m.toLowerCase() ){
case 'post': p=params.join('&'); break;
case 'get': u+='?'+params.join('&'); p=null; break;
}
xhr.open( m.toUpperCase(), u, true );
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send( p );
}
/*
event handler assigned to each `a` within the list ( li.active > a )
*/
function getcsvdata(e){
try{
e.preventDefault();
var method='post';
var url=location.href;
var params={
filename:e.target.innerHTML
};
var callback=csvcallback;
var options={};
ajax.call( this, method, url, params, callback, options );
}catch( err ){
console.warn( err );
}
}
/*
ajax callback to process the response from the php script at the top
*/
function csvcallback( data ){
try{
var table=document.getElementById('toggle-vis');
if( table ){
var parent=table.parentNode;
parent.removeChild( table );
parent.insertAdjacentHTML('beforeend',data);
}
}catch( err ){
console.warn( err );
}
}
/*
Bind event handlers to each `a` in list
*/
document.addEventListener('DOMContentLoaded',function(){
var col=Array.prototype.slice.call( document.querySelectorAll('li.active > a') );
col.forEach(function(e){
e.addEventListener('click',getcsvdata,false);
});
}, false );
</script>
</head>
<body>
<h1>CSV Files</h1>
<ul id='list'>
<?php
/* edit to suit */
$dir='c:/temp2/csvfiles';
$col=glob( $dir . '/*.csv' );
if( !empty( $col ) ){
foreach( $col as $file ){
echo "<li class='active'><a href='#'>$file</a></li>";
}
}
?>
</ul>
<table id='toggle-vis'>
<tr>
<td>csv data to appear here when links clicked</td>
</tr>
</table>
</body>
</html>
Following the piece of code may help to you.
var csvData;
$(document).ready(function() {
$("#btnGET").click(function() {
csvData = $.ajax({
type: "GET",
url: "<csv file path>",
dataType: "text/csv",
success: function (result) {
alert(result);
alert("done!"+ csvData.getAllResponseHeaders())
}
});
});
});
I have this action that retrieves the crop values when I crop an image in the image editor and update the value in the db record (with update_field().
So I can update the value of the field in the database, but I don't know how to set the value of the field in the post editor. The field value remains blank and when the user update the post the value is being overwritten by with null value.
How can I do?
add_action( 'wp_save_image_editor_file', 'save_crop_data');
function save_crop_data(){
$attachment_id = $_REQUEST['postid'];
$parent = get_post_ancestors($attachment_id);
$post_id = $parent[0];
update_field('crop_data', $_REQUEST['history'], $post_id);
return $saved;
}
PHP
add_action( 'admin_enqueue_scripts', 'portfolio_admin_script' );
function portfolio_admin_script() {
global $post_type;
if( 'portfolio' == $post_type )
wp_enqueue_script( 'portfolio-admin-script', get_stylesheet_directory_uri() . '/portfolio.js', array( 'jquery', 'media-editor' ), '', true );
}
JAVASCRIPT (file portfolio.js)
jQuery(function ($) {
$(document).ajaxComplete(function (event, xhr, settings) {
//intercept the ajax event on media library close
if (typeof settings.data === 'string' && /action=get-post-thumbnail-html/.test(settings.data) && xhr.responseJSON && typeof xhr.responseJSON.data === 'string') {
var crop_data_stored = decodeURIComponent(getCookie("crop_values"));
crop_data_stored = crop_data_stored.replace(/\\"/g, '"');
if (crop_data_stored != '' && $('#acf-field-crop_data').val() == '') {
jQuery('#acf-field-crop_data').val(crop_data_stored);
deleteCookie("crop_values");
}
}
});
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
function deleteCookie(name) {
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;";
};
});
I am working on WordPress plugin. In plugin there is a check box, when a user checked the checkbox a value will be saved in database via ajax and when its unchecked the value will be deleted from database via ajax. So I create a checkbox and write an ajax code.
Here is my code:
HTML Code
<?php
$cart_items = get_cart_contents();
$cart_info = array();
foreach ($cart_items as $_data) {
$prod_id = $_data['id'];
$cart_info[] = array(
'prod_id' => $prod_id,
);
}
$_cart_sr = serialize($cart_info);
?>
<label class="label" for="purchase">
<?php _e('Purchase', 'product'); ?>
<input type="checkbox" id="purchase" />
</label>
<input type="hidden" class="cart_info" value='<?php echo $_cart_sr; ?>'>
Here is my Ajax and PHP Code:
add_action('wp_ajax_values_save', 'save_check_value');
add_action('wp_ajax_nopriv_values_save', 'save_check_value');
add_action('wp_ajax_values_delete', 'delete_check_value');
add_action('wp_ajax_nopriv_values_delete', 'delete_check_value');
add_action("wp_head", "edd_gift_email_ajax");
function edd_gift_email_ajax() {
?>
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery("#purchase").click(function () {
if(jQuery(this).is(":checked")) {
var cart_info_save = jQuery('.cart_info').val();
var data_save = {
action: 'values_save',
cart_info_save: cart_info_save
}
jQuery.post('<?php echo admin_url('admin-ajax.php'); ?>', data_save, function (save_result) {
alert(save_result);
});
} else {
var cart_info_delete = jQuery('.cart_info').val();
var data_delete = {
action: 'values_delete',
cart_info_delete: cart_info_delete
}
jQuery.post('<?php echo admin_url('admin-ajax.php'); ?>', data_delete, function (delete_result) {
alert(delete_result);
});
}
});
});
</script>
<?php
}
And here is my save and delete query
function save_check_value() {
global $wpdb;
$info_save = stripcslashes($_REQUEST['cart_info_save']);
$cart_info_un_sr_save = unserialize($info_save);
foreach ($cart_info_un_sr_save as $user_gift_cart_save) {
$prod_user_id_save = $user_cart_save['prod_id'];
echo $prod_user_id_save . " _ Add This";
//update_post_meta($prod_user_id_save, 'this_product', '1');
}
}
function delete_check_value() {
global $wpdb;
$info_delete = stripcslashes($_REQUEST['cart_info_delete']);
$cart_info_un_sr_delete = unserialize($info_delete);
foreach ($cart_info_un_sr_delete as $user_cart_delete) {
$prod_user_id_delete = $user_cart_delete['prod_id'];
echo $prod_user_id_delete . " _ Delete This";
//delete_post_meta($prod_user_id_delete, 'this_product', '1');
}
}
So when I checked the check box the alert gives me this value 168 _ Add This (this is what I want) but when I unchecked the check box the alert gives me this value 0 (I want this value 168 _ Delete This).
I checked every thing but I got confused that why else condition not give me the right value.
Any suggestions.
Not directly a solution but I can't help thinking there is quite a lot of duplication of code which could be somewhat simplified.
The initial javascript function could be like:
<script type="text/javascript">
jQuery( document ).ready(function() {
jQuery("#purchase").click( function() {
var action=jQuery(this).is(":checked") ? 'save' : 'delete';
var cart_info=jQuery('.cart_info').val();
var data={
action:'value_'+action,
cart_info:cart_info
};
jQuery.post('<?php echo admin_url('admin-ajax.php'); ?>', data, function( result ) {
alert( result );
});
}
});
});
</script>
And rather than two distinct functions that share almost the same code you could do:
<?php
function check_value() {
global $wpdb;
$info = stripcslashes( $_REQUEST['cart_info'] );
$cart_info = unserialize( $info );
/* To find the `action` analyse the following */
exit( print_r( $cart_info ) );
foreach( $cart_info as $gift ) {
list( $junk, $action ) = explode( '_', $gift['action'] );
$product = $gift['prod_id'];
echo $product . " _ ".$action." this";
switch( $action ){
case 'save':
update_post_meta($product, 'this_product', '1');
break;
case 'delete':
delete_post_meta($product, 'this_product', '1');
break;
}
}
}
?>
The answer of #RamRaider is good but You can still reduce more code and might be it will work for you as well :)
Here's the jQuery:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#purchase").click( function() {
// Method variable will be using to define which
// function should trigger later in our PHP
var cart_method = jQuery(this).is(":checked") ? 'save' : 'delete';
var cart_info = jQuery('.cart_info').val();
var data = {
action: 'modify_cart',
cart_method: cart_method,
cart_info: cart_info
};
jQuery.post('<?php echo admin_url('admin-ajax.php'); ?>', data, function( result ) {
alert( result );
});
}
});
});
</script>
And then here is our PHP code:
<?php
function modify_cart_func() {
global $wpdb;
// Get method from our jQuery
$method = $_POST['cart_method'];
$info = stripcslashes( $_REQUEST['cart_info'] );
$cart_info = unserialize( $info );
foreach( $cart_info as $gift ) {
// If method is save
if ($method == 'save') {
update_post_meta($gift['product_id'], 'this_product', 1);
// If method is delete
} else if ($method == 'delete') {
delete_post_meta($gift['product_id'], 'this_product', 1);
}
}
}
?>
And finally your ajax call:
<?php
add_action('wp_ajax_modify_cart', 'modify_cart_func');
add_action('wp_ajax_nopriv_modify_cart', 'modify_cart_func');
?>
Hope that makes sense to you ;)
I am not sure if this causes the problem but if you are calling ajax when not logged in it tries to call wp-ajax with action email_values_delete not values_delete which i guess you are trying to call. Of course you might have that action as well for some other functionality.
If that is not the case change this
add_action('wp_ajax_nopriv_email_values_delete', 'delete_check_value');
To this
add_action('wp_ajax_nopriv_values_delete', 'delete_check_value');
You should also add wp_die(); in the end of each php function you are calling via wp-ajax.
Hope this helps.
Edit:
Sorry, it tries to call values_delete but since there is only email_values_delete (for non logged in users) defined I would guess ajax request might return something like 0.
Ive been trying to get this done for hours now and its making my head rattle.
Ive nearly got it, but unfortunately when no content is wrapped its showing the title of the shortcode.
For instance one of my titles is shortcode 1 and when its wrapped around some text it should show [thirdwidth]content goes here[/thirdwidth]
But if i do not wrap it, it shows the title.
shortcode 1[thirdwidth][/thirdwidth]
Why is this doing it?
Here is the code on the php front:
function register_customcode_dropdown( $buttons ) {
array_push( $buttons, "Shortcodes" );
return $buttons;
}
function add_customcode_dropdown( $plugin_array ) {
$plugin_array['Shortcodes'] = get_template_directory_uri() . '/style/js/TinyMCE_js.js';
return $plugin_array;
}
function customcode_dropdown() {
if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') ) {
return;
}
if ( get_user_option('rich_editing') == 'true' ) {
add_filter( 'mce_external_plugins', 'add_customcode_dropdown' );
add_filter( 'mce_buttons', 'register_customcode_dropdown' );
}
}
add_action('init', 'customcode_dropdown');
Here is the TinyMCE_js.js file
(function() {
tinymce.create('tinymce.plugins.Shortcodes', {
init : function(ed, url) {
},
createControl : function(n, cm) {
if(n=='Shortcodes'){
var mlb = cm.createListBox('Shortcodes', {
title : 'Shortcodes',
onselect : function(v) {
if(tinyMCE.activeEditor.selection.getContent() == ''){
tinyMCE.activeEditor.selection.setContent( v )
}
if(v == 'shortcode 1'){
selected = tinyMCE.activeEditor.selection.getContent();
if( selected ){
//If text is selected when button is clicked
//Wrap shortcode around it.
content = '[thirdwidth]'+selected+'[/thirdwidth]';
}else{
content = '[thirdwidth][/thirdwidth]';
}
tinymce.execCommand('mceInsertContent', false, content);
}
if(v == 'shortcode 2'){
selected = tinyMCE.activeEditor.selection.getContent();
if( selected ){
//If text is selected when button is clicked
//Wrap shortcode around it.
content = '[12]'+selected+'[/12]';
}else{
content = '[12][/12]';
}
tinymce.execCommand('mceInsertContent', false, content);
}
}
});
// Add some menu items
var my_shortcodes = ['shortcode 1','shortcode 2'];
for(var i in my_shortcodes)
mlb.add(my_shortcodes[i],my_shortcodes[i]);
return mlb;
}
return null;
}
});
tinymce.PluginManager.add('Shortcodes', tinymce.plugins.Shortcodes);
})();
Thanks
Found the issue, it was I left this in:
if(tinyMCE.activeEditor.selection.getContent() == ''){
tinyMCE.activeEditor.selection.setContent( v )
}
I'm using Dojo 1.7.2 and I try the following code
var request = xhr.get({
url: location,
content : content,
load : function( data ){
for( var x in data )
{
alert ( x + data[x] );
}
},
error : function()
{
alert( 'Had an eror' );
},
handleAs : 'json'
});
Then in php i do the following to try and detect the xmlhttprequest
function isAjax(){
$ajax = (isset( $_SERVER[ 'HTTP_X_REQUESTED_WITH' ] ) ) &&
( strtolower( $_SERVER[ 'HTTP_X_REQUESTED_WITH' ] ) == 'xmlhttprequest' );
return $ajax;
}
But the isAjax function returns false.
If I do xhr.post then it works fine. I'm thinking this is just a side effect of using GET instead of POST? Is that it or is it something else that I'm not checking for.
This solution is based on Zend Framework version.
function isAjax() {
$header = 'X_REQUESTED_WITH';
// Try to get it from the $_SERVER array first
$temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
if (isset($_SERVER[$temp])) {
return $_SERVER[$temp] == 'XMLHttpRequest';
}
// This seems to be the only way to get the Authorization header on
// Apache
if (function_exists('apache_request_headers')) {
$headers = apache_request_headers();
if (isset($headers[$header])) {
return $headers[$header] == 'XMLHttpRequest';
}
$header = strtolower($header);
foreach ($headers as $key => $value) {
if (strtolower($key) == $header) {
return true;
}
}
}
return false;
}
It is not a standard that this header is appended - as it is an unnescesary overhead in most cases.
You need to set the header yourself - and can call it whatever you please really. What you want is headers: { "X-Requested-With": "XMLHttpRequest" }:
var request = xhr.get({
url: location,
content : content,
headers: { "X-Requested-With": "XMLHttpRequest" }, // << < add this
load : function( data ){
for( var x in data )
{
alert ( x + data[x] );
}
},
error : function()
{
alert( 'Had an eror' );
},
handleAs : 'json'
});