jQuery(document).ready(function($) { //console.log('mxchatChat object:', mxchatChat); //console.log('Link Target Toggle Value:', mxchatChat.link_target_toggle); const toolbarIconColor = mxchatChat.toolbar_icon_color || '#212121'; // Initialize color settings var userMessageBgColor = mxchatChat.user_message_bg_color; var userMessageFontColor = mxchatChat.user_message_font_color; var botMessageBgColor = mxchatChat.bot_message_bg_color; var botMessageFontColor = mxchatChat.bot_message_font_color; // Add live agent message colors var liveAgentMessageBgColor = mxchatChat.live_agent_message_bg_color; var liveAgentMessageFontColor = mxchatChat.live_agent_message_font_color; var linkTarget = mxchatChat.link_target_toggle === 'on' ? '_blank' : '_self'; var lastSeenMessageId = ''; // Initialize session ID var sessionId = getChatSession(); let pollingInterval; // Variable to store the interval ID let processedMessageIds = new Set(); // Add this at the top with your other variables //console.log('Live Agent BG Color:', liveAgentMessageBgColor); //console.log('Live Agent Font Color:', liveAgentMessageFontColor); let activePdfFile = null; let activeWordFile = null; function getChatSession() { var sessionId = getCookie('mxchat_session_id'); //console.log("Session ID retrieved from cookie: ", sessionId); if (!sessionId) { sessionId = generateSessionId(); //console.log("Generated new session ID: ", sessionId); setChatSession(sessionId); } //console.log("Final session ID: ", sessionId); return sessionId; } function setChatSession(sessionId) { // Set the cookie with a 24-hour expiration (86400 seconds) document.cookie = "mxchat_session_id=" + sessionId + "; path=/; max-age=86400; SameSite=Lax"; } // Get cookie value by name function getCookie(name) { let value = "; " + document.cookie; let parts = value.split("; " + name + "="); if (parts.length == 2) return parts.pop().split(";").shift(); } // Generate a new session ID function generateSessionId() { return 'mxchat_chat_' + Math.random().toString(36).substr(2, 9); } // Function to send the message to the chatbot (backend) function sendMessageToChatbot(message) { var sessionId = getChatSession(); // Reuse the session ID logic // Hide the popular questions section $('#mxchat-popular-questions').hide(); // Show thinking indicator (no need to append the user's message again) appendThinkingMessage(); scrollToBottom(); //console.log("Sending message to chatbot:", message); // Log the message //console.log("Session ID:", sessionId); // Log the session ID // Call the chatbot using the same call logic as sendMessage callMxChat(message, function(response) { // ** Ensure temporary thinking message is removed before adding new response ** $('.temporary-message').remove(); // Replace thinking indicator with actual response replaceLastMessage("bot", response); }); } function sendMessage() { var message = $('#chat-input').val(); // Get value from textarea if (message) { appendMessage("user", message); // Append user's message $('#chat-input').val(''); // Clear the textarea $('#chat-input').css('height', 'auto'); // Reset height after clearing content // Hide the popular questions section $('#mxchat-popular-questions').hide(); // Show typing indicator appendThinkingMessage(); scrollToBottom(); callMxChat(message, function(response) { // Replace typing indicator with actual response replaceLastMessage("bot", response); }); } } // Function to append a thinking message with animation function appendThinkingMessage() { // Remove any existing thinking dots first $('.thinking-dots').remove(); // Retrieve the bot message font color and background color var botMessageFontColor = mxchatChat.bot_message_font_color; var botMessageBgColor = mxchatChat.bot_message_bg_color; var thinkingHtml = '
' + '
' + '' + '' + '' + '
' + '
'; // Append the thinking dots to the chat container (or within the temporary message div) $("#chat-box").append('
' + thinkingHtml + '
'); scrollToBottom(); } // Trigger send button click when "Enter" key is pressed in the textarea $('#chat-input').keypress(function(e) { if (e.which == 13 && !e.shiftKey) { // Check if "Enter" is pressed without Shift e.preventDefault(); // Prevent default "Enter" behavior $('#send-button').click(); // Trigger send button click } }); // Handle send button click $('#send-button').click(function() { sendMessage(); }); // Handle click on popular questions $('.mxchat-popular-question').on('click', function () { var question = $(this).text(); // Get the text of the clicked question // Append the question as if the user typed it appendMessage("user", question); // Send the question to the server (backend) sendMessageToChatbot(question); }); // Use the linkTarget in your linkify function function linkify(inputText) { // Check for already linked URLs and skip them // We use negative lookaheads to skip anything already in an tag var markdownLinkPattern = /\[([^\]]+)\]\((https?:\/\/[^\s]+)\)/g; var replacedText = inputText.replace(markdownLinkPattern, '$1'); // Replace standalone URLs not already in an tag var urlPattern = /(^|[^">])(https?:\/\/[^\s<]+)/gim; replacedText = replacedText.replace(urlPattern, '$1$2'); // Replace "www." prefixed URLs not already in an tag var wwwPattern = /(^|[^">])(www\.[\S]+(\b|$))(?![^<]*<\/a>)/gim; replacedText = replacedText.replace(wwwPattern, '$1$2'); return replacedText; } function scrollElementToTop(element) { var chatBox = $('#chat-box'); var elementTop = element.position().top + chatBox.scrollTop(); chatBox.animate({ scrollTop: elementTop }, 500); } // Optimized scrollToBottom function for instant scrolling function scrollToBottom(instant = false) { var chatBox = $('#chat-box'); if (instant) { // Instantly set the scroll position to the bottom chatBox.scrollTop(chatBox.prop("scrollHeight")); } else { // Use requestAnimationFrame for smoother scrolling if needed let start = null; const scrollHeight = chatBox.prop("scrollHeight"); const initialScroll = chatBox.scrollTop(); const distance = scrollHeight - initialScroll; const duration = 500; // Duration in ms function smoothScroll(timestamp) { if (!start) start = timestamp; const progress = timestamp - start; const currentScroll = initialScroll + (distance * (progress / duration)); chatBox.scrollTop(currentScroll); if (progress < duration) { requestAnimationFrame(smoothScroll); } else { chatBox.scrollTop(scrollHeight); // Ensure it's exactly at the bottom } } requestAnimationFrame(smoothScroll); } } // Function to format text with **bold** inside double asterisks function formatBoldText(text) { return text.replace(/\*\*(.*?)\*\*/g, '$1'); } // Function to convert newline characters to HTML line breaks and handle paragraph spacing function convertNewlinesToBreaks(text) { // Split the text into paragraphs (marked by double newlines or multiple
tags) const paragraphs = text.split(/(?:\n\n|\\s*\)/g); // Wrap each paragraph in

tags return paragraphs .map(para => `

${para.trim()}

`) .join(''); } // Copy to clipboard function // Function to copy text to clipboard function copyToClipboard(text) { var tempInput = $(''); $('body').append(tempInput); tempInput.val(text).select(); document.execCommand('copy'); tempInput.remove(); } function updateChatModeIndicator(mode) { const indicator = document.getElementById('chat-mode-indicator'); if (indicator) { indicator.textContent = mode === 'agent' ? 'Live Agent' : 'AI Agent'; } // Start or stop polling based on mode if (mode === 'agent') { startPolling(); } else { stopPolling(); } } function callMxChat(message, callback) { //console.log("Sending message to chatbot:", message); $.ajax({ url: mxchatChat.ajax_url, type: 'POST', dataType: 'json', data: { action: 'mxchat_handle_chat_request', message: message, session_id: getChatSession(), nonce: mxchatChat.nonce }, success: function(response) { //console.log("callMxChat response:", response); // Check for chat_mode in the response if (response.chat_mode) { updateChatModeIndicator(response.chat_mode); } // Also check in fallbackResponse if exists else if (response.fallbackResponse && response.fallbackResponse.chat_mode) { updateChatModeIndicator(response.fallbackResponse.chat_mode); } // Add PDF filename handling if (response.data && response.data.filename) { showActivePdf(response.data.filename); activePdfFile = response.data.filename; } // Add redirect check here if (response.redirect_url) { // Show the message first let responseText = response.text || ''; if (responseText) { replaceLastMessage("bot", responseText); } // Then redirect after a short delay setTimeout(() => { window.location.href = response.redirect_url; }, 1500); return; // Exit early since we're redirecting } // Check for live agent response if (response.success && response.data && response.data.status === 'waiting_for_agent') { updateChatModeIndicator('agent'); // Do not replace the thinking dots; just wait for the agent's actual response return; } // Handle other responses let responseText = response.text || ''; let responseHtml = response.html || ''; let responseMessage = response.message || ''; // Check for mode change in text response if (responseText === 'You are now chatting with the AI chatbot.') { updateChatModeIndicator('ai'); } // For product card or chatbot responses with HTML if (responseText && responseHtml) { replaceLastMessage("bot", responseText, responseHtml); } // For regular chatbot responses with just text else if (responseText) { replaceLastMessage("bot", responseText); } // For responses with only HTML (like product cards) else if (responseHtml) { replaceLastMessage("bot", "", responseHtml); } // For legacy message format else if (responseMessage) { replaceLastMessage("bot", responseMessage); } // Fallback error case else { console.error("Unexpected response format:", response); replaceLastMessage("bot", "I'm sorry, something went wrong."); } if (response.message_id) { lastSeenMessageId = response.message_id; } }, error: function(xhr, status, error) { //console.log("Error communicating with the server:", xhr.status, error); replaceLastMessage("bot", "An unexpected error occurred."); } }); } function appendMessage(sender, messageText = '', messageHtml = '', images = [], isTemporary = false) { //console.log("Appending message. Sender:", sender, "Content:", messageText); try { // Determine styles based on sender type let messageClass, bgColor, fontColor; if (sender === "user") { messageClass = "user-message"; bgColor = userMessageBgColor; fontColor = userMessageFontColor; } else if (sender === "agent") { messageClass = "agent-message"; bgColor = liveAgentMessageBgColor; fontColor = liveAgentMessageFontColor; } else { messageClass = "bot-message"; bgColor = botMessageBgColor; fontColor = botMessageFontColor; } const messageDiv = $('
') .addClass(messageClass) .css({ 'background': bgColor, 'color': fontColor, }); // Add CSS for paragraphs messageDiv.css({ 'margin-bottom': '1em' }); // Format and process the message content let fullMessage = linkify(formatBoldText(convertNewlinesToBreaks(formatCodeBlocks(messageText)))); // Add images if provided if (images && images.length > 0) { fullMessage += ''; } // Append HTML content if provided if (messageHtml) { fullMessage += '

