From 6d1497f3ba53722c0ed4c5f851016a1018123e0e Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Wed, 28 Aug 2024 20:31:54 -0700 Subject: [PATCH] Add documentation to PNI search related JS files (#12742) * Added doc to utils.js * Added doc to pni-sort-dropdown.js and pni-toggle.js * Added doc to slider-area.js * Added doc to member-functions.js * Added doc to history.js --- source/js/buyers-guide/search/history.js | 35 +++++++--- .../buyers-guide/search/member-functions.js | 17 ++++- .../buyers-guide/search/pni-sort-dropdown.js | 28 ++++++++ source/js/buyers-guide/search/pni-toggle.js | 9 +++ source/js/buyers-guide/search/slider-area.js | 21 +++++- source/js/buyers-guide/search/utils.js | 66 +++++++++++++------ 6 files changed, 140 insertions(+), 36 deletions(-) diff --git a/source/js/buyers-guide/search/history.js b/source/js/buyers-guide/search/history.js index 54bfaffa240..cb11b8012f3 100644 --- a/source/js/buyers-guide/search/history.js +++ b/source/js/buyers-guide/search/history.js @@ -6,10 +6,13 @@ const parentTitle = document.querySelector(`.parent-title`); const toggle = document.querySelector(`#product-filter-pni-toggle`); /** - * ... + * Set up history management + * * @param {*} instance - * @param {*} searchBar - * @param {*} searchInput + * @param {Element} searchBar - The search bar element + * @param {Element} searchInput - The search input element + * @param {Element} mobileSearchBar - The mobile search bar element + * @param {Element} mobileSearchInput - The mobile search input element */ export function setupHistoryManagement( instance, @@ -35,10 +38,18 @@ export function setupHistoryManagement( } /** - * ... + * Update History state and update page UI accordingly + * * @param {*} instance - * @param {*} searchBar - * @param {*} searchInput + * @param {Element} searchBar - The search bar element + * @param {Element} searchInput - The search input element + * @param {Element} mobileSearchBar - The mobile search bar element + * @param {Element} mobileSearchInput - The mobile search input element + * + * @todo FIXME. We need to revisit and improve the implementation of this function. + * It's unclear why history.replaceState needs to be called twice. + * It's also unclear why there are repeated if-else statements especially for search parameters. + * Further investigation is needed to understand the purpose of this function. */ export function performInitialHistoryReplace( instance, @@ -120,10 +131,13 @@ export function performInitialHistoryReplace( } /** - * ... + * Set up the window.popstate event listener + * * @param {*} instance - * @param {*} searchBar - * @param {*} searchInput + * @param {Element} searchBar - The search bar element + * @param {Element} searchInput - The search input element + * @param {Element} mobileSearchBar - The mobile search bar element + * @param {Element} mobileSearchInput - The mobile search input element */ export function setupPopStateHandler( instance, @@ -183,7 +197,8 @@ export function setupPopStateHandler( } /** - * ... + * Apply data stored in the history state to the page + * * @param {*} instance */ export function applyHistory(instance) { diff --git a/source/js/buyers-guide/search/member-functions.js b/source/js/buyers-guide/search/member-functions.js index bb178e42d4c..9cfe673255b 100644 --- a/source/js/buyers-guide/search/member-functions.js +++ b/source/js/buyers-guide/search/member-functions.js @@ -5,7 +5,8 @@ const parentTitle = document.querySelector(`.parent-title`); const subcategories = document.querySelectorAll(`.subcategories`); /** - * ... + * Attach event listeners to the nav links and subcategory links + * * @param {*} instance */ export function setupNavLinks(instance) { @@ -116,7 +117,8 @@ export function setupNavLinks(instance) { } /** - * ... + * Attach event listeners to "go back to all" link + * * @param {*} instance */ export function setupGoBackToAll(instance) { @@ -153,8 +155,11 @@ export function setupGoBackToAll(instance) { } /** - * ... + * Attach event listeners to the Product Review nav links + * * @param {*} instance + * + * @todo See if we can make this DRYer by making use of the toggleProductReviewView function? */ export function setupReviewLinks(instance) { const navLinks = document.querySelectorAll(`.product-review-link`); @@ -179,6 +184,9 @@ export function setupReviewLinks(instance) { } } +/** + * Toggle the Product Review view + */ export function toggleProductReviewView() { const editorialContent = document.querySelector(".editorial-content"); const navLinks = document.querySelectorAll(`.product-review-link`); @@ -190,6 +198,9 @@ export function toggleProductReviewView() { } } +/** + * Toggle the category related articles section + */ export function toggleCategoryRelatedArticles(category) { const relatedArticles = document.querySelectorAll("[data-show-for-category]"); diff --git a/source/js/buyers-guide/search/pni-sort-dropdown.js b/source/js/buyers-guide/search/pni-sort-dropdown.js index 154ec8305fd..a4813c3455c 100644 --- a/source/js/buyers-guide/search/pni-sort-dropdown.js +++ b/source/js/buyers-guide/search/pni-sort-dropdown.js @@ -4,6 +4,9 @@ const DOWN_ARROW_KEY_CODE = 40; const UP_ARROW_KEY_CODE = 38; const ESCAPE_KEY_CODE = 27; +/** + * Dropdown component for sorting products on PNI + */ export class PNISortDropdown { constructor(searchFilter) { this.searchFilter = searchFilter; @@ -81,6 +84,11 @@ export class PNISortDropdown { } } + /** + * Sets the selected list item and updates the dropdown button content. + * @param {Event} e - The event (e.g., click, keydown) + * @param {boolean} [pushUpdate=true] - Whether to push the update to the history state. + */ setSelectedListItem(e, pushUpdate = true) { this.listItems.forEach((item) => { const itemDiv = item.querySelector("div"); @@ -99,12 +107,20 @@ export class PNISortDropdown { } } + /** + * Closes the dropdown list. + */ closeList() { this.listContainer.classList.add("tw-hidden"); this.dropdownButton.setAttribute("aria-expanded", false); this.dropdownButtonArrow.classList.remove("tw-rotate-180"); } + /** + * Opens the dropdown list. + * + * @param {boolean} [withFocus=false] - Whether to focus on the first list item. + */ openList(withFocus = false) { this.listContainer.classList.remove("tw-hidden"); this.dropdownButton.setAttribute("aria-expanded", true); @@ -118,6 +134,11 @@ export class PNISortDropdown { } } + /** + * Toggle the visibility of the dropdown list + * + * @param {Event} e The event (e.g., click, keydown) + */ toggleListVisibility(e) { const isExpanded = this.dropdownButton.getAttribute("aria-expanded") === "true"; @@ -140,6 +161,13 @@ export class PNISortDropdown { } } + /** + * Focus on the next list item based on the given direction. + * + * @param {number} direction - They key code of the direction to move the focus (e.g., key code for up arrow / down arrow) + * + * @todo Consider refactoring this method to make it more readable and maintainable. + */ focusNextListItem(direction) { const activeElementId = document.activeElement.id; const currentActiveElementIndex = this.listItemIds.indexOf(activeElementId); diff --git a/source/js/buyers-guide/search/pni-toggle.js b/source/js/buyers-guide/search/pni-toggle.js index b5c3a47b576..9afbd22218b 100644 --- a/source/js/buyers-guide/search/pni-toggle.js +++ b/source/js/buyers-guide/search/pni-toggle.js @@ -1,6 +1,9 @@ import { Utils } from "./utils.js"; import { gsap } from "gsap"; +/** + * The control that toggles the "Privacy Not Included" filter on the product list. + */ export class PNIToggle { constructor(searchFilter) { this.searchFilter = searchFilter; @@ -51,7 +54,13 @@ export class PNIToggle { }); } + /** + * Toggle the "Privacy Not Included" filter on the product list. + * + * @param {boolean} doFilter - Whether to filter the list for "Privacy Not Included" products. + */ togglePrivacyOnly(doFilter) { + console.log(doFilter); const { searchFilter, categoryTitle } = this; gsap.set("figure.product-box.privacy-ding", { opacity: 1, y: 0 }); diff --git a/source/js/buyers-guide/search/slider-area.js b/source/js/buyers-guide/search/slider-area.js index 524d14323cc..395030816eb 100644 --- a/source/js/buyers-guide/search/slider-area.js +++ b/source/js/buyers-guide/search/slider-area.js @@ -1,8 +1,8 @@ /** - * mouse/touch scroll functionality for the category area - * @param {*} event + * Mouse/touch scroll functionality for the sub category area on mobile + * + * @todo Rename this file to something more specific. Maybe something like subcategory-scroll.js */ - const subcategories = document.querySelectorAll(`.subcategories`); const subContainer = document.querySelector(`.subcategory-header`); const subClasses = subContainer.classList; @@ -14,6 +14,11 @@ function stop(evt) { evt.stopImmediatePropagation(); } +/** + * A event handler that initiate the scroll functionality on the sub category area + * + * @param {Event} event The event that triggered the function + */ export function markScrollStart(event) { stop(event); subClasses.add("cursor-grabbing", "select-none"); @@ -27,6 +32,11 @@ export function markScrollStart(event) { document.addEventListener(`mouseup`, markScrollEnd); } +/** + * A event handler for moving the scorll on the sub category area + * + * @param {Event} event The event that triggered the function + */ function markScrollMove(event) { subcategories.forEach((subcategory) => { subcategory.classList.add("pointer-events-none"); @@ -35,6 +45,11 @@ function markScrollMove(event) { subContainer.scrollLeft = pos.left - dx; } +/** + * A event handler for stopping the scorll on the sub category area + * + * @param {Event} event The event that triggered the function + */ function markScrollEnd(event) { stop(event); diff --git a/source/js/buyers-guide/search/utils.js b/source/js/buyers-guide/search/utils.js index f6544c1e62e..5e57d3c32e7 100644 --- a/source/js/buyers-guide/search/utils.js +++ b/source/js/buyers-guide/search/utils.js @@ -14,9 +14,10 @@ const PARENT_TITLE = document.querySelector(`.parent-title`); export class Utils { /** - *... - * @param {*} category - * @returns + * Return the title of the page based on the category passed in the argument + * + * @param {String} category name of the category + * @returns {String} title of the page */ static getTitle(category) { if (category == "None") @@ -29,9 +30,12 @@ export class Utils { } /** - * ... + * Update page header to the category passed in the argument + * * @param {*} category * @param {*} parent + * + * @todo Improve the implementation to increase code readibility */ static updateHeader(category, parent) { const headerText = document.querySelector(".category-header"); @@ -90,6 +94,7 @@ export class Utils { /** * Activate a specific category nav link + * * @param {String} category category name */ static activateCatNav(category = "None") { @@ -113,6 +118,7 @@ export class Utils { /** * Set active category nav link + * * @param {String} category name of the category */ static setActiveCatNavLink(category) { @@ -128,8 +134,11 @@ export class Utils { } /** - * ... - * @param {*} text + * Toggle products' visibility based on search text + * + * @param {String} text search text + * + * @todo Rename to "filterProductsBySearchText" */ static toggleProducts(text) { gsap.set(ALL_PRODUCTS, { opacity: 1, y: 0 }); @@ -147,7 +156,7 @@ export class Utils { } /** - * Scroll Animation used solely for the 'All Products' section + * Scroll animation used solely for the 'All Products' section */ static toggleScrollAnimation() { gsap.set("figure.product-box.d-flex", { opacity: 0, y: 100 }); @@ -204,8 +213,11 @@ export class Utils { } /** - * ... - * @param {*} category + * Toggle products' visibility based on category + * + * @param {String} category category name + * + * @todo Rename to "filterProductsByCategory" */ static showProductsForCategory(category) { gsap.set(ALL_PRODUCTS, { opacity: 1, y: 0 }); @@ -222,8 +234,9 @@ export class Utils { } /** - * ... - * @param {*} category + * Toggle CTA visibility based on category + * + * @param {String} category category name */ static toggleCtaForCategory(category) { const categoryPageCta = document.getElementById("category-featured-cta"); @@ -239,10 +252,13 @@ export class Utils { } /** - * ... - * @param {*} product - * @param {*} text - * @returns + * Test if any of the product fields contains the search text + * + * @param {Element} product DOM element of the product + * @param {String} text search text + * @returns {Boolean} Whether the product contains the search text + * + * @todo Rename to "doesProductContainSearchText" */ static test(product, text) { // Note that the following is absolutely not true for all @@ -263,16 +279,18 @@ export class Utils { } /** - * ... - * @param {*} product - * @param {*} category - * @returns + * Check if the product belongs to the category + * + * @param {Element} product DOM element of the product + * @param {String} category category name + * @returns {Boolean} Whether the product belongs to the category */ static testCategories(product, category) { if (category === "None") { return true; } + // all the categories this product belongs to const productCategories = Array.from( product.querySelectorAll(".product-categories") ); @@ -281,7 +299,7 @@ export class Utils { } /** - * ... + * Sort the products by the default sort order */ static sortFilteredProducts() { const container = document.querySelector(`.product-box-list`); @@ -316,7 +334,9 @@ export class Utils { } /** + * Toggle the visibility of "no results" notice * + * @todo Rename to "toggleNoResultsNotice" */ static checkForEmptyNotice() { let qs = `figure.product-box:not(.d-none)`; @@ -336,6 +356,11 @@ export class Utils { } } + /** + * Toggle the visibility of the creepy face and speech + * + * @todo Rename to "toggleCreepyFace" + */ static moveCreepyFace() { const CREEPINESS_FACE = document.querySelector( ".creep-o-meter-information" @@ -383,6 +408,7 @@ export class Utils { /** * Scroll to a specific subcategory nav link if it exists on the page + * * @param {string} category - The name of the category */ static scrollToSubCategory(category) {