Uploaded image for project: 'XWiki Platform'
  1. XWiki Platform
  2. XWIKI-25675

The xwiki:dom:updated event sent after an asynchronous rendering targets the removed placeholder instead of the rendered content

    XMLWordPrintable

Details

    • Unknown

    Description

      Since XWIKI-24559, async.js sends the xwiki:dom:updated event once the result of an asynchronous rendering is displayed, but the event targets the placeholder that was replaced by the result, not the result itself:

      element.replaceWith(xhr.responseText);
      $(document).trigger('xwiki:dom:updated', {elements: element.toArray()});
      

      replaceWith leaves element pointing to the removed placeholder. The listeners of the event, which initialize the updated elements, look for what to initialize inside elements that are not in the page anymore, so they find nothing.

      Steps to reproduce

      Example with the Chart.js application, whose charts are drawn on page load and on xwiki:dom:updated, in the updated elements (seen with the OpenProject Charts macro of the Project Management application, which renders its charts asynchronously):

      1. Edit a page containing an asynchronously rendered chart with the in-place editor
      2. Click "Done" (or "Save & View")

      Result: the chart is empty, until the page is reloaded.

      A simple page view works, because the Chart.js JavaScript is only loaded with the asynchronous result and, when loaded, initializes the whole page. The event is needed when the JavaScript is already loaded, e.g. after saving with the in-place editor, or with several asynchronous charts on the same page depending on the timing.

      Proposed fix

      As suggested by Marius: create the new elements first, pass them to replaceWith and to the event. Calling the event with the parent of the placeholder isn't an option, since it would initialize again sibling elements that weren't changed.

      const newElements = $($.parseHTML(xhr.responseText, document, false));
      element.replaceWith(newElements);
      $(document).trigger('xwiki:dom:updated', {elements: newElements.filter('*').toArray()});
      
      • $.parseHTML rather than $(xhr.responseText): $() only parses the string as HTML when it starts with <.
      • false drops the inline scripts of the result, which replaceWith executes today. Inline scripts are a bad practice and a security risk, and the scripts needed by the result are declared in an HTTP header handled by xwiki.js, but this is a behaviour change for asynchronous content relying on inline scripts, to mention in the release notes.
      • Add a functional test checking that the content rendered asynchronously gets initialized, since XWIKI-24559 didn't have one.

      Attachments

        Issue Links

          Activity

            People

              mflorea Marius Dumitru Florea
              vmassol Vincent Massol
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated: