Plugin Directory


Ignore:
Timestamp:
10/02/2026 01:56:12 PM (4 weeks ago)
Author:
mxchat
Message:

Release 3.2.24 - Safari links in replies now open; Slack live-agent delivery is reported honestly and no longer prefixed with stray characters; uploaded documents and PDFs are named properly, can carry a Source URL and no longer duplicate on re-upload; digit-led part numbers work again on a Pinecone document index; Custom Provider embeddings supported through the REST API and index sizing; WooCommerce product tags indexed; personal data export covers pre-chat form visitors; new Re-import affected entries tool

File:
1 edited

Legend:

Unmodified
Added
Removed
  • mxchat-basic/trunk/js/chat-script.js

    r3718803 r3724923  
    13081308    // Server-pushed html to append as its OWN bot bubble once the stream
    13091309    // finishes (e.g. the consent-safe YouTube embed, plan 03ba33). Rendering is
    1310     // deferred to [DONE] so the embed always lands BELOW the streamed text.
     1310    // deferred to the end of the stream so the embed always lands BELOW the
     1311    // streamed text.
    13111312    let pendingAppendHtml = '';
     1313
     1314    // Render the stashed appendix as its own bot bubble below the streamed
     1315    // text — mirrors how it is saved in the transcript, so history replays
     1316    // identically. Called from BOTH ends of a stream: the [DONE] line and
     1317    // the stream simply closing (the OpenAI Responses path and Gemini end
     1318    // without a [DONE] line). The stash is cleared, so a stream that sends
     1319    // [DONE] and then closes renders it once. Any future appendix-type
     1320    // event belongs in here, not in one of the two branches.
     1321    function flushAppendHtml() {
     1322        if (pendingAppendHtml) {
     1323            appendMessage("bot", "", pendingAppendHtml, [], false, botId);
     1324            pendingAppendHtml = '';
     1325        }
     1326    }
    13121327
    13131328    // Abortable stream: a fresh controller per turn, keyed by bot instance.
    … …  
    13931408                    enableChatInput(botId);
    13941409
     1410                    flushAppendHtml();
     1411
    13951412                    // Scroll the user's last message to the top now that the
    13961413                    // bot's full reply has rendered (gives max reading room).
    … …  
    14251442                            enableChatInput(botId);
    14261443
    1427                             // Render any server-pushed appendix html (e.g. the
    1428                             // YouTube embed) as its own bot bubble below the
    1429                             // streamed text — mirrors how it is saved in the
    1430                             // transcript, so history replays identically.
    1431                             if (pendingAppendHtml) {
    1432                                 appendMessage("bot", "", pendingAppendHtml, [], false, botId);
    1433                                 pendingAppendHtml = '';
    1434                             }
     1444                            flushAppendHtml();
    14351445
    14361446                            // Scroll the user's last message to the top now
    … …  
    22532263}
    22542264
     2265// Link clicks in bot and agent messages: the click is recorded, the browser
     2266// follows the anchor itself. Navigation must not wait for the tracking
     2267// request: a window.open() made from that request's callback is outside the
     2268// visitor's tap, and Safari's pop-up blocker drops it without a message.
     2269
     2270// Give a tracked anchor the target it should open in, and noopener on a new tab.
     2271function prepareTrackedLink($link) {
     2272    if (linkTarget === '_blank' && $link.attr('target') !== '_blank') {
     2273        $link.attr('target', '_blank');
     2274    }
     2275    if ($link.attr('target') === '_blank') {
     2276        var rel = $link.attr('rel') || '';
     2277        if (!/(^|\s)noopener(\s|$)/.test(rel)) {
     2278            $link.attr('rel', $.trim(rel + ' noopener'));
     2279        }
     2280    }
     2281}
     2282
     2283// Record one click, fire-and-forget. sendBeacon survives the page unloading
     2284// when the link opens in the same tab.
     2285function trackLinkClick(href, messageContext, botId) {
     2286    var fields = {
     2287        action: 'mxchat_track_url_click',
     2288        session_id: getChatSession(botId),
     2289        url: href,
     2290        message_context: messageContext,
     2291        nonce: mxchatChat.nonce
     2292    };
     2293    try {
     2294        if (navigator.sendBeacon && typeof FormData !== 'undefined') {
     2295            var body = new FormData();
     2296            $.each(fields, function(name, value) {
     2297                body.append(name, value == null ? '' : value);
     2298            });
     2299            if (navigator.sendBeacon(mxchatChat.ajax_url, body)) {
     2300                return;
     2301            }
     2302        }
     2303    } catch (error) {
     2304        // Fall through to the plain request
     2305    }
     2306    $.ajax({
     2307        url: mxchatChat.ajax_url,
     2308        type: 'POST',
     2309        data: fields
     2310    });
     2311}
     2312
    22552313//   Helper function to attach link tracking with proper event handling
    22562314function attachLinkTracking(messageDiv, messageText, botId) {
    … …  
    22722330                $link.off('click.tracking');
    22732331
     2332                // The anchor carries its own target: the browser follows it
     2333                prepareTrackedLink($link);
     2334
    22742335                // Add new click handler with namespace
    22752336                $link.on('click.tracking', function(e) {
    2276                     e.preventDefault();
    22772337                    e.stopPropagation();
    22782338
    … …  
    22812341                        : '';
    22822342
    2283                     // Track the click
    2284                     $.ajax({
    2285                         url: mxchatChat.ajax_url,
    2286                         type: 'POST',
    2287                         data: {
    2288                             action: 'mxchat_track_url_click',
    2289                             session_id: getChatSession(botId),
    2290                             url: originalHref,
    2291                             message_context: messageContext,
    2292                             nonce: mxchatChat.nonce
    2293                         },
    2294                         complete: function() {
    2295                             // Always redirect, even if tracking fails
    2296                             if ($link.attr('target') === '_blank' || linkTarget === '_blank') {
    2297                                 window.open(originalHref, '_blank');
    2298                             } else {
    2299                                 window.location.href = originalHref;
    2300                             }
    2301                         }
    2302                     });
    2303 
    2304                     return false; // Extra insurance to prevent default
     2343                    prepareTrackedLink($link);
     2344                    trackLinkClick(originalHref, messageContext, botId);
    23052345                });
    23062346            }
    … …  
    45524592
    45534593        if (originalHref && (originalHref.startsWith('http://') || originalHref.startsWith('https://'))) {
    4554             e.preventDefault();
    4555             e.stopPropagation();
    4556 
    4557             // Mark as tracked
    4558             $link.attr('data-tracked', 'true');
    4559 
    45604594            // Get bot ID from the chat box context
    45614595            var botId = getBotIdFromElement(this);
    … …  
    45644598            const messageText = messageDiv.text().substring(0, 200);
    45654599
    4566             $.ajax({
    4567                 url: mxchatChat.ajax_url,
    4568                 type: 'POST',
    4569                 data: {
    4570                     action: 'mxchat_track_url_click',
    4571                     session_id: getChatSession(botId),
    4572                     url: originalHref,
    4573                     message_context: messageText,
    4574                     nonce: mxchatChat.nonce
    4575                 },
    4576                 complete: function() {
    4577                     if ($link.attr('target') === '_blank' || linkTarget === '_blank') {
    4578                         window.open(originalHref, '_blank');
    4579                     } else {
    4580                         window.location.href = originalHref;
    4581                     }
    4582                 }
    4583             });
    4584 
    4585             return false;
     4600            // Same path as attachLinkTracking(): set the target, record the
     4601            // click, and let the browser follow the anchor.
     4602            prepareTrackedLink($link);
     4603            trackLinkClick(originalHref, messageText, botId);
    45864604        }
    45874605    }
Note: See TracChangeset for help on using the changeset viewer.