diff --git a/index.html b/index.html index 0054f6e5f..d479fe384 100644 --- a/index.html +++ b/index.html @@ -1,14 +1,10 @@ - Patterns demo pages - - + + +

Demos and documentation for the individual patterns

diff --git a/src/core/base.js b/src/core/base.js index b118ce487..285a6107e 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -46,6 +46,10 @@ const initBasePattern = function ($el, options, trigger) { }; const Base = async function ($el, options, trigger) { + if (!$el) { + log.warn("No element given to pattern."); + return; + } if (!$el.jquery) { $el = $($el); } diff --git a/src/core/base.test.js b/src/core/base.test.js index d1bfb2770..79ad83e88 100644 --- a/src/core/base.test.js +++ b/src/core/base.test.js @@ -58,6 +58,18 @@ describe("pat-base: The Base class for patterns", function () { expect(tmp.el).toBe(node); }); + it("Does nothing when initialized with no DOM node", function () { + const Tmp = Base.extend({ + name: "example", + init: () => {}, + }); + const tmp = new Tmp(null); + console.log(tmp); + expect(tmp instanceof Tmp).toBeTruthy(); + expect(tmp.$el).toBeFalsy(); + expect(tmp.el).toBeFalsy(); + }); + it("will automatically register a pattern in the registry when extended", function () { jest.spyOn(registry, "register"); var NewPattern = Base.extend({ diff --git a/src/core/dom.js b/src/core/dom.js index 1cd739706..ccb8ade37 100644 --- a/src/core/dom.js +++ b/src/core/dom.js @@ -4,8 +4,14 @@ import events from "./events"; const DATA_PREFIX = "__patternslib__data_prefix__"; const DATA_STYLE_DISPLAY = "__patternslib__style__display"; +/** + * Return an array of DOM nodes. + * + * @param {Node|NodeList|jQuery} nodes - The DOM node to start the search from. + * + * @returns {Array} - An array of DOM nodes. + */ const toNodeArray = (nodes) => { - // Return an array of DOM nodes if (nodes.jquery || nodes instanceof NodeList) { // jQuery or document.querySelectorAll nodes = [...nodes]; @@ -15,10 +21,15 @@ const toNodeArray = (nodes) => { return nodes; }; +/** + * Like querySelectorAll but including the element where it starts from. + * Returns an Array, not a NodeList + * + * @param {Node} el - The DOM node to start the search from. + * + * @returns {Array} - The DOM nodes found. + */ const querySelectorAllAndMe = (el, selector) => { - // Like querySelectorAll but including the element where it starts from. - // Returns an Array, not a NodeList - if (!el) { return []; } @@ -30,16 +41,23 @@ const querySelectorAllAndMe = (el, selector) => { return all; }; +/** + * Wrap a element with a wrapper element. + * + * @param {Node} el - The DOM node to wrap. + */ const wrap = (el, wrapper) => { - // Wrap a element with a wrapper element. // See: https://stackoverflow.com/a/13169465/1337474 - el.parentNode.insertBefore(wrapper, el); wrapper.appendChild(el); }; +/** + * Hides the element with ``display: none`` and stores the current display value. + * + * @param {Node} el - The DOM node to hide. + */ const hide = (el) => { - // Hides the element with ``display: none`` if (el.style.display === "none") { // Nothing to do. return; @@ -51,38 +69,65 @@ const hide = (el) => { el.setAttribute("hidden", ""); }; +/** + * Shows element by removing ``display: none`` and restoring the display value + * to whatever it was before. + * + * @param {Node} el - The DOM node to show. + */ const show = (el) => { - // Shows element by removing ``display: none`` and restoring the display - // value to whatever it was before. const val = el[DATA_STYLE_DISPLAY] || null; el.style.display = val; delete el[DATA_STYLE_DISPLAY]; el.removeAttribute("hidden", ""); }; +/** + * Return all direct parents of ``el`` matching ``selector``. + * This matches against all parents but not the element itself. + * The order of elements is from the search starting point up to higher + * DOM levels. + * + * @param {Node} el - The DOM node to start the search from. + * @param {String} selector - CSS selector to match against. + * @returns {Array} - List of matching DOM nodes. + */ const find_parents = (el, selector) => { - // Return all direct parents of ``el`` matching ``selector``. - // This matches against all parents but not the element itself. - // The order of elements is from the search starting point up to higher - // DOM levels. const ret = []; - let parent = el?.parentNode?.closest?.(selector); + let parent = el; while (parent) { - ret.push(parent); parent = parent.parentNode?.closest?.(selector); + if (parent) ret.push(parent); } return ret; }; +/** + * Find an element in the whole DOM tree if the selector is an ID selector, + * otherwise use the given element as the starting point. + * + * @param {Node} el - The DOM node to start the search from. + * @param {String} selector - The CSS selector to search for. + * + * @returns {NodeList} - The DOM nodes found. + * + */ const find_scoped = (el, selector) => { // If the selector starts with an object id do a global search, // otherwise do a local search. return (selector.indexOf("#") === 0 ? document : el).querySelectorAll(selector); }; +/** + * Return all HTMLElement parents of el, starting from the direct parent of el. + * The document itself is excluded because it's not a real DOM node. + * + * @param {Node} el - The DOM node to start the search from. + * + * @returns {Array} - The DOM nodes found. + */ const get_parents = (el) => { // Return all HTMLElement parents of el, starting from the direct parent of el. - // The document itself is excluded because it's not a real DOM node. const parents = []; let parent = el?.parentNode; while (parent) { @@ -211,7 +256,7 @@ const find_scroll_container = (el, direction, fallback = document.body) => { * @param name {String} - The name of the variable. Note - this is stored on * the DOM node prefixed with the DATA_PREFIX. * @param default_value {Any} - Optional default value. - * @return {Any} - The value which is stored on the DOM node. + * @returns {Any} - The value which is stored on the DOM node. */ const get_data = (el, name, default_value) => { return el[`${DATA_PREFIX}${name}`] || default_value; diff --git a/src/core/dom.test.js b/src/core/dom.test.js index 96f47442c..6595b8cfd 100644 --- a/src/core/dom.test.js +++ b/src/core/dom.test.js @@ -177,12 +177,14 @@ describe("core.dom tests", () => { done(); }); + it("don't break with no element.", (done) => { const res = dom.find_parents(null, ".findme"); expect(res.length).toEqual(0); done(); }); + it("don't break with DocumentFragment without a parent.", (done) => { const el = new DocumentFragment(); el.innerHTML = `
`; diff --git a/src/core/utils.js b/src/core/utils.js index 2c93bc832..b96b20728 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -156,14 +156,6 @@ function extend(obj) { } // END: Taken from Underscore.js until here. -function rebaseURL(base, url) { - base = new URL(base, window.location).href; // If base is relative make it absolute. - if (url.indexOf("://") !== -1 || url[0] === "/" || url.indexOf("data:") === 0) { - return url; - } - return base.slice(0, base.lastIndexOf("/") + 1) + url; -} - function findLabel(input) { var $label; for ( @@ -683,7 +675,6 @@ var utils = { escapeRegExp: escapeRegExp, isObject: isObject, extend: extend, - rebaseURL: rebaseURL, findLabel: findLabel, elementInViewport: elementInViewport, removeWildcardClass: removeWildcardClass, diff --git a/src/core/utils.test.js b/src/core/utils.test.js index 6ff61683b..c0d0cdb64 100644 --- a/src/core/utils.test.js +++ b/src/core/utils.test.js @@ -3,50 +3,6 @@ import $ from "jquery"; import { jest } from "@jest/globals"; describe("basic tests", function () { - describe("rebaseURL", function () { - it("Keep URL with scheme", function () { - expect( - utils.rebaseURL("http://example.com/foo/", "http://other.com/me") - ).toBe("http://other.com/me"); - }); - - it("Keep URL with absolute path", function () { - expect(utils.rebaseURL("http://example.com/foo/", "/me")).toBe("/me"); - }); - - it("Rebase to base with filename", function () { - expect( - utils.rebaseURL("http://example.com/foo/index.html", "me/page.html") - ).toBe("http://example.com/foo/me/page.html"); - }); - - it("Rebase to base with directory path", function () { - expect(utils.rebaseURL("http://example.com/foo/", "me/page.html")).toBe( - "http://example.com/foo/me/page.html" - ); - }); - - it("Rebase with absolute base url", function () { - expect( - utils.rebaseURL("/foo/", "me/page.html").indexOf("/foo/me/page.html") > 0 - ).toBe(true); - }); - - it("Rebase with relative base url", function () { - expect( - utils - .rebaseURL("example.com/foo/", "me/page.html") - .indexOf("example.com/foo/me/page.html") > 0 - ).toBe(true); - }); - - it("Doesn't rebase data: urls", function () { - expect( - utils.rebaseURL("http://example.com/foo/", "data:image-base64gibberish") - ).toBe("data:image-base64gibberish"); - }); - }); - describe("removeDuplicateObjects", function () { it("removes removes duplicates inside an array of objects", function () { var objs = []; diff --git a/src/pat/auto-scale/index.html b/src/pat/auto-scale/index.html index 19abaa51d..4d5b172cc 100644 --- a/src/pat/auto-scale/index.html +++ b/src/pat/auto-scale/index.html @@ -1,14 +1,10 @@ - Auto scale - - + + + @@ -82,8 +78,7 @@ > open in fullscreen - -