Overview
'chatux' is a library that allows you to easily create chat windows on your PC or mobile
It is licensed under MIT license.
Features
It is an independent and lightweight chat user interface (chat UI) library for javascript.
- You can create pages for chat agents and chat bots that support both smartphones and PCs.
- For PC, show chat in a window that does not disturb existing content
- For mobile devices like smart phones and tablets, chat UI will be overlaid on existing pages to avoid disturbing
existing content
Demo
https://ayan4m1.github.io/chatux/
Usage
This demo is simple echo chat. But a few command available.If you write "show buttons", you can see action buttons in
chat. Or you write "show image", you can see image in chat.
Example project is available in this repo.
Quick Start
Check this example.
<!doctype html>
<html lang="en">
<head>
<title>chatux example</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1"
/>
</head>
<body style="padding:0px;margin:0px;">
<div style="padding:40px">
<h1>chatux example</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/chatux/dist/chatux.min.js"></script>
<script>
const chatux = new ChatUx();
const opt = {
api: {
endpoint:
'https://script.google.com/macros/s/AKfycbwpf8iZfGXkJD6K__oCVQYF35HLBQjYxmKP0Ifrpe_piK4By4rh/exec',
method: 'GET',
dataType: 'jsonp',
escapeUserInput: true
},
window: {
title: 'My chat',
infoUrl: 'https://github.com/riversun/chatux'
}
};
chatux.init(opt);
chatux.start(true);
</script>
</body>
</html>
Minimal Example
With NPM
npm install chatux --save
Code
import { ChatUx } from 'chatux';
const chatux = new ChatUx();
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
escapeUserInput: true
}
});
chatux.start();
With script tag
<script src="https://cdn.jsdelivr.net/npm/chatux/dist/chatux.min.js"></script>
Code
const chatux = new ChatUx();
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
escapeUserInput: true
}
});
chatux.start();
How it works
The system of chatux is very simple.
Let's look at the execution sequence of chatux.
Suppose you have a chat server for chatux at http://localhost:8080/chat
Specify server endpoint like this.
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
escapeUserInput: true
}
});
The following is the sequence.
{
"output": [
{
"type": "text",
"value": "You say 'hello'"
}
]
}
-
- According to the response, chatux renders the result on the chat screen.
So, if you create chat server that can do this kind of interaction, you can easily create chatbots etc.
Next, let's see how to render.
Chat server
Let's create a simple chat server.
- initialize npm project and install express
npm init
npm install express
- Write a simple server that returns json.
const express = require('express');
const app = express();
const port = 8080;
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', '*');
next();
});
app.get('/chat', function (req, res) {
const userInputText = req.query.text;
const response = {
output: []
};
const msg = response.output;
msg.push({
type: 'text',
value: `You say ${userInputText}`
});
res.json(response);
});
app.listen(port, () => {
console.log('chat server started on port:' + port);
});
npm start
http://localhost:8081/chat?text=hello
You will get JSON for chatux as follows.
{
"output": [
{
"type": "text",
"value": "You say hello"
}
]
}
- Access from ChatUX on browser
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
escapeUserInput: true
}
});
chatux.start(true);
Custom query parameters
There are two approaches to specifying query parameters.
1.Custom query parameters can be set at initialization.
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
params: {
param1: 'value1',
param2: 'value2'
}
}
});
chat ux will send parameters like 'https://example.com/api?param1=value1¶m2=value2'
2.Custom parameters can be set at each request.
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json'
},
methods: {
onPrepareRequest: (httpClient) => {
httpClient.params.param1 = 'value1';
httpClient.params.param2 = 'value2';
},
onFinishRequest: (httpClient) => {
delete httpClient.params.param1;
delete httpClient.params.param2;
}
}
});
If nothing is set, only the query parameter named 'text' will be set when you tap send button.
There are two approaches to set http headers.
1.Custom headeres can be set at initialization.
You can specify http-headers like as follows.
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
escapeUserInput: true,
headers: {
Authorization: 'Bearer ABCD123ABCD123ABCD123',
'X-Additional-Headers': 'something_value'
}
}
});
2.Custom headers can be set at each request.
chatux.init({
api: {
endpoint: 'http://localhost:8080/chat',
method: 'GET',
dataType: 'json',
escapeUserInput: true
},
methods: {
onPrepareRequest: (httpClient) => {
httpClient.headers = {};
httpClient.headers['Authorization'] = 'Bearer ABCD123ABCD123ABCD123';
httpClient.headers['X-Additional-Headers'] = 'something_value';
}
}
});
Note
- Http headers cannot be sent when using jsonp.
- Don't forget 'Access-Control-Allow-Headers' when accessing with cors :)
How to render a chat UI
Since chatux can render various variations of chat UI, I introduce them below. I want to show raw JSON and code example
for chat server respectively.
Show text
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'text',
value: 'Hello world'
});
res.json(response);
});
JSON
{
"output": [
{
"type": "text",
"value": "Hello world!"
}
]
}
RESULT
Show image
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'image',
value: 'https://avatars1.githubusercontent.com/u/11747460'
});
res.json(response);
});
JSON
{
"output": [
{
"type": "image",
"value": "https://avatars1.githubusercontent.com/u/11747460"
}
]
}
RESULT
Show action buttons
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
const opts = [];
opts.push({ label: 'label1', value: 'value1' });
opts.push({ label: 'label2', value: 'value2' });
opts.push({ label: 'label3', value: 'value3' });
msg.push({ type: 'option', options: opts });
res.json(response);
});
JSON
{
"output": [
{
"type": "option",
"options": [
{
"label": "label1",
"value": "value1"
},
{
"label": "label2",
"value": "value2"
},
{
"label": "label3",
"value": "value3"
}
]
}
]
}
RESULT
Show html
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'html',
value:
'Click <a href="https://github.com/riversun" target="_blank" >here</a> to open a page.',
delayMs: 500
});
res.json(response);
});
JSON
{
"output": [
{
"type": "html",
"value": "Click <a href=\"https://github.com/riversun\" target=\"_blank\" >here</a> to open a page.",
"delayMs": 500
}
]
}
RESULT
Show youtube
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
const videoId = 'TP4lxliMHXY';
msg.push({
type: 'youtube',
value: videoId,
delayMs: 500
});
res.json(response);
});
JSON
{
"output": [
{
"type": "youtube",
"value": "TP4lxliMHXY",
"delayMs": 500
}
]
}
RESULT
Show multiple elements
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'text',
value: 'What is this?',
delayMs: 500
});
msg.push({
type: 'image',
value:
'https://upload.wikimedia.org/wikipedia/commons/a/a3/Aptenodytes_forsteri_-Snow_Hill_Island%2C_Antarctica_-adults_and_juvenile-8.jpg'
});
const opts = [];
opts.push({ label: 'bob', value: 'value1' });
opts.push({ label: 'riversun', value: 'value2' });
opts.push({ label: 'john', value: 'value3' });
msg.push({ type: 'option', options: opts });
res.json(response);
});
JSON
{
"output": [
{
"type": "text",
"value": "What is this?",
"delayMs": 500
},
{
"type": "image",
"value": "https://upload.wikimedia.org/wikipedia/commons/a/a3/Aptenodytes_forsteri_-Snow_Hill_Island%2C_Antarctica_-adults_and_juvenile-8.jpg"
},
{
"type": "option",
"options": [
{
"label": "bob",
"value": "value1"
},
{
"label": "riversun",
"value": "value2"
},
{
"label": "john",
"value": "value3"
}
]
}
]
}
RESULT
Open sub window (ex.Url you want to show)
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'window',
title: 'iframe page',
url: 'https://riversun.github.io/i18nice',
left: 20,
top: 20,
width: 400,
height: 250,
addYOffset: true,
overflow: 'hidden',
backgroundColor: 'black',
delayMs: 10
});
res.json(response);
});
JSON
{
"output": [
{
"type": "window",
"title": "iframe page",
"url": "https://riversun.github.io/i18nice",
"left": 20,
"top": 20,
"width": 400,
"height": 250,
"addYOffset": true
}
]
}
RESULT
Open sub window (ex.Show youtube video on the window)
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'window',
title: 'youtube movie',
html:
'<div style="position: relative; width: 100%; padding-top: 56.25%;background:black;overflow: hidden">' +
'<iframe style="position: absolute;top: 0;right: 0;width: 100% !important;height: 100% !important;" width="400" height="300" src="https://www.youtube.com/embed/nepdFs-2V1Y" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>',
mobileUrl: 'https://www.youtube.com/embed/nepdFs-2V1Y',
left: 60,
top: 60,
width: 400,
height: 250,
addYOffset: true,
overflow: 'hidden',
backgroundColor: 'black',
delayMs: 10
});
res.json(response);
});
JSON
{
"output": [
{
"type": "window",
"title": "youtube movie",
"html": "<div style=\"position: relative; width: 100%; padding-top: 56.25%;background:black;overflow: hidden\"><iframe style=\"position: absolute;top: 0;right: 0;width: 100% !important;height: 100% !important;\" width=\"400\" height=\"300\" src=\"https://www.youtube.com/embed/nepdFs-2V1Y\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe></div>",
"mobileUrl": "https://www.youtube.com/embed/nepdFs-2V1Y",
"left": 60,
"top": 60,
"width": 400,
"height": 250,
"addYOffset": true,
"overflow": "hidden",
"backgroundColor": "black",
"delayMs": 10
}
]
}
RESULT
Open sub window (ex.Video on Google Drive)
SERVER CODE
app.get('/chat', function (req, res) {
const response = { output: [] };
const msg = response.output;
msg.push({
type: 'window',
title: 'google drive movie',
html:
'<div style="position: relative; width: 100%; padding-top: 56.25%;background:black;overflow: hidden">' +
'<iframe style="position: absolute;top: 0;right: 0;width: 100% !important;height: 100% !important;" src="https://drive.google.com/file/d/1FfOnq85pQgXtNsZeaF7P_CCsdKzcRrQk/preview" width="400" height="300"></iframe>' +
'</div>',
mobileUrl:
'https://drive.google.com/file/d/1FfOnq85pQgXtNsZeaF7P_CCsdKzcRrQk/preview',
left: 100,
top: 100,
width: 400,
height: 250,
addYOffset: true,
overflow: 'hidden',
backgroundColor: 'black',
delayMs: 10
});
res.json(response);
});
JSON
{
"output": [
{
"type": "window",
"title": "google drive movie",
"html": "<div style=\"position: relative; width: 100%; padding-top: 56.25%;background:black;overflow: hidden\"><iframe style=\"position: absolute;top: 0;right: 0;width: 100% !important;height: 100% !important;\" src=\"https://drive.google.com/file/d/something_id/preview\" width=\"400\" height=\"300\"></iframe></div>",
"mobileUrl": "https://drive.google.com/file/d/something_id/preview",
"left": 100,
"top": 100,
"width": 400,
"height": 250,
"addYOffset": true,
"overflow": "hidden",
"backgroundColor": "black",
"delayMs": 10
}
]
}
RESULT
Initialization parameters
The following example shows all ChatUX initialization parameters. You can customize the behavior of ChatUX as you
like.
const chatux = new ChatUx();
const opt = {
renderMode: 'auto',
buttonOffWhenOpenFrame: false,
bot: {
wakeupText: null,
botPhoto: null,
humanPhoto: null,
widget: {
sendLabel: 'SEND',
placeHolder: 'Say something'
}
},
api: {
endpoint: 'http://localhost:8081/chat',
method: 'GET',
dataType: 'json',
errorResponse: {
output: [
{ type: 'text', value: 'Sorry, an error occurred' }
]
},
headers: {
Authorization: 'Bearer ABCD123ABCD123ABCD123',
'X-Additional-Headers': 'something_value'
},
params: {
param1: 'value1',
param2: 'value2'
}
},
window: {
title: 'My chat',
infoUrl: 'https://github.com/riversun/chatux',
size: {
width: 350,
height: 500,
minWidth: 300,
minHeight: 300,
titleHeight: 50
},
appearance: {
border: {
shadow: '2px 2px 10px rgba(0, 0, 0, 0.5)',
width: 0,
radius: 6
},
titleBar: {
fontSize: 14,
color: 'white',
background: '#4784d4',
leftMargin: 40,
height: 40,
buttonWidth: 36,
buttonHeight: 16,
buttonColor: 'white',
buttons: [
{
fa: 'fas fa-times',
name: 'hideButton',
visible: true
}
],
buttonsOnLeft: [
{
fa: 'fas fa-comment-alt',
name: 'info',
visible: true
}
]
}
}
},
wakeupButton: {
right: 20,
bottom: 20,
size: 60,
fontSize: 25
},
methods: {
onChatWindowCreate: (win) => {
console.log('#onChatWindowCreate');
},
onChatWindowPause: (win) => {
console.log('#onChatWindowPause');
},
onChatWindowResume: (win) => {
console.log('#onChatWindowResume');
},
onUserInput: (userInputText) => {
console.log('#onUserInput userInputText=' + userInputText);
if (userInputText === 'end') {
const consumed = true;
chatux.dispose();
return consumed;
}
},
onServerResponse: (response) => {
console.log('#onServerResponse response=' + JSON.stringify(response));
return response;
}
}
};
chatux.init(opt);
chatux.start(true);