-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8253f87
commit 4fc2745
Showing
31 changed files
with
14,225 additions
and
25 deletions.
There are no files selected for viewing
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>JSDoc: Source: hyperwave.js</title> | ||
|
||
<script src="scripts/prettify/prettify.js"> </script> | ||
<script src="scripts/prettify/lang-css.js"> </script> | ||
<!--[if lt IE 9]> | ||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> | ||
<![endif]--> | ||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> | ||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> | ||
</head> | ||
|
||
<body> | ||
|
||
<div id="main"> | ||
|
||
<h1 class="page-title">Source: hyperwave.js</h1> | ||
|
||
|
||
|
||
|
||
|
||
|
||
<section> | ||
<article> | ||
<pre class="prettyprint source linenums"><code>/** | ||
* Configuration object for hyperwave. | ||
* @typedef {Object} HyperwaveConfig | ||
* @property {boolean} debug - If true, enables debug mode which logs additional information. | ||
* @property {string} defaultMethod - The default HTTP method used for fetching content. | ||
* @property {number} defaultDebounceDelay - The default delay in milliseconds for debouncing events. | ||
* @property {number} defaultLimit - The default number of items to fetch per pagination request. | ||
* @property {number} defaultTotalItems - The default total number of items available for pagination. | ||
* @property {string} logPrefix - Prefix to use for log messages to distinguish them. | ||
*/ | ||
|
||
/** @type {HyperwaveConfig} */ | ||
const hyperwaveConfig = { | ||
debug: true, | ||
defaultMethod: "GET", | ||
defaultDebounceDelay: 50, | ||
defaultLimit: 32, | ||
defaultTotalItems: 2048, | ||
logPrefix: "hyperwave:", | ||
}; | ||
|
||
/** | ||
* Logs messages to the console if debug mode is enabled. | ||
* @param {string} level - The log level, e.g., "log" or "error". | ||
* @param {...any} messages - The messages or objects to log. | ||
*/ | ||
const log = (level, ...messages) => { | ||
if (hyperwaveConfig.debug) { | ||
console[level](`${hyperwaveConfig.logPrefix}`, ...messages); | ||
} | ||
}; | ||
|
||
/** | ||
* Creates a debounced version of the provided function. | ||
* @param {Function} func - The function to debounce. | ||
* @param {number} delay - The delay in milliseconds to wait before invoking the function. | ||
* @returns {Function} - The debounced function. | ||
*/ | ||
const createDebouncedFunction = (func, delay) => { | ||
let timeoutId; | ||
return (...args) => { | ||
clearTimeout(timeoutId); | ||
timeoutId = setTimeout(() => func.apply(this, args), delay); | ||
}; | ||
}; | ||
|
||
/** | ||
* Fetches content from a specified URL using the provided options. | ||
* @param {string} url - The URL to fetch content from. | ||
* @param {Object} [fetchOptions={}] - Options to customize the fetch request. | ||
* @param {string} [fetchOptions.method] - The HTTP method to use. | ||
* @param {Object} [fetchOptions.headers] - Headers to include in the request. | ||
* @returns {Promise<string|null>} - A promise that resolves to the fetched content or null if an error occurs. | ||
*/ | ||
const fetchContent = async (url, fetchOptions = {}) => { | ||
const options = { | ||
method: fetchOptions.method || hyperwaveConfig.defaultMethod, | ||
headers: { Accept: "text/html", ...fetchOptions.headers }, | ||
...fetchOptions, | ||
}; | ||
|
||
try { | ||
const response = await fetch(url, options); | ||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); | ||
const content = await response.text(); | ||
log("log", `Content fetched from ${url}`, content.length); | ||
return content; | ||
} catch (error) { | ||
log("error", `Error fetching from ${url}:`, error); | ||
return null; | ||
} | ||
}; | ||
|
||
/** | ||
* Updates a target element with new content, either replacing or appending based on mode. | ||
* @param {HTMLElement} targetElement - The element to update with new content. | ||
* @param {string} content - The HTML content to update. | ||
* @param {string} mode - The mode of updating, either "replace" or "append". | ||
*/ | ||
const updateTargetElement = (targetElement, content, mode = "replace") => { | ||
if (mode === "replace") { | ||
targetElement.innerHTML = content; | ||
} else if (mode === "append") { | ||
const tempDiv = document.createElement("div"); | ||
tempDiv.innerHTML = content; | ||
while (tempDiv.firstChild) { | ||
targetElement.appendChild(tempDiv.firstChild); | ||
} | ||
} | ||
attachHyperwaveHandlers(targetElement); | ||
}; | ||
|
||
/** | ||
* Constructs a URL for pagination with the given offset and limit. | ||
* @param {HTMLElement} triggerElement - The element that triggered the pagination. | ||
* @param {number} offset - The offset for pagination. | ||
* @param {number} limit - The limit for pagination. | ||
* @returns {string} - The constructed URL for pagination. | ||
*/ | ||
const buildPaginationUrl = (triggerElement, offset, limit) => { | ||
const url = new URL( | ||
triggerElement.getAttribute("href"), | ||
window.location.origin, | ||
); | ||
url.searchParams.set("offset", offset); | ||
url.searchParams.set("limit", limit); | ||
return url.toString(); | ||
}; | ||
|
||
/** | ||
* Handles pagination by fetching the next set of content and updating the target element. | ||
* @param {HTMLElement} triggerElement - The element that triggered the pagination. | ||
* @param {Object} fetchOptions - Options to customize the fetch request. | ||
* @returns {Function} - A function to handle fetching the next page of content. | ||
*/ | ||
const handlePagination = (triggerElement, fetchOptions) => { | ||
let offset = parseInt(triggerElement.getAttribute("offset") || "0", 10); | ||
const limit = parseInt( | ||
triggerElement.getAttribute("limit") || hyperwaveConfig.defaultLimit, | ||
10, | ||
); | ||
const totalItems = parseInt( | ||
triggerElement.getAttribute("total") || hyperwaveConfig.defaultTotalItems, | ||
10, | ||
); | ||
const mode = triggerElement.getAttribute("update-mode") || "replace"; | ||
|
||
let isFetching = false; | ||
|
||
return async () => { | ||
if (isFetching || offset >= totalItems) return; | ||
|
||
isFetching = true; | ||
const url = buildPaginationUrl(triggerElement, offset, limit); | ||
const content = await fetchContent(url, fetchOptions); | ||
if (content) { | ||
const target = document.querySelector( | ||
triggerElement.getAttribute("target"), | ||
); | ||
updateTargetElement(target, content, mode); | ||
offset += limit; | ||
triggerElement.setAttribute("offset", offset); | ||
log("log", `Content updated. New offset set: ${offset}`); | ||
} | ||
isFetching = false; | ||
}; | ||
}; | ||
|
||
/** | ||
* Sets up event handlers for the given trigger element based on its attributes. | ||
* @param {HTMLElement} triggerElement - The element to set up event handlers for. | ||
*/ | ||
const setupEventHandlers = (triggerElement) => { | ||
const method = | ||
triggerElement.getAttribute("method") || hyperwaveConfig.defaultMethod; | ||
const trigger = triggerElement.getAttribute("trigger") || "click"; | ||
const debounceDelay = parseInt( | ||
triggerElement.getAttribute("debounce") || | ||
hyperwaveConfig.defaultDebounceDelay, | ||
10, | ||
); | ||
const scrollThreshold = parseInt( | ||
triggerElement.getAttribute("scroll-threshold") || "300", | ||
10, | ||
); | ||
|
||
const fetchOptions = { | ||
method: method.toUpperCase(), | ||
headers: { Accept: "text/html" }, | ||
}; | ||
|
||
log( | ||
"log", | ||
`Setting up event handlers: method=${method}, trigger=${trigger}, debounceDelay=${debounceDelay}, scrollThreshold=${scrollThreshold}`, | ||
); | ||
|
||
const loadNextPage = handlePagination(triggerElement, fetchOptions); | ||
|
||
const eventHandler = createDebouncedFunction(async (event) => { | ||
if (trigger !== "scroll") event.preventDefault(); | ||
|
||
if (trigger === "scroll") { | ||
const nearBottom = | ||
document.body.offsetHeight - (window.innerHeight + window.scrollY) <= | ||
scrollThreshold; | ||
if (!nearBottom) return; | ||
} | ||
|
||
await loadNextPage(); | ||
}, debounceDelay); | ||
|
||
if (trigger === "DOMContentLoaded") { | ||
loadNextPage(); | ||
} else { | ||
const targetElement = trigger === "scroll" ? window : triggerElement; | ||
targetElement.addEventListener(trigger, eventHandler); | ||
triggerElement._hyperwaveHandler = eventHandler; | ||
|
||
if (trigger === "scroll") { | ||
loadNextPage(); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Attaches hyperwave event handlers to all elements within a given root element. | ||
* @param {HTMLElement} rootElement - The root element to search for trigger elements. | ||
*/ | ||
const attachHyperwaveHandlers = (rootElement) => { | ||
const elements = Array.from(rootElement.querySelectorAll("[href]")).filter( | ||
(element) => !["A", "LINK"].includes(element.tagName), | ||
); | ||
elements.forEach((element) => setupEventHandlers(element)); | ||
}; | ||
|
||
document.addEventListener("DOMContentLoaded", () => { | ||
log("log", "DOMContentLoaded event triggered"); | ||
attachHyperwaveHandlers(document); | ||
|
||
const observer = new MutationObserver((mutations) => { | ||
mutations.forEach((mutation) => { | ||
mutation.addedNodes.forEach((node) => { | ||
if (node.nodeType === Node.ELEMENT_NODE) { | ||
log("log", "MutationObserver detected new element:", node); | ||
attachHyperwaveHandlers(node); | ||
} | ||
}); | ||
}); | ||
}); | ||
|
||
observer.observe(document.body, { childList: true, subtree: true }); | ||
}); | ||
</code></pre> | ||
</article> | ||
</section> | ||
|
||
|
||
|
||
|
||
</div> | ||
|
||
<nav> | ||
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#attachHyperwaveHandlers">attachHyperwaveHandlers</a></li><li><a href="global.html#buildPaginationUrl">buildPaginationUrl</a></li><li><a href="global.html#createDebouncedFunction">createDebouncedFunction</a></li><li><a href="global.html#fetchContent">fetchContent</a></li><li><a href="global.html#handlePagination">handlePagination</a></li><li><a href="global.html#hyperwaveConfig">hyperwaveConfig</a></li><li><a href="global.html#log">log</a></li><li><a href="global.html#setupEventHandlers">setupEventHandlers</a></li><li><a href="global.html#updateTargetElement">updateTargetElement</a></li></ul> | ||
</nav> | ||
|
||
<br class="clear"> | ||
|
||
<footer> | ||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.3</a> on Wed Jul 17 2024 18:00:30 GMT-0500 (Central Daylight Time) | ||
</footer> | ||
|
||
<script> prettyPrint(); </script> | ||
<script src="scripts/linenumber.js"> </script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>JSDoc: Home</title> | ||
|
||
<script src="scripts/prettify/prettify.js"> </script> | ||
<script src="scripts/prettify/lang-css.js"> </script> | ||
<!--[if lt IE 9]> | ||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> | ||
<![endif]--> | ||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> | ||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> | ||
</head> | ||
|
||
<body> | ||
|
||
<div id="main"> | ||
|
||
<h1 class="page-title">Home</h1> | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<h3> </h3> | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
</div> | ||
|
||
<nav> | ||
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#attachHyperwaveHandlers">attachHyperwaveHandlers</a></li><li><a href="global.html#buildPaginationUrl">buildPaginationUrl</a></li><li><a href="global.html#createDebouncedFunction">createDebouncedFunction</a></li><li><a href="global.html#fetchContent">fetchContent</a></li><li><a href="global.html#handlePagination">handlePagination</a></li><li><a href="global.html#hyperwaveConfig">hyperwaveConfig</a></li><li><a href="global.html#log">log</a></li><li><a href="global.html#setupEventHandlers">setupEventHandlers</a></li><li><a href="global.html#updateTargetElement">updateTargetElement</a></li></ul> | ||
</nav> | ||
|
||
<br class="clear"> | ||
|
||
<footer> | ||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.3</a> on Wed Jul 17 2024 18:00:30 GMT-0500 (Central Daylight Time) | ||
</footer> | ||
|
||
<script> prettyPrint(); </script> | ||
<script src="scripts/linenumber.js"> </script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/*global document */ | ||
(() => { | ||
const source = document.getElementsByClassName('prettyprint source linenums'); | ||
let i = 0; | ||
let lineNumber = 0; | ||
let lineId; | ||
let lines; | ||
let totalLines; | ||
let anchorHash; | ||
|
||
if (source && source[0]) { | ||
anchorHash = document.location.hash.substring(1); | ||
lines = source[0].getElementsByTagName('li'); | ||
totalLines = lines.length; | ||
|
||
for (; i < totalLines; i++) { | ||
lineNumber++; | ||
lineId = `line${lineNumber}`; | ||
lines[i].id = lineId; | ||
if (lineId === anchorHash) { | ||
lines[i].className += ' selected'; | ||
} | ||
} | ||
} | ||
})(); |
Oops, something went wrong.