From 769d3ea14ba788b8b201d8bdec7717cd74728a0d Mon Sep 17 00:00:00 2001 From: gneb Date: Thu, 2 Mar 2023 21:47:22 +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 0a34daf..0790ee1 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: e = "" } = {}) { if (this.position = this.getPosition(t), this.open = !1, this.inputText = "", this.appName = e, !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 ("" === e) throw new Error("invalid app name"); this.getChatInitialData(e).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 [e, n] = t.split("-"); return { [e]: "40px", [n]: "40px" } } initialize() { const t = document.createElement("div"); t.style.position = "fixed", t.style.zIndex = "9999", Object.keys(this.position).forEach((e => t.style[e] = this.position[e])), document.body.appendChild(t); const e = document.createElement("div"); e.classList.add(`${nm}-button-container`); const n = document.createElement("span"); n.innerHTML = '\n \n \n ', n.classList.add(`${nm}-icon`), this.chatIcon = n; 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(), e.appendChild(this.chatIcon), e.appendChild(this.closeIcon), e.addEventListener("click", this.toggleOpen.bind(this)), t.appendChild(this.chatContainer), t.appendChild(e), this.chatContent.innerHTML += this.chatStripe(!0, this.welcomeMessage, "") } createStyles() { const t = document.createElement("style"); document.head.appendChild(t), t.innerHTML = `\n .${nm}-clearfix::after {content: "";clear: both;display: table;}.${nm}-icon {cursor: pointer;width: 100%;position: absolute;top: 11px;left: 13px;transition: transform .3s ease;color: white;}.${nm}-hidden {transform: scale(0);}.${nm}-button-container {background: linear-gradient(to bottom right, #4294e3, #8f12fd);width: 70px;height: 70px;border-radius: 50%;}.${nm}-chat-container {box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);right: -25px;bottom: 75px;position: absolute;transition: max-height .2s ease;background-color: white;border-radius: 10px;}.${nm}-chat-container.hidden {max-height: 0px;}.${nm}-scrpt-header {display: inline-block;width: 100%;margin: 0;padding: 10px;color: white;background: linear-gradient(to bottom right, #4294e3, #8f12fd);border-top-left-radius: 10px;border-top-right-radius: 10px;}.${nm}-chat-container form input {padding: 20px;display: inline-block;width: calc(100% - 50px);border: 0px;background-color: #f7f7f7;}.${nm}-chat-container form input:focus {outline: none;}.${nm}-chat-container form button {cursor: pointer;color: #8f12fd;background-color: #f7f7f7;border: 0;border-radius: 4px;padding: 20px 10px;}.${nm}-scrpt-chat-bottom-menu {padding-top: 20px;list-style-type: none;text-align: center;padding-left: 0px;margin-left: 0px;}.${nm}-scrpt-chat-bottom-menu li {display: inline-block;padding-left: 30px;padding-right: 30px;cursor: pointer;}.${nm}-bottom-menu-icon {padding-bottom: 5px;display: inline-block;}.${nm}-chat-content {display: block;width: 100%;padding: 10px;height: 510px;overflow-y: scroll;position: relative;box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);}.${nm}-close-button, .${nm}-fullscreen-button {border: 0px;background-color: white;border-radius: 100%;padding-bottom: 3px;float: right;margin-left: 4px;}.${nm}-msg-box {display: inline-block;width:80%;}.${nm}-msg-box p {padding: 7px;}.${nm}-income {float: left;}.${nm}-outcome {float: right;}.${nm}-bubble-outcome {background-color: gray;color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-left-radius: 10px;}.${nm}-bubble-income {background-color: #f7f7f7;color: #424242;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;}\n ` } createChatContainerContent() { const t = document.createElement("span"); t.classList.add(`${nm}-clearfix`), this.chatContainer.innerHTML = ""; const e = document.createElement("div"); e.classList.add(`${nm}-scrpt-header`); const n = document.createElement("button"); n.innerHTML = '\n \n ', n.classList.add(`${nm}-close-button`), n.addEventListener("click", (() => this.closeChat())), e.appendChild(n), this.fullScreenButton = document.createElement("button"), this.fullScreenButton.innerHTML = '\n \n ', this.fullScreenButton.classList.add(`${nm}-fullscreen-button`), this.fullScreenButton.addEventListener("click", (() => this.fullscreenchat())), e.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 e = document.createElement("li"), n = document.createElement("span"); n.classList.add(`${nm}-bottom-menu-icon`), n.innerHTML = t.icon, e.appendChild(n); let i = document.createElement("br"); e.appendChild(i); let o = document.createElement("span"); o.innerHTML = t.text, e.appendChild(o), a.appendChild(e) })), this.chatContainer.appendChild(e), this.chatContainer.appendChild(i), this.chatContainer.appendChild(t), this.chatContainer.appendChild(a) } async submit(t) { t.preventDefault(); let e = this.generateUniqueId(), n = document.getElementById(`${nm}-text`), i = n.value; if ("" === i.trim()) return; this.chatContent.innerHTML += this.chatStripe(!1, i, ""), n.disabled = !0, n.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, " ", e); const a = document.getElementById(e); 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, e) { let n = 0, i = setInterval((() => { if (n < e.length) t.innerHTML += e.charAt(n), n++, 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, e, n) { return `\n
\n

${e}

\n
\n ` } async getChatInitialData(t) { let e = await this.makeRequest("GET", `${domain}/api/project/${t}/init`), n = JSON.parse(e); this.welcomeMessage = n.data.welcome_message, this.inputText = n.data.input_text } makeRequest(t, e, n = {}) { return new Promise((function (i, o) { let a = new XMLHttpRequest; a.open(t, e), 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(n).length ? a.send(JSON.stringify(n)) : 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: e = "" } = {}) { if (this.position = this.getPosition(t), this.open = !1, this.inputText = "", this.appName = e, !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 ("" === e) throw new Error("invalid app name"); this.getChatInitialData(e).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 [e, n] = t.split("-"); return { [e]: "40px", [n]: "40px" } } initialize() { const t = document.createElement("div"); t.style.position = "fixed", t.style.zIndex = "9999", Object.keys(this.position).forEach((e => t.style[e] = this.position[e])), document.body.appendChild(t); const e = document.createElement("div"); e.classList.add(`${nm}-button-container`); const n = document.createElement("span"); n.innerHTML = '\n \n \n ', n.classList.add(`${nm}-icon`), this.chatIcon = n; 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(), e.appendChild(this.chatIcon), e.appendChild(this.closeIcon), e.addEventListener("click", this.toggleOpen.bind(this)), t.appendChild(this.chatContainer), t.appendChild(e), this.chatContent.innerHTML += this.chatStripe(!0, this.welcomeMessage, "") } createStyles() { const t = document.createElement("style"); document.head.appendChild(t), t.innerHTML = `\n .${nm}-clearfix::after {content: "";clear: both;display: table;}.${nm}-icon {cursor: pointer;width: 100%;position: absolute;top: 11px;left: 13px;transition: transform .3s ease;color: white;}.${nm}-hidden {transform: scale(0);}.${nm}-button-container {background: linear-gradient(to bottom right, #4294e3, #8f12fd);width: 70px;height: 70px;border-radius: 50%;}.${nm}-chat-container {box-shadow: 0 0 18px 8px rgba(0,0,0, 0.1);right: -25px;bottom: 75px;position: absolute;transition: max-height .2s ease;background-color: white;border-radius: 10px;}.${nm}-chat-container.hidden {max-height: 0px;}.${nm}-scrpt-header {display: inline-block;width: 100%;margin: 0;padding: 10px;color: white;background: linear-gradient(to bottom right, #4294e3, #8f12fd);border-top-left-radius: 10px;border-top-right-radius: 10px;}.${nm}-chat-container form input {padding: 20px;display: inline-block;width: calc(100% - 50px);border: 0px;background-color: #f7f7f7;}.${nm}-chat-container form input:focus {outline: none;}.${nm}-chat-container form button {cursor: pointer;color: #8f12fd;background-color: #f7f7f7;border: 0;border-radius: 4px;padding: 20px 10px;}.${nm}-scrpt-chat-bottom-menu {padding-top: 20px;list-style-type: none;text-align: center;padding-left: 0px;margin-left: 0px;}.${nm}-scrpt-chat-bottom-menu li {display: inline-block;padding-left: 30px;padding-right: 30px;cursor: pointer;}.${nm}-bottom-menu-icon {padding-bottom: 5px;display: inline-block;}.${nm}-chat-content {display: block;width: 100%;padding: 10px;height: 510px;overflow-y: scroll;position: relative;box-shadow: 0 4px 2px -2px rgba(0,0,0, 0.1);}.${nm}-close-button, .${nm}-fullscreen-button {border: 0px;background-color: white;border-radius: 100%;padding-bottom: 3px;float: right;margin-left: 4px;}.${nm}-msg-box {display: inline-block;width:80%;}.${nm}-msg-box p {padding: 7px;}.${nm}-income {float: left;}.${nm}-outcome {float: right;}.${nm}-bubble-outcome {background-color: gray;color: white;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-left-radius: 10px;}.${nm}-bubble-income {background-color: #f7f7f7;color: #424242;border-top-left-radius: 10px;border-top-right-radius: 10px;border-bottom-right-radius: 10px;}\n ` } createChatContainerContent() { const t = document.createElement("span"); t.classList.add(`${nm}-clearfix`), this.chatContainer.innerHTML = ""; const e = document.createElement("div"); e.classList.add(`${nm}-scrpt-header`); const n = document.createElement("button"); n.innerHTML = '\n \n ', n.classList.add(`${nm}-close-button`), n.addEventListener("click", (() => this.closeChat())), e.appendChild(n), this.fullScreenButton = document.createElement("button"), this.fullScreenButton.innerHTML = '\n \n ', this.fullScreenButton.classList.add(`${nm}-fullscreen-button`), this.fullScreenButton.addEventListener("click", (() => this.fullscreenchat())), e.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 e = document.createElement("li"), n = document.createElement("span"); n.classList.add(`${nm}-bottom-menu-icon`), n.innerHTML = t.icon, e.appendChild(n); let i = document.createElement("br"); e.appendChild(i); let o = document.createElement("span"); o.innerHTML = t.text, e.appendChild(o), a.appendChild(e) })), this.chatContainer.appendChild(e), this.chatContainer.appendChild(i), this.chatContainer.appendChild(t), this.chatContainer.appendChild(a) } async submit(t) { t.preventDefault(); let e = this.generateUniqueId(), n = document.getElementById(`${nm}-text`), i = n.value; if ("" === i.trim()) return; this.chatContent.innerHTML += this.chatStripe(!1, i, ""), n.disabled = !0, n.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, " ", e); const a = document.getElementById(e); 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, e) { let n = 0, i = setInterval((() => { if (n < e.length) t.innerHTML += e.charAt(n), n++, 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, e, n) { return `\n
\n

${e}

\n
\n ` } async getChatInitialData(t) { let e = await this.makeRequest("GET", `${domain}/api/project/${t}/init`), n = JSON.parse(e); this.welcomeMessage = n.data.welcome_message, this.inputText = n.data.input_text } makeRequest(t, e, n = {}) { return new Promise((function (i, o) { let a = new XMLHttpRequest; a.open(t, e), 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(n).length ? a.send(JSON.stringify(n)) : a.send() })) } } \ No newline at end of file