PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 1.5.4
MxChat – AI Chatbot & Content Generation for WordPress v1.5.4
3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 2.0.3 2.0.4 2.0.5 2.0.6 All 152 releases
← All changes | js/chat-script.js +169 -588 2.0.41.5.4 View file →
@@ -1,8 +1,8 @@
1 1 jQuery(document).ready(function($) {
2 2 //console.log('mxchatChat object:', mxchatChat);
3 3 //console.log('Link Target Toggle Value:', mxchatChat.link_target_toggle);
4 -// Add these variables at the top of your chat-script.js file
4 +
5 5 const toolbarIconColor = mxchatChat.toolbar_icon_color || '#212121';
6 6
7 7 // Initialize color settings
8 8 var userMessageBgColor = mxchatChat.user_message_bg_color;
@@ -14,11 +14,9 @@
14 14 var liveAgentMessageFontColor = mxchatChat.live_agent_message_font_color;
15 15
16 16
17 17 var linkTarget = mxchatChat.link_target_toggle === 'on' ? '_blank' : '_self';
18 - let lastSeenMessageId = '';
19 - let notificationCheckInterval;
20 - let notificationBadge;
18 + var lastSeenMessageId = '';
21 19 // Initialize session ID
22 20 var sessionId = getChatSession();
23 21
24 22 let pollingInterval; // Variable to store the interval ID
@@ -25,110 +23,12 @@
25 23 let processedMessageIds = new Set(); // Add this at the top with your other variables
26 24 //console.log('Live Agent BG Color:', liveAgentMessageBgColor);
27 25 //console.log('Live Agent Font Color:', liveAgentMessageFontColor);
28 26 let activePdfFile = null;
29 - let activeWordFile = null;
30 27
31 28
32 -// Function to create and append notification badge
33 -// Function to create and append notification badge
34 -function createNotificationBadge() {
35 - console.log("Creating notification badge...");
36 - const chatButton = document.getElementById('floating-chatbot-button');
37 - console.log("Chat button found:", !!chatButton);
38 -
39 - if (!chatButton) return;
40 29
41 - // Remove any existing badge first
42 - const existingBadge = chatButton.querySelector('.chat-notification-badge');
43 - if (existingBadge) {
44 - console.log("Removing existing badge");
45 - existingBadge.remove();
46 - }
47 30
48 - notificationBadge = document.createElement('div');
49 - notificationBadge.className = 'chat-notification-badge';
50 - notificationBadge.style.cssText = `
51 - display: none;
52 - position: absolute;
53 - top: -5px;
54 - right: -5px;
55 - background-color: red;
56 - color: white;
57 - border-radius: 50%;
58 - padding: 4px 8px;
59 - font-size: 12px;
60 - font-weight: bold;
61 - z-index: 10001;
62 - `;
63 - chatButton.style.position = 'relative';
64 - chatButton.appendChild(notificationBadge);
65 -
66 - console.log("Notification badge created and appended:", {
67 - exists: !!notificationBadge,
68 - parent: notificationBadge?.parentNode?.id,
69 - display: notificationBadge?.style?.display
70 - });
71 -}
72 -
73 -// Function to check for new messages
74 -function checkForNewMessages() {
75 - const sessionId = getChatSession();
76 - const chatPersistenceEnabled = mxchatChat.chat_persistence_toggle === 'on';
77 -
78 - if (!chatPersistenceEnabled) return;
79 -
80 - $.ajax({
81 - url: mxchatChat.ajax_url,
82 - type: 'POST',
83 - data: {
84 - action: 'mxchat_check_new_messages',
85 - session_id: sessionId,
86 - last_seen_id: lastSeenMessageId,
87 - nonce: mxchatChat.nonce
88 - },
89 - success: function(response) {
90 - if (response.success && response.data.hasNewMessages) {
91 - showNotification();
92 - }
93 - }
94 - });
95 -}
96 -
97 -// Function to show notification
98 -function showNotification() {
99 - const badge = document.getElementById('chat-notification-badge');
100 - if (badge && $('#floating-chatbot').hasClass('hidden')) {
101 - badge.style.display = 'block';
102 - badge.textContent = '1';
103 - }
104 -}
105 -
106 -function hideNotification() {
107 - const badge = document.getElementById('chat-notification-badge');
108 - if (badge) {
109 - badge.style.display = 'none';
110 - }
111 -}
112 -// Function to start notification checking
113 -function startNotificationChecking() {
114 - const chatPersistenceEnabled = mxchatChat.chat_persistence_toggle === 'on';
115 - if (!chatPersistenceEnabled) return;
116 -
117 - createNotificationBadge();
118 - notificationCheckInterval = setInterval(checkForNewMessages, 30000); // Check every 30 seconds
119 -}
120 -
121 -// Function to stop notification checking
122 -function stopNotificationChecking() {
123 - if (notificationCheckInterval) {
124 - clearInterval(notificationCheckInterval);
125 - }
126 -}
127 -
128 -
129 -
130 -
131 31 function getChatSession() {
132 32 var sessionId = getCookie('mxchat_session_id');
133 33 //console.log("Session ID retrieved from cookie: ", sessionId);
134 34
@@ -256,35 +156,24 @@
256 156 sendMessageToChatbot(question);
257 157 });
258 158
259 159
260 -// Add this new function to handle markdown headers
261 -function formatMarkdownHeaders(text) {
262 - // Handle h1 to h6 headers
263 - return text.replace(/^(#{1,6})\s(.+)$/gm, function(match, hashes, content) {
264 - const level = hashes.length;
265 - return `<h${level} class="chat-heading">${content}</h${level}>`;
266 - });
267 -}
268 -
269 -// Update the linkify function to handle both URLs and markdown
160 +// Use the linkTarget in your linkify function
270 161 function linkify(inputText) {
271 - // First process markdown headers
272 - let processedText = formatMarkdownHeaders(inputText);
273 -
274 - // Then process links as before
162 + // Check for already linked URLs and skip them
163 + // We use negative lookaheads to skip anything already in an <a> tag
275 164 var markdownLinkPattern = /\[([^\]]+)\]\((https?:\/\/[^\s]+)\)/g;
276 - processedText = processedText.replace(markdownLinkPattern, '<a href="$2" target="' + linkTarget + '">$1</a>');
165 + var replacedText = inputText.replace(markdownLinkPattern, '<a href="$2" target="' + linkTarget + '">$1</a>');
277 166
278 167 // Replace standalone URLs not already in an <a> tag
279 168 var urlPattern = /(^|[^">])(https?:\/\/[^\s<]+)/gim;
280 - processedText = processedText.replace(urlPattern, '$1<a href="$2" target="' + linkTarget + '">$2</a>');
169 + replacedText = replacedText.replace(urlPattern, '$1<a href="$2" target="' + linkTarget + '">$2</a>');
281 170
282 171 // Replace "www." prefixed URLs not already in an <a> tag
283 172 var wwwPattern = /(^|[^">])(www\.[\S]+(\b|$))(?![^<]*<\/a>)/gim;
284 - processedText = processedText.replace(wwwPattern, '$1<a href="http://$2" target="' + linkTarget + '">$2</a>');
173 + replacedText = replacedText.replace(wwwPattern, '$1<a href="http://$2" target="' + linkTarget + '">$2</a>');
285 174
286 - return processedText;
175 + return replacedText;
287 176 }
288 177
289 178
290 179 function scrollElementToTop(element) {
@@ -331,17 +220,19 @@
331 220 return text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
332 221 }
333 222
334 223 // Function to convert newline characters to HTML line breaks and handle paragraph spacing
335 -function convertNewlinesToBreaks(text) {
336 - // Split the text into paragraphs (marked by double newlines or multiple <br> tags)
337 - const paragraphs = text.split(/(?:\n\n|\<br\>\s*\<br\>)/g);
338 -
339 - // Wrap each paragraph in <p> tags
340 - return paragraphs
341 - .map(para => `<p>${para.trim()}</p>`)
342 - .join('');
343 -}
224 + function convertNewlinesToBreaks(text) {
225 + var lines = text.split('\n');
226 + var formattedText = '';
227 +
228 + for (var i = 0; i < lines.length; i++) {
229 + formattedText += lines[i] + '<br>';
230 + }
231 +
232 + return formattedText;
233 + }
234 +
344 235 // Copy to clipboard function
345 236 // Function to copy text to clipboard
346 237 function copyToClipboard(text) {
347 238 var tempInput = $('<input>');
@@ -366,8 +257,10 @@
366 257 }
367 258 }
368 259
369 260 function callMxChat(message, callback) {
261 + //console.log("Sending message to chatbot:", message);
262 +
370 263 $.ajax({
371 264 url: mxchatChat.ajax_url,
372 265 type: 'POST',
373 266 dataType: 'json',
@@ -377,26 +270,37 @@
377 270 session_id: getChatSession(),
378 271 nonce: mxchatChat.nonce
379 272 },
380 273 success: function(response) {
381 - // Existing chat mode check
274 + //console.log("callMxChat response:", response);
275 +
276 + // Check for chat_mode in the response
382 277 if (response.chat_mode) {
383 278 updateChatModeIndicator(response.chat_mode);
384 279 }
280 + // Also check in fallbackResponse if exists
385 281 else if (response.fallbackResponse && response.fallbackResponse.chat_mode) {
386 282 updateChatModeIndicator(response.fallbackResponse.chat_mode);
387 283 }
388 -
389 - // Add PDF filename handling
390 - if (response.data && response.data.filename) {
391 - showActivePdf(response.data.filename);
392 - activePdfFile = response.data.filename;
284 +
285 + // Add redirect check here
286 + if (response.redirect_url) {
287 + // Show the message first
288 + let responseText = response.text || '';
289 + if (responseText) {
290 + replaceLastMessage("bot", responseText);
291 + }
292 + // Then redirect after a short delay
293 + setTimeout(() => {
294 + window.location.href = response.redirect_url;
295 + }, 1500);
296 + return; // Exit early since we're redirecting
393 297 }
394 298
395 -
396 299 // Check for live agent response
397 300 if (response.success && response.data && response.data.status === 'waiting_for_agent') {
398 301 updateChatModeIndicator('agent');
302 + // Do not replace the thinking dots; just wait for the agent's actual response
399 303 return;
400 304 }
401 305
402 306 // Handle other responses
@@ -403,33 +307,31 @@
403 307 let responseText = response.text || '';
404 308 let responseHtml = response.html || '';
405 309 let responseMessage = response.message || '';
406 310
311 + // Check for mode change in text response
407 312 if (responseText === 'You are now chatting with the AI chatbot.') {
408 313 updateChatModeIndicator('ai');
409 314 }
410 315
411 - // Handle the message and show notification if chat is hidden
412 - if (responseText || responseHtml || responseMessage) {
413 - // Update the messages as before
414 - if (responseText && responseHtml) {
415 - replaceLastMessage("bot", responseText, responseHtml);
416 - } else if (responseText) {
417 - replaceLastMessage("bot", responseText);
418 - } else if (responseHtml) {
419 - replaceLastMessage("bot", "", responseHtml);
420 - } else if (responseMessage) {
421 - replaceLastMessage("bot", responseMessage);
422 - }
423 -
424 - // Check if chat is hidden and show notification
425 - if ($('#floating-chatbot').hasClass('hidden')) {
426 - const badge = $('#chat-notification-badge');
427 - if (badge.length) {
428 - badge.show();
429 - }
430 - }
431 - } else {
316 + // For product card or chatbot responses with HTML
317 + if (responseText && responseHtml) {
318 + replaceLastMessage("bot", responseText, responseHtml);
319 + }
320 + // For regular chatbot responses with just text
321 + else if (responseText) {
322 + replaceLastMessage("bot", responseText);
323 + }
324 + // For responses with only HTML (like product cards)
325 + else if (responseHtml) {
326 + replaceLastMessage("bot", "", responseHtml);
327 + }
328 + // For legacy message format
329 + else if (responseMessage) {
330 + replaceLastMessage("bot", responseMessage);
331 + }
332 + // Fallback error case
333 + else {
432 334 console.error("Unexpected response format:", response);
433 335 replaceLastMessage("bot", "I'm sorry, something went wrong.");
434 336 }
435 337
@@ -437,8 +339,9 @@
437 339 lastSeenMessageId = response.message_id;
438 340 }
439 341 },
440 342 error: function(xhr, status, error) {
343 + //console.log("Error communicating with the server:", xhr.status, error);
441 344 replaceLastMessage("bot", "An unexpected error occurred.");
442 345 }
443 346 });
444 347 }
@@ -463,20 +366,15 @@
463 366 bgColor = botMessageBgColor;
464 367 fontColor = botMessageFontColor;
465 368 }
466 369
467 - const messageDiv = $('<div>')
468 - .addClass(messageClass)
469 - .css({
470 - 'background': bgColor,
471 - 'color': fontColor,
472 - });
370 + const messageDiv = $('<div>')
371 + .addClass(messageClass)
372 + .css({
373 + 'background': bgColor,
374 + 'color': fontColor,
375 + });
473 376
474 - // Add CSS for paragraphs
475 - messageDiv.css({
476 - 'margin-bottom': '1em'
477 - });
478 -
479 377 // Format and process the message content
480 378 let fullMessage = linkify(formatBoldText(convertNewlinesToBreaks(formatCodeBlocks(messageText))));
481 379
482 380 // Add images if provided
@@ -516,12 +414,12 @@
516 414 }
517 415 }
518 416 });
519 417
418 + // Update the last seen message ID if applicable
520 419 if (messageText.id) {
521 - lastSeenMessageId = messageText.id;
522 - hideNotification();
523 - }
420 + lastSeenMessageId = messageText.id;
421 + }
524 422 } catch (error) {
525 423 console.error("Error rendering message with images:", error);
526 424 }
527 425 }
@@ -573,20 +471,9 @@
573 471 'background-color': bgColor,
574 472 'color': fontColor,
575 473 })
576 474 .removeClass('temporary-message')
577 - .fadeIn(200, function() {
578 - if (sender === "bot" || sender === "agent") {
579 - const lastUserMessage = $('#chat-box').find('.user-message').last();
580 - if (lastUserMessage.length) {
581 - scrollElementToTop(lastUserMessage);
582 - }
583 - // Show notification if chat is hidden
584 - if ($('#floating-chatbot').hasClass('hidden')) {
585 - showNotification();
586 - }
587 - }
588 - });
475 + .fadeIn(200);
589 476 });
590 477 } else {
591 478 appendMessage(sender, responseText, responseHtml, images);
592 479 }
@@ -592,8 +479,9 @@
592 479 }
593 480 }
594 481
595 482
483 +
596 484 function startPolling() {
597 485 // Clear any existing interval first
598 486 stopPolling();
599 487 // Start new polling interval
@@ -609,11 +497,11 @@
609 497 }
610 498 }
611 499
612 500
613 -// Update your checkForAgentMessages function
614 501 function checkForAgentMessages() {
615 502 const sessionId = getChatSession();
503 +
616 504 $.ajax({
617 505 url: mxchatChat.ajax_url,
618 506 type: 'POST',
619 507 dataType: 'json',
@@ -623,24 +511,17 @@
623 511 last_seen_id: lastSeenMessageId,
624 512 nonce: mxchatChat.nonce
625 513 },
626 514 success: function (response) {
515 + //console.log("Agent messages polling response:", response);
627 516 if (response.success && response.data?.new_messages) {
628 - let hasNewMessage = false;
629 -
630 517 response.data.new_messages.forEach(function (message) {
631 518 if (message.role === "agent" && !processedMessageIds.has(message.id)) {
632 - hasNewMessage = true;
633 519 replaceLastMessage("agent", message.content);
634 520 lastSeenMessageId = message.id;
635 521 processedMessageIds.add(message.id);
636 522 }
637 523 });
638 -
639 - if (hasNewMessage && $('#floating-chatbot').hasClass('hidden')) {
640 - showNotification();
641 - }
642 -
643 524 scrollToBottom(true);
644 525 }
645 526 },
646 527 error: function (xhr, status, error) {
@@ -767,37 +648,29 @@
767 648 return textArea.value;
768 649 }
769 650
770 651
771 -// Update formatCodeBlocks function
772 652 function formatCodeBlocks(text) {
773 - // First handle raw PHP tags
774 - text = text.replace(/(<\?php[\s\S]*?\?>)/g, (match) => {
775 - return `<pre><code class="language-php">${escapeHtml(match)}</code></pre>`;
776 - });
653 + // Ensure the input is a string; otherwise, convert or return empty
654 + if (typeof text !== 'string') {
655 + console.error("formatCodeBlocks: Input is not a string:", text);
656 + return typeof text === 'object' && text.text ? text.text : ""; // Use .text if available, else empty
657 + }
777 658
778 - // Then handle code blocks with backticks
779 - text = text.replace(/```php5?\n([\s\S]+?)```/gi, (match, code) => {
780 - return `<pre><code class="language-php">${escapeHtml(code)}</code></pre>`;
659 + const codeBlockPattern = /```(\w+)?\n?([\s\S]+?)```/g;
660 +
661 + return text.replace(codeBlockPattern, (_, language, codeContent) => {
662 + language = language || 'plaintext';
663 +
664 + return `
665 + <div class="mxchat-code-block-container">
666 + <button class="mxchat-copy-button" aria-label="Copy to clipboard">Copy</button>
667 + <pre class="mxchat-code-block"><code class="mxchat-language-${language}">${escapeHtml(codeContent)}</code></pre>
668 + </div>`;
781 669 });
670 +}
782 671
783 - return text;
784 -}
785 672
786 -// Update escapeHtml function to preserve existing code blocks
787 -function escapeHtml(unsafe) {
788 - // First check if it's already a code block
789 - if (unsafe.includes('<pre><code') || unsafe.includes('</code></pre>')) {
790 - return unsafe;
791 - }
792 -
793 - return unsafe
794 - .replace(/&/g, "&amp;")
795 - .replace(/</g, "&lt;")
796 - .replace(/>/g, "&gt;")
797 - .replace(/"/g, "&quot;")
798 - .replace(/'/g, "&#039;");
799 -}
800 673 // Utility function to escape HTML
801 674 function escapeHtml(unsafe) {
802 675 return unsafe
803 676 .replace(/&/g, "&amp;")
@@ -811,18 +684,20 @@
811 684
812 685
813 686 // Function to convert newlines, skipping preformatted text
814 687 function convertNewlinesToBreaks(text) {
815 - // Split while preserving code blocks
816 - return text.split(/(<pre\b[^>]*>[\s\S]*?<\/pre>)/g).map(part => {
817 - if (part.startsWith('<pre')) return part;
818 - return part.replace(/(^|[^>])\n/g, '$1<br>');
819 - }).join('');
688 + // Regex to exclude <pre> and <code> tags from adding <br> tags
689 + return text.replace(/(^|[^>])\n/g, '$1<br>');
820 690 }
821 691
822 692
823 693
694 +$(document).ready(function() {
695 + loadChatHistory();
696 +});
824 697
698 +
699 +
825 700 // Helper function to check if a string is an image HTML
826 701 function isImageHtml(str) {
827 702 return str.startsWith('<img') && str.endsWith('>');
828 703 }
@@ -848,8 +723,20 @@
848 723 $('body').css('overflow', '');
849 724 }
850 725 }
851 726
727 + // Function to show the chatbot widget (moved outside the Complianz logic)
728 + function showChatWidget() {
729 + setTimeout(function() {
730 + $('#floating-chatbot-button').css('display', 'flex').fadeTo(500, 1);
731 + }, 250);
732 + }
733 +
734 + // Function to hide the chatbot widget
735 + function hideChatWidget() {
736 + $('#floating-chatbot-button').css('display', 'none');
737 + }
738 +
852 739 // Pre-chat dismissal check function (wrapped in a function for reuse)
853 740 function checkPreChatDismissal() {
854 741 $.ajax({
855 742 url: mxchatChat.ajax_url,
@@ -869,93 +756,9 @@
869 756 console.error('Failed to check pre-chat message dismissal status.');
870 757 }
871 758 });
872 759 }
873 -
874 - // Function to show the chatbot widget
875 -function showChatWidget() {
876 - // First ensure display is set
877 - $('#floating-chatbot-button').css('display', 'flex');
878 - // Then handle the fade
879 - $('#floating-chatbot-button').fadeTo(500, 1);
880 - // Force visibility
881 - $('#floating-chatbot-button').removeClass('hidden');
882 - //console.log('Showing widget');
883 -}
884 760
885 -// Function to hide the chatbot widget
886 -function hideChatWidget() {
887 - $('#floating-chatbot-button').css('display', 'none');
888 - $('#floating-chatbot-button').addClass('hidden');
889 - //console.log('Hiding widget');
890 -}
891 -
892 -function initializeChatVisibility() {
893 - //console.log('Initializing chat visibility');
894 - const complianzEnabled = mxchatChat.complianz_toggle === 'on' ||
895 - mxchatChat.complianz_toggle === '1' ||
896 - mxchatChat.complianz_toggle === 1;
897 -
898 - if (complianzEnabled && typeof cmplz_has_consent === "function" && typeof complianz !== 'undefined') {
899 - // Initial check
900 - checkConsentAndShowChat();
901 -
902 - // Listen for consent changes
903 - $(document).on('cmplz_status_change', function(event) {
904 - //console.log('Status change detected');
905 - checkConsentAndShowChat();
906 - });
907 - } else {
908 - // If Complianz is not enabled, always show
909 - $('#floating-chatbot-button')
910 - .css('display', 'flex')
911 - .removeClass('hidden no-consent')
912 - .fadeTo(500, 1);
913 -
914 - // Also check pre-chat message when Complianz is not enabled
915 - checkPreChatDismissal();
916 - }
917 -}
918 -
919 -
920 -
921 -function checkConsentAndShowChat() {
922 - var consentStatus = cmplz_has_consent('marketing');
923 - var consentType = complianz.consenttype;
924 -
925 - //console.log('Checking consent:', {status: consentStatus,type: consentType});
926 -
927 - let $widget = $('#floating-chatbot-button');
928 - let $chatbot = $('#floating-chatbot');
929 - let $preChat = $('#pre-chat-message');
930 -
931 - if (consentStatus === true) {
932 - //console.log('Consent granted - showing widget');
933 - $widget
934 - .removeClass('no-consent')
935 - .css('display', 'flex')
936 - .removeClass('hidden')
937 - .fadeTo(500, 1);
938 - $chatbot.removeClass('no-consent');
939 -
940 - // Show pre-chat message if not dismissed
941 - checkPreChatDismissal();
942 - } else {
943 - //console.log('No consent - hiding widget');
944 - $widget
945 - .addClass('no-consent')
946 - .fadeTo(500, 0, function() {
947 - $(this)
948 - .css('display', 'none')
949 - .addClass('hidden');
950 - });
951 - $chatbot.addClass('no-consent');
952 -
953 - // Hide pre-chat message when no consent
954 - $preChat.hide();
955 - }
956 -}
957 -
958 761 // Function to dismiss pre-chat message for 24 hours
959 762 function handlePreChatDismissal() {
960 763 $('#pre-chat-message').fadeOut(200);
961 764 $.ajax({
@@ -979,8 +782,47 @@
979 782 e.stopPropagation();
980 783 handlePreChatDismissal();
981 784 });
982 785
786 + // Function for Complianz logic
787 + var applyComplianzLogic = mxchatChat.complianz_toggle;
788 + if (applyComplianzLogic) {
789 + function checkConsentAndShowChat() {
790 + var consentStatus = typeof cmplz_has_consent === "function" && cmplz_has_consent('marketing');
791 + var consentType = typeof complianz !== 'undefined' ? complianz.consenttype : null;
792 +
793 + // Show the chatbot by default
794 + showChatWidget();
795 +
796 + if (consentType === 'optin' && !consentStatus) {
797 + // For opt-in, hide only if user explicitly denies consent
798 + hideChatWidget();
799 + } else if (consentType === 'optout' && consentStatus === false) {
800 + // For opt-out, hide only if user explicitly denies consent
801 + hideChatWidget();
802 + } else {
803 + // Keep showing the chatbot
804 + showChatWidget();
805 + }
806 +
807 + checkPreChatDismissal(); // Ensure we check dismissal after consent is handled
808 + }
809 +
810 + // Initial check when the page loads
811 + checkConsentAndShowChat();
812 +
813 + // Listen for changes in consent status
814 + $(document).on('cmplz_status_change', function(event, category) {
815 + if (category === 'marketing') {
816 + checkConsentAndShowChat();
817 + }
818 + });
819 + } else {
820 + // If Complianz is not toggled on, always show the chatbot
821 + showChatWidget();
822 + checkPreChatDismissal(); // Always check pre-chat dismissal when consent logic is not applied
823 + }
824 +
983 825 // Toggle chatbot visibility on floating button click
984 826 $(document).on('click', '#floating-chatbot-button', function() {
985 827 var chatbot = $('#floating-chatbot');
986 828 if (chatbot.hasClass('hidden')) {
@@ -985,15 +827,16 @@
985 827 var chatbot = $('#floating-chatbot');
986 828 if (chatbot.hasClass('hidden')) {
987 829 chatbot.removeClass('hidden').addClass('visible');
988 830 $(this).addClass('hidden');
989 - $('#chat-notification-badge').hide(); // Hide notification when opening chat
990 831 disableScroll();
832 + // Hide the pre-chat message without dismissing it
991 833 $('#pre-chat-message').fadeOut(250);
992 834 } else {
993 835 chatbot.removeClass('visible').addClass('hidden');
994 836 $(this).removeClass('hidden');
995 837 enableScroll();
838 + // Show the pre-chat message again if it hasn't been dismissed
996 839 checkPreChatDismissal();
997 840 }
998 841 });
999 842
@@ -1032,10 +875,12 @@
1032 875 $(':root').css('--vh', vh + 'px');
1033 876 }
1034 877
1035 878 // Set the height when the page loads
879 + $(document).ready(function() {
880 + setFullHeight();
881 + });
1036 882
1037 -
1038 883 // Set the height on resize and orientation change events
1039 884 $(window).on('resize orientationchange', function() {
1040 885 setFullHeight();
1041 886 });
@@ -1072,27 +917,24 @@
1072 917
1073 918
1074 919 // Event listener for Add to Cart button
1075 920 $(document).on('click', '.mxchat-add-to-cart-button', function() {
1076 - var productId = $(this).data('product-id');
1077 - // Add a special prefix to indicate this is from button
1078 - appendMessage("user", "add to cart");
1079 - sendMessageToChatbot("!addtocart"); // Special command to indicate button click
921 + var productId = $(this).data('product-id'); // Get product ID from data attribute
922 +
923 + // Simulate user message first for proper ordering
924 + appendMessage("user", "add to cart"); // Display the user's "add to cart" message first
925 +
926 +
927 + // Use existing function to send the "add to cart" command to the chatbot
928 + sendMessageToChatbot("add to cart"); // Triggers the chatbot response as though user typed it
1080 929 });
1081 930
1082 931
1083 -if (document.getElementById('pdf-upload-btn')) {
1084 - document.getElementById('pdf-upload-btn').addEventListener('click', function() {
1085 - document.getElementById('pdf-upload').click();
1086 - });
1087 -}
932 +// PDF Upload button click handler
933 +document.getElementById('pdf-upload-btn').addEventListener('click', function() {
934 + document.getElementById('pdf-upload').click();
935 +});
1088 936
1089 -if (document.getElementById('word-upload-btn')) {
1090 - document.getElementById('word-upload-btn').addEventListener('click', function() {
1091 - document.getElementById('word-upload').click();
1092 - });
1093 -}
1094 -
1095 937 // PDF file input change handler
1096 938 document.getElementById('pdf-upload').addEventListener('change', async function(e) {
1097 939 const file = e.target.files[0];
1098 940
@@ -1165,76 +1007,8 @@
1165 1007 this.value = ''; // Reset file input
1166 1008 }
1167 1009 });
1168 1010
1169 -// Word file input change handler
1170 -document.getElementById('word-upload').addEventListener('change', async function(e) {
1171 - const file = e.target.files[0];
1172 -
1173 - if (!file || file.type !== 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
1174 - alert('Please select a valid Word document (.docx).');
1175 - return;
1176 - }
1177 -
1178 - if (!sessionId) {
1179 - console.error('No session ID found');
1180 - alert('Error: No session ID found');
1181 - return;
1182 - }
1183 -
1184 - // Disable buttons and show loading state
1185 - const uploadBtn = document.getElementById('word-upload-btn');
1186 - const sendBtn = document.getElementById('send-button');
1187 - const originalBtnContent = uploadBtn.innerHTML;
1188 -
1189 - try {
1190 - const formData = new FormData();
1191 - formData.append('action', 'mxchat_upload_word');
1192 - formData.append('word_file', file);
1193 - formData.append('session_id', sessionId);
1194 - formData.append('nonce', mxchatChat.nonce);
1195 -
1196 - uploadBtn.disabled = true;
1197 - sendBtn.disabled = true;
1198 - uploadBtn.innerHTML = `<svg class="spinner" viewBox="0 0 50 50">
1199 - <circle cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
1200 - </svg>`;
1201 -
1202 - const response = await fetch(mxchatChat.ajax_url, {
1203 - method: 'POST',
1204 - body: formData
1205 - });
1206 -
1207 - const data = await response.json();
1208 -
1209 - if (data.success) {
1210 - // Hide popular questions if they exist
1211 - const popularQuestionsContainer = document.getElementById('mxchat-popular-questions');
1212 - if (popularQuestionsContainer) {
1213 - popularQuestionsContainer.style.display = 'none';
1214 - }
1215 -
1216 - // Show the active Word document name
1217 - showActiveWord(data.data.filename);
1218 -
1219 - appendMessage('bot', data.data.message);
1220 - scrollToBottom();
1221 - activeWordFile = data.data.filename;
1222 - } else {
1223 - console.error('Upload failed:', data.data);
1224 - alert('Failed to upload Word document. Please try again.');
1225 - }
1226 - } catch (error) {
1227 - console.error('Upload error:', error);
1228 - alert('Error uploading file. Please try again.');
1229 - } finally {
1230 - uploadBtn.disabled = false;
1231 - sendBtn.disabled = false;
1232 - uploadBtn.innerHTML = originalBtnContent;
1233 - this.value = ''; // Reset file input
1234 - }
1235 -});
1236 -
1237 1011 // Function to show active PDF name in toolbar
1238 1012 function showActivePdf(filename) {
1239 1013 const container = document.getElementById('active-pdf-container');
1240 1014 const nameElement = document.getElementById('active-pdf-name');
@@ -1247,22 +1021,8 @@
1247 1021 nameElement.textContent = filename;
1248 1022 container.style.display = 'flex';
1249 1023 }
1250 1024
1251 -// Function to show active Word document name in toolbar
1252 -function showActiveWord(filename) {
1253 - const container = document.getElementById('active-word-container');
1254 - const nameElement = document.getElementById('active-word-name');
1255 -
1256 - if (!container || !nameElement) {
1257 - console.error('Word document container elements not found');
1258 - return;
1259 - }
1260 -
1261 - nameElement.textContent = filename;
1262 - container.style.display = 'flex';
1263 -}
1264 -
1265 1025 // Function to remove active PDF
1266 1026 function removeActivePdf() {
1267 1027 const container = document.getElementById('active-pdf-container');
1268 1028 const nameElement = document.getElementById('active-pdf-name');
@@ -1293,41 +1053,9 @@
1293 1053 console.error('Error removing PDF:', error);
1294 1054 });
1295 1055 }
1296 1056
1297 -// Function to remove active Word document
1298 -function removeActiveWord() {
1299 - const container = document.getElementById('active-word-container');
1300 - const nameElement = document.getElementById('active-word-name');
1301 -
1302 - if (!container || !nameElement || !activeWordFile) return;
1303 -
1304 - fetch(mxchatChat.ajax_url, {
1305 - method: 'POST',
1306 - headers: {
1307 - 'Content-Type': 'application/x-www-form-urlencoded',
1308 - },
1309 - body: new URLSearchParams({
1310 - 'action': 'mxchat_remove_word',
1311 - 'session_id': sessionId,
1312 - 'nonce': mxchatChat.nonce
1313 - })
1314 - })
1315 - .then(response => response.json())
1316 - .then(data => {
1317 - if (data.success) {
1318 - container.style.display = 'none';
1319 - nameElement.textContent = '';
1320 - activeWordFile = null;
1321 - appendMessage('bot', 'Word document removed.');
1322 - }
1323 - })
1324 - .catch(error => {
1325 - console.error('Error removing Word document:', error);
1326 - });
1327 -}
1328 -
1329 -// Add remove button click handlers
1057 +// Add remove button click handler
1330 1058 document.getElementById('remove-pdf-btn')?.addEventListener('click', function(e) {
1331 1059 e.preventDefault();
1332 1060 e.stopPropagation();
1333 1061 removeActivePdf();
@@ -1332,19 +1060,12 @@
1332 1060 e.stopPropagation();
1333 1061 removeActivePdf();
1334 1062 });
1335 1063
1336 -document.getElementById('remove-word-btn')?.addEventListener('click', function(e) {
1337 - e.preventDefault();
1338 - e.stopPropagation();
1339 - removeActiveWord();
1340 -});
1341 -
1342 -// Check initial document status
1343 -function checkInitialDocumentStatus() {
1064 +// Check initial PDF status on load
1065 +function checkInitialPdfStatus() {
1344 1066 if (!sessionId) return;
1345 1067
1346 - // Check PDF status
1347 1068 fetch(mxchatChat.ajax_url, {
1348 1069 method: 'POST',
1349 1070 headers: {
1350 1071 'Content-Type': 'application/x-www-form-urlencoded',
@@ -1364,31 +1085,8 @@
1364 1085 })
1365 1086 .catch(error => {
1366 1087 console.error('Error checking PDF status:', error);
1367 1088 });
1368 -
1369 - // Check Word document status
1370 - fetch(mxchatChat.ajax_url, {
1371 - method: 'POST',
1372 - headers: {
1373 - 'Content-Type': 'application/x-www-form-urlencoded',
1374 - },
1375 - body: new URLSearchParams({
1376 - 'action': 'mxchat_check_word_status',
1377 - 'session_id': sessionId,
1378 - 'nonce': mxchatChat.nonce
1379 - })
1380 - })
1381 - .then(response => response.json())
1382 - .then(data => {
1383 - if (data.success && data.data.filename) {
1384 - showActiveWord(data.data.filename);
1385 - activeWordFile = data.data.filename;
1386 - }
1387 - })
1388 - .catch(error => {
1389 - console.error('Error checking Word document status:', error);
1390 - });
1391 1089 }
1392 1090
1393 1091 // Apply toolbar settings
1394 1092 if (mxchatChat.chat_toolbar_toggle === 'on') {
@@ -1398,9 +1096,9 @@
1398 1096 }
1399 1097
1400 1098 // Initialize on page load
1401 1099 document.addEventListener('DOMContentLoaded', function() {
1402 - checkInitialDocumentStatus();
1100 + checkInitialPdfStatus();
1403 1101 });
1404 1102
1405 1103 // Style all toolbar elements
1406 1104 const toolbarElements = [
@@ -1405,11 +1103,9 @@
1405 1103 // Style all toolbar elements
1406 1104 const toolbarElements = [
1407 1105 '#mxchat-chatbot .toolbar-btn svg',
1408 1106 '#mxchat-chatbot .active-pdf-name',
1409 - '#mxchat-chatbot .active-word-name',
1410 - '#mxchat-chatbot .remove-pdf-btn svg',
1411 - '#mxchat-chatbot .remove-word-btn svg'
1107 + '#mxchat-chatbot .remove-pdf-btn svg'
1412 1108 ];
1413 1109 $(toolbarElements.join(', ')).css({
1414 1110 'fill': toolbarIconColor,
1415 1111 'color': toolbarIconColor
@@ -1416,122 +1112,10 @@
1416 1112 });
1417 1113
1418 1114
1419 1115
1420 -// Ensure essential elements are defined
1421 -const emailForm = document.getElementById('email-collection-form');
1422 -const emailBlocker = document.getElementById('email-blocker');
1423 -const chatbotWrapper = document.getElementById('chat-container');
1424 -
1425 -if (emailForm && emailBlocker && chatbotWrapper) {
1426 - // Check if email exists for the current session
1427 - function checkSessionAndEmail() {
1428 - const sessionId = getChatSession();
1429 - //console.log("[DEBUG JS] checkSessionAndEmail -> sessionId:", sessionId);
1430 -
1431 - fetch(mxchatChat.ajax_url, {
1432 - method: 'POST',
1433 - headers: {
1434 - 'Content-Type': 'application/x-www-form-urlencoded',
1435 - },
1436 - body: new URLSearchParams({
1437 - action: 'mxchat_check_email_provided',
1438 - session_id: sessionId,
1439 - nonce: mxchatChat.nonce,
1440 - }),
1441 - })
1442 - .then((response) => response.json())
1443 - .then((data) => {
1444 - //console.log("[DEBUG JS] mxchat_check_email_provided response:", data);
1445 -
1446 - if (data.success) {
1447 - if (data.data.logged_in) {
1448 - //console.log("[DEBUG JS] User is logged in. Hiding email form.");
1449 - emailBlocker.style.display = 'none';
1450 - chatbotWrapper.style.display = 'flex';
1451 - } else if (data.data.email) {
1452 - //console.log("[DEBUG JS] Email found for session. Hiding email form.");
1453 - emailBlocker.style.display = 'none';
1454 - chatbotWrapper.style.display = 'flex';
1455 - } else {
1456 - //console.log("[DEBUG JS] No email provided. Showing email form.");
1457 - emailBlocker.style.display = 'flex';
1458 - chatbotWrapper.style.display = 'none';
1459 - }
1460 - } else {
1461 - //console.log("[DEBUG JS] Error or no data received. Showing email form.");
1462 - emailBlocker.style.display = 'flex';
1463 - chatbotWrapper.style.display = 'none';
1464 - }
1465 - })
1466 - .catch((error) => {
1467 - // console.error("[DEBUG JS] Fetch error -> forcing email form visible:", error);
1468 - emailBlocker.style.display = 'flex';
1469 - chatbotWrapper.style.display = 'none';
1470 - });
1471 -}
1472 -
1473 -
1474 -
1475 - // Handle email form submission
1476 - emailForm.addEventListener('submit', function (event) {
1477 - event.preventDefault();
1478 - const userEmail = document.getElementById('user-email').value;
1479 - const sessionId = getChatSession();
1480 -
1481 - if (userEmail) {
1482 - fetch(mxchatChat.ajax_url, {
1483 - method: 'POST',
1484 - headers: {
1485 - 'Content-Type': 'application/x-www-form-urlencoded',
1486 - },
1487 - body: new URLSearchParams({
1488 - action: 'mxchat_handle_save_email_and_response',
1489 - email: userEmail,
1490 - session_id: sessionId,
1491 - nonce: mxchatChat.nonce,
1492 - }),
1493 - })
1494 - .then((response) => response.json())
1495 - .then((data) => {
1496 - //console.log('Backend response:', data);
1497 - if (data.success) {
1498 - //console.log('Email saved successfully:', userEmail);
1499 - emailBlocker.style.display = 'none';
1500 - chatbotWrapper.style.display = 'flex';
1501 -
1502 - // Optionally handle bot response
1503 - if (data.message) {
1504 - appendMessage('bot', data.message);
1505 - scrollToBottom();
1506 - }
1507 - } else {
1508 - console.error('Error saving email:', data.message || 'Unknown error');
1509 - }
1510 - })
1511 - .catch((error) => {
1512 - console.error('AJAX error:', error);
1513 - });
1514 - }
1515 - });
1516 -
1517 - // Check session and email status on page load
1518 - checkSessionAndEmail();
1519 -} else {
1520 - console.error('Essential elements for email handling are missing.');
1521 -}
1522 -
1523 -
1524 -// Initialize when document is ready
1525 -$(document).ready(function() {
1526 - setFullHeight();
1527 - initializeChatVisibility();
1528 - loadChatHistory();
1529 -
1530 1116 });
1531 1117
1532 -});
1533 -
1534 1118 // Event listener for copy button
1535 1119 document.addEventListener("click", (e) => {
1536 1120 if (e.target.classList.contains("mxchat-copy-button")) {
1537 1121 const copyButton = e.target;
@@ -1552,7 +1136,4 @@
1552 1136 });
1553 1137 }
1554 1138 }
1555 1139 });
1556 -
1557 -
1558 -