Skip to content

Commit

Permalink
Comment the js.
Browse files Browse the repository at this point in the history
  • Loading branch information
EarthlingDavey committed Oct 15, 2024
1 parent 03b5b18 commit fcee827
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 138 deletions.
140 changes: 3 additions & 137 deletions public/app/themes/clarity/src/globals/js/ajax-filter.js
Original file line number Diff line number Diff line change
@@ -1,140 +1,8 @@
import AjaxTemplating from "./ajax-templating.js";
import { getFormData, renderResults, renderPagination } from "./ajax-utils.js";

export default (function ($) {
/**
* Render the response to the page.
*
* The results type should match the php response object
* as returned by the `FilterSearch->mapResults()` method.
* @typedef {Object} Post
* @property {string} ID
* @property {string} post_title
* @property {string} post_date_formatted
* @property {string} post_excerpt_formatted
* @property {string} permalink
* @property {string} post_type
* @property {string} post_thumbnail
* @property {string} post_thumbnail_alt
*
* @typedef {Object} Results
* @property {Post[]} posts
* @property {string} templateName
*
* The response type should match the php response object
* as returned by the `FilterSearch->loadSearchResults()` method.
* @typedef {Object} Response
* @property {Object} aggregates
* @property {number} aggregates.currentPage
* @property {number} aggregates.resultsPerPage
* @property {number} aggregates.totalResults
* @property {Results} results
*
* @param {Response} response
*/

const renderResults = ({
results: { posts, templateName },
aggregates: { currentPage, totalResults },
}) => {
// Remove all articles if page is 1.
if (currentPage === 1) {
$(".c-article-item, .c-events-item-list").remove();
}

const t = new AjaxTemplating(templateName);

const resultsHtml = posts.map((props) => t.renderHtml(props));

// Append the html to the content section.
$("#content").append(resultsHtml);

// Update the title.
$("#title-section").text(`${totalResults} search results`);
};

/**
* Render pagination to the page.
*/

const renderPagination = ({ currentPage, resultsPerPage, totalResults }) => {

if(resultsPerPage === undefined || resultsPerPage === -1) {
return;
}

const isLastPage = currentPage * resultsPerPage >= totalResults;

const paginationTitle = ({ totalResults, isLastPage }) => {
if (!totalResults) {
return "No Results";
}
if (isLastPage) {
return "No More Results";
}
return `Load Next ${resultsPerPage} Results`;
};

const template = new AjaxTemplating("pagination");

// Update the pagination.
const paginationHtml = template.renderHtml({
title: paginationTitle({ totalResults, isLastPage }),
// Disable the button if it's the last page.
disabled: isLastPage ? `disabled="disabled"` : "",
// Adjust the zero-indexed current page.
currentPageFormatted: parseInt(currentPage),
// Calculate the total pages - if no results, then set as 1 to render '1 of 1'.
totalPages: !totalResults ? 1 : Math.ceil(totalResults / resultsPerPage),
});

$(".c-pagination").html(paginationHtml);

// Update the page number on the pagination element.
if (!isLastPage) {
$(".c-pagination button").attr("data-page", currentPage + 1);
}
};

/**
* Parse a form instance into an object.
*
* @param {HTMLElement} form
* @returns {[string, string][]}
*/

const getFormData = (form) => {
const formData = new FormData(form);

const prefix = formData.get("prefix");

// Loop all form entries, remove the prefix from keys, and assign to data.
const entries = [...formData.entries()]
.map(([key, value]) => {
// Remove prefix if it exists.
const newKey = key.startsWith(prefix) ? key.replace(prefix, "") : key;

// Parse the page number to integer.
if ("page" === newKey) {
value = parseInt(value);
}

return [newKey, value];
})
.filter(([key, value]) => {
// Skip prefix and template keys, and empty values.
if (["prefix"].includes(key) || value === "") {
return false;
}

return true;
});

entries.push(["action", $(form).attr("action")]);

return Object.fromEntries(entries);
};

$.fn.moji_ajaxFilter = function () {
// Default ajax props.
const DEFAULT_AJAX_PROPS = {
type: "POST",
url: mojAjax.ajaxurl,
Expand All @@ -147,12 +15,10 @@ export default (function ($) {

const $form = $("#ff, #ff_events");

const initialFormData = getFormData($form.get(0));

// On page load get the ajax props and store them on the pagination element.
$(".c-pagination").data("ajax-props", {
...DEFAULT_AJAX_PROPS,
data: initialFormData,
data: getFormData($form.get(0)),
});

/**
Expand Down
3 changes: 2 additions & 1 deletion public/app/themes/clarity/src/globals/js/ajax-templating.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* This Class is responsible for rendering HTML from AJAX template.
* This class is responsible for rendering HTML from an AJAX template.
*
* This is an extension of a bare bones templating engine.
* @see https://stackoverflow.com/a/39065147/6671505
*
* @example
Expand Down
144 changes: 144 additions & 0 deletions public/app/themes/clarity/src/globals/js/ajax-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import AjaxTemplating from "./ajax-templating.js";

/**
* Parse the values of a form instance into an object.
*
* @param {HTMLElement} form
* @returns {[string, string][]}
*/

export const getFormData = (form) => {
const formData = new FormData(form);

const prefix = formData.get("prefix");

// Loop all form entries, remove the prefix from keys, and assign to data.
const entries = [...formData.entries()]
.map(([key, value]) => {
// Remove prefix if it exists.
const newKey = key.startsWith(prefix) ? key.replace(prefix, "") : key;

// Parse the page number to integer.
if ("page" === newKey) {
value = parseInt(value);
}

return [newKey, value];
})
.filter(([key, value]) => {
// Skip prefix and template keys, and empty values.
if (["prefix"].includes(key) || value === "") {
return false;
}

return true;
});

entries.push(["action", $(form).attr("action")]);

return Object.fromEntries(entries);
};

/**
* Render the response to the page.
*
* The results type should match the php response object
* as returned by the `FilterSearch->mapResults()` method.
*
* @typedef {Object} Post
* @property {string} ID
* @property {string} post_title
* @property {string} post_date_formatted
* @property {string} post_excerpt_formatted
* @property {string} permalink
* @property {string} post_type
* @property {string} post_thumbnail
* @property {string} post_thumbnail_alt
*
* @typedef {Object} Results
* @property {Post[]} posts
* @property {string} templateName
*
* The response type should match the php response object
* as returned by the `FilterSearch->loadSearchResults()` method.
*
* @typedef {Object} Response
* @property {Object} aggregates
* @property {number} aggregates.currentPage
* @property {number} aggregates.resultsPerPage
* @property {number} aggregates.totalResults
* @property {Results} results
*
* @param {Response} response
*/

export const renderResults = ({
results: { posts, templateName },
aggregates: { currentPage, totalResults },
}) => {
// Remove all articles if page is 1.
if (currentPage === 1) {
$(".c-article-item, .c-events-item-list").remove();
}

// Load an instance of the AjaxTemplating class.
const t = new AjaxTemplating(templateName);

// Render the html for each post.
const resultsHtml = posts.map((props) => t.renderHtml(props));

// Append the html to the content section.
$("#content").append(resultsHtml);

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.

// Update the title.
$("#title-section").text(`${totalResults} search results`);
};

/**
* Render pagination to the page.
*
* @param {Object} props
* @param {number} props.currentPage
* @param {number} props.resultsPerPage
* @param {number} props.totalResults
*
* @returns {void}
*/

export const renderPagination = ({ currentPage, resultsPerPage, totalResults }) => {
if (resultsPerPage === undefined || resultsPerPage === -1) {
return;
}

const isLastPage = currentPage * resultsPerPage >= totalResults;

const paginationTitle = ({ totalResults, isLastPage }) => {
if (!totalResults) {
return "No Results";
}
if (isLastPage) {
return "No More Results";
}
return `Load Next ${resultsPerPage} Results`;
};

const template = new AjaxTemplating("pagination");

// Update the pagination.
const paginationHtml = template.renderHtml({
title: paginationTitle({ totalResults, isLastPage }),
// Disable the button if it's the last page.
disabled: isLastPage ? `disabled="disabled"` : "",
// Adjust the zero-indexed current page.
currentPageFormatted: parseInt(currentPage),
// Calculate the total pages - if no results, then set as 1 to render '1 of 1'.
totalPages: !totalResults ? 1 : Math.ceil(totalResults / resultsPerPage),
});

$(".c-pagination").html(paginationHtml);

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.

// Update the page number on the pagination element.
if (!isLastPage) {
$(".c-pagination button").attr("data-page", currentPage + 1);
}
};

0 comments on commit fcee827

Please sign in to comment.