' + messageHtml; } messageDiv.html(fullMessage); // Add a class for temporary messages if needed if (isTemporary) { messageDiv.addClass('temporary-message'); } // Append the message to the chat box messageDiv.hide().appendTo('#chat-box').fadeIn(300, function () { if (sender === "bot") { // After bot's message is displayed, scroll the last user message to the top const lastUserMessage = $('#chat-box').find('.user-message').last(); if (lastUserMessage.length) { scrollElementToTop(lastUserMessage); } } }); // Update the last seen message ID if applicable if (messageText.id) { lastSeenMessageId = messageText.id; } } catch (error) { console.error("Error rendering message with images:", error); } } function replaceLastMessage(sender, responseText, responseHtml = '', images = []) { var messageClass = sender === "user" ? "user-message" : sender === "agent" ? "agent-message" : "bot-message"; var lastMessageDiv = $('#chat-box').find('.bot-message.temporary-message, .agent-message.temporary-message').last(); // Determine styles let bgColor, fontColor; if (sender === "user") { bgColor = userMessageBgColor; fontColor = userMessageFontColor; } else if (sender === "agent") { bgColor = liveAgentMessageBgColor; fontColor = liveAgentMessageFontColor; } else { bgColor = botMessageBgColor; fontColor = botMessageFontColor; } var fullMessage = linkify(formatBoldText(convertNewlinesToBreaks(formatCodeBlocks(responseText)))); if (responseHtml) { fullMessage += '

' + responseHtml; } if (images.length > 0) { fullMessage += ''; } if (lastMessageDiv.length) { lastMessageDiv.fadeOut(200, function() { $(this) .html(fullMessage) .removeClass('bot-message user-message') .addClass(messageClass) .css({ 'background-color': bgColor, 'color': fontColor, }) .removeClass('temporary-message') .fadeIn(200, function() { // After message is displayed, scroll last user message to top if (sender === "bot" || sender === "agent") { const lastUserMessage = $('#chat-box').find('.user-message').last(); if (lastUserMessage.length) { scrollElementToTop(lastUserMessage); } } }); }); } else { appendMessage(sender, responseText, responseHtml, images); } } function startPolling() { // Clear any existing interval first stopPolling(); // Start new polling interval pollingInterval = setInterval(checkForAgentMessages, 5000); //console.log("Started agent message polling"); } function stopPolling() { if (pollingInterval) { clearInterval(pollingInterval); pollingInterval = null; //console.log("Stopped agent message polling"); } } function checkForAgentMessages() { const sessionId = getChatSession(); $.ajax({ url: mxchatChat.ajax_url, type: 'POST', dataType: 'json', data: { action: 'mxchat_fetch_new_messages', session_id: sessionId, last_seen_id: lastSeenMessageId, nonce: mxchatChat.nonce }, success: function (response) { //console.log("Agent messages polling response:", response); if (response.success && response.data?.new_messages) { response.data.new_messages.forEach(function (message) { if (message.role === "agent" && !processedMessageIds.has(message.id)) { replaceLastMessage("agent", message.content); lastSeenMessageId = message.id; processedMessageIds.add(message.id); } }); scrollToBottom(true); } }, error: function (xhr, status, error) { console.error("Polling error:", xhr, status, error); } }); } function loadChatHistory() { var sessionId = getChatSession(); var chatPersistenceEnabled = mxchatChat.chat_persistence_toggle === 'on'; if (chatPersistenceEnabled && sessionId) { $.ajax({ url: mxchatChat.ajax_url, type: 'POST', dataType: 'json', data: { action: 'mxchat_fetch_conversation_history', session_id: sessionId }, success: function(response) { if (response.success && response.data && Array.isArray(response.data.conversation)) { var $chatBox = $('#chat-box'); var $fragment = $(document.createDocumentFragment()); let highestMessageId = lastSeenMessageId; if (response.data.chat_mode) { updateChatModeIndicator(response.data.chat_mode); } $.each(response.data.conversation, function(index, message) { // Skip agent messages if persistence is off if (!chatPersistenceEnabled && message.role === 'agent') { return; } var messageClass, messageBgColor, messageFontColor; switch (message.role) { case 'user': messageClass = 'user-message'; messageBgColor = userMessageBgColor; messageFontColor = userMessageFontColor; break; case 'agent': messageClass = 'agent-message'; messageBgColor = liveAgentMessageBgColor; messageFontColor = liveAgentMessageFontColor; break; default: messageClass = 'bot-message'; messageBgColor = botMessageBgColor; messageFontColor = botMessageFontColor; break; } var messageElement = $('
').addClass(messageClass) .css({ 'background': messageBgColor, 'color': messageFontColor }); var content = message.content; content = content.replace(/\\'/g, "'").replace(/\\"/g, '"'); content = decodeHTMLEntities(content); if (content.includes("mxchat-product-card") || content.includes("mxchat-image-gallery")) { messageElement.html(content); } else { var formattedContent = linkify( formatBoldText( convertNewlinesToBreaks(formatCodeBlocks(content)) ) ); messageElement.html(formattedContent); } $fragment.append(messageElement); // In loadChatHistory, change this part: if (message.id) { highestMessageId = Math.max(highestMessageId, message.id); processedMessageIds.add(message.id); // Add all message IDs to processed set } }); $chatBox.append($fragment); scrollToBottom(true); if (response.data.conversation.length > 0) { $('#mxchat-popular-questions').hide(); } // Update lastSeenMessageId after history loads lastSeenMessageId = highestMessageId; // Only update chat mode if persistence is enabled if (chatPersistenceEnabled && response.data.conversation.length > 0) { var lastMessage = response.data.conversation[response.data.conversation.length - 1]; if (lastMessage.role === 'agent') { updateChatModeIndicator('agent'); } } } else { console.warn("No conversation history found."); } }, error: function(xhr, status, error) { console.error("Error loading chat history:", status, error); appendMessage("bot", "Unable to load chat history."); } }); } else { console.warn("Chat persistence is disabled or no session ID found. Not loading history."); } } // Function to decode HTML entities function decodeHTMLEntities(text) { var textArea = document.createElement('textarea'); textArea.innerHTML = text; return textArea.value; } function formatCodeBlocks(text) { // Ensure the input is a string; otherwise, convert or return empty if (typeof text !== 'string') { console.error("formatCodeBlocks: Input is not a string:", text); return typeof text === 'object' && text.text ? text.text : ""; // Use .text if available, else empty } const codeBlockPattern = /```(\w+)?\n?([\s\S]+?)```/g; return text.replace(codeBlockPattern, (_, language, codeContent) => { language = language || 'plaintext'; return `
${escapeHtml(codeContent)}
`; }); } // Utility function to escape HTML function escapeHtml(unsafe) { return unsafe .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // Function to convert newlines, skipping preformatted text function convertNewlinesToBreaks(text) { // Regex to exclude
 and  tags from adding 
tags return text.replace(/(^|[^>])\n/g, '$1
'); } $(document).ready(function() { loadChatHistory(); }); // Helper function to check if a string is an image HTML function isImageHtml(str) { return str.startsWith(''); } // Function to remove thinking dots function removeThinkingDots() { $('.thinking-dots').closest('.temporary-message').remove(); } function isMobile() { // This can be a simple check, or more sophisticated detection of mobile devices return window.innerWidth <= 768; // Example threshold for mobile devices } function disableScroll() { if (isMobile()) { $('body').css('overflow', 'hidden'); } } function enableScroll() { if (isMobile()) { $('body').css('overflow', ''); } } // Pre-chat dismissal check function (wrapped in a function for reuse) function checkPreChatDismissal() { $.ajax({ url: mxchatChat.ajax_url, type: 'POST', data: { action: 'mxchat_check_pre_chat_message_status', _ajax_nonce: mxchatChat.nonce }, success: function(response) { if (response.success && !response.data.dismissed) { $('#pre-chat-message').fadeIn(250); } else { $('#pre-chat-message').hide(); } }, error: function() { console.error('Failed to check pre-chat message dismissal status.'); } }); } // Function to show the chatbot widget function showChatWidget() { // First ensure display is set $('#floating-chatbot-button').css('display', 'flex'); // Then handle the fade $('#floating-chatbot-button').fadeTo(500, 1); // Force visibility $('#floating-chatbot-button').removeClass('hidden'); //console.log('Showing widget'); } // Function to hide the chatbot widget function hideChatWidget() { $('#floating-chatbot-button').css('display', 'none'); $('#floating-chatbot-button').addClass('hidden'); //console.log('Hiding widget'); } function initializeChatVisibility() { //console.log('Initializing chat visibility'); const complianzEnabled = mxchatChat.complianz_toggle === 'on' || mxchatChat.complianz_toggle === '1' || mxchatChat.complianz_toggle === 1; if (complianzEnabled && typeof cmplz_has_consent === "function" && typeof complianz !== 'undefined') { // Initial check checkConsentAndShowChat(); // Listen for consent changes $(document).on('cmplz_status_change', function(event) { //console.log('Status change detected'); checkConsentAndShowChat(); }); } else { // If Complianz is not enabled, always show $('#floating-chatbot-button') .css('display', 'flex') .removeClass('hidden no-consent') .fadeTo(500, 1); // Also check pre-chat message when Complianz is not enabled checkPreChatDismissal(); } } // Initialize when document is ready $(document).ready(function() { //console.log('Document ready - starting initialization'); initializeChatVisibility(); }); function checkConsentAndShowChat() { var consentStatus = cmplz_has_consent('marketing'); var consentType = complianz.consenttype; //console.log('Checking consent:', {status: consentStatus,type: consentType}); let $widget = $('#floating-chatbot-button'); let $chatbot = $('#floating-chatbot'); let $preChat = $('#pre-chat-message'); if (consentStatus === true) { //console.log('Consent granted - showing widget'); $widget .removeClass('no-consent') .css('display', 'flex') .removeClass('hidden') .fadeTo(500, 1); $chatbot.removeClass('no-consent'); // Show pre-chat message if not dismissed checkPreChatDismissal(); } else { //console.log('No consent - hiding widget'); $widget .addClass('no-consent') .fadeTo(500, 0, function() { $(this) .css('display', 'none') .addClass('hidden'); }); $chatbot.addClass('no-consent'); // Hide pre-chat message when no consent $preChat.hide(); } } // Function to dismiss pre-chat message for 24 hours function handlePreChatDismissal() { $('#pre-chat-message').fadeOut(200); $.ajax({ url: mxchatChat.ajax_url, type: 'POST', data: { action: 'mxchat_dismiss_pre_chat_message', _ajax_nonce: mxchatChat.nonce }, success: function() { $('#pre-chat-message').hide(); }, error: function() { console.error('Failed to dismiss pre-chat message.'); } }); } // Handle pre-chat message dismissal on button click $(document).on('click', '.close-pre-chat-message', function(e) { e.stopPropagation(); handlePreChatDismissal(); }); // Toggle chatbot visibility on floating button click $(document).on('click', '#floating-chatbot-button', function() { var chatbot = $('#floating-chatbot'); if (chatbot.hasClass('hidden')) { chatbot.removeClass('hidden').addClass('visible'); $(this).addClass('hidden'); disableScroll(); // Hide the pre-chat message without dismissing it $('#pre-chat-message').fadeOut(250); } else { chatbot.removeClass('visible').addClass('hidden'); $(this).removeClass('hidden'); enableScroll(); // Show the pre-chat message again if it hasn't been dismissed checkPreChatDismissal(); } }); $(document).on('click', '#exit-chat-button', function() { $('#floating-chatbot').addClass('hidden').removeClass('visible'); $('#floating-chatbot-button').removeClass('hidden'); enableScroll(); }); // Close pre-chat message on click $(document).on('click', '.close-pre-chat-message', function(e) { e.stopPropagation(); // Prevent triggering the parent .pre-chat-message click $('#pre-chat-message').fadeOut(200, function() { $(this).remove(); }); }); // Open chatbot when pre-chat message is clicked $(document).on('click', '#pre-chat-message', function() { var chatbot = $('#floating-chatbot'); if (chatbot.hasClass('hidden')) { chatbot.removeClass('hidden').addClass('visible'); $('#floating-chatbot-button').addClass('hidden'); $('#pre-chat-message').fadeOut(250); // Hide pre-chat message disableScroll(); // Disable scroll when chatbot opens } }); // If the chatbot is initially hidden, ensure the button is visible if ($('#floating-chatbot').hasClass('hidden')) { $('#floating-chatbot-button').removeClass('hidden'); } function setFullHeight() { var vh = $(window).innerHeight() * 0.01; $(':root').css('--vh', vh + 'px'); } // Set the height when the page loads $(document).ready(function() { setFullHeight(); }); // Set the height on resize and orientation change events $(window).on('resize orientationchange', function() { setFullHeight(); }); // Now handle the close button to dismiss the pre-chat message for 24 hours var closeButton = document.querySelector('.close-pre-chat-message'); if (closeButton) { closeButton.addEventListener('click', function() { $('#pre-chat-message').fadeOut(200); // Hide the message // Send an AJAX request to set the transient flag for 24 hours $.ajax({ url: mxchatChat.ajax_url, type: 'POST', data: { action: 'mxchat_dismiss_pre_chat_message', _ajax_nonce: mxchatChat.nonce }, success: function() { //console.log('Pre-chat message dismissed for 24 hours.'); // Ensure the message is hidden after dismissal $('#pre-chat-message').hide(); }, error: function() { //console.error('Failed to dismiss pre-chat message.'); } }); }); } // Event listener for Add to Cart button $(document).on('click', '.mxchat-add-to-cart-button', function() { var productId = $(this).data('product-id'); // Add a special prefix to indicate this is from button appendMessage("user", "add to cart"); sendMessageToChatbot("!addtocart"); // Special command to indicate button click }); if (document.getElementById('pdf-upload-btn')) { document.getElementById('pdf-upload-btn').addEventListener('click', function() { document.getElementById('pdf-upload').click(); }); } if (document.getElementById('word-upload-btn')) { document.getElementById('word-upload-btn').addEventListener('click', function() { document.getElementById('word-upload').click(); }); } // PDF file input change handler document.getElementById('pdf-upload').addEventListener('change', async function(e) { const file = e.target.files[0]; if (!file || file.type !== 'application/pdf') { alert('Please select a valid PDF file.'); return; } if (!sessionId) { console.error('No session ID found'); alert('Error: No session ID found'); return; } if (!mxchatChat || !mxchatChat.ajax_url || !mxchatChat.nonce) { console.error('mxchatChat not properly configured:', mxchatChat); alert('Error: Ajax configuration missing'); return; } // Disable buttons and show loading state const uploadBtn = document.getElementById('pdf-upload-btn'); const sendBtn = document.getElementById('send-button'); const originalBtnContent = uploadBtn.innerHTML; try { const formData = new FormData(); formData.append('action', 'mxchat_upload_pdf'); formData.append('pdf_file', file); formData.append('session_id', sessionId); formData.append('nonce', mxchatChat.nonce); uploadBtn.disabled = true; sendBtn.disabled = true; uploadBtn.innerHTML = ` `; const response = await fetch(mxchatChat.ajax_url, { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { // Hide popular questions if they exist const popularQuestionsContainer = document.getElementById('mxchat-popular-questions'); if (popularQuestionsContainer) { popularQuestionsContainer.style.display = 'none'; } // Show the active PDF name showActivePdf(data.data.filename); appendMessage('bot', data.data.message); scrollToBottom(); activePdfFile = data.data.filename; } else { console.error('Upload failed:', data.data); alert('Failed to upload PDF. Please try again.'); } } catch (error) { console.error('Upload error:', error); alert('Error uploading file. Please try again.'); } finally { uploadBtn.disabled = false; sendBtn.disabled = false; uploadBtn.innerHTML = originalBtnContent; this.value = ''; // Reset file input } }); // Word file input change handler document.getElementById('word-upload').addEventListener('change', async function(e) { const file = e.target.files[0]; if (!file || file.type !== 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { alert('Please select a valid Word document (.docx).'); return; } if (!sessionId) { console.error('No session ID found'); alert('Error: No session ID found'); return; } // Disable buttons and show loading state const uploadBtn = document.getElementById('word-upload-btn'); const sendBtn = document.getElementById('send-button'); const originalBtnContent = uploadBtn.innerHTML; try { const formData = new FormData(); formData.append('action', 'mxchat_upload_word'); formData.append('word_file', file); formData.append('session_id', sessionId); formData.append('nonce', mxchatChat.nonce); uploadBtn.disabled = true; sendBtn.disabled = true; uploadBtn.innerHTML = ` `; const response = await fetch(mxchatChat.ajax_url, { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { // Hide popular questions if they exist const popularQuestionsContainer = document.getElementById('mxchat-popular-questions'); if (popularQuestionsContainer) { popularQuestionsContainer.style.display = 'none'; } // Show the active Word document name showActiveWord(data.data.filename); appendMessage('bot', data.data.message); scrollToBottom(); activeWordFile = data.data.filename; } else { console.error('Upload failed:', data.data); alert('Failed to upload Word document. Please try again.'); } } catch (error) { console.error('Upload error:', error); alert('Error uploading file. Please try again.'); } finally { uploadBtn.disabled = false; sendBtn.disabled = false; uploadBtn.innerHTML = originalBtnContent; this.value = ''; // Reset file input } }); // Function to show active PDF name in toolbar function showActivePdf(filename) { const container = document.getElementById('active-pdf-container'); const nameElement = document.getElementById('active-pdf-name'); if (!container || !nameElement) { console.error('PDF container elements not found'); return; } nameElement.textContent = filename; container.style.display = 'flex'; } // Function to show active Word document name in toolbar function showActiveWord(filename) { const container = document.getElementById('active-word-container'); const nameElement = document.getElementById('active-word-name'); if (!container || !nameElement) { console.error('Word document container elements not found'); return; } nameElement.textContent = filename; container.style.display = 'flex'; } // Function to remove active PDF function removeActivePdf() { const container = document.getElementById('active-pdf-container'); const nameElement = document.getElementById('active-pdf-name'); if (!container || !nameElement || !activePdfFile) return; fetch(mxchatChat.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ 'action': 'mxchat_remove_pdf', 'session_id': sessionId, 'nonce': mxchatChat.nonce }) }) .then(response => response.json()) .then(data => { if (data.success) { container.style.display = 'none'; nameElement.textContent = ''; activePdfFile = null; appendMessage('bot', 'PDF removed.'); } }) .catch(error => { console.error('Error removing PDF:', error); }); } // Function to remove active Word document function removeActiveWord() { const container = document.getElementById('active-word-container'); const nameElement = document.getElementById('active-word-name'); if (!container || !nameElement || !activeWordFile) return; fetch(mxchatChat.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ 'action': 'mxchat_remove_word', 'session_id': sessionId, 'nonce': mxchatChat.nonce }) }) .then(response => response.json()) .then(data => { if (data.success) { container.style.display = 'none'; nameElement.textContent = ''; activeWordFile = null; appendMessage('bot', 'Word document removed.'); } }) .catch(error => { console.error('Error removing Word document:', error); }); } // Add remove button click handlers document.getElementById('remove-pdf-btn')?.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); removeActivePdf(); }); document.getElementById('remove-word-btn')?.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); removeActiveWord(); }); // Check initial document status function checkInitialDocumentStatus() { if (!sessionId) return; // Check PDF status fetch(mxchatChat.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ 'action': 'mxchat_check_pdf_status', 'session_id': sessionId, 'nonce': mxchatChat.nonce }) }) .then(response => response.json()) .then(data => { if (data.success && data.data.filename) { showActivePdf(data.data.filename); activePdfFile = data.data.filename; } }) .catch(error => { console.error('Error checking PDF status:', error); }); // Check Word document status fetch(mxchatChat.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ 'action': 'mxchat_check_word_status', 'session_id': sessionId, 'nonce': mxchatChat.nonce }) }) .then(response => response.json()) .then(data => { if (data.success && data.data.filename) { showActiveWord(data.data.filename); activeWordFile = data.data.filename; } }) .catch(error => { console.error('Error checking Word document status:', error); }); } // Apply toolbar settings if (mxchatChat.chat_toolbar_toggle === 'on') { $('.chat-toolbar').show(); } else { $('.chat-toolbar').hide(); } // Initialize on page load document.addEventListener('DOMContentLoaded', function() { checkInitialDocumentStatus(); }); // Style all toolbar elements const toolbarElements = [ '#mxchat-chatbot .toolbar-btn svg', '#mxchat-chatbot .active-pdf-name', '#mxchat-chatbot .active-word-name', '#mxchat-chatbot .remove-pdf-btn svg', '#mxchat-chatbot .remove-word-btn svg' ]; $(toolbarElements.join(', ')).css({ 'fill': toolbarIconColor, 'color': toolbarIconColor }); // Ensure essential elements are defined const emailForm = document.getElementById('email-collection-form'); const emailBlocker = document.getElementById('email-blocker'); const chatbotWrapper = document.getElementById('chat-container'); if (emailForm && emailBlocker && chatbotWrapper) { // Check if email exists for the current session function checkSessionAndEmail() { const sessionId = getChatSession(); //console.log("[DEBUG JS] checkSessionAndEmail -> sessionId:", sessionId); fetch(mxchatChat.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ action: 'mxchat_check_email_provided', session_id: sessionId, nonce: mxchatChat.nonce, }), }) .then((response) => response.json()) .then((data) => { //console.log("[DEBUG JS] mxchat_check_email_provided response:", data); if (data.success) { if (data.data.logged_in) { //console.log("[DEBUG JS] User is logged in. Hiding email form."); emailBlocker.style.display = 'none'; chatbotWrapper.style.display = 'flex'; } else if (data.data.email) { //console.log("[DEBUG JS] Email found for session. Hiding email form."); emailBlocker.style.display = 'none'; chatbotWrapper.style.display = 'flex'; } else { //console.log("[DEBUG JS] No email provided. Showing email form."); emailBlocker.style.display = 'flex'; chatbotWrapper.style.display = 'none'; } } else { //console.log("[DEBUG JS] Error or no data received. Showing email form."); emailBlocker.style.display = 'flex'; chatbotWrapper.style.display = 'none'; } }) .catch((error) => { // console.error("[DEBUG JS] Fetch error -> forcing email form visible:", error); emailBlocker.style.display = 'flex'; chatbotWrapper.style.display = 'none'; }); } // Handle email form submission emailForm.addEventListener('submit', function (event) { event.preventDefault(); const userEmail = document.getElementById('user-email').value; const sessionId = getChatSession(); if (userEmail) { fetch(mxchatChat.ajax_url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ action: 'mxchat_handle_save_email_and_response', email: userEmail, session_id: sessionId, nonce: mxchatChat.nonce, }), }) .then((response) => response.json()) .then((data) => { //console.log('Backend response:', data); if (data.success) { //console.log('Email saved successfully:', userEmail); emailBlocker.style.display = 'none'; chatbotWrapper.style.display = 'flex'; // Optionally handle bot response if (data.message) { appendMessage('bot', data.message); scrollToBottom(); } } else { console.error('Error saving email:', data.message || 'Unknown error'); } }) .catch((error) => { console.error('AJAX error:', error); }); } }); // Check session and email status on page load checkSessionAndEmail(); } else { console.error('Essential elements for email handling are missing.'); } }); // Event listener for copy button document.addEventListener("click", (e) => { if (e.target.classList.contains("mxchat-copy-button")) { const copyButton = e.target; const codeBlock = copyButton .closest(".mxchat-code-block-container") .querySelector(".mxchat-code-block code"); if (codeBlock) { // Preserve formatting using innerText navigator.clipboard.writeText(codeBlock.innerText).then(() => { copyButton.textContent = "Copied!"; copyButton.setAttribute("aria-label", "Copied to clipboard"); setTimeout(() => { copyButton.textContent = "Copy"; copyButton.setAttribute("aria-label", "Copy to clipboard"); }, 2000); }); } } });