From b541d816e4b1c919c6c3fe6f6bf036874a48350c Mon Sep 17 00:00:00 2001 From: gneb Date: Thu, 2 Mar 2023 21:38:02 +0400 Subject: [PATCH] ver 4 --- src/scrpt.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scrpt.min.js b/src/scrpt.min.js index 6838033..88906ec 100644 --- a/src/scrpt.min.js +++ b/src/scrpt.min.js @@ -1 +1 @@ -const xPositions = ["left", "right"], yPositions = ["top", "bottom"], nm = "scrpt", chatWidth = "400px", domain = "http://http://164.90.239.9/:8000"; class Scrpt { loadInterval; constructor({ position: t = "bottom-right", appName: n = "" } = {}) { if (this.position = this.getPosition(t), this.open = !1, this.inputText = "", this.appName = n, !t.includes("-")) throw new Error("position must include - symbol. for example bottom-right"); if (!yPositions.includes(t.split("-")[0])) throw new Error("y position must be top or bottom"); if (!xPositions.includes(t.split("-")[1])) throw new Error("x position must be left or right"); if ("" === n) throw new Error("invalid app name"); this.getChatInitialData(n).then((t => { this.initialize() })), this.createStyles() } detectMob() { return [/Android/i, /webOS/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i].some((t => navigator.userAgent.match(t))) } getPosition(t) { const [n, e] = t.split("-"); return { [n]: "40px", [e]: "40px" } } initialize() { const t = document.createElement("div"); t.style.position = "fixed", t.style.zIndex = "9999", Object.keys(this.position).forEach((n => t.style[n] = this.position[n])), document.body.appendChild(t); const n = document.createElement("div"); n.classList.add(`${nm}-button-container`); const e = document.createElement("span"); e.innerHTML = '\n \n \n ', e.classList.add(`${nm}-icon`), this.chatIcon = e; const i = document.createElement("span"); i.innerHTML = '\n \n ', i.classList.add(`${nm}-icon`, `${nm}-hidden`), this.closeIcon = i, this.chatContainer = document.createElement("div"), this.chatContainer.classList.add(`${nm}-hidden`, `${nm}-chat-container`), this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 5 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "0px" : "75px", this.createChatContainerContent(), n.appendChild(this.chatIcon), n.appendChild(this.closeIcon), n.addEventListener("click", this.toggleOpen.bind(this)), t.appendChild(this.chatContainer), t.appendChild(n), this.chatContent.innerHTML += this.chatStripe(!0, this.welcomeMessage, "") } createStyles() { const t = document.createElement("style"); document.head.appendChild(t), t.innerHTML = `\n .${nm}-clearfix::after {\n content: "";\n clear: both;\n display: table;\n }\n\n .${nm}-icon {\n cursor: pointer;\n width: 100%;\n position: absolute;\n top: 11px;\n left: 13px;\n transition: transform .3s ease; \n color: white;\n }\n .${nm}-hidden {\n transform: scale(0);\n }\n .${nm}-button-container {\n background: linear-gradient(to bottom right, #4294e3, #8f12fd);\n width: 70px;\n height: 70px;\n border-radius: 50%;\n }\n\n .${nm}-chat-container {\n box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);\n right: -25px;\n bottom: 75px;\n position: absolute;\n transition: max-height .2s ease;\n background-color: white;\n border-radius: 10px;\n }\n\n .${nm}-chat-container.hidden {\n max-height: 0px;\n }\n\n .${nm}-scrpt-header {\n display: inline-block;\n width: 100%;\n margin: 0;\n padding: 10px;\n color: white;\n background: linear-gradient(to bottom right, #4294e3, #8f12fd);\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n }\n\n .${nm}-chat-container form input {\n padding: 20px;\n display: inline-block;\n width: calc(100% - 50px);\n border: 0px;\n background-color: #f7f7f7;\n }\n .${nm}-chat-container form input:focus {\n outline: none;\n }\n\n .${nm}-chat-container form button {\n cursor: pointer;\n color: #8f12fd;\n background-color: #f7f7f7;\n border: 0;\n border-radius: 4px;\n padding: 20px 10px;\n }\n .${nm}-scrpt-chat-bottom-menu {\n padding-top: 20px;\n list-style-type: none;\n text-align: center;\n padding-left: 0px;\n margin-left: 0px;\n }\n .${nm}-scrpt-chat-bottom-menu li {\n display: inline-block;\n padding-left: 30px;\n padding-right: 30px;\n cursor: pointer;\n }\n .${nm}-bottom-menu-icon {\n padding-bottom: 5px;\n display: inline-block;\n }\n .${nm}-chat-content {\n display: block;\n width: 100%;\n padding: 10px;\n height: 510px;\n overflow-y: scroll;\n position: relative;\n box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);\n }\n\n .${nm}-close-button, .${nm}-fullscreen-button {\n border: 0px;\n background-color: white;\n border-radius: 100%;\n padding-bottom: 3px;\n float: right;\n margin-left: 4px;\n }\n .${nm}-msg-box {\n display: inline-block;\n width:80%;\n }\n .${nm}-msg-box p {\n padding: 7px;\n }\n .${nm}-income {\n float: left;\n }\n .${nm}-outcome {\n float: right;\n }\n .${nm}-bubble-outcome {\n background-color: gray;\n color: white;\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n border-bottom-left-radius: 10px;\n }\n .${nm}-bubble-income {\n background-color: #f7f7f7;\n color: #424242;\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n border-bottom-right-radius: 10px;\n }\n ` } createChatContainerContent() { const t = document.createElement("span"); t.classList.add(`${nm}-clearfix`), this.chatContainer.innerHTML = ""; const n = document.createElement("div"); n.classList.add(`${nm}-scrpt-header`); const e = document.createElement("button"); e.innerHTML = '\n \n ', e.classList.add(`${nm}-close-button`), e.addEventListener("click", (() => this.closeChat())), n.appendChild(e), this.fullScreenButton = document.createElement("button"), this.fullScreenButton.innerHTML = '\n \n ', this.fullScreenButton.classList.add(`${nm}-fullscreen-button`), this.fullScreenButton.addEventListener("click", (() => this.fullscreenchat())), n.appendChild(this.fullScreenButton); const i = document.createElement("form"); i.classList.add(`${nm}-content`); const o = document.createElement("input"); o.requered = !0, o.id = `${nm}-text`, o.type = "text", o.placeholder = this.inputText, this.btn = document.createElement("button"), this.btn.innerHTML = '\n \n ', this.chatContent = document.createElement("div"), this.chatContent.classList.add(`${nm}-chat-content`), i.appendChild(this.chatContent), i.appendChild(t), i.appendChild(o), i.appendChild(this.btn), i.addEventListener("submit", this.submit.bind(this)); const a = document.createElement("ul"); a.classList.add(`${nm}-scrpt-chat-bottom-menu`);[{ icon: '\n \n \n ', text: "Home", click: function () { alert(this.text) } }, { icon: '\n \n \n \n ', text: "Chat", click: function () { alert(this.text) } }, { icon: '\n \n \n \n ', text: "Help", click: function () { alert(this.text) } }].forEach((t => { let n = document.createElement("li"), e = document.createElement("span"); e.classList.add(`${nm}-bottom-menu-icon`), e.innerHTML = t.icon, n.appendChild(e); let i = document.createElement("br"); n.appendChild(i); let o = document.createElement("span"); o.innerHTML = t.text, n.appendChild(o), a.appendChild(n) })), this.chatContainer.appendChild(n), this.chatContainer.appendChild(i), this.chatContainer.appendChild(t), this.chatContainer.appendChild(a) } async submit(t) { t.preventDefault(); let n = this.generateUniqueId(), e = document.getElementById(`${nm}-text`), i = e.value; if ("" === i.trim()) return; this.chatContent.innerHTML += this.chatStripe(!1, i, ""), e.disabled = !0, e.value = "", this.btn.disabled = !0; let o = await this.makeRequest("POST", `${domain}/answer?name=${this.appName}`, { question: i }); o = JSON.parse(o), this.chatContent.innerHTML += this.chatStripe(!0, " ", n); const a = document.getElementById(n); this.typeText(a, o.answer) } toggleOpen() { this.open = !this.open, this.open ? this.openChat() : this.closeChat() } fullscreenchat() { "400px" === this.chatContainer.style.width ? (this.chatContainer.style.width = window.innerWidth - 30 + "px", this.chatContainer.style.height = window.innerHeight - 125 + "px") : (this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 17 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "0px" : "75px", this.chatContainer.style.height = "auto") } closeChat() { this.open = !1, this.chatIcon.classList.remove(`${nm}-hidden`), this.closeIcon.classList.add(`${nm}-hidden`), this.chatContainer.classList.add(`${nm}-hidden`) } openChat() { this.chatIcon.classList.add(`${nm}-hidden`), this.closeIcon.classList.remove(`${nm}-hidden`), this.chatContainer.classList.remove(`${nm}-hidden`) } typeText(t, n) { let e = 0, i = setInterval((() => { if (e < n.length) t.innerHTML += n.charAt(e), e++, this.chatContent.scrollTop = this.chatContent.scrollHeight; else { clearInterval(i), document.getElementById(`${nm}-text`).disabled = !1, this.btn.disabled = !1 } }), 20) } uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (t => (t ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> t / 4).toString(16))) } generateUniqueId() { return this.uuidv4() } chatStripe(t, n, e) { return `\n
\n

${n}

\n
\n ` } async getChatInitialData(t) { let n = await this.makeRequest("GET", `${domain}/api/project/${t}/init`), e = JSON.parse(n); this.welcomeMessage = e.data.welcome_message, this.inputText = e.data.input_text } makeRequest(t, n, e = {}) { return new Promise((function (i, o) { let a = new XMLHttpRequest; a.open(t, n), a.setRequestHeader("Content-type", "application/json"), a.onload = function () { this.status >= 200 && this.status < 300 ? i(a.response) : o({ status: this.status, statusText: a.statusText }) }, a.onerror = function () { o({ status: this.status, statusText: a.statusText }) }, 0 !== Object.keys(e).length ? a.send(JSON.stringify(e)) : a.send() })) } } \ No newline at end of file +const xPositions = ["left", "right"], yPositions = ["top", "bottom"], nm = "scrpt", chatWidth = "400px", domain = "http://164.90.239.9/:8000"; class Scrpt { loadInterval; constructor({ position: t = "bottom-right", appName: n = "" } = {}) { if (this.position = this.getPosition(t), this.open = !1, this.inputText = "", this.appName = n, !t.includes("-")) throw new Error("position must include - symbol. for example bottom-right"); if (!yPositions.includes(t.split("-")[0])) throw new Error("y position must be top or bottom"); if (!xPositions.includes(t.split("-")[1])) throw new Error("x position must be left or right"); if ("" === n) throw new Error("invalid app name"); this.getChatInitialData(n).then((t => { this.initialize() })), this.createStyles() } detectMob() { return [/Android/i, /webOS/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i].some((t => navigator.userAgent.match(t))) } getPosition(t) { const [n, e] = t.split("-"); return { [n]: "40px", [e]: "40px" } } initialize() { const t = document.createElement("div"); t.style.position = "fixed", t.style.zIndex = "9999", Object.keys(this.position).forEach((n => t.style[n] = this.position[n])), document.body.appendChild(t); const n = document.createElement("div"); n.classList.add(`${nm}-button-container`); const e = document.createElement("span"); e.innerHTML = '\n \n \n ', e.classList.add(`${nm}-icon`), this.chatIcon = e; const i = document.createElement("span"); i.innerHTML = '\n \n ', i.classList.add(`${nm}-icon`, `${nm}-hidden`), this.closeIcon = i, this.chatContainer = document.createElement("div"), this.chatContainer.classList.add(`${nm}-hidden`, `${nm}-chat-container`), this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 5 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "0px" : "75px", this.createChatContainerContent(), n.appendChild(this.chatIcon), n.appendChild(this.closeIcon), n.addEventListener("click", this.toggleOpen.bind(this)), t.appendChild(this.chatContainer), t.appendChild(n), this.chatContent.innerHTML += this.chatStripe(!0, this.welcomeMessage, "") } createStyles() { const t = document.createElement("style"); document.head.appendChild(t), t.innerHTML = `\n .${nm}-clearfix::after {\n content: "";\n clear: both;\n display: table;\n }\n\n .${nm}-icon {\n cursor: pointer;\n width: 100%;\n position: absolute;\n top: 11px;\n left: 13px;\n transition: transform .3s ease; \n color: white;\n }\n .${nm}-hidden {\n transform: scale(0);\n }\n .${nm}-button-container {\n background: linear-gradient(to bottom right, #4294e3, #8f12fd);\n width: 70px;\n height: 70px;\n border-radius: 50%;\n }\n\n .${nm}-chat-container {\n box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);\n right: -25px;\n bottom: 75px;\n position: absolute;\n transition: max-height .2s ease;\n background-color: white;\n border-radius: 10px;\n }\n\n .${nm}-chat-container.hidden {\n max-height: 0px;\n }\n\n .${nm}-scrpt-header {\n display: inline-block;\n width: 100%;\n margin: 0;\n padding: 10px;\n color: white;\n background: linear-gradient(to bottom right, #4294e3, #8f12fd);\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n }\n\n .${nm}-chat-container form input {\n padding: 20px;\n display: inline-block;\n width: calc(100% - 50px);\n border: 0px;\n background-color: #f7f7f7;\n }\n .${nm}-chat-container form input:focus {\n outline: none;\n }\n\n .${nm}-chat-container form button {\n cursor: pointer;\n color: #8f12fd;\n background-color: #f7f7f7;\n border: 0;\n border-radius: 4px;\n padding: 20px 10px;\n }\n .${nm}-scrpt-chat-bottom-menu {\n padding-top: 20px;\n list-style-type: none;\n text-align: center;\n padding-left: 0px;\n margin-left: 0px;\n }\n .${nm}-scrpt-chat-bottom-menu li {\n display: inline-block;\n padding-left: 30px;\n padding-right: 30px;\n cursor: pointer;\n }\n .${nm}-bottom-menu-icon {\n padding-bottom: 5px;\n display: inline-block;\n }\n .${nm}-chat-content {\n display: block;\n width: 100%;\n padding: 10px;\n height: 510px;\n overflow-y: scroll;\n position: relative;\n box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);\n }\n\n .${nm}-close-button, .${nm}-fullscreen-button {\n border: 0px;\n background-color: white;\n border-radius: 100%;\n padding-bottom: 3px;\n float: right;\n margin-left: 4px;\n }\n .${nm}-msg-box {\n display: inline-block;\n width:80%;\n }\n .${nm}-msg-box p {\n padding: 7px;\n }\n .${nm}-income {\n float: left;\n }\n .${nm}-outcome {\n float: right;\n }\n .${nm}-bubble-outcome {\n background-color: gray;\n color: white;\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n border-bottom-left-radius: 10px;\n }\n .${nm}-bubble-income {\n background-color: #f7f7f7;\n color: #424242;\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n border-bottom-right-radius: 10px;\n }\n ` } createChatContainerContent() { const t = document.createElement("span"); t.classList.add(`${nm}-clearfix`), this.chatContainer.innerHTML = ""; const n = document.createElement("div"); n.classList.add(`${nm}-scrpt-header`); const e = document.createElement("button"); e.innerHTML = '\n \n ', e.classList.add(`${nm}-close-button`), e.addEventListener("click", (() => this.closeChat())), n.appendChild(e), this.fullScreenButton = document.createElement("button"), this.fullScreenButton.innerHTML = '\n \n ', this.fullScreenButton.classList.add(`${nm}-fullscreen-button`), this.fullScreenButton.addEventListener("click", (() => this.fullscreenchat())), n.appendChild(this.fullScreenButton); const i = document.createElement("form"); i.classList.add(`${nm}-content`); const o = document.createElement("input"); o.requered = !0, o.id = `${nm}-text`, o.type = "text", o.placeholder = this.inputText, this.btn = document.createElement("button"), this.btn.innerHTML = '\n \n ', this.chatContent = document.createElement("div"), this.chatContent.classList.add(`${nm}-chat-content`), i.appendChild(this.chatContent), i.appendChild(t), i.appendChild(o), i.appendChild(this.btn), i.addEventListener("submit", this.submit.bind(this)); const a = document.createElement("ul"); a.classList.add(`${nm}-scrpt-chat-bottom-menu`);[{ icon: '\n \n \n ', text: "Home", click: function () { alert(this.text) } }, { icon: '\n \n \n \n ', text: "Chat", click: function () { alert(this.text) } }, { icon: '\n \n \n \n ', text: "Help", click: function () { alert(this.text) } }].forEach((t => { let n = document.createElement("li"), e = document.createElement("span"); e.classList.add(`${nm}-bottom-menu-icon`), e.innerHTML = t.icon, n.appendChild(e); let i = document.createElement("br"); n.appendChild(i); let o = document.createElement("span"); o.innerHTML = t.text, n.appendChild(o), a.appendChild(n) })), this.chatContainer.appendChild(n), this.chatContainer.appendChild(i), this.chatContainer.appendChild(t), this.chatContainer.appendChild(a) } async submit(t) { t.preventDefault(); let n = this.generateUniqueId(), e = document.getElementById(`${nm}-text`), i = e.value; if ("" === i.trim()) return; this.chatContent.innerHTML += this.chatStripe(!1, i, ""), e.disabled = !0, e.value = "", this.btn.disabled = !0; let o = await this.makeRequest("POST", `${domain}/answer?name=${this.appName}`, { question: i }); o = JSON.parse(o), this.chatContent.innerHTML += this.chatStripe(!0, " ", n); const a = document.getElementById(n); this.typeText(a, o.answer) } toggleOpen() { this.open = !this.open, this.open ? this.openChat() : this.closeChat() } fullscreenchat() { "400px" === this.chatContainer.style.width ? (this.chatContainer.style.width = window.innerWidth - 30 + "px", this.chatContainer.style.height = window.innerHeight - 125 + "px") : (this.chatContainer.style.width = this.detectMob() ? window.innerWidth - 17 + "px" : "400px", this.chatContainer.style.bottom = this.detectMob() ? "0px" : "75px", this.chatContainer.style.height = "auto") } closeChat() { this.open = !1, this.chatIcon.classList.remove(`${nm}-hidden`), this.closeIcon.classList.add(`${nm}-hidden`), this.chatContainer.classList.add(`${nm}-hidden`) } openChat() { this.chatIcon.classList.add(`${nm}-hidden`), this.closeIcon.classList.remove(`${nm}-hidden`), this.chatContainer.classList.remove(`${nm}-hidden`) } typeText(t, n) { let e = 0, i = setInterval((() => { if (e < n.length) t.innerHTML += n.charAt(e), e++, this.chatContent.scrollTop = this.chatContent.scrollHeight; else { clearInterval(i), document.getElementById(`${nm}-text`).disabled = !1, this.btn.disabled = !1 } }), 20) } uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (t => (t ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> t / 4).toString(16))) } generateUniqueId() { return this.uuidv4() } chatStripe(t, n, e) { return `\n
\n

${n}

\n
\n ` } async getChatInitialData(t) { let n = await this.makeRequest("GET", `${domain}/api/project/${t}/init`), e = JSON.parse(n); this.welcomeMessage = e.data.welcome_message, this.inputText = e.data.input_text } makeRequest(t, n, e = {}) { return new Promise((function (i, o) { let a = new XMLHttpRequest; a.open(t, n), a.setRequestHeader("Content-type", "application/json"), a.onload = function () { this.status >= 200 && this.status < 300 ? i(a.response) : o({ status: this.status, statusText: a.statusText }) }, a.onerror = function () { o({ status: this.status, statusText: a.statusText }) }, 0 !== Object.keys(e).length ? a.send(JSON.stringify(e)) : a.send() })) } } \ No newline at end of file