Skip to content

Instantly share code, notes, and snippets.

@patrickbolle
Last active September 17, 2024 16:14
Show Gist options
  • Save patrickbolle/ff958c82065f4f83936b9c76cf921d04 to your computer and use it in GitHub Desktop.
Save patrickbolle/ff958c82065f4f83936b9c76cf921d04 to your computer and use it in GitHub Desktop.
filter.js
#rk_filter {
display: none; /* hide filter by default */
flex-wrap: wrap;
justify-content: center;
margin: 20px 0;
}
#rk_filter select {
margin: 0 5px;
padding: 10px 15px;
border: 1px solid #ccc;
border-radius: 3px;
cursor: pointer;
min-width: 150px;
}
#rk_filter select:focus {
outline: none;
box-shadow: 0 0 5px #333;
}
#rk_filter .cancel-filter {
margin-left: 5px;
padding: 10px 15px;
color: white;
color: white;
border-radius: 3px;
cursor: pointer;
}
console.log("Recipe Kit | filter.js loaded.");
console.log(window.rk_filters);
// Helper function to get selected tags from the URL
function getSelectedTagsFromURL() {
const currentPath = window.location.pathname;
const selectedTags = [];
if (currentPath.includes("/tagged/")) {
const tagsSegment = currentPath.split("/tagged/")[1];
const tags = tagsSegment.split("+");
tags.forEach((tag) => {
if (tag) {
// Decode the URL-encoded tag and replace hyphens with spaces
selectedTags.push(
decodeURIComponent(tag.trim()).toLowerCase().replace(/-/g, " ")
);
}
});
}
return selectedTags;
}
// Initialize selectedTag for each filter based on the URL
window.rk_filters.forEach((filter) => {
const selectedTags = getSelectedTagsFromURL();
const matchingTag = filter.tags.find((tag) => {
const normalizedTag = tag.trim().toLowerCase();
return selectedTags.includes(normalizedTag);
});
filter.selectedTag = matchingTag || "";
});
function capitalizeTag(tag) {
if (!tag) return false;
return tag
.split(/[\s-]+/)
.map(
(word) => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase()
)
.join(" ");
}
// Helper function to update the default option's text
function updateDefaultOptionText(select, filter) {
const defaultOption = select.querySelector("option[disabled]");
defaultOption.text = `${filter.name}: ${
capitalizeTag(filter.selectedTag) || window.all_translation || "All"
}`;
}
// Helper function to update the URL
function updateURL(filters) {
const currentPath = window.location.pathname;
let newURL = currentPath;
let tags = filters
.map((filter) =>
encodeURIComponent(
filter.selectedTag.trim().toLowerCase().replace(/\s+/g, "-")
)
)
.filter((tag) => tag);
if (tags.length > 0) {
// Remove the existing /tagged/ segment from the URL
if (currentPath.includes("/tagged/")) {
newURL = currentPath.split("/tagged/")[0];
}
// Add /tagged/ and append tags
newURL += "/tagged/" + tags.join("+");
}
window.location.href = newURL;
}
// Helper function to create and append a filter dropdown
function createFilterDropdown(filter, container) {
if (
filter.tags.some((tag) =>
window.all_tags
.map((t) => t.trim().toLowerCase())
.includes(tag.trim().toLowerCase())
)
) {
const select = document.createElement("select");
select.className = "filter-dropdown";
const option = document.createElement("option");
option.text = `${filter.name}: ${
capitalizeTag(filter.selectedTag) || window.all_translation || "All"
}`;
option.disabled = true;
option.selected = true;
select.appendChild(option);
filter.tags.forEach((tag) => {
if (
window.all_tags
.map((t) => t.trim().toLowerCase())
.includes(tag.trim().toLowerCase())
) {
const option = document.createElement("option");
const capitalizedTag = tag
.trim()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" "); // Capitalize each word
option.value = tag.trim();
option.text = capitalizedTag;
select.appendChild(option);
}
});
select.addEventListener("change", () => {
filter.selectedTag = select.value.trim();
updateDefaultOptionText(select, filter);
updateURL(window.rk_filters);
});
updateDefaultOptionText(select, filter); // Set default text on page load
container.appendChild(select);
}
}
// Helper function to create a 'Cancel Filter' button
function createCancelFilterButton(container) {
const cancelButton = document.createElement("button");
cancelButton.className = "cancel-filter";
cancelButton.innerText = window.cancel_translation || "Cancel Filter";
cancelButton.addEventListener("click", () => {
window.location.href = window.blog;
});
container.appendChild(cancelButton);
}
document.addEventListener("DOMContentLoaded", () => {
const currentPath = window.location.pathname;
const filterContainer = document.getElementById("rk_filter");
if (window.rk_filters.length > 0) {
filterContainer.style.display = "flex";
}
window.rk_filters.forEach((filter) => {
createFilterDropdown(filter, filterContainer);
});
if (currentPath.includes("/tagged/")) {
createCancelFilterButton(filterContainer);
}
if (window.h1_placement == true) {
// Try to place the filter below the first H1 tag, if not leave it where it is:
// Search for the first h1 tag
const h1Element = document.querySelector("h1");
// Grab the rk_filter div element
const rkFilter = document.getElementById("rk_filter");
// Check if an h1 tag exists
// If no h1 tag is found, keep the rk_filter div in its current location
if (h1Element) {
// If an h1 tag is found, insert the rk_filter div right after it
h1Element.insertAdjacentElement("afterend", rkFilter);
}
}
});
{% liquid
assign filter_1_name = block.settings.filter_1_name
assign filter_1_tags = block.settings.filter_1_tags | split: ','
assign filter_2_name = block.settings.filter_2_name
assign filter_2_tags = block.settings.filter_2_tags | split: ','
assign filter_3_name = block.settings.filter_3_name
assign filter_3_tags = block.settings.filter_3_tags | split: ','
assign all_tags = blog.tags | uniq
%}
<script>
window.rk_filters = [
{
name: "{{ filter_1_name }}",
tags: {{ filter_1_tags | json }}
},
{
name: "{{ filter_2_name }}",
tags: {{ filter_2_tags | json }}
},
{
name: "{{ filter_3_name }}",
tags: {{ filter_3_tags | json }}
}
].map(filter => {
filter.tags = filter.tags.map(tag => tag.trim());
return filter;
});
window.all_tags = {{ all_tags | json }} || JSON.parse(localStorage.getItem('all_tags')) || [];
window.blog = '{{ blog.url }}';
window.h1_placement = {{ block.settings.h1_placement }};
window.all_translation = '{{ block.settings.all_translation }}';
window.cancel_translation = '{{ block.settings.cancel_translation }}';
</script>
<div id="rk_filter"></div>
<style>
#rk_filter {
justify-content: {{ block.settings.alignment }} !important;
}
#rk_filter button {
border: 1px solid {{ block.settings.button_colour | default: 'rgb(255, 130, 130)' }};
background-color: {{ block.settings.button_colour | default: 'rgb(255, 130, 130)' }};
}
</style>
{% schema %}
{
"name": "Recipe Kit Filter",
"target": "section",
"javascript": "filter.js",
"stylesheet": "filter.css",
"enabled_on": {
"templates": ["blog"]
},
"settings": [
{
"type": "text_alignment",
"id": "alignment",
"label": "Alignment"
},
{
"type": "checkbox",
"label": "Try placing filter near blog title",
"id": "h1_placement"
},
{
"type": "text",
"id": "filter_1_name",
"label": "Filter #1 Name (eg. Diet)"
},
{
"type": "text",
"id": "filter_1_tags",
"label": "Filter #1 Tags (eg. vegan, keto)"
},
{
"type": "text",
"id": "filter_2_name",
"label": "Filter #2 Name"
},
{
"type": "text",
"id": "filter_2_tags",
"label": "Filter #2 Tags"
},
{
"type": "text",
"id": "filter_3_name",
"label": "Filter #3 Name"
},
{
"type": "text",
"id": "filter_3_tags",
"label": "Filter #3 Tags"
},
{
"type": "color",
"id": "button_colour",
"label": "Cancel Button Colour"
},
{
"type": "header",
"content": "Translations",
"info": "Modify these fields if you need to change the various default English filter language to your store's language."
},
{
"type": "text",
"id": "all_translation",
"label": "All"
},
{
"type": "text",
"id": "cancel_translation",
"label": "Cancel Filter"
}
]
}
{% endschema %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment