JavaScript only being called once in Squarespace

2020-01-29 02:40发布

问题:

I have some custom JavaScript on my SquareSpace site that manipulates Product titles beyond what you can do with SquareSpace's default style editor. It works when initially loading the page (https://www.manilva.co/catalogue-accessories/) but if you click on any of the categories on the left, the styling resets to the default.

I'm assuming the JavaScript is being overwritten by the SquareSpace style, but I can't figure out why. Perhaps I'm calling the function in the wrong place?

Any suggestions would be helpful.

Thanks!

Current code:

document.querySelectorAll(".ProductList-filter-list-item-link".forEach(i=>i.addEventListener("click", function()
  {
      var prodList = document.querySelectorAll("h1.ProductList-title");
  for (i = 0, len = prodList.length; i < len; i++) 
  {
    var text = prodList[i].innerText;
    var index = text.indexOf('-');
    var lower = text.substring(0, index);
    var higher = text.substring(index + 2);
    prodList[i].innerHTML = lower.bold() + "<br>" + higher;

  });

回答1:

The source of your problem is that your template has AJAX loading enabled. There are currently a couple generally-accepted ways to deal with this as a Squarespace developer:

  1. Disable AJAX loading
  2. Write your javascript functions in a manner that will run on initial site load and whenever an "AJAX load" takes place.

Option 1 - Disable AJAX:

  1. In the Home Menu, click Design, and then click Site Styles.
  2. Scroll down to Site: Loading.
  3. Uncheck Enable Ajax Loading.


Option 2 - Account for AJAX in Your JS

There are a number of ways that developers approach this, including the following, added via sitewide code injection:

<script>
window.Squarespace.onInitialize(Y, function() {
  // do stuff
});
</script>

or

<script>
(function() {
  // Establish a function that does stuff.
  var myFunction = function() {
    // Do stuff here.
  };

  // Initialize the fn on site load.
  myFunction();
  // myFunction2(); , etc...

  // Reinit. the fn on each new AJAX-loaded page.
  window.addEventListener("mercury:load", myFunction);
})();
</script>

or

<script>
(function() {
  // Establish a function that does stuff.
  var myFunction = function() {
    // Do stuff here.
  };

  // Initialize the fn on site load.
  myFunction();

  // Reinit. the fn on each new AJAX-loaded page.
  new MutationObserver(function() {
    myFunction();
    // myFunction2(); , etc...
  }).observe(document.body, {attributes:true, attributeFilter:["id"]});
})();
</script>

Each of those works for most of the latest (at time of writing) templates most of the time. Each of those have their advantages and disadvantages, and contexts where they do not work as one might expect (for example, on the /cart/ page or other "system" pages). By adding your code within the context of one of the methods above, and ensuring that the code is of course working in the desired contexts and without its own bugs/issues, you will have your code run on initial site load and on each AJAX page load (with some exceptions, depending on the method you use).



回答2:

Your problem is the page does not reload when clicking a button on the left, just some elements are removed, added and replaced. The changed elements will not be restyled. You will need to re-run your JavaScript after one of those buttons is clicked. Perhaps something like this:

document.querySelectorAll(
    ".ProductList-filter-list-item"
).forEach(
    i=>i.addEventListener(
        "click", ()=>console.log("hello")
    )
)

where you replace console.log("hello") with whatever resets your formatting.