Closed Jenan closed 6 years ago
👋
You will need a regex to detect the colons-syntax emojis, then you will be able to reconstruct your children with a mix of strings and Emoji
components (given you already are in a React app)
Here’s a quick snippet of how we parse them in Missive:
let string = 'Hello, how are you? :thumbsup:'
let regex = new RegExp('(^|\\s)(\:[a-zA-Z0-9-_+]+\:(\:skin-tone-[2-6]\:)?)', 'g')
let match
while (match = colonsRegex.exec(string)) {
let colons = match[2]
let offset = match.index + match[1].length
let length = colons.length
console.log(colons, offset, length)
}
The colons
variable can be used as-is w/ the Emoji
component: <Emoji emoji={colons}>
, it supports skin color too.
The rest (instead of the console.log
) can vary depending on many factors, so I’ll let you figure out how that can be implemented in your app 😄
Thank you for your suggestion.
I would like to ask you about the implementation this awesome component with some input or textarea. Can you share some code or suggest some example how implement this component with input/textbox? :)
BWT: second question - how display in component <Emoji emoji=':)' />
smile like this :)
how to set emoji into a textarea box or input box
Hello @kiranbabu189 , this is a bit complicated, but I have found a good solution.
I will explain it step by step.
Access the onClick method from the emoji-mart and act the chosen emoji.
onClick={this.handleClickEmojiIcon}
handleClickEmojiIcon(emoji) { ... }
Add these two lines to both componentDidMount and componentWillUnmount.
document.addEventListener('input', this.handleCursorPosition.bind(this), true);
document.addEventListener('click', this.handleCursorPosition.bind(this), true);
And create the method
handleCursorPosition(e) {
if (e.target === this.textarea) {
this.setState({
curserPositonStart: e.target.selectionStart,
curserPositonEnd: e.target.selectionEnd });
}
}
Be aware that you must place a reference on the textarea. I have called this in my case textarea.
ref={ref => (this.textarea = ref)}
const textareaStrParts = [
`${this.textarea.value.substring(0, this.state.curserPositonStart)}`,
`${emoji.native}`,
`${this.textarea.value.substring(this.state.curserPositonEnd, this.length)}`,
];
textareaValue = textareaStrParts.join('');
Then you can transfer the result back to the textarea.
I hope I could help you
thanks man for your effort. i will certainly give a try... :)
On Mon, Jul 31, 2017 at 2:05 PM, Jan Bürling notifications@github.com wrote:
Hello @kiranbabu189 https://github.com/kiranbabu189 , this is a bit complicated, but I have found a good solution.
I will explain it step by step.
- Handler for the emoji-mart
Access the onClick method from the emoji-mart and act the chosen emoji.
onClick={this.handleClickEmojiIcon}
handleClickEmojiIcon(emoji) { ... }
- Get the curser positon in textarea
Add these two lines to both componentDidMount and componentWillUnmount.
document.addEventListener('input', this.handleCursorPosition.bind(this), true); document.addEventListener('click', this.handleCursorPosition.bind(this), true);
And create the method
handleCursorPosition(e) { if (e.target === this.textarea) { this.setState({ curserPositonStart: e.target.selectionStart, curserPositonEnd: e.target.selectionEnd }); } }
Be aware that you must place a reference on the textarea. I have called this in my case textarea. ref={ref => (this.textarea = ref)}
- The content of handleClickEmojiIcon method
const textareaStrParts = [
${this.textarea.value.substring(0, this.state.curserPositonStart)}
,${emoji.native}
,${this.textarea.value.substring(this.state.curserPositonEnd, this.length)}
, ];textareaValue = textareaStrParts.join('');
Then you can transfer the result back to the textarea.
I hope I could help you
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/missive/emoji-mart/issues/79#issuecomment-319003881, or mute the thread https://github.com/notifications/unsubscribe-auth/ATR8Sdcc54q29MYC3Xi3zs4sDJwthMEDks5sTZHtgaJpZM4NdA-s .
@kiranbabu189 Please, if you create a detailed working sample, feel free to share it. :)
@janbuerling Why not just use the following this.textarea.selectionStart directly like so:
const textareaStrParts = [
`${this.textarea.value.substring(0, this.textarea.selectionStart)}`,
`${emoji.native}`,
`${this.textarea.value.substring(this.textarea.selectionEnd, this.length)}`,
];
textareaValue = textareaStrParts.join('');
I tried this and it works, however I feel I may be missing an edge case that you aren't...
Hi @EtienneLem Could you please help me figure this out. How I can render
var body = "Hello, how are you? <Emoji emoji=':thumbsup:' size={64} />"
with
<div dangerouslySetInnerHTML={{__html: body}}></div>
Only way I can think of, but only works with native emojis:
var EmojiMart = require('emoji-mart')
var body = "Hello, how are you? ${EmojiMart.emojiIndex.emojis['+1'].native}"
Because dangerouslySetInnerHTML
doesn’t support components, only pure HTML. We could eventually add a toHTML
function to the component that would return an HTML string.
I'd be keen for a toHTML
function. I'm working with a markdown component which requires its input to be supplied in a parameter (it too would be using dangerouslySetInnerHTML
).
+1, I really need toHTML
to support dangerouslySetInnerHTML
too.
Here is my solution to render native emoji as <Emoji />
components. Hope it'll be useful to somebody. Feel free to suggest improvements in the comments to the gist.
Whole code: https://gist.github.com/veob/1dfe6cfb39a4a5768ec66c5e2cec9574
The gist of the gist (sorry):
let matchArr;
let lastOffset = 0;
const parts = [];
// *children* is a string containing native emoji
while ((matchArr = regexp.exec(children)) !== null) {
parts.push(children.substring(lastOffset, matchArr.index));
// skip 2 chars, because an emoji is 2-chars wide
lastOffset = matchArr.index + 2;
const emoji = getByNative(matchArr[0]);
if (emoji) {
parts.push(<Emoji emoji={emoji.id} size={16} />);
} else {
parts.push(matchArr[0]);
}
}
parts.push(children.substring(lastOffset, children.length));
Starting v2.4.1, you can now use the Emoji component with dangerouslySetInnerHTML
Using with
dangerouslySetInnerHTML
The Emoji component being a functional component, you can call it as you would call any function instead of using JSX. Make sure you pass
html: true
for it to return an HTML string.<span dangerouslySetInnerHTML={{ __html: Emoji({ html: true set: 'apple' emoji: '+1' size: 24 }) }}></span>
here is my variant how to take a string like "something righft here and some smile here :shrug: with another :santa::skin-tone-3:" and replace colons in string to emojiis and futher parsing into html:
let matchArr;
let lastOffset = 0;
const regex = new RegExp('(\:[a-zA-Z0-9-_+]+\:(\:skin-tone-[2-6]\:)?)', 'g');
const partsOfTheMessageText = [];
while ((matchArr = regex.exec(currentMessage.text)) !== null) {
const previousText = currentMessage.text.substring(lastOffset, matchArr.index);
if (previousText.length) partsOfTheMessageText.push(previousText);
lastOffset = matchArr.index + matchArr[0].length;
const emoji = (
<Emoji
emoji={matchArr[0]}
set="emojione"
size={22}
fallback={(em, props) => {
return em ? `:${em.short_names[0]}:` : props.emoji;
}}
/>
);
if (emoji) {
partsOfTheMessageText.push(emoji);
} else {
partsOfTheMessageText.push(matchArr[0]);
}
}
const finalPartOfTheText = currentMessage.text.substring(lastOffset, currentMessage.text.length);
if (finalPartOfTheText.length) partsOfTheMessageText.push(finalPartOfTheText);`
and somewhere in return method of message bubble: `return ( ...
...`
adasdaasasd
asda
``
Just tested on latest chrome and safari.
const colons = `:[a-zA-Z0-9-_+]+:`;
const skin = `:skin-tone-[2-6]:`;
const colonsRegex = new RegExp(`(${colons}${skin}|${colons})`, 'g');
interface Props {
content: string;
}
function Component({content}: Props) {
return (
<div>
{content
.split(colonsRegex)
.map(
(emoji, idx) =>
!!emoji && (
<Emoji
size={24}
key={idx}
emoji={emoji}
fallback={() => emoji as any}
/>
)
)}
</div>
);
}
Hello,
I want to display the Emoji Component like bellow but I don't know how can I replace the html result with component like:
Can you help me with this please?
Thank you.
I get html like this
Hello, how are you? :thumbsup:
I would like to get something like this: