Duffer Derek
/**
*
* Social Warfare - The Javascript
*
* @since 1.0.0 | 01 JAN 2016 | Created
* @since 3.4.0 | 19 OCT 2018 | Cleaned, Refactored, Simplified, Docblocked.
* @since 3.6.0 | 22 APR 2019 | Removed Facebook share counts. These are now
* fetched via PHP on the server side just like all
* other social networks.
* @package SocialWarfare\Assets\JS\
* @copyright Copyright (c) 2018, Warfare Plugins, LLC
* @license GPL-3.0+
*
*
* This is the primary javascript file used by the Social Warfare plugin. It is
* loaded both on the frontend and the backend. It is used to control all client
* side manipulation of the HTML.
*
*
* Table of Contents:
*
* #1. Initialization Functions
* Property: socialWarfare.paddingTop
* Property: socialWarfare.paddingBottom
* Function: socialWarfare.initPlugin()
* Function: socialWarfare.establishPanels()
*
* #2. Static Horizontal Button Panel Controls
* Function: socialWarfare.activateHoverStates()
* Function: socialWarfare.resetStaticPanel()
* Function: socialWarfare.handleButtonClicks()
*
* #3. Floating Buttons Panel Controls
* Function: socialWarfare.createFloatHorizontalPanel()
* Function: socialWarfare.staticPanelIsVisible()
* Function: socialWarfare.updateFloatingButtons()
* Function: socialWarfare.toggleMobileButtons()
* Function: socialWarfare.toggleFloatingVerticalPanel()
* Function: socialWarfare.toggleFloatingHorizontalPanel()
* Function: socialWarfare.positionFloatSidePanel()
*
* #4. Pinterest Image Hover Save Buttons
* Function: socialWarfare.enablePinterestSaveButtons()
* Function: socialWarfare.renderPinterestSaveButton()
* Function: socialWarfare.findPinterestBrowserSaveButtons()
* Function: socialWarfare.removePinterestBrowserSaveButtons()
*
* #5. Facebook Share Count Functions
* Function: socialWarfare.fetchFacebookShares()
* Function: socialWarfare.parseFacebookShares()
*
* #6. Utility/Helper Functions
* Function: socialWarfare.throttle()
* Function: socialWarfare.trigger()
* Function: socialWarfare.trackClick()
* Function: socialWarfare.checkListeners()
* Function: socialWarfare.establishBreakpoint()
* Function: socialWarfare.isMobile()
*
*
* Javascript variables created on the server:
*
* bool swpClickTracking (SWP_Script.php)
* bool socialWarfare.floatBeforeContent
* object swpPinIt
* string swp_admin_ajax
* string swp_post_url
* string swp_post_recovery_url
*
*/
/**
* The first thing we want to do is to declare our socialWarfare object. We are
* going to use this object to store all functions that our plugin uses. This will
* allow us to avoid any naming collisions as well as allowing us to keep things
* more neatly organized.
*
*/
window.socialWarfare = window.socialWarfare || {};
/**
* This allows us to scope all variables and functions to within this anonymous
* function. However, since we are using a global object, socialWarfare, we will
* still be able to access our functions and variables from anywhere.
*
*/
(function(window, $) {
'use strict';
if ( typeof $ != 'function' ) {
if ( typeof jQuery == 'function' ) {
var $ = jQuery;
}
else {
console.log("Social Warfare requires jQuery, or $ as an alias of jQuery. Please make sure your theme provides access to jQuery before activating Social Warfare.");
return;
}
}
/**
* Values from the server may be sent as strings, but may also be empty.
* In this context, we are interested in strings with length only.
*/
function isString(maybeString) {
return typeof maybeString == 'string' && maybeString.length > 0;
}
/***************************************************************************
*
*
* SECTION #1: INITIALIZATION FUNCTIONS
*
*
***************************************************************************/
/**
* These variables measure the amount of padding at the top and bottom of
* the page upon the dom loaded event. We grab these early on and keep them
* stored so that we can add 50 pixels of padding whenever the floating
* horizontal buttons are displayed. This will allow us to avoid having our
* buttons hover over menus or copyright information in the footer.
*
*/
socialWarfare.paddingTop = parseInt($('body').css('padding-top'));
socialWarfare.paddingBottom = parseInt($('body').css('padding-bottom'));
/**
* Initializes the buttons provided that they exist.
*
* This function will activate the hover effects for the buttons, it will
* create the floting buttons, center vertically the side panel, handle
* and set up the button clicks, and monitor the scroll activity in order to
* show and hide any floating buttons.
*
* @param void
* @return void
*
*/
socialWarfare.initPlugin = function() {
$("body").css({
paddingTop: socialWarfare.paddingTop,
paddingBottom: socialWarfare.paddingBottom
});
socialWarfare.establishPanels();
socialWarfare.establishBreakpoint();
// Bail out if no buttons panels exist.
if (!socialWarfare.panels.staticHorizontal && !socialWarfare.panels.floatingSide && !socialWarfare.panels.floatingHorizontal) {
return;
}
socialWarfare.emphasizeButtons();
socialWarfare.createFloatHorizontalPanel();
socialWarfare.positionFloatSidePanel();
socialWarfare.activateHoverStates();
socialWarfare.handleButtonClicks();
socialWarfare.updateFloatingButtons();
socialWarfare.closeLightboxOverlay();
socialWarfare.preloadPinterestImages();
if (typeof swpPinIt == 'object' && swpPinIt.enabled == true) {
socialWarfare.createHoverSaveButton();
socialWarfare.triggerImageListeners();
}
/**
* In some instances, the click bindings were not being instantiated
* properly when they were run as the DOM was loaded. So we built this
* checkListeners() function to recheck every 2 seconds, 5 total times, to
* ensure that the buttons panel exist and activate the click bindings.
*
*/
setTimeout(function() {
socialWarfare.checkListeners(0, 5)
}, 2000);
/**
* This will allow us to monitor whether or not the static horizontal
* buttons are inside the viewport as a user is scrolling the page. If
* they are not in the viewport, we will display the floating buttons.
* The throttle is to prevent it from firing non stop and causing the
* floating buttons to flicker.
*
*/
var time = Date.now();
var scrollDelay = 50;
$(window).scroll(function() {
if ((time + scrollDelay - Date.now()) < 0) {
socialWarfare.updateFloatingButtons();
time = Date.now();
}
});
}
/**
* This will cause our resize event to wait until the user is fully done
* resizing the window prior to resetting and rebuilding the buttons and
* their positioning and re-initializing the plugin JS functions.
*
*/
var resizeWait;
socialWarfare.onWindowResize = function(){
clearTimeout(resizeWait);
resizeWait = setTimeout(socialWarfare.initPlugin, 100 );
}
/**
* Finds each kind of buttons panel, if it exists, and stores it to the
* socialWarfare object for later reference. This is useful for reading data
* attributes of buttons panels without needing to fetch the panel every time.
*
* @return object The object which holds each of the kinds of buttons panels.
*/
socialWarfare.establishPanels = function() {
//* Initialize the panels object with the three known panel types.
socialWarfare.panels = {
staticHorizontal: null,
floatingSide: null,
floatingHorizontal: null
};
// Set each type of panel as a jQuery object (with 0 or more panels)
socialWarfare.panels.staticHorizontal = $(".swp_social_panel").not(".swp_social_panelSide");
socialWarfare.panels.floatingSide = $(".swp_social_panelSide");
return socialWarfare.panels;
}
/**
* A function to emphasize the first couple of buttons in the panel.
*
* @since 4.0.0 | 14 JUL 2019 | Created
* @param void
* @return void
*
*/
socialWarfare.emphasizeButtons = function() {
/**
* If the variable that was passed from the server with the setting
* isn't set, then bail early. Gracefully fail.
*
*/
if (typeof socialWarfare.variables.emphasizeIcons == 'undefined') {
return;
}
/**
* Don't use this feature on mobile. This is a desktop only feature.
*
*/
if (socialWarfare.isMobile()) {
return;
}
/**
* Loop through each buttons panel on the page. Within each panel, we'll
* loop through each of the buttons and emphasize them.
*
*/
jQuery(".swp_social_panel:not(.swp_social_panelSide)").each(function(i, panel){
jQuery(panel).find(".nc_tweetContainer:not(.total_shares)").each( function(index, button) {
if( index < socialWarfare.variables.emphasizeIcons) {
var shareWidth = jQuery(button).find(".swp_share").width();
var iconWidth = jQuery(button).find("i.sw").outerWidth();
var iconTextWidth = shareWidth + iconWidth + 35;
var containerWidth = jQuery(button).width();
var change = 1 + ((shareWidth + 35) / containerWidth);
if(change < 2) {
jQuery(button)
.addClass("swp_nohover")
.css({'flex': '2 1 0%'})
.find('.iconFiller')
.width(iconTextWidth);
} else {
jQuery(button)
.addClass("swp_nohover")
.css({'flex': change + ' 1 0%'})
.find('.iconFiller')
.width(iconTextWidth);
}
}
});
});
}
/***************************************************************************
*
*
* SECTION #2: STATIC HORIZONTAL BUTTON PANEL CONTROLS
*
*
***************************************************************************/
/**
* This triggers the hover effect that you see when you hover over the
* buttons in the panel. It measures the space needed to expand the button
* to reveal the call to action for that network and then uses flex to
* expand it and to shrink the other buttons to make room for the expansion.
*
* @since 2.1.0
* @param void
* @return void
*
*/
socialWarfare.activateHoverStates = function() {
socialWarfare.trigger('pre_activate_buttons');
$('.swp_social_panel:not(.swp_social_panelSide) .nc_tweetContainer').on('mouseenter', function() {
if ($(this).hasClass('swp_nohover')) {
return;
}
socialWarfare.resetStaticPanel();
var termWidth = $(this).find('.swp_share').outerWidth();
var iconWidth = $(this).find('i.sw').outerWidth();
var containerWidth = $(this).width();
var change = 1 + ((termWidth + 35) / containerWidth);
$(this).find('.iconFiller').width(termWidth + iconWidth + 25 + 'px');
$(this).css("flex", change + ' 1 0%');
});
$('.swp_social_panel:not(.swp_social_panelSide)').on('mouseleave', socialWarfare.resetStaticPanel);
}
/**
* Resets the static panels to their default styles. After they've been
* expanded by activateHoverStates(), this function returns the buttons to
* their normal state once a user is no longer hovering over the buttons.
*
* @see activateHoverStates().
* @param void
* @return void
*
*/
socialWarfare.resetStaticPanel = function() {
$(".swp_social_panel:not(.swp_social_panelSide) .nc_tweetContainer:not(.swp_nohover) .iconFiller").removeAttr("style");
$(".swp_social_panel:not(.swp_social_panelSide) .nc_tweetContainer:not(.swp_nohover)").removeAttr("style");
}
/**
* Handle clicks on the buttons that open share windows. It fetches the
* share link, it opens the share link into a new window, it sizes the
* popout window, and makes sure the user is able to share the content.
*
* This also handles sending the events to Google Analytics and Google Tag
* Manager if the user has that feature enabled.
*
* @since 1.0.0 | 01 JAN 2018 | Created
* @since 4.0.0 | 25 FEB 2020 | Added "Print" button functionality.
* @since 4.0.0 | 28 FEB 2020 | Added the Pinterest multi image section.
* @param void
* @return bool Returns false on failure.
*
*/
socialWarfare.handleButtonClicks = function() {
/**
* In order to avoid the possibility that this function may be called
* more than once, we remove all click handlers from our buttons prior
* to activating the new click handler. Prior to this, there were some
* unique instances where clicking on a button would cause multiple
* share windows to pop out.
*
*/
$('.nc_tweet, a.swp_CTT').off('click');
$('.nc_tweet, a.swp_CTT').on('click', function(event) {
/**
* This will intercept clicks that are made on the "Print" button
* and trigger the window.print() method opening the browser's print
* functionality.
*
*/
if($(this).parent('.swp_print').length > 0) {
event.preventDefault();
window.print();
return;
}
/**
* This will intercept clicks that are made on the Pinterest button
* if the Pinterest button is set to display multiple images
* available to the user to choose from. This will trigger the
* lightbox overlay presenting the images to the user.
*
*/
if( true === $(this).hasClass('pinterest_multi_image_select') ) {
event.preventDefault();
socialWarfare.openMultiPinterestOverlay( $(this) );
return;
}
/**
* This will intercept clicks that are made on the "More" button and
* load up our lightbox containing the buttons panels with all of
* the available buttons for the entire plugin.
*
*/
if($(this).parent('.swp_more').length > 0) {
event.preventDefault();
socialWarfare.openMoreOptions( $(this) );
return;
}
/**
* Some buttons that don't have popout share windows can use the
* 'nopop' class to disable this click handler. This will then make
* that button behave like a standard link and allow the browser's
* default click handler to handle it. This is for things like the
* email button.
*
* This used to return false, but that cancels the default event
* from firing. The whole purpose of this exclusion is to allow the
* original event to fire so returning without a value allows it to
* work.
*
*/
if ($(this).hasClass('noPop')) {
return event;
}
/**
* Our click handlers will use the data-link html attribute on the
* button as the share URL when opening the share window. Therefore,
* we need to make sure that this attribute exists.
*
*/
if ('undefined' == typeof $(this).data('link') && false === $(this).is('.swp-hover-pin-button')) {
return event;
}
/**
* This needs to run after all of the bail out conditions above have
* been run. We don't want to preventDefault if a condition exists
* wherein we don't want to take over the event.
*
*/
event.preventDefault();
/**
* Fetch the share link that we'll use to call the popout share
* windows and then declare the variables that we'll be using later.
*
*/
var href = $(this).data('link').replace('’', '\'');
var height, width, top, left, instance, windowAttributes, network;
/**
* These are the default dimensions that are used by most of the
* popout share windows. Additionally, a few of the windows have
* their own javascript that will resize the window dynamically
* once loaded.
*
*/
height = 270;
width = 500;
/**
* Pinterest, Buffer, and Flipboard use a different size than the
* rest so if it's one of those buttons, overwrite the defaults
* that we set above.
*
*/
if ($(this).is('.swp_pinterest a, .buffer_link a, .flipboard a, .swp-hover-pin-button')) {
height = 550;
width = 775;
}
/**
* If a button was clicked, use the data-network attribute to
* figure out which network is being shared. If it was a click
* to tweet that was clicked on, just use ctt as the network.
*
*/
if ($(this).hasClass('nc_tweet')) {
network = $(this).parents('.nc_tweetContainer').data('network');
} else if ($(this).hasClass('swp_CTT')) {
network = 'ctt';
}
/**
* We'll measure the window and then run some calculations to ensure
* that our popout share window opens perfectly centered on the
* browser window.
*
*/
top = window.screenY + (window.innerHeight - height) / 2;
left = window.screenX + (window.innerWidth - width) / 2;
windowAttributes = 'height=' + height + ',width=' + width + ',top=' + top + ',left=' + left;
instance = window.open(href, network, windowAttributes);
// Active Google Analytics event tracking for the button click.
socialWarfare.trackClick(network);
});
}
/**
* The openMultiPinterestOverlay() function will control the overlay that
* appears on the screen when the user has multiple Pinterest images
* available to choose from.
*
* @since 4.0.0 | 28 FEB 2020 | Created
* @param object element The Pinterest button DOM element that was clicked.
* @return void
*
*/
socialWarfare.openMultiPinterestOverlay = function( element ) {
// If the overly has already been loaded once, just fade it in.
if( $('.pinterest-overlay').length > 0 ) {
$('.pinterest-overlay').fadeIn();
$('.swp-lightbox-inner').scrollTop(0);
return;
}
/**
* We'll use this variable to store the string of html as we build it out.
*
*/
var html = '';
/**
* The pin data will be a JSON encoded array of data needed to build the
* Pinterest image selection overlay. It will contain the following data:
*
* description - The Pinterest Description
* url - The processes, shareable link to the post.
* images - An array of image URL's to populate the selection.
*
*/
var pin_data = element.data('pins');
var pin_images = '';
/**
* We'll loop through each available image that the user has provided
* and create a pinnable link to each one for the end user to select from.
*
*/
pin_data.images.forEach( function( image ) {
// Build the share link for this image.
var share_url = 'https://pinterest.com/pin/create/button/?url=' + pin_data.url +
'&media=' + image +
'&description=' + encodeURIComponent( pin_data.description );
// Build out the HTML for the image and button.
var pin_html = '';
pin_html += '<div class="pin_image_select_wrapper">';
pin_html += '<img class="pin_image" src="'+ image +'" />';
pin_html += '<a class="swp-hover-pin-button" href="'+ share_url +'" data-link="'+ share_url +'">Save</a>';
pin_html += '</div>';
// Add all the images and buttons to the main html.
pin_images += pin_html;
});
// Create the html for the lightbox overlay, the title, and the close button.
html += '<div class="swp-lightbox-wrapper pinterest-overlay"><div class="swp-lightbox-inner">';
html += '<i class="sw swp_pinterest_icon top_icon"></i>';
html += '<div class="swp-lightbox-close"></div>';
html += '<h5>Which image would you like to pin?</h5>';
html += '<div class="pin_images_wrapper">';
html += pin_images;
html += '</div>';
html += socialWarfare.buildPoweredByLink();
html += '</div></div>';
// Append it, and hide it first so that we can fade it in.
$('body').append(html);
$('.pinterest-overlay').hide().fadeIn();
// Add the click handlers to the newly added elements (i.e. the buttons)
socialWarfare.handleButtonClicks();
/**
* Here we'll loop through all of the images, and find the shortest one.
* We'll then restrict all of them to be that height. This way all of the
* images in the row will be the same height.
*
* Since we're looking for the smalled image, we'll start with an
* insanely high number and every time we encounter one that is shorter,
* we'll overwrite the number with that one.
*
*/
var max_height = 999999;
/**
* The images.load() will fire each and every time an image in the set
* is loaded. This means that if there are 5 images, it will fire off
* 5 separate times. However, we only want to fire after the last one is
* loaded. As such, we'll count the number of elements, and iterate a
* counter on each lap through the loop. Then once the counter reaches
* the total count of the images, we'll run our function. This means that
* it will only run one time after all of the images have loaded.
*
*/
var iteration = 0, images = $('.pinterest-overlay .pin_images_wrapper img');
/**
* This will run when each image is loaded, so we'll filter below to
* only run when the last one is finished.
*
* This will cause each of the images to be the same exact height as one
* another while also always filling up 100% of the width of the overlay
* container. It's very similar to the Flick image layout effect.
*
*/
images.load( function() {
// This will run after the last image has been loaded.
if( ++iteration === images.length ) {
// This will select all of the images and loop through them.
images.each( function() {
// Check if this image is shorter than the previous image.
if( $(this).height() < max_height ) {
// If it is shorter, this becomes our new "max height"
max_height = $(this).height();
}
/**
* Once we've looped through all of the images and determined
* the shortest image, now we'll set the height of all of the
* taller images to match the shortest one. Now they are all the
* same height.
*
*/
}).promise().done( function() {
// This will make all of the images the same height.
images.height(max_height + 'px');
// Calculate the number of horizontal rows.
var number_of_rows = Math.ceil( images.length / 4 );
// Loop through each row of images.
for (i = 0; i < number_of_rows; i++) {
// Select the images that are in this row.
var current_row_images = images.slice( i * 4, i * 4 + 4 );
// If a row only has 2 images, it will be a maximum of 50% filled.
var max_allowable_width = current_row_images.length / 4;
// Find the total width of the container element.
var total_width = $('.pin_images_wrapper').width();
// Find the total width of all of the images in this row.
var total_images_width = 0;
current_row_images.each( function() {
total_images_width = total_images_width + $(this).width();
});
// Find the ratio between image width and container width.
var ratio = total_width / total_images_width;
/**
* This will set the width of each pin to our calculated
* value minus 1% since we add 1% of padding to the side.
*
*/
current_row_images.each( function() {
var new_width = ( ( $(this).width() * ratio / total_width ) * 100) * max_allowable_width - 1;
$(this).parent().width( new_width + '%' );
$(this).height('auto');
});
/**
* Some of the image heights were off by as much as 2px
* from each other. With this, we'll just grab the height
* of the first image in the set and then set all the
* heights and widths to a static measurements.
*
*/
var height = current_row_images.first().height();
current_row_images.each( function() {
$(this).width( $(this).width() ).height(height);
});
}
});
}
});
}
socialWarfare.buildPoweredByLink = function() {
var html = '';
if( true === socialWarfare.variables.powered_by_toggle ) {
var anchor_tag_open = '';
var anchor_tag_close = '';
if( false !== socialWarfare.variables.affiliate_link ) {
anchor_tag_open = '<a href="'+ socialWarfare.variables.affiliate_link +'" target="_blank">';
anchor_tag_close = '</a>';
}
html = '<div class="swp_powered_by">'+ anchor_tag_open +'<span>Powered by</span> <img src="/wp-content/plugins/social-warfare/assets/images/admin-options-page/social-warfare-pro-light.png">'+ anchor_tag_close +'</div>';
}
return html;
}
/**
* If we preload the images prior to bringing up the overlay, they'll be
* ready so that we can run our resizing algorithms on them and get the
* overlay loaded instantly when called.
*
* @since 4.0.0 | 29 FEB 2020 | Created
* @param void
* @return void
*
*/
socialWarfare.preloadPinterestImages = function() {
// Bail if we don't have a Pinterest Multi-Image setup to preload.
if( $('.pinterest_multi_image_select').length < 1 ) {
return;
}
// Fetch the pin_data from the data attribute.
var pin_data = $('.pinterest_multi_image_select').data('pins');
// Loop through the Pinterest images and preload them.
pin_data.images.forEach( function( image_url ) {
var image_object = new Image();
image_object.src = image_url;
});
}
/**
* The openMoreOptions function will open up the lightbox panel that contains
* all of the social network buttons for the entire plugin allowing the user
* to choose from all available sharing options.
*
* @param void
* @return void
*
*/
socialWarfare.openMoreOptions = function( element ) {
// If the options already exist, just reopen them by fading them in.
if( $('.swp-more-wrapper').length > 0 ) {
$('.swp-more-wrapper').fadeIn();
return;
}
// Fetch the post_id from the parent container, the buttons panel.
var post_id = element.parents('.swp_social_panel').data('post-id');
// Setup the data for the admin-ajax call to fetch the button's html.
var data = {
action: 'swp_buttons_panel',
post_id: post_id,
_ajax_nonce: swp_nonce
};
// Post the data to the admin-ajax and fetch the html.
jQuery.post(swp_ajax_url, data, function(response){
// Append the fetched html to the body.
$('body').append(response);
// Hide the appended html only so that we can fade it into view.
$('.swp-lightbox-wrapper').hide().fadeIn();
// Activate the hover states and button click handlers.
socialWarfare.activateHoverStates();
socialWarfare.handleButtonClicks();
});
}
/**
* The closeLightboxOverlay() function will handle clicks on the red X in the
* corner of the more options box and will fade the lightbox out of view.
*
* @param void
* @return void
*
*/
socialWarfare.closeLightboxOverlay = function() {
// Handle clicks on the red X
$('body').on('click','.swp-lightbox-close', function() {
// Fade the lightbox out of view and scroll it to the top so that it
// doesn't open midway down the viewport.
$('.swp-lightbox-wrapper').fadeOut();
});
// Handle presses of the "Escape" button on the keyboard.
$(document).keyup(function(e) {
if (e.key === "Escape") {
// Fade the lightbox out of view and scroll it to the top so that it
// doesn't open midway down the viewport.
$('.swp-lightbox-wrapper').fadeOut();
}
});
}
/***************************************************************************
*
*
* SECTION #3: FLOATING BUTTONS PANEL CONTROLS
*
*
***************************************************************************/
/**
* Clones a copy of the static buttons to use as a floating panel.
*
* We clone a set of the static horizontal buttons so that when we create
* the floating set we can make the position match exactly. This way when
* they are showing up and disappearing, it will create the allusion that
* the static buttons are just getting glued to the edge of the screen and
* following along with the user as they scroll.
*
* @since 1.0.0 | 01 JAN 2016 | Created
* @param void
* @return void
*
*/
socialWarfare.createFloatHorizontalPanel = function() {
//* If a horizontal panel does not exist, we can not create a bar.
if (!socialWarfare.panels.staticHorizontal.length) {
return;
}
var floatLocation = socialWarfare.panels.staticHorizontal.data("float");
var mobileFloatLocation = socialWarfare.panels.staticHorizontal.data("float-mobile");
var backgroundColor = socialWarfare.panels.staticHorizontal.data("float-color");
var wrapper = $('<div class="nc_wrapper swp_floating_horizontal_wrapper" style="background-color:' + backgroundColor + '"></div>');
var barLocation = '';
//* .swp_social_panelSide is the side floater.
if ($(".nc_wrapper").length) {
$(".nc_wrapper").remove();
}
//* repeating the code above for the new selector.
if ($(".swp_floating_horizontal_wrapper").length) {
$(".swp_floating_horizontal_wrapper").remove();
}
//* No floating bars are used at all.
if (floatLocation != 'top' && floatLocation != 'bottom' && mobileFloatLocation != "top" && mobileFloatLocation != "bottom") {
return;
}
//* Set the location (top or bottom) of the bar depending on
if (socialWarfare.isMobile()) {
barLocation = mobileFloatLocation;
} else {
barLocation = floatLocation;
}
//* Assign a CSS class to the wrapper based on the float-mobile location.
wrapper.addClass(barLocation).hide().appendTo('body');
//* Save the new buttons panel to our ${panels} object.
socialWarfare.panels.floatingHorizontal = socialWarfare.panels.staticHorizontal.first().clone();
socialWarfare.panels.floatingHorizontal.addClass('nc_floater').appendTo(wrapper);
socialWarfare.updateFloatingHorizontalDimensions();
$(".swp_social_panel .swp_count").css({
transition: "padding .1s linear"
});
}
/**
* Callback on window resize to update the width and position of a
* floatingHorizontal panel.
*
*/
socialWarfare.updateFloatingHorizontalDimensions = function() {
// If there is no static set to measure, just bail out.
if (!socialWarfare.panels.staticHorizontal.length) {
return;
}
// If there is no floating set, just bail.
if(!socialWarfare.panels.floatingHorizontal) {
return;
}
/**
* We'll create the default width and left properties here. Then we'll
* attempt to pull these properties from the actual panel that we are
* cloning below. If those measurements exist, we clone them. If not,
* we use these defaults.
*
*/
var width = "100%";
var left = 0;
var panel = socialWarfare.panels.staticHorizontal;
var parent = panel.parent();
//* Ignore the invisible wrapper div, it has no width.
if (parent.hasClass("swp-hidden-panel-wrap")) {
parent = parent.parent();
}
if( 'undefined' !== typeof panel.offset().left ) {
left = panel.offset().left;
}
if( 'undefined' !== typeof panel.width() ) {
width = panel.width();
}
if( left == 0 ) {
left = parent.offset().left;
}
//* The panel width is 'auto', which evaluates to 100%
if (width == 100 || width == 0) {
width = parent.width();
}
//* Give the bar panel the appropriate classname and put it in its wrapper.
socialWarfare.panels.floatingHorizontal.css({
width: width,
left: left
});
}
/**
* Determines if a set of static buttons is currenty visible on the screen.
*
* We will use this to determine whether or not we should display a set of
* floating buttons. Whenever the static buttons are visible, we hide the
* floating buttons. Whenever the static buttons are not visible, we show
* the floating buttons.
*
* @param void
* @return bool True if a static set of buttons is visible on the screen, else false.
*
*/
socialWarfare.staticPanelIsVisible = function() {
var visible = false;
var scrollPos = $(window).scrollTop();
//* Iterate each buttons panel, checking each to see if it is currently visible.
$(".swp_social_panel").not(".swp_social_panelSide, .nc_floater").each(function(index) {
var offset = $(this).offset();
//* Do not display floating buttons before the horizontal panel.
//* PHP json_encode() maps `true` to "1" and `false` to "".
if (typeof socialWarfare.floatBeforeContent != 'undefined' && "1" != socialWarfare.floatBeforeContent) {
var theContent = $(".swp-content-locator").parent();
//* We are in sight of an "Above the content" panel.
if (index === 0 && theContent.length && theContent.offset().top > (scrollPos + $(window).height())) {
visible = true;
}
}
//* Do not display floating buttons if a panel is currently visible.
if ($(this).is(':visible') &&
offset.top + $(this).height() > scrollPos &&
offset.top < (scrollPos + $(window).height())) {
visible = true;
}
});
return visible;
}
/**
* Handler to toggle the display of either the side or bar floating buttons.
*
* We only show the floating buttons when the static horizontal buttons are
* not in the visible view port. This function is used to toggle their
* visibility when they need to be shown or hidden.
*
* @since 2.0.0 | 01 JAN 2016 | Created
* @param void
* @return void
*
*/
socialWarfare.updateFloatingButtons = function() {
// If buttons are on the page, there must be either a static horizontal
if (socialWarfare.panels.staticHorizontal.length) {
var panel = socialWarfare.panels.staticHorizontal;
}
// Or a side floating panel.
else if (socialWarfare.panels.floatingSide.length) {
var panel = socialWarfare.panels.floatingSide;
}
else {
return;
}
// Adjust the floating bar
var location = panel.data('float');
if (true == socialWarfare.isMobile()) {
var location = panel.data('float-mobile');
}
//* There are no floating buttons enabled, hide any that might exist.
if (location == 'none') {
return $(".nc_wrapper, .swp_floating_horizontal_wrapper, .swp_social_panelSide").hide();
}
if (socialWarfare.isMobile()) {
socialWarfare.toggleMobileButtons();
socialWarfare.toggleFloatingHorizontalPanel();
return;
}
if (location == "right" || location == "left") {
socialWarfare.toggleFloatingVerticalPanel();
}
if (location == "bottom" || location == "top") {
socialWarfare.toggleFloatingHorizontalPanel();
}
}
/**
* Toggle the visibilty of a mobile bar.
*
* @return void
*
*/
socialWarfare.toggleMobileButtons = function() {
//* There are never any left/right floating buttons on mobile, so hide them.
socialWarfare.panels.floatingSide.hide();
var visibility = socialWarfare.staticPanelIsVisible() ? "collapse" : "visible";
$(".nc_wrapper, .swp_floating_horizontal_wrapper").css("visibility", visibility);
}
/**
* Toggle the display of a side panel, depending on static panel visibility.
*
* @return void
*
*/
socialWarfare.toggleFloatingVerticalPanel = function() {
var direction = '';
var location = socialWarfare.panels.floatingSide.data("float");
var visible = socialWarfare.staticPanelIsVisible();
var offset = "";
//* This is on mobile and does not use side panels.
if (socialWarfare.isMobile()) {
return socialWarfare.panels.floatingSide.hide();
}
if (!socialWarfare.panels.floatingSide || !socialWarfare.panels.floatingSide.length) {
// No buttons panel! Update `visible` to hide floaters.
visible = true;
}
if (socialWarfare.panels.floatingSide.data("transition") == "slide") {
direction = location;
offset = visible ? "-150px" : "5px";
//* Update the side panel CSS with the direction and amount.
socialWarfare.panels.floatingSide.css(direction, offset).show();
}
else {
/**
* We had problems with the fading buttons flickering rather than having
* a smooth fade animation. The workaround was to manually control opacity,
* fade, and opacity again.
*
*/
if (visible) {
socialWarfare.panels.floatingSide.css("opacity", 1)
.fadeOut(300)
.css("opacity", 0);
}
else {
socialWarfare.panels.floatingSide.css("opacity", 0)
.fadeIn(300)
.css("display", "flex")
.css("opacity", 1);
}
}
}
socialWarfare.hasReferencePanel = function() {
return typeof socialWarfare.panels.staticHorizontal != 'undefined' &&
socialWarfare.panels.staticHorizontal.length > 0
}
/**
* Toggle the display of a floating bar, depending on static panel visibility.
*
* @return void
*
*/
socialWarfare.toggleFloatingHorizontalPanel = function() {
if (!socialWarfare.hasReferencePanel()) {
return;
}
// If there is no floating set, just bail.
if(!socialWarfare.panels.floatingHorizontal) {
return;
}
var panel = socialWarfare.panels.floatingHorizontal.first();
var location = socialWarfare.isMobile() ? $(panel).data("float-mobile") : $(panel).data("float");
var newPadding = (location == "bottom") ? socialWarfare.paddingBottom : socialWarfare.paddingTop;
var paddingProp = "padding-" + location;
if (location == 'off') {
return;
}
//* Restore the padding to initial values.
if (socialWarfare.staticPanelIsVisible()) {
$(".nc_wrapper, .swp_floating_horizontal_wrapper").hide();
if (socialWarfare.isMobile() && $("#wpadminbar").length) {
$("#wpadminbar").css("top", 0);
}
}
// Add some padding to the page so it fits nicely at the top or bottom.
else {
newPadding += 50;
$(".nc_wrapper, .swp_floating_horizontal_wrapper").show();
//* Compensate for the margin-top added to <html> by #wpadminbar.
if (socialWarfare.isMobile() && location == 'top' && $("#wpadminbar").length) {
$("#wpadminbar").css("top", panel.parent().height());
}
}
//* Update padding to be either initial values, or to use padding for floatingHorizontal panels.
$("body").css(paddingProp, newPadding);
}
/**
* This method is used to vertically center the floating buttons when they
* are positioned on the left or right of the screen.
*
* @since 3.4.0 | 18 OCT 2018 | Created
* @param void
* @param void All changes are made to the dom.
*
*/
socialWarfare.positionFloatSidePanel = function() {
var panelHeight, windowHeight, offset;
var sidePanel = socialWarfare.panels.floatingSide;
/**
* If no such element exists, we obviously just need to bail out and
* not try to center anything.
*
*/
if (!sidePanel || !sidePanel.length) {
return;
}
/**
* We don't need to center the side panel buttons if the position is set
* to top or bottom. This will isntead be directly controlled by the CSS
* that is associated with these classes.
*
*/
if( sidePanel.hasClass('swp_side_top') || sidePanel.hasClass('swp_side_bottom') ) {
return;
}
/**
* We'll need the height of the panel itself and the height of the
* actual browser window in order to calculate how to center it.
*
*/
panelHeight = sidePanel.outerHeight();
windowHeight = window.innerHeight;
/**
* If for some reason the panel is actually taller than the window
* itself, just stick it to the top of the window and the bottom will
* just have to overflow past the bottom of the screen.
*
*/
if (panelHeight > windowHeight) {
return sidePanel.css("top", 0);
}
/**
* Calculate the center position of panel and then apply the relevant
* CSS to the panel.
*
*/
offset = (windowHeight - panelHeight) / 2;
sidePanel.css("top", offset);
}
/***************************************************************************
*
*
* SECTION #4: PINTEREST IMAGE HOVER SAVE BUTTONS
*
*
***************************************************************************/
// Create a single instance of the save button and store it in socialWarfare.
socialWarfare.createHoverSaveButton = function() {
/**
* This is a compatibility patch to make our plugin work nicely with the
* Thrive Architect plugin. This will do two things:
*
* 1. It will stop the Pinterest Save button from appearing on images
* when the post being loaded is inside of the Thrive Architect page
* builder/editor.
*
* 2. It will locate any old Save buttons that have been added previously
* that were then erroneously saved in the database. This way, whenever
* they edit a post, it will simultanously repair/remove the invalid
* markup that was stored in the database.
*
*/
if( $('.tve_editor_page').length ) {
$('.sw-pinit-button').remove();
$('.sw-pinit').each( function() {
var inner_content = $('.sw-pinit').contents();
$(this).replaceWith(inner_content);
});
return;
}
var button = $(document.createElement("a"));
button.css("display: none");
button.addClass("swp-hover-pin-button");
button.text("Save");
socialWarfare.hoverSaveButton = $(button);
return button;
}
/**
* Find all images of the images that are in the content area by looking
* for the .swp-content-locator div which is an empty div that we add via
* the_content() hook just so that we can target it here. Then iterate
* through them and determine if we should add a Pinterest save button.
*
*/
socialWarfare.triggerImageListeners = function() {
$(".swp-content-locator").parent().find("img").off('mouseenter', socialWarfare.renderPinterestSaveButton)
$(".swp-content-locator").parent().find("img").on('mouseenter', socialWarfare.renderPinterestSaveButton)
// We need to assign the hover callback to new images
// loaded by ajax as the visitor scrolls through the page.
setTimeout(socialWarfare.triggerImageListeners, 2000);
}
socialWarfare.getPinMedia = function( image ) {
/**
* If the swpPinIt.image_source variable exists, it means that the user
* forces their custom Pinterest image instaed of the visitor's selection.
*
*/
if (isString(swpPinIt.image_source)) {
return swpPinIt.image_source;
}
// Most images will have a src already defined, this gets top priority.
if (isString(image.attr("src"))) {
return image.attr("src");
}
// Otherise check common data-attributes for an image source.
var dataSources = ['src', 'lazy-src', 'media'];
var media = '';
// Search for the first existing value and keep it if found.
dataSources.some(function(maybeSource) {
if (isString(image.data(maybeSource))) {
media = image.data(maybeSource);
return true;
}
})
if (media == '') {
return;
}
// Use a jQuery image to guarantee we have an absolute path to the resource.
// Pinterest throws an error when passed a relative path.
var i = $("<img>");
i.attr("src", media)
return i.prop("src");
}
/**
* This is where we compute a description that will be used when the
* image is shared to Pinterest. In order of precedence, we will use the
* image's data-pin-description attribute, the custom Pinterest description
* for the post passed from the server, the image title, or the image
* description.
*
*/
socialWarfare.getPinDescription = function(image) {
if (isString(image.data("pin-description"))) {
return image.data("pin-description");
}
if (isString(swpPinIt.image_description)) {
return swpPinIt.image_description;
}
// Try image Title or Alt text.
if (isString(image.attr("title"))) {
return image.attr("title");
}
if (isString(image.attr("alt"))) {
return image.attr("alt");
}
// Default to the post title if nothing else is found.
if (isString(swpPinIt.post_title)) {
return swpPinIt.post_title;
}
}
/**
* Adds the "Save" button to images when the option is enabled.
*
* This method will search and destroy any Pinterest save buttons that have
* been added by the Pinterest browser extension and then render the html
* needed to add our own proprietary Pinterest buttons on top of images.
*
* @param void
* @return void
*
*/
socialWarfare.enablePinterestSaveButtons = function() {
/**
* Search and Destroy: This will find any Pinterest buttons that were
* added via their browser extension and then destroy them so that only
* ours are on the page.
*
*/
jQuery('img').on('mouseenter', function() {
var pinterestBrowserButtons = socialWarfare.findPinterestBrowserSaveButtons();
if (typeof pinterestBrowserButtons != 'undefined' && pinterestBrowserButtons) {
socialWarfare.removePinterestBrowserSaveButtons(pinterestBrowserButtons);
}
});
}
socialWarfare.toggleHoverSaveDisplay = function(image) {
var top = image.offset().top;
var left = image.offset().left;
var vMargin = 15;
var hMargin = 15;
var button_size = swpPinIt.button_size || 1;
var buttonHeight = 24;
var buttonWidth = 120;
// Known height from CSS is 34 px.
// Known width from CSS is 120 px.
switch (swpPinIt.vLocation) {
case "top" :
top += vMargin;
break;
case "middle" :
var offset = image.height() / 2 - (vMargin / 2) - (buttonHeight / 2);
top += offset;
break;
case "bottom" :
top += image.height() - vMargin - buttonHeight;
break;
}
switch (swpPinIt.hLocation) {
case "left" :
left += hMargin;
break;
case "center" :
var offset = image.width() / 2 - (hMargin / 2) - (buttonWidth / 2);
left += offset;
break;
case "right" :
left += image.width() - hMargin - buttonWidth;
break;
}
socialWarfare.hoverSaveButton.css({
"top": top,
"left": left,
"transform": "scale(" + button_size + ")",
"transform-origin": swpPinIt.vLocation + ' ' + swpPinIt.hLocation,
});
// Entering the button from the image triggers mouseleave and mouseenter.
// Keep the button where it would otherwise disappear due to a mouseleave.
image.on("mouseleave", function(event) {
if (event.relatedTarget != null && event.relatedTarget.className == 'swp-hover-pin-button') {
return;
}
$(".swp-hover-pin-button").remove();
});
$(document.body).append(socialWarfare.hoverSaveButton);
}
/**
* This function renders the HTML needed to print the save buttons on the images.
*
* @param void
* @since void
*
*/
socialWarfare.renderPinterestSaveButton = function(event) {
if (event.relatedTarget && event.relatedTarget.className == 'swp-hover-pin-button') {
return;
}
if ($(".swp-hover-pin-button").length > 0) {
return;
}
var image = $(event.target);
/**
* This disables the Pinterest save buttons on images that are anchors/links
* if the user has them disabled on them in the options page. So if this
* image is a link, we just bail out.
*
*/
if (typeof swpPinIt.disableOnAnchors != undefined && swpPinIt.disableOnAnchors) {
if (image.parents().filter("a").length) {
return;
}
}
/**
* In the option page, the user can set a minimum width and a minimum
* height. Anything that isn't as large as these image dimensions will
* be skipped. This is a JS variable that is generated and output by
* the server.
*
*/
if (image.outerHeight() < swpPinIt.minHeight || image.outerWidth() < swpPinIt.minWidth) {
return;
}
/**
* We offer users the option to manually opt any image out of having a
* Pinterest save button on it by simply adding either the no_pin class
* or the no-pin class. There is also a checkbox in the media uploader
* that when checked will add one of these classes. If this image has
* one, skip it.
*
*/
if (image.hasClass('no_pin') || image.hasClass('no-pin')) {
return;
}
socialWarfare.toggleHoverSaveDisplay(image);
var description = socialWarfare.getPinDescription(image);
var media = socialWarfare.getPinMedia(image);
var shareLink = 'http://pinterest.com/pin/create/bookmarklet/?media=' + encodeURI(media) + '&url=' + encodeURI(document.URL) + '&is_video=false' + '&description=' + encodeURIComponent(description);
function openPinterestDialogue(event) {
var offsetLeft = ($(window).width() - 775) / 2;
var offsetTop = ($(window).height() - 550) / 2;
var position = ',top=' + offsetTop + ',left=' + offsetLeft;
window.open(shareLink, 'Pinterest', 'width=775,height=550,status=0,toolbar=0,menubar=0,location=1,scrollbars=1' + position);
socialWarfare.trackClick('pin_image');
$(".swp-hover-pin-button").remove();
}
$(".swp-hover-pin-button").on("click", openPinterestDialogue);
// The elemnt and its event handlers are removed in toggleHoverSaveDisplay().
}
/**
* Looks for a "Save" button created by Pinterest addons.
*
* @param void
* @return HTMLNode if the Pinterest button is found, else NULL.
*
*/
socialWarfare.findPinterestBrowserSaveButtons = function() {
var pinterestRed, pinterestRed2019, pinterestZIndex, pinterestBackgroundSize, button, style;
//* Known constants used by Pinterest.
pinterestRed = "rgb(189, 8, 28)";
pinterestRed2019 = "rgb(230, 0, 35)";
pinterestZIndex = "8675309";
pinterestBackgroundSize = "14px 14px";
button = null;
//* The Pinterest button is a <span/>, so check each span for a match.
document.querySelectorAll("span").forEach(function(element, index) {
style = window.getComputedStyle(element);
if (style.backgroundColor == pinterestRed || style.backgroundColor == pinterestRed2019) {
if (style.backgroundSize == pinterestBackgroundSize && style.zIndex == pinterestZIndex) {
button = element;
}
}
});
return button;
}
/**
* Removes the "save" button created by Pinterest Browser Extension.
*
*/
socialWarfare.removePinterestBrowserSaveButtons = function(button) {
var pinterestSquare, style, size;
pinterestSquare = button.nextSibling;
//* The sibling to the Pinterest button is always a span.
if ( pinterestSquare != undefined && pinterestSquare.nodeName == 'SPAN') {
style = window.getComputedStyle(pinterestSquare);
size = "24px";
//* If the sibling is indeed the correct Pinterest sibling, destory it all.
if (style.width.indexOf(size) === 0 && style.height.indexOf(size) === 0) {
pinterestSquare.remove()
}
}
button.remove();
}
/***************************************************************************
*
*
* SECTION #5: FACEBOOK SHARE COUNT FUNCTIONS
*
*
***************************************************************************/
/**
* Makes external requsts to fetch Facebook share counts. We fetch Facebook
* share counts via the frontened Javascript because their API has harsh
* rate limits that are IP Address based. So it's very easy for a website to
* hit those limits and recieve temporary bans from accessing the share count
* data. By using the front end, the IP Addresses are distributed to users,
* are therefore spread out, and don't hit the rate limits.
*
* @param void
* @return void
*
*/
socialWarfare.fetchFacebookShares = function() {
// Compile the API links
var url1 = 'https://graph.facebook.com/v6.0/?fields=og_object{engagement}&id=' + swp_post_url;
var url2 = swp_post_recovery_url ? 'https://graph.facebook.com/v6.0/?fields=og_object{engagement}&id=' + swp_post_recovery_url : '';
// Record the tested URL's
console.log('Facebook Share API: ' + url1 );
console.log('Facebook Share API (recovery): ' + url2);
// Use this to ensure that we wait until the API requests are done.
$.when( $.get( url1 ), $.get( url2 ) )
.then(function(response1, response2) {
var shares, shares1, shares2, data;
// Parse the shares and add them up into a running total.
shares1 = socialWarfare.parseFacebookShares(response1[0]);
shares2 = 0;
if (swp_post_recovery_url) {
shares2 = socialWarfare.parseFacebookShares(response2[0]);
}
// This will eliminate adding together duplicate data.
shares = shares1;
if( shares1 !== shares2 ) {
shares = shares1 + shares2;
}
// Compile the data and send out the AJAX request to store the count.
var data = {
action: 'swp_facebook_shares_update',
post_id: swp_post_id,
share_counts: shares
};
$.post(swp_admin_ajax, data, function(response) {
console.log(response);
});
});
}
/**
* Sums the share data from a facebook API response. This is a utility
* function used by socialWarfare.fetchFacebookShares to allow easy access
* to parsing out the JSON response that we got from Facebook's API and
* converting it into an integer that reflects the tally of all activity
* on the URl in question including like, comments, and shares.
*
* @param object response The API response received from Facebook.
* @return number The total shares summed from the request, or 0.
*
*/
socialWarfare.parseFacebookShares = function(response) {
if ('undefined' === typeof response.og_object) {
console.log('Facebook Shares: 0');
return 0;
}
console.log('Facebook Shares: ' + response.og_object.engagement.count);
return parseInt(response.og_object.engagement.count);
}
/***************************************************************************
*
*
* SECTION #6: UTILITY/HELPER FUNCTIONS
*
*
***************************************************************************/
/**
* The throttle function is used to control how often an event can be fired.
* We use this exclusively to control how often scroll events go off. In some
* cases, the scroll event which controls when the floating buttons appear
* or disappear, was firing so often on scroll that the floating buttons were
* rapidly flickering in and out of view. This solves that.
*
* @param integer delay How often in ms to allow the event to fire.
* @param function callback The function to run if the timeout period is expired.
* @return function The callback function.
*
*/
// socialWarfare.throttle = function(delay, callback) {
// var timeoutID = 0;
// // The previous time `callback` was called.
// var lastExec = 0;
//
// function wrapper() {
// var wrap = this;
// var elapsed = +new Date() - lastExec;
// var args = arguments;
//
// function exec() {
// lastExec = +new Date();
// callback.apply(wrap, args);
// }
//
// function clear() {
// timeoutID = 0;
// lastExec = 0;
// }
//
// timeoutID && clearTimeout(timeoutID);
//
// if (elapsed > delay) {
// exec();
// } else {
// timeoutID = setTimeout(exec, delay - elapsed);
// }
// }
//
// if (socialWarfare.guid) {
// wrapper.guid = callback.guid = callback.guid || socialWarfareguid++;
// }
//
// console.log(wrapper)
//
// return wrapper;
// };
/**
* A simple wrapper for easily triggering DOM events. This will allow us to
* fire off our own custom events that our addons can then bind to in order
* to run their own functions in sequence with ours here.
*
* @param string event The name of the event to trigger.
* @return void
*
*/
socialWarfare.trigger = function(event) {
$(window).trigger($.Event(event));
}
/**
* Fire an event for Google Analytics and GTM.
*
* @since 2.4.0 | 18 OCT 2018 | Created
* @param string event A string identifying the button being clicked.
* @return void
*
*/
socialWarfare.trackClick = function(event) {
/**
* If click tracking has been enabled in the user settings, we'll
* need to send the event via Googel Analytics. The swpClickTracking
* variable will be dynamically generated via PHP and output in the
* footer of the page.
*
*/
if (true === swpClickTracking) {
/**
* If Google Analytics is present on the page, we'll send the
* event via their object and methods.
*
*/
if ('function' == typeof ga) {
ga('send', 'event', 'social_media', 'swp_' + event + '_share');
}
/**
* If Google Tag Manager is present on the page, we'll send the
* event via their object and methods.
*
*/
if ('object' == typeof dataLayer) {
dataLayer.push({ 'event': 'swp_' + event + '_share' });
}
}
}
/**
* Checks to see if we have a buttons panel. If so, forces a re-run of the
* handleButtonClicks callback.
*
* @param number count The current iteration of the loop cycle.
* @param number limit The maximum number of iterations for the loop cycle.
* @return void or function handleButtonClicks().
*
*/
socialWarfare.checkListeners = function(count, limit) {
/**
* Once we've checked for the buttons panel a certain number of times,
* we're simply going to bail out and stop checking. Right now, it is
* set to run 5 times for a total of 10 seconds.
*
*/
if (count > limit) {
return;
}
/**
* The primary reason we are doing this is to ensure that a set of
* buttons does indeed exist when the click bindings are created. So
* this looks for the buttons and check's for their existence. If we
* find them, we fire off the handleButtonClicks() function.
*
*/
var panel = $('.swp_social_panel');
if (panel.length > 0 && panel.find('.swp_pinterest')) {
socialWarfare.handleButtonClicks();
return;
}
/**
* If we haven't found any buttons panel, then after 2 more seconds,
* we'll fire off this function again until the limit has been reached.
*
*/
setTimeout(function() {
socialWarfare.checkListeners(++count, limit)
}, 2000);
}
/**
* Stores the user-defined mobile breakpoint in the socialWarfare object. In
* other functions, if the width of the current browser is smaller than this
* breakpoint, we will switch over and use the mobile options for the buttons
* panels.
*
*/
socialWarfare.establishBreakpoint = function() {
var panel = $('.swp_social_panel');
socialWarfare.breakpoint = 1100;
if (panel.length && panel.data('min-width') || panel.data('min-width') == 0) {
socialWarfare.breakpoint = parseInt( panel.data('min-width') );
}
}
/**
* Checks to see if the current viewport is within the defined mobile
* breakpoint. The user sets a width in the options page. Any window
* viewport that is not as wide as that width will trigger isMobile to
* return as true.
*
*/
socialWarfare.isMobile = function() {
return $(window).width() < socialWarfare.breakpoint;
}
/**
* Load the plugin once the DOM has been loaded.
*
*/
$(document).ready(function() {
// This is what fires up the entire plugin's JS functionality.
socialWarfare.initPlugin();
socialWarfare.panels.floatingSide.hide();
/**
* On resize, we're going to purge and re-init the entirety of the
* socialWarfare functions. This will fully reset all of the floating
* buttons which will allow for a clean transition if the size change
* causes the isMobile() check to flip from true to false or vica versa.
*
*/
$(window).resize(socialWarfare.onWindowResize);
if ('undefined' !== typeof swpPinIt && swpPinIt.enabled) {
socialWarfare.enablePinterestSaveButtons();
}
});
/**
* This reactivates and creates new image hover pin buttons when a page has
* been loaded via AJAX. The 'load' event is the proper event that theme and
* plugin creators are supposed to use when the AJAX load is complete.
*
*/
$(window).on('load', function() {
if ('undefined' !== typeof swpPinIt && swpPinIt.enabled) {
socialWarfare.enablePinterestSaveButtons();
}
window.clearCheckID = 0;
});
})(this, jQuery);
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists