Skip to content

Instantly share code, notes, and snippets.

@matt-e-king
Last active August 2, 2018 21:36
Show Gist options
  • Save matt-e-king/f3977f226f27d2230d286894e7fab001 to your computer and use it in GitHub Desktop.
Save matt-e-king/f3977f226f27d2230d286894e7fab001 to your computer and use it in GitHub Desktop.
A simple VueJS TidioChat component that creates the <script> tag and accepts an array of supported TidioChat events and $emits them back up to the parent
/**
* TidioChat.js
* A simple VueJS TidioChat component that creates the <script> tag and accepts an array of supported TidioChat events and $emits them back up to the parent
*
* vue-loader single file component example
*
* <template>
* <tidio-chat
* src="//code.tidio.co/<app key>.js"
* :visitor="visitorObject"
* :events="['ready', 'messageFromOperator']"
* @ready="() => { // do something }"
* @messageFromOperator="() => { // do something }">
* </tidio-chat>
* </template>
*
* <script>
* // import tidio component
* import TidioChat from '@/components/TidioChat/TidioChat'
*
* export default {
* components: {
* TidioChat
* },
*
* data() {
* return {
* visitorObject: {
* // see https://docs.tidiochat.com/#defining-visitor-data
* }
* }
* }
* }
* </script>
*/
// using store module tidio.js, which "listens" to the LOGOUT_USE mutation
// then calls window.tidioChatApi.display(false)
// this isn't necessary, can use any technique to check to see if visitor object is empy
import isEmpty from 'lodash.isEmpty'
export default {
name: 'tidio-chat',
watch: {
chatReady: 'initializeChat',
visitor: 'updateVisitor'
},
props: {
id: {
type: String,
default: 'tidioChat'
},
src: {
type: String,
required: true
},
visitor: {
type: Object,
default: () => ({})
},
// pass a props with an array of supported events as strings
// see this.setEventListeners
events: {
type: Array,
validator(vals) {
const tidioEvents = [
'ready',
'setStatus',
'messageFromOperator',
'messageFromVisitor',
'offlineFormFilled',
'preFormFilled',
'resize',
'popUpShow',
'popUpHide'
]
vals.forEach((val) => {
if (!tidioEvents.includes(val)) return false
})
return true
},
default: () => ([])
}
},
created() {
// using VueJS render method
// but this technique can be used with same results
// let tidioScript = document.createElement('script')
// tidioScript.setAttribute('src', this.src)
// tidioScript.setAttribute('id', this.id)
// tidioScript.addEvenListener('load', this.initializeChat)
// document.body.appendChild(tidioScript)
if (document && !isEmpty(this.visitor)) this.updateVisitor()
},
methods: {
updateVisitor() {
document.tidioIdentify = { ...this.visitor }
},
initializeChat() {
this.setEventListeners()
},
// loop over each event in this.events props and set it up as listener with the tidio api
// $emit respective events so parent componenets can react accordingly
setEventListeners() {
if (window.tidioChatApi) {
this.events.map((event) => {
window.tidioChatApi.on(event, (e) => {
this.$emit(event, e)
})
})
} else {
console.warn('window.tidioChatApi not found on window')
}
}
},
render(createElement) {
let { id, src } = this
// using render function to create <script> tag in document
// currently both this way and documet.createElement both create warning:
// [Violation] Avoid using document.write()
return createElement('script', {
attrs: { id, src },
on: {
load: () => { this.initializeChat() }
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment