/* jshint sub: true */ var EMOJI_BAR = (function() { var dom = document.createElement("div"), overlay = document.createElement("div"), emojisDom = document.createElement("div"), unicodeEmojis = document.createElement("ul"), customEmojis = document.createElement("ul"), searchBar = document.createElement("input"), emojiCache = { unicode: {}, custom: {}}, emojiDetail = document.createElement("div"), emojiDetailImg = document.createElement("span"), emojiDetailName = document.createElement("span"), /** @type {function((string|null))|undefined} */ emojiSelectedHandler, context, /** @type {function():boolean} */ isSupported = function() { return ("searchEmojis" in window); }, makeHeader = function(imgSrc) { var img = document.createElement("img"), dom = document.createElement("div"); img.src = imgSrc; dom.appendChild(img); dom.className = R.klass.emojibar.header; return dom; }, /** @type {function(string, Element):{dom:Element,visible:boolean}} */ wrapEmojiLi = function(emojiName, emojiDom) { var dom = document.createElement("li"); dom.appendChild(emojiDom); dom.className = R.klass.emojibar.item; dom.id = "emojibar-" +emojiName; return { visible: false, dom: dom }; }, /** @type {function(string, *):{dom:Element,visible:boolean}} */ makeUnicodeEmojiLi = function(emojiName, emoji) { var domEmoji = window['makeEmoji'](emoji), domParent = document.createElement("span"); domParent.appendChild(domEmoji); domParent.className = R.klass.emoji.medium; return wrapEmojiLi(emojiName, domParent); }, /** @type {function(string, string):{dom:Element,visible:boolean}} */ makeCustomEmoji = function(emojiName, emojiSrc) { var domEmoji = document.createElement("span"), domParent = document.createElement("span"); domEmoji.className = R.klass.emoji.emoji +' ' +R.klass.emoji.custom; domEmoji.style.backgroundImage = 'url("' +emojiSrc +'")'; domParent.appendChild(domEmoji); domParent.className = R.klass.emoji.medium; return wrapEmojiLi(emojiName, domParent); }, /** @type {function(Object., Object.):Array.<{name:string, pos:number, count:number}>} */ sortEmojis = function(emojiObj, favoriteEmojis) { var names = [], index = 0; for (var i in emojiObj) { var obj = { name: i, pos: index, count: 0 }; if (emojiObj[i].names) for (var nameI =0, nbNames = emojiObj[i].names.length; nameI < nbNames; nameI++) obj.count += (favoriteEmojis[emojiObj[i].names[nameI]] || 0); names.push(obj); } names = names.sort(function(a, b) { var diff = b.count -a.count; if (diff) return diff; return a.pos -b.pos; }); return names; }, /** @type {function(string):number} */ searchFromService = function(queryString) { var emojiCount =0, /** @type {Object.} */ foundEmojis = window['searchEmojis'](queryString), /** @type {Array.<{name:string, pos:number, count:number}>} */ sortedEmojiNames = sortEmojis(foundEmojis, context.self.prefs.favoriteEmojis), i, nbEmojis; for (i in emojiCache.unicode) { if (emojiCache.unicode[i].visible) { // We remove every item to reorder them (add them in order) emojiCache.unicode[i].visible = false; unicodeEmojis.removeChild(emojiCache.unicode[i].dom); } } for (i =0, nbEmojis = sortedEmojiNames.length; i < nbEmojis; i++) { var emojiName = sortedEmojiNames[i].name, e = emojiCache.unicode[emojiName]; if (!e) e = emojiCache.unicode[emojiName] = makeUnicodeEmojiLi(emojiName, foundEmojis[emojiName]); if (!e.visible) { e.visible = true; unicodeEmojis.appendChild(e.dom); } emojiCount++; } return emojiCount; }, /** @type {function(string):number} */ searchFromCustom = function(queryString) { var i, nbEmojis, emojiCount = 0; for (i in emojiCache.custom) { if (emojiCache.custom[i].visible) { emojiCache.custom[i].visible = false; customEmojis.removeChild(emojiCache.custom[i].dom); } } /** @type {Array.<{name:string, pos:number, count:number}>} */ var sortedEmojiNames = sortEmojis(context.emojis.data, context.self.prefs.favoriteEmojis); for (i =0, nbEmojis = sortedEmojiNames.length; i < nbEmojis; i++) { var emojiName = sortedEmojiNames[i].name; if ((queryString === '' || emojiName.substr(0, queryString.length) === queryString) && context.emojis.data[emojiName].substr(0, 6) !== 'alias:') { var e = emojiCache.custom[emojiName]; if (!e) e = emojiCache.custom[emojiName] = makeCustomEmoji(emojiName, context.emojis.data[emojiName]); if (!e.visible) { e.visible = true; customEmojis.appendChild(e.dom); } emojiCount++; } } return emojiCount; }, /** @type function(string=):number */ search = function(queryString) { var emojiCount = 0; queryString = (queryString === undefined) ? searchBar.value : queryString; // Service emojis if (isSupported()) { emojiCount += searchFromService(queryString); } emojiCount += searchFromCustom(queryString); // Custom emojis return emojiCount; }, /** @type function(Element, ChatContext, function((string|null))=):boolean */ spawn = function(domParent, ctx, handler) { if (isSupported()) { context = ctx; emojiSelectedHandler = handler; domParent.appendChild(overlay); domParent.appendChild(dom); searchBar.value = ""; search(); searchBar.focus(); return true; } return false; }, /** @type {function():boolean} */ doClose = function() { if (dom.parentElement) { dom.parentElement.removeChild(overlay); dom.parentElement.removeChild(dom); return true; } return false; }, /** @type {function():boolean} */ close = function() { var closed = doClose(); if (!closed) return false; if (emojiSelectedHandler) emojiSelectedHandler(null); return true; }, onEmojiSelected = function(emojiName) { if (doClose() && emojiSelectedHandler) emojiSelectedHandler(emojiName); } ; overlay.addEventListener("click", function(e) { var bounds = dom.getBoundingClientRect(); if (e.screenY < bounds.top || e.screenY > bounds.bottom || e.screenX < bounds.left || e.screenX > bounds.right) close(); }); overlay.className = R.klass.emojibar.overlay; dom.className = R.klass.emojibar.container; emojisDom.className = R.klass.emojibar.emojis; emojiDetail.className = R.klass.emojibar.detail.container; emojiDetailImg.className = R.klass.emojibar.detail.img; emojiDetailName.className = R.klass.emojibar.detail.name; unicodeEmojis.className = customEmojis.className = R.klass.emojibar.list; searchBar.className = R.klass.emojibar.search; emojiDetail.appendChild(emojiDetailImg); emojiDetail.appendChild(emojiDetailName); emojisDom.appendChild(makeHeader(window['emojiProviderHeader'])); emojisDom.appendChild(unicodeEmojis); emojisDom.appendChild(makeHeader("emojicustom.png")); emojisDom.appendChild(customEmojis); dom.appendChild(emojisDom); dom.appendChild(emojiDetail); dom.appendChild(searchBar); searchBar.addEventListener("keyup", function() { search(); }); var makeDelegate = function(e, cb) { var target = e.target; while (target !== dom && target && target.nodeName !== "LI") target = target.parentElement; if (target && target.nodeName === "LI" && target.id && target.id.substr(0, "emojibar-".length) === "emojibar-") { var emojiId = target.id.substr("emojibar-".length); return cb(emojiId); } cb(null); }; dom.addEventListener("mousemove", function(e) { makeDelegate(e, function(emoji) { var emojiCached = emoji ? (emojiCache.unicode[emoji] || emojiCache.custom[emoji]) : null; if (emojiCached) { emojiDetailImg.innerHTML = emojiCached.dom.outerHTML; emojiDetailName.textContent = ':' +emoji +':'; } else { emojiDetailImg.textContent = ""; emojiDetailName.textContent = ""; } }); }); dom.addEventListener("click", function(e) { makeDelegate(e, function(emoji) { if (emoji) onEmojiSelected(emoji); }); }); return { isSupported: isSupported, spawn: spawn, search: search, close: close }; })();