emojiBar.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. /** @type {function((string|null))|undefined} */
  10. ,emojiSelectedHandler
  11. /** @type {function():boolean} */
  12. ,isSupported = function() {
  13. return ("searchEmojis" in window);
  14. }
  15. ,makeHeader = function(imgSrc) {
  16. var img = document.createElement("img")
  17. ,dom = document.createElement("div");
  18. img.src = imgSrc;
  19. dom.appendChild(img);
  20. dom.className = R.klass.emojibar.header;
  21. return dom;
  22. }
  23. /** @type {function(string, Element):{dom:Element,visible:boolean}} */
  24. ,wrapEmojiLi = function(emojiName, emojiDom) {
  25. var dom = document.createElement("li");
  26. dom.appendChild(emojiDom);
  27. dom.className = R.klass.emojibar.item;
  28. dom.id = "emojibar-" +emojiName;
  29. return {
  30. visible: false
  31. ,dom: dom
  32. };
  33. }
  34. /** @type {function(string, *):{dom:Element,visible:boolean}} */
  35. ,makeUnicodeEmojiLi = function(emojiName, emoji) {
  36. var domEmoji = window['makeEmoji'](emoji)
  37. ,domParent = document.createElement("span");
  38. domParent.appendChild(domEmoji);
  39. domParent.className = R.klass.emoji.medium;
  40. return wrapEmojiLi(emojiName, domParent);
  41. }
  42. /** @type function(string=):number */
  43. ,search = function(queryString) {
  44. var emojiCount = 0
  45. ,toRemove = [];
  46. queryString = queryString === undefined ? searchBar.value : queryString;
  47. if (isSupported()) {
  48. /** @type {Object.<string, *>} */
  49. var emojis = window['searchEmojis'](queryString);
  50. for (var i in emojiCache.unicode) {
  51. if (emojiCache.unicode[i].visible && !emojis[i]) {
  52. emojiCache.unicode[i].visible = false;
  53. unicodeEmojis.removeChild(emojiCache.unicode[i].dom);
  54. }
  55. }
  56. for (var i in emojis) {
  57. var e = emojiCache.unicode[i];
  58. if (!e)
  59. e = emojiCache.unicode[i] = makeUnicodeEmojiLi(i, emojis[i]);
  60. if (!e.visible) {
  61. e.visible = true;
  62. unicodeEmojis.appendChild(e.dom);
  63. }
  64. emojiCount++;
  65. }
  66. }
  67. //TODO custom
  68. return emojiCount;
  69. }
  70. /** @type function(Element, function((string|null))=):boolean */
  71. ,spawn = function(domParent, handler) {
  72. if (isSupported()) {
  73. emojiSelectedHandler = handler;
  74. domParent.appendChild(overlay);
  75. domParent.appendChild(dom);
  76. searchBar.value = "";
  77. search();
  78. searchBar.focus();
  79. return true;
  80. }
  81. return false;
  82. }
  83. /** @type {function():boolean} */
  84. ,doClose = function() {
  85. if (dom.parentElement) {
  86. dom.parentElement.removeChild(overlay);
  87. dom.parentElement.removeChild(dom);
  88. return true;
  89. }
  90. return false;
  91. }
  92. /** @type {function():boolean} */
  93. ,close = function() {
  94. var closed = doClose();
  95. if (!closed)
  96. return false;
  97. if (emojiSelectedHandler)
  98. emojiSelectedHandler(null);
  99. return true;
  100. }
  101. ,onEmojiSelected = function(emojiName) {
  102. if (doClose() && emojiSelectedHandler)
  103. emojiSelectedHandler(emojiName);
  104. }
  105. ;
  106. overlay.addEventListener("click", function(e) {
  107. var bounds = dom.getBoundingClientRect();
  108. if (e.screenY < bounds.top || e.screenY > bounds.bottom ||
  109. e.screenX < bounds.left || e.screenX > bounds.right)
  110. close();
  111. });
  112. overlay.className = R.klass.emojibar.overlay;
  113. dom.className = R.klass.emojibar.container;
  114. emojisDom.className = R.klass.emojibar.emojis;
  115. unicodeEmojis.className = customEmojis.className = R.klass.emojibar.list;
  116. searchBar.className = R.klass.emojibar.search;
  117. emojisDom.appendChild(makeHeader(window['emojiProviderHeader']));
  118. emojisDom.appendChild(unicodeEmojis);
  119. emojisDom.appendChild(makeHeader("emojicustom.png"));
  120. emojisDom.appendChild(customEmojis);
  121. dom.appendChild(emojisDom);
  122. dom.appendChild(searchBar);
  123. searchBar.addEventListener("keyup", function() {
  124. search();
  125. });
  126. dom.addEventListener("click", function(e) {
  127. var target = e.target;
  128. while (target !== dom && target && target.nodeName !== "LI")
  129. target = target.parentElement;
  130. if (target && target.nodeName === "LI" && target.id && target.id.substr(0, "emojibar-".length) === "emojibar-") {
  131. var emojiId = target.id.substr("emojibar-".length);
  132. onEmojiSelected(emojiId);
  133. }
  134. });
  135. return {
  136. isSupported: isSupported
  137. ,spawn: spawn
  138. ,search: search
  139. ,close: close
  140. };
  141. })();