wombat icon indicating copy to clipboard operation
wombat copied to clipboard

Suggestion: Post message on 'unload' event

Open VascoRatoFCCN opened this issue 4 years ago • 0 comments

Recently I came across an issue: when replaying heavier websites, after clicking on a hyperlink on the page, the frame and banner around the iframe would take a while to update. This happens because wombat notifies the frame about new pages being loaded by posting a message when the 'load' event triggers. However, this event is only triggered after the page completes loading.

My suggestion would be to have wombat post a message on the 'unload' event, which is sent as soon as a change of context is requested. This has the issue that the event happens before the new URL is set on window.location.href, but by taking heavy inspiration from this StackOverflow answer, I was able to implement the desired behavior.

I implemented it in the pywb custom frame rather than editing wombat.js. When the unload event happens, a message is posted with wb_type set to 'unload', which as far as I could tell is currently an unused wb_type in wombat.

With this I was able to have the frame react as soon as a hyperlink was clicked. Here is the code I used:

var cframe = new ContentFrame({
  "url": "{{ url }}" + window.location.hash,
  "prefix": "{{ wb_prefix }}",
  "request_ts": "{{ wb_url.timestamp }}",
  "iframe": "#replay_iframe"
});

// adding an 'unload' event message to be able to quickly react to changes in context.
const iframe = document.getElementById('replay_iframe');
function unloadHandler(e) {
  // Timeout needed because the URL changes immediately after
  // the `unload` event is dispatched.
  setTimeout(function () {
    let splitUrl = iframe.contentWindow.location.href.split('mp_/');
    if (splitUrl.length < 2) {
      return;
    }
    let message = {
      url: splitUrl.filter((x, i) => { return i > 0 }).join('mp_/'),
      ts: splitUrl[0].split('/').pop(),
      wb_type: 'unload'
    };
    window.postMessage(message);
  }, 0);
};
function attachUnload() {
  // Remove the unloadHandler in case it was already attached.
  // Otherwise, the change will be dispatched twice.
  iframe.contentWindow.removeEventListener("unload", unloadHandler);
  iframe.contentWindow.addEventListener("unload", unloadHandler);
}
iframe.addEventListener("load", attachUnload);

VascoRatoFCCN avatar Oct 13 '21 11:10 VascoRatoFCCN