PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 1.1.6
MxChat – AI Chatbot & Content Generation for WordPress v1.1.6
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.6, 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 var rateLimitMessage = mxchatChat.rate_limit_message || "Rate limit exceeded. Please try again later.";
13
14 // Function to handle sending a message
15 function sendMessage() {
16 var message = $('#chat-input').val();
17 if (message) {
18 appendMessage("user", message);
19 $('#chat-input').val('');
20
21 // Show typing indicator
22 appendThinkingMessage(); // Use this instead of appendMessage for the typing indicator
23 scrollToBottom(); // Add this line
24
25 callMxChat(message, function(response) {
26 // Replace typing indicator with actual response
27 replaceLastMessage("bot", response);
28 });
29 }
30 }
31
32 // Function to append a thinking message with animation
33 function appendThinkingMessage() {
34 // Remove any existing thinking dots first
35 $('.thinking-dots').remove();
36
37 // Retrieve the bot message font color and background color
38 var botMessageFontColor = mxchatChat.bot_message_font_color;
39 var botMessageBgColor = mxchatChat.bot_message_bg_color;
40
41 var thinkingHtml = '<div class="thinking-dots-container">' +
42 '<div class="thinking-dots">' +
43 '<span class="dot" style="background-color: ' + botMessageFontColor + ';"></span>' +
44 '<span class="dot" style="background-color: ' + botMessageFontColor + ';"></span>' +
45 '<span class="dot" style="background-color: ' + botMessageFontColor + ';"></span>' +
46 '</div>' +
47 '</div>';
48
49 // Append the thinking dots to the chat container (or within the temporary message div)
50 $("#chat-box").append('<div class="bot-message temporary-message" style="background-color: ' + botMessageBgColor + ';">' + thinkingHtml + '</div>');
51 scrollToBottom();
52 }
53
54 // Trigger send button click when "Enter" key is pressed in the input field
55 $('#chat-input').keypress(function(e) {
56 if (e.which == 13) {
57 e.preventDefault();
58 $('#send-button').click();
59 }
60 });
61
62 // Handle send button click
63 $('#send-button').click(function() {
64 sendMessage();
65 });
66
67 // Use the linkTarget in your linkify function
68 function linkify(inputText) {
69 // Convert Markdown-style links to HTML links first
70 var markdownLinkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
71 var replacedText = inputText.replace(markdownLinkPattern, '<a href="$2" target="' + linkTarget + '">$1</a>');
72
73 // URLs starting with http://, https://, or ftp://, but not already inside an <a> tag
74 var urlPattern = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[--A-Z0-9+&@#\/%=~_|])(?![^<]*<\/a>)/gim;
75 replacedText = replacedText.replace(urlPattern, '<a href="$1" target="' + linkTarget + '">$1</a>');
76
77 // URLs starting with "www." not already inside an <a> tag
78 var wwwPattern = /(^|[^\/])(www\.[\S]+(\b|$))(?![^<]*<\/a>)/gim;
79 replacedText = replacedText.replace(wwwPattern, '$1<a href="http://$2" target="' + linkTarget + '">$2</a>');
80
81 return replacedText;
82 }
83
84
85
86 // Updated appendMessage function
87 function appendMessage(sender, message, isTemporary = false) {
88 var messageClass = sender === "user" ? "user-message" : "bot-message";
89 var bgColor = sender === "user" ? mxchatChat.user_message_bg_color : mxchatChat.bot_message_bg_color;
90 var fontColor = sender === "user" ? mxchatChat.user_message_font_color : mxchatChat.bot_message_font_color;
91
92 var messageDiv = $('<div>').addClass(messageClass).css({
93 'background': bgColor,
94 'color': fontColor
95 });
96
97 if (sender === "assistant") {
98 var codeRegex = /```([^]+)```/; // Regex to detect code blocks
99 var match = codeRegex.exec(message);
100 message = linkify(message);
101
102 if (match) {
103 var beforeCode = message.substring(0, match.index);
104 var codePart = match[1]; // Extracted code content
105 var afterCode = message.substring(match.index + match[0].length);
106
107 if (beforeCode.trim()) {
108 messageDiv.append($('<span>').html(convertNewlinesToBreaks(beforeCode)));
109 }
110
111 var codeBlock = $('<pre>').append($('<code>').text(codePart));
112 var copyButton = $('<button>').text('Copy').addClass('copy-btn');
113 messageDiv.append(codeBlock).append(copyButton);
114
115 copyButton.on('click', function() {
116 copyToClipboard(codePart);
117 alert('Code copied to clipboard!');
118 });
119
120 if (afterCode.trim()) {
121 messageDiv.append($('<span>').html(convertNewlinesToBreaks(afterCode)));
122 }
123 } else {
124 messageDiv.html(formatBoldText(convertNewlinesToBreaks(message)));
125 }
126 } else {
127 messageDiv.html(formatBoldText(convertNewlinesToBreaks(message)));
128 }
129
130 if (isTemporary) {
131 messageDiv.addClass('temporary-message'); // Add a class for temporary messages
132 }
133
134 messageDiv.hide().appendTo('#chat-box').fadeIn(300); // Fade in the new message
135 }
136
137 // Function to replace the last message in the chat
138 function replaceLastMessage(sender, newMessage) {
139 var messageClass = sender === "user" ? "user-message" : "bot-message";
140 var lastMessageDiv = $('#chat-box').find('.' + messageClass + '.temporary-message').last();
141
142 // Check if the new message is the rate limit message before replacing
143 if (newMessage === mxchatChat.rate_limit_message) {
144 // Append rate limit message without replacing anything
145 appendMessage("bot", newMessage);
146 return; // Exit the function to prevent replacing the rate limit message
147 }
148 if (lastMessageDiv.length) {
149 lastMessageDiv.fadeOut(200, function() {
150 // Replace the content and fade in
151 $(this).html(newMessage).removeClass('temporary-message').fadeIn(200);
152 });
153 } else {
154 appendMessage(sender, newMessage);
155 }
156 scrollToBottom();
157 }
158
159 function scrollToBottom() {
160 var chatBox = $('#chat-box');
161 var newMessage = chatBox.children().last();
162
163 // Calculate the position to scroll to
164 // which is the top of the last message
165 var positionToScroll = newMessage.position().top + chatBox.scrollTop();
166
167 // Animate the scrolling to the calculated position
168 chatBox.animate({
169 scrollTop: positionToScroll
170 }, 500);
171 }
172
173 // Function to format text with **bold** inside double asterisks
174 function formatBoldText(text) {
175 return text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
176 }
177
178 // Function to convert newline characters to HTML line breaks and handle paragraph spacing
179 function convertNewlinesToBreaks(text) {
180 var lines = text.split('\n');
181 var formattedText = '';
182
183 for (var i = 0; i < lines.length; i++) {
184 formattedText += lines[i] + '<br>';
185 }
186
187 return formattedText;
188 }
189
190 // Copy to clipboard function
191 // Function to copy text to clipboard
192 function copyToClipboard(text) {
193 var tempInput = $('<input>');
194 $('body').append(tempInput);
195 tempInput.val(text).select();
196 document.execCommand('copy');
197 tempInput.remove();
198 }
199
200
201 function callMxChat(message, callback) {
202 $.ajax({
203 url: mxchatChat.ajax_url,
204 type: 'POST',
205 dataType: 'json',
206 data: {
207 action: 'mxchat_handle_chat_request',
208 message: message,
209 nonce: mxchatChat.nonce
210 },
211 success: function(response) {
212 removeThinkingDots();
213
214 if (response.success === false && response.data && response.data.message) {
215 // If the response is an error with a message, display that message
216 appendMessage("bot", response.data.message);
217 } else if (response.redirect_url) {
218 // Redirect the user to the checkout page if requested
219 window.location.href = response.redirect_url;
220 } else if (response.message && typeof response.message === 'string') {
221 // Handle the valid response
222 var botMessage = linkify(response.message);
223 botMessage = convertNewlinesToBreaks(botMessage);
224 callback(botMessage);
225 } else {
226 // Handle unexpected formats
227 appendMessage("bot", "An unexpected response was received. Please try again.");
228 }
229 },
230 error: function(jqXHR, textStatus, errorThrown) {
231 removeThinkingDots();
232 appendMessage("bot", "Error communicating with the server.");
233 }
234 });
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