I created a custom widget to display a calendar and the code for the calendar can be found here.
From my theme root directory, the folder structure looks like this:
inc/most-recent-widget.php
All the calendar code has been added in the widget class:
class __themename_Most_recent_widget extends WP_Widget{
private $weekDayName = array ("MON","TUE","WED","THU","FRI","SAT","SUN");
private $currentDay = 0;
private $currentMonth = 0;
private $currentYear = 0;
private $currentMonthStart = null;
private $currentMonthDaysLength = null;
function __construct() {
parent::__construct(
'_themename_most_recent_widget',
esc_html__('Recent Posts', '_themename'),
['description' => esc_html__('some description', '_themename')]
);
$this->currentYear = date ( "Y", time () );
$this->currentMonth = date ( "m", time () );
if (! empty ( $_POST ['year'] )) {
$this->currentYear = $_POST ['year'];
}
if (! empty ( $_POST ['month'] )) {
$this->currentMonth = $_POST ['month'];
}
$this->currentMonthStart = $this->currentYear . '-' . $this->currentMonth . '-01';
$this->currentMonthDaysLength = date ( 't', strtotime ( $this->currentMonthStart ) );
}
function getCalendarHTML() {
$calendarHTML = '<div id="calendar-outer">';
$calendarHTML .= '<div class="calendar-nav">' . $this->getCalendarNavigation() . '</div>';
$calendarHTML .= '<ul class="week-name-title">' . $this->getWeekDayName () . '</ul>';
$calendarHTML .= '<ul class="week-day-cell">' . $this->getWeekDays () . '</ul>';
$calendarHTML .= '</div>';
return $calendarHTML;
}
function getCalendarNavigation() {
$prevMonthYear = date ( 'm,Y', strtotime ( $this->currentMonthStart. ' -1 Month' ) );
$prevMonthYearArray = explode(",",$prevMonthYear);
$nextMonthYear = date ( 'm,Y', strtotime ( $this->currentMonthStart . ' +1 Month' ) );
$nextMonthYearArray = explode(",",$nextMonthYear);
$navigationHTML = '<div class="prev" data-prev-month="' . $prevMonthYearArray[0] . '" data-prev-year = "' . $prevMonthYearArray[1]. '"><</div>';
$navigationHTML .= '<span id="currentMonth">' . date ( 'M ', strtotime ( $this->currentMonthStart ) ) . '</span>';
$navigationHTML .= '<span contenteditable="true" id="currentYear">'. date ( 'Y', strtotime ( $this->currentMonthStart ) ) . '</span>';
$navigationHTML .= '<div class="next" data-next-month="' . $nextMonthYearArray[0] . '" data-next-year = "' . $nextMonthYearArray[1]. '">></div>';
return $navigationHTML;
}
function getWeekDayName() {
$WeekDayName= '';
foreach ( $this->weekDayName as $dayname ) {
$WeekDayName.= '<li>' . $dayname . '</li>';
}
return $WeekDayName;
}
function getWeekDays() {
$weekLength = $this->getWeekLengthByMonth ();
$firstDayOfTheWeek = date ( 'N', strtotime ( $this->currentMonthStart ) );
$weekDays = "";
for($i = 0; $i < $weekLength; $i ++) {
for($j = 1; $j <= 7; $j ++) {
$cellIndex = $i * 7 + $j;
$cellValue = null;
if ($cellIndex == $firstDayOfTheWeek) {
$this->currentDay = 1;
}
if (! empty ( $this->currentDay ) && $this->currentDay <= $this->currentMonthDaysLength) {
$cellValue = $this->currentDay;
$this->currentDay ++;
}
$weekDays .= '<li>' . $cellValue . '</li>';
}
}
return $weekDays;
}
function getWeekLengthByMonth() {
$weekLength = intval ( $this->currentMonthDaysLength / 7 );
if($this->currentMonthDaysLength % 7 > 0) {
$weekLength++;
}
$monthStartDay= date ( 'N', strtotime ( $this->currentMonthStart) );
$monthEndingDay= date ( 'N', strtotime ( $this->currentYear . '-' . $this->currentMonth . '-' . $this->currentMonthDaysLength) );
if ($monthEndingDay < $monthStartDay) {
$weekLength++;
}
return $weekLength;
}
public function widget($args, $instance){
echo $this->getCalendarHTML();
}
}
function __themename_register_most_recent_widget(){
register_widget('__themename_Most_recent_widget');
}
add_action('widgets_init', '__themename_register_most_recent_widget');
Inside the above class, my widget method, which is what calls the calendar looks like this:
public function widget($args, $instance){
echo $this->getCalendarHTML();
}
Until here the calendar shows up with its styling.
How can I get the Javascript and Ajax code to run?
I created a js file named customize-controls.js:
(function( $ ) {
$(document).ready(function(){
$(document).on("click", '.prev', function(event) {
var month = $(this).data("prev-month");
var year = $(this).data("prev-year");
getCalendar(month,year);
});
$(document).on("click", '.next', function(event) {
var month = $(this).data("next-month");
var year = $(this).data("next-year");
getCalendar(month,year);
});
$(document).on("blur", '#currentYear', function(event) {
var month = $('#currentMonth').text();
var year = $('#currentYear').text();
getCalendar(month,year);
});
});
function getCalendar(month,year){
var url = "/testtheme/wp-admin/admin-ajax.php";
$.ajax({
url: url,
action : 'calendar_events',
type: "POST",
data:'month='+month+'&year='+year,
success: function(response){
$("#calendar-html-output").html(response);
},
error: function(){}
});
}
})( jQuery );
When I view the calendar and try to click on one of the controls I see the following in my console:
VM3244:1 POST http://localhost/testtheme/wp-admin/admin-ajax.php 400 (Bad Request)
EDIT:
My functions.php looks like the following:
function twentynineteen_scripts() {
wp_enqueue_style( 'twentynineteen-style', get_stylesheet_uri(), array(), wp_get_theme()->get( 'Version' ) );
wp_enqueue_script( 'twentynineteen-customControl', get_theme_file_uri( '/js/customize-controls.js' ), array('jquery'), '1.1', true );
wp_localize_script( 'customize-controls-script', 'php_obj',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' )
)
);
}
add_action( 'wp_enqueue_scripts', 'twentynineteen_scripts' );
add_action( 'wp_ajax_calendar_events', 'calendar_events_callback' );
add_action( 'wp_ajax_nopriv_calendar_events', 'calendar_events_callback' );
function calendar_events_callback() {
exit();
}
How can I get the javascript side working?
There are a few issues with your code.
You never set the admin-ajax.php URL like that. You have to use script localization:
in your case, where you have the wp_register_script() or wp_enqueue_script() function you also have to use wp_localize_script().
PHP File
Not sure what is your script handle but I will put down an example:
wp_enqueue_script('customize-controls-script', get_stylesheet_directory_uri() . 'customize-controls.js');
wp_localize_script( 'customize-controls-script', 'php_obj',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' )
)
);
JS File
And then in your JS file you use that php_obj variable we just sent using wp_localize_script():
function getCalendar(month,year){
var url = php_obj.ajaxUrl;
$.post({
url,
data:{
action: 'calendar_events',
month: month,
year: year
},
success: function(response){
$("#calendar-html-output").html(response);
},
error: function(){}
});
}
You need to add the WP actions to handle the ajax request. You can learn more here
WordPress is usually returning the 400 response when the ajax actions are not set correctly in PHP.
As an example. I will put down a quick sample:
add_action( 'wp_ajax_calendar_events', 'calendar_events_callback' );
add_action( 'wp_ajax_nopriv_calendar_events', 'calendar_events_callback' );
function calendar_events_callback() {
// logic for the output
// here you output the html you need to the calendar
// make sure you exit so the output stops when the request is done
exit();
}
Let me know if that is clear or if you need more help with it.
Here is another good reference regarding the use of AJAX in WP
EDIT
After the code you added make sure the handle of the wp_enqueue_script() is the same as the wp_localize_script() one:
function twentynineteen_scripts() {
wp_enqueue_style( 'twentynineteen-style', get_stylesheet_uri(), array(), wp_get_theme()->get( 'Version' ) );
wp_enqueue_script( 'twentynineteen-customControl', get_theme_file_uri( '/js/customize-controls.js' ), array('jquery'), '1.1', true );
wp_localize_script( 'twentynineteen-customControl', 'php_obj',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' )
)
);
}
EDIT 2
Given the fact that WP does not allow you to instantiate the widget by doing $calendar_widget = new __themename_Most_recent_widget();, means that you have to move the PHPCalendar methods in another class that you then instantiate in both the widget and the AJAX call.
That means:
CalendarWidget class
class CalendarWidget{
private $weekDayName = array ("MON","TUE","WED","THU","FRI","SAT","SUN");
private $currentDay = 0;
private $currentMonth = 0;
private $currentYear = 0;
private $currentMonthStart = null;
private $currentMonthDaysLength = null;
function __construct() {
//method here
}
function getCalendarHTML() {
//method here
}
function getCalendarNavigation() {
//method here
}
function getWeekDayName() {
//method here
}
function getWeekDays() {
//method here
}
function getWeekLengthByMonth() {
//method here
}
}
Widget Class File
class __themename_Most_recent_widget extends WP_Widget{
function __construct() {
parent::__construct(
'_themename_most_recent_widget',
esc_html__('Recent Posts', '_themename'),
['description' => esc_html__('some description', '_themename')]
);
}
public function widget($args, $instance){
$phpCalendar = new CalendarWidget();
$calendarHTML = $phpCalendar->getCalendarHTML();
echo $calendarHTML;
}
}
function __themename_register_most_recent_widget(){
register_widget('__themename_Most_recent_widget');
}
add_action('widgets_init', '__themename_register_most_recent_widget');
Functions.php
function twentynineteen_scripts() {
wp_enqueue_style( 'twentynineteen-style', get_stylesheet_uri(), array(), wp_get_theme()->get( 'Version' ) );
wp_enqueue_script( 'twentynineteen-customControl', get_theme_file_uri( '/js/customize-controls.js' ), array('jquery'), '1.1', true );
wp_localize_script( 'twentynineteen-customControl', 'php_obj',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' )
)
);
}
add_action( 'wp_enqueue_scripts', 'twentynineteen_scripts' );
add_action( 'wp_ajax_calendar_events', 'calendar_events_callback' );
add_action( 'wp_ajax_nopriv_calendar_events', 'calendar_events_callback' );
function calendar_events_callback() {
$phpCalendar = new CalendarWidget();
$calendarHTML = $phpCalendar->getCalendarHTML();
echo $calendarHTML;
exit();
}
This should do it :)
Related
I'm trying to add more than one fee to the order total amount checkout using ajax.
So far, the first fee, insurance_shipping_fee, is working correctly, but when checking the second one, premium_gift_box, I receive a 400 error ("xxx.com/wp-admin/admin-ajax.php").
Any ideas on why?
Any help appreciated
This is the full code:
// Calculate insurance fee
function as_calculate_insurance_fee() {
$shipping_country = WC()->customer->get_shipping_country();
$cart_subtotal = WC()->cart->subtotal;
$cart_subtotal_rounded = ceil($cart_subtotal / 100) * 100;
if($shipping_country == 'AU') {
if($cart_subtotal <= 5000) $insurance_fee = $cart_subtotal_rounded/100 + 1;
} else {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ($chosen_shipping == 'free_shipping:12' || $chosen_shipping == 'starshipit_4') {
if($cart_subtotal <= 5000) $insurance_fee = $cart_subtotal_rounded/100 * 3;
} else if($chosen_shipping == 'starshipit_5') {
$insurance_fee = ($cart_subtotal_rounded - 1000)/100 * 3 + 25;
}
}
return $insurance_fee;
}
// Add a Shipping Insurance checkbox field
function add_custom_checkout_checkbox() {
$insurance_fee = as_calculate_insurance_fee();
if( WC()->session->get('enable_fee') ) $checked = true;
else $checked = false;
woocommerce_form_field( 'insurance_fee', array(
'type' => 'checkbox',
'label' => __('<span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">'.get_woocommerce_currency().' </span>'.$insurance_fee.'</bdi></span>'),
'class' => array( 'form-row-wide' ),
), $checked );
}
add_action( 'as_review_order_after_shipping', 'add_custom_checkout_checkbox', 20 );
// Add Signature Gift Box checkbox field
function add_custom_checkout_checkbox_2() {
if( WC()->session->get('enable_fee_2') ) $checked = true;
else $checked = false;
woocommerce_form_field( 'premium_giftbox_fee', array(
'type' => 'checkbox',
'label' => __('<span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">'.get_woocommerce_currency().' </span>9</bdi></span>'),
'class' => array( 'form-row-wide' ),
), $checked );
}
add_action( 'as_review_order_before_shipping', 'add_custom_checkout_checkbox_2', 20 );
// Add custom fees
function custom_fee( $cart ) {
// Only on checkout
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! is_checkout() )
return;
$insurance_fee = as_calculate_insurance_fee();
if( WC()->session->get('enable_fee') )
$cart->add_fee( __( 'Insurance fee', 'woocommerce'), $insurance_fee );
if( WC()->session->get('enable_fee_2') )
$cart->add_fee( __( 'Siganture Gift Box fee', 'woocommerce'), 9 );
}
add_action( 'woocommerce_cart_calculate_fees', 'custom_fee', 20, 1 );
// Remove "(optional)" label on checkbox field
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( ( 'insurance_fee' === $key || 'premium_giftbox_fee' === $key ) && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );
// jQuery - Ajax script
function checkout_fees_script() {
// Only on Checkout
if( is_checkout() && ! is_wc_endpoint_url() ) :
if( WC()->session->__isset('enable_fee') )
WC()->session->__unset('enable_fee');
if( WC()->session->__isset('enable_fee_2') )
WC()->session->__unset('enable_fee_2');
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on('change', 'input[name=insurance_fee]', function(e){
var fee = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'enable_fee',
'enable_fee': fee,
},
success: function (result) {
$('body').trigger('update_checkout');
},
});
});
$('form.checkout').on('change', 'input[name=premium_giftbox_fee]', function(e){
var fee2 = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'enable_fee_2',
'enable_fee_2': fee2,
},
success: function (result) {
$('body').trigger('update_checkout');
},
});
});
});
</script>
<?php
endif;
}
add_action( 'wp_footer', 'checkout_fees_script' );
// Get Ajax request and saving to WC session
function get_enable_fee() {
if ( isset($_POST['enable_fee']) ) {
WC()->session->set('enable_fee', ($_POST['enable_fee'] ? true : false) );
}
if ( isset($_POST['enable_fee_2']) ) {
WC()->session->set('enable_fee_2', ($_POST['enable_fee_2'] ? true : false) );
}
die();
}
add_action( 'wp_ajax_enable_fee', 'get_enable_fee' );
add_action( 'wp_ajax_nopriv_enable_fee', 'get_enable_fee' );
```
You forgot to register the second fee ajax action.
It should be like that.
add_action( 'wp_ajax_enable_fee', 'get_enable_fee' );
add_action( 'wp_ajax_nopriv_enable_fee', 'get_enable_fee' );
add_action( 'wp_ajax_enable_fee_2', 'get_enable_fee' );
add_action( 'wp_ajax_nopriv_enable_fee_2', 'get_enable_fee' );
I am setting up a custom post with a front-office display filter via taxonomy. After several hours of research and tests, I finally managed to get what I want but I still have 2 little things on which I am stuck... I would have liked to add an ALL button to re-display all my archives if we clicked on another filter before.
I also can’t add a class to my filter button when it is activated... Do you have a lead to refer me please?
Below what I did:
archive-work.php
<div id="work-filter" class="col-md-12">
<?php get_work_filters(); ?>
</div>
<div class="work-results animated fadeIn">
<?php $res = my_get_posts();
echo $res['response']; ?>
</div>
functions.php
/***************** filter work ****************/
function ajax_filter_posts_scripts() {
// Enqueue script
wp_register_script('afp_script', get_template_directory_uri() .
'/assets/js/work.js', false, null, false);
wp_enqueue_script('afp_script');
wp_localize_script( 'afp_script', 'afp_vars', array(
'afp_nonce' => wp_create_nonce( 'afp_nonce' ), // Create nonce which we later will use to verify AJAX request
'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
)
);
}
add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);
$result = array();
// Script for getting posts
function ajax_filter_get_posts( $work_item ) {
// Verify nonce
if( !isset( $_POST['afp_nonce'] ) ||
!wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ))
die('Permission denied');
$work_item = $_POST['expertises'];
$result = json_encode(my_get_posts($work_item, true));
echo $result;
die();
}
function my_get_posts($work_item = '', $ajax = false){
// WP Query
$args = array(
'expertises' => $work_item,
'post_type' => 'work',
'posts_per_page' => -1,
);
// If taxonomy is not set, remove key from array and get all posts
if( !$work_item ) {
unset( $args['expertises'] );
}
$query = new WP_Query( $args );
$html = '';
$items = array();
if ( $query->have_posts() ) :
while ( $query->have_posts() ) :
$query->the_post();
$res = '<div class="works">'.
'<a href="'.get_permalink().'">'.
'<article class="panel panel-default" id="post-'.get_the_id().'">'.
'<div class="panel-body">'.
'<div class="panel-cover">'.
'<h3>'.get_the_title().'</h3>'.
get_the_excerpt().
'</div>'.
'<div class="imgworkarch">'.
get_the_post_thumbnail( $post = null, $size = 'archivework' ).
'</div>'.
'</div>'.
'</article>'.
'</a>' .
'</div>';
$ajax ? $items[] = $res : $html .= $res;
endwhile;
$result['response'] = $ajax ? $items : $html;
$result['status'] = 'success';
else:
$result['response'] = '<h2>No posts found</h2>';
$result['status'] = '404';
endif;
wp_reset_postdata();
return $result;
}
add_action('wp_ajax_filter_posts', 'ajax_filter_get_posts');
add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_get_posts');
//Get Work Filters
function get_work_filters()
{
$work_items = get_terms('expertises');
$filters_html = false;
$count = count( $work_items );
if( $count > 0 ):
foreach( $work_items as $work_item )
{
$work_item_id = $work_item->term_id;
$work_item_name = $work_item->name;
$filters_html .= '<a href="' .
get_term_link( $work_item ) .
'" class="btn work-filter" title="' .
$work_item->slug . '">' . $work_item->name . '</a> ';
}
echo $filters_html;
endif;
}
work.js
$(document).ready(function(){
// work filters
$('.work-filter').click( function(event) {
// Prevent default action - opening tag page
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
// Get tag slug from title attirbute
var expertises = $(this).attr('title');
data = {
action: 'filter_posts', // function to execute
afp_nonce: afp_vars.afp_nonce, // wp_nonce
post_type: "work", // selected tag
expertises: expertises,
};
$.ajax({
type: "post",
dataType: "json",
url: afp_vars.afp_ajax_url,
data: data,
success: function(data, textStatus, XMLHttpRequest) {
console.log(data);
// Restore div visibility
$('.work-results').fadeOut()
.queue(function(n) {
$(this).html(data.response);
n();
}).fadeIn();
},
error: function( XMLHttpRequest, textStatus, errorThrown ) {
/*console.log( MLHttpRequest );
console.log( textStatus );
console.log( errorThrown );*/
$('.work-results').fadeOut()
.queue(function(n) {
$(this).html("No items found. ");
n();
}).fadeIn();
}
});
});
});
Maybe it's too late to answer this, but I hope it helps someone.
You just have to add another button into your work-filter block with a different title like 'reset', then remove the taxonomy filter on the query in your my_get_posts when the value matches the title. Here is the code:
function my_get_posts($taxonomy = '', $ajax = false)
{
if($taxonomy != 'reset'){
$args = array(
'service' => $taxonomy,
'post_type' => 'projects',
'posts_per_page' => -1,
);
}else{
$args = array(
'post_type' => 'projects',
'posts_per_page' => -1,
);
}
if (!$taxonomy) {
unset($args['service']);
}
$query = new WP_Query($args);
$html = '';
$items = array();
if ($query->have_posts()) :
while ($query->have_posts()) :
$query->the_post();
$res = '<div class="col-lg-4">' .
'<a href="' . get_permalink() . '">' .
'<article class="panel panel-default" id="post-' . get_the_id() . '">' .
'<div class="panel-body">' .
get_the_post_thumbnail() .
'<div class="panel-cover">' .
'<h3>' . get_the_title() . '</h3>' .
get_the_content() .
'</div>' .
'</div>' .
'</article>' .
'</a>' .
'</div>';
$ajax ? $items[] = $res : $html .= $res;
endwhile;
$result['response'] = $ajax ? $items : $html;
$result['status'] = 'success';
else :
$result['response'] = '<h2>No posts found</h2>';
$result['status'] = '404';
endif;
wp_reset_postdata();
return $result;
}
function reset_all(){
echo 'All ';
}
I am trying to add custom product type to product like here wild card
and i succeeded but now i have to add this value to cart with ajax how i suppose to do this with drop-down and shortcode? i just added load_book.js but didn't added any script code because i don't know how to write ajax code for this. thanks.
My code:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_filter("product_type_options", "woo_bookable_product");
function woo_bookable_product($product_type_options)
{
$product_type_options["Bookable"] = array(
"id" => "_bookable",
"wrapper_class" => "show_if_simple",
"label" => "Bookable",
"description" => "Book Your Product",
"default" => "yes",
);
return $product_type_options;
}
add_action("save_post_product",'woo_save_bookable_data', 10, 3);
function woo_save_bookable_data($post_ID, $product, $update)
{
$meta_value = $_POST["_bookable"] ? 'yes' : 'no';
update_post_meta($product->ID, "_bookable" ,$meta_value);
}
function woo_bookable_scripts()
{
wp_enqueue_script('load_book', plugin_dir_url( __FILE__ ).'js/load_book.js',array('jquery'));
wp_localize_script('load_book','ajax_object',array('ajax_url'=>admin_url('admin-ajax.php')));
}
add_action('wp_enqueue_scripts','woo_bookable_scripts');
add_action('wp_ajax_woo_bookable_shortcode', 'woo_bookable_shortcode');
add_action('wp_ajax_nopriv_woo_bookable_shortcode', 'woo_bookable_shortcode');
function woo_bookable_shortcode()
{
$Data = '';
$query = new WP_Query(array(
'post_type' => 'product',
'meta_key' => '_bookable'
));
$Data.='<select name="woo_book_id" class="woo_book_pro">
<option value="0">Bookable Products</option>';
if($query->have_posts()):while($query->have_posts()):$query->the_post();
$Data.='<option value="'. get_the_ID() .'">'. get_the_title() .'</option>';
endwhile;endif;
$Data.='</select>';
$Data.= woo_bookable_add_to_cart();
echo $Data;
}
add_shortcode('bookable','woo_bookable_shortcode');
Finally find the solution
PHP:
<?php
/**
* Plugin Name: Bookable
* Description: Add shortcode [bookable] or in php - echo do_shortcode('[bookable]');
* Version: 0.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( class_exists( 'WooCommerce' ) || in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) || function_exists( 'WC' ) && is_object( WC() ) && is_a( WC(), 'WooCommerce' ) ){
/////////////////////////////////////////////////////////////////////////////////////////////////
add_filter("product_type_options", "woo_bookable_product");
if(!function_exists('woo_bookable_product')):
function woo_bookable_product($product_type_options)
{
$product_type_options["bookable"] = array(
"id" => "_bookable",
"wrapper_class" => "show_if_simple",
"label" => __("Bookable",'woocommerce'),
"description" => __("Check if product is bookable or not",'woocommerce'),
"default" => "no",
);
return $product_type_options;
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
add_action( 'woocommerce_add_cart_item_data', 'woo_bookable_custom_field', 10, 2 );
if(!function_exists('woo_bookable_custom_field')):
function woo_bookable_custom_field( $cart_item_data, $product_id )
{
$get_custom_meta = get_post_meta( $product_id , '_bookable', true );
if( $get_custom_meta == 'yes' )
{
$cart_item_data[ '_bookable' ] = $get_custom_meta;
$len = 10;
$word = array_merge(range('a', 'z'), range('A', 'Z'));
$name = shuffle($word);
$name = substr(implode($word), 0, $len);
$cart_item_data['unique_key'] = $name ;
}
return $cart_item_data;
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
add_filter( 'woocommerce_get_item_data', 'render_woo_bookable_meta_data', 10, 2 );
if(!function_exists('render_woo_bookable_meta_data')):
function render_woo_bookable_meta_data( $cart_data, $cart_item )
{
global $woocommerce;
$custom_items = array();
if( !empty( $cart_data ) )
{
$custom_items = $cart_data;
}
if( isset( $cart_item['_bookable'] ) )
{
$custom_items[] = array(
"name" => __( "Bookable", "woocommerce" ),
"value" => $cart_item['_bookable'] );
$custom_items[] = array(
"name" => __( $cart_item['unique_key'], "woocommerce" ),
"value" => '$10' );
}
return $custom_items;
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );
if(!function_exists('add_custom_price')):
function add_custom_price( $cart_object )
{
foreach ( $cart_object->get_cart() as $hash => $value )
{
if($value['_bookable'] && $value['data']->is_on_sale())
{
$newprice = $value['data']->get_sale_price()+10;
$value['data']->set_price( $newprice );
}
elseif($value['_bookable'])
{
$not_sell = $value['data']->get_regular_price()+10;
$value['data']->set_price( $not_sell );
}
}
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
add_action( 'woocommerce_cart_calculate_fees', 'woo_bookable_cart_calculate_totals', 10, 1 );
if(!function_exists('woo_bookable_cart_calculate_totals')):
function woo_bookable_cart_calculate_totals( $cart_object )
{
$get_price = 0;
foreach ( $cart_object->get_cart() as $hash => $value )
{
if(!empty($value['_bookable']))
{
$percent = 10;
$get_price += $value['line_total'];
$fee = ($get_price * $percent) / 100;
}
}
$cart_object->add_fee( __("Bookable Charge($percent%)"),$fee ,false );
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
add_action("save_post_product",'woo_save_bookable_data', 10, 3);
if(!function_exists('woo_save_bookable_data')):
function woo_save_bookable_data($post_ID, $product, $update)
{
$meta_value = $_POST["_bookable"];
if(isset($meta_value))
{
$meta_value = 'yes';
update_post_meta( $product->ID, "_bookable" ,$meta_value );
wp_set_object_terms( $product->ID, 'Bookable', 'product_tag' );
}
else
{
delete_post_meta($product->ID, "_bookable");
wp_remove_object_terms( $product->ID, 'Bookable', 'product_tag' );
}
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
add_action('woocommerce_add_order_item_meta','woo_bookable_add_order_meta', 9, 3 );
if(!function_exists('woo_bookable_add_order_meta')):
function woo_bookable_add_order_meta( $item_id, $item_values, $item_key )
{
if( ! empty( $item_values['_bookable'] ) )
wc_update_order_item_meta( $item_id, '_bookable', sanitize_text_field( $item_values['_bookable'] ) );
}
endif;
/////////////////////////////////////////////////////////////////////////////////////////////////
}
else
{
add_action( 'admin_notices', 'woo_bookable_active' );
if(!function_exists('woo_bookable_active')):
function woo_bookable_active()
{
$err_text = site_url()."/wp-admin/plugin-install.php?tab=plugin-information&plugin=woocommerce&TB_iframe=true";
?>
<div class="error notice">
<p><?php echo sprintf("Please Activate or <a href='%s'>Install Woocommerce</a> to use Bookable plugin",$err_text); ?></p>
</div>
<?php
//If woocommerce is not installed deactive plugin
if (is_plugin_active('bookable/bookable.php')) {
deactivate_plugins(plugin_basename(__FILE__));
}
unset($_GET['activate']);
}
endif;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
add_action('wp_enqueue_scripts','woo_bookable_scripts');
function woo_bookable_scripts()
{
wp_enqueue_script('load_book', plugin_dir_url( __FILE__ ).'js/load_book.js',array('jquery'));
wp_localize_script('load_book','ajax_object',array('ajax_url'=>admin_url('admin-ajax.php')));
}
/////////////////////////////////////////////////////////////////////////////////////////////////
add_shortcode('bookable','woo_bookable_shortcode');
function woo_bookable_shortcode()
{
global $product;
$Data = '';
$query = new WP_Query(array(
'post_type' => 'product',
'meta_key' => '_bookable',
'meta_value' => 'yes'
) );
$Data.='<select name="woo_book_id" class="woo_book_pro">
<option value="0">Bookable Products</option>';
if($query->have_posts()):while($query->have_posts()):$query->the_post();
$Data.='<option value="'. get_the_ID() .'">'. get_the_title() .'</option>';
endwhile;endif;
$Data.='</select>';
$Data.= woo_bookable_add_to_cart();
echo $Data;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
$InArray = array('woo_bookable_product_id','woo_bookable_add_to_cart');
foreach($InArray as $SingleValue)
{
add_action('wp_ajax_'.$SingleValue,$SingleValue);
add_action('wp_ajax_nopriv_'.$SingleValue,$SingleValue);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
function woo_bookable_product_id()
{
$product_id = $_POST['product_id'];
if($product_id != null && $product_id!=0)
{
$add['id'] = 'success';
$add['msg'] = 'View Cart';
WC()->cart->add_to_cart( $product_id);
}
else
{
$add['id'] = 'fail';
$add['msg'] = 'Please Select Product From DropDown!!';
}
echo json_encode($add);
die();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
function woo_bookable_add_to_cart()
{
return '<button type="submit" style="margin-left:10px" name="add-to-cart" value="" class="single_add_to_cart_button button alt">Add To Cart</button>
<div class="message"></div>';
die();
}
ajax Script:
jQuery(document).ready(function()
{
jQuery("select.woo_book_pro").change(function(e)
{
var id = jQuery('.woo_book_pro option:selected').val();
var action = 'woo_bookable_add_to_cart';
jQuery.ajax({
url:ajax_object.ajax_url,
type:"POST",
dataType:"json",
cache:false,
data:{
"action":action,
"id":id
},
success: function(data)
{
jQuery('.single_add_to_cart_button').attr('value',id);
jQuery('.single_add_to_cart_button').attr("disabled", "disabled");
jQuery('.single_add_to_cart_button').text('WAIT...');
setTimeout(function() {
jQuery('.single_add_to_cart_button').removeAttr("disabled");
jQuery('.single_add_to_cart_button').text('Add To Cart');
}, 3000);
}
});
});
jQuery(".single_add_to_cart_button").click(function(e) {
e.preventDefault();
var product_id = jQuery(this).val();
var action = 'woo_bookable_product_id';
jQuery('.message').empty();
jQuery.ajax({
url:ajax_object.ajax_url,
type:"POST",
dataType:"json",
cache:false,
data:{
"action":action,
"product_id":product_id
},
success: function(data)
{
if(data.id == 'success')
{
jQuery('.message').prepend(data.msg);
return false;
}
if(data.id == 'fail')
{
jQuery('.message').prepend(data.msg).css('color','#F33')
return false;
}
}
});
});
});
Attempting to integrate this nice tutorial from #dingo_d into a Woocommerce archive-product.php template. Here's what I've got so far:
archive-product.php
Added $cat_id under get_header
get_header( 'shop' );
$cat_id = get_query_var('cat');
Wrapped the loop with div
<main id="main" class="site-main ajax_posts" role="main">
<?php woocommerce_product_loop_start(); ?>
...
<?php woocommerce_product_loop_end(); ?>
</main><!-- /#main -->
pagination.php
the template file being overridden by my theme with the woocommerce pagination commented out
<div id="more_posts" data-category="<?php echo esc_attr($cat_id); ?>"><?php esc_html_e('Load More', 'siiimple') ?></div>
<!--<nav class="woocommerce-pagination">
<?php
echo paginate_links( apply_filters( 'woocommerce_pagination_args', array(
'base' => esc_url_raw( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) ),
'format' => '',
'add_args' => false,
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $wp_query->max_num_pages,
'prev_text' => '←',
'next_text' => '→',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3
) ) );
?>
</nav>-->
functions.js
( function( $ ) {
//LOAD MORE
var $content = $('.ajax_posts');
var $loader = $('#more_posts');
var cat = $loader.data('category');
var ppp = 3;
var offset = $('#main').find('.post').length;
$loader.on( 'click', load_ajax_posts );
function load_ajax_posts() {
if (!($loader.hasClass('post_loading_loader') ||
$loader.hasClass('post_no_more_posts'))) {
$.ajax({
type: 'POST',
dataType: 'html',
url: screenReaderText.ajaxurl,
data: {
'cat': cat,
'ppp': ppp,
'offset': offset,
'action': 'mytheme_more_post_ajax'
},
beforeSend : function () {
$loader.addClass('post_loading_loader').html('');
},
success: function (data) {
var $data = $(data);
if ($data.length) {
var $newElements = $data.css({ opacity: 0 });
$content.append($newElements);
$loader.removeClass('post_loading_loader');
$newElements.animate({ opacity: 1 });
$loader.removeClass('post_loading_loader').html(screenReaderText.loadmore);
} else {
$loader.removeClass('post_loading_loader').addClass('post_no_more_posts').html(screenReaderText.noposts);
}
},
error : function (jqXHR, textStatus, errorThrown) {
$loader.html($.parseJSON(jqXHR.responseText) + ' :: ' + textStatus + ' :: ' + errorThrown);
console.log(jqXHR);
},
});
}
offset += ppp;
return false;
}
//LOAD MORE
} )( jQuery );
functions.php
Placed at bottom of functions.php
// LOAD MORE
$ajaxurl = '';
if( in_array('sitepress-multilingual-cms/sitepress.php', get_option('active_plugins')) ){
$ajaxurl .= admin_url( 'admin-ajax.php?lang=' . ICL_LANGUAGE_CODE );
} else{
$ajaxurl .= admin_url( 'admin-ajax.php');
}
// END LOAD MORE
wp_localize_script( 'twentysixteen-script', 'screenReaderText', array(
'expand' => __( 'expand child menu', 'siiimple' ),
'collapse' => __( 'collapse child menu', 'siiimple' ),
//LOAD MORE
'ajaxurl' => $ajaxurl,
'noposts' => esc_html__('No older posts found', 'siiimple'),
'loadmore' => esc_html__('Load more', 'siiimple')
// END LOAD MORE
) );
//LOAD MORE
add_action('wp_ajax_nopriv_mytheme_more_post_ajax', 'mytheme_more_post_ajax');
add_action('wp_ajax_mytheme_more_post_ajax', 'mytheme_more_post_ajax');
if (!function_exists('mytheme_more_post_ajax')) {
function mytheme_more_post_ajax(){
$ppp = (isset($_POST['ppp'])) ? $_POST['ppp'] : 3;
$cat = (isset($_POST['cat'])) ? $_POST['cat'] : 0;
$offset = (isset($_POST['offset'])) ? $_POST['offset'] : 0;
$args = array(
'post_type' => 'product',
'posts_per_page' => $ppp,
'cat' => $cat,
'offset' => $offset,
);
$loop = new WP_Query($args);
$out = '';
if ($loop -> have_posts()) :
while ($loop -> have_posts()) :
$loop -> the_post();
$category_out = array();
$categories = get_the_category();
foreach ($categories as $category_one) {
$category_out[] ='' .$category_one->name.'';
}
$category_out = implode(', ', $category_out);
$cat_out = (!empty($categories)) ? '<span class="cat-links"><span class="screen-reader-text">'.esc_html__('Categories', 'twentysixteen').'</span>'.$category_out.'</span>' : '';
$out .= '<article id="post-'. get_the_ID().'" class="'. implode(' ', get_post_class()) .'">
<header class="entry-header">';
$out .= '<h2 class="entry-title">'.get_the_title().'</h2>';
$out .= '</header>'.
'</article>';
endwhile;
endif;
wp_reset_postdata();
wp_die($out);
}
}
//END LOAD MORE
That's it. Don't think I'm missing anything...Thanks!
I've created a wordpress plugin to vote on a post, using ajax.
When you click the 'vote' link the jquery popup works, your vote is added but then the page reloads
add_action("wp_ajax_my_user_vote", "my_user_vote");
add_action("wp_ajax_nopriv_my_user_vote", "my_must_login");
function my_user_vote() {
if ( !wp_verify_nonce( $_REQUEST['nonce'], "my_user_vote_nonce")) {
exit("No naughty business please");
}
$user_id = get_current_user_id();
date_default_timezone_set('GMT+2');
$dateVoted = get_user_meta($user_id, 'date');
$today = date('d M Y');
if ($dateVoted === $today){
//Already Voted
echo '<script language="javascript">';
echo 'alert("already voted")';
/*
echo 'alert("User ID: ' . $user_id . '")';
echo 'alert("Date Voted: ' . $dateVoted . '")';
echo 'alert("Today: ' . $today . '")';
*/
echo '</script>';
}else{
$vote_count = get_post_meta($_REQUEST["post_id"], "votes", true);
$vote_count = ($vote_count == '') ? 0 : $vote_count;
$new_vote_count = $vote_count + 1;
$vote = update_post_meta($_REQUEST["post_id"], "votes", $new_vote_count);
if($vote === false) {
$result['type'] = "error";
$result['vote_count'] = $vote_count;
}
else {
$result['type'] = "success";
$result['vote_count'] = $new_vote_count;
}
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$result = json_encode($result);
echo $result;
}
else {
header("Location: ".$_SERVER["HTTP_REFERER"]);
}
update_user_meta( $user_id, 'date', $today );
}
die();
}
function my_must_login() {
echo "You must log in to vote";
die();
}
add_action( 'init', 'my_script_enqueuer' );
function my_script_enqueuer() {
wp_register_script( "my_voter_script", WP_PLUGIN_URL.'/video-of-the- day/my_voter_script.js', array('jquery') );
wp_localize_script( 'my_voter_script', 'myAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' )));
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'my_voter_script' );
}
I also have a jquery file:
jQuery(document).ready( function() {
jQuery(".user_vote").click( function() {
post_id = jQuery(this).attr("data-post_id")
nonce = jQuery(this).attr("data-nonce")
jQuery.ajax({
type : "post",
dataType : "json",
url : myAjax.ajaxurl,
data : {action: "my_user_vote", post_id : post_id, nonce: nonce},
success: function(response) {
if(response.type == "success") {
}
else {
alert("Your vote could not be added")
}
}
});
})
});
why is the ajax not working?
Try this
jQuery(".user_vote").click( function(e) {
e.PreventDefault();
});