Advertisement
Guest User

Index.html

a guest
Nov 30th, 2024
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.84 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Modern Chat Widget</title>
  7. <!-- <link rel="stylesheet" href="styles.css"> -->
  8. </head>
  9. <body>
  10. <!-- Chat Container -->
  11. <div id="chat-container">
  12. <div id="chat-header">
  13. <h2>Chat</h2>
  14. <button id="close-chat">✕</button>
  15. </div>
  16. <div id="chat-messages"></div>
  17. <div id="chat-input-container">
  18. <input type="text" id="chat-input" placeholder="Type a message..." />
  19. <button id="send-button">Send</button>
  20. </div>
  21. </div>
  22.  
  23. <!-- Expand Chat Button -->
  24. <button id="expand-chat">
  25. <svg fill="#ffffff" height="24px" width="24px" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
  26. <path d="M30,1.5c-16.542,0-30,12.112-30,27c0,5.205,1.647,10.246,4.768,14.604c-0.591,6.537-2.175,11.39-4.475,13.689
  27. c-0.304,0.304-0.38,0.769-0.188,1.153C0.276,58.289,0.625,58.5,1,58.5c0.046,0,0.093-0.003,0.14-0.01
  28. c0.405-0.057,9.813-1.412,16.617-5.338C21.622,54.711,25.738,55.5,30,55.5c16.542,0,30-12.112,30-27S46.542,1.5,30,1.5z" />
  29. </svg>
  30. </button>
  31.  
  32. <!-- Code Snippet Template -->
  33. <template id="code-snippet-template">
  34. <div class="code-snippet">
  35. <button class="copy-button">Copy</button>
  36. <pre><code></code></pre>
  37. </div>
  38. </template>
  39.  
  40.  
  41. <!-- Header and Bold Template -->
  42. <template id="header-template">
  43. <strong class="header"></strong>
  44. </template>
  45. <template id="bold-black-template">
  46. <span class="bold-black"></span>
  47. </template>
  48.  
  49. <script>
  50. document.addEventListener('DOMContentLoaded', () => {
  51. const chatContainer = document.getElementById('chat-container');
  52. const chatMessages = document.getElementById('chat-messages');
  53. const chatInput = document.getElementById('chat-input');
  54. const chatForm = document.getElementById('chat-form');
  55. const sendButton = document.getElementById('send-button');
  56. const expandChatButton = document.getElementById('expand-chat');
  57. const closeChatButton = document.getElementById('close-chat');
  58. let lastMessage = '';
  59. expandChatButton.addEventListener('click', () => {
  60. chatContainer.classList.add('expanded');
  61. expandChatButton.classList.add('hidden');
  62. });
  63.  
  64. closeChatButton.addEventListener('click', () => {
  65. chatContainer.classList.remove('expanded');
  66. expandChatButton.classList.remove('hidden');
  67. });
  68.  
  69. document.addEventListener('click', (e) => {
  70. if (e.target.classList.contains('copy-button')) {
  71. const codeSnippet = e.target.closest('.code-snippet');
  72. const codeElement = codeSnippet.querySelector('code');
  73.  
  74. if (codeElement) {
  75. const code = codeElement.textContent; // Get the text
  76. navigator.clipboard.writeText(code).then(() => {
  77. alert('Code copied to clipboard!');
  78. }).catch(() => {
  79. alert('Failed to copy code to clipboard.');
  80. });
  81. } else {
  82. console.error('Code element not found!');
  83. }
  84. }
  85. });
  86.  
  87. sendButton.addEventListener('click', async () => {
  88. const message = chatInput.value.trim();
  89. if (message) {
  90. lastMessage = message;
  91. addMessageToChat('user', message);
  92. chatInput.value = '';
  93. addTypingAnimation();
  94.  
  95. const MAX_RETRIES = 3; // Maximum number of retries
  96. let retryCount = 0; // Retry counter
  97. let timeoutReached = false;
  98.  
  99. const showRetryButtons = () => {
  100. removeTypingAnimation();
  101. const messageElement = document.createElement('div');
  102. messageElement.className = 'message bot';
  103. messageElement.innerHTML = `
  104. <p>Čas vypršel. Zkusit znovu nebo smazat chat?</p>
  105. <button id="retry-button">Zkusit znovu</button>
  106. <button id="clear-button">Smazat</button>
  107. `;
  108. chatMessages.appendChild(messageElement);
  109. chatMessages.scrollTop = chatMessages.scrollHeight;
  110.  
  111. document.getElementById('retry-button').addEventListener('click', () => {
  112. messageElement.remove();
  113. retryMessage();
  114. });
  115. document.getElementById('clear-button').addEventListener('click', () => {
  116. chatMessages.innerHTML = '';
  117. });
  118. };
  119.  
  120. const timeoutId = setTimeout(() => {
  121. timeoutReached = true;
  122. showRetryButtons();
  123. }, 20000);
  124.  
  125. const warningTimeoutId = setTimeout(() => {
  126. if (!timeoutReached) {
  127. addMessageToChat('bot', 'Prosím počkejte, generace zprávy zabrala déle než obvykle.');
  128. }
  129. }, 15000);
  130.  
  131. while (retryCount < MAX_RETRIES) {
  132. try {
  133. const response = await fetch('https://aiceskekraje.vercel.app/chat', {
  134. method: 'POST',
  135. headers: { 'Content-Type': 'application/json' },
  136. body: JSON.stringify({ message }),
  137. });
  138.  
  139. if (timeoutReached) return;
  140.  
  141. clearTimeout(timeoutId);
  142. clearTimeout(warningTimeoutId);
  143. removeTypingAnimation();
  144.  
  145. if (response.ok) {
  146. const data = await response.json();
  147. addMessageToChat('bot', data.response);
  148. return; // Exit on success
  149. } else {
  150. console.warn(`Retrying... Attempt ${retryCount + 1}`);
  151. retryCount++;
  152. }
  153. } catch (error) {
  154. console.error(`Error sending message: ${error}`);
  155. retryCount++;
  156. if (retryCount >= MAX_RETRIES) {
  157. removeTypingAnimation();
  158. addMessageToChat(
  159. 'bot',
  160. 'Došlo k chybě při odesílání zprávy. Prosím zkuste to znovu.'
  161. );
  162. }
  163. }
  164. }
  165. }
  166. });
  167.  
  168.  
  169. function addMessageToChat(role, content) {
  170. const messageElement = document.createElement('div');
  171. messageElement.className = `message ${role}`;
  172.  
  173. const parsedContent = parseMessageContent(content);
  174. messageElement.appendChild(parsedContent);
  175.  
  176. chatMessages.appendChild(messageElement);
  177. chatMessages.scrollTop = chatMessages.scrollHeight;
  178. }
  179.  
  180.  
  181.  
  182.  
  183. function parseMessageContent(content) {
  184. const messageFragment = document.createDocumentFragment();
  185.  
  186. // Regex patterns
  187. const codePattern = /```([\s\S]*?)```/g; // Matches ```...```
  188. const headerPattern = /##(.+?)##/g; // Matches ###...###
  189. const boldPattern = /\*\*(.+?)\*\*/g; // Matches ***...***
  190.  
  191. let lastIndex = 0;
  192.  
  193. // Replace code blocks
  194. let match;
  195. while ((match = codePattern.exec(content)) !== null) {
  196. // Append preceding text
  197. if (lastIndex < match.index) {
  198. const text = content.substring(lastIndex, match.index);
  199. messageFragment.appendChild(document.createTextNode(text));
  200. }
  201.  
  202. // Create a code snippet
  203. const codeSnippet = document.getElementById('code-snippet-template').content.cloneNode(true);
  204. codeSnippet.querySelector('code').textContent = match[1]; // Add code content
  205. messageFragment.appendChild(codeSnippet);
  206.  
  207. // Attach copy functionality to the new snippet
  208. // setTimeout(() => attachCopyFunctionality(), 0); // Ensure DOM updates before attaching
  209.  
  210. lastIndex = codePattern.lastIndex;
  211. }
  212.  
  213. // Append remaining content after code blocks
  214. if (lastIndex < content.length) {
  215. content = content.substring(lastIndex);
  216.  
  217. // Replace headers
  218. content = content.replace(headerPattern, (_, headerText) => {
  219. const headerElement = document.getElementById('header-template').content.cloneNode(true);
  220. headerElement.querySelector('.header').textContent = headerText.trim();
  221. messageFragment.appendChild(headerElement);
  222. return '';
  223. });
  224.  
  225. // Replace bold-black text
  226. content = content.replace(boldPattern, (_, boldText) => {
  227. const boldElement = document.getElementById('bold-black-template').content.cloneNode(true);
  228. boldElement.querySelector('.bold-black').textContent = boldText.trim();
  229. messageFragment.appendChild(boldElement);
  230. return '';
  231. });
  232.  
  233. // Add any remaining plain text
  234. if (content.trim()) {
  235. messageFragment.appendChild(document.createTextNode(content));
  236. }
  237. }
  238.  
  239. return messageFragment;
  240. }
  241.  
  242. function delay(ms) {
  243. return new Promise(resolve => setTimeout(resolve, ms));
  244. }
  245.  
  246. async function addTypingAnimation() {
  247. const typingElement = document.createElement('div');
  248. typingElement.className = 'message bot typing';
  249. chatMessages.appendChild(typingElement);
  250. chatMessages.scrollTop = chatMessages.scrollHeight;
  251.  
  252. let keepTyping = true;
  253.  
  254. const animateTyping = async () => {
  255. while (keepTyping) {
  256. typingElement.textContent = '.';
  257. await delay(500);
  258. typingElement.textContent = '..';
  259. await delay(500);
  260. typingElement.textContent = '...';
  261. await delay(500);
  262. }
  263. };
  264.  
  265. animateTyping();
  266.  
  267. typingElement.cleanup = () => {
  268. keepTyping = false;
  269. typingElement.remove();
  270. };
  271. }
  272.  
  273. function removeTypingAnimation() {
  274. const typingElement = chatMessages.querySelector('.typing');
  275. if (typingElement && typeof typingElement.cleanup === 'function') {
  276. typingElement.cleanup();
  277. }
  278. }
  279.  
  280. function retryMessage() {
  281. chatInput.value = lastMessage;
  282. sendButton.click();
  283. }
  284. });
  285. </script>
  286.  
  287. <style>
  288. body {
  289. font-family: 'Arial', sans-serif;
  290. background-color: #f9f9f9;
  291. margin: 0;
  292. padding: 0;
  293. }
  294.  
  295. .code-snippet {
  296. position: relative;
  297. border: 1px solid #ddd;
  298. background-color: #f8f8f8;
  299. border-radius: 5px;
  300. margin: 10px 0;
  301. padding: 10px;
  302. overflow: hidden;
  303. }
  304.  
  305. #close-chat {
  306. position: absolute;
  307. top: 10px;
  308. right: 10px;
  309. background-color: #ffffff;
  310. color: rgb(0, 0, 0);
  311. border: none;
  312. border-radius: 3px;
  313. padding: 5px 10px;
  314. font-size: 12px;
  315. cursor: pointer;
  316. z-index: 10;
  317. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  318. }
  319.  
  320. .code-snippet pre {
  321. margin: 0;
  322. padding: 10px;
  323. overflow-x: auto;
  324. background: transparent;
  325. }
  326.  
  327. .copy-button {
  328. position: absolute;
  329. top: 10px;
  330. right: 10px;
  331. background-color: #007bff;
  332. color: white;
  333. border: none;
  334. border-radius: 3px;
  335. padding: 5px 10px;
  336. font-size: 12px;
  337. cursor: pointer;
  338. z-index: 10;
  339. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  340. }
  341.  
  342. .copy-button:hover {
  343. background-color: #0056b3;
  344. }
  345.  
  346.  
  347. #chat-container {
  348. position: fixed;
  349. bottom: 20px;
  350. right: 20px;
  351. width: 350px;
  352. height: 500px;
  353. background-color: #ffffff;
  354. border-radius: 10px;
  355. box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
  356. display: none;
  357. flex-direction: column;
  358. overflow: hidden;
  359. transition: all 0.3s ease;
  360. z-index: 1000;
  361. }
  362.  
  363. #chat-container.expanded {
  364. display: flex;
  365. }
  366.  
  367. #chat-header {
  368. background-color: #007bff;
  369. color: white;
  370. padding: 15px;
  371. display: flex;
  372. justify-content: space-between;
  373. align-items: center;
  374. font-size: 16px;
  375. }
  376.  
  377. #chat-messages {
  378. flex: 1;
  379. padding: 10px;
  380. overflow-y: auto;
  381. background-color: #f7f7f7;
  382. }
  383.  
  384. .message {
  385. margin-bottom: 10px;
  386. padding: 10px;
  387. border-radius: 15px;
  388. max-width: 70%;
  389. word-wrap: break-word;
  390. }
  391.  
  392. .message.user {
  393. background-color: #007bff;
  394. color: white;
  395. align-self: flex-end;
  396. }
  397.  
  398. .message.bot {
  399. background-color: #e5e5ea;
  400. color: black;
  401. align-self: flex-start;
  402. }
  403.  
  404. #chat-input-container {
  405. display: flex;
  406. padding: 10px;
  407. border-top: 1px solid #ddd;
  408. background-color: #ffffff;
  409. }
  410.  
  411. #chat-input {
  412. flex-grow: 1;
  413. padding: 10px;
  414. border: 1px solid #ccc;
  415. border-radius: 5px;
  416. font-size: 14px;
  417. }
  418.  
  419. #send-button {
  420. margin-left: 10px;
  421. padding: 10px 15px;
  422. background-color: #007bff;
  423. color: white;
  424. border: none;
  425. border-radius: 5px;
  426. font-size: 14px;
  427. cursor: pointer;
  428. }
  429.  
  430. #expand-chat {
  431. position: fixed;
  432. bottom: 20px;
  433. right: 20px;
  434. width: 60px;
  435. height: 60px;
  436. background-color: #007bff;
  437. color: white;
  438. border: none;
  439. border-radius: 50%;
  440. box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  441. display: flex;
  442. justify-content: center;
  443. align-items: center;
  444. cursor: pointer;
  445. z-index: 1000;
  446. }
  447.  
  448. #expand-chat svg {
  449. width: 24px;
  450. height: 24px;
  451. fill: white;
  452. }
  453.  
  454. .hidden {
  455. display: none;
  456. }
  457.  
  458. #expand-chat.hidden {
  459. display: none !important;
  460. }
  461.  
  462.  
  463. .message.bot.typing {
  464. font-style: italic;
  465. color: gray;
  466. }
  467.  
  468. </style>
  469. </body>
  470. </html>
  471.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement