PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 1.0.10
MxChat – AI Chatbot & Content Generation for WordPress v1.0.10
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.0.10, at js/chat-script.js

362 lines 14.3 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 //console.log("API Response:", response);
215 removeThinkingDots();
216
217 if (response.message && typeof response.message === 'string') {
218 // Handle the valid response
219 var botMessage = linkify(response.message);
220 botMessage = convertNewlinesToBreaks(botMessage);
221 callback(botMessage);
222 } else if (response.error) {
223 // Handle errors returned by the server
224 appendMessage("bot", response.error.message || "An unexpected error occurred.");
225 } else {
226 // Handle unexpected formats
227 //console.log("Unexpected API response format:", response);
228 appendMessage("bot", "An unexpected response was received. Please try again.");
229 }
230 },
231 error: function(jqXHR, textStatus, errorThrown) {
232 //console.error("AJAX Error:", textStatus, errorThrown);
233 removeThinkingDots();
234 appendMessage("bot", "Error communicating with the server.");
235 }
236 });
237 }
238
239
240 // Helper function to check if a string is an image HTML
241 function isImageHtml(str) {
242 return str.startsWith('<img') && str.endsWith('>');
243 }
244
245 // Function to remove thinking dots
246 function removeThinkingDots() {
247 $('.thinking-dots').closest('.temporary-message').remove();
248 }
249
250 function isMobile() {
251 // This can be a simple check, or more sophisticated detection of mobile devices
252 return window.innerWidth <= 768; // Example threshold for mobile devices
253 }
254
255 function disableScroll() {
256 if (isMobile()) {
257 $('body').css('overflow', 'hidden');
258 }
259 }
260
261 function enableScroll() {
262 if (isMobile()) {
263 $('body').css('overflow', '');
264 }
265 }
266
267 // Show and fade in the chat widget after a delay
268 function showAndFadeInChatWidget() {
269 // Wait for 5 seconds before showing and starting the fade-in
270 setTimeout(function() {
271 $('#floating-chatbot-button').css('display', 'flex').fadeTo(500, 1);
272 $('#pre-chat-message').fadeIn(500); // Fade in the pre-chat message
273 }, 250);
274 }
275
276 // Call the function when the document is ready
277 showAndFadeInChatWidget();
278
279 // Toggle chatbot visibility on floating button click
280 $(document).on('click', '#floating-chatbot-button', function() {
281 var chatbot = $('#floating-chatbot');
282 if (chatbot.hasClass('hidden')) {
283 chatbot.removeClass('hidden').addClass('visible');
284 $(this).addClass('hidden');
285 $('#pre-chat-message').fadeOut(250); // Hide pre-chat message
286 disableScroll(); // Disable scroll when chatbot opens
287 } else {
288 chatbot.removeClass('visible').addClass('hidden');
289 $(this).removeClass('hidden');
290 $('#pre-chat-message').fadeIn(250); // Show pre-chat message
291 enableScroll(); // Enable scroll when chatbot closes
292 }
293 });
294
295 // Close button click handler for chat widget
296 $(document).on('click', '#exit-chat-button', function() {
297 $('#floating-chatbot').addClass('hidden').removeClass('visible');
298 $('#floating-chatbot-button').removeClass('hidden');
299 $('#pre-chat-message').fadeIn(250); // Show pre-chat message
300 enableScroll(); // Enable scroll when chatbot is minimized
301 });
302
303 // Close pre-chat message on click
304 $(document).on('click', '.close-pre-chat-message', function(e) {
305 e.stopPropagation(); // Prevent triggering the parent .pre-chat-message click
306 $('#pre-chat-message').fadeOut(200, function() {
307 $(this).remove();
308 });
309 });
310
311 // Open chatbot when pre-chat message is clicked
312 $(document).on('click', '#pre-chat-message', function() {
313 var chatbot = $('#floating-chatbot');
314 if (chatbot.hasClass('hidden')) {
315 chatbot.removeClass('hidden').addClass('visible');
316 $('#floating-chatbot-button').addClass('hidden');
317 $('#pre-chat-message').fadeOut(250); // Hide pre-chat message
318 disableScroll(); // Disable scroll when chatbot opens
319 }
320 });
321
322 // If the chatbot is initially hidden, ensure the button is visible
323 if ($('#floating-chatbot').hasClass('hidden')) {
324 $('#floating-chatbot-button').removeClass('hidden');
325 }
326
327 function setFullHeight() {
328 var vh = $(window).innerHeight() * 0.01;
329 $(':root').css('--vh', vh + 'px');
330 }
331
332 // Set the height when the page loads
333 $(document).ready(function() {
334 setFullHeight();
335 });
336
337 // Set the height on resize and orientation change events
338 $(window).on('resize orientationchange', function() {
339 setFullHeight();
340 });
341
342
343
344
345 var preChatMessage = document.getElementById('pre-chat-message');
346 var closeButton = document.querySelector('.close-pre-chat-message');
347
348 if (closeButton) {
349 closeButton.addEventListener('click', function() {
350 preChatMessage.style.display = 'none';
351
352 // Send an AJAX request to set the transient flag
353 var xhr = new XMLHttpRequest();
354 xhr.open('POST', mxchatChat.ajax_url, true);
355 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
356 xhr.send('action=mxchat_dismiss_pre_chat_message&_ajax_nonce=' + mxchatChat.nonce);
357 });
358 }
359
360
361 });
362