Squarespace jQuery Code Injection

What to implement

  1. Include a shipping dropdown selector that shows shipping times and prices, read in the shipping information from another page

2. Add a search bar to the header that displays as a magnifying glass and then expands into a search bar when clicked, it should also popup with the search results when the user starts typing

3. Change how colours and sizes are displayed from dropdown list to colour selector palette

Injecting My First Code

I had never injected JavaScript into Squarespace before so first off I decided to try and get something very simple working to give me a good starting point.

I added the following JavaScript into the header, this should add the html "<h1>Hello World!</h1>" into the element with the id of "block-ca33eeb90eb2c5aa8c35" :

<script>
window.onload = function() {
document.getElementById("block-ca33eeb90eb2c5aa8c35").innerHTML = "<h1>Hello World!</h1>";
}
</script>

This is the website before saving the code:

When saving the code it had the following effect:

I then decided to use the jQuery Javascript library as a lot of the features it offered would be beneficial for what I wanted to implement, I found the following website very useful to understand the syntax

https://www.w3schools.com/jquery/

I loaded the jQuery library into my Squarespace site using the following line of code:

<script src="<https://code.jquery.com/jquery-3.6.0.js>"></script>

Implementing the Shipping Dropdown Box 1)

First off I added a dropdown box and a div element using a HTML block:

<div class="country-container">
<select id="country-select" >
<option value="">Select your country</option>
</select>
<div id="country-display">Delivery Times and Cost</div>
</div>

I created a new unlinked page and named it shipping, on this page I created a text block and inserted the shipping data for every country in the following format

COUNTRY_NAME, DELIVERY_TIME, DELIVERY_COST

Note the commas in the above are very important and are used to separate each input

Having the data for the shipping information on this page will allow anyone with access to the website in Squarespace the ability to update this information.

After a bit of playing around with jQuery I managed to get the following code to work:

<script>
$(document).ready(function () {
//read all options in from shipping page
$.get("/shipping", function (data) {
data = $(data).find("p");
//print them into a hidden div so they can be read in through an each loop
$("div#test").html(data);
//for each item add an option element with number of days and cost data attributes
$("div#test p").each(function () {
const countryArray = $(this).text().split(","); //Split each paragraph using the comma
//Add each country to a select element and add the delivery days and costs as attributes
$("select#country-select").append(
"<option data-country=" +
countryArray[0].trim() +
" data-days=" +
countryArray[1].trim() +
" data-cost=" +
countryArray[2].trim() +
">" +
countryArray[0].trim() +
"</option>"
);
});
//Select the UK as the default option
$("select#country-select option[data-country=UK]")
.attr("selected", "selected")
.change();
});
//When the selected option is changed, change the text displayed in the div
$("#country-select").change(function () {
var optionSelected = $(this).find("option:selected");
var day = optionSelected.data("days") + " days - ";
var cost = "£" + optionSelected.data("cost");
var country = optionSelected.data("country") + " - ";
$("#country-display").text(country + day + cost);
});
});
</script>

Limitations

  • The shipping information will only be updated when someone manually updates it, it is not in any way linked to the actual shipping price that is given to Squarespace at a different point

Implementing the Search Bar 2)

Having a search bar in the header is not a standard feature in Squarespace, I found the following guide which explains how to add it there:

https://www.will-myers.com/articles/adding-a-search-bar-to-your-header-in-squarespace-71

After completing the above steps I then wanted to change it so that only a magnifying glass was shown until the user clicked it, to do this I used a magnifying glass from the font awesome icon library and added some jQuery and CSS to hide and show some elements when the user clicked.

//Link to the fontawesome icon
<script src="<https://kit.fontawesome.com/95625e95a1.js>" crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
$(function () {
//Change the id to the id of the search block in the footer
let searchBlock = $("#block-48b06b63c27b9bc086e0")
.attr("id", "")
.addClass("header-search-bar");

//Display the magnifiying glass icon
$("<i class='fa-solid fa-magnifying-glass'></i>").insertBefore(
$(".showOnDesktop .header-actions-action--cart")
);
$("<div class='search hide'></div>").insertBefore("header");
$("div.search").append(searchBlock);
$("div.search").append("<i class='fa-solid fa-xmark'></i>");

//When the magnificy glass is clicked
$("i.fa-magnifying-glass").click(function () {
//hide everything in the header and display the search bar full width
$("header").addClass("hide"); //hide the header
$("div.search").removeClass("hide"); //unhide the search bar
});

//Show an X mark icon that will re show the header when clicked
$("i.fa-xmark").click(function () {
$("header").removeClass("hide"); //unhide the header
$("div.search").addClass("hide"); //hide the search bar
});
})
});
</script>;

Limitations

  • Search bar is currently limited to the functionality that Squarespace have added
  • Does not currently display on a customised menu

Implementing Colour and Size Selectors 3)

I started by hiding the previous dropdown boxes:

//Hides both dropdown boxes
$("div.variant-select-wrapper").hide();

Then adding a <ul> tag, using the correct selectors here is slightly complex:

$("div.variant-select-wrapper:has(select[data-variant-option-name='Color'])")
.after("<ul class='color-selector'>");

Then for each option that is in the dropdown box except the first option which is used as a placeholder we add an <li> tag with some inline CSS to set the color

//for every option in the select tag except the first
$("div.variant-select-wrapper:has(select[data-variant-option-name='Color']) option:not(:first)")
.each(function () {
var color = $(this).val(); //store the color
$(
"<li class='color-selector-item'> <button class='color-selector-button' type='button' title='" +
color +
"' style='background-color: " +
color +
" !important;'>" +
color +
"</button></li>"
).appendTo("ul.color-selector");
});
//after the loop close the <ul> tag
$("li.color-selector-item:last").after("</ul>");

When any of the colour selectors are clicked we want to display the colour on the screen as text and select it through the dropdown box hidden in the background:

$("button.color-selector-button").click(function () {
//Chnage the text on the screen
$("div.variant-option-title:contains('Color')").html(
"Color: " + $(this).text()
);
});

Unfortunately I encountered problems with setting the hidden dropdown selectors.

Problems encountered implementing colour and size selector:

Changing the value of the select element as below would not change the colour that was written in the dropdown menu on the screen

$("select[data-variant-option-name=Color]")
.val($(this).text());

Even triggering the change event did not work:

$("select[data-variant-option-name=Color]")
.val($(this).text())
.change();

The only way I found to change what was in the dropdown was to change the data-text attribute highlighted in the above HTML

<div class="variant-select-wrapper color-wrapper" data-text="White" id="yui_3_17_2_1_1651002078249_616">
<select aria-label="Select Color" data-variant-option-name="Color" id="yui_3_17_2_1_1651002078249_615">
<option value="">Select Color</option>
<option value="Black">Black</option><option value="White">White</option><option value="Grey">Grey</option><option value="Teal">Teal</option><option value="Charcoal">Charcoal</option><option value="Purple">Purple</option>
</select>
</div>
$("div.variant-select-wrapper.color-wrapper")
.attr("data-text", $(this).text())
.change();

Although this worked in terms of displaying the colour in the dropdown when one of the new color selectors was clicked it did not then allow me to add that item to the basket stating “Please select a Color and Size”

I looked through the HTML and noticed that when I manually made a selection through the dropdown boxes there were a few notable attributes that changed

data-unselected-options="["Color","Size"]"

The above would change to remove one or both of the items when selected, when color was selected:

data-unselected-options="["Size"]"

Also a new attribute would be added when both color and size were selected:

data-selected-variant="{"attributes":{"Size":"M","Color":"White"},"optionValues":[
{"optionName":"Size","value":"M"},{"optionName":"Color","value":"White"}],
"id":"ae248023-a7b2-4ebb-89ef-55764797f7e1","sku":"SQ2275958","price":4000,
"salePrice":0,"priceMoney":{"currency":"GBP","value":"40.00"},
"salePriceMoney":{"currency":"GBP","value":"0.00"},"onSale":false,"unlimited":true,
"qtyInStock":0,"width":0,"height":0,"weight":0,"imageIds":[],"images":[],"len":0}"

Also the following attribute would be added if the variant was in stock

data-variant-in-stock="true"

If I manually hard coded these values and set the data-unselected-options to be empty, the data-variant-in-stock to be true and the data-selected-variant to be a real value I was able to add the item to the cart, the problem with this is that I would not be able to easily get all the information for the data-selected-variant attribute as well as whether the variant was in stock.

I need to find a way to select the dropdown box in the background as if a user was just clicking it manually.

The Solution

Finally I found the solution to trigger the select of both the colour and size Squarespace selectors

document.querySelector("select[data-variant-option-name='Color']").dispatchEvent(new Event("change"));

The following code shows simply how to select a colour and size using jQuery and then trigger the change event so when the add to cart button is pressed the correct item is added to the cart:

$(document).ready(function () {
let myColour = "Grey";
let mySize = "M";

$(".variant-option-title").click(function () {
$("select[data-variant-option-name=Color]").val(myColour);
document.querySelector("select[data-variant-option-name='Color']").dispatchEvent(new Event("change"));
$("select[data-variant-option-name=Size]").val(mySize);
document.querySelector("select[data-variant-option-name='Size']").dispatchEvent(new Event("change"));
});
});

Limitations

  • The colours will only display if they are html colours as in this list (supported by all browsers), this means that the product variant must also be named as this colour, it is possible to get around this in the future by linking colours to hex or RGB values or even pictures but this simplifies it for now (An alert is displayed when a colour does not exist, will detect typos etc)
  • The image does not change to display a different colour variant when it is changed

View the website here

https://crane-cinnamon-w8mr.squarespace.com/

Password — 123

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store