I want to add a style tag to the head section according to shortcode parameters. I wrote a function for styles and want to call its add_action in a shortcode function.
However, the style is not added in the head. If I call add_action outside of the function, it works successfully.
Please let me know how I can call the statement "add_action" inside a php function, and how I can send parameters to a function to call add_action.
This is my code:
function ag_appearance( $year ){
?>
<style type="text/css">
/*Some style here*/
</style>
<?php
}
add_action( 'wp_head', 'ag_appearance' ); /* this is working */
function dp_agenda( $atts, $content = null ){
extract( shortcode_atts( array(
'year' => '',
'day' => '',
'summit' => '',
'complexity' => '',
'certification' => '',
'event' => '',
'make' => ''
), $atts ) );
add_action( 'wp_head', 'ag_appearance' );
/* this is not working, while i want to call here by $year parameter */
}
I would suggest creating a CSS file containing the style you want to add to the header (appearance.css for example) and placing that in the theme folder so you know where it is (I usually use /css for styles). Then use wp_enqueue_style to set the style in the header when the containing function is called. Sort of like this:
function dp_agenda( $atts, $content = null ){
extract( shortcode_atts( array(
'year' => '',
'day' => '',
'summit' => '',
'complexity' => '',
'certification' => '',
'event' => '',
'make' => ''
), $atts ) );
wp_enqueue_style('appearance',get_stylesheet_directory_uri().'/css/appearance.css');
/* this is not working, while i want to call here by $year parameter */
}
Enqueued styles in WordPress, by default, are placed in the head via wp_head() and scripts are placed wherever you have wp_footer() placed, usually before the </body> tag.
You can also use wp_enqueue_script to pull your javascript files.
Related
*Context
I am new to WordPress plugin development and I have just started developing one. Which is basically a blog slider plugin. The concept is very simple. The user can use shortcodes with parameters to determine which posts and how many posts to be shown. There is no admin settings page for changing the appearance of the slider though, but I'll work on that. The user have to use shortcode whenever the slider is needed.
The development part is also simple. I am checking the parameters that the user passes through the shortcode. And then a query runs and returns an array of posts and then displays the structure. Very simple.
*Problem
Now I am trying to make the plugin options more dynamic (via shortcode) i.e. the user can control whether the slider should auto-play or not, loop should be enabled or not, pause on hover, dots/nav hide or show etc. I am using owl carousel for this slider. So that means I have to change the attributes of the slider in JavaScript file.
The basic idea is to take the parameters from function's $atts array, and pass it to the JavaScript file. I know this can be accomplished using wp_localize_script, but I cannot figure out how.
Here is my code to make things more clear.
mainfile.php
add_shortcode( 'sp-slider', 'sp_slider_get_posts');
function sp_slider_get_posts( $atts ) {
$values = shortcode_atts( array(
'number' => '-1',
'category-id' => '', //DEFAULT VALUE null, WILL BE REPLACED ONCE USER DECLARES IN SHORTCODE
'category-name' => '',
'orderby' => '',
'order' => '',
'include-posts' => '',
'exclude-posts' => '',
'author-id' => '',
'author-name' => '',
'autoplay' => ''
), $atts );
if( !empty($values['number']) ||
!empty($values['category-id']) ||
!empty($values['category-name']) ||
!empty($values['orderby']) ||
!empty($values['order']) ||
!empty($values['include-posts']) ||
!empty($values['exclude-posts']) ||
!empty($values['author-id']) ||
!empty($values['author-name']) ||
!empty($values['autoplay'])) {
$args = array(
'numberposts' => $values['number'],
'cat' => $values['category-id'],
'category_name' => $values['category-name'],
'orderby' => $values['orderby'],
'order' => $values['order'],
'include' => $values['include-posts'],
'exclude' => $values['exclude-posts'],
'meta_key' => '',
'meta_value' => '',
'post_parent' => '',
'author' => $values['author-id'],
'author_name' => $values['author-name'],
'post_status' => 'publish',
'suppress_filters' => true,
'fields' => '',
);
$autoplay = $values['autoplay']; //GET AUTOPLAY VALUE. NO IDEA HOW TO USE IT. SO I TRIED THE FOLLOWING
// THE FOLLOWING FUNCTION HOLDS THE wp_localize_script FUNCTION, WHICH IS DECLARED AT THE END OF THIS CURRENT FUNCTION sp_slider_get_posts.
sp_carousel_settings($autoplay); //PASSING THE USER INPUT
$posts_array = get_posts( $args );
if( !empty( $posts_array ) ) {
$output = "<div class='sp-slider-wrapper'>";
$output .= '<div class="owl-carousel owl-theme">';
foreach( $posts_array as $post ) {
include( "includes/inc_slider_section.php"); // ALL THE SLIDER STRUCTURE IS IN DIFFERENT FILE WHICH IS INCLUDED HERE
}
$output .="</div>";
$output .="</div>";
}
return $output;
}
}
// HERE IS sp_carousel_settings() DECLARATION
function sp_carousel_settings( $autoplay ) {
$carousel_settings = array( 'autoplay' => $autoplay);
wp_localize_script( 'sp_main_js', 'carousel_settings', $carousel_settings );
}
add_action( 'wp_enqueue_scripts', 'sp_carousel_settings' );
mainjs.js
$(document).ready(function() {
...
...
var autoplay= '';
if(typeof carousel_settings !== 'undefined') {
autoplay = carousel_settings.autoplay;
}
else {
autoplay = false;
}
$('.owl-carousel').owlCarousel({
loop:true,
autoplay:autoplay,
autoplayTimeout:2000,
autoplayHoverPause:true,
...
...
}
})
This doesn't work. Here I would like to mention that, in add_action() function, if i put wp_footer instead of wp_enqueue_scripts, it adds the script to the footer of the page (I have checked it by viewing the source) but the autoplay value is null.
Another thing i would mention is that, in sp_carousel_settings() function, instead of passing the $autoplay variable, if I write any static value like this $carousel_settings = array( 'autoplay' => true);, it works.
*I tried echoing out $autoplay inside sp_carousel_settings() and it prints the value! But does not get to the js file.
*I tried checking the value of $autoplay and pass a hardcore sting inside wp_localize_script like
function sp_carousel_settings( $autoplay ) {
if( $autoplay == "true" ) {
echo "Inside!!!";
$carousel_settings = array( 'autoplay' => true);
}
else {
echo "Outside!!!";
$carousel_settings = array( 'autoplay' => false);
}
wp_localize_script( 'sp_main_js', 'carousel_settings', $carousel_settings );
}
add_action( 'wp_footer', 'sp_carousel_settings' );
Does not work. EVEN it prints out "Inside!!!" but does not pass true in autoplay. The value is always false.
*I have registered the js file in the beginning of the plugin, where the plugin activates and gets initialized. Like this
function sp_slider_include_css_js() {
...
...
wp_register_script('sp_main_js', plugins_url('assets/js/main.js',__FILE__));
wp_enqueue_script('sp_main_js');
...
...
}
add_action( 'wp_footer','sp_slider_include_css_js');
*I have searched internet for help but was unable to find. Any reference will be appreciated.
*I know that I might be using the function in an improper way. I am clueless (and new to this).
Have to do some changes like,
Step 1:
function sp_carousel_settings() {
wp_register_script( 'sp_main_js', 'you/file/path/here', array( 'jquery' ), '1.0', true);
}
add_action( 'wp_enqueue_scripts', 'sp_carousel_settings' );
Step 2:
add_shortcode( 'sp-slider', 'sp_slider_get_posts');
function sp_slider_get_posts( $atts ) {
.....
$carousel_settings = array( 'autoplay' => $autoplay);
wp_localize_script( 'sp_main_js', 'carousel_settings', $carousel_settings );
wp_enqueue_script( 'sp_main_js' );
......
}
I've built an ACF block. As per the documentation, I've created the following via functions.php:
<?php
/**
* Register ACF Blocks
*/
add_action('acf/init', 'my_acf_init');
function my_acf_init() {
// check function exists
if( function_exists('acf_register_block') ) {
// Gallery block
acf_register_block(array(
'name' => 'gallery',
'title' => __('Gallery'),
'description' => __('A custom gallery block.'),
'render_callback' => 'my_acf_block_render_callback',
'category' => 'formatting',
'icon' => 'format-gallery',
'keywords' => array( 'gallery' ),
'enqueue_assets' => function() {
wp_enqueue_style( 'fancybox-style' );
wp_enqueue_script( 'fancybox-js', get_template_directory_uri() . '/js/fancybox/jquery.fancybox.min.js', array('jquery'), '1.0', true );
}
));
}
}
The 'enqueue_assets' function allows me to enqueue styles and scripts if the block is loaded.
The script loads in the footer as intended. However, the styles also load in the footer.
I've tried registering the style via functions and then enqueing it in the block, but it still loads in the footer. Here's how I'm registering the style.
wp_register_style( 'fancybox-style', get_template_directory_uri() . '/js/fancybox/jquery.fancybox.min.css');
Is there a way within WordPress to force styles to load in the header?
I am adding load more comments button in comments section. i want load function wp_list_comments using Ajax, function are loading but wp_list_comment not display in wordpress 4.3.16 version. How to solve this problem???
My code are is:
// maybe it isn't the best way to declare global $post variable, but it is simple and works perfectly!
add_action('wp_ajax_cloadmore', 'misha_comments_loadmore_handler');
add_action('wp_ajax_nopriv_cloadmore', 'misha_comments_loadmore_handler');
function misha_comments_loadmore_handler(){
global $post;
$post = get_post( $_POST['post_id'] );
setup_postdata( $post );
// actually we must copy the params from wp_list_comments() used in our theme
wp_list_comments( array(
'page' => $_POST['cpage'], // current comment page
'per_page' => get_option('comments_per_page'),
'style' => '<div>', // comments won't wrapped in this tag and it is awesome!
'short_ping' => true,
) );
die; // don't forget this thing if you don't want "0" to be displayed
}
Try this code.
add_action('wp_ajax_cloadmore', 'misha_comments_loadmore_handler');
add_action('wp_ajax_nopriv_cloadmore', 'misha_comments_loadmore_handler');
function misha_comments_loadmore_handler(){
$comments = get_comments(array(
'post_id' => $_POST['post_id'],
'status' => 'approve'
));
wp_list_comments(array(
'page' => $_POST['cpage'], // current comment page
'per_page' => get_option('comments_per_page'),
'style' => '<div>', // comments won't wrapped in this tag and it is awesome!
'short_ping' => true,
), $comments);
die; // don't forget this thing if you don't want "0" to be displayed
}
I am developing a child theme for the Storefront Theme. I use the Product Category Widget as a dropdown under the header which fits my needs perfectly, though I need the same (if possible) dropdown menu to show up on every Category Page, instead of just the Main Page.
I am customizing this code which almost does it:
/**
* WooCommerce Extra Feature
* --------------------------
*
* Register a shortcode that creates a product categories dropdown list
*
* Use: [product_categories_dropdown orderby="title" count="0" hierarchical="0"]
*/
add_shortcode( 'product_categories_dropdown', 'woo_product_categories_dropdown' );
function woo_product_categories_dropdown( $atts ) {
extract( shortcode_atts(array(
'count' => '0',
'hierarchical' => '0',
'orderby' => ''
), $atts ) );
ob_start();
// Stuck with this until a fix for http://core.trac.wordpress.org/ticket/13258
wc_product_dropdown_categories( array(
'orderby' => ! empty( $orderby ) ? $orderby : 'order',
'hierarchical' => $hierarchical,
'show_uncategorized' => 0,
'show_counts' => $count
) );
?>
<script type='text/javascript'>
/* <![CDATA[ */
jQuery(function(){
var product_cat_dropdown = jQuery(".dropdown_product_cat");
function onProductCatChange() {
if ( product_cat_dropdown.val() !=='' ) {
location.href = "<?php echo esc_url( home_url() ); ?>/?product_cat=" +product_cat_dropdown.val();
}
}
product_cat_dropdown.change( onProductCatChange );
});
/* ]]> */
</script>
<?php
return ob_get_clean();
}
Now I need to hide the counters and show the empty Categories.
I haven't be able to get that.
How can I hide the counters and show the empty Categories?
In your code there was:
some mistakes in the code like wrong 'show_counts' that is 'show_count' (without s) … Now hiding counters is enabled and functional.
missing argument 'hide_empty' to show empty categories
In this shortcode you can alter the following optional arguments:
hierarchical that is disabled by default (set to '0')
hide_empty that is disabled by default (set to '0')
show_count that is now disabled by default (set to '0')
depth that is disabled by default (set to '0')
orderby set to category "order" by default (can be by names too: "name")
Added a custom hook woocommerce_product_categories_shortcode_dropdown_args that will allow extended customizations…
Here is the new code:
add_shortcode( 'product_categories_dropdown', 'woo_product_categories_dropdown' );
function woo_product_categories_dropdown( $atts ) {
// Attributes
$atts = shortcode_atts( array(
'hierarchical' => '0', // or '1'
'hide_empty' => '0', // or '1'
'show_count' => '0', // or '1'
'depth' => '0', // or Any integer number to define depth
'orderby' => 'order', // or 'name'
), $atts, 'product_categories_dropdown' );
ob_start();
wc_product_dropdown_categories( apply_filters( 'woocommerce_product_categories_shortcode_dropdown_args', array(
'depth' => $atts['depth'],
'hierarchical' => $atts['hierarchical'],
'hide_empty' => $atts['hide_empty'],
'orderby' => $atts['orderby'],
'show_uncategorized' => 0,
'show_count' => $atts['show_count'],
) ) );
?>
<script type='text/javascript'>
jQuery(function($){
var product_cat_dropdown = $(".dropdown_product_cat");
function onProductCatChange() {
if ( product_cat_dropdown.val() !=='' ) {
location.href = "<?php echo esc_url( home_url() ); ?>/?product_cat=" +product_cat_dropdown.val();
}
}
product_cat_dropdown.change( onProductCatChange );
});
</script>
<?php
return ob_get_clean();
}
Code goes in function.php file of the active child theme (or active theme).
Tested and works.
1) Example usage - All product categories and subcategories hierarchically displayed:
[product_categories_dropdown orderby='name' hierarchical='1']
In php code you can use it this way:
echo do_shortcode("[product_categories_dropdown orderby='name' hierarchical='1']");
or inserted in html tags:
<?php echo do_shortcode("[product_categories_dropdown orderby='name' hierarchical='1']"); ?>
2) Example usage - Only "main parent" product categories:
[product_categories_dropdown depth='1' hierarchical='1']
In php code you can use it this way:
echo do_shortcode("[product_categories_dropdown depth='1' hierarchical='1']");
or inserted in html tags:
<?php echo do_shortcode("[product_categories_dropdown depth='1' hierarchical='1']"); ?>
This is how it is displayed by default, for this it is not necessary to add more code.
Theirs would be that the products were grouped to the category of products that belong, and that it had a drop-down for each category of products, instead of a single one.
example:
Cars (dropdown)
Audi
Merdeces
BMW
Motorbike (dropdown)
Honda
Yamaha
Ducati
I was wondering if possible to setup a shortcode and have the name of the shortcode also work as an attribute. How I have mine currently setup is like so
add_shortcode('tooltip', 'tooltip');
function tooltip( $atts $content = null) {
array(
'type' => '',
);
So when someone in wordpress uses the shortcode you type in
[tooltip type="fruit"]Item Name[/tooltip]
Although I was wondering is it possible to just use the name of the shortcode as a atts so I can short it a little bit and have it look like this
[tooltip="fruit"]Item Name[/tooltip]
So pretty much cut out the type attribute and use the name of the shortcode tooltip as an attribute instead.
Nope, what you're proposing isn't possible. It may be shorter but in my opinion it would be confusing so I don't see it ever being something that's made possible short of you building the functionality yourself.
You have to use first item in $atts array, ($atts[0]) when using shortcode tag as attribute.
Working example:
<?php
add_shortcode('tooltip', 'tooltip');
function tooltip(Array $atts = array(), $content = null, $tag = null) {
$args = shortcode_atts(array( 0 => null ), $atts);
$args['type'] = trim($args[0], '"=');
unset($args[0]);
extract($args);
// Your code starts here ...
$output = array(
'$type' => $type,
'$content' => $content
);
$output = '<pre>' . print_r($output, true) . '</pre>';
return $output;
}
Please replace everything after // Your code starts here ...
Executing example:
[tooltip="fruit"]Item Name[/tooltip]
will return:
<pre>Array
(
[$type] => fruit
[$content] => Item Name
)
</pre>