emojiBar.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. var EMOJI_BAR = (function() {
  2. var dom = document.createElement("div")
  3. ,overlay = document.createElement("div")
  4. ,emojisDom = document.createElement("div")
  5. ,unicodeEmojis = document.createElement("ul")
  6. ,customEmojis = document.createElement("ul")
  7. ,searchBar = document.createElement("input")
  8. ,emojiCache = { unicode: {}, custom: {}}
  9. ,emojiDetail = document.createElement("div")
  10. ,emojiDetailImg = document.createElement("span")
  11. ,emojiDetailName = document.createElement("span")
  12. /** @type {function((string|null))|undefined} */
  13. ,emojiSelectedHandler
  14. /** @type {function():boolean} */
  15. ,isSupported = function() {
  16. return ("searchEmojis" in window);
  17. }
  18. ,makeHeader = function(imgSrc) {
  19. var img = document.createElement("img")
  20. ,dom = document.createElement("div");
  21. img.src = imgSrc;
  22. dom.appendChild(img);
  23. dom.className = R.klass.emojibar.header;
  24. return dom;
  25. }
  26. /** @type {function(string, Element):{dom:Element,visible:boolean}} */
  27. ,wrapEmojiLi = function(emojiName, emojiDom) {
  28. var dom = document.createElement("li");
  29. dom.appendChild(emojiDom);
  30. dom.className = R.klass.emojibar.item;
  31. dom.id = "emojibar-" +emojiName;
  32. return {
  33. visible: false
  34. ,dom: dom
  35. };
  36. }
  37. /** @type {function(string, *):{dom:Element,visible:boolean}} */
  38. ,makeUnicodeEmojiLi = function(emojiName, emoji) {
  39. var domEmoji = window['makeEmoji'](emoji)
  40. ,domParent = document.createElement("span");
  41. domParent.appendChild(domEmoji);
  42. domParent.className = R.klass.emoji.medium;
  43. return wrapEmojiLi(emojiName, domParent);
  44. }
  45. /** @type function(string=):number */
  46. ,search = function(queryString) {
  47. var emojiCount = 0
  48. ,toRemove = [];
  49. queryString = queryString === undefined ? searchBar.value : queryString;
  50. if (isSupported()) {
  51. var
  52. /** @type {Object.<string, *>} */
  53. foundEmojis = window['searchEmojis'](queryString)
  54. ,index = 0;
  55. for (var i in emojiCache.unicode) {
  56. if (emojiCache.unicode[i].visible) {
  57. // We remove every item to reorder them (add them in order)
  58. emojiCache.unicode[i].visible = false;
  59. unicodeEmojis.removeChild(emojiCache.unicode[i].dom);
  60. }
  61. }
  62. for (var i in foundEmojis) {
  63. var e = emojiCache.unicode[i];
  64. if (!e)
  65. e = emojiCache.unicode[i] = makeUnicodeEmojiLi(i, foundEmojis[i]);
  66. if (!e.visible) {
  67. e.visible = true;
  68. unicodeEmojis.appendChild(e.dom);
  69. }
  70. emojiCount++;
  71. }
  72. }
  73. //TODO custom
  74. return emojiCount;
  75. }
  76. /** @type function(Element, function((string|null))=):boolean */
  77. ,spawn = function(domParent, handler) {
  78. if (isSupported()) {
  79. emojiSelectedHandler = handler;
  80. domParent.appendChild(overlay);
  81. domParent.appendChild(dom);
  82. searchBar.value = "";
  83. search();
  84. searchBar.focus();
  85. return true;
  86. }
  87. return false;
  88. }
  89. /** @type {function():boolean} */
  90. ,doClose = function() {
  91. if (dom.parentElement) {
  92. dom.parentElement.removeChild(overlay);
  93. dom.parentElement.removeChild(dom);
  94. return true;
  95. }
  96. return false;
  97. }
  98. /** @type {function():boolean} */
  99. ,close = function() {
  100. var closed = doClose();
  101. if (!closed)
  102. return false;
  103. if (emojiSelectedHandler)
  104. emojiSelectedHandler(null);
  105. return true;
  106. }
  107. ,onEmojiSelected = function(emojiName) {
  108. if (doClose() && emojiSelectedHandler)
  109. emojiSelectedHandler(emojiName);
  110. }
  111. ;
  112. overlay.addEventListener("click", function(e) {
  113. var bounds = dom.getBoundingClientRect();
  114. if (e.screenY < bounds.top || e.screenY > bounds.bottom ||
  115. e.screenX < bounds.left || e.screenX > bounds.right)
  116. close();
  117. });
  118. overlay.className = R.klass.emojibar.overlay;
  119. dom.className = R.klass.emojibar.container;
  120. emojisDom.className = R.klass.emojibar.emojis;
  121. emojiDetail.className = R.klass.emojibar.detail.container;
  122. emojiDetailImg.className = R.klass.emojibar.detail.img;
  123. emojiDetailName.className = R.klass.emojibar.detail.name;
  124. unicodeEmojis.className = customEmojis.className = R.klass.emojibar.list;
  125. searchBar.className = R.klass.emojibar.search;
  126. emojiDetail.appendChild(emojiDetailImg);
  127. emojiDetail.appendChild(emojiDetailName);
  128. emojisDom.appendChild(makeHeader(window['emojiProviderHeader']));
  129. emojisDom.appendChild(unicodeEmojis);
  130. emojisDom.appendChild(makeHeader("emojicustom.png"));
  131. emojisDom.appendChild(customEmojis);
  132. dom.appendChild(emojisDom);
  133. dom.appendChild(emojiDetail);
  134. dom.appendChild(searchBar);
  135. searchBar.addEventListener("keyup", function() {
  136. search();
  137. });
  138. var makeDelegate = function(e, cb) {
  139. var target = e.target;
  140. while (target !== dom && target && target.nodeName !== "LI")
  141. target = target.parentElement;
  142. if (target && target.nodeName === "LI" && target.id && target.id.substr(0, "emojibar-".length) === "emojibar-") {
  143. var emojiId = target.id.substr("emojibar-".length);
  144. return cb(emojiId);
  145. }
  146. cb(null);
  147. };
  148. dom.addEventListener("mousemove", function(e) {
  149. makeDelegate(e, function(emoji) {
  150. var emojiCached = emoji ? (emojiCache.unicode[emoji] || emojiCache.custom[emoji]) : null;
  151. if (emojiCached) {
  152. emojiDetailImg.innerHTML = emojiCached.dom.outerHTML;
  153. emojiDetailName.textContent = ':' +emoji +':';
  154. } else {
  155. emojiDetailImg.textContent = "";
  156. emojiDetailName.textContent = "";
  157. }
  158. });
  159. });
  160. dom.addEventListener("click", function(e) {
  161. makeDelegate(e, onEmojiSelected);
  162. });
  163. return {
  164. isSupported: isSupported
  165. ,spawn: spawn
  166. ,search: search
  167. ,close: close
  168. };
  169. })();