WordPress/wp-includes/js/wp-emoji.js
Andrew Ozz 01c26527ea Emoji: fix loop when replacement images fail to load.
Props iseulde. Fixes #32128 for trunk.
Built from https://develop.svn.wordpress.org/trunk@32323


git-svn-id: http://core.svn.wordpress.org/trunk@32294 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2015-04-29 03:19:26 +00:00

182 lines
4.1 KiB
JavaScript

( function( window, settings ) {
function wpEmoji() {
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
/**
* Flag to determine if the browser and the OS support emoji.
*
* @since 4.2.0
*
* @var Boolean
*/
supportsEmoji = false,
/**
* Flag to determine if the browser and the OS support flag (two character) emoji.
*
* @since 4.2.0
*
* @var Boolean
*/
supportsFlagEmoji = false,
/**
* Flag to determine if we should replace emoji characters with images.
*
* @since 4.2.0
*
* @var Boolean
*/
replaceEmoji = false,
isIE8 = window.navigator.userAgent.indexOf( 'IE 8' ) !== -1,
// Private
twemoji, timer,
count = 0;
/**
* Runs when the document load event is fired, so we can do our first parse of the page.
*
* @since 4.2.0
*/
function load() {
if ( typeof window.twemoji === 'undefined' ) {
// Break if waiting for longer than 30 sec.
if ( count > 600 ) {
return;
}
// Still waiting.
window.clearTimeout( timer );
timer = window.setTimeout( load, 50 );
count++;
return;
}
twemoji = window.twemoji;
if ( MutationObserver ) {
new MutationObserver( function( mutationRecords ) {
var i = mutationRecords.length,
addedNodes, removedNodes, ii, node;
while ( i-- ) {
addedNodes = mutationRecords[ i ].addedNodes;
removedNodes = mutationRecords[ i ].removedNodes;
ii = addedNodes.length;
if (
ii === 1 && removedNodes.length === 1 &&
addedNodes[0].nodeType === 3 &&
removedNodes[0].nodeName === 'IMG' &&
addedNodes[0].data === removedNodes[0].alt
) {
return;
}
while ( ii-- ) {
node = addedNodes[ ii ];
if ( node.nodeType === 3 ) {
node = node.parentNode;
}
if ( node && node.nodeType === 1 ) {
parse( node );
}
}
}
} ).observe( document.body, {
childList: true,
subtree: true
} );
}
parse( document.body );
}
/**
* Given an element or string, parse any emoji characters into Twemoji images.
*
* @since 4.2.0
*
* @param {HTMLElement|String} object The element or string to parse.
* @param {Object} args Additional options for Twemoji.
*/
function parse( object, args ) {
if ( ! replaceEmoji ) {
return object;
}
args = args || {};
return twemoji.parse( object, {
base: settings.baseUrl,
ext: settings.ext,
className: args.className || 'emoji',
imgAttr: args.imgAttr,
callback: function( icon, options ) {
// Ignore some standard characters that TinyMCE recommends in its character map.
switch ( icon ) {
case 'a9':
case 'ae':
case '2122':
case '2194':
case '2660':
case '2663':
case '2665':
case '2666':
return false;
}
if ( ! supportsFlagEmoji && supportsEmoji &&
! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) ) {
return false;
}
return ''.concat( options.base, icon, options.ext );
}
} );
}
// Load when the readyState changes to 'interactive', not 'complete'.
function onLoad() {
if ( ( ! isIE8 && 'interactive' === document.readyState ) || ( isIE8 && 'complete' === document.readyState ) ) {
load();
}
}
/**
* Initialize our emoji support, and set up listeners.
*/
if ( settings ) {
supportsEmoji = window._wpemojiSettings.supports.simple;
supportsFlagEmoji = window._wpemojiSettings.supports.flag;
replaceEmoji = ! supportsEmoji || ! supportsFlagEmoji;
if ( ( ! isIE8 && 'loading' === document.readyState ) || ( isIE8 && 'complete' !== document.readyState ) ) {
if ( document.addEventListener ) {
document.addEventListener( 'readystatechange', onLoad, false );
} else if ( document.attachEvent ) {
document.attachEvent( 'onreadystatechange', onLoad );
}
} else {
load();
}
}
return {
replaceEmoji: replaceEmoji,
parse: parse
};
}
window.wp = window.wp || {};
window.wp.emoji = new wpEmoji();
} )( window, window._wpemojiSettings );