diff --git a/app/assets/javascripts/discourse/components/emoji-picker.js.es6 b/app/assets/javascripts/discourse/components/emoji-picker.js.es6 index d032c63abf..cc29852ac4 100644 --- a/app/assets/javascripts/discourse/components/emoji-picker.js.es6 +++ b/app/assets/javascripts/discourse/components/emoji-picker.js.es6 @@ -77,10 +77,10 @@ export default Ember.Component.extend({ selectedDiversityChanged() { keyValueStore.setObject({key: EMOJI_SELECTED_DIVERSITY, value: this.get("selectedDiversity")}); - $.each($list.find(".emoji.diversity[src!='']"), (_, icon) => this._setIconSrc(icon, true) ); + $.each($list.find(".emoji.diversity"), (_, button) => this._setButtonBackground(button, true) ); if(this.get("filter") !== "") { - $.each($results.find(".emoji.diversity"), (_, icon) => this._setIconSrc(icon, true) ); + $.each($results.find(".emoji.diversity"), (_, button) => this._setButtonBackground(button, true) ); } }, @@ -88,7 +88,7 @@ export default Ember.Component.extend({ recentEmojisChanged() { const $recentSection = $list.find(".section[data-section='recent']"); const $recentSectionGroup = $recentSection.find(".section-group"); - const $recentCategory = $picker.find(".category-icon a[title='recent']").parent(); + const $recentCategory = $picker.find(".category-icon button[data-section='recent']").parent(); // we set height to 0 to avoid it being taken into account for scroll position if(_.isEmpty(this.get("recentEmojis"))) { @@ -102,8 +102,7 @@ export default Ember.Component.extend({ const recentEmojis = _.map(this.get("recentEmojis"), code => { return { code, src: emojiUrlFor(code) }; }); - const model = { recentEmojis }; - const template = findRawTemplate("emoji-picker-recent")(model); + const template = findRawTemplate("emoji-picker-recent")({recentEmojis}); $recentSectionGroup.html(template); this._bindHover($recentSectionGroup); }, @@ -136,6 +135,13 @@ export default Ember.Component.extend({ this._setDiversity(); this._positionPicker(); this._scrollTo(); + this._loadCategoriesEmojis(); + }); + }, + + _loadCategoriesEmojis() { + $.each($picker.find(".categories-column button.emoji"), (_, button) => { + this._setButtonBackground(button, false); }); }, @@ -188,9 +194,7 @@ export default Ember.Component.extend({ const hasDiversity = isSkinTonableEmoji(code); const diversity = hasDiversity ? "diversity" : ""; const scaledCode = this._codeWithDiversity(code, hasDiversity); - return ` - - `; + return ``; }) ).show(); this._bindHover($results); @@ -214,15 +218,14 @@ export default Ember.Component.extend({ }, _bindCategoryClick() { - $picker.find(".category-icon").on("click", "a", (event) => { + $picker.find(".category-icon").on("click", "button.emoji", (event) => { this.set("filter", ""); $results.empty(); $list.show(); - const section = $(event.currentTarget).attr("title"); + const section = $(event.currentTarget).data("section"); const $section = $list.find(`.section[data-section="${section}"]`); const scrollTop = $list.scrollTop() + ($section.offset().top - $list.offset().top); - this._scrollTo(scrollTop); return false; }); @@ -233,12 +236,12 @@ export default Ember.Component.extend({ ($hoverables || $list.find(".section-group")).on({ mouseover: (event) => { - const code = this._codeForEmojiLink($(event.currentTarget)); + const code = this._codeForEmojiButton($(event.currentTarget)); const html = ` :${code}:`; replaceInfoContent(html); }, mouseleave: () => replaceInfoContent() - }, "a"); + }, "button.emoji"); }, _bindResizing() { @@ -263,7 +266,7 @@ export default Ember.Component.extend({ _bindEmojiClick($emojisContainer) { const handler = (event) => { - const code = this._codeForEmojiLink($(event.currentTarget)); + const code = this._codeForEmojiButton($(event.currentTarget)); if($(event.currentTarget).parents(".section[data-section='recent']").length === 0) { this._trackEmojiUsage(code); @@ -283,7 +286,7 @@ export default Ember.Component.extend({ $emojisContainer .off("touchstart") - .on("touchstart", "a", (touchStartEvent) => { + .on("touchstart", "button.emoji", (touchStartEvent) => { const $this = $(touchStartEvent.currentTarget); $this.on("touchend", (touchEndEvent) => { handler.bind(self)(touchEndEvent); @@ -292,7 +295,7 @@ export default Ember.Component.extend({ $this.on("touchmove", () => $this.off("touchend") ); }); } else { - $emojisContainer.off("click").on("click", "a", e => handler.bind(this)(e) ); + $emojisContainer.off("click").on("click", "button.emoji", e => handler.bind(this)(e) ); } }, @@ -336,7 +339,7 @@ export default Ember.Component.extend({ if(selectedSection) { const sectionTitle = selectedSection.$section.data("section"); $picker.find(".category-icon").removeClass("current"); - $picker.find(`.category-icon a[title='${sectionTitle}']`) + $picker.find(`.category-icon button[data-section='${sectionTitle}']`) .parent() .addClass("current"); @@ -478,7 +481,7 @@ export default Ember.Component.extend({ _loadSection($section) { const sectionName = $section.data("section"); if(keyValueStore.getObject(EMOJI_CACHED_SECTIONS).indexOf(sectionName) > -1) { - $.each($section.find(".emoji[src='']"), (_, icon) => this._setIconSrc(icon) ); + $.each($section.find(".emoji"), (_, button) => this._setButtonBackground(button) ); } else { Ember.run.later( this, () => { @@ -486,7 +489,7 @@ export default Ember.Component.extend({ key: EMOJI_CACHED_SECTIONS, value: keyValueStore.getObject(EMOJI_CACHED_SECTIONS).concat(sectionName) }); - $.each($section.find(".emoji[src='']"), (_, icon) => this._setIconSrc(icon) ); + $.each($section.find(".emoji"), (_, button) => this._setButtonBackground(button) ); }, 1500 ); @@ -528,24 +531,23 @@ export default Ember.Component.extend({ } }, - _codeForEmojiLink($a) { - const title = $a.attr("title"); - const $img = $a.find("img"); - return this._codeWithDiversity(title, $img.hasClass("diversity")); + _codeForEmojiButton($button) { + const title = $button.attr("title"); + return this._codeWithDiversity(title, $button.hasClass("diversity")); }, - _setIconSrc(icon, diversity) { - const $icon = $(icon); + _setButtonBackground(button, diversity) { + const $button = $(button); const code = this._codeWithDiversity( - $icon.parent().attr("title"), - diversity || $icon.hasClass("diversity") + $button.attr("title"), + diversity || $button.hasClass("diversity") ); // force visual reloading if needed - if($icon.attr("src") !== "") { - $icon.attr("src", ""); + if($button.css("background-image") !== "none") { + $button.css("background-image", ""); } - $icon.attr("src", emojiUrlFor(code)); + $button.css("background-image", `url("${emojiUrlFor(code)}")`); }, }); diff --git a/app/assets/javascripts/discourse/templates/emoji-picker-recent.raw.hbs b/app/assets/javascripts/discourse/templates/emoji-picker-recent.raw.hbs index 4f309612fb..0ead5e5aee 100644 --- a/app/assets/javascripts/discourse/templates/emoji-picker-recent.raw.hbs +++ b/app/assets/javascripts/discourse/templates/emoji-picker-recent.raw.hbs @@ -1,5 +1,3 @@ {{#each recentEmojis as |emoji|}} - - - + {{/each}} diff --git a/app/assets/javascripts/discourse/templates/emoji-picker.raw.hbs.erb b/app/assets/javascripts/discourse/templates/emoji-picker.raw.hbs.erb index 98d195c4da..eb54ef2a10 100644 --- a/app/assets/javascripts/discourse/templates/emoji-picker.raw.hbs.erb +++ b/app/assets/javascripts/discourse/templates/emoji-picker.raw.hbs.erb @@ -1,23 +1,17 @@ - - - + <% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %> - - - + " title="<%= group["tabicon"] %>"> <% end %> <% if !Emoji.custom.blank? %> - - - + <% end %> @@ -49,9 +43,7 @@ <% group["icons"].each do |icon| %> - - - + " tabindex="-1" title="<%= icon['name']%>"> <% end %> @@ -64,9 +56,7 @@ {{#each customEmojis as |emoji|}} - - - + {{/each}} diff --git a/app/assets/stylesheets/common/base/emoji.scss b/app/assets/stylesheets/common/base/emoji.scss index 1d914c28ae..cfbfbaff50 100644 --- a/app/assets/stylesheets/common/base/emoji.scss +++ b/app/assets/stylesheets/common/base/emoji.scss @@ -1,3 +1,9 @@ +body img.emoji { + width: 20px; + height: 20px; + vertical-align: middle; +} + .emoji-picker { box-shadow: 0 1px 5px rgba(0,0,0,0.4); background-clip: padding-box; @@ -27,6 +33,11 @@ margin: 4px auto; -webkit-filter: grayscale(100%); filter: grayscale(100%); + + button.emoji { + margin: 0; + padding: 0; + } } .emoji-picker .category-icon.current, .emoji-picker .category-icon:hover { @@ -48,10 +59,6 @@ flex-direction: column; } -.emoji-picker .list .emoji { - margin: 5px; -} - .emoji-picker .section-header { padding: 8px; margin-bottom: 4px; @@ -84,13 +91,6 @@ padding: 4px; } -.emoji-picker .section-group a:hover, .emoji-picker .results a:hover { - display: inline-block; - vertical-align: top; - border-radius: 50%; - background-color: lighten($tertiary, 30%); -} - .emoji-picker .footer { align-items: center; display: flex; @@ -146,10 +146,30 @@ text-shadow: 0.5px 1.5px 0 rgba(0,0,0,0.3); } -body img.emoji { - width: 20px; +.emoji-picker button.emoji { + background: transparent; + background-position: center; + background-repeat: no-repeat; + border-radius: 0; + background-size: 20px 20px; + -moz-box-sizing: content-box; + box-sizing: content-box; height: 20px; - vertical-align: middle; + margin: 0; + padding: 0; + border: 0; + vertical-align: top; + width: 20px; + outline: none; + padding: 3px; + margin: 2px; +} + +.emoji-picker .section-group button.emoji:hover, .emoji-picker .results button.emoji:hover { + display: inline-block; + vertical-align: top; + border-radius: 50%; + background-color: lighten($tertiary, 40%); } .wmd-emoji-button:before { @@ -213,21 +233,17 @@ body img.emoji { flex: 1; } -.emoji-picker .results .emoji { - margin: 5px; -} - .emoji-picker .filter .clear-filter { position: absolute; right: 5px; top: 12px; border: 0; background: none; - color: $primary; + color: dark-light-choose(scale-color($header_primary, $lightness: 50%), $header_primary); outline: none; display: none; &:hover { - color: $tertiary; + color: $primary; } } diff --git a/test/javascripts/acceptance/emoji-picker-test.js.es6 b/test/javascripts/acceptance/emoji-picker-test.js.es6 index 9f23c9342c..cb0c68b898 100644 --- a/test/javascripts/acceptance/emoji-picker-test.js.es6 +++ b/test/javascripts/acceptance/emoji-picker-test.js.es6 @@ -36,7 +36,7 @@ QUnit.test("emojis can be hovered to display info", assert => { click("button.emoji.btn"); andThen(() => { - $(".emoji-picker a[title='grinning']").trigger('mouseover'); + $(".emoji-picker button[title='grinning']").trigger('mouseover'); andThen(() => { assert.equal( find('.emoji-picker .info').html().trim(), @@ -52,7 +52,7 @@ QUnit.skip("emoji picker has sections", assert => { click("#topic-footer-buttons .btn.create"); click("button.emoji.btn"); - click(".emoji-picker .categories-column a[title='travel']"); + click(".emoji-picker .categories-column button[title='travel']"); andThen(() => { assert.notEqual( find('.emoji-picker .list').scrollTop(), @@ -67,7 +67,7 @@ QUnit.skip("emoji picker triggers event when picking emoji", assert => { click("#topic-footer-buttons .btn.create"); click("button.emoji.btn"); - click(".emoji-picker a[title='grinning']"); + click(".emoji-picker button[title='grinning']"); andThen(() => { assert.equal( find('.d-editor-input').val(), @@ -81,18 +81,18 @@ QUnit.test("emoji picker has a list of recently used emojis", assert => { visit("/t/internationalization-localization/280"); click("#topic-footer-buttons .btn.create"); click("button.emoji.btn"); - click(".emoji-picker .clear-recent"); - click(".emoji-picker a[title='grinning']"); + click(".emoji-picker .clear-recent"); + click(".emoji-picker .section[data-section='people'] button.emoji[title='grinning']"); andThen(() => { assert.equal( - find('.section[data-section="recent"]').css("display"), + find('.emoji-picker .section[data-section="recent"]').css("display"), "block", "it shows recent section" ); assert.equal( - find('.section[data-section="recent"] .section-group img.emoji').length, + find('.emoji-picker .section[data-section="recent"] .section-group button.emoji').length, 1, "it adds the emoji code to the recently used emojis list" ); @@ -101,19 +101,19 @@ QUnit.test("emoji picker has a list of recently used emojis", assert => { click(".emoji-picker .clear-recent"); andThen(() => { assert.equal( - find('.section[data-section="recent"] .section-group img.emoji').length, + find('.emoji-picker .section[data-section="recent"] .section-group button.emoji').length, 0, "it has cleared recent emojis" ); assert.equal( - find('.section[data-section="recent"]').css("display"), + find('.emoji-picker .section[data-section="recent"]').css("display"), "none", "it hides recent section" ); assert.equal( - find('.category-icon a[title="recent"]').parent().css("display"), + find('.emoji-picker .category-icon button.emoji[data-section="recent"]').parent().css("display"), "none", "it hides recent category icon" ); @@ -126,18 +126,18 @@ QUnit.skip("emoji picker correctly orders recently used emojis", assert => { click("button.emoji.btn"); click(".emoji-picker .clear-recent"); - click(".emoji-picker a[title='grinning']"); - click(".emoji-picker a[title='sunglasses']"); - click(".emoji-picker a[title='grinning']"); + click(".emoji-picker button[title='grinning']"); + click(".emoji-picker button[title='sunglasses']"); + click(".emoji-picker button[title='grinning']"); andThen(() => { assert.equal( - find('.section[data-section="recent"] .section-group img.emoji').length, + find('.section[data-section="recent"] .section-group button.emoji').length, 2, "it has multiple recent emojis" ); assert.equal( - find('.section[data-section="recent"] .section-group img.emoji').first().attr('src'), + find('.section[data-section="recent"] .section-group button.emoji').first().attr('src'), `/images/emoji/emoji_one/grinning.png?v=${v}`, "it puts the last used emoji in first" ); @@ -151,7 +151,7 @@ QUnit.skip("emoji picker lazy loads emojis", assert => { click("button.emoji.btn"); andThen(() => { - const $emoji = $('.emoji-picker a[title="massage_woman"] img'); + const $emoji = $('.emoji-picker button[title="massage_woman"] img'); assert.equal( $emoji.attr('src'), "", diff --git a/test/javascripts/components/d-editor-test.js.es6 b/test/javascripts/components/d-editor-test.js.es6 index 643fc25c52..9f9cbe2217 100644 --- a/test/javascripts/components/d-editor-test.js.es6 +++ b/test/javascripts/components/d-editor-test.js.es6 @@ -766,7 +766,7 @@ componentTest('emoji', { jumpEnd(this.$('textarea.d-editor-input')[0]); click('button.emoji'); - click('a[title=grinning]'); + click('.emoji-picker .section[data-section="people"] button.emoji[title="grinning"]'); andThen(() => { assert.equal(this.get('value'), 'hello world.:grinning:'); });