Twitter Emoji Support

By Yuichirou Last update Oct 15, 2009 — Installed 1,428 times.

There are 2 previous versions of this script.

// ==UserScript==
// @name           Twitter Emoji Support
// @namespace      http://d.hatena.ne.jp/Yuichirou/
// @include        http://twitter.com/*
// @include        https://twitter.com/*
// ==/UserScript==

var emojiRegExp = /[\uDBB8-\uDBBA]./;
var emojiURL = location.protocol + "//mail.google.com/mail/e/"

function decodeSurrogatePair(str) {
  var upper = str.charCodeAt(0) - 0xD800;
  var lower = str.charCodeAt(1) - 0xDC00;
  //if (upper < 0 || 0x400 <= upper) throw new Error(upper);
  //if (lower < 0 || 0x400 <= lower) throw new Error(lower);
  return 0x10000 + (upper * 0x400) + lower;
}

function replaceEmojiFromTextNode(textNode) {
  var text = textNode.nodeValue;

  while (!!(res = text.match(emojiRegExp))) {
    var emoji_num = decodeSurrogatePair(res[0]) - 0xFE000;

    var newTextNode = document.createTextNode(text.slice(0, res.index));
    textNode.parentNode.insertBefore(newTextNode, textNode);

    var img = document.createElement("img");
    img.src = emojiURL + ("00" + emoji_num.toString(16).toUpperCase()).slice(-3);
    img.style.height = "1.04em";
    img.style.verticalAlign = "text-top";
    textNode.parentNode.insertBefore(img, textNode);

    textNode.nodeValue = text.slice(res.index + 2);

    text = textNode.nodeValue;
  }
}

function replaceEmoji(elm) {
  if (emojiRegExp.test(elm.textContent)) {
    if (elm.nodeName === "#text") {
      replaceEmojiFromTextNode(elm);
    } else if (elm.childNodes) {
      Array.forEach(elm.childNodes, replaceEmoji);
    }
  }
}

var tweets = document.getElementsByClassName("entry-content");
Array.forEach(tweets, replaceEmoji);

var timeline = document.getElementById('timeline');
if (timeline) {
  timeline.parentNode.addEventListener('DOMNodeInserted', function (evt) {
    var elm = evt.target;
    if (elm.className && elm.className.match(/status/i)) {
      var contentElm = elm.getElementsByClassName("entry-content")[0];
      replaceEmoji(contentElm);
    }
  }, false);
}