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

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