0

When my site loads single posts, some Facebook buttons (share, save, like) with the associated statistics are displayed in three different places: at the top and at the bottom for posts and in the sidebar for the site. I think, this is slowing the site load, so, the question is how to load these buttons and the associated statistics only once (in a variable), then to display them in several places?

I know about the W3 Total Cache and other similar plugins, but how about other ways? Maybe with some PHP code?

2
  • Is the markup the same in the 3 instances? Commented Nov 8, 2017 at 13:46
  • just added a new version with a better browser support. Commented Nov 15, 2017 at 17:30

1 Answer 1

1

lurie. I would use vanilla Javascript in the front end. This way, you don't need to invalidate any server cache. Here is a untested solution.

The Javascript File - using ES6 features and forEach polyfill

In your main javascript file:

'use strict';

/**
 * @summary Clones social buttons and insert them elsewhere
 *
 * Clones social buttons and insert them elsewhere in the DOM after the window.load event.
 * Can be used to clone anything else, in fact.
 *
 * @listens window.load
 *
 * @param string $sourceSelector a CSS3 element selector for the element to be cloned
 * @param array $wrappersSelectors an array of CSS3 element selectors to append the cloned elements
 * @returns voide
 */
function cloneSocialButtonsES6( sourceSelector = '', wrappersSelectors = [] ) {
    // get the source element
    var originalButtons = document.querySelector( sourceSelector );
    // if wrappersSelectors is empty or not-provided, bail and logs to console
    if ( wrappersSelectors.length === 0) {
        console.error('wrappersSelectors must be a non-empty array of CSS3 selectors');
        return;
    }
    // for each item in wrappersSelectors array, clones the source element
    wrappersSelectors.forEach( function( wrapper ){
        // get the wrapper element in the DOM
        var wrapper = document.querySelector( wrapper );
        // for each wrapper in the array, clones the source element and appends it to wrapper
        var clone = originalButtons.cloneNode( true );
        wrapper.appendChild(clone);
    });
}

// lazy load cloneSocialButtons on window.load event
if ( window.addEventListener ) {
    window.addEventListener('load', cloneSocialButtons, false);
}
else if (window.attachEvent) {
    window.attachEvent("onload", cloneSocialButtons);
}
else {
    window.onload = cloneSocialButtons;
};

This version makes use of certain ES6 features like forEach method for arrays and default value for function arguments. It's cleaner, but has less browser support.

I recommend you to use a service like Polyfill.io or to use Chris Ferdinandi's Array.forEach polyfill as suggested in his Pocket Guides You could use in a separate file with all utilities and polyfills you might need.

/**
 * Array.prototype.forEach() polyfill
 * @author Chris Ferdinandi
 * @license MIT
 */
if (window.Array && !Array.prototype.forEach) {
    Array.prototype.forEach = function (callback, thisArg) {
        thisArg = thisArg || window;
        for (var i = 0; i < this.length; i++) {
            callback.call(thisArg, this[i], i, this);
        }
    };
}

The Javascript File - Without forEach polyfill

Better browser support, but much more verbose;

'use strict';

/**
 * @summary Clones social buttons and insert them elsewhere
 *
 * Clones social buttons and insert them elsewhere in the DOM after the window.load event.
 * Can be used to clone anything else, in fact.
 *
 * @listens window.load
 *
 * @param string $sourceSelector a CSS3 element selector for the element to be cloned
 * @param array $wrappersSelectors an array of CSS3 element selectors to append the cloned elements
 * @returns voide
 */
function cloneSocialButtons( sourceSelector, wrappersSelectors ) {
    sourceSelector = sourceSelector || '';
    wrappersSelectors = wrappersSelectors || [];
    // get the source element
    var originalButtons = document.querySelector( sourceSelector );
    // if wrappersSelectors is empty or not-provided, bail and logs to console
    var wrappersLength = wrappersSelectors.length;
    if ( wrappersLength === 0) {
        console.error('wrappersSelectors must be a non-empty array of CSS3 selectors');
        return;
    }
    // for each item in wrappersSelectors array, clones the source element
    for (var i = 0; i < wrappersLength; i++) {
       // get the wrapper element in the DOM
       var wrapper = document.querySelector( wrappersSelectors[i] );
       // for each wrapper in the array, clones the source element and appends it to wrapper
       var clone = originalButtons.cloneNode( true );
       wrapper.appendChild(clone);
    }


}

// lazy load cloneSocialButtons on window.load event
if ( window.addEventListener ) {
    window.addEventListener('load', cloneSocialButtons, false);
}
else if (window.attachEvent) {
    window.attachEvent("onload", cloneSocialButtons);
}
else {
    window.onload = cloneSocialButtons;
};

The PHP Function

Placed in functions.php or in a site specific plugin.

function wpse_285324_social_scripts() {
    wp_register_script( 'wpse_285324_social_buttons_cloner', $path_to_the_javascript_script, array(''), '0.1.0', true);
    wp_register_script( 'wpse_285324_social_buttons_cloner');

};
add_action('wp_enqueue_scripts', 'wpse_285324_social_scripts');

Important note

I think it's a good starting point for you.

Let me know if it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.