diff --git a/web/public/embed.js b/web/public/embed.js
index 0111ce8c31a2c9..8f13a7178c055a 100644
--- a/web/public/embed.js
+++ b/web/public/embed.js
@@ -14,17 +14,18 @@
const config = window[configKey];
// SVG icons for open and close states
- const svgIcons = {
- open: `
+ `;
// Main function to embed the chatbot
async function embedChatbot() {
+ let isDragging = false
+
if (!config || !config.token) {
console.error(`${configKey} is empty or token is not provided`);
return;
@@ -33,7 +34,9 @@
async function compressAndEncodeBase64(input) {
const uint8Array = new TextEncoder().encode(input);
const compressedStream = new Response(
- new Blob([uint8Array]).stream().pipeThrough(new CompressionStream('gzip'))
+ new Blob([uint8Array])
+ .stream()
+ .pipeThrough(new CompressionStream("gzip"))
).arrayBuffer();
const compressedUint8Array = new Uint8Array(await compressedStream);
return btoa(String.fromCharCode(...compressedUint8Array));
@@ -112,33 +115,30 @@
// Function to reset the iframe position
function resetIframePosition() {
- if (window.innerWidth <= 640)
- return
+ if (window.innerWidth <= 640) return;
const targetIframe = document.getElementById(iframeId);
const targetButton = document.getElementById(buttonId);
if (targetIframe && targetButton) {
const buttonRect = targetButton.getBoundingClientRect();
- const buttonInBottom = buttonRect.top - 5 > targetIframe.clientHeight
+ const buttonInBottom = buttonRect.top - 5 > targetIframe.clientHeight;
if (buttonInBottom) {
- targetIframe.style.bottom = '0px';
- targetIframe.style.top = 'unset';
- }
- else {
- targetIframe.style.bottom = 'unset';
- targetIframe.style.top = '0px';
+ targetIframe.style.bottom = "0px";
+ targetIframe.style.top = "unset";
+ } else {
+ targetIframe.style.bottom = "unset";
+ targetIframe.style.top = "0px";
}
const buttonInRight = buttonRect.right > targetIframe.clientWidth;
if (buttonInRight) {
- targetIframe.style.right = '0';
- targetIframe.style.left = 'unset';
- }
- else {
- targetIframe.style.right = 'unset';
+ targetIframe.style.right = "0";
+ targetIframe.style.left = "unset";
+ } else {
+ targetIframe.style.right = "unset";
targetIframe.style.left = 0;
}
}
@@ -193,33 +193,41 @@
const displayDiv = document.createElement("div");
displayDiv.style.cssText =
"position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; z-index: 2147483647;";
- displayDiv.innerHTML = svgIcons.open;
+ displayDiv.innerHTML = svgIcons;
containerDiv.appendChild(displayDiv);
document.body.appendChild(containerDiv);
// Add click event listener to toggle chatbot
- containerDiv.addEventListener("click", function () {
+ containerDiv.addEventListener("click", handleClick);
+ // Add touch event listener
+ containerDiv.addEventListener("touchend", handleClick);
+
+ function handleClick() {
+ if (isDragging) return;
+
const targetIframe = document.getElementById(iframeId);
if (!targetIframe) {
- containerDiv.prepend(createIframe());
+ containerDiv.appendChild(createIframe());
resetIframePosition();
this.title = "Exit (ESC)";
- displayDiv.innerHTML = svgIcons.close;
- document.addEventListener('keydown', handleEscKey);
+ setSvgIcon("close");
+ document.addEventListener("keydown", handleEscKey);
return;
}
- targetIframe.style.display = targetIframe.style.display === "none" ? "block" : "none";
- displayDiv.innerHTML = targetIframe.style.display === "none" ? svgIcons.open : svgIcons.close;
+ targetIframe.style.display =
+ targetIframe.style.display === "none" ? "block" : "none";
+ targetIframe.style.display === "none"
+ ? setSvgIcon("open")
+ : setSvgIcon("close");
if (targetIframe.style.display === "none") {
- document.removeEventListener('keydown', handleEscKey);
+ document.removeEventListener("keydown", handleEscKey);
} else {
- document.addEventListener('keydown', handleEscKey);
+ document.addEventListener("keydown", handleEscKey);
}
-
resetIframePosition();
- });
+ }
// Enable dragging if specified in config
if (config.draggable) {
@@ -229,20 +237,39 @@
// Function to enable dragging of the chat button
function enableDragging(element, axis) {
- let isDragging = false;
- let startX, startY;
+ let startX, startY, startClientX, startClientY;
element.addEventListener("mousedown", startDragging);
- document.addEventListener("mousemove", drag);
- document.addEventListener("mouseup", stopDragging);
+ element.addEventListener("touchstart", startDragging);
function startDragging(e) {
- isDragging = true;
- startX = e.clientX - element.offsetLeft;
- startY = e.clientY - element.offsetTop;
+ isDragging = false;
+ if (e.type === "touchstart") {
+ startX = e.touches[0].clientX - element.offsetLeft;
+ startY = e.touches[0].clientY - element.offsetTop;
+ startClientX = e.touches[0].clientX;
+ startClientY = e.touches[0].clientY;
+ } else {
+ startX = e.clientX - element.offsetLeft;
+ startY = e.clientY - element.offsetTop;
+ }
+ document.addEventListener("mousemove", drag);
+ document.addEventListener("touchmove", drag, { passive: false });
+ document.addEventListener("mouseup", stopDragging);
+ document.addEventListener("touchend", stopDragging);
+ e.preventDefault();
}
function drag(e) {
+ const touch = e.type === "touchmove" ? e.touches[0] : e;
+ const deltaX = touch.clientX - startClientX;
+ const deltaY = touch.clientY - startClientY;
+
+ // Determine whether it is a drag operation
+ if (Math.abs(deltaX) > 8 || Math.abs(deltaY) > 8) {
+ isDragging = true;
+ }
+
if (!isDragging) return;
element.style.transition = "none";
@@ -252,11 +279,17 @@
const targetIframe = document.getElementById(iframeId);
if (targetIframe) {
targetIframe.style.display = "none";
- element.querySelector("div").innerHTML = svgIcons.open;
+ setSvgIcon("open");
}
- const newLeft = e.clientX - startX;
- const newBottom = window.innerHeight - e.clientY - startY;
+ let newLeft, newBottom;
+ if (e.type === "touchmove") {
+ newLeft = e.touches[0].clientX - startX;
+ newBottom = window.innerHeight - e.touches[0].clientY - startY;
+ } else {
+ newLeft = e.clientX - startX;
+ newBottom = window.innerHeight - e.clientY - startY;
+ }
const elementRect = element.getBoundingClientRect();
const maxX = window.innerWidth - elementRect.width;
@@ -279,9 +312,16 @@
}
function stopDragging() {
- isDragging = false;
+ setTimeout(() => {
+ isDragging = false;
+ }, 0);
element.style.transition = "";
element.style.cursor = "pointer";
+
+ document.removeEventListener("mousemove", drag);
+ document.removeEventListener("touchmove", drag);
+ document.removeEventListener("mouseup", stopDragging);
+ document.removeEventListener("touchend", stopDragging);
}
}
@@ -291,18 +331,27 @@
}
}
+ function setSvgIcon(type = "open") {
+ if (type === "open") {
+ document.getElementById("openIcon").style.display = "block";
+ document.getElementById("closeIcon").style.display = "none";
+ } else {
+ document.getElementById("openIcon").style.display = "none";
+ document.getElementById("closeIcon").style.display = "block";
+ }
+ }
+
// Add esc Exit keyboard event triggered
function handleEscKey(event) {
- if (event.key === 'Escape') {
+ if (event.key === "Escape") {
const targetIframe = document.getElementById(iframeId);
- const button = document.getElementById(buttonId);
- if (targetIframe && targetIframe.style.display !== 'none') {
- targetIframe.style.display = 'none';
- button.querySelector('div').innerHTML = svgIcons.open;
+ if (targetIframe && targetIframe.style.display !== "none") {
+ targetIframe.style.display = "none";
+ setSvgIcon("open");
}
}
}
- document.addEventListener('keydown', handleEscKey);
+ document.addEventListener("keydown", handleEscKey);
// Set the embedChatbot function to run when the body is loaded,Avoid infinite nesting
if (config?.dynamicScript) {
@@ -310,4 +359,4 @@
} else {
document.body.onload = embedChatbot;
}
-})();
\ No newline at end of file
+})();
diff --git a/web/public/embed.min.js b/web/public/embed.min.js
index 728f74bfd7dd69..13837183c0e1cc 100644
--- a/web/public/embed.min.js
+++ b/web/public/embed.min.js
@@ -1,8 +1,4 @@
-(()=>{let t="difyChatbotConfig",a="dify-chatbot-bubble-button",c="dify-chatbot-bubble-window",p=window[t],u={open:`
-
- `,close:`
-
- `};async function e(){if(p&&p.token){var e=new URLSearchParams({...await(async()=>{var e=p?.inputs||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n[e]=await o(t)})),n})(),...await(async()=>{var e=p?.systemVariables||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n["sys."+e]=await o(t)})),n})()});let t=`${p.baseUrl||`https://${p.isDev?"dev.":""}udify.app`}/chatbot/${p.token}?`+e;e=i();async function o(e){e=(new TextEncoder).encode(e),e=new Response(new Blob([e]).stream().pipeThrough(new CompressionStream("gzip"))).arrayBuffer(),e=new Uint8Array(await e);return btoa(String.fromCharCode(...e))}function i(){var e=document.createElement("iframe");return e.allow="fullscreen;microphone",e.title="dify chatbot bubble window",e.id=c,e.src=t,e.style.cssText=`
+(()=>{let t="difyChatbotConfig",m="dify-chatbot-bubble-button",h="dify-chatbot-bubble-window",p=window[t];async function e(){let u=!1;if(p&&p.token){var e=new URLSearchParams({...await(async()=>{var e=p?.inputs||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n[e]=await o(t)})),n})(),...await(async()=>{var e=p?.systemVariables||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n["sys."+e]=await o(t)})),n})()});let t=`${p.baseUrl||`https://${p.isDev?"dev.":""}udify.app`}/chatbot/${p.token}?`+e;e=s();async function o(e){e=(new TextEncoder).encode(e),e=new Response(new Blob([e]).stream().pipeThrough(new CompressionStream("gzip"))).arrayBuffer(),e=new Uint8Array(await e);return btoa(String.fromCharCode(...e))}function s(){var e=document.createElement("iframe");return e.allow="fullscreen;microphone",e.title="dify chatbot bubble window",e.id=h,e.src=t,e.style.cssText=`
position: absolute;
display: flex;
flex-direction: column;
@@ -18,7 +14,7 @@
z-index: 2147483640;
overflow: hidden;
user-select: none;
- `,e}function r(){var e,t;window.innerWidth<=640||(e=document.getElementById(c),t=document.getElementById(a),e&&t&&((t=t.getBoundingClientRect()).top-5>e.clientHeight?(e.style.bottom="0px",e.style.top="unset"):(e.style.bottom="unset",e.style.top="0px"),t.right>e.clientWidth?(e.style.right="0",e.style.left="unset"):(e.style.right="unset",e.style.left=0)))}function n(){let n=document.createElement("div");Object.entries(p.containerProps||{}).forEach(([e,t])=>{"className"===e?n.classList.add(...t.split(" ")):"style"===e?"object"==typeof t?Object.assign(n.style,t):n.style.cssText=t:"function"==typeof t?n.addEventListener(e.replace(/^on/,"").toLowerCase(),t):n[e]=t}),n.id=a;var e=document.createElement("style");document.head.appendChild(e),e.sheet.insertRule(`
+ `,e}function d(){var e,t;window.innerWidth<=640||(e=document.getElementById(h),t=document.getElementById(m),e&&t&&((t=t.getBoundingClientRect()).top-5>e.clientHeight?(e.style.bottom="0px",e.style.top="unset"):(e.style.bottom="unset",e.style.top="0px"),t.right>e.clientWidth?(e.style.right="0",e.style.left="unset"):(e.style.right="unset",e.style.left=0)))}function n(){let n=document.createElement("div");Object.entries(p.containerProps||{}).forEach(([e,t])=>{"className"===e?n.classList.add(...t.split(" ")):"style"===e?"object"==typeof t?Object.assign(n.style,t):n.style.cssText=t:"function"==typeof t?n.addEventListener(e.replace(/^on/,"").toLowerCase(),t):n[e]=t}),n.id=m;var e=document.createElement("style"),e=(document.head.appendChild(e),e.sheet.insertRule(`
#${n.id} {
position: fixed;
bottom: var(--${n.id}-bottom, 1rem);
@@ -33,4 +29,10 @@
cursor: pointer;
z-index: 2147483647;
}
- `);let t=document.createElement("div");if(t.style.cssText="position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; z-index: 2147483647;",t.innerHTML=u.open,n.appendChild(t),document.body.appendChild(n),n.addEventListener("click",function(){var e=document.getElementById(c);e?(e.style.display="none"===e.style.display?"block":"none",t.innerHTML="none"===e.style.display?u.open:u.close,"none"===e.style.display?document.removeEventListener("keydown",d):document.addEventListener("keydown",d),r()):(n.prepend(i()),r(),this.title="Exit (ESC)",t.innerHTML=u.close,document.addEventListener("keydown",d))}),p.draggable){var s=n;var l=p.dragAxis||"both";let i=!1,r,d;s.addEventListener("mousedown",function(e){i=!0,r=e.clientX-s.offsetLeft,d=e.clientY-s.offsetTop}),document.addEventListener("mousemove",function(e){var t,n,o;i&&(s.style.transition="none",s.style.cursor="grabbing",(t=document.getElementById(c))&&(t.style.display="none",s.querySelector("div").innerHTML=u.open),t=e.clientX-r,e=window.innerHeight-e.clientY-d,o=s.getBoundingClientRect(),n=window.innerWidth-o.width,o=window.innerHeight-o.height,"x"!==l&&"both"!==l||s.style.setProperty(`--${a}-left`,Math.max(0,Math.min(t,n))+"px"),"y"!==l&&"both"!==l||s.style.setProperty(`--${a}-bottom`,Math.max(0,Math.min(e,o))+"px"))}),document.addEventListener("mouseup",function(){i=!1,s.style.transition="",s.style.cursor="pointer"})}}e.style.display="none",document.body.appendChild(e),2048
+
+
+
+
+
+ `,n.appendChild(e),document.body.appendChild(n),n.addEventListener("click",t),n.addEventListener("touchend",t),p.draggable){var r=n;var a=p.dragAxis||"both";let s,d,t,l;function o(e){u=!1,"touchstart"===e.type?(s=e.touches[0].clientX-r.offsetLeft,d=e.touches[0].clientY-r.offsetTop,t=e.touches[0].clientX,l=e.touches[0].clientY):(s=e.clientX-r.offsetLeft,d=e.clientY-r.offsetTop),document.addEventListener("mousemove",i),document.addEventListener("touchmove",i,{passive:!1}),document.addEventListener("mouseup",c),document.addEventListener("touchend",c),e.preventDefault()}function i(n){var o="touchmove"===n.type?n.touches[0]:n,i=o.clientX-t,o=o.clientY-l;if(u=8{u=!1},0),r.style.transition="",r.style.cursor="pointer",document.removeEventListener("mousemove",i),document.removeEventListener("touchmove",i),document.removeEventListener("mouseup",c),document.removeEventListener("touchend",c)}r.addEventListener("mousedown",o),r.addEventListener("touchstart",o)}}e.style.display="none",document.body.appendChild(e),2048