home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / js / wp-emoji.js < prev    next >
Encoding:
JavaScript  |  2016-08-04  |  6.6 KB  |  230 lines

  1.  
  2. ( function( window, settings ) {
  3.     function wpEmoji() {
  4.         var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
  5.  
  6.         // Compression and maintain local scope
  7.         document = window.document,
  8.  
  9.         // Private
  10.         twemoji, timer,
  11.         loaded = false,
  12.         count = 0,
  13.         ie11 = window.navigator.userAgent.indexOf( 'Trident/7.0' ) > 0;
  14.  
  15.         /**
  16.          * Detect if the browser supports SVG.
  17.          *
  18.          * @since 4.6.0
  19.          *
  20.          * @return {Boolean} True if the browser supports svg, false if not.
  21.          */
  22.         function browserSupportsSvgAsImage() {
  23.             if ( !! document.implementation.hasFeature ) {
  24.                 // Source: Modernizr
  25.                 // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/svg/asimg.js
  26.                 return document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#Image', '1.1' );
  27.             }
  28.  
  29.             // document.implementation.hasFeature is deprecated. It can be presumed
  30.             // if future browsers remove it, the browser will support SVGs as images.
  31.             return true;
  32.         }
  33.  
  34.         /**
  35.          * Runs when the document load event is fired, so we can do our first parse of the page.
  36.          *
  37.          * @since 4.2.0
  38.          */
  39.         function load() {
  40.             if ( loaded ) {
  41.                 return;
  42.             }
  43.  
  44.             if ( typeof window.twemoji === 'undefined' ) {
  45.                 // Break if waiting for longer than 30 sec.
  46.                 if ( count > 600 ) {
  47.                     return;
  48.                 }
  49.  
  50.                 // Still waiting.
  51.                 window.clearTimeout( timer );
  52.                 timer = window.setTimeout( load, 50 );
  53.                 count++;
  54.  
  55.                 return;
  56.             }
  57.  
  58.             twemoji = window.twemoji;
  59.             loaded = true;
  60.  
  61.             if ( MutationObserver ) {
  62.                 new MutationObserver( function( mutationRecords ) {
  63.                     var i = mutationRecords.length,
  64.                         addedNodes, removedNodes, ii, node;
  65.  
  66.                     while ( i-- ) {
  67.                         addedNodes = mutationRecords[ i ].addedNodes;
  68.                         removedNodes = mutationRecords[ i ].removedNodes;
  69.                         ii = addedNodes.length;
  70.  
  71.                         if (
  72.                             ii === 1 && removedNodes.length === 1 &&
  73.                             addedNodes[0].nodeType === 3 &&
  74.                             removedNodes[0].nodeName === 'IMG' &&
  75.                             addedNodes[0].data === removedNodes[0].alt &&
  76.                             'load-failed' === removedNodes[0].getAttribute( 'data-error' )
  77.                         ) {
  78.                             return;
  79.                         }
  80.  
  81.                         while ( ii-- ) {
  82.                             node = addedNodes[ ii ];
  83.  
  84.                             if ( node.nodeType === 3 ) {
  85.                                 if ( ! node.parentNode ) {
  86.                                     continue;
  87.                                 }
  88.  
  89.                                 if ( ie11 ) {
  90.                                     /*
  91.                                      * IE 11's implementation of MutationObserver is buggy.
  92.                                      * It unnecessarily splits text nodes when it encounters a HTML
  93.                                      * template interpolation symbol ( "{{", for example ). So, we
  94.                                      * join the text nodes back together as a work-around.
  95.                                      */
  96.                                     while( node.nextSibling && 3 === node.nextSibling.nodeType ) {
  97.                                         node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
  98.                                         node.parentNode.removeChild( node.nextSibling );
  99.                                     }
  100.                                 }
  101.  
  102.                                 node = node.parentNode;
  103.                             }
  104.  
  105.                             if ( ! node || node.nodeType !== 1 ||
  106.                                 ( node.className && typeof node.className === 'string' && node.className.indexOf( 'wp-exclude-emoji' ) !== -1 ) ) {
  107.  
  108.                                 continue;
  109.                             }
  110.  
  111.                             if ( test( node.textContent ) ) {
  112.                                 parse( node );
  113.                             }
  114.                         }
  115.                     }
  116.                 } ).observe( document.body, {
  117.                     childList: true,
  118.                     subtree: true
  119.                 } );
  120.             }
  121.  
  122.             parse( document.body );
  123.         }
  124.  
  125.         /**
  126.          * Test if a text string contains emoji characters.
  127.          *
  128.          * @since 4.3.0
  129.          *
  130.          * @param {String} text The string to test
  131.          *
  132.          * @return {Boolean} Whether the string contains emoji characters.
  133.          */
  134.         function test( text ) {
  135.             // Single char. U+20E3 to detect keycaps. U+00A9 "copyright sign" and U+00AE "registered sign" not included.
  136.             var single = /[\u203C\u2049\u20E3\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2300\u231A\u231B\u2328\u2388\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638\u2639\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692\u2693\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753\u2754\u2755\u2757\u2763\u2764\u2795\u2796\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05\u2B06\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]/,
  137.             // Surrogate pair range. Only tests for the second half.
  138.             pair = /[\uDC00-\uDFFF]/;
  139.  
  140.             if ( text ) {
  141.                 return  pair.test( text ) || single.test( text );
  142.             }
  143.  
  144.             return false;
  145.         }
  146.  
  147.         /**
  148.          * Given an element or string, parse any emoji characters into Twemoji images.
  149.          *
  150.          * @since 4.2.0
  151.          *
  152.          * @param {HTMLElement|String} object The element or string to parse.
  153.          * @param {Object} args Additional options for Twemoji.
  154.          */
  155.         function parse( object, args ) {
  156.             var params;
  157.  
  158.             if ( settings.supports.everything || ! twemoji || ! object ||
  159.                 ( 'string' !== typeof object && ( ! object.childNodes || ! object.childNodes.length ) ) ) {
  160.  
  161.                 return object;
  162.             }
  163.  
  164.             args = args || {};
  165.             params = {
  166.                 base: browserSupportsSvgAsImage() ? settings.svgUrl : settings.baseUrl,
  167.                 ext:  browserSupportsSvgAsImage() ? settings.svgExt : settings.ext,
  168.                 className: args.className || 'emoji',
  169.                 callback: function( icon, options ) {
  170.                     // Ignore some standard characters that TinyMCE recommends in its character map.
  171.                     switch ( icon ) {
  172.                         case 'a9':
  173.                         case 'ae':
  174.                         case '2122':
  175.                         case '2194':
  176.                         case '2660':
  177.                         case '2663':
  178.                         case '2665':
  179.                         case '2666':
  180.                             return false;
  181.                     }
  182.  
  183.                     if ( settings.supports.everythingExceptFlag &&
  184.                         ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) && // Country flags
  185.                         ! /^(1f3f3-fe0f-200d-1f308|1f3f4-200d-2620-fe0f)$/.test( icon )             // Rainbow and pirate flags
  186.                     ) {
  187.                         return false;
  188.                     }
  189.  
  190.                     return ''.concat( options.base, icon, options.ext );
  191.                 },
  192.                 onerror: function() {
  193.                     if ( twemoji.parentNode ) {
  194.                         this.setAttribute( 'data-error', 'load-failed' );
  195.                         twemoji.parentNode.replaceChild( document.createTextNode( twemoji.alt ), twemoji );
  196.                     }
  197.                 }
  198.             };
  199.  
  200.             if ( typeof args.imgAttr === 'object' ) {
  201.                 params.attributes = function() {
  202.                     return args.imgAttr;
  203.                 };
  204.             }
  205.  
  206.             return twemoji.parse( object, params );
  207.         }
  208.  
  209.         /**
  210.          * Initialize our emoji support, and set up listeners.
  211.          */
  212.         if ( settings ) {
  213.             if ( settings.DOMReady ) {
  214.                 load();
  215.             } else {
  216.                 settings.readyCallback = load;
  217.             }
  218.         }
  219.  
  220.         return {
  221.             parse: parse,
  222.             test: test
  223.         };
  224.     }
  225.  
  226.     window.wp = window.wp || {};
  227.     window.wp.emoji = new wpEmoji();
  228.  
  229. } )( window, window._wpemojiSettings );
  230.