PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 1.1.2
MxChat – AI Chatbot & Content Generation for WordPress v1.1.2
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
mxchat-basic / js / chat-script.js

chat-script.js in MxChat – AI Chatbot & Content Generation for WordPress 1.1.2, at js/chat-script.js

395 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(document).ready(function($) {
2 // Check if floating chatbot button exists
3 var floatingButton = $('#floating-chatbot-button');
4
5 // Retrieve color settings from PHP
6 var userMessageBgColor = mxchatChat.user_message_bg_color;
7 var userMessageFontColor = mxchatChat.user_message_font_color;
8 var botMessageBgColor = mxchatChat.bot_message_bg_color;
9 var botMessageFontColor = mxchatChat.bot_message_font_color;
10 // Retrieve link target setting (passed from PHP through wp_localize_script)
11 var linkTarget = mxchatChat.link_target === 'on' ? '_blank' : '_self'; // Explicitly check for 'on' or 'off'
12
13 // Function to handle sending a message
14 function sendMessage() {
15 var message = $('#chat-input').val();
16 if (message) {
17 appendMessage("user", message);
18 $('#chat-input').val('');
19
20 // Show typing indicator
21 appendThinkingMessage(); // Use this instead of appendMessage for the typing indicator
22 scrollToBottom(); // Add this line
23
24 callMxChat(message, function(response) {
25 // Replace typing indicator with actual response
26 replaceLastMessage("bot", response);
27 });
28 }
29 }
30
31 // Function to append a thinking message with animation
32 function appendThinkingMessage() {
33 // Remove any existing thinking dots first
34 $('.thinking-dots').remove();
35
36 // Retrieve the bot message font color and background color
37 var botMessageFontColor = mxchatChat.bot_message_font_color;
38 var botMessageBgColor = mxchatChat.bot_message_bg_color;
39
40 var thinkingHtml = '<div class="thinking-dots-container">' +
41 '<div class="thinking-dots">' +
42 '<span class="dot" style="background-color: ' + botMessageFontColor + ';"></span>' +
43 '<span class="dot" style="background-color: ' + botMessageFontColor + ';"></span>' +
44 '<span class="dot" style="background-color: ' + botMessageFontColor + ';"></span>' +
45 '</div>' +
46 '</div>';
47
48 // Append the thinking dots to the chat container (or within the temporary message div)
49 $("#chat-box").append('<div class="bot-message temporary-message" style="background-color: ' + botMessageBgColor + ';">' + thinkingHtml + '</div>');
50 scrollToBottom();
51 }
52
53 // Trigger send button click when "Enter" key is pressed in the input field
54 $('#chat-input').keypress(function(e) {
55 if (e.which == 13) {
56 e.preventDefault();
57 $('#send-button').click();
58 }
59 });
60
61 // Handle send button click
62 $('#send-button').click(function() {
63 sendMessage();
64 });
65
66 // Use the linkTarget in your linkify function
67 function linkify(inputText) {
68 // Convert Markdown-style links to HTML links first
69 var markdownLinkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
70 var replacedText = inputText.replace(markdownLinkPattern, '<a href="$2" target="' + linkTarget + '">$1</a>');
71
72 // URLs starting with http://, https://, or ftp://, but not already inside an <a> tag
73 var urlPattern = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[--A-Z0-9+&@#\/%=~_|])(?![^<]*<\/a>)/gim;
74 replacedText = replacedText.replace(urlPattern, '<a href="$1" target="' + linkTarget + '">$1</a>');
75
76 // URLs starting with "www." not already inside an <a> tag
77 var wwwPattern = /(^|[^\/])(www\.[\S]+(\b|$))(?![^<]*<\/a>)/gim;
78 replacedText = replacedText.replace(wwwPattern, '$1<a href="http://$2" target="' + linkTarget + '">$2</a>');
79
80 return replacedText;
81 }
82
83
84
85 // Updated appendMessage function
86 function appendMessage(sender, message, isTemporary = false) {
87 var messageClass = sender === "user" ? "user-message" : "bot-message";
88 var bgColor = sender === "user" ? mxchatChat.user_message_bg_color : mxchatChat.bot_message_bg_color;
89 var fontColor = sender === "user" ? mxchatChat.user_message_font_color : mxchatChat.bot_message_font_color;
90
91 var messageDiv = $('<div>').addClass(messageClass).css({
92 'background': bgColor,
93 'color': fontColor
94 });
95
96 if (sender === "assistant") {
97 var codeRegex = /```([^]+)```/; // Regex to detect code blocks
98 var match = codeRegex.exec(message);
99 message = linkify(message);
100
101 if (match) {
102 var beforeCode = message.substring(0, match.index);
103 var codePart = match[1]; // Extracted code content
104 var afterCode = message.substring(match.index + match[0].length);
105
106 if (beforeCode.trim()) {
107 messageDiv.append($('<span>').html(convertNewlinesToBreaks(beforeCode)));
108 }
109
110 var codeBlock = $('<pre>').append($('<code>').text(codePart));
111 var copyButton = $('<button>').text('Copy').addClass('copy-btn');
112 messageDiv.append(codeBlock).append(copyButton);
113
114 copyButton.on('click', function() {
115 copyToClipboard(codePart);
116 alert('Code copied to clipboard!');
117 });
118
119 if (afterCode.trim()) {
120 messageDiv.append($('<span>').html(convertNewlinesToBreaks(afterCode)));
121 }
122 } else {
123 messageDiv.html(formatBoldText(convertNewlinesToBreaks(message)));
124 }
125 } else {
126 messageDiv.html(formatBoldText(convertNewlinesToBreaks(message)));
127 }
128
129 if (isTemporary) {
130 messageDiv.addClass('temporary-message'); // Add a class for temporary messages
131 }
132
133 messageDiv.hide().appendTo('#chat-box').fadeIn(300); // Fade in the new message
134 }
135
136 // Function to replace the last message in the chat
137 function replaceLastMessage(sender, newMessage) {
138 var messageClass = sender === "user" ? "user-message" : "bot-message";
139 var lastMessageDiv = $('#chat-box').find('.' + messageClass + '.temporary-message').last();
140
141 // Check if the new message is the rate limit message before replacing
142 if (newMessage === mxchatChat.rate_limit_message) {
143 // Append rate limit message without replacing anything
144 appendMessage("bot", newMessage);
145 return; // Exit the function to prevent replacing the rate limit message
146 }
147 if (lastMessageDiv.length) {
148 lastMessageDiv.fadeOut(200, function() {
149 // Replace the content and fade in
150 $(this).html(newMessage).removeClass('temporary-message').fadeIn(200);
151 });
152 } else {
153 appendMessage(sender, newMessage);
154 }
155 scrollToBottom();
156 }
157
158 function scrollToBottom() {
159 var chatBox = $('#chat-box');
160 var newMessage = chatBox.children().last();
161
162 // Calculate the position to scroll to
163 // which is the top of the last message
164 var positionToScroll = newMessage.position().top + chatBox.scrollTop();
165
166 // Animate the scrolling to the calculated position
167 chatBox.animate({
168 scrollTop: positionToScroll
169 }, 500);
170 }
171
172 // Function to format text with **bold** inside double asterisks
173 function formatBoldText(text) {
174 return text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
175 }
176
177 // Function to convert newline characters to HTML line breaks and handle paragraph spacing
178 function convertNewlinesToBreaks(text) {
179 var lines = text.split('\n');
180 var formattedText = '';
181
182 for (var i = 0; i < lines.length; i++) {
183 formattedText += lines[i] + '<br>';
184 }
185
186 return formattedText;
187 }
188
189 // Copy to clipboard function
190 // Function to copy text to clipboard
191 function copyToClipboard(text) {
192 var tempInput = $('<input>');
193 $('body').append(tempInput);
194 tempInput.val(text).select();
195 document.execCommand('copy');
196 tempInput.remove();
197 }
198
199 // Retrieve the custom rate limit message
200 var rateLimitMessage = mxchatChat.rate_limit_message || "Rate limit exceeded. Please try again later.";
201
202 // Call MxChat API
203 function callMxChat(message, callback) {
204 $.ajax({
205 url: mxchatChat.ajax_url,
206 type: 'POST',
207 dataType: 'json',
208 data: {
209 action: 'mxchat_handle_chat_request',
210 message: message,
211 nonce: mxchatChat.nonce
212 },
213 success: function(response) {
214 removeThinkingDots();
215
216 if (response.redirect_url) {
217 // Redirect the user to the checkout page if requested
218 window.location.href = response.redirect_url;
219 } else if (response.message && typeof response.message === 'string') {
220 // Handle the valid response
221 var botMessage = linkify(response.message);
222 botMessage = convertNewlinesToBreaks(botMessage);
223 callback(botMessage);
224 } else if (response.error) {
225 // Handle errors returned by the server
226 appendMessage("bot", response.error.message || "An unexpected error occurred.");
227 } else {
228 // Handle unexpected formats
229 appendMessage("bot", "An unexpected response was received. Please try again.");
230 }
231 },
232 error: function(jqXHR, textStatus, errorThrown) {
233 removeThinkingDots();
234 appendMessage("bot", "Error communicating with the server.");
235 }
236 });
237 }
238
239
240
241 // Helper function to check if a string is an image HTML
242 function isImageHtml(str) {
243 return str.startsWith('<img') && str.endsWith('>');
244 }
245
246 // Function to remove thinking dots
247 function removeThinkingDots() {
248 $('.thinking-dots').closest('.temporary-message').remove();
249 }
250
251 function isMobile() {
252 // This can be a simple check, or more sophisticated detection of mobile devices
253 return window.innerWidth <= 768; // Example threshold for mobile devices
254 }
255
256 function disableScroll() {
257 if (isMobile()) {
258 $('body').css('overflow', 'hidden');
259 }
260 }
261
262 function enableScroll() {
263 if (isMobile()) {
264 $('body').css('overflow', '');
265 }
266 }
267
268 // Function to show the chatbot widget (moved outside the Complianz logic)
269 function showChatWidget() {
270 setTimeout(function() {
271 $('#floating-chatbot-button').css('display', 'flex').fadeTo(500, 1);
272 $('#pre-chat-message').fadeIn(500);
273 }, 250);
274 }
275
276 // Function to hide the chatbot widget
277 function hideChatWidget() {
278 $('#floating-chatbot-button').css('display', 'none');
279 $('#pre-chat-message').fadeOut(250);
280 }
281
282 var applyComplianzLogic = mxchatChat.complianz_toggle;
283
284 if (applyComplianzLogic) {
285 // Apply the Complianz logic for showing/hiding the chatbot based on consent
286 function checkConsentAndShowChat() {
287 var consentStatus = typeof cmplz_has_consent === "function" && cmplz_has_consent('marketing');
288 var consentType = typeof complianz !== 'undefined' ? complianz.consenttype : null;
289 console.log('cmplz_has_consent("marketing"):', consentStatus);
290 console.log('Complianz consent type:', consentType);
291
292 if (consentType === 'optin' && !consentStatus) {
293 hideChatWidget();
294 } else if (consentType === 'optout' && !consentStatus) {
295 hideChatWidget();
296 } else {
297 showChatWidget();
298 }
299 }
300
301 checkConsentAndShowChat();
302
303 $(document).on('cmplz_status_change', function(event, category) {
304 console.log('Consent status changed for category:', category);
305 checkConsentAndShowChat();
306 });
307 } else {
308 // Show the chatbot by default if Complianz logic is not applied
309 showChatWidget();
310 }
311
312 // Toggle chatbot visibility on floating button click
313 $(document).on('click', '#floating-chatbot-button', function() {
314 var chatbot = $('#floating-chatbot');
315 if (chatbot.hasClass('hidden')) {
316 chatbot.removeClass('hidden').addClass('visible');
317 $(this).addClass('hidden');
318 $('#pre-chat-message').fadeOut(250); // Hide pre-chat message
319 disableScroll(); // Disable scroll when chatbot opens
320 } else {
321 chatbot.removeClass('visible').addClass('hidden');
322 $(this).removeClass('hidden');
323 $('#pre-chat-message').fadeIn(250); // Show pre-chat message
324 enableScroll(); // Enable scroll when chatbot closes
325 }
326 });
327
328 // Close button click handler for chat widget
329 $(document).on('click', '#exit-chat-button', function() {
330 $('#floating-chatbot').addClass('hidden').removeClass('visible');
331 $('#floating-chatbot-button').removeClass('hidden');
332 $('#pre-chat-message').fadeIn(250); // Show pre-chat message
333 enableScroll(); // Enable scroll when chatbot is minimized
334 });
335
336 // Close pre-chat message on click
337 $(document).on('click', '.close-pre-chat-message', function(e) {
338 e.stopPropagation(); // Prevent triggering the parent .pre-chat-message click
339 $('#pre-chat-message').fadeOut(200, function() {
340 $(this).remove();
341 });
342 });
343
344 // Open chatbot when pre-chat message is clicked
345 $(document).on('click', '#pre-chat-message', function() {
346 var chatbot = $('#floating-chatbot');
347 if (chatbot.hasClass('hidden')) {
348 chatbot.removeClass('hidden').addClass('visible');
349 $('#floating-chatbot-button').addClass('hidden');
350 $('#pre-chat-message').fadeOut(250); // Hide pre-chat message
351 disableScroll(); // Disable scroll when chatbot opens
352 }
353 });
354
355 // If the chatbot is initially hidden, ensure the button is visible
356 if ($('#floating-chatbot').hasClass('hidden')) {
357 $('#floating-chatbot-button').removeClass('hidden');
358 }
359
360 function setFullHeight() {
361 var vh = $(window).innerHeight() * 0.01;
362 $(':root').css('--vh', vh + 'px');
363 }
364
365 // Set the height when the page loads
366 $(document).ready(function() {
367 setFullHeight();
368 });
369
370 // Set the height on resize and orientation change events
371 $(window).on('resize orientationchange', function() {
372 setFullHeight();
373 });
374
375
376
377
378 var preChatMessage = document.getElementById('pre-chat-message');
379 var closeButton = document.querySelector('.close-pre-chat-message');
380
381 if (closeButton) {
382 closeButton.addEventListener('click', function() {
383 preChatMessage.style.display = 'none';
384
385 // Send an AJAX request to set the transient flag
386 var xhr = new XMLHttpRequest();
387 xhr.open('POST', mxchatChat.ajax_url, true);
388 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
389 xhr.send('action=mxchat_dismiss_pre_chat_message&_ajax_nonce=' + mxchatChat.nonce);
390 });
391 }
392
393
394 });
395