PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 2.1.1
MxChat – AI Chatbot & Content Generation for WordPress v2.1.1
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
← All changes | js/mxchat-admin.js +157 -57 2.0.62.1.1 View file →
@@ -169,9 +169,9 @@
169 169
170 170 // Initialize color pickers with debouncing
171 171 $autosaveSections.find('.my-color-field').each(function() {
172 172 const $colorField = $(this);
173 -
173 +
174 174 $(this).wpColorPicker({
175 175 change: useDebounce(function(event, ui) {
176 176 // Safety check - ensure we have a valid field and value
177 177 if (!$colorField || !$colorField.val()) {
@@ -240,9 +240,9 @@
240 240 });
241 241 });
242 242
243 243 // Reinitialize color pickers when switching tabs
244 - $('.mxchat-nav-tab').on('click.mxchat', function() {
244 + $('.mxchat-tab-button').on('click.mxchat', function() {
245 245 setTimeout(function() {
246 246 $('.my-color-field:visible').wpColorPicker('close');
247 247 }, 100);
248 248 });
@@ -250,41 +250,36 @@
250 250
251 251 // Initialize tabs system
252 252 function initTabs() {
253 253 // Remove any existing handlers first
254 - $('.mxchat-nav-tab').off('click.mxchat');
255 -
254 + $('.mxchat-tab-button').off('click.mxchat');
255 +
256 256 // Add new click handlers
257 - $('.mxchat-nav-tab').on('click.mxchat', function(e) {
257 + $('.mxchat-tab-button').on('click.mxchat', function(e) {
258 258 e.preventDefault();
259 259 e.stopPropagation();
260 -
260 +
261 261 var $this = $(this);
262 -
263 - // Get tab ID - try href first, fallback to data-tab, then to default
264 - var tabId = $this.attr('href');
265 - if (tabId) {
266 - tabId = tabId.replace('#', '');
267 - } else {
268 - tabId = $this.data('tab') || 'chatbot';
269 - }
270 -
262 +
263 + // Get tab ID from data-tab attribute
264 + var tabId = $this.data('tab') || 'chatbot';
265 +
271 266 // Safety check for empty tabId
272 267 if (!tabId) {
273 268 console.warn('No tab identifier found');
274 269 return;
275 270 }
276 -
277 - // Update tabs
278 - $('.mxchat-nav-tab').removeClass('mxchat-nav-tab-active');
279 - $this.addClass('mxchat-nav-tab-active');
280 -
271 +
272 + // Update tab buttons
273 + $('.mxchat-tab-button').removeClass('active');
274 + $this.addClass('active');
275 +
281 276 // Update content areas - with safety check
282 - $('.mxchat-tab-content').removeClass('active').hide();
277 + $('.mxchat-tab-content').removeClass('active');
283 278 var $targetTab = $('#' + tabId);
284 279 if ($targetTab.length) {
285 - $targetTab.addClass('active').show();
286 -
280 + $targetTab.addClass('active');
281 +
287 282 // Store active tab
288 283 try {
289 284 localStorage.setItem('mxchat_active_tab', tabId);
290 285 } catch (e) {
@@ -294,25 +289,25 @@
294 289 console.warn('Tab content #' + tabId + ' not found');
295 290 }
296 291 });
297 292 }
298 -
293 +
299 294 // Initialize tabs and handle events
300 295 initTabs();
301 296 $(document).on('widget-added widget-updated postbox-toggled', initTabs);
302 -
297 +
303 298 // Activate initial tab
304 299 try {
305 300 var savedTab = localStorage.getItem('mxchat_active_tab');
306 301 if (savedTab && $('#' + savedTab).length > 0) {
307 - $('.mxchat-nav-tab[href="#' + savedTab + '"]').trigger('click.mxchat');
302 + $('.mxchat-tab-button[data-tab="' + savedTab + '"]').trigger('click.mxchat');
308 303 } else {
309 - $('.mxchat-nav-tab').first().trigger('click.mxchat');
304 + $('.mxchat-tab-button').first().trigger('click.mxchat');
310 305 }
311 306 } catch (e) {
312 - $('.mxchat-nav-tab').first().trigger('click.mxchat');
307 + $('.mxchat-tab-button').first().trigger('click.mxchat');
313 308 }
314 -
309 +
315 310 // Attach edit modal event handler
316 311 $(document).on('click', '.mxchat-edit-button', function() {
317 312 const intentId = $(this).data('intent-id');
318 313 const phrases = $(this).data('phrases');
@@ -317,9 +312,9 @@
317 312 const intentId = $(this).data('intent-id');
318 313 const phrases = $(this).data('phrases');
319 314 mxchatOpenEditModal(intentId, phrases);
320 315 });
321 -
316 +
322 317 // Toggle visibility handlers
323 318 function toggleVisibility(selector) {
324 319 $(selector).on('click', function() {
325 320 var inputField = $(this).prev('input');
@@ -331,9 +326,9 @@
331 326 $(this).text('Show');
332 327 }
333 328 });
334 329 }
335 -
330 +
336 331 // Initialize all toggle visibility buttons
337 332 [
338 333 '#toggleApiKeyVisibility',
339 334 '#toggleWooCommerceSecretVisibility',
@@ -346,9 +341,116 @@
346 341 '#toggleSecretKeyVisibility',
347 342 '#toggleBotTokenVisibility',
348 343 '#toggleDeepSeekApiKeyVisibility'
349 344 ].forEach(toggleVisibility);
350 -
345 +
346 + // Handle API key visibility based on model selection
347 + // Handle API key visibility based on model selection
348 +function setupAPIKeyVisibility() {
349 + // Cache the selectors
350 + const $chatModelSelect = $('#model');
351 + const $embeddingModelSelect = $('#embedding_model');
352 +
353 + // First, locate and mark the API key rows
354 + setupAPIKeyRows();
355 +
356 + // Initial setup based on current selections
357 + updateApiKeyVisibility();
358 +
359 + // Listen for changes to the model selectors
360 + $chatModelSelect.on('change', updateApiKeyVisibility);
361 + $embeddingModelSelect.on('change', updateApiKeyVisibility);
362 +
363 + /**
364 + * Locate and mark rows that contain API key fields
365 + */
366 + function setupAPIKeyRows() {
367 + // Find key rows by their field IDs
368 + const providerMap = {
369 + 'api_key': 'openai',
370 + 'xai_api_key': 'xai',
371 + 'claude_api_key': 'claude',
372 + 'deepseek_api_key': 'deepseek',
373 + 'voyage_api_key': 'voyage'
374 + };
375 +
376 + $.each(providerMap, function(fieldId, provider) {
377 + const $field = $('#' + fieldId);
378 + if ($field.length) {
379 + const $row = $field.closest('tr');
380 + $row.addClass('mxchat-setting-row');
381 + $row.attr('data-provider', provider);
382 + }
383 + });
384 + }
385 +
386 + /**
387 + * Updates the visibility of API key fields based on current model selections
388 + */
389 + function updateApiKeyVisibility() {
390 + const chatModel = $chatModelSelect.val();
391 + const embeddingModel = $embeddingModelSelect.val();
392 +
393 + // Determine which providers are needed
394 + const isOpenAIChat = chatModel && chatModel.startsWith('gpt-');
395 + const isXAI = chatModel && chatModel.startsWith('grok-');
396 + const isClaude = chatModel && chatModel.startsWith('claude-');
397 + const isDeepSeek = chatModel && chatModel.startsWith('deepseek-');
398 +
399 + const isOpenAIEmbedding = embeddingModel && embeddingModel.startsWith('text-embedding-');
400 + const isVoyage = embeddingModel && embeddingModel.startsWith('voyage-');
401 +
402 + // Update API key visibility for each provider
403 + updateWrapperVisibility('openai', isOpenAIChat || isOpenAIEmbedding);
404 + updateWrapperVisibility('xai', isXAI);
405 + updateWrapperVisibility('claude', isClaude);
406 + updateWrapperVisibility('deepseek', isDeepSeek);
407 + updateWrapperVisibility('voyage', isVoyage);
408 +
409 + // Update provider-specific notices for OpenAI
410 + if (isOpenAIChat && isOpenAIEmbedding) {
411 + $('div[data-provider="openai"] .api-key-notice').text(
412 + 'Required for your selected chat model and embedding model. Important: You must add credits before use.'
413 + );
414 + } else if (isOpenAIChat) {
415 + $('div[data-provider="openai"] .api-key-notice').text(
416 + 'Required for your selected chat model. Important: You must add credits before use.'
417 + );
418 + } else if (isOpenAIEmbedding) {
419 + $('div[data-provider="openai"] .api-key-notice').text(
420 + 'Required for your selected embedding model. Important: You must add credits before use.'
421 + );
422 + }
423 + }
424 +
425 + /**
426 + * Updates visibility of a specific provider's API key wrapper
427 + */
428 + function updateWrapperVisibility(provider, isVisible) {
429 + const $row = $('tr.mxchat-setting-row[data-provider="' + provider + '"]');
430 +
431 + if (!$row.length) {
432 + console.warn('API key row not found for provider: ' + provider);
433 + return;
434 + }
435 +
436 + if (isVisible) {
437 + $row.show();
438 + if (!$row.hasClass('highlighted')) {
439 + $row.addClass('highlighted');
440 + setTimeout(() => {
441 + $row.removeClass('highlighted');
442 + }, 1500);
443 + }
444 + } else {
445 + $row.hide();
446 + }
447 + }
448 +}
449 +
450 + // Initialize API key visibility
451 + setupAPIKeyVisibility();
452 +
351 453 // Add Intent Form Submission
352 454 $('#mxchat-add-intent-form').on('submit', function(event) {
353 455 $('#mxchat-intent-loading').show();
354 456 $('#mxchat-intent-loading-text').show();
@@ -353,9 +455,9 @@
353 455 $('#mxchat-intent-loading').show();
354 456 $('#mxchat-intent-loading-text').show();
355 457 $(this).find('button[type="submit"]').hide();
356 458 });
357 -
459 +
358 460 // Inline Edit Functionality
359 461 $('.edit-button').on('click', function() {
360 462 var row = $(this).closest('tr');
361 463 row.find('.content-view, .url-view').hide();
@@ -362,9 +464,9 @@
362 464 row.find('.content-edit, .url-edit').show();
363 465 row.find('.edit-button').hide();
364 466 row.find('.save-button').show();
365 467 });
366 -
468 +
367 469 // Save button handler
368 470 $('.save-button').on('click', function() {
369 471 var button = $(this);
370 472 var row = button.closest('tr');
@@ -370,12 +472,12 @@
370 472 var row = button.closest('tr');
371 473 var id = button.data('id');
372 474 var newContent = row.find('.content-edit').val();
373 475 var newUrl = row.find('.url-edit').val();
374 -
476 +
375 477 button.prop('disabled', true);
376 478 button.text('Saving...');
377 -
479 +
378 480 $.ajax({
379 481 url: mxchatAdmin.ajax_url,
380 482 type: 'POST',
381 483 data: {
@@ -387,9 +489,9 @@
387 489 },
388 490 success: function(response) {
389 491 button.prop('disabled', false);
390 492 button.text('Save');
391 -
493 +
392 494 if (response.success) {
393 495 row.find('.content-view').html(newContent.replace(/\n/g, "<br>"));
394 496 if (newUrl) {
395 497 row.find('.url-view').html('<a href="' + newUrl + '" target="_blank">' + newUrl + '</a>');
@@ -395,9 +497,9 @@
395 497 row.find('.url-view').html('<a href="' + newUrl + '" target="_blank">' + newUrl + '</a>');
396 498 } else {
397 499 row.find('.url-view').html('N/A');
398 500 }
399 -
501 +
400 502 row.find('.content-edit, .url-edit').hide();
401 503 row.find('.content-view, .url-view').show();
402 504 row.find('.save-button').hide();
403 505 row.find('.edit-button').show();
@@ -411,15 +513,15 @@
411 513 alert('An error occurred while saving.');
412 514 }
413 515 });
414 516 });
415 -
517 +
416 518 // Activation handling
417 519 const form = $('#mxchat-activation-form');
418 520 const spinner = $('#mxchat-activation-spinner');
419 521 const submitButton = $('#activate_license_button');
420 522 const licenseStatus = $('#mxchat-license-status');
421 -
523 +
422 524 if (form.length && licenseStatus.length && submitButton.length) {
423 525 function handleActivationResponse(response) {
424 526 spinner.hide();
425 527 if (response.success) {
@@ -431,14 +533,14 @@
431 533 alert(response.data || 'Activation failed. Please check your input.');
432 534 submitButton.prop('disabled', false);
433 535 }
434 536 }
435 -
537 +
436 538 form.on('submit', function(event) {
437 539 event.preventDefault();
438 540 spinner.show();
439 541 submitButton.prop('disabled', true);
440 -
542 +
441 543 var formData = {
442 544 action: 'mxchat_activate_license',
443 545 mxchat_pro_email: $('#mxchat_pro_email').val(),
444 546 mxchat_activation_key: $('#mxchat_activation_key').val(),
@@ -443,9 +545,9 @@
443 545 mxchat_pro_email: $('#mxchat_pro_email').val(),
444 546 mxchat_activation_key: $('#mxchat_activation_key').val(),
445 547 security: mxchatAdmin.license_nonce
446 548 };
447 -
549 +
448 550 $.post(mxchatAdmin.ajax_url, formData, function(response) {
449 551 handleActivationResponse(response);
450 552 }).fail(function() {
451 553 alert('Server error. Please try again.');
@@ -453,15 +555,15 @@
453 555 submitButton.prop('disabled', false);
454 556 });
455 557 });
456 558 }
457 -
559 +
458 560 // Questions handling
459 561 $('.mxchat-add-question').on('click', function () {
460 562 const container = $('#mxchat-additional-questions-container');
461 563 const questionCount = container.find('.mxchat-question-row').length + 4;
462 564 const questionIndex = container.find('.mxchat-question-row').length;
463 -
565 +
464 566 const newQuestion = `
465 567 <div class="mxchat-question-row">
466 568 <input type="text"
467 569 name="additional_popular_questions[]"
@@ -473,18 +575,18 @@
473 575 </div>
474 576 `;
475 577 container.append(newQuestion);
476 578 });
477 -
579 +
478 580 $(document).on('click', '.mxchat-remove-question', function () {
479 581 $(this).closest('.mxchat-question-row').remove();
480 582 saveQuestions();
481 583 });
482 -
584 +
483 585 $(document).on('change', '.mxchat-question-input', function() {
484 586 saveQuestions();
485 587 });
486 -
588 +
487 589 function saveQuestions() {
488 590 const questions = [];
489 591 $('.mxchat-question-input').each(function() {
490 592 const value = $(this).val().trim();
@@ -491,17 +593,17 @@
491 593 if (value) {
492 594 questions.push(value);
493 595 }
494 596 });
495 -
597 +
496 598 const feedbackContainer = $('<div class="feedback-container"></div>');
497 599 const spinner = $('<div class="saving-spinner"></div>');
498 600 const successIcon = $('<div class="success-icon">✔</div>');
499 -
601 +
500 602 // Append feedback after the add button
501 603 $('.mxchat-add-question').after(feedbackContainer);
502 604 feedbackContainer.append(spinner);
503 -
605 +
504 606 // Save via AJAX
505 607 $.ajax({
506 608 url: mxchatAdmin.ajax_url,
507 609 type: 'POST',
@@ -529,9 +631,9 @@
529 631 feedbackContainer.remove();
530 632 }
531 633 });
532 634 }
533 -
635 +
534 636 // Live agent status handler
535 637 const statusToggle = document.getElementById('live_agent_status');
536 638 const statusText = statusToggle?.parentElement.nextElementSibling?.querySelector('.status-text');
537 639 if (statusToggle && statusText) {
@@ -537,9 +639,9 @@
537 639 if (statusToggle && statusText) {
538 640 statusToggle.addEventListener('change', function() {
539 641 // Update display text
540 642 statusText.textContent = this.checked ? 'Online' : 'Offline';
541 -
643 +
542 644 // Send the correct on/off value to the server
543 645 if (window.mxchatSaveSetting) {
544 646 window.mxchatSaveSetting('live_agent_status', this.checked ? 'on' : 'off');
545 647 }
@@ -544,9 +646,9 @@
544 646 window.mxchatSaveSetting('live_agent_status', this.checked ? 'on' : 'off');
545 647 }
546 648 });
547 649 }
548 -
650 +
549 651 // Function to adjust the textarea height to content
550 652 function adjustTextareaHeight() {
551 653 this.style.height = 'auto'; // Reset to auto to calculate scrollHeight
552 654 this.style.height = this.scrollHeight + 'px'; // Expand to content height
@@ -562,7 +664,5 @@
562 664
563 665 // Bind events
564 666 $textarea.on('focus input', adjustTextareaHeight) // Expand on focus and input
565 667 .on('blur', resetTextareaHeight); // Reset on blur
566 -
567 -
568 -});
668 +});