Avoiding Duplicate function names in Post Loop (WP_Footer script)

Say I created a plugin that injects content (used as a shortcode) into a post. I’m trying to push that code for each post to the bottom of the page.

This works fine, however when you are on an archive page with multiple posts using the same shortcode, there is an obvious conflict because the function names become duplicate and it will only output the footer code (activate_flex_slider) once.

Read More
<?php
function your_function() {
    echo '<p>This is inserted at the bottom</p>';
}
add_action('wp_footer', 'your_function');
?>

What i’m trying to do is output footer script so that there are multiple jQuery instances pointing to their respective ID’s…

<?php
    function flex_slider() {
        $output ='<ul class="flexslider"><li>Slide Content</li></ul>';
        return $output;
    }


    function activate_flex_slider(){
        ?>
    <script>
                ( function ($) {
             $(window).load(function(){

       //different number will be prepended to ID (matches post ID #)
      $('#carousel-<?php echo $post->ID ?>').flexslider();
    });
        })(jQuery);
    </script>
<?php
    }

    // Hook into footer so slider becomes active after page loads
    add_action('wp_footer','activate_flex_slider');

    // Create the Shortcode
    add_shortcode('flex_slider', 'flex_slider');
    ?>

Related posts

Leave a Reply

2 comments

  1. I would wrap the whole thing in a class and put your data into a class var.

    class WPA69616_Plugin {
        private $data = '';
    
        public function __construct() {
            add_shortcode('my_shortcode', array($this, 'add_content'));
            add_action('wp_footer', array($this, 'output_content'));
        }
    
        public function add_content($atts) {
            extract( shortcode_atts( array(
                'content' => ''
            ), $atts ) );
            $this->data .= $content;
        }
    
        public function output_content() {
            echo $this->data;
        }
    }
    $wpa69616_plugin = new WPA69616_Plugin();  
    
  2. I’ve used Flexslider before and still had a plugin for shortcodes lying around. It’s a bit dusty, but I’ve uploaded it to my dev install now that I came across this question and it still works (and does so with multiple sliders on the same page), so here’s the main plugin file’s contents:

    Flexslider with WP Shortcodes

    /**
     * Holds the URL
     *
     * @since 1.0
     */
    if ( ! defined( 'WPSE69616_RELPATH' ) )
        define( 'WPSE69616_RELPATH', plugin_dir_url( __FILE__ ) );
    
    if ( ! class_exists( 'WPSE69616_SLIDER' ) ) :
    class WPSE69616_SLIDER {
    
        /**
         * Scripts & Styles
         *
         * @since 1.0
         */
        public function init() {
            /* default flexslider stylesheet */
            wp_register_style( 'wpse69616-default', WPFS_RELPATH . 'css/flexslider.css', false, '1.8' );
            /* few fixes for WP */
            wp_register_style( 'wpse69616-fixes', WPFS_RELPATH . 'css/fixes.css', false, '1.0' );
            /* the actual slider */
            wp_register_script( 'wpse69616-flexslider', WPFS_RELPATH . 'js/jquery.flexslider-min.js', array('jquery'), '1.8', true );
            /* slider initialization */
            wp_register_script( 'wpse69616-flex-init', WPFS_RELPATH . 'js/initialization.js', array('wpse69616-flexslider'), '1.0', true );
        }
    
        /**
         * Slider Shortcodes
         *
         * @since 1.0
         */
        public function slider( $atts, $content='' ) {
            wp_enqueue_style( 'wpse69616-default' );
            wp_enqueue_style( 'wpse69616-fixes' );
            wp_enqueue_script( 'wpse69616-flexslider' );
            wp_enqueue_script( 'wpse69616-flex-init' );
            extract( shortcode_atts( array(
                'id' => ''
            ), $atts ) );
            $id = ! empty( $id ) ? ' id="' . $id . '"' : '';
            $content = do_shortcode( $content );
    
            return '<div' . $id . ' class="flexslider">' .
                    '<ul class="slides">' . $content . '</ul>' .
                '</div>';
        }
        public function slide( $atts, $content='' ) {
            $content = do_shortcode( $content );
            return '<li>' . $content . '</li>';
        }
    
        /**
         * Class Constructor
         *
         * @since 1.0
         */
        public function __construct() {
            add_action( 'wp_loaded', array( &$this, 'init' ) );
            add_shortcode( 'slide', array( &$this, 'slide' ) );
            add_shortcode( 'flexslider', array( &$this, 'slider' ) );
        }
    
    } // class
    endif; // class exists
    
    $wpse69616_slider = new WPSE69616_SLIDER();
    

    In this plugin I initialize all the sliders with the same properties, so for the initialization.js above

    jQuery(window).load(function() {
        jQuery('.flexslider').flexslider( {
            slideshow: false,
            controlNav: true,
            prevText: "<",
            nextText: ">",
        });
    });
    

    will suffice.

    Note that you only need multiple jQuery functions if you want to use the slider with different properties each time. Otherwise you can target all of them by using a class as a selector (as is done above).

    Varying Properties

    If you must have varying properties, this is how that’d be done (I will assume you have an array of properties from somewhere – postmeta, options, whatever). The array would look like this:

    $slider_properties = array(
        array(
            'id' => 53 // some post ID
            'slideshow' => 'false',
            'controlNav' => 'true'
        ),
        array(
            'id' => 101 // some post ID
            'slideshow' => 'true',
            'controlNav' => 'false'
        )
    );
    

    And then you could add

    wp_localize_script( 'wpse69616-flex-init', 'wpseSlider', $slider_properties );
    

    to the main plugin class and as for the js do

    (function($) {
        $(window).load(function() {
            for( var i=0; i<wpseSlider.length; i++ ) {
                $( '#carousel-' + wpseSlider[i].id ).flexslider( {
                    slideshow: wpseSlider[i].slideshow,
                    controlNav: wpseSlider[i].controlNav,
                    prevText: "<",
                    nextText: ">",
                });
            }
        });
    })(jQuery);
    

    And with that you’d have multiple instances of the slider, each with it’s own set of arguments.