3

I'm working on a Squarespace site at the moment, trying to figure out how I can bind a function to their AjaxLoader without much success.

Here is a demo site that uses this loader

In my console I can see all the XHR requests being triggered when switching between pages, and I've tried using the debug to capture event listeners.

I thought something bound to "readystatechange" would work, but it only triggers on the initial page load.

$(window).on("readystatechange", doStuff);
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
jfox
  • 848
  • 1
  • 8
  • 23
  • Somewhat related is the following post. At the bottom of the answer there is information about disabling the AJAX loader altogether. That's not really ideal, but depending on what you're trying to accomplish, it may be of some use: http://stackoverflow.com/a/38919264/5338581 – Brandon Sep 09 '16 at 12:29
  • @Brandon Thank you – I'm not really keen on disabling it though. I came up with a solution using a setTimout function bound to the ui click events. Caches the page id, and then breaks when it changes. It's just so ugly – jfox Sep 09 '16 at 12:56

3 Answers3

3

I found a pretty nice solution using mutationObservers on the Squarespace Answers forum – thank you @octopus!

Copy and pasted from here

Hope this helps anyone else struggling.

 window.onload = function(){
   react();
   watch(react);
 };
 function react() {
   var id = document.body.getAttribute('id'),
       target = 'collection-5787c6b0cd0f6801e859286a';
   console.log(id);
   if (id === target) {
     // execute your code for this page
   }
 }
 function watch(callback) {
   MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
   var observer = new MutationObserver(function(mutations) {
     for (var index = 0; index < mutations.length; index++) {
       var mutation = mutations[index];
       if (mutation.type === 'attributes') { 
         callback();
       }
     }
   });
   observer.observe(document.body, {
     attributes: true,
     attributeFilter: ['id']
   });
 }
jfox
  • 848
  • 1
  • 8
  • 23
1

The ajaxLoader.js is using the modular pattern and has encapsulated the httpRequest. I don't believe you can bind to it.

  (function(window, document){
    'use strict';

     var DEBUG = true;
     var httpRequest; // THE HTTP REQUEST USED FOR THE AJAX
     var ajaxFired = false;
     var currentEvent;
     var currentTarget;
     var indexNextAnim = true;
     ...

The httpRequest is set and used in the ajax function:

ajax: function (url) {

  httpRequest = new XMLHttpRequest();
  httpRequest.open('GET', url);
  httpRequest.timeout = this.TIMEOUT;
  httpRequest.onreadystatechange = this.handleRequest.bind(this, url);
  httpRequest.ontimeout = this.handleTimeout.bind(this, url);
  httpRequest.send(null);
},
meditari
  • 131
  • 2
  • 7
  • hmm well that's annoying. Do you have any suggestions on how I could manipulate the page content after it has been changed? – jfox Sep 09 '16 at 11:08
  • If you are using jQuery you might be able to use the [Global Ajax Event Handlers](https://api.jquery.com/category/ajax/global-ajax-event-handlers/). However I'm not positive that is for ajax calls that aren't using the jQuery library. – meditari Sep 09 '16 at 11:11
1

This is very easy to solve. Simply modify the AjaxLoader prototype to add an additional custom init function right along side of where Squarespace runs their own block init.

This assumes you've bound some sort of custom object that holds your init function(s). Sometimes to better to use some sort of custom event emitter for this, but that would be some additional dev. This seems much easier.

 window.onload = function() {
   this.AjaxLoader.prototype.initializeSqsBlocks = function () {
     window.SQS.Lifecycle.init();

     console.log( "Foo!" );
     window.CUSTOM.YourCustomInitFunction();
   }
 };

The end result is that when the ajaxloader fires, it will trigger the initializeSqsBlocks init as usual, which you've now hijacked to add your own additional init function. It's kind of a makeshift way of attaching an emitter to the ajaxloader without modifying it too much.

jasonbarone
  • 172
  • 3
  • 17