PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 1.6.1
MxChat – AI Chatbot & Content Generation for WordPress v1.6.1
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 +72 -181 2.0.31.6.1 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
@@ -28,107 +26,10 @@
28 26 let activePdfFile = null;
29 27 let activeWordFile = null;
30 28
31 29
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 30
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 31
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 32 function getChatSession() {
132 33 var sessionId = getCookie('mxchat_session_id');
133 34 //console.log("Session ID retrieved from cookie: ", sessionId);
134 35
@@ -355,8 +256,10 @@
355 256 }
356 257 }
357 258
358 259 function callMxChat(message, callback) {
260 + //console.log("Sending message to chatbot:", message);
261 +
359 262 $.ajax({
360 263 url: mxchatChat.ajax_url,
361 264 type: 'POST',
362 265 dataType: 'json',
@@ -366,37 +269,41 @@
366 269 session_id: getChatSession(),
367 270 nonce: mxchatChat.nonce
368 271 },
369 272 success: function(response) {
370 - // Existing chat mode check
273 + //console.log("callMxChat response:", response);
274 +
275 + // Check for chat_mode in the response
371 276 if (response.chat_mode) {
372 277 updateChatModeIndicator(response.chat_mode);
373 278 }
279 + // Also check in fallbackResponse if exists
374 280 else if (response.fallbackResponse && response.fallbackResponse.chat_mode) {
375 281 updateChatModeIndicator(response.fallbackResponse.chat_mode);
376 282 }
377 -
378 283 // Add PDF filename handling
379 284 if (response.data && response.data.filename) {
380 285 showActivePdf(response.data.filename);
381 286 activePdfFile = response.data.filename;
382 287 }
383 -
384 - // Add redirect check here
288 + // Add redirect check here
385 289 if (response.redirect_url) {
290 + // Show the message first
386 291 let responseText = response.text || '';
387 292 if (responseText) {
388 293 replaceLastMessage("bot", responseText);
389 294 }
295 + // Then redirect after a short delay
390 296 setTimeout(() => {
391 297 window.location.href = response.redirect_url;
392 298 }, 1500);
393 - return;
299 + return; // Exit early since we're redirecting
394 300 }
395 301
396 302 // Check for live agent response
397 303 if (response.success && response.data && response.data.status === 'waiting_for_agent') {
398 304 updateChatModeIndicator('agent');
305 + // Do not replace the thinking dots; just wait for the agent's actual response
399 306 return;
400 307 }
401 308
402 309 // Handle other responses
@@ -403,33 +310,31 @@
403 310 let responseText = response.text || '';
404 311 let responseHtml = response.html || '';
405 312 let responseMessage = response.message || '';
406 313
314 + // Check for mode change in text response
407 315 if (responseText === 'You are now chatting with the AI chatbot.') {
408 316 updateChatModeIndicator('ai');
409 317 }
410 318
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 {
319 + // For product card or chatbot responses with HTML
320 + if (responseText && responseHtml) {
321 + replaceLastMessage("bot", responseText, responseHtml);
322 + }
323 + // For regular chatbot responses with just text
324 + else if (responseText) {
325 + replaceLastMessage("bot", responseText);
326 + }
327 + // For responses with only HTML (like product cards)
328 + else if (responseHtml) {
329 + replaceLastMessage("bot", "", responseHtml);
330 + }
331 + // For legacy message format
332 + else if (responseMessage) {
333 + replaceLastMessage("bot", responseMessage);
334 + }
335 + // Fallback error case
336 + else {
432 337 console.error("Unexpected response format:", response);
433 338 replaceLastMessage("bot", "I'm sorry, something went wrong.");
434 339 }
435 340
@@ -437,8 +342,9 @@
437 342 lastSeenMessageId = response.message_id;
438 343 }
439 344 },
440 345 error: function(xhr, status, error) {
346 + //console.log("Error communicating with the server:", xhr.status, error);
441 347 replaceLastMessage("bot", "An unexpected error occurred.");
442 348 }
443 349 });
444 350 }
@@ -516,12 +422,12 @@
516 422 }
517 423 }
518 424 });
519 425
426 + // Update the last seen message ID if applicable
520 427 if (messageText.id) {
521 - lastSeenMessageId = messageText.id;
522 - hideNotification();
523 - }
428 + lastSeenMessageId = messageText.id;
429 + }
524 430 } catch (error) {
525 431 console.error("Error rendering message with images:", error);
526 432 }
527 433 }
@@ -574,17 +480,14 @@
574 480 'color': fontColor,
575 481 })
576 482 .removeClass('temporary-message')
577 483 .fadeIn(200, function() {
484 + // After message is displayed, scroll last user message to top
578 485 if (sender === "bot" || sender === "agent") {
579 486 const lastUserMessage = $('#chat-box').find('.user-message').last();
580 487 if (lastUserMessage.length) {
581 488 scrollElementToTop(lastUserMessage);
582 489 }
583 - // Show notification if chat is hidden
584 - if ($('#floating-chatbot').hasClass('hidden')) {
585 - showNotification();
586 - }
587 490 }
588 491 });
589 492 });
590 493 } else {
@@ -609,11 +512,11 @@
609 512 }
610 513 }
611 514
612 515
613 -// Update your checkForAgentMessages function
614 516 function checkForAgentMessages() {
615 517 const sessionId = getChatSession();
518 +
616 519 $.ajax({
617 520 url: mxchatChat.ajax_url,
618 521 type: 'POST',
619 522 dataType: 'json',
@@ -623,24 +526,17 @@
623 526 last_seen_id: lastSeenMessageId,
624 527 nonce: mxchatChat.nonce
625 528 },
626 529 success: function (response) {
530 + //console.log("Agent messages polling response:", response);
627 531 if (response.success && response.data?.new_messages) {
628 - let hasNewMessage = false;
629 -
630 532 response.data.new_messages.forEach(function (message) {
631 533 if (message.role === "agent" && !processedMessageIds.has(message.id)) {
632 - hasNewMessage = true;
633 534 replaceLastMessage("agent", message.content);
634 535 lastSeenMessageId = message.id;
635 536 processedMessageIds.add(message.id);
636 537 }
637 538 });
638 -
639 - if (hasNewMessage && $('#floating-chatbot').hasClass('hidden')) {
640 - showNotification();
641 - }
642 -
643 539 scrollToBottom(true);
644 540 }
645 541 },
646 542 error: function (xhr, status, error) {
@@ -767,37 +663,29 @@
767 663 return textArea.value;
768 664 }
769 665
770 666
771 -// Update formatCodeBlocks function
772 667 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 - });
668 + // Ensure the input is a string; otherwise, convert or return empty
669 + if (typeof text !== 'string') {
670 + console.error("formatCodeBlocks: Input is not a string:", text);
671 + return typeof text === 'object' && text.text ? text.text : ""; // Use .text if available, else empty
672 + }
777 673
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>`;
674 + const codeBlockPattern = /```(\w+)?\n?([\s\S]+?)```/g;
675 +
676 + return text.replace(codeBlockPattern, (_, language, codeContent) => {
677 + language = language || 'plaintext';
678 +
679 + return `
680 + <div class="mxchat-code-block-container">
681 + <button class="mxchat-copy-button" aria-label="Copy to clipboard">Copy</button>
682 + <pre class="mxchat-code-block"><code class="mxchat-language-${language}">${escapeHtml(codeContent)}</code></pre>
683 + </div>`;
781 684 });
685 +}
782 686
783 - return text;
784 -}
785 687
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 688 // Utility function to escape HTML
801 689 function escapeHtml(unsafe) {
802 690 return unsafe
803 691 .replace(/&/g, "&amp;")
@@ -811,18 +699,20 @@
811 699
812 700
813 701 // Function to convert newlines, skipping preformatted text
814 702 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('');
703 + // Regex to exclude <pre> and <code> tags from adding <br> tags
704 + return text.replace(/(^|[^>])\n/g, '$1<br>');
820 705 }
821 706
822 707
823 708
709 +$(document).ready(function() {
710 + loadChatHistory();
711 +});
824 712
713 +
714 +
825 715 // Helper function to check if a string is an image HTML
826 716 function isImageHtml(str) {
827 717 return str.startsWith('<img') && str.endsWith('>');
828 718 }
@@ -914,11 +804,15 @@
914 804 // Also check pre-chat message when Complianz is not enabled
915 805 checkPreChatDismissal();
916 806 }
917 807 }
808 +// Initialize when document is ready
809 +$(document).ready(function() {
810 + //console.log('Document ready - starting initialization');
811 + initializeChatVisibility();
812 +});
918 813
919 814
920 -
921 815 function checkConsentAndShowChat() {
922 816 var consentStatus = cmplz_has_consent('marketing');
923 817 var consentType = complianz.consenttype;
924 818
@@ -985,15 +879,16 @@
985 879 var chatbot = $('#floating-chatbot');
986 880 if (chatbot.hasClass('hidden')) {
987 881 chatbot.removeClass('hidden').addClass('visible');
988 882 $(this).addClass('hidden');
989 - $('#chat-notification-badge').hide(); // Hide notification when opening chat
990 883 disableScroll();
884 + // Hide the pre-chat message without dismissing it
991 885 $('#pre-chat-message').fadeOut(250);
992 886 } else {
993 887 chatbot.removeClass('visible').addClass('hidden');
994 888 $(this).removeClass('hidden');
995 889 enableScroll();
890 + // Show the pre-chat message again if it hasn't been dismissed
996 891 checkPreChatDismissal();
997 892 }
998 893 });
999 894
@@ -1032,10 +927,12 @@
1032 927 $(':root').css('--vh', vh + 'px');
1033 928 }
1034 929
1035 930 // Set the height when the page loads
931 + $(document).ready(function() {
932 + setFullHeight();
933 + });
1036 934
1037 -
1038 935 // Set the height on resize and orientation change events
1039 936 $(window).on('resize orientationchange', function() {
1040 937 setFullHeight();
1041 938 });
@@ -1520,15 +1417,9 @@
1520 1417 console.error('Essential elements for email handling are missing.');
1521 1418 }
1522 1419
1523 1420
1524 -// Initialize when document is ready
1525 -$(document).ready(function() {
1526 - setFullHeight();
1527 - initializeChatVisibility();
1528 - loadChatHistory();
1529 1421
1530 -});
1531 1422
1532 1423 });
1533 1424
1534 1425 // Event listener for copy button