From e2dad3e47775e07eb39643bbfe2024b05b00a643 Mon Sep 17 00:00:00 2001 From: chylex <contact@chylex.com> Date: Wed, 27 Sep 2017 13:25:05 +0200 Subject: [PATCH] Automatically convert :emoji_name: in emoji keyboard plugin Closes #160 --- Resources/Plugins/emoji-keyboard/browser.js | 101 +++++++++++++++++++- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/Resources/Plugins/emoji-keyboard/browser.js b/Resources/Plugins/emoji-keyboard/browser.js index 7ec200cc..0b1cc55c 100644 --- a/Resources/Plugins/emoji-keyboard/browser.js +++ b/Resources/Plugins/emoji-keyboard/browser.js @@ -66,6 +66,7 @@ enabled(){ this.currentSpanner = null; var wasSearchFocused = false; + var lastEmojiKeyword, lastEmojiPosition, lastEmojiLength; var hideKeyboard = (refocus) => { $(this.currentKeyboard).remove(); @@ -81,8 +82,14 @@ enabled(){ $(".emoji-keyboard-popup-btn").removeClass("is-selected"); if (refocus){ - $(".js-compose-text", ".js-docked-compose").focus(); + this.composeInput.focus(); + + if (lastEmojiKeyword){ + document.execCommand("insertText", false, lastEmojiKeyword); + } } + + lastEmojiKeyword = null; }; var generateEmojiHTML = skinTone => { @@ -229,7 +236,7 @@ enabled(){ }; var insertEmoji = (src, alt) => { - let input = $(".js-compose-text", ".js-docked-compose"); + let input = this.composeInput; let val = input.val(); let posStart = input[0].selectionStart; @@ -241,6 +248,8 @@ enabled(){ input[0].selectionStart = posStart+alt.length; input[0].selectionEnd = posStart+alt.length; + lastEmojiKeyword = null; + if (wasSearchFocused){ $(".emoji-keyboard-search").children("input").focus(); } @@ -270,6 +279,85 @@ enabled(){ } }; + this.composeInputKeyDownEvent = function(e){ + if (lastEmojiKeyword && (e.keyCode === 8 || e.keyCode === 27)){ // backspace, escape + let ele = $(this)[0]; + + if (ele.selectionStart === lastEmojiPosition){ + ele.selectionStart -= lastEmojiLength; // selects the emoji + document.execCommand("insertText", false, lastEmojiKeyword); + + e.preventDefault(); + e.stopPropagation(); + } + + lastEmojiKeyword = null; + } + }; + + this.composeInputKeyPressEvent = function(e){ + if (String.fromCharCode(e.which) === ':'){ + let ele = $(this); + let val = ele.val(); + + let firstColon = val.lastIndexOf(':', ele[0].selectionStart); + return if firstColon === -1; + + let search = val.substring(firstColon+1, ele[0].selectionStart); + return if !/^[a-z_]+$/i.test(search); + + let keywords = search.split("_").filter(kw => kw.length > 0).map(kw => kw.toLowerCase()); + return if keywords.length === 0; + + let foundName = me.emojiNames.filter(name => keywords.every(kw => name.includes(kw))); + + if (foundName.length === 0){ + return; + } + + lastEmojiKeyword = `:${search}:`; + lastEmojiPosition = lastEmojiLength = 0; + + if (foundName.length === 1){ + let foundIndex = me.emojiNames.indexOf(foundName[0]); + let foundEmoji; + + for(let array of [ me.emojiData1, me.emojiData2[me.selectedSkinTone], me.emojiData3 ]){ + if (foundIndex >= array.length){ + foundIndex -= array.length; + } + else{ + foundEmoji = array[foundIndex]; + break; + } + } + + if (foundEmoji){ + e.preventDefault(); + + ele.val(val.substring(0, firstColon)+foundEmoji+val.substring(ele[0].selectionStart)); + ele[0].selectionEnd = ele[0].selectionStart = firstColon+foundEmoji.length; + ele.focus(); + + lastEmojiPosition = firstColon+foundEmoji.length; + lastEmojiLength = foundEmoji.length; + } + } + else if (foundName.length > 1){ + e.preventDefault(); + ele.val(val.substring(0, firstColon)+val.substring(ele[0].selectionStart)); + ele[0].selectionEnd = ele[0].selectionStart = firstColon; + + me.generateKeyboard($(".emoji-keyboard-popup-btn").offset().left, getKeyboardTop()); + $(".emoji-keyboard-search").children("input").focus(); + document.execCommand("insertText", false, keywords.join(" ")); + } + } + else{ + lastEmojiKeyword = null; + } + }; + this.composeInputFocusEvent = function(e){ wasSearchFocused = false; }; @@ -300,15 +388,18 @@ enabled(){ ready(){ this.composeDrawer = $("[data-drawer='compose']"); + this.composeInput = $(".js-compose-text", ".js-docked-compose"); this.composePanelScroller = $(".js-compose-scroller", ".js-docked-compose").first().children().first(); this.composePanelScroller.on("scroll", this.composerScrollEvent); $(".emoji-keyboard-popup-btn").on("click", this.emojiKeyboardButtonClickEvent); - $(".js-compose-text", ".js-docked-compose").on("focus", this.composeInputFocusEvent); $(document).on("click", this.documentClickEvent); $(document).on("keydown", this.documentKeyEvent); $(document).on("uiComposeImageAdded", this.uploadFilesEvent); + this.composeInput.on("keydown", this.composeInputKeyDownEvent); + this.composeInput.on("keypress", this.composeInputKeyPressEvent); + this.composeInput.on("focus", this.composeInputFocusEvent); this.composeDrawer.on("uiComposeTweetSending", this.composerSendingEvent); // HTML generation @@ -429,10 +520,12 @@ disabled(){ $(".emoji-keyboard-popup-btn").off("click", this.emojiKeyboardButtonClickEvent); $(".emoji-keyboard-popup-btn").remove(); - $(".js-compose-text", ".js-docked-compose").off("focus", this.composeInputFocusEvent); $(document).off("click", this.documentClickEvent); $(document).off("keydown", this.documentKeyEvent); $(document).off("uiComposeImageAdded", this.uploadFilesEvent); + this.composeInput.off("keydown", this.composeInputKeyDownEvent); + this.composeInput.off("keypress", this.composeInputKeyPressEvent); + this.composeInput.off("focus", this.composeInputFocusEvent); this.composeDrawer.off("uiComposeTweetSending", this.composerSendingEvent); TD.mustaches["compose/docked_compose.mustache"] = this.prevComposeMustache;