In the age of Artificial Intelligence and Machine Learning, chat bots are becoming the major part of many businesses. Chat bots are little different than the menu based systems like IVR calls, where we can have some options to work with and select the responses. Chat Bots can interact with user in innovative ways and make it easier for the user to talk in natural language in place of selecting items from menu. Chat Bots uses NLP (Natural Language Processing) and identify the intent of the users through their messages. In many domain specific chatbots the identification of intent is done through text classification. Another part is extracting meaningful information from the messages posted by the user, this is another area of NLP which is named entity extraction. By the way this post is not covering aspects of NLP and AI of chat bots. Here we are just creating a web based chat bot window which can be easily modified and worked with.
We are going to work with HTML, CSS and JavaScript.
A sample chat windows is present at lower right corner of this page with chatbot symbol: .Let’s take a look into the design of the chatbot window. First of all we see all the web components that is the elements which make the chatbot. It include:
- Chatbot launcher icon
- Chatbot boxed area
- Chatbot title with close, minimize, maximize, expand and collapse buttons
- Text box or Text area for user input
- Send button with html form to submit user input
- Showing user messages and bot responses in single window
Sample HTML look like below. For simplicity purpose I have removed all JavaScript functions which gets called, included ids and classes of elements which can be referred in CSS.
<div id="ChatBot" onclick="toggle_chat_window()">Launch Chatbot
</div>
<div id="chat" class="chat">
<div id="window">
<div id="title">Let's talk about Ankit Gupta
<div id="minimize" type="button" onclick="minimize_chat_window()">_</div>
<div id="maximize" type="button" onclick="maximize_chat_window()">[ ]</div>
<div id="expand" type="button" onclick="expand_chat_window()">< ></div>
<div id="contract" type="button" onclick="contract_chat_window()">> <</div>
<div id="close" type="button" onclick="toggle_chat_window()">✖</div>
</div>
<div class="bot" id="welcome">Hi, I am Ankit's virtual assistant. Please ask me about him or choose the option from below.
</div>
</div>
<form id="to_bot" onsubmit="return add_bot_response(document.getElementById('userMsg').value)">
<input id="userMsg" type="textarea">
<input id="send" value="Send" type="submit">
</form>
</div>
Without CSS the ChatBot window look like below:
As we see with no formatting the HTML doesn’t at all look like a chat window. So let’s add the CSS part to it:
<style>
:root{
--color:#00005e;
--link-bg-color:#87ceeb;
--bot-bg-color:#f2f2f2;
--user-bg-color:#e6e7f2;
--chat-bg-color:#ffffff;
--contract-height:30rem;
--contract-width:20rem;
--expand-width:25rem;
--expand-height:35rem;
--height:var( --contract-height );
--width:var( --contract-width );
--window-position-from-right:0rem;
--window-position-from-bottom:0rem;
--chat-coverage:60%;
--send-button-width:5rem;
--send-button-height:2rem;
}
#chat .link{
background-color:var(--link-bg-color);
color:var(--color);
min-width:calc(var(--width)/3);
min-height:calc(var(--height)/10);
margin:0rem;
padding-top:0.8rem;
border:1px solid var(--color);
border-radius:0.25rem;
text-align:left;
}
#chat a{
text-decoration:none;
color:var(--color);
}
#chat a::after {
content:">";
float:right;
padding-right:0.5rem;
text-decoration:bold;
}
#chat .bot{
position:relative;
background-color:var(--bot-bg-color);
margin:0.20rem;
padding:1rem;
width:var(--chat-coverage);
float:left;
border-radius:0rem 1.5rem 1.5rem 1.5rem;
text-align:justify;
}
.bot::before{
content:url(/wp-content/uploads/2022/05/chatbot.png);
padding-right:1rem;
float:left;
}
.user::before{
content:url(/wp-content/uploads/2022/05/user.png);
padding-left:1rem;
float:right;
}
#userMsg{
position:fixed;
bottom:var(--window-position-from-bottom);
right:calc( var(--window-position-from-right) + var(--send-button-width) );
width: calc( var(--width) - var(--send-button-width) );
height: var(--send-button-height);
border-radius:.25rem;
z-index:999;
font-size:1.5rem;
}
#send{
position:fixed;
bottom:var(--window-position-from-bottom);
right:var(--window-position-from-right);
width:var(--send-button-width);
height:var(--send-button-height);
padding:.25rem;
z-index:999;
}
#chat{
display:none;
border:1px solid var(--color);
position:fixed;
width:var(--width);
height:var(--height);
right:var(--window-position-from-right);
bottom:calc( var(--send-button-height) + var(--window-position-from-bottom) );
background-color:var(--chat-bg-color);
overflow-x:hidden;
overflow-y:auto;
z-index:999;
}
#title{
background-color:var(--color);
position:fixed;
bottom:calc( var(--height) + var(--send-button-height) + var(--window-position-from-bottom) );
width:calc( var(--width) - 1rem);
padding:0.49rem;
border-radius:1rem 1rem 0rem 0rem;
text-decoration:bold;
color:white;
z-index:999;
user-select:none;
}
#close{
position:fixed;
bottom:calc( var(--window-position-from-bottom) + var(--height) + var(--send-button-height) + 0.5rem );
right:calc( var(--window-position-from-right) + 1rem);
}
#maximize{
position:fixed;
bottom:calc( var(--window-position-from-bottom) + var(--height) + var(--send-button-height) + 0.5rem );
right:calc( var(--window-position-from-right) + 2.5rem );
display:none;
}
#minimize{
position:fixed;
bottom:calc( var(--window-position-from-bottom) + var(--height) + var(--send-button-height) + 0.5rem );
right:calc( var(--window-position-from-right) + 2.5rem );
font-weight:bold;
display:block;
}
#expand{
position:fixed;
bottom:calc( var(--window-position-from-bottom) + var(--height) + var(--send-button-height) + 0.5rem );
right:calc( var(--window-position-from-right) + 4rem );
font-weight:bold;
display:block;
}
#contract{
position:fixed;
bottom:calc( var(--window-position-from-bottom) + var(--height) + var(--send-button-height) + 0.5rem );
right:calc( var(--window-position-from-right) + 4rem );
font-weight:bold;
display:none;
}
#ChatBot{
position:fixed;
bottom: var(--window-position-from-bottom) ;
right: var(--window-position-from-right) ;
background-color:white;
z-index:999;
}
#chat .user{
position:relative;
background-color:var(--user-bg-color);
margin:.20rem;
padding:1rem;
width:var(--chat-coverage);
float:right;
text-align:justify;
border-radius:1.5rem 0rem 1.5rem 1.5rem;
}
</style>
The above css hides the chat elements and only shows the section with id ChatBot so you are able to see the text “Launch Chatbot”. Clicking on it doesn’t work as for modification to static page we need to use javascript.
We have following javascript in the code:
<script>
var saved_height_ex = "0px";
var saved_width_ex = "0px";
var saved_height = "0px";
var saved_send_button_height = "0px";
var saved_width = "0px";
function toggle_chat_window(){
var visible = document.getElementById("chat").style.display;
if(visible == "block"){
document.getElementById("chat").style.display="none";
document.getElementById("ChatBot").style.display="block";
}else{
document.getElementById("chat").style.display="block";
document.getElementById("ChatBot").style.display="none";
}
}
function maximize_chat_window(){
var root= document.querySelector(":root");
root.style.setProperty("--height",saved_height);
root.style.setProperty("--send-button-height",saved_send_button_height);
document.getElementById("minimize").style.display="block";
document.getElementById("maximize").style.display="none";
document.getElementById("userMsg").style.display="block";
document.getElementById("send").style.display="block";
}
function minimize_chat_window(){
var root= document.querySelector(":root");
saved_height = getComputedStyle(root).getPropertyValue("--height");
saved_send_button_height = getComputedStyle(root).getPropertyValue("--send-button-height");
root.style.setProperty("--height","0px");
root.style.setProperty("--send-button-height","0px");
document.getElementById("userMsg").style.display="none";
document.getElementById("send").style.display="none";
document.getElementById("minimize").style.display="none";
document.getElementById("maximize").style.display="block";
}
function expand_chat_window(){
var root= document.querySelector(":root");
saved_width_ex = getComputedStyle(root).getPropertyValue("--width");
root.style.setProperty("--width",(getComputedStyle(root).getPropertyValue("--expand-width")));
saved_height_ex = getComputedStyle(root).getPropertyValue("--height");
root.style.setProperty("--height",(getComputedStyle(root).getPropertyValue("--expand-height")));
document.getElementById("expand").style.display="none";
document.getElementById("contract").style.display="block";
}
function contract_chat_window(){
var root= document.querySelector(":root");
root.style.setProperty("--width",(getComputedStyle(root).getPropertyValue("--contract-width")));
root.style.setProperty("--height",(getComputedStyle(root).getPropertyValue("--contract-height")));
document.getElementById("expand").style.display="block";
document.getElementById("contract").style.display="none";
}
function get_bot_response(msg){
if(msg.length == 1){
return "Please select one of the options";
}
return "You will find proper response in near future, currently under development";
}
function add_bot_response(msg){
if(msg.trim().length!=0)
{
var chat=document.getElementById("chat");
var userSaid = document.createElement("div");
userSaid.appendChild(document.createTextNode(msg));
userSaid.classList.add("user");
var botSaid = document.createElement("div");
botSaid.classList.add("bot");
botSaid.appendChild(document.createTextNode(get_bot_response(msg)));
chat.appendChild(userSaid);
chat.appendChild(botSaid);
document.getElementById("userMsg").value="";
chat.scrollTop = chat.scrollHeight;
}
return false;
}
/* Below function isn't working properly yet */
/*function chat_drag_drop_enable(){
var isMoving=false;
var x=0;
var y=0;
var title=document.getElementById("title");
title.addEventListener('mousedown',e => {
var root= document.querySelector(":root");
window_x = getComputedStyle(root).getPropertyValue("--window-position-from-right");
window_y = getComputedStyle(root).getPropertyValue("--window-position-from-bottom");
x = e.offsetX;
y = e.offsetY;
isMoving=true;
});
title.addEventListener('mousemove',e => {
if(isMoving === true){
var root= document.querySelector(":root");
window_x = getComputedStyle(root).getPropertyValue("--window-position-from-right");
window_y = getComputedStyle(root).getPropertyValue("--window-position-from-bottom");
root.style.setProperty("--window-position-from-right",e.offsetX);
root.style.setProperty("--window-position-from-bottom",e.offsetY);
}
});
title.addEventListener('mouseup',e=>{
isMoving = false;
});
}
*/
</script>
This will convert the chatbot window to one you are able to view in bottom right corner of the page.
Update: I have changed the code of chatbot in lower right corner but not on the blog as current code look better to understand. Writing JavaScript within HTML didn’t look good to me. So, I changed the code and added event listeners through JavaScript within JavaScript code to add onclick event to selected elements. It let me write clean code.
Then I got another idea to generate all HTML on the fly, like Angular 2 which used one single element and replace it’s content. The latest code implements that feature too. There is minimal HTML, elements are added through JavaScript and their look and feel modified through CSS.