Mercurial > hg > isophonics-drupal-site
view core/modules/big_pipe/js/big_pipe.es6.js @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | 1fec387a4317 |
children |
line wrap: on
line source
/** * @file * Renders BigPipe placeholders using Drupal's Ajax system. */ (function($, Drupal, drupalSettings) { /** * Maps textContent of <script type="application/vnd.drupal-ajax"> to an AJAX response. * * @param {string} content * The text content of a <script type="application/vnd.drupal-ajax"> DOM node. * @return {Array|boolean} * The parsed Ajax response containing an array of Ajax commands, or false in * case the DOM node hasn't fully arrived yet. */ function mapTextContentToAjaxResponse(content) { if (content === '') { return false; } try { return JSON.parse(content); } catch (e) { return false; } } /** * Executes Ajax commands in <script type="application/vnd.drupal-ajax"> tag. * * These Ajax commands replace placeholders with HTML and load missing CSS/JS. * * @param {number} index * Current index. * @param {HTMLScriptElement} placeholderReplacement * Script tag created by BigPipe. */ function bigPipeProcessPlaceholderReplacement(index, placeholderReplacement) { const placeholderId = placeholderReplacement.getAttribute( 'data-big-pipe-replacement-for-placeholder-with-id', ); const content = this.textContent.trim(); // Ignore any placeholders that are not in the known placeholder list. Used // to avoid someone trying to XSS the site via the placeholdering mechanism. if ( typeof drupalSettings.bigPipePlaceholderIds[placeholderId] !== 'undefined' ) { const response = mapTextContentToAjaxResponse(content); // If we try to parse the content too early (when the JSON containing Ajax // commands is still arriving), textContent will be empty or incomplete. if (response === false) { /** * Mark as unprocessed so this will be retried later. * @see bigPipeProcessDocument() */ $(this).removeOnce('big-pipe'); } else { // Create a Drupal.Ajax object without associating an element, a // progress indicator or a URL. const ajaxObject = Drupal.ajax({ url: '', base: false, element: false, progress: false, }); // Then, simulate an AJAX response having arrived, and let the Ajax // system handle it. ajaxObject.success(response, 'success'); } } } // The frequency with which to check for newly arrived BigPipe placeholders. // Hence 50 ms means we check 20 times per second. Setting this to 100 ms or // more would cause the user to see content appear noticeably slower. const interval = drupalSettings.bigPipeInterval || 50; // The internal ID to contain the watcher service. let timeoutID; /** * Processes a streamed HTML document receiving placeholder replacements. * * @param {HTMLDocument} context * The HTML document containing <script type="application/vnd.drupal-ajax"> * tags generated by BigPipe. * * @return {bool} * Returns true when processing has been finished and a stop signal has been * found. */ function bigPipeProcessDocument(context) { // Make sure we have BigPipe-related scripts before processing further. if (!context.querySelector('script[data-big-pipe-event="start"]')) { return false; } $(context) .find('script[data-big-pipe-replacement-for-placeholder-with-id]') .once('big-pipe') .each(bigPipeProcessPlaceholderReplacement); // If we see the stop signal, clear the timeout: all placeholder // replacements are guaranteed to be received and processed. if (context.querySelector('script[data-big-pipe-event="stop"]')) { if (timeoutID) { clearTimeout(timeoutID); } return true; } return false; } function bigPipeProcess() { timeoutID = setTimeout(() => { if (!bigPipeProcessDocument(document)) { bigPipeProcess(); } }, interval); } bigPipeProcess(); // If something goes wrong, make sure everything is cleaned up and has had a // chance to be processed with everything loaded. $(window).on('load', () => { if (timeoutID) { clearTimeout(timeoutID); } bigPipeProcessDocument(document); }); })(jQuery, Drupal, drupalSettings);