/* Detect-zoom
* -----------
* Cross Browser Zoom and Pixel Ratio Detector
* Version 1.0.4 | Apr 1 2013
* dual-licensed under the WTFPL and MIT license
* Maintained by https://github/tombigel
* Original developer https://github.com/yonran
*/
//AMD and CommonJS initialization copied from https://github.com/zohararad/audio5js
(function (root, ns, factory) {
"use strict";
if (typeof (module) !== 'undefined' && module.exports) { // CommonJS
module.exports = factory(ns, root);
} else if (typeof (define) === 'function' && define.amd) { // AMD
define("factory", function () {
return factory(ns, root);
});
} else {
root[ns] = factory(ns, root);
}
}(window, 'detectZoom', function () {
/**
* Use devicePixelRatio if supported by the browser
* @return {Number}
* @private
*/
var devicePixelRatio = function () {
return window.devicePixelRatio || 1;
};
/**
* Fallback function to set default values
* @return {Object}
* @private
*/
var fallback = function () {
return {
zoom: 1,
devicePxPerCssPx: 1
};
};
/**
* IE 8 and 9: no trick needed!
* TODO: Test on IE10 and Windows 8 RT
* @return {Object}
* @private
**/
var ie8 = function () {
var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* For IE10 we need to change our technique again...
* thanks https://github.com/stefanvanburen
* @return {Object}
* @private
*/
var ie10 = function () {
var zoom = Math.round((document.documentElement.offsetHeight / window.innerHeight) * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* Mobile WebKit
* the trick: window.innerWIdth is in CSS pixels, while
* screen.width and screen.height are in system pixels.
* And there are no scrollbars to mess up the measurement.
* @return {Object}
* @private
*/
var webkitMobile = function () {
var deviceWidth = (Math.abs(window.orientation) == 90) ? screen.height : screen.width;
var zoom = deviceWidth / window.innerWidth;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* Desktop Webkit
* the trick: an element's clientHeight is in CSS pixels, while you can
* set its line-height in system pixels using font-size and
* -webkit-text-size-adjust:none.
* device-pixel-ratio: http://www.webkit.org/blog/55/high-dpi-web-sites/
*
* Previous trick (used before http://trac.webkit.org/changeset/100847):
* documentElement.scrollWidth is in CSS pixels, while
* document.width was in system pixels. Note that this is the
* layout width of the document, which is slightly different from viewport
* because document width does not include scrollbars and might be wider
* due to big elements.
* @return {Object}
* @private
*/
var webkit = function () {
var important = function (str) {
return str.replace(/;/g, " !important;");
};
var div = document.createElement('div');
div.innerHTML = "1 2 3 4 5 6 7 8 9 0";
div.setAttribute('style', important('font: 100px/1em sans-serif; -webkit-text-size-adjust: none; text-size-adjust: none; height: auto; width: 1em; padding: 0; overflow: visible;'));
// The container exists so that the div will be laid out in its own flow
// while not impacting the layout, viewport size, or display of the
// webpage as a whole.
// Add !important and relevant CSS rule resets
// so that other rules cannot affect the results.
var container = document.createElement('div');
container.setAttribute('style', important('width:0; height:0; overflow:hidden; visibility:hidden; position: absolute;'));
container.appendChild(div);
document.body.appendChild(container);
var zoom = 1000 / div.clientHeight;
zoom = Math.round(zoom * 100) / 100;
document.body.removeChild(container);
return{
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* no real trick; device-pixel-ratio is the ratio of device dpi / css dpi.
* (Note that this is a different interpretation than Webkit's device
* pixel ratio, which is the ratio device dpi / system dpi).
*
* Also, for Mozilla, there is no difference between the zoom factor and the device ratio.
*
* @return {Object}
* @private
*/
var firefox4 = function () {
var zoom = mediaQueryBinarySearch('min--moz-device-pixel-ratio', '', 0, 10, 20, 0.0001);
zoom = Math.round(zoom * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom
};
};
/**
* Firefox 18.x
* Mozilla added support for devicePixelRatio to Firefox 18,
* but it is affected by the zoom level, so, like in older
* Firefox we can't tell if we are in zoom mode or in a device
* with a different pixel ratio
* @return {Object}
* @private
*/
var firefox18 = function () {
return {
zoom: firefox4().zoom,
devicePxPerCssPx: devicePixelRatio()
};
};
/**
* works starting Opera 11.11
* the trick: outerWidth is the viewport width including scrollbars in
* system px, while innerWidth is the viewport width including scrollbars
* in CSS px
* @return {Object}
* @private
*/
var opera11 = function () {
var zoom = window.top.outerWidth / window.top.innerWidth;
zoom = Math.round(zoom * 100) / 100;
return {
zoom: zoom,
devicePxPerCssPx: zoom * devicePixelRatio()
};
};
/**
* Use a binary search through media queries to find zoom level in Firefox
* @param property
* @param unit
* @param a
* @param b
* @param maxIter
* @param epsilon
* @return {Number}
*/
var mediaQueryBinarySearch = function (property, unit, a, b, maxIter, epsilon) {
var matchMedia;
var head, style, div;
if (window.matchMedia) {
matchMedia = window.matchMedia;
} else {
head = document.getElementsByTagName('head')[0];
style = document.createElement('style');
head.appendChild(style);
div = document.createElement('div');
div.className = 'mediaQueryBinarySearch';
div.style.display = 'none';
document.body.appendChild(div);
matchMedia = function (query) {
style.sheet.insertRule('@media ' + query + '{.mediaQueryBinarySearch ' + '{text-decoration: underline} }', 0);
var matched = getComputedStyle(div, null).textDecoration == 'underline';
style.sheet.deleteRule(0);
return {matches: matched};
};
}
var ratio = binarySearch(a, b, maxIter);
if (div) {
head.removeChild(style);
document.body.removeChild(div);
}
return ratio;
function binarySearch(a, b, maxIter) {
var mid = (a + b) / 2;
if (maxIter <= 0 || b - a < epsilon) {
return mid;
}
var query = "(" + property + ":" + mid + unit + ")";
if (matchMedia(query).matches) {
return binarySearch(mid, b, maxIter - 1);
} else {
return binarySearch(a, mid, maxIter - 1);
}
}
};
/**
* Generate detection function
* @private
*/
var detectFunction = (function () {
var func = fallback;
//IE8+
if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) {
func = ie8;
}
// IE10+ / Touch
else if (window.navigator.msMaxTouchPoints) {
func = ie10;
}
//Mobile Webkit
else if ('orientation' in window && typeof document.body.style.webkitMarquee === 'string') {
func = webkitMobile;
}
//WebKit
else if (typeof document.body.style.webkitMarquee === 'string') {
func = webkit;
}
//Opera
else if (navigator.userAgent.indexOf('Opera') >= 0) {
func = opera11;
}
//Last one is Firefox
//FF 18.x
else if (window.devicePixelRatio) {
func = firefox18;
}
//FF 4.0 - 17.x
else if (firefox4().zoom > 0.001) {
func = firefox4;
}
return func;
}());
return ({
/**
* Ratios.zoom shorthand
* @return {Number} Zoom level
*/
zoom: function () {
return detectFunction().zoom;
},
/**
* Ratios.devicePxPerCssPx shorthand
* @return {Number} devicePxPerCssPx level
*/
device: function () {
return detectFunction().devicePxPerCssPx;
}
});
}));
var wpcom_img_zoomer = {
clientHintSupport: {
gravatar: false,
files: false,
photon: false,
mshots: false,
staticAssets: false,
latex: false,
imgpress: false,
},
useHints: false,
zoomed: false,
timer: null,
interval: 1000, // zoom polling interval in millisecond
// Should we apply width/height attributes to control the image size?
imgNeedsSizeAtts: function( img ) {
// Do not overwrite existing width/height attributes.
if ( img.getAttribute('width') !== null || img.getAttribute('height') !== null )
return false;
// Do not apply the attributes if the image is already constrained by a parent element.
if ( img.width < img.naturalWidth || img.height < img.naturalHeight )
return false;
return true;
},
hintsFor: function( service ) {
if ( this.useHints === false ) {
return false;
}
if ( this.hints() === false ) {
return false;
}
if ( typeof this.clientHintSupport[service] === "undefined" ) {
return false;
}
if ( this.clientHintSupport[service] === true ) {
return true;
}
return false;
},
hints: function() {
try {
var chrome = window.navigator.userAgent.match(/\sChrome\/([0-9]+)\.[.0-9]+\s/)
if (chrome !== null) {
var version = parseInt(chrome[1], 10)
if (isNaN(version) === false && version >= 46) {
return true
}
}
} catch (e) {
return false
}
return false
},
init: function() {
var t = this;
try{
t.zoomImages();
t.timer = setInterval( function() { t.zoomImages(); }, t.interval );
}
catch(e){
}
},
stop: function() {
if ( this.timer )
clearInterval( this.timer );
},
getScale: function() {
var scale = detectZoom.device();
// Round up to 1.5 or the next integer below the cap.
if ( scale <= 1.0 ) scale = 1.0;
else if ( scale <= 1.5 ) scale = 1.5;
else if ( scale <= 2.0 ) scale = 2.0;
else if ( scale <= 3.0 ) scale = 3.0;
else if ( scale <= 4.0 ) scale = 4.0;
else scale = 5.0;
return scale;
},
shouldZoom: function( scale ) {
var t = this;
// Do not operate on hidden frames.
if ( "innerWidth" in window && !window.innerWidth )
return false;
// Don't do anything until scale > 1
if ( scale == 1.0 && t.zoomed == false )
return false;
return true;
},
zoomImages: function() {
var t = this;
var scale = t.getScale();
if ( ! t.shouldZoom( scale ) ){
return;
}
t.zoomed = true;
// Loop through all the elements on the page.
var imgs = document.getElementsByTagName("img");
for ( var i = 0; i < imgs.length; i++ ) {
// Wait for original images to load
if ( "complete" in imgs[i] && ! imgs[i].complete )
continue;
// Skip images that have srcset attributes.
if ( imgs[i].hasAttribute('srcset') ) {
continue;
}
// Skip images that don't need processing.
var imgScale = imgs[i].getAttribute("scale");
if ( imgScale == scale || imgScale == "0" )
continue;
// Skip images that have already failed at this scale
var scaleFail = imgs[i].getAttribute("scale-fail");
if ( scaleFail && scaleFail <= scale )
continue;
// Skip images that have no dimensions yet.
if ( ! ( imgs[i].width && imgs[i].height ) )
continue;
// Skip images from Lazy Load plugins
if ( ! imgScale && imgs[i].getAttribute("data-lazy-src") && (imgs[i].getAttribute("data-lazy-src") !== imgs[i].getAttribute("src")))
continue;
if ( t.scaleImage( imgs[i], scale ) ) {
// Mark the img as having been processed at this scale.
imgs[i].setAttribute("scale", scale);
}
else {
// Set the flag to skip this image.
imgs[i].setAttribute("scale", "0");
}
}
},
scaleImage: function( img, scale ) {
var t = this;
var newSrc = img.src;
var isFiles = false;
var isLatex = false;
var isPhoton = false;
// Skip slideshow images
if ( img.parentNode.className.match(/slideshow-slide/) )
return false;
// Scale gravatars that have ?s= or ?size=
if ( img.src.match( /^https?:\/\/([^\/]*\.)?gravatar\.com\/.+[?&](s|size)=/ ) ) {
if ( this.hintsFor( "gravatar" ) === true ) {
return false;
}
newSrc = img.src.replace( /([?&](s|size)=)(\d+)/, function( $0, $1, $2, $3 ) {
// Stash the original size
var originalAtt = "originals",
originalSize = img.getAttribute(originalAtt);
if ( originalSize === null ) {
originalSize = $3;
img.setAttribute(originalAtt, originalSize);
if ( t.imgNeedsSizeAtts( img ) ) {
// Fix width and height attributes to rendered dimensions.
img.width = img.width;
img.height = img.height;
}
}
// Get the width/height of the image in CSS pixels
var size = img.clientWidth;
// Convert CSS pixels to device pixels
var targetSize = Math.ceil(img.clientWidth * scale);
// Don't go smaller than the original size
targetSize = Math.max( targetSize, originalSize );
// Don't go larger than the service supports
targetSize = Math.min( targetSize, 512 );
return $1 + targetSize;
});
}
// Scale mshots that have width
else if ( img.src.match(/^https?:\/\/([^\/]+\.)*(wordpress|wp)\.com\/mshots\/.+[?&]w=\d+/) ) {
if ( this.hintsFor( "mshots" ) === true ) {
return false;
}
newSrc = img.src.replace( /([?&]w=)(\d+)/, function($0, $1, $2) {
// Stash the original size
var originalAtt = 'originalw', originalSize = img.getAttribute(originalAtt);
if ( originalSize === null ) {
originalSize = $2;
img.setAttribute(originalAtt, originalSize);
if ( t.imgNeedsSizeAtts( img ) ) {
// Fix width and height attributes to rendered dimensions.
img.width = img.width;
img.height = img.height;
}
}
// Get the width of the image in CSS pixels
var size = img.clientWidth;
// Convert CSS pixels to device pixels
var targetSize = Math.ceil(size * scale);
// Don't go smaller than the original size
targetSize = Math.max( targetSize, originalSize );
// Don't go bigger unless the current one is actually lacking
if ( scale > img.getAttribute("scale") && targetSize <= img.naturalWidth )
targetSize = $2;
if ( $2 != targetSize )
return $1 + targetSize;
return $0;
});
// Update height attribute to match width
newSrc = newSrc.replace( /([?&]h=)(\d+)/, function($0, $1, $2) {
if ( newSrc == img.src ) {
return $0;
}
// Stash the original size
var originalAtt = 'originalh', originalSize = img.getAttribute(originalAtt);
if ( originalSize === null ) {
originalSize = $2;
img.setAttribute(originalAtt, originalSize);
}
// Get the height of the image in CSS pixels
var size = img.clientHeight;
// Convert CSS pixels to device pixels
var targetSize = Math.ceil(size * scale);
// Don't go smaller than the original size
targetSize = Math.max( targetSize, originalSize );
// Don't go bigger unless the current one is actually lacking
if ( scale > img.getAttribute("scale") && targetSize <= img.naturalHeight )
targetSize = $2;
if ( $2 != targetSize )
return $1 + targetSize;
return $0;
});
}
// Scale simple imgpress queries (s0.wp.com) that only specify w/h/fit
else if ( img.src.match(/^https?:\/\/([^\/.]+\.)*(wp|wordpress)\.com\/imgpress\?(.+)/) ) {
if ( this.hintsFor( "imgpress" ) === true ) {
return false;
}
var imgpressSafeFunctions = ["zoom", "url", "h", "w", "fit", "filter", "brightness", "contrast", "colorize", "smooth", "unsharpmask"];
// Search the query string for unsupported functions.
var qs = RegExp.$3.split('&');
for ( var q in qs ) {
q = qs[q].split('=')[0];
if ( imgpressSafeFunctions.indexOf(q) == -1 ) {
return false;
}
}
// Fix width and height attributes to rendered dimensions.
img.width = img.width;
img.height = img.height;
// Compute new src
if ( scale == 1 )
newSrc = img.src.replace(/\?(zoom=[^&]+&)?/, '?');
else
newSrc = img.src.replace(/\?(zoom=[^&]+&)?/, '?zoom=' + scale + '&');
}
// Scale files.wordpress.com, LaTeX, or Photon images (i#.wp.com)
else if (
( isFiles = img.src.match(/^https?:\/\/([^\/]+)\.files\.wordpress\.com\/.+[?&][wh]=/) ) ||
( isLatex = img.src.match(/^https?:\/\/([^\/.]+\.)*(wp|wordpress)\.com\/latex\.php\?(latex|zoom)=(.+)/) ) ||
( isPhoton = img.src.match(/^https?:\/\/i[\d]{1}\.wp\.com\/(.+)/) )
) {
if ( false !== isFiles && this.hintsFor( "files" ) === true ) {
return false
}
if ( false !== isLatex && this.hintsFor( "latex" ) === true ) {
return false
}
if ( false !== isPhoton && this.hintsFor( "photon" ) === true ) {
return false
}
// Fix width and height attributes to rendered dimensions.
img.width = img.width;
img.height = img.height;
// Compute new src
if ( scale == 1 ) {
newSrc = img.src.replace(/\?(zoom=[^&]+&)?/, '?');
} else {
newSrc = img.src;
var url_var = newSrc.match( /([?&]w=)(\d+)/ );
if ( url_var !== null && url_var[2] ) {
newSrc = newSrc.replace( url_var[0], url_var[1] + img.width );
}
url_var = newSrc.match( /([?&]h=)(\d+)/ );
if ( url_var !== null && url_var[2] ) {
newSrc = newSrc.replace( url_var[0], url_var[1] + img.height );
}
var zoom_arg = '&zoom=2';
if ( !newSrc.match( /\?/ ) ) {
zoom_arg = '?zoom=2';
}
img.setAttribute( 'srcset', newSrc + zoom_arg + ' ' + scale + 'x' );
}
}
// Scale static assets that have a name matching *-1x.png or *@1x.png
else if ( img.src.match(/^https?:\/\/[^\/]+\/.*[-@]([12])x\.(gif|jpeg|jpg|png)(\?|$)/) ) {
if ( this.hintsFor( "staticAssets" ) === true ) {
return false;
}
// Fix width and height attributes to rendered dimensions.
img.width = img.width;
img.height = img.height;
var currentSize = RegExp.$1, newSize = currentSize;
if ( scale <= 1 )
newSize = 1;
else
newSize = 2;
if ( currentSize != newSize )
newSrc = img.src.replace(/([-@])[12]x\.(gif|jpeg|jpg|png)(\?|$)/, '$1'+newSize+'x.$2$3');
}
else {
return false;
}
// Don't set img.src unless it has changed. This avoids unnecessary reloads.
if ( newSrc != img.src ) {
// Store the original img.src
var prevSrc, origSrc = img.getAttribute("src-orig");
if ( !origSrc ) {
origSrc = img.src;
img.setAttribute("src-orig", origSrc);
}
// In case of error, revert img.src
prevSrc = img.src;
img.onerror = function(){
img.src = prevSrc;
if ( img.getAttribute("scale-fail") < scale )
img.setAttribute("scale-fail", scale);
img.onerror = null;
};
// Finally load the new image
img.src = newSrc;
}
return true;
}
};
wpcom_img_zoomer.init();
;
/* global pm, wpcom_reblog */
var jetpackLikesWidgetQueue = [];
var jetpackLikesWidgetBatch = [];
var jetpackLikesMasterReady = false;
function JetpackLikespostMessage( message, target ) {
if ( 'string' === typeof message ){
try {
message = JSON.parse( message );
} catch(e) {
return;
}
}
pm( {
target: target,
type: 'likesMessage',
data: message,
origin: '*'
} );
}
function JetpackLikesBatchHandler() {
var requests = [];
jQuery( 'div.jetpack-likes-widget-unloaded' ).each( function() {
if ( jetpackLikesWidgetBatch.indexOf( this.id ) > -1 ) {
return;
}
jetpackLikesWidgetBatch.push( this.id );
var regex = /like-(post|comment)-wrapper-(\d+)-(\d+)-(\w+)/,
match = regex.exec( this.id ),
info;
if ( ! match || match.length !== 5 ) {
return;
}
info = {
blog_id: match[2],
width: this.width
};
if ( 'post' === match[1] ) {
info.post_id = match[3];
} else if ( 'comment' === match[1] ) {
info.comment_id = match[3];
}
info.obj_id = match[4];
requests.push( info );
});
if ( requests.length > 0 ) {
JetpackLikespostMessage( { event: 'initialBatch', requests: requests }, window.frames['likes-master'] );
}
}
function JetpackLikesMessageListener( event, message ) {
var allowedOrigin, $container, $list, offset, rowLength, height, scrollbarWidth;
if ( 'undefined' === typeof event.event ) {
return;
}
// We only allow messages from one origin
allowedOrigin = window.location.protocol + '//widgets.wp.com';
if ( allowedOrigin !== message.origin ) {
return;
}
if ( 'masterReady' === event.event ) {
jQuery( document ).ready( function() {
jetpackLikesMasterReady = true;
var stylesData = {
event: 'injectStyles'
},
$sdTextColor = jQuery( '.sd-text-color' ),
$sdLinkColor = jQuery( '.sd-link-color' );
if ( jQuery( 'iframe.admin-bar-likes-widget' ).length > 0 ) {
JetpackLikespostMessage( { event: 'adminBarEnabled' }, window.frames[ 'likes-master' ] );
stylesData.adminBarStyles = {
background: jQuery( '#wpadminbar .quicklinks li#wp-admin-bar-wpl-like > a' ).css( 'background' ),
isRtl: ( 'rtl' === jQuery( '#wpadminbar' ).css( 'direction' ) )
};
}
if ( ! window.addEventListener ) {
jQuery( '#wp-admin-bar-admin-bar-likes-widget' ).hide();
}
stylesData.textStyles = {
color: $sdTextColor.css( 'color' ),
fontFamily: $sdTextColor.css( 'font-family' ),
fontSize: $sdTextColor.css( 'font-size' ),
direction: $sdTextColor.css( 'direction' ),
fontWeight: $sdTextColor.css( 'font-weight' ),
fontStyle: $sdTextColor.css( 'font-style' ),
textDecoration: $sdTextColor.css('text-decoration')
};
stylesData.linkStyles = {
color: $sdLinkColor.css('color'),
fontFamily: $sdLinkColor.css('font-family'),
fontSize: $sdLinkColor.css('font-size'),
textDecoration: $sdLinkColor.css('text-decoration'),
fontWeight: $sdLinkColor.css( 'font-weight' ),
fontStyle: $sdLinkColor.css( 'font-style' )
};
JetpackLikespostMessage( stylesData, window.frames[ 'likes-master' ] );
JetpackLikesBatchHandler();
jQuery( document ).on( 'inview', 'div.jetpack-likes-widget-unloaded', function() {
jetpackLikesWidgetQueue.push( this.id );
});
});
}
if ( 'showLikeWidget' === event.event ) {
jQuery( '#' + event.id + ' .post-likes-widget-placeholder' ).fadeOut( 'fast', function() {
jQuery( '#' + event.id + ' .post-likes-widget' ).fadeIn( 'fast', function() {
JetpackLikespostMessage( { event: 'likeWidgetDisplayed', blog_id: event.blog_id, post_id: event.post_id, obj_id: event.obj_id }, window.frames['likes-master'] );
});
});
}
if ( 'clickReblogFlair' === event.event ) {
wpcom_reblog.toggle_reblog_box_flair( event.obj_id );
}
if ( 'showOtherGravatars' === event.event ) {
$container = jQuery( '#likes-other-gravatars' );
$list = $container.find( 'ul' );
$container.hide();
$list.html( '' );
$container.find( '.likes-text span' ).text( event.total );
jQuery.each( event.likers, function( i, liker ) {
var element = jQuery( '
' );
element.addClass( liker.css_class );
element.find( 'a' ).
attr({
href: liker.profile_URL,
rel: 'nofollow',
target: '_parent'
}).
addClass( 'wpl-liker' );
element.find( 'img' ).
attr({
src: liker.avatar_URL,
alt: liker.name
}).
css({
width: '30px',
height: '30px',
paddingRight: '3px'
});
$list.append( element );
} );
offset = jQuery( '[name=\'' + event.parent + '\']' ).offset();
$container.css( 'left', offset.left + event.position.left - 10 + 'px' );
$container.css( 'top', offset.top + event.position.top - 33 + 'px' );
rowLength = Math.floor( event.width / 37 );
height = ( Math.ceil( event.likers.length / rowLength ) * 37 ) + 13;
if ( height > 204 ) {
height = 204;
}
$container.css( 'height', height + 'px' );
$container.css( 'width', rowLength * 37 - 7 + 'px' );
$list.css( 'width', rowLength * 37 + 'px' );
$container.fadeIn( 'slow' );
scrollbarWidth = $list[0].offsetWidth - $list[0].clientWidth;
if ( scrollbarWidth > 0 ) {
$container.width( $container.width() + scrollbarWidth );
$list.width( $list.width() + scrollbarWidth );
}
}
}
pm.bind( 'likesMessage', JetpackLikesMessageListener );
jQuery( document ).click( function( e ) {
var $container = jQuery( '#likes-other-gravatars' );
if ( $container.has( e.target ).length === 0 ) {
$container.fadeOut( 'slow' );
}
});
function JetpackLikesWidgetQueueHandler() {
var $wrapper, wrapperID, found;
if ( ! jetpackLikesMasterReady ) {
setTimeout( JetpackLikesWidgetQueueHandler, 500 );
return;
}
if ( jetpackLikesWidgetQueue.length > 0 ) {
// We may have a widget that needs creating now
found = false;
while( jetpackLikesWidgetQueue.length > 0 ) {
// Grab the first member of the queue that isn't already loading.
wrapperID = jetpackLikesWidgetQueue.splice( 0, 1 )[0];
if ( jQuery( '#' + wrapperID ).hasClass( 'jetpack-likes-widget-unloaded' ) ) {
found = true;
break;
}
}
if ( ! found ) {
setTimeout( JetpackLikesWidgetQueueHandler, 500 );
return;
}
} else if ( jQuery( 'div.jetpack-likes-widget-unloaded' ).length > 0 ) {
// Grab any unloaded widgets for a batch request
JetpackLikesBatchHandler();
// Get the next unloaded widget
wrapperID = jQuery( 'div.jetpack-likes-widget-unloaded' ).first()[0].id;
if ( ! wrapperID ) {
// Everything is currently loaded
setTimeout( JetpackLikesWidgetQueueHandler, 500 );
return;
}
}
if ( 'undefined' === typeof wrapperID ) {
setTimeout( JetpackLikesWidgetQueueHandler, 500 );
return;
}
$wrapper = jQuery( '#' + wrapperID );
$wrapper.find( 'iframe' ).remove();
if ( $wrapper.hasClass( 'slim-likes-widget' ) ) {
$wrapper.find( '.post-likes-widget-placeholder' ).after( '' );
} else {
$wrapper.find( '.post-likes-widget-placeholder' ).after( '' );
}
$wrapper.removeClass( 'jetpack-likes-widget-unloaded' ).addClass( 'jetpack-likes-widget-loading' );
$wrapper.find( 'iframe' ).load( function( e ) {
var $iframe = jQuery( e.target );
$wrapper.removeClass( 'jetpack-likes-widget-loading' ).addClass( 'jetpack-likes-widget-loaded' );
JetpackLikespostMessage( { event: 'loadLikeWidget', name: $iframe.attr( 'name' ), width: $iframe.width() }, window.frames[ 'likes-master' ] );
if ( $wrapper.hasClass( 'slim-likes-widget' ) ) {
$wrapper.find( 'iframe' ).Jetpack( 'resizeable' );
}
});
setTimeout( JetpackLikesWidgetQueueHandler, 250 );
}
JetpackLikesWidgetQueueHandler();
;
// WARNING: This file is distributed verbatim in Jetpack. There should be nothing WordPress.com specific in this file. @hide-in-jetpack
(function($){ // Open closure
// Local vars
var Scroller, ajaxurl, stats, type, text, totop;
// IE requires special handling
var isIE = ( -1 != navigator.userAgent.search( 'MSIE' ) );
if ( isIE ) {
var IEVersion = navigator.userAgent.match(/MSIE\s?(\d+)\.?\d*;/);
var IEVersion = parseInt( IEVersion[1] );
}
// HTTP ajaxurl when site is HTTPS causes Access-Control-Allow-Origin failure in Desktop and iOS Safari
if ( "https:" == document.location.protocol ) {
infiniteScroll.settings.ajaxurl = infiniteScroll.settings.ajaxurl.replace( "http://", "https://" );
}
/**
* Loads new posts when users scroll near the bottom of the page.
*/
Scroller = function( settings ) {
var self = this;
// Initialize our variables
this.id = settings.id;
this.body = $( document.body );
this.window = $( window );
this.element = $( '#' + settings.id );
this.wrapperClass = settings.wrapper_class;
this.ready = true;
this.disabled = false;
this.page = 1;
this.offset = settings.offset;
this.currentday = settings.currentday;
this.order = settings.order;
this.throttle = false;
this.handle = '
';
this.click_handle = settings.click_handle;
this.google_analytics = settings.google_analytics;
this.history = settings.history;
this.origURL = window.location.href;
this.pageCache = {};
// Footer settings
this.footer = $( '#infinite-footer' );
this.footer.wrap = settings.footer;
// Core's native MediaElement.js implementation needs special handling
this.wpMediaelement = null;
// We have two type of infinite scroll
// cases 'scroll' and 'click'
if ( type == 'scroll' ) {
// Bind refresh to the scroll event
// Throttle to check for such case every 300ms
// On event the case becomes a fact
this.window.bind( 'scroll.infinity', function() {
this.throttle = true;
});
// Go back top method
self.gotop();
setInterval( function() {
if ( this.throttle ) {
// Once the case is the case, the action occurs and the fact is no more
this.throttle = false;
// Reveal or hide footer
self.thefooter();
// Fire the refresh
self.refresh();
self.determineURL(); // determine the url
}
}, 250 );
// Ensure that enough posts are loaded to fill the initial viewport, to compensate for short posts and large displays.
self.ensureFilledViewport();
this.body.bind( 'post-load', { self: self }, self.checkViewportOnLoad );
} else if ( type == 'click' ) {
if ( this.click_handle ) {
this.element.append( this.handle );
}
this.body.delegate( '#infinite-handle', 'click.infinity', function() {
// Handle the handle
if ( self.click_handle ) {
$( '#infinite-handle' ).remove();
}
// Fire the refresh
self.refresh();
});
}
// Initialize any Core audio or video players loaded via IS
this.body.bind( 'post-load', { self: self }, self.initializeMejs );
};
/**
* Check whether we should fetch any additional posts.
*/
Scroller.prototype.check = function() {
var container = this.element.offset();
// If the container can't be found, stop otherwise errors result
if ( 'object' !== typeof container ) {
return false;
}
var bottom = this.window.scrollTop() + this.window.height(),
threshold = container.top + this.element.outerHeight(false) - (this.window.height() * 2);
return bottom > threshold;
};
/**
* Renders the results from a successful response.
*/
Scroller.prototype.render = function( response ) {
this.body.addClass( 'infinity-success' );
// Check if we can wrap the html
this.element.append( response.html );
this.body.trigger( 'post-load', response );
this.ready = true;
};
/**
* Returns the object used to query for new posts.
*/
Scroller.prototype.query = function() {
return {
page : this.page,
currentday : this.currentday,
order : this.order,
scripts : window.infiniteScroll.settings.scripts,
styles : window.infiniteScroll.settings.styles,
query_args : window.infiniteScroll.settings.query_args,
last_post_date : window.infiniteScroll.settings.last_post_date
};
};
/**
* Scroll back to top.
*/
Scroller.prototype.gotop = function() {
var blog = $( '#infinity-blog-title' );
blog.attr( 'title', totop );
// Scroll to top on blog title
blog.bind( 'click', function( e ) {
$( 'html, body' ).animate( { scrollTop: 0 }, 'fast' );
e.preventDefault();
});
};
/**
* The infinite footer.
*/
Scroller.prototype.thefooter = function() {
var self = this,
width;
// Check if we have an id for the page wrapper
if ( $.type( this.footer.wrap ) === "string" ) {
width = $( 'body #' + this.footer.wrap ).outerWidth( false );
// Make the footer match the width of the page
if ( width > 479 )
this.footer.find( '.container' ).css( 'width', width );
}
// Reveal footer
if ( this.window.scrollTop() >= 350 )
self.footer.animate( { 'bottom': 0 }, 'fast' );
else if ( this.window.scrollTop() < 350 )
self.footer.animate( { 'bottom': '-50px' }, 'fast' );
};
/**
* Controls the flow of the refresh. Don't mess.
*/
Scroller.prototype.refresh = function() {
var self = this,
query, jqxhr, load, loader, color, customized;
// If we're disabled, ready, or don't pass the check, bail.
if ( this.disabled || ! this.ready || ! this.check() )
return;
// Let's get going -- set ready to false to prevent
// multiple refreshes from occurring at once.
this.ready = false;
// Create a loader element to show it's working.
if ( this.click_handle ) {
loader = '';
this.element.append( loader );
loader = this.element.find( '.infinite-loader' );
color = loader.css( 'color' );
try {
loader.spin( 'medium-left', color );
} catch ( error ) { }
}
// Generate our query vars.
query = $.extend({
action: 'infinite_scroll'
}, this.query() );
// Inject Customizer state.
if ( 'undefined' !== typeof wp && wp.customize && wp.customize.settings.theme ) {
customized = {};
query.wp_customize = 'on';
query.theme = wp.customize.settings.theme.stylesheet;
wp.customize.each( function( setting ) {
if ( setting._dirty ) {
customized[ setting.id ] = setting();
}
} );
query.customized = JSON.stringify( customized );
query.nonce = wp.customize.settings.nonce.preview;
}
// Fire the ajax request.
jqxhr = $.post( infiniteScroll.settings.ajaxurl, query );
// Allow refreshes to occur again if an error is triggered.
jqxhr.fail( function() {
if ( self.click_handle ) {
loader.hide();
}
self.ready = true;
});
// Success handler
jqxhr.done( function( response ) {
// On success, let's hide the loader circle.
if ( self.click_handle ) {
loader.hide();
}
// Check for and parse our response.
if ( ! response || ! response.type ) {
return;
}
// If we've succeeded...
if ( response.type == 'success' ) {
// If additional scripts are required by the incoming set of posts, parse them
if ( response.scripts ) {
$( response.scripts ).each( function() {
var elementToAppendTo = this.footer ? 'body' : 'head';
// Add script handle to list of those already parsed
window.infiniteScroll.settings.scripts.push( this.handle );
// Output extra data, if present
if ( this.extra_data ) {
var data = document.createElement('script'),
dataContent = document.createTextNode( "//" );
data.type = 'text/javascript';
data.appendChild( dataContent );
document.getElementsByTagName( elementToAppendTo )[0].appendChild(data);
}
// Build script tag and append to DOM in requested location
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = this.src;
script.id = this.handle;
// If MediaElement.js is loaded in by this set of posts, don't initialize the players a second time as it breaks them all
if ( 'wp-mediaelement' === this.handle ) {
self.body.unbind( 'post-load', self.initializeMejs );
}
if ( 'wp-mediaelement' === this.handle && 'undefined' === typeof mejs ) {
self.wpMediaelement = {};
self.wpMediaelement.tag = script;
self.wpMediaelement.element = elementToAppendTo;
setTimeout( self.maybeLoadMejs.bind( self ), 250 );
} else {
document.getElementsByTagName( elementToAppendTo )[0].appendChild(script);
}
} );
}
// If additional stylesheets are required by the incoming set of posts, parse them
if ( response.styles ) {
$( response.styles ).each( function() {
// Add stylesheet handle to list of those already parsed
window.infiniteScroll.settings.styles.push( this.handle );
// Build link tag
var style = document.createElement('link');
style.rel = 'stylesheet';
style.href = this.src;
style.id = this.handle + '-css';
// Destroy link tag if a conditional statement is present and either the browser isn't IE, or the conditional doesn't evaluate true
if ( this.conditional && ( ! isIE || ! eval( this.conditional.replace( /%ver/g, IEVersion ) ) ) )
var style = false;
// Append link tag if necessary
if ( style )
document.getElementsByTagName('head')[0].appendChild(style);
} );
}
// stash the response in the page cache
self.pageCache[self.page] = response;
// Increment the page number
self.page++;
// Record pageview in WP Stats, if available.
if ( stats )
new Image().src = document.location.protocol + '//pixel.wp.com/g.gif?' + stats + '&post=0&baba=' + Math.random();
// Add new posts to the postflair object
if ( 'object' == typeof response.postflair && 'object' == typeof WPCOM_sharing_counts )
WPCOM_sharing_counts = $.extend( WPCOM_sharing_counts, response.postflair );
// Render the results
self.render.apply( self, arguments );
// If 'click' type and there are still posts to fetch, add back the handle
if ( type == 'click' ) {
if ( response.lastbatch ) {
if ( self.click_handle ) {
$( '#infinite-handle' ).remove();
// Update body classes
self.body.addClass( 'infinity-end' ).removeClass( 'infinity-success' );
} else {
self.body.trigger( 'infinite-scroll-posts-end' );
}
} else {
if ( self.click_handle ) {
self.element.append( self.handle );
} else {
self.body.trigger( 'infinite-scroll-posts-more' );
}
}
} else if ( response.lastbatch ) {
self.disabled = true;
self.body.addClass( 'infinity-end' ).removeClass( 'infinity-success' );
}
// Update currentday to the latest value returned from the server
if ( response.currentday ) {
self.currentday = response.currentday;
}
// Fire Google Analytics pageview
if ( self.google_analytics ) {
var ga_url = self.history.path.replace( /%d/, self.page );
if ( 'object' === typeof _gaq ) {
_gaq.push( [ '_trackPageview', ga_url ] );
}
if ( 'function' === typeof ga ) {
ga( 'send', 'pageview', ga_url );
}
}
}
});
return jqxhr;
};
/**
* Core's native media player uses MediaElement.js
* The library's size is sufficient that it may not be loaded in time for Core's helper to invoke it, so we need to delay until `mejs` exists.
*/
Scroller.prototype.maybeLoadMejs = function() {
if ( null === this.wpMediaelement ) {
return;
}
if ( 'undefined' === typeof mejs ) {
setTimeout( this.maybeLoadMejs, 250 );
} else {
document.getElementsByTagName( this.wpMediaelement.element )[0].appendChild( this.wpMediaelement.tag );
this.wpMediaelement = null;
// Ensure any subsequent IS loads initialize the players
this.body.bind( 'post-load', { self: this }, this.initializeMejs );
}
}
/**
* Initialize the MediaElement.js player for any posts not previously initialized
*/
Scroller.prototype.initializeMejs = function( ev, response ) {
// Are there media players in the incoming set of posts?
if ( ! response.html || -1 === response.html.indexOf( 'wp-audio-shortcode' ) && -1 === response.html.indexOf( 'wp-video-shortcode' ) ) {
return;
}
// Don't bother if mejs isn't loaded for some reason
if ( 'undefined' === typeof mejs ) {
return;
}
// Adapted from wp-includes/js/mediaelement/wp-mediaelement.js
// Modified to not initialize already-initialized players, as Mejs doesn't handle that well
$(function () {
var settings = {};
if ( typeof _wpmejsSettings !== 'undefined' ) {
settings.pluginPath = _wpmejsSettings.pluginPath;
}
settings.success = function (mejs) {
var autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay;
if ( 'flash' === mejs.pluginType && autoplay ) {
mejs.addEventListener( 'canplay', function () {
mejs.play();
}, false );
}
};
$('.wp-audio-shortcode, .wp-video-shortcode').not( '.mejs-container' ).mediaelementplayer( settings );
});
}
/**
* Trigger IS to load additional posts if the initial posts don't fill the window.
* On large displays, or when posts are very short, the viewport may not be filled with posts, so we overcome this by loading additional posts when IS initializes.
*/
Scroller.prototype.ensureFilledViewport = function() {
var self = this,
windowHeight = self.window.height(),
postsHeight = self.element.height(),
aveSetHeight = 0,
wrapperQty = 0;
// Account for situations where postsHeight is 0 because child list elements are floated
if ( postsHeight === 0 ) {
$( self.element.selector + ' > li' ).each( function() {
postsHeight += $( this ).height();
} );
if ( postsHeight === 0 ) {
self.body.unbind( 'post-load', self.checkViewportOnLoad );
return;
}
}
// Calculate average height of a set of posts to prevent more posts than needed from being loaded.
$( '.' + self.wrapperClass ).each( function() {
aveSetHeight += $( this ).height();
wrapperQty++;
} );
if ( wrapperQty > 0 )
aveSetHeight = aveSetHeight / wrapperQty;
else
aveSetHeight = 0;
// Load more posts if space permits, otherwise stop checking for a full viewport
if ( postsHeight < windowHeight && ( postsHeight + aveSetHeight < windowHeight ) ) {
self.ready = true;
self.refresh();
}
else {
self.body.unbind( 'post-load', self.checkViewportOnLoad );
}
}
/**
* Event handler for ensureFilledViewport(), tied to the post-load trigger.
* Necessary to ensure that the variable `this` contains the scroller when used in ensureFilledViewport(). Since this function is tied to an event, `this` becomes the DOM element the event is tied to.
*/
Scroller.prototype.checkViewportOnLoad = function( ev ) {
ev.data.self.ensureFilledViewport();
}
/**
* Identify archive page that corresponds to majority of posts shown in the current browser window.
*/
Scroller.prototype.determineURL = function () {
var self = this,
windowTop = $( window ).scrollTop(),
windowBottom = windowTop + $( window ).height(),
windowSize = windowBottom - windowTop,
setsInView = [],
setsHidden = [],
pageNum = false;
// Find out which sets are in view
$( '.' + self.wrapperClass ).each( function() {
var id = $( this ).attr( 'id' ),
setTop = $( this ).offset().top,
setHeight = $( this ).outerHeight( false ),
setBottom = 0,
setPageNum = $( this ).data( 'page-num' );
// Account for containers that have no height because their children are floated elements.
if ( 0 === setHeight ) {
$( '> *', this ).each( function() {
setHeight += $( this ).outerHeight( false );
} );
}
// Determine position of bottom of set by adding its height to the scroll position of its top.
setBottom = setTop + setHeight;
// Populate setsInView object. While this logic could all be combined into a single conditional statement, this is easier to understand.
if ( setTop < windowTop && setBottom > windowBottom ) { // top of set is above window, bottom is below
setsInView.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
}
else if( setTop > windowTop && setTop < windowBottom ) { // top of set is between top (gt) and bottom (lt)
setsInView.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
}
else if( setBottom > windowTop && setBottom < windowBottom ) { // bottom of set is between top (gt) and bottom (lt)
setsInView.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
} else {
setsHidden.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
}
} );
$.each(setsHidden, function() {
var $set = $('#' + this.id);
if( $set.hasClass( 'is--replaced' ) ) {
return;
}
self.pageCache[ this.pageNum].html = $set.html();
$set.css('min-height', ( this.bottom - this.top ) + 'px' )
.addClass('is--replaced')
.empty();
});
$.each(setsInView, function() {
var $set = $('#' + this.id);
if( $set.hasClass('is--replaced') ) {
$set.css('min-height', '').removeClass('is--replaced');
if( this.pageNum in self.pageCache ) {
$set.html( self.pageCache[this.pageNum].html );
self.body.trigger( 'post-load', self.pageCache[this.pageNum] );
}
}
});
// Parse number of sets found in view in an attempt to update the URL to match the set that comprises the majority of the window.
if ( 0 == setsInView.length ) {
pageNum = -1;
}
else if ( 1 == setsInView.length ) {
var setData = setsInView.pop();
// If the first set of IS posts is in the same view as the posts loaded in the template by WordPress, determine how much of the view is comprised of IS-loaded posts
if ( ( ( windowBottom - setData.top ) / windowSize ) < 0.5 )
pageNum = -1;
else
pageNum = setData.pageNum;
}
else {
var majorityPercentageInView = 0;
// Identify the IS set that comprises the majority of the current window and set the URL to it.
$.each( setsInView, function( i, setData ) {
var topInView = 0,
bottomInView = 0,
percentOfView = 0;
// Figure percentage of view the current set represents
if ( setData.top > windowTop && setData.top < windowBottom )
topInView = ( windowBottom - setData.top ) / windowSize;
if ( setData.bottom > windowTop && setData.bottom < windowBottom )
bottomInView = ( setData.bottom - windowTop ) / windowSize;
// Figure out largest percentage of view for current set
if ( topInView >= bottomInView )
percentOfView = topInView;
else if ( bottomInView >= topInView )
percentOfView = bottomInView;
// Does current set's percentage of view supplant the largest previously-found set?
if ( percentOfView > majorityPercentageInView ) {
pageNum = setData.pageNum;
majorityPercentageInView = percentOfView;
}
} );
}
// If a page number could be determined, update the URL
// -1 indicates that the original requested URL should be used.
if ( 'number' == typeof pageNum ) {
if ( pageNum != -1 )
pageNum++;
self.updateURL( pageNum );
}
}
/**
* Update address bar to reflect archive page URL for a given page number.
* Checks if URL is different to prevent pollution of browser history.
*/
Scroller.prototype.updateURL = function( page ) {
// IE only supports pushState() in v10 and above, so don't bother if those conditions aren't met.
if ( ! window.history.pushState ) {
return;
}
var self = this,
offset = self.offset > 0 ? self.offset - 1 : 0,
pageSlug = -1 == page ? self.origURL : window.location.protocol + '//' + self.history.host + self.history.path.replace( /%d/, page + offset ) + self.history.parameters;
if ( window.location.href != pageSlug ) {
history.pushState( null, null, pageSlug );
}
}
/**
* Pause scrolling.
*/
Scroller.prototype.pause = function() {
this.disabled = true;
};
/**
* Resume scrolling.
*/
Scroller.prototype.resume = function() {
this.disabled = false;
};
/**
* Ready, set, go!
*/
$( document ).ready( function() {
// Check for our variables
if ( 'object' != typeof infiniteScroll )
return;
// Set ajaxurl (for brevity)
ajaxurl = infiniteScroll.settings.ajaxurl;
// Set stats, used for tracking stats
stats = infiniteScroll.settings.stats;
// Define what type of infinity we have, grab text for click-handle
type = infiniteScroll.settings.type;
text = infiniteScroll.settings.text;
totop = infiniteScroll.settings.totop;
// Initialize the scroller (with the ID of the element from the theme)
infiniteScroll.scroller = new Scroller( infiniteScroll.settings );
/**
* Monitor user scroll activity to update URL to correspond to archive page for current set of IS posts
*/
if( type == 'click' ) {
var timer = null;
$( window ).bind( 'scroll', function() {
// run the real scroll handler once every 250 ms.
if ( timer ) { return; }
timer = setTimeout( function() {
infiniteScroll.scroller.determineURL();
timer = null;
} , 250 );
});
}
// Integrate with Selective Refresh in the Customizer.
if ( 'undefined' !== typeof wp && wp.customize && wp.customize.selectiveRefresh ) {
/**
* Handle rendering of selective refresh partials.
*
* Make sure that when a partial is rendered, the Jetpack post-load event
* will be triggered so that any dynamic elements will be re-constructed,
* such as ME.js elements, Photon replacements, social sharing, and more.
* Note that this is applying here not strictly to posts being loaded.
* If a widget contains a ME.js element and it is previewed via selective
* refresh, the post-load would get triggered allowing any dynamic elements
* therein to also be re-constructed.
*
* @param {wp.customize.selectiveRefresh.Placement} placement
*/
wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
var content;
if ( 'string' === typeof placement.addedContent ) {
content = placement.addedContent;
} else if ( placement.container ) {
content = $( placement.container ).html();
}
if ( content ) {
$( document.body ).trigger( 'post-load', { html: content } );
}
} );
/*
* Add partials for posts added via infinite scroll.
*
* This is unnecessary when MutationObserver is supported by the browser
* since then this will be handled by Selective Refresh in core.
*/
if ( 'undefined' === typeof MutationObserver ) {
$( document.body ).on( 'post-load', function( e, response ) {
var rootElement = null;
if ( response.html && -1 !== response.html.indexOf( 'data-customize-partial' ) ) {
if ( infiniteScroll.settings.id ) {
rootElement = $( '#' + infiniteScroll.settings.id );
}
wp.customize.selectiveRefresh.addPartials( rootElement );
}
} );
}
}
});
})(jQuery); // Close closure
;
/* jshint ignore:start */
!function(d,s,id){
var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';
if(!d.getElementById(id)){
js=d.createElement(s);
js.id=id;js.src=p+"://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);
}
}(document,"script","twitter-wjs");
/* jshint ignore:end */
;
/***
* Warning: This file is remotely enqueued in Jetpack's Masterbar module.
* Changing it will also affect Jetpack sites.
*/
jQuery( document ).ready( function( $, wpcom ) {
var masterbar,
menupops = $( 'li#wp-admin-bar-blog.menupop, li#wp-admin-bar-newdash.menupop, li#wp-admin-bar-my-account.menupop' ),
newmenu = $( '#wp-admin-bar-new-post-types' );
// Unbind hoverIntent, we want clickable menus.
menupops
.unbind( 'mouseenter mouseleave' )
.removeProp( 'hoverIntent_t' )
.removeProp( 'hoverIntent_s' )
.on( 'mouseover', function(e) {
var li = $(e.target).closest( 'li.menupop' );
menupops.not(li).removeClass( 'ab-hover' );
li.toggleClass( 'ab-hover' );
} )
.on( 'click touchstart', function(e) {
var $target = $( e.target );
if ( masterbar.focusSubMenus( $target ) ) {
return;
}
e.preventDefault();
masterbar.toggleMenu( $target );
} );
masterbar = {
focusSubMenus: function( $target ) {
// Handle selection of menu items
if ( ! $target.closest( 'ul' ).hasClass( 'ab-top-menu' ) ) {
$target
.closest( 'li' );
return true;
}
return false;
},
toggleMenu: function( $target ) {
var $li = $target.closest( 'li.menupop' ),
$html = $( 'html' );
$( 'body' ).off( 'click.ab-menu' );
$( '#wpadminbar li.menupop' ).not($li).removeClass( 'ab-active wpnt-stayopen wpnt-show' );
if ( $li.hasClass( 'ab-active' ) ) {
$li.removeClass( 'ab-active' );
$html.removeClass( 'ab-menu-open' );
} else {
$li.addClass( 'ab-active' );
$html.addClass( 'ab-menu-open' );
$( 'body' ).on( 'click.ab-menu', function( e ) {
if ( ! $( e.target ).parents( '#wpadminbar' ).length ) {
e.preventDefault();
masterbar.toggleMenu( $li );
$( 'body' ).off( 'click.ab-menu' );
}
} );
}
}
};
} );;
/*globals JSON */
( function( $ ) {
var eventName = 'wpcom_masterbar_click';
var linksTracksEvents = {
//top level items
'wp-admin-bar-blog' : 'my_sites',
'wp-admin-bar-newdash' : 'reader',
'wp-admin-bar-ab-new-post' : 'write_button',
'wp-admin-bar-my-account' : 'my_account',
'wp-admin-bar-notes' : 'notifications',
//my sites - top items
'wp-admin-bar-switch-site' : 'my_sites_switch_site',
'wp-admin-bar-blog-info' : 'my_sites_site_info',
'wp-admin-bar-site-view' : 'my_sites_view_site',
'wp-admin-bar-blog-stats' : 'my_sites_site_stats',
'wp-admin-bar-plan' : 'my_sites_plan',
'wp-admin-bar-plan-badge' : 'my_sites_plan_badge',
//my sites - manage
'wp-admin-bar-edit-page' : 'my_sites_manage_site_pages',
'wp-admin-bar-new-page-badge' : 'my_sites_manage_add_page',
'wp-admin-bar-edit-post' : 'my_sites_manage_blog_posts',
'wp-admin-bar-new-post-badge' : 'my_sites_manage_add_post',
'wp-admin-bar-edit-attachment' : 'my_sites_manage_media',
'wp-admin-bar-new-attachment-badge' : 'my_sites_manage_add_media',
'wp-admin-bar-comments' : 'my_sites_manage_comments',
'wp-admin-bar-edit-jetpack-testimonial' : 'my_sites_manage_testimonials',
'wp-admin-bar-new-jetpack-testimonial' : 'my_sites_manage_add_testimonial',
'wp-admin-bar-edit-jetpack-portfolio' : 'my_sites_manage_portfolio',
'wp-admin-bar-new-jetpack-portfolio' : 'my_sites_manage_add_portfolio',
//my sites - personalize
'wp-admin-bar-themes' : 'my_sites_personalize_themes',
'wp-admin-bar-cmz' : 'my_sites_personalize_themes_customize',
//my sites - configure
'wp-admin-bar-sharing' : 'my_sites_configure_sharing',
'wp-admin-bar-people' : 'my_sites_configure_people',
'wp-admin-bar-people-add' : 'my_sites_configure_people_add_button',
'wp-admin-bar-plugins' : 'my_sites_configure_plugins',
'wp-admin-bar-domains' : 'my_sites_configure_domains',
'wp-admin-bar-domains-add' : 'my_sites_configure_add_domain',
'wp-admin-bar-blog-settings' : 'my_sites_configure_settings',
'wp-admin-bar-legacy-dashboard' : 'my_sites_configure_wp_admin',
//reader
'wp-admin-bar-followed-sites' : 'reader_followed_sites',
'wp-admin-bar-reader-followed-sites-manage': 'reader_manage_followed_sites',
'wp-admin-bar-discover-discover' : 'reader_discover',
'wp-admin-bar-discover-search' : 'reader_search',
'wp-admin-bar-my-activity-my-likes' : 'reader_my_likes',
//account
'wp-admin-bar-user-info' : 'my_account_user_name',
// account - profile
'wp-admin-bar-my-profile' : 'my_account_profile_my_profile',
'wp-admin-bar-account-settings' : 'my_account_profile_account_settings',
'wp-admin-bar-billing' : 'my_account_profile_manage_purchases',
'wp-admin-bar-security' : 'my_account_profile_security',
'wp-admin-bar-notifications' : 'my_account_profile_notifications',
//account - special
'wp-admin-bar-get-apps' : 'my_account_special_get_apps',
'wp-admin-bar-next-steps' : 'my_account_special_next_steps',
'wp-admin-bar-help' : 'my_account_special_help',
};
var notesTracksEvents = {
openSite: function( data ) {
return {
clicked: 'masterbar_notifications_panel_site',
site_id: data.siteId
};
},
openPost: function( data ) {
return {
clicked: 'masterbar_notifications_panel_post',
site_id: data.siteId,
post_id: data.postId
};
},
openComment: function( data ) {
return {
clicked: 'masterbar_notifications_panel_comment',
site_id: data.siteId,
post_id: data.postId,
comment_id: data.commentId
};
}
};
function recordTracksEvent( eventProps ) {
eventProps = eventProps || {};
window._tkq = window._tkq || [];
window._tkq.push( [ 'recordEvent', eventName, eventProps ] );
}
function parseJson( s, defaultValue ) {
try {
return JSON.parse( s );
} catch ( e ) {
return defaultValue;
}
}
$( document ).ready( function() {
var trackableLinks = '.mb-trackable .ab-item:not(div),' +
'#wp-admin-bar-notes .ab-item,' +
'#wp-admin-bar-user-info .ab-item,' +
'.mb-trackable .ab-secondary';
$( trackableLinks ).on( 'click touchstart', function( e ) {
var $target = $( e.target ),
$parent = $target.closest( 'li' );
if ( ! $parent ) {
return;
}
var trackingId = $target.attr( 'ID' ) || $parent.attr( 'ID' );
if ( ! linksTracksEvents.hasOwnProperty( trackingId ) ) {
return;
}
var eventProps = { 'clicked': linksTracksEvents[ trackingId ] };
recordTracksEvent( eventProps );
} );
} );
// listen for postMessage events from the notifications iframe
$( window ).on( 'message', function( e ) {
var event = ! e.data && e.originalEvent.data ? e.originalEvent : event;
if ( event.origin !== 'https://widgets.wp.com' ) {
return;
}
var data = ( 'string' === typeof event.data ) ? parseJson( event.data, {} ) : event.data;
if ( 'notesIframeMessage' !== data.type ) {
return;
}
var eventData = notesTracksEvents[ data.action ];
if ( ! eventData ) {
return;
}
recordTracksEvent( eventData( data ) );
} );
} )( jQuery );
;
var wpcom = window.wpcom || {};
wpcom.actionbar = {};
wpcom.actionbar.data = actionbardata;
// This might be better in another file, but is here for now
(function($){
var fbd = wpcom.actionbar.data,
d = document,
docHeight = $( d ).height(),
b = d.getElementsByTagName( 'body' )[0],
lastScrollTop = 0,
lastScrollDir, fb, fhtml, fbhtml, fbHtmlLi,
followingbtn, followbtn, fbdf, action,
slkhtml = '', foldhtml = '', reporthtml = '',
customizeIcon, editIcon, statsIcon, themeHtml = '', signupHtml = '', loginHtml = '',
viewReaderHtml = '', editSubsHtml = '', editFollowsHtml = '',
toggleactionbar, $actionbar;
// Don't show actionbar when iframed
if ( window != window.top ) {
return;
}
fhtml = '