UNPKG

@claudio.giuliano/fm-chatbot-client

Version:

A chat widget to deploy virtual assistants made with Rasa on any website

962 lines (837 loc) 37.7 kB
/* global console*/ function FmChatbotEs5() { 'use strict'; var _this = this; var UID = new IDGenerator().generate(); var DEFAULT_FONT_FAMILY = "\"Titillium Web\", \"Geneva\", \"Tahoma\", sans-serif, serif";//"Arial, Helvetica, sans-serif"; var DEFAULT_PAY_LOAD = "/start"; var apiUrl = null; var selector = "fm-chatbot"; /** * Gets the browser's name and version * @constructor */ function Browser() { this.get = function getBrowser() { var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; console.debug("user agent", ua); if (/trident/i.test(M[1])) { tem = /\brv[ :]+(\d+)/g.exec(ua) || []; return {name: 'IE', version: (tem[1] || '')}; } if (M[1] === 'Chrome') { tem = ua.match(/\bOPR|Edge\/(\d+)/); if (tem !== null) { return {name: 'Opera', version: tem[1]}; } } M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?']; if ((tem = ua.match(/version\/(\d+)/i)) !== null) { M.splice(1, 1, tem[1]); } return { name: M[0], version: parseInt(M[1]) }; }; } var BROWSER = new Browser().get(); /** * Creates the chatbot widget * @param args */ this.create = function (args) { console.info("creating the chatbot widget...", args); console.info("browser", BROWSER); //todo polling to check the connection // selector contains the chatbot in the host page if (args.hasOwnProperty("selector")) { selector = args.selector; } if (args.hasOwnProperty("apiUrl")) { try { apiUrl = new URL(args.apiUrl); } catch (e) { console.error(e); return; } } else { console.warn("no apiURL"); } //todo load/save the conversations? document.addEventListener("DOMContentLoaded", function () { // create and show the chatbot widget init(args); // change the widget size based on media type media(args); // welcome the user, or send a notification if the service is not available // to in this case che chatbot could be closed welcome(args); }); // todo change position based on the page scroll // document.addEventListener("scroll", function () { // console.info("scrolling..."); // let chatbotContainer = document.getElementById(selector); // // console.info("scrolling...", document.documentElement.scrollTop); // if (document.documentElement.scrollTop > 0) { // chatbotContainer.style.paddingBottom = "100px"; // } else { // chatbotContainer.style.paddingBottom = "0"; // } // }); }; var MAX_WIDTH = 640; var MAX_HEIGHT = 420; /** * Sets the chatbot widget size based on the media type. * @param args */ function media(args) { console.log("changing the chatbot widget size..."); var maxWidthQuery = window.matchMedia("screen and (max-width: " + MAX_WIDTH + "px)"); fitToWidth(maxWidthQuery); var maxHeightQuery = window.matchMedia("screen and (max-height: " + MAX_HEIGHT + "px)"); fitToHeight(maxHeightQuery); // addEventListener is not supported on Safari < 14 (See https://stackoverflow.com/questions/35719526/safari-ignore-window-matchmedia) if (BROWSER.version >= 14) { maxWidthQuery.addEventListener('change', fitToWidth); maxHeightQuery.addEventListener('change', fitToHeight); } else { maxWidthQuery.addListener(fitToWidth); maxHeightQuery.addListener(fitToHeight); } } /** * Sets the chatbot widget width. * @param e */ function fitToWidth(e) { console.info("fit the chatbot widget to screen width", e); var chatbotContainer = document.getElementById(selector); var chatbotOpenIcon = document.getElementById("fm-chatbot-open-icon"); var chatbotOpenBtn = document.getElementById("fm-chatbot-open-btn"); var chatbotGrid = document.getElementById("fm-chatbot-grid"); var viewportSize = getViewportSize(); console.debug("chatbot size", viewportSize); //todo use padding if back-to-top is displayed: back-to-top-show if (e.matches) { /* the viewport is MAX_WIDTH pixels wide or less */ console.debug("the viewport is " + MAX_WIDTH + "pixels wide or less", e); chatbotContainer.style.margin = "16px"; chatbotOpenBtn.style.width = "40px"; chatbotOpenBtn.style.height = "40px"; chatbotOpenIcon.style.fontSize = "20px"; //var w = viewportSize["width"] - 32; //let h = viewportSize["height"] - 60 - 70 - 100; //console.info("w,h", w, h); //chatbotGrid.style.gridTemplateColumns = w + "px"; chatbotGrid.style.gridTemplateColumns = "auto"; } else { /* the viewport is more than than MAX_WIDTH pixels wide */ console.debug("the viewport is more than than " + MAX_WIDTH + " pixels wide", e); chatbotContainer.style.margin = "32px"; chatbotOpenBtn.style.width = "56px"; chatbotOpenBtn.style.height = "56px"; chatbotOpenIcon.style.fontSize = "32px"; // chatbotContainer.style.bottom = "32px"; // chatbotContainer.style.right = "32px"; var w = MAX_WIDTH - 64; //let h = 300 - 60 - 70;//viewportSize["height"] - 200; //console.info("w,h", w, h); chatbotGrid.style.gridTemplateColumns = w + "px"; } } /** * Sets the chatbot widget height. * @param e */ function fitToHeight(e) { console.info("fit the chatbot widget to screen height", e); var chatbotContainer = document.getElementById(selector); var chatbotGrid = document.getElementById("fm-chatbot-grid"); var chatbotHeader = document.getElementById('fm-chatbot-header'); var chatbotFooter = document.getElementById('fm-chatbot-footer'); var viewportSize = getViewportSize(); console.debug("chatbot size", viewportSize); var h; if (e.matches) { /* the viewport is MAX_HEIGHT pixels high or less */ console.debug("the viewport is " + MAX_HEIGHT + " pixels high or less", e); h = viewportSize["height"] - chatbotHeader.offsetHeight - chatbotFooter.offsetHeight - 100; console.debug("h,w,h,f", h, viewportSize["height"], chatbotHeader.offsetHeight, chatbotFooter.offsetHeight); //chatbotGrid.style.gridTemplateColumns = w + "px"; //chatbotGrid.style.gridTemplateColumns = "auto"; chatbotGrid.style.gridTemplateRows = "auto " + h + "px auto"; //chatbotGrid.style.gridTemplateRows = "auto auto auto"; } else { /* the viewport is more than than MAX_HEIGHT pixels high */ console.debug("the viewport is more than than " + MAX_HEIGHT + " pixels high", e); h = MAX_HEIGHT - chatbotHeader.offsetHeight - chatbotFooter.offsetHeight;//viewportSize["height"] - 200; console.debug("h,w,h,f", h, viewportSize["height"], chatbotHeader.offsetHeight, chatbotFooter.offsetHeight); chatbotGrid.style.gridTemplateRows = "auto " + h + "px auto"; } } /** * Issues intent /start to get the welcome message. * @param args */ function welcome(args) { console.info("getting the welcome message..."); var initPayload = DEFAULT_PAY_LOAD; if (args.hasOwnProperty("initPayload") && args.initPayload.length) { initPayload = args.initPayload; } call(initPayload, args); } function deleteCookie(name, path, domain) { if (getCookie(name)) { document.cookie = name + "=" + ((path) ? ";path=" + path : "") + ((domain) ? ";domain=" + domain : "") + ";expires=Thu, 01 Jan 1970 00:00:01 GMT"; } console.debug("chatbot cookies", document.cookie); } function setCookie(name, value, days) { var d = new Date(); d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)); var expires = "expires=" + d.toUTCString(); document.cookie = name + "=" + value + ";" + expires + ";path=/"; console.debug("set the chatbot cookies", document.cookie); } function getCookie(name) { console.debug("getting the chatbot cookies", document.cookie); name += "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) === ' ') { c = c.substring(1); } if (c.indexOf(name) === 0) { return c.substring(name.length, c.length); } } return ""; } /** * Inits the chatbot widget. * @param args */ function init(args) { console.info("initializing the chatbot widget...") addChatbotStyle(args); //let position = getPosition(args); var chatbotContainer = document.getElementById(selector); chatbotContainer.style.position = "relative"; chatbotContainer.style.zIndex = "2"; chatbotContainer.style.fontFamily = DEFAULT_FONT_FAMILY; chatbotContainer.style.position = "fixed"; chatbotContainer.style.bottom = "0"; chatbotContainer.style.right = "0"; // chatbotContainer.setAttribute("role", "region"); // chatbotContainer.setAttribute("aria-label", "Finestra del chatbot"); //<h1 id="tchat-title" class="sr-only">Finestra del chatbot</h1> // chatbotContainer.style.bottom = position["bottom"] + "px"; // chatbotContainer.style.right = position["right"] + "px"; var chatbotButton = addAndGetChatbotButton(args); var chatbotComponent = addAndGetChatbotComponent(args); //todo set not visible when created chatbotContainer.appendChild(chatbotButton); chatbotContainer.appendChild(chatbotComponent); var open = args.hasOwnProperty("open") ? args.open : true; var isVisible = getCookie("is_visible"); //showChatbotSwitch(isVisible); if (open && isVisible !== null && isVisible === "true") { showChatbotComponent(args); } else { hideChatbotComponent(args); } var botInput = document.getElementById("fm-chatbot-input"); botInput.addEventListener("keyup", function (event) { console.trace(event); if (event.code === "Enter") { // Cancel the default action, if needed event.preventDefault(); submitMessage(args); } updateSubmitMessage(); }); var closeBtn = document.getElementById("fm-chatbot-close-btn"); closeBtn.onclick = function () { hideChatbotComponent(args); setCookie("is_visible", false, 90); // toggleChatbotComponent() }; var openBtn = document.getElementById("fm-chatbot-open-btn"); openBtn.onclick = function () { showChatbotComponent(args); setCookie("is_visible", true, 90); }; var sendBtn = document.getElementById("fm-chatbot-send-btn"); sendBtn.onclick = function () { submitMessage(args); updateSubmitMessage(); }; } /** * Shows/hides the send button. */ function updateSubmitMessage() { var botInput = document.getElementById("fm-chatbot-input"); var sendBtn = document.getElementById("fm-chatbot-send-btn"); //console.debug("input",botInput.value); if (botInput.value.length === 0) { sendBtn.style.visibility = "hidden"; sendBtn.setAttribute("aria-hidden", "true"); } else { sendBtn.style.visibility = "visible"; sendBtn.setAttribute("aria-hidden", "false"); } } /** * Dynamically sets the chatbot style. */ function addChatbotStyle(args) { console.info("adding chatbot style...", args); //Google fonts var link = document.createElement('link'); link.rel = 'stylesheet'; link.href = "https://fonts.googleapis.com/icon?family=Material+Icons"; var head = document.getElementsByTagName('head')[0]; head.appendChild(link); //.sr-only // see https://a11y-guidelines.orange.com/en/web/components-examples/chatbot/ var srOnlyStyle = document.createElement('style'); //style.type = 'text/css'; srOnlyStyle.innerHTML = '.sr-only { position: absolute;\n' + ' width: 1px;\n' + ' height: 1px;\n' + ' padding: 0;\n' + ' margin: -1px;\n' + ' overflow: hidden;\n' + ' clip: rect(0,0,0,0);\n' + ' border: 0; }'; head.appendChild(srOnlyStyle); // // .tooltip // var tooltipStyle = document.createElement('style'); // tooltipStyle.innerHTML = '.tooltip {\n' + // ' position: relative;\n' + // ' display: inline-block;\n' + // ' }'; // // head.appendChild(tooltipStyle); // // var tooltipAndTextStyle = document.createElement('style'); // tooltipAndTextStyle.innerHTML = '.tooltip .tooltiptext1 {\n' + // ' visibility: hidden;\n' + // ' width: 200px;\n' + // ' background-color: #F5F5F5;\n' + // ' color: black;\n' + // ' /*text-align: center;*/\n' + // ' border-radius: 4px;\n' + // ' padding: 5px;\n' + // ' position: absolute;\n' + // ' z-index: 1;\n' + // ' bottom: 150%;\n' + // ' right: 0%;\n' + // ' margin-left: -120px;\n' + // ' opacity: 0;\n' + // ' transition: opacity 0.3s;\n' + // ' text-align: left;\n' + // ' font-size: 0.8em;\n' + // ' padding: 5px;\n' + // ' }'; // // // head.appendChild(tooltipAndTextStyle); // // var tooltipAndTextAfterStyle = document.createElement('style'); // tooltipAndTextAfterStyle.innerHTML = '.tooltip .tooltiptext1::after {\n' + // ' content: "";\n' + // ' position: absolute;\n' + // ' top: 100%;\n' + // ' right: 10%;\n' + // ' /*margin-left: -5px;*/\n' + // ' border-width: 5px;\n' + // ' border-style: solid;\n' + // ' border-color: #F5F5F5 transparent transparent transparent;\n' + // ' }'; // // // head.appendChild(tooltipAndTextAfterStyle); // // var tooltipHoverAndTextStyle = document.createElement('style'); // tooltipHoverAndTextStyle.innerHTML = '.tooltip:hover .tooltiptext1 {\n' + // ' visibility: visible;\n' + // ' opacity: 1;\n' + // ' }'; // // // head.appendChild(tooltipHoverAndTextStyle); } /** * Returns the viewport size. * @returns {{width, height}} */ function getViewportSize() { var e = window; var a = 'inner'; if (!('innerWidth' in window)) { a = 'client'; e = document.documentElement || document.body; } return {width: e[a + 'Width'], height: e[a + 'Height']}; } /** * Creates and returns the chatbot component. * @param args * @returns {HTMLDivElement} */ function addAndGetChatbotComponent(args) { console.info("adding the chatbot component...", args); //let dimensions = getDimensions(args); var chatbotComponent = document.createElement('div'); chatbotComponent.id = "fm-chatbot-container"; // chatbotContainer.style.position = "fixed"; // chatbotContainer.style.bottom = "161px"; // chatbotContainer.style.right = "20px"; chatbotComponent.style.background = "transparent"; chatbotComponent.style.borderRadius = "4px 4px 4px 4px"; chatbotComponent.style.boxShadow = "0 0 5px 2px rgba(0,0,0,.15)"; chatbotComponent.setAttribute("role", "region"); chatbotComponent.setAttribute("aria-labelledby", "fm-chatbot-title"); var chatbotGrid = document.createElement('div'); chatbotGrid.id = "fm-chatbot-grid"; chatbotGrid.style.display = "grid"; chatbotGrid.style.borderStyle = "none"; // chatbotGrid.style.gridTemplateColumns = dimensions["width"] + "px"; // chatbotGrid.style.gridTemplateRows = "60px " + dimensions["height"] + "px 70px"; chatbotGrid.style.background = "transparent"; var chatbotHeader = document.createElement('div'); chatbotHeader.id = "fm-chatbot-header"; chatbotHeader.style.background = "#3980E8"; chatbotHeader.style.color = "white"; chatbotHeader.style.borderRadius = "4px 4px 0 0"; chatbotHeader.style.padding = "10px"; chatbotHeader.style.display = "grid"; chatbotHeader.style.borderStyle = "none"; chatbotHeader.style.gridTemplateColumns = "90% 10%"; chatbotHeader.style.gridTemplateRows = "auto auto"; // chatbotHeader.style.gridTemplateColumns = "80%"; // chatbotHeader.style.gridTemplateRows = "50% 25% 25%"; var chatbotCloseButton = document.createElement('button'); chatbotCloseButton.id = "fm-chatbot-close-btn"; //chatbotCloseButton.style.visibility = "hidden"; chatbotCloseButton.type = "button"; if (args.hasOwnProperty("closeTooltip") && args.closeTooltip.length > 0) { chatbotCloseButton.title = args.closeTooltip; //Used by Bootstrap chatbotCloseButton.setAttribute("data-toggle", "tooltip"); } chatbotCloseButton.style.border = "none"; chatbotCloseButton.style.color = "white"; chatbotCloseButton.style.background = "transparent"; chatbotCloseButton.style.position = "relative"; //chatbotCloseButton.style.float = "right"; //chatbotCloseButton.style.textAlign = "center"; //chatbotCloseButton.style.verticalAlign = "center"; chatbotCloseButton.style.cursor = "pointer"; //chatbotCloseButton.style.float = "right"; chatbotCloseButton.innerHTML = "<span class=\"material-icons\" style=\"font-size:24px;\">close</span>"; chatbotCloseButton.setAttribute("aria-label", "Chiudi il chatbot"); //chatbotCloseButton.appendChild(chatbotSendButton); var chatbotTitle = document.createElement('h1'); chatbotTitle.id = "fm-chatbot-title"; chatbotTitle.style.margin = "0"; chatbotTitle.style.padding = "0"; chatbotTitle.style.fontSize = "1.1em"; chatbotTitle.style.fontWeight = "bolder"; if (args.hasOwnProperty("title")) { // title + close //chatbotTitle.innerHTML = "<span style='font-size: 1.1em;font-weight: bolder'>" + args["title"] + "</span>" + "<button type='button'><span id=\"fm-chatbot-close-btn\" class=\"material-icons\" style=\"cursor: pointer; float: right;font-size:24px;\">close</span></button>"; chatbotTitle.innerHTML = "<span>" + args.title + "</span>"; } // chatbotTitle.style.fontSize = "1.1em"; // chatbotTitle.style.fontWeight = "bolder"; var chatbotSubtitle = document.createElement('h2'); chatbotSubtitle.id = "fm-chatbot-subtitle"; chatbotSubtitle.style.margin = "0"; chatbotSubtitle.style.padding = "0"; chatbotSubtitle.style.fontSize = "0.8em"; chatbotSubtitle.style.fontWeight = "lighter"; //chatbotSubtitle.innerHTML = "Chiedi su vaccini, tamponi, quarantena&#8230;"; if (args.hasOwnProperty("subtitle")) { //chatbotSubtitle.innerHTML = "Chiedi su vaccini, tamponi, quarantena&#8230;"; chatbotSubtitle.innerHTML = "<span>" + args.subtitle + "</span>"; } //chatbotSubtitle.style.fontStyle = "italic"; chatbotSubtitle.style.fontWeight = "lighter"; chatbotSubtitle.style.fontSize = "0.8em"; //chatbotSubtitle.style.color = "#e8e4c9"; chatbotSubtitle.style.whiteSpace = "nowrap"; chatbotSubtitle.style.overflow = "hidden"; chatbotSubtitle.style.textOverflow = "ellipsis"; // white-space: nowrap; // overflow: hidden; // text-overflow: ellipsis; chatbotHeader.appendChild(chatbotTitle); chatbotHeader.appendChild(chatbotCloseButton); // chatbotHeader.appendChild(chatbotTitle); chatbotHeader.appendChild(chatbotSubtitle); var chatbotMain = document.createElement('div'); chatbotMain.id = "fm-chatbot-main-container"; chatbotMain.className = "fm-chatbot-main"; chatbotMain.style.background = "white"; //chatbotMain.style.color="gray"; chatbotMain.style.overflow = "scroll"; chatbotMain.style.padding = "10px"; chatbotMain.setAttribute("tabindex", "0"); chatbotMain.setAttribute("aria-live", "polite"); var chatbotFooter = document.createElement('div'); chatbotFooter.id = "fm-chatbot-footer"; //chatbotFooter.className = "fm-chatbot-footer"; chatbotFooter.style.background = "#F5F5F5"; chatbotFooter.style.color = "black"; chatbotFooter.style.padding = "10px"; chatbotFooter.style.borderRadius = "0 0 4px 4px"; var chatbotInput = document.createElement('textarea'); chatbotInput.id = "fm-chatbot-input"; //chatbotInput.className = "fm-chatbot-input"; chatbotInput.autocomplete = "off"; //chatbotInput.rows = 2; //chatbotInput.cols = 26; chatbotInput.style.width = "80%"; chatbotInput.style.height = "100%"; if (args.hasOwnProperty("inputTextFieldHint")) { //chatbotInput.placeholder = "Fai una domanda"; chatbotInput.placeholder = args.inputTextFieldHint; } //chatbotInput.textContent = "posso fare il tampone privatamente?"; chatbotInput.style.background = "#F5F5F5"; chatbotInput.style.border = "none"; chatbotInput.style.cursor = "pointer"; chatbotInput.style.color = "black"; chatbotInput.style.fontSize = "0.9em"; chatbotInput.style.fontStyle = "normal"; chatbotInput.style.position = "relative"; chatbotInput.style.float = "left"; chatbotInput.style.textAlign = "left"; chatbotInput.style.verticalAlign = "auto"; chatbotInput.style.resize = "none"; chatbotInput.style.overflow = "hidden"; chatbotInput.style.outline = "none"; chatbotInput.style.fontFamily = DEFAULT_FONT_FAMILY; chatbotInput.setAttribute("aria-label", "Messaggio da inviare"); chatbotFooter.appendChild(chatbotInput); var chatbotSendButton = document.createElement('button'); chatbotSendButton.id = "fm-chatbot-send-btn"; chatbotSendButton.style.visibility = "hidden"; chatbotSendButton.type = "button"; chatbotSendButton.style.border = "none"; chatbotSendButton.style.color = "#3980E8"; chatbotSendButton.style.background = "transparent"; chatbotSendButton.style.position = "relative"; chatbotSendButton.style.float = "right"; chatbotSendButton.style.textAlign = "center"; chatbotSendButton.style.verticalAlign = "center"; chatbotSendButton.style.cursor = "pointer"; chatbotSendButton.innerHTML = "<span class=\"material-icons\" style=\"font-size:24px;\">send</span>"; chatbotSendButton.setAttribute("aria-label", "Invia il messaggio"); chatbotFooter.appendChild(chatbotSendButton); chatbotGrid.appendChild(chatbotHeader); chatbotGrid.appendChild(chatbotMain); chatbotGrid.appendChild(chatbotFooter); chatbotComponent.appendChild(chatbotGrid); //chatbot.appendChild(chatbotContainer); return chatbotComponent; } /** * Creates and returns the chatbot button. * @param args * @returns {HTMLDivElement} */ function addAndGetChatbotButton(args) { console.info("adding chatbot open button...", args); var chatbotSwitchContainer = document.createElement('div'); chatbotSwitchContainer.id = "fm-chatbot-button-container"; //chatbotSwitchContainer.className = "tooltip"; // chatbotSwitchContainer.style.position = "relative"; // chatbotSwitchContainer.style.bottom = "0";//position["bottom"]; // chatbotSwitchContainer.style.right = "0";//position["right"]; //chatbotSwitchContainer.style.fontFamily = "" //chatbotSwitchContainer.style.zIndex = "1"; var chatbotOpenButton = document.createElement('button'); chatbotOpenButton.id = "fm-chatbot-open-btn"; chatbotOpenButton.type = "button"; if (args.hasOwnProperty("tooltip") && args.tooltip.length > 0) { chatbotOpenButton.title = args.tooltip; //Used by Bootstrap chatbotOpenButton.setAttribute("data-toggle", "tooltip"); } chatbotOpenButton.style.border = "none"; chatbotOpenButton.style.color = "white"; chatbotOpenButton.style.background = "#3980E8"; //chatbotOpenButton.style.padding = "10px"; chatbotOpenButton.style.height = "56px"; chatbotOpenButton.style.width = "56px"; chatbotOpenButton.style.borderRadius = "50%"; //chatbotSwitchButton.style.position = "relative"; chatbotOpenButton.style.float = "right"; chatbotOpenButton.style.textAlign = "center"; chatbotOpenButton.style.verticalAlign = "center"; chatbotOpenButton.style.cursor = "pointer"; chatbotOpenButton.style.boxShadow = "0 0 5px 2px rgba(0,0,0,.15)"; chatbotOpenButton.setAttribute("aria-label", "Apri il chatbot"); chatbotOpenButton.innerHTML = "<span id=\"fm-chatbot-open-icon\" class=\"material-icons\" style=\"font-size:36px;\">smart_toy</span>"; // if (args.hasOwnProperty("tooltip") && args.tooltip.length > 0) { // var chatbotOpenBtnTooltip = document.createElement('div'); // chatbotOpenBtnTooltip.className = "tooltiptext1"; // //chatbotOpenBtnTooltip.innerHTML = String.format("<span>{0}</span>", args["tooltip"]); // chatbotOpenBtnTooltip.innerHTML = "<span>" + args.tooltip + "</span>"; // chatbotSwitchContainer.appendChild(chatbotOpenBtnTooltip); // } chatbotSwitchContainer.appendChild(chatbotOpenButton); return chatbotSwitchContainer; } //todo remove // if (!String.format) { // String.format = function (format) { // var args = Array.prototype.slice.call(arguments, 1); // return format.replace(/{(\d+)}/g, function (match, number) { // return typeof args[number] !== 'undefined' ? args[number] : match; // }); // }; // } /** * Shows the chatbot component and hides the chatbot button. * @param args */ function showChatbotComponent(args) { console.info("showing the chatbot component..."); var chatbotContainer = document.getElementById("fm-chatbot-container"); var switchContainer = document.getElementById("fm-chatbot-button-container"); chatbotContainer.style.display = "block"; chatbotContainer.setAttribute("aria-hidden", "false"); switchContainer.style.display = "none"; switchContainer.setAttribute("aria-hidden", "true"); if (args.hasOwnProperty("onWidgetEvent")) { args.onWidgetEvent.onChatOpen(); } } /** * Hides the chatbot component and shows the chatbot button. * @param args */ function hideChatbotComponent(args) { console.info("hiding the chatbot component..."); var chatbotContainer = document.getElementById("fm-chatbot-container"); var switchContainer = document.getElementById("fm-chatbot-button-container"); chatbotContainer.style.display = "none"; chatbotContainer.setAttribute("aria-hidden", "true"); switchContainer.style.display = "block"; switchContainer.setAttribute("aria-hidden", "false"); if (args.hasOwnProperty("onWidgetEvent")) { args.onWidgetEvent.onChatClose(); } } /** * Shows and sends the user message. * @param args */ function submitMessage(args) { var input = document.getElementById("fm-chatbot-input"); console.debug("sending input", input.value); if (input.value) { var message = input.value.trim(); if (message.length > 0) { addUserInput(message); call(message, args); } input.value = ""; } } /** * Adds the user message to the chat thread. * @param value */ function addUserInput(value) { console.debug("showing user input", value); var botMain = document.getElementById("fm-chatbot-main-container"); var div = document.createElement('div'); div.className = "user-input"; div.style.background = "#3980E8"; div.style.color = "white"; div.style.borderRadius = "4px 4px 4px 4px"; div.style.margin = "10px 10px 10px 40px"; div.style.padding = "10px"; div.style.wordWrap = "break-word"; div.style.fontSize = "0.9em"; //div.innerHTML = "<span>" + value + "</span>"; div.innerHTML = "<span class=\"sr-only\">Io dico:</span>" + value; botMain.appendChild(div); botMain.scrollTop = botMain.scrollHeight; } /** * Adds the bot message to the chat thread. * @param value */ function addBotOutput(value) { console.debug("showing bot output", value); var botMain = document.getElementById("fm-chatbot-main-container"); var div = document.createElement('div'); div.style.background = "#F5F5F5"; div.style.color = "black"; div.style.borderRadius = "4px 4px 4px 4px"; div.style.margin = "10px 40px 10px 10px"; div.style.padding = "10px"; div.style.wordWrap = "break-word"; div.style.fontSize = "0.9em"; div.className = "bot-output"; // div.innerHTML = "<span>" + value + "</span>"; div.innerHTML = "<span class=\"sr-only\">Covibot dice:</span>" + value; botMain.appendChild(div); botMain.scrollTop = botMain.scrollHeight; } /** * Generates a uniq session id. */ function IDGenerator() { this.length = 8; this.timestamp = +new Date(); var _getRandomInt = function (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; this.generate = function () { //console.info("getting a new SID..."); var ts = this.timestamp.toString(); var parts = ts.split("").reverse(); var id = "0ES5V111-"; for (var i = 0; i < this.length; ++i) { var index = _getRandomInt(0, parts.length - 1); id += parts[index]; } return id; }; } /** * Calls the Rasa's rest endpoint. * @param value * @param args */ //time curl -s -w "\n" -XPOST https://rasa5007.pokedem.com/webhooks/rest/webhook -H "Content-Type: application/json" -H "Accept-Charset: UTF-8" -d '{"sender": "user_240", "message": "scarica moduli per la prima dose"}'|jq . function call(value, args) { var data = {sender: UID, message: value}; console.debug("calling the chatbot rest endpoint...", data); var delay = (typeof args.customMessageDelay === 'number') ? args.customMessageDelay : 0; // addWaitAnimation(200); //console.debug("url", apiUrl); fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept-Charset': 'UTF-8' }, body: JSON.stringify(data), }) .then(function (response) { return response.json(); }) .then(function (data) { console.debug('chatbot uttered', data); //todo setTimeout(function () { if (data && data.length > 0) { removeWaitAnimation(); for (var i = 0; i < data.length; i++) { var output = replaceMarkdown(data[i].text); console.trace("bot said", i, output); addBotOutput(output); args.onApiEvent.bot_uttered(); } } }, delay); }) .catch(function (error) { console.error('Error:', error); //todo according to the error the bot could be hidden removeWaitAnimation(); if (args.hasOwnProperty("hideWhenServiceNotAvailable") && args.hideWhenServiceNotAvailable) { console.debug("hiding the chatbot components..."); hideChatbotComponent(args); //todo remove the open button? } else { if (args.hasOwnProperty("serviceNotAvailableMessage") && args.serviceNotAvailableMessage.length > 0) { addBotOutput(args.serviceNotAvailableMessage); } } //todo try to connect again? or wait for a refresh? }).finally(function () { console.debug('chatbot call ended'); // removeWaitAnimation(); }); } /** * Starts the waiting state. * @param speed */ function addWaitAnimation(speed) { console.debug("adding wait animation...", speed); speed = (typeof speed !== 'undefined') ? speed : 200; var botMain = document.getElementById("fm-chatbot-main-container"); var div = document.createElement('div'); div.className = "fm-chatbot-wait-animation"; //div.style.verticalAlign= "center"; div.textContent = "Ooo"; // div.style.color = "gray"; // div.style.fontSize = "1.2em"; // div.style.letterSpacing = "0.5em"; // div.style.marginLeft = "10px"; div.style.background = "#F5F5F5"; div.style.color = "black"; div.style.borderRadius = "10px 10px 10px 10px"; div.style.margin = "10px 40px 10px 10px"; div.style.padding = "10px"; div.style.wordWrap = "break-word"; div.style.fontSize = "0.9em"; //div.textContent = "attendi..." //div.innerHTML = "&#9675;&#9679;&#9675;&#9679;"; //div.innerHTML = "&#9711;&#9675;&#9675;" //div.innerHTML = ".&nbsp;.&nbsp;.&nbsp;"; //div.innerHTML = "<span style='vertical-align: center;'>&#9711;&#9675;&#9675;</span>" botMain.appendChild(div); botMain.scrollTop = botMain.scrollHeight; // const element = document.getElementById("id"); var textNode = div.childNodes[0]; // assuming no other children var text = textNode.data; setInterval(function () { text = text[text.length - 1] + text.substring(0, text.length - 1); textNode.data = text; }, speed); } var italicRegex = /\*([^*]+)\*/g; var strongRegex = /\*\*([^*]+)\*\*/g; var aRegex = /\[([^\]]+)]\(([^)]+)\)/g; /** * Replaces markdown with html tags. * Currently, link and font style are supported. * @param input */ function replaceMarkdown(input) { return input.replace(strongRegex, '<strong>$1</strong>').replace(aRegex, '<a href="$2">$1</a>').replace(italicRegex, '<em>$1</em>'); } /** * Stops the waiting status */ function removeWaitAnimation() { console.debug("removing wait animation..."); var waitAnimations = document.getElementsByClassName("fm-chatbot-wait-animation"); for (var i = 0; i < waitAnimations.length; i++) { waitAnimations[i].remove(); } } }