/* 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();
;
/*! Responsive JS Library v1.2.2 */
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
window.matchMedia = window.matchMedia || (function(doc, undefined){
var bool,
docElem = doc.documentElement,
refNode = docElem.firstElementChild || docElem.firstChild,
// fakeBody required for
fakeBody = doc.createElement('body'),
div = doc.createElement('div');
div.id = 'mq-test-1';
div.style.cssText = "position:absolute;top:-100em";
fakeBody.style.background = "none";
fakeBody.appendChild(div);
return function(q){
div.innerHTML = '';
docElem.insertBefore(fakeBody, refNode);
bool = div.offsetWidth == 42;
docElem.removeChild(fakeBody);
return { matches: bool, media: q };
};
})(document);
/*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
(function( win ){
//exposed namespace
win.respond = {};
//define update even in native-mq-supporting browsers, to avoid errors
respond.update = function(){};
//expose media query support flag for external use
respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches;
//if media queries are supported, exit here
if( respond.mediaQueriesSupported ){ return; }
//define vars
var doc = win.document,
docElem = doc.documentElement,
mediastyles = [],
rules = [],
appendedEls = [],
parsedSheets = {},
resizeThrottle = 30,
head = doc.getElementsByTagName( "head" )[0] || docElem,
base = doc.getElementsByTagName( "base" )[0],
links = head.getElementsByTagName( "link" ),
requestQueue = [],
//loop stylesheets, send text content to translate
ripCSS = function(){
var sheets = links,
sl = sheets.length,
i = 0,
//vars for loop:
sheet, href, media, isCSS;
for( ; i < sl; i++ ){
sheet = sheets[ i ],
href = sheet.href,
media = sheet.media,
isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
//only links plz and prevent re-parsing
if( !!href && isCSS && !parsedSheets[ href ] ){
// selectivizr exposes css through the rawCssText expando
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
translate( sheet.styleSheet.rawCssText, href, media );
parsedSheets[ href ] = true;
} else {
if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base)
|| href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
requestQueue.push( {
href: href,
media: media
} );
}
}
}
}
makeRequests();
},
//recurse through request queue, get css text
makeRequests = function(){
if( requestQueue.length ){
var thisRequest = requestQueue.shift();
ajax( thisRequest.href, function( styles ){
translate( styles, thisRequest.href, thisRequest.media );
parsedSheets[ thisRequest.href ] = true;
makeRequests();
} );
}
},
//find media blocks in css text, convert to style blocks
translate = function( styles, href, media ){
var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ),
ql = qs && qs.length || 0,
//try to get CSS path
href = href.substring( 0, href.lastIndexOf( "/" )),
repUrls = function( css ){
return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
},
useMedia = !ql && media,
//vars used in loop
i = 0,
j, fullq, thisq, eachq, eql;
//if path exists, tack on trailing slash
if( href.length ){ href += "/"; }
//if no internal queries exist, but media attr does, use that
//note: this currently lacks support for situations where a media attr is specified on a link AND
//its associated stylesheet has internal CSS media queries.
//In those cases, the media attribute will currently be ignored.
if( useMedia ){
ql = 1;
}
for( ; i < ql; i++ ){
j = 0;
//media attr
if( useMedia ){
fullq = media;
rules.push( repUrls( styles ) );
}
//parse for styles
else{
fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
}
eachq = fullq.split( "," );
eql = eachq.length;
for( ; j < eql; j++ ){
thisq = eachq[ j ];
mediastyles.push( {
media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
rules : rules.length - 1,
hasquery: thisq.indexOf("(") > -1,
minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
} );
}
}
applyMedia();
},
lastCall,
resizeDefer,
// returns the value of 1em in pixels
getEmValue = function() {
var ret,
div = doc.createElement('div'),
body = doc.body,
fakeUsed = false;
div.style.cssText = "position:absolute;font-size:1em;width:1em";
if( !body ){
body = fakeUsed = doc.createElement( "body" );
body.style.background = "none";
}
body.appendChild( div );
docElem.insertBefore( body, docElem.firstChild );
ret = div.offsetWidth;
if( fakeUsed ){
docElem.removeChild( body );
}
else {
body.removeChild( div );
}
//also update eminpx before returning
ret = eminpx = parseFloat(ret);
return ret;
},
//cached container for 1em value, populated the first time it's needed
eminpx,
//enable/disable styles
applyMedia = function( fromResize ){
var name = "clientWidth",
docElemProp = docElem[ name ],
currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
styleBlocks = {},
lastLink = links[ links.length-1 ],
now = (new Date()).getTime();
//throttle resize calls
if( fromResize && lastCall && now - lastCall < resizeThrottle ){
clearTimeout( resizeDefer );
resizeDefer = setTimeout( applyMedia, resizeThrottle );
return;
}
else {
lastCall = now;
}
for( var i in mediastyles ){
var thisstyle = mediastyles[ i ],
min = thisstyle.minw,
max = thisstyle.maxw,
minnull = min === null,
maxnull = max === null,
em = "em";
if( !!min ){
min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
}
if( !!max ){
max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
}
// if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true
if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
if( !styleBlocks[ thisstyle.media ] ){
styleBlocks[ thisstyle.media ] = [];
}
styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
}
}
//remove any existing respond style element(s)
for( var i in appendedEls ){
if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){
head.removeChild( appendedEls[ i ] );
}
}
//inject active styles, grouped by media type
for( var i in styleBlocks ){
var ss = doc.createElement( "style" ),
css = styleBlocks[ i ].join( "\n" );
ss.type = "text/css";
ss.media = i;
//originally, ss was appended to a documentFragment and sheets were appended in bulk.
//this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
head.insertBefore( ss, lastLink.nextSibling );
if ( ss.styleSheet ){
ss.styleSheet.cssText = css;
}
else {
ss.appendChild( doc.createTextNode( css ) );
}
//push to appendedEls to track for later removal
appendedEls.push( ss );
}
},
//tweaked Ajax functions from Quirksmode
ajax = function( url, callback ) {
var req = xmlHttp();
if (!req){
return;
}
req.open( "GET", url, true );
req.onreadystatechange = function () {
if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){
return;
}
callback( req.responseText );
}
if ( req.readyState == 4 ){
return;
}
req.send( null );
},
//define ajax obj
xmlHttp = (function() {
var xmlhttpmethod = false;
try {
xmlhttpmethod = new XMLHttpRequest();
}
catch( e ){
xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" );
}
return function(){
return xmlhttpmethod;
};
})();
//translate CSS
ripCSS();
//expose update for re-running respond later on
respond.update = ripCSS;
//adjust on resize
function callMedia(){
applyMedia( true );
}
if( win.addEventListener ){
win.addEventListener( "resize", callMedia, false );
}
else if( win.attachEvent ){
win.attachEvent( "onresize", callMedia );
}
})(this);
/**
* jQuery Friendly IE6 Upgrade Notice Plugin 1.0.0
*
* http://code.google.com/p/friendly-ie6-upgrade-notice/
*
* Copyright (c) 2013 Emil Uzelac - ThemeID
*
* http://www.gnu.org/licenses/gpl.html
*/
if (jQuery.browser.msie && jQuery.browser.version <= 6)
jQuery('').appendTo('#container');
/**
* jQuery Scroll Top Plugin 1.0.0
*/
jQuery(document).ready(function ($) {
$('a[href="#scroll-top"]').click(function () {
$('html, body').animate({
scrollTop: 0
}, 'slow');
return false;
});
});;
/**
* Handles toggling the main navigation menu for small screens.
*/
jQuery( document ).ready( function( $ ) {
var $masthead = $( '#header' ),
timeout = false;
$.fn.smallMenu = function() {
$masthead.find( '.site-navigation' ).removeClass( 'main-navigation' ).addClass( 'main-small-navigation' );
$masthead.find( '.site-navigation h1' ).removeClass( 'assistive-text' ).addClass( 'menu-toggle' );
$( '.menu-toggle' ).unbind( 'click' ).click( function() {
$masthead.find( '.menu' ).toggle();
$( this ).toggleClass( 'toggled-on' );
} );
};
// Check viewport width on first load.
if ( $( window ).width() < 651 )
$.fn.smallMenu();
// Check viewport width when user resizes the browser window.
$( window ).resize( function() {
var browserWidth = $( window ).width();
if ( false !== timeout )
clearTimeout( timeout );
timeout = setTimeout( function() {
if ( browserWidth < 651 ) {
$.fn.smallMenu();
} else {
$masthead.find( '.site-navigation' ).removeClass( 'main-small-navigation' ).addClass( 'main-navigation' );
$masthead.find( '.site-navigation h1' ).removeClass( 'menu-toggle' ).addClass( 'assistive-text' );
$masthead.find( '.menu' ).removeAttr( 'style' );
}
}, 200 );
} );
var container = $( '.site-navigation' );
// Fix child menus for touch devices.
function fixMenuTouchTaps( container ) {
var touchStartFn,
parentLink = container.find( '.menu-item-has-children > a, .page_item_has_children > a' );
if ( 'ontouchstart' in window ) {
touchStartFn = function( e ) {
var menuItem = this.parentNode;
if ( ! menuItem.classList.contains( 'focus' ) ) {
e.preventDefault();
for( var i = 0; i < menuItem.parentNode.children.length; ++i ) {
if ( menuItem === menuItem.parentNode.children[i] ) {
continue;
}
menuItem.parentNode.children[i].classList.remove( 'focus' );
}
menuItem.classList.add( 'focus' );
} else {
menuItem.classList.remove( 'focus' );
}
};
for ( var i = 0; i < parentLink.length; ++i ) {
parentLink[i].addEventListener( 'touchstart', touchStartFn, false )
}
}
}
fixMenuTouchTaps( container );
} );;
/* global WPCOM_sharing_counts, grecaptcha */
/* jshint unused:false */
var sharing_js_options;
if ( sharing_js_options && sharing_js_options.counts ) {
var WPCOMSharing = {
done_urls: [],
get_counts: function() {
var url, requests, id, service, service_request;
if ( 'undefined' === typeof WPCOM_sharing_counts ) {
return;
}
for ( url in WPCOM_sharing_counts ) {
id = WPCOM_sharing_counts[ url ];
if ( 'undefined' !== typeof WPCOMSharing.done_urls[ id ] ) {
continue;
}
requests = {
// Pinterest handles share counts for both http and https
pinterest: [
window.location.protocol +
'//api.pinterest.com/v1/urls/count.json?callback=WPCOMSharing.update_pinterest_count&url=' +
encodeURIComponent( url ),
],
// Facebook protocol summing has been shown to falsely double counts, so we only request the current URL
facebook: [
window.location.protocol +
'//graph.facebook.com/?callback=WPCOMSharing.update_facebook_count&ids=' +
encodeURIComponent( url ),
],
};
for ( service in requests ) {
if ( ! jQuery( 'a[data-shared=sharing-' + service + '-' + id + ']' ).length ) {
continue;
}
while ( ( service_request = requests[ service ].pop() ) ) {
jQuery.getScript( service_request );
}
if ( sharing_js_options.is_stats_active ) {
WPCOMSharing.bump_sharing_count_stat( service );
}
}
WPCOMSharing.done_urls[ id ] = true;
}
},
// get the version of the url that was stored in the dom (sharing-$service-URL)
get_permalink: function( url ) {
if ( 'https:' === window.location.protocol ) {
url = url.replace( /^http:\/\//i, 'https://' );
} else {
url = url.replace( /^https:\/\//i, 'http://' );
}
return url;
},
update_facebook_count: function( data ) {
var url, permalink;
if ( ! data ) {
return;
}
for ( url in data ) {
if (
! data.hasOwnProperty( url ) ||
! data[ url ].share ||
! data[ url ].share.share_count
) {
continue;
}
permalink = WPCOMSharing.get_permalink( url );
if ( ! ( permalink in WPCOM_sharing_counts ) ) {
continue;
}
WPCOMSharing.inject_share_count(
'sharing-facebook-' + WPCOM_sharing_counts[ permalink ],
data[ url ].share.share_count
);
}
},
update_pinterest_count: function( data ) {
if ( 'undefined' !== typeof data.count && data.count * 1 > 0 ) {
WPCOMSharing.inject_share_count(
'sharing-pinterest-' + WPCOM_sharing_counts[ data.url ],
data.count
);
}
},
inject_share_count: function( id, count ) {
var $share = jQuery( 'a[data-shared=' + id + '] > span' );
$share.find( '.share-count' ).remove();
$share.append(
'' + WPCOMSharing.format_count( count ) + ''
);
},
format_count: function( count ) {
if ( count < 1000 ) {
return count;
}
if ( count >= 1000 && count < 10000 ) {
return String( count ).substring( 0, 1 ) + 'K+';
}
return '10K+';
},
bump_sharing_count_stat: function( service ) {
new Image().src =
document.location.protocol +
'//pixel.wp.com/g.gif?v=wpcom-no-pv&x_sharing-count-request=' +
service +
'&r=' +
Math.random();
},
};
}
( function( $ ) {
var $body, $sharing_email;
$.fn.extend( {
share_is_email: function() {
return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(
this.val()
);
},
} );
$body = $( document.body ).on( 'post-load', WPCOMSharing_do );
$( document ).ready( function() {
$sharing_email = $( '#sharing_email' );
$body.append( $sharing_email );
WPCOMSharing_do();
} );
function WPCOMSharing_do() {
var $more_sharing_buttons;
if ( 'undefined' !== typeof WPCOMSharing ) {
WPCOMSharing.get_counts();
}
$more_sharing_buttons = $( '.sharedaddy a.sharing-anchor' );
$more_sharing_buttons.click( function() {
return false;
} );
$( '.sharedaddy a' ).each( function() {
if (
$( this ).attr( 'href' ) &&
$( this )
.attr( 'href' )
.indexOf( 'share=' ) !== -1
) {
$( this ).attr( 'href', $( this ).attr( 'href' ) + '&nb=1' );
}
} );
// Show hidden buttons
// Touchscreen device: use click.
// Non-touchscreen device: use click if not already appearing due to a hover event
$more_sharing_buttons.on( 'click', function() {
var $more_sharing_button = $( this ),
$more_sharing_pane = $more_sharing_button.parents( 'div:first' ).find( '.inner' );
if ( $more_sharing_pane.is( ':animated' ) ) {
// We're in the middle of some other event's animation
return;
}
if ( true === $more_sharing_pane.data( 'justSlid' ) ) {
// We just finished some other event's animation - don't process click event so that slow-to-react-clickers don't get confused
return;
}
$sharing_email.slideUp( 200 );
$more_sharing_pane
.css( {
left: $more_sharing_button.position().left + 'px',
top: $more_sharing_button.position().top + $more_sharing_button.height() + 3 + 'px',
} )
.slideToggle( 200 );
} );
if ( document.ontouchstart === undefined ) {
// Non-touchscreen device: use hover/mouseout with delay
$more_sharing_buttons.hover(
function() {
var $more_sharing_button = $( this ),
$more_sharing_pane = $more_sharing_button.parents( 'div:first' ).find( '.inner' ),
timer;
if ( ! $more_sharing_pane.is( ':animated' ) ) {
// Create a timer to make the area appear if the mouse hovers for a period
timer = setTimeout( function() {
var handler_item_leave,
handler_item_enter,
handler_original_leave,
handler_original_enter,
close_it;
$sharing_email.slideUp( 200 );
$more_sharing_pane.data( 'justSlid', true );
$more_sharing_pane
.css( {
left: $more_sharing_button.position().left + 'px',
top:
$more_sharing_button.position().top + $more_sharing_button.height() + 3 + 'px',
} )
.slideDown( 200, function() {
// Mark the item as have being appeared by the hover
$more_sharing_button.data( 'hasoriginal', true ).data( 'hasitem', false );
setTimeout( function() {
$more_sharing_pane.data( 'justSlid', false );
}, 300 );
$more_sharing_pane
.mouseleave( handler_item_leave )
.mouseenter( handler_item_enter );
$more_sharing_button
.mouseleave( handler_original_leave )
.mouseenter( handler_original_enter );
} );
// The following handlers take care of the mouseenter/mouseleave for the share button and the share area - if both are left then we close the share area
handler_item_leave = function() {
$more_sharing_button.data( 'hasitem', false );
if ( $more_sharing_button.data( 'hasoriginal' ) === false ) {
var timer = setTimeout( close_it, 800 );
$more_sharing_button.data( 'timer2', timer );
}
};
handler_item_enter = function() {
$more_sharing_button.data( 'hasitem', true );
clearTimeout( $more_sharing_button.data( 'timer2' ) );
};
handler_original_leave = function() {
$more_sharing_button.data( 'hasoriginal', false );
if ( $more_sharing_button.data( 'hasitem' ) === false ) {
var timer = setTimeout( close_it, 800 );
$more_sharing_button.data( 'timer2', timer );
}
};
handler_original_enter = function() {
$more_sharing_button.data( 'hasoriginal', true );
clearTimeout( $more_sharing_button.data( 'timer2' ) );
};
close_it = function() {
$more_sharing_pane.data( 'justSlid', true );
$more_sharing_pane.slideUp( 200, function() {
setTimeout( function() {
$more_sharing_pane.data( 'justSlid', false );
}, 300 );
} );
// Clear all hooks
$more_sharing_button
.unbind( 'mouseleave', handler_original_leave )
.unbind( 'mouseenter', handler_original_enter );
$more_sharing_pane
.unbind( 'mouseleave', handler_item_leave )
.unbind( 'mouseenter', handler_item_leave );
return false;
};
}, 200 );
// Remember the timer so we can detect it on the mouseout
$more_sharing_button.data( 'timer', timer );
}
},
function() {
// Mouse out - remove any timer
$more_sharing_buttons.each( function() {
clearTimeout( $( this ).data( 'timer' ) );
} );
$more_sharing_buttons.data( 'timer', false );
}
);
} else {
$( document.body ).addClass( 'jp-sharing-input-touch' );
}
$( document ).click( function() {
// Click outside
// remove any timer
$more_sharing_buttons.each( function() {
clearTimeout( $( this ).data( 'timer' ) );
} );
$more_sharing_buttons.data( 'timer', false );
// slide down forcibly
$( '.sharedaddy .inner' ).slideUp();
} );
// Add click functionality
$( '.sharedaddy ul' ).each( function() {
if ( 'yep' === $( this ).data( 'has-click-events' ) ) {
return;
}
$( this ).data( 'has-click-events', 'yep' );
var printUrl = function( uniqueId, urlToPrint ) {
$( 'body:first' ).append(
''
);
};
// Print button
$( this )
.find( 'a.share-print' )
.click( function() {
var ref = $( this ).attr( 'href' ),
do_print = function() {
if ( ref.indexOf( '#print' ) === -1 ) {
var uid = new Date().getTime();
printUrl( uid, ref );
} else {
print();
}
};
// Is the button in a dropdown?
if ( $( this ).parents( '.sharing-hidden' ).length > 0 ) {
$( this )
.parents( '.inner' )
.slideUp( 0, function() {
do_print();
} );
} else {
do_print();
}
return false;
} );
// Press This button
$( this )
.find( 'a.share-press-this' )
.click( function() {
var s = '';
if ( window.getSelection ) {
s = window.getSelection();
} else if ( document.getSelection ) {
s = document.getSelection();
} else if ( document.selection ) {
s = document.selection.createRange().text;
}
if ( s ) {
$( this ).attr( 'href', $( this ).attr( 'href' ) + '&sel=' + encodeURI( s ) );
}
if (
! window.open(
$( this ).attr( 'href' ),
't',
'toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=570'
)
) {
document.location.href = $( this ).attr( 'href' );
}
return false;
} );
// Email button
$( 'a.share-email', this ).on( 'click', function() {
var url = $( this ).attr( 'href' );
var currentDomain = window.location.protocol + '//' + window.location.hostname + '/';
if ( url.indexOf( currentDomain ) !== 0 ) {
return true;
}
if ( $sharing_email.is( ':visible' ) ) {
$sharing_email.slideUp( 200 );
} else {
$( '.sharedaddy .inner' ).slideUp();
$( '#sharing_email .response' ).remove();
$( '#sharing_email form' ).show();
$( '#sharing_email form input[type=submit]' ).removeAttr( 'disabled' );
$( '#sharing_email form a.sharing_cancel' ).show();
// Reset reCATPCHA if exists.
if (
'object' === typeof grecaptcha &&
'function' === typeof grecaptcha.reset &&
window.___grecaptcha_cfg.count
) {
grecaptcha.reset();
}
// Show dialog
$sharing_email
.css( {
left: $( this ).offset().left + 'px',
top: $( this ).offset().top + $( this ).height() + 'px',
} )
.slideDown( 200 );
// Hook up other buttons
$( '#sharing_email a.sharing_cancel' )
.unbind( 'click' )
.click( function() {
$( '#sharing_email .errors' ).hide();
$sharing_email.slideUp( 200 );
$( '#sharing_background' ).fadeOut();
return false;
} );
// Submit validation
$( '#sharing_email input[type=submit]' )
.unbind( 'click' )
.click( function() {
var form = $( this ).parents( 'form' );
var source_email_input = form.find( 'input[name=source_email]' );
var target_email_input = form.find( 'input[name=target_email]' );
// Disable buttons + enable loading icon
$( this ).prop( 'disabled', true );
form.find( 'a.sharing_cancel' ).hide();
form.find( 'img.loading' ).show();
$( '#sharing_email .errors' ).hide();
$( '#sharing_email .error' ).removeClass( 'error' );
if ( ! source_email_input.share_is_email() ) {
source_email_input.addClass( 'error' );
}
if ( ! target_email_input.share_is_email() ) {
target_email_input.addClass( 'error' );
}
if ( $( '#sharing_email .error' ).length === 0 ) {
// AJAX send the form
$.ajax( {
url: url,
type: 'POST',
data: form.serialize(),
success: function( response ) {
form.find( 'img.loading' ).hide();
if ( response === '1' || response === '2' || response === '3' ) {
$( '#sharing_email .errors-' + response ).show();
form.find( 'input[type=submit]' ).removeAttr( 'disabled' );
form.find( 'a.sharing_cancel' ).show();
if (
'object' === typeof grecaptcha &&
'function' === typeof grecaptcha.reset
) {
grecaptcha.reset();
}
} else {
$( '#sharing_email form' ).hide();
$sharing_email.append( response );
$( '#sharing_email a.sharing_cancel' ).click( function() {
$sharing_email.slideUp( 200 );
$( '#sharing_background' ).fadeOut();
return false;
} );
}
},
} );
return false;
}
form.find( 'img.loading' ).hide();
form.find( 'input[type=submit]' ).removeAttr( 'disabled' );
form.find( 'a.sharing_cancel' ).show();
$( '#sharing_email .errors-1' ).show();
return false;
} );
}
return false;
} );
} );
$( 'li.share-email, li.share-custom a.sharing-anchor' ).addClass( 'share-service-visible' );
}
} )( jQuery );
;