ember-emojione
is your emoji solution for Ember, based on the EmojiOne project.
EmojiOne version 2 is used, which is free to use for everyone (CC BY-SA 4.0), you're only required to give appropriate credit to EmojiOne authors somewhere in your app/website. Unfortunately, EmojiOne 3 is a paid product for commercial use.
Demo: https://deveo.github.io/ember-emojione/ ✨
- Support
- Requirements
- Quick installation
- Detailed Installation
- Runtime Configuration in config/environment.js
- Usage
- Upgrading from older versions
- Development
- Credits
- License
Bug reports and feature requests are very welcome. In case you have something to suggest or report, please file an issue to the issue queue. But first make sure there's no similar issue. ;)
If you're having trouble using this addon in your project, please file a properly structured question at StackOverflow. It is important that you use ember.js
and ember-emojione
tags for your question to be seen.
- Ember 2.16+
- Node 8+
If you don't want to go into the nuances of installation and configuration, use these short installation instructions. Then you can skip to the Usage section.
Quick installation will use these defaults:
- Emoji are rendered as PNG sprites.
- Sprite size is 64×64 px.
- The sprite sheet is included into your app's distro (it's not available on JSDelivr).
- This addon's components are available (picker, wrapper, typing assistance).
Run these console commands in your app:
ember install ember-emojione
bower install -S emojione-js=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/lib/js/emojione.js
bower install -S emojione-css=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/assets/sprites/emojione.sprites.css
bower install -S emojione-png=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/assets/sprites/emojione.sprites.png
bower install -S emojione-defs=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/emoji.json
If your app uses ember-cli-sass
, the addon will not import component CSS automatically, so that you have more control. Import manually what you need:
@import "node_modules/ember-emojione/app/styles/helpers/mixin";
@import "node_modules/ember-emojione/app/styles/components/emoji-assist";
@import "node_modules/ember-emojione/app/styles/components/emoji-picker";
Now you should be good to go. If your development server has been running, don't forget to restart it.
The emojione
Bower package, which this addon relies on, is over 90 MiB large. As EmojiOne assets can be served from the "free and super-fast" JSDelivr CDN, many developers won't need any EmojiOne images locally.
This addon can be configured to include as few or as much assets and dependencies as you need.
With npm:
ember install ember-emojione
With Yarn:
yarn add -D ember-emojione
If you choose to use individual images (i. e. no sprite sheet) AND you want to bundle individual emoji images into your app distro (i. e. no separate CDN), you'll need to install the full emojione
package (option 2).
In any other case, it is recommended that you install only the files you need (option 1).
The bare minimum you need to display emoji are just two files: JS and CSS. To use this addon's components, you'll also need the JSON file with emoji definitions.
Luckily, Bower allows downloading individual files as individual dependencies:
First, include the EmojiOne JS library (note that the package name is emojione-js
and not simply emojione
):
bower install -S emojione-js=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/lib/js/emojione.js
Then include the CSS. Here you have two options.
Normal CSS, works with individual PNGs, individual SVGs and SVG sprite sheet:
bower install -S emojione-css=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/assets/css/emojione.css
Or, if you want to use PNG sprite sheet, add this CSS instead:
bower install -S emojione-css=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/assets/sprites/emojione.sprites.css
If you're gonna use the components, you'll also need emoji definitions. Definitions add 438 KiB to your distro size (54 KiB gzipped).
bower install -S emojione-defs=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/emoji.json
If you chose to use a sprite sheet, you must install it locally, because EmojiOne sprite sheets aren't available on JSDelivr (as of January 2017). Skip this step if you're gonna serve the sprite sheet from your own CDN, separate from you app distro.
PNG sprite sheet:
bower install -S emojione-png=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/assets/sprites/emojione.sprites.png
SVG sprite sheet:
bower install -S emojione-svg=https://raw.githubusercontent.com/Ranks/emojione/v2.2.7/assets/sprites/emojione.sprites.svg
Including the whole package, which is over 90 MiB large, is only reasonable if you want to use individual images rather than sprite sheets AND you want to serve them locally rather than via the free CDN.
Simply install it via:
bower install -S emojione
Note: your app's distro size will not grow by 90 MiB. In the next installation step, you'll decide which assets to include into the distro.
But every clean bower install
will be substantially slower. This may include your CI builds.
Values shown below are the defaults. If you're happy with them, you don't need to edit ember-cli-build.js
at all.
var app = new EmberApp(defaults, {
'ember-emojione': {
// Did you install individual files or the full package?
separatePackages: true,
// Do you want EmojiOne CSS to be included in your app?
shouldImportCss: true,
// Are you going to use components that insert emoji?
shouldImportDefs: true,
// Whether to use a sprite sheet or individual images
spriteSheet: true,
// Enable one of these options if you want to include
// EmojiOne assets into your app's distro.
shouldIncludePngSprite: true,
shouldIncludeSvgSprite: false,
shouldIncludePngImages: false,
shouldIncludeSvgImages: false,
// If you chose individual images in the previous section,
// you can customize their size and color here.
// 'png' and 'png_bw' assets come in 64×64 px size.
pngImagesKind: 'png', // png, png_128x128, png_512x512, png_bw
svgImagesKind: 'svg', // svg, svg_bw
// You can also customize package names to import.
// You don't need to edit this if you carefully followed
// previous installation steps
packageNameMain: 'emojione',
packageNameJs: 'emojione-js',
packageNameCss: 'emojione-css',
packageNameDefs: 'emojione-defs',
packageNamePngSprite: 'emojione-png',
packageNameSvgSprite: 'emojione-svg',
// Whether to keep or remove `ember-emojione` components from build
shouldIncludeComponents: true,
},
});
Note: if you set shouldIncludeComponents
to false
, you will not be able to define the following modules in your app:
app/components/emoji-picker
app/components/emoji-picker/*
app/components/emoji-picker-wrapper
app/components/emoji-picker-toggler
app/components/emoji-typing-assistance
app/helpers/eeo-*
Skip this section if you're not using this addon's components.
If your app uses ember-cli-sass
, add some of these to your Sass:
@import "node_modules/ember-emojione/app/styles/helpers/mixin";
@import "node_modules/ember-emojione/app/styles/components/emoji-assist";
@import "node_modules/ember-emojione/app/styles/components/emoji-picker";
If your app doesn't use ember-cli-sass
, precompiled styles will be included automatically.
Configuration is optional. If you're happy with defaults shown below, you don't need to edit config/environment.js
.
ember-emojione
relies on emojione.js defaults.
To configure ember-emojione
and override emojione
options, add these options to your app's config/environment.js
. Default values are shown:
"ember-emojione": {
// Used to skip certain portions of the input string.
// Useful for Markdown code blocks. Apply after Markdown transformation.
// Set to `false` to disable.
regexToSkip: /<code[\s\S]*?>[\s\S]*?<\/code>/gm,
// EmojiOne library options
emojione: {
imageType: 'png', // or svg
imageTitleTag: true, // set to false to remove title attribute from img tag
unicodeAlt: true, // use the unicode char as the alt attribute (makes copy and pasting the resulting text better)
ascii: false, // change to true to convert ascii smileys
// The following options are inferred from `ember-cli-build.js`.
// You only need to override these options if you want to serve
// assets from a custom CDN separate from you app's distro.
imagePathPNG: 'https://cdn.jsdelivr.net/emojione/assets/png/',
imagePathSVG: 'https://cdn.jsdelivr.net/emojione/assets/svg/',
imagePathSVGSprites: './../assets/sprites/emojione.sprites.svg',
}
}
Things to note:
-
The
sprites
option can not be configured from here. To enablesprites
, override thespriteSheet
option inember-cli-build.js
. It is also possible to override thesprites
when invoking theinject-emoji
helper. -
The path to PNG sprite sheet is configured via CSS. If you're serving it from a custom CDN, add this style into your app:
.emojione { background-image: url('path/to/your/emojione.sprites.png'); }
-
If you chose to include local SVG assets, default SVG paths will use root-relative urls, e. g.
/ember-emojione/svg/1f631.svg
. If you serve your app from a subdirectory, please override one of the SVG URL options to include the subdirectory. You don't need this if you serve SVG assets from a CDN (default).
This helper is used to convert a string with emoji codes into a string of HTML with emoji images.
You must manually mark the input string as HTML-safe:
Ember.String.htmlSafe("Hi! :sunglasses:")
By doing so you acknowledge responsibility that the input string never contains malicious code. Neglecting this responsibility will make your app/website prone to XSS attacks.
Use triple curlies to inject HTML into your template:
Result:
You can override ember-emojione
and emojione.js
options for a single invocation of inject-emoji
:
If you use individual PNGs, individual SVGs or SVG sprites, customizing emoji size is quite easy: you simply apply width
and height
to the .emojione
selector.
But for PNG sprites (default), that won't work.
The easiest solution for PNG sprites is to use the zoom
CSS property, but it doesn't work in Firefox.
For a cross-browser solution, use the code below. It is a Sass mixin; if you're not using Sass, you can compile it on SassMeister. The trick is to scale the emoji via CSS transform, then apply negative margins to remove extra whitespace.
@mixin emojione-size ($target-size, $original-size: 64px) {
transform: scale(#{$target-size / $original-size});
margin: ($target-size - $original-size) / 2;
}
.emojione {
@include emojione-size(20px);
}
If this is unacceptable for you, use custom-sized PNG spritesheets. Official EmojiOne spritesheets have an unfortunate 1px padding between sprites, making it impossible to resize it with background-size
.
To resolve this problem, whe have prepared cusrom PNG spritesheets tailored to various sizes: emojione-png-sprites.
Here's a StackOverflow post explaining in detail how to use ember-emojione
with emojione-png-sprites
.
You can inject emoji programmatically via the injectEmoji
convenience function:
import {injectEmoji} from 'ember-emojione/helpers/inject-emoji';
injectEmoji(inputString, options);
It returns an html-safe string if the input was html-safe. Otherwise, it returns a regular string.
import {htmlSafe, isHTMLSafe} from '@ember/string';
import {injectEmoji} from 'ember-emojione/helpers/inject-emoji';
const options = {regexToSkip: false, emojiOne: {ascii: true}};
const inputUnsafeString = ':D';
const resultUnsafeString = injectEmoji(inputUnsafeString, options);
isHTMLSafe(resultUnsafeString) // => false
typeof resultUnsafeString; // => "string"
const inputSafeString = htmlSafe(inputUnsafeString);
const resultSafeString = injectEmoji(inputSafeString, options);
isHTMLSafe(resultSafeString); // => true
typeof resultSafeString; // => "object"
typeof resultSafeString.toString(); // => "string"
inject-emoji
will ignore emoji located within portions of the input string that match given regular expression.
The regex can be configured via the regexToSkip
option.
By default, the regex matches <code>...</code>
elements.
To disable skipping, set regexToSkip
to false
.
emoji-picker-wrapper
abstracts the logic of:
- showing/hiding the
emoji-picker
andemoji-typing-assistance
popups; - positioning the
emoji-typing-assistance
popup next to the caret; - inserting emoji into the text field, taking into consideration caret position;
- navigating the
emoji-typing-assistance
popup with the keyboard while staying focused on the text field...
...while making no assumptions about page layout and looks, giving you full control.
The price of giving you full control of layout and looks is pretty elaborate usage.
Here's the full example. Below it's broken down into steps.
{
wikiPageText: 'This is a sample wiki page',
}
To understand the example, let's assemble it step by step.
-
We start with a text field, either an
input
ortextarea
. This text field accepts a value with a text from thewikiPageText
property:{ wikiPageText: 'This is a sample wiki page', }
-
In your HTML structure, decide where you're gonna put the emoji picker popup and the button that toggles the emoji picker.
The locations depend on your HTML layout and page design. In this example, we're gonna keep it simple:
-
Wrap the text field with an HTML element that has
position: relative
anddisplay
of eitherblock
orinline-block
:In this example the HTML element uses inline styles for simplicity, but that's not a requirement.
-
The emoji typing assistance popup should be located next to the textarea, within that element with
position: relative
: -
Wrap the three items with the
emoji-picker-wrapper
component:It should serve as a common parent for everything that we set up earlier.
-
Pass the following arguments into the wrapper component:
text
: the same bound property as you pass into the text field;inputSelector
: a CSS selector that uniquely identifies the text field within the wrapper;
-
Implement the
emojiInsertedAction
action and pass it into the wrapper component.The action receives the text updated with emoji inserted. It must update the value that you pass into both the text field and the wrapper.
The action could look like this:
actions: { emojiInserted(text) { this.setProperties({text}); } }
But the simplest way of implementing the action is the
mut
helper, which lets you avoid adding the above action code to your controller/component. -
The wrapper component will create instances of the three child components:
emojiPicker
,emojiPickerToggler
andemojiAssist
.These instances come preconfigured to work together, saving you a ton of boilerplate code.
Receive them from the wrapper component and insert into dedicated places:
You can customize them if you want. Read each component's documentation below to see how you can customize them.
That's it!
Here's a list of options that are preconfigured for the components. Make sure not to override them:
-
emoji-picker
selectAction
closeAction
isVisible
-
emoji-picker-toggler
toggleAction
isEmojiPickerVisible
-
emoji-typing-assistance
filterInput
$input
keyPressNotifier
selectAction
Option | Type | Default value | Description |
---|---|---|---|
inputSelector |
String | required | Unique selector of a text field where emoji will be inserted. |
text |
String | required | Content of the text field. Emoji code will be inserted into this text. |
emojiInsertedAction |
Action | required | Action to execute when emoji is inserted. Will be called with new text already containing an emoji code. |
shouldSetFocusToInput |
Boolean | true |
Whether to focus on the input field after emoji insertion or closing the picker with Esc. |
isEmojiPickerVisible |
Boolean | false |
Lets you control picker visibility manually. Don't override this if you're using emojiPickerToggler which controls it for you. |
emojiTypingRegex |
RegExp | `/(?:^ | \s)(:[\w_+-]+)$/` |
emoji-picker-wrapper
yields a hash that contains the following properties:
Option | Type | Description |
---|---|---|
emojiPicker |
Component | Preconfigured emoji-picker component. |
emojiPickerToggler |
Component | Preconfigured emoji-picker-toggler component. |
emojiAssist |
Component | Preconfigured emoji-typing assistance component. |
isEmojiPickerVisible |
Boolean | Whether emoji picker is visible. |
This component is used to select emoji from a list. Designed as a popup.
Render it like this:
The following options are preconfigured by the wrapper component. Override them only if you're using emoji-picker
manually, without the wrapper:
Option | Type | Default value | Description |
---|---|---|---|
selectAction |
Action | required | Action to execute when an emoji is clicked |
closeAction |
Action | undefined |
Action to execute on click outside of the component |
isVisible |
Boolean | false |
Controls component visibility with display: none (from Ember.Component ) |
These are the options that you can configure regardless of whether you're using the wrapper.
Option | Type | Default value | Description |
---|---|---|---|
toneSelectAction |
Action | undefined |
Action to execute when skin tone is changed |
shouldCloseOnSelect |
Boolean | false |
Whether to execute the close action when an emoji is selected |
disableAutoFocus |
Boolean | false |
Prevents from focusing on component when first rendered |
textNoEmojiFound |
String | "No emoji found" |
Override for i18n |
textSearch |
String | "Search" |
Override for i18n |
textClearSearch |
String | "Clear search" |
Override for i18n |
This component isn't supposed to be used separately. It's yielded by the emoji-picker-wrapper
component and is used to control emoji picker visibility.
This component has no styles, you'll have to style it yourself.
Can be used in inline and block form.
Options preconfigured by the wrapper are not listed.
Option | Type | Default value | Description |
---|---|---|---|
label |
String or undefined | undefined |
If block is not provided, will be used for button content. |
labelWhenOpen |
String or undefined | undefined |
If block is not provided, will be used for button content when the picker is visible. If not provided, label will be used instead. |
any other attribute | String or undefined |
undefined |
Any other attributes will be bound to HTML attributes of the component. |
This component isn't supposed to be used separately. It's yielded by the emoji-picker-wrapper
component and is used to control emoji picker visibility.
It shows suggestions when user types in an emoji code, letting them insert the emoji quicker.
Options preconfigured by the wrapper are not listed.
Option | Type | Default value | Description |
---|---|---|---|
minLength |
Integer | 3 |
Minimum length of the emoji code fragment for the component to appear, including the leading colon. |
The emojione
library makes itself available as a global.
To help you stay true to the Ember way, this addon lets you import the library as a ES module:
import emojione from 'emojione';
The hack we
The addon itself does not integrate with any i18n solution.
Components accept i18n strings as arguments. You can subclass components to change defaults.
In order to translate emoji descriptions (visibile on some emoji on hover), you'll have to override the emojiDefs
property on the emoji
service.
Some major version bumps introduce breaking changes. Read below what you need to change in your app in order to upgrade ember-emojione
.
emoji-picker-wrapper
used to yield three components separately:
In 2.0.0+, it yields a hash that contains the components:
No changes required.
npm i -g yarn
git clone <repository-url>
this repositorycd ember-emojione
yarn install
⚠️ bower install
npm run lint:hbs
npm run lint:js
npm run lint:js -- --fix
ember test
– Runs the test suite on the current Ember versionember test --server
– Runs the test suite in "watch mode"ember try:each
– Runs the test suite against multiple Ember versions
This project uses Yarn to lock dependencies. Install yarn with npm i -g yarn
.
To install this addon's npm dependencies locally, do:
yarn install
To install an Ember addon into this addon, do:
yarn add -D <package-name>
ember g <package-name>
An error message "no such blueprint" is expected in case the addon does not want to do boilerplate customizations.
For more information on using ember-cli, visit https://ember-cli.com/.
Main branches are named as gen-1
, gen-2
, etc. Default branch on GitHub is where active development happens.
This naming scheme is due to the fact that this project uses SemVer. As a result, major version number will rise very quickly, without any correlation with actual major changes in the app.
The number in the branch name, "generation", is supposed to be incremented in these cases:
- A huge improvement or change happens in the addon.
- There's a change in the addon's API or architecture which introduces a necessity to maintain more than one branch at a time.
- The codebase is started from scratch.
Pull requests are welcome from feature branches. Make sure to discus proposed changes with addon maintainers to avoid wasted effort.
Maintaining the TOC by hand is extremely tedious. Use this tiny webapp to generate the TOC automatically. Enable the first two checkboxes there.
This command will deploy the app to https://deveo.github.io/ember-emojione/ :
ember deploy prod
Proudly built in @Deveo by @lolmaus, @vvainio and contributors.
This addon includes fragments of code borrowed from:
- the crhayes/ember-cli-emojione addon (MIT license),
- the cibernox/ember-power-select addon (MIT license),
- the DockYard/ember-one-way-controls addon (MIT license),
- Elad Shahar's template string CP gist (MIT license).
MIT.