Vue.js emojione in a chat application
by riyaz_ali
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/emojione@3.1.6/extras/css/emojione.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea.css">
<!-- Vuejs application -->
<div id="app">
<div class="chat">
<message v-for="(msg, index) in messages" :key="index" :class="msg.type" :content="msg.content" />
</div>
<message-box />
</div>
<script type="x-template" id="messagebox">
<div class="message-box">
<textarea></textarea>
</div>
</script>
SCSS
body {
background: #20262e;
padding: 16px;
}
#app {
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
background-image: url('http://backgroundcheckall.com/wp-content/uploads/2017/12/whatsapp-background-android-5.jpg')
}
.chat {
padding: 8px;
height: 100%;
border-radius: 2px;
.message {
margin: 8px 4px;
font-family: sans-serif;
&.sent {
display: flex;
justify-content: flex-end;
margin-left: 25%;
color: #262626;
.bubble {
position: relative;
background: #dcf8c6;
border-radius: .4em;
display: inline-block;
padding: 8px;
&::after {
content: '';
position: absolute;
right: 0;
top: 50%;
width: 0;
height: 0;
border: 9px solid transparent;
border-left-color: #dcf8c6;
border-right: 0;
margin-top: -9px;
margin-right: -9px;
}
}
}
&.received {
margin-right: 25%;
color: #262626;
.bubble {
position: relative;
background: #fff;
border-radius: .4em;
display: inline-block;
padding: 8px;
&::after {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 0;
height: 0;
border: 9px solid transparent;
border-right-color: #fff;
border-left: 0;
margin-top: -9px;
margin-left: -9px;
}
}
}
}
}
.message-box {
position: relative;
padding: 16px;
textarea {
display: block;
border: none;
border-radius: 2px;
outline: none;
padding: 0.5rem;
width: 95%;
margin: auto;
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
}
}
JavaScript
// global require
require.config({
paths: {
'jquery': 'https://code.jquery.com/jquery-3.3.1',
'Vue': 'https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue',
'emojione': 'https://cdn.jsdelivr.net/npm/emojione@3.1.6/lib/js/emojione',
'jquery.textcomplete': 'https://cdnjs.cloudflare.com/ajax/libs/jquery.textcomplete/1.8.4/jquery.textcomplete',
'emojionearea': 'https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea'
},
shim: {
'emojione': {
'exports': 'emojione'
}
},
map: {
"*": {
"jquery": "jquery-shield"
},
"jquery-shield": {
"jquery": "jquery"
},
// patch plugins
"jquery.textcomplete": {
"jquery": "jquery"
},
"emojionearea": {
"jquery": "jquery"
}
}
})
// define shield
define('jquery-shield', ['jquery', 'jquery.textcomplete', 'emojionearea'], function($){
return $ //.noConflict(); uncomment if you want to hide jquery from window
})
// app entrypoint
require(['require', 'jquery', 'Vue', 'emojione', 'jquery.textcomplete', 'emojionearea'], function(require, $, Vue, emojione){
// define the <message /> component
Vue.component('message', {
props: ['content'],
render(h){
return h('div', {
class: {
'message': true
}
}, [h('div', {
class: {
'bubble': true
},
domProps: {
innerHTML: emojione.toImage(this.content)
}
})])
}
});
// define <message-box /> component
Vue.component('message-box', {
template: "#messagebox",
mounted(){
// find the <input />
$(this.$el).find('textarea').emojioneArea()
}
})
// just some helpers
let send = txt => ({type: 'sent', content: txt})
let recv = txt => ({type: 'received', content: txt})
// render our chat application
let $app = new Vue({
data(){
return {
messages: [
send('Hey :hugging:!!'),
recv('Hello there...