From 58db7ea41651979044bd84d60f24681c8e9904f7 Mon Sep 17 00:00:00 2001 From: Lakshya Thakur Date: Tue, 20 Oct 2020 01:13:44 +0530 Subject: [PATCH 01/20] Added brief on DOM interfaces + func signatures + fixed MDN links --- docs/create-modify-element.mdx | 48 +++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index 9b6aafa..3902e07 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -9,6 +9,12 @@ import Admonition from "../components/Admonition" import Accordion from "../components/Accordion" import MDN from "../components/MDNBadge" +:::note DOM interfaces +Every kind of **DOM** node is represented by an interface based on **Node** interface. +**Element, Document and DocumentFragment** interfaces inherit from Node. +More about DOM interfaces [here](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) +::: + ## Finding elements ### 1. querySelector() @@ -36,7 +42,7 @@ document.querySelector(".not-found"); // null - + ### 2. querySelectorAll() @@ -60,17 +66,19 @@ for (let p of paras) { } ``` - + ## Create / insert element ### 3. createElement() -It creates a new HTML element, taking the tag name (`"div"`) as argument. +`document.createElement(tagName) : Element` + +This method creates a new HTML element, taking the specified HTML tag name as argument. ```js document.createElement("div") -// creates
+// creates a
element ``` @@ -94,7 +102,7 @@ document.createElement("div") `Element.setAttribute(name, value)` -It sets a attribute on the current element. +This method sets an attribute on the current element. `name` - name of the attribute to add. Ex- "type". `value` - value of the attribute. Ex- "text". @@ -110,9 +118,9 @@ ele.setAttribute("type", "text") ### 5. appendChild() -`Element.appendChild(newElement)` +`Node.appendChild(newNode)` -It inserts a new element as the last child of the parent element. +This method inserts a new node as the last child of the parent node. ```js let eleDiv = document.createElement("div") @@ -150,11 +158,11 @@ eleDiv.appendChild(eleH1) ### 6. removeChild() -`Element.removeChild(childElement)` +`Node.removeChild(childNode)` -This method tries to remove a child element from the parent and returns the removed node. +This method tries to remove a child node from the parent and returns the removed node. -If the element to be removed is not a child of the parent element, it throws a `NotFoundError` DOMException. +If the node to be removed is not a child of the parent node, it throws a `NotFoundError` DOMException. ```js //
@@ -168,13 +176,13 @@ parentEle.removeChild(childEle) ### 7. insertBefore() -`Element.insertBefore(newEle, refEle)` +`Node.insertBefore(newEle, refEle)` -This method inserts a new child element before another child within a parent. +This method inserts a new child node before another node within a parent. `newEle` - The node to be inserted. -`refEle` - The reference element before which newEle should be inserted. If refEle is `null`, then newEle is added as the last child. +`refEle` - The reference node before which newEle should be inserted. If refEle is `null`, then newEle is added as the last child. ```js //
    @@ -204,19 +212,15 @@ parent.insertBefore(newEle, ref.nextSibling) ### 8. Document Fragment +`document.createDocumentFragment() : DocumentFragment` + +This method is used to create a new empty document fragment. + DocumentFragment can be considered to be a off-screen lightweight `document` object. It is generally used for batching multiple operations - by doing them in the fragment over time and then rendering the whole content to the visible DOM in one shot . Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). -**Methods** - - -`document.createDocumentFragment()` - creates a new empty fragment. - -`.appendChild()` / `.insertBefore()` - can be used to move the whole content of the fragment to the actual DOM. - -**Example** - - ```js let fragment = document.createDocumentFragment() @@ -229,6 +233,8 @@ outerEle.appendChild(fragment) // This will remove all content from fragment and // insert them within outerEle. +// .appendChild()/.insertBefore() - can be used to move the whole content of the fragment to the actual DOM. + ``` From 3188ef8a5be6271dbebae59dca61b8d75cb6b951 Mon Sep 17 00:00:00 2001 From: Lakshya Thakur Date: Fri, 23 Oct 2020 15:40:01 +0530 Subject: [PATCH 02/20] Make changes as per code feedback --- docs/create-modify-element.mdx | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index 3902e07..ed6b5cf 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -11,8 +11,7 @@ import MDN from "../components/MDNBadge" :::note DOM interfaces Every kind of **DOM** node is represented by an interface based on **Node** interface. -**Element, Document and DocumentFragment** interfaces inherit from Node. -More about DOM interfaces [here](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) +**Element, Document and DocumentFragment** interfaces inherit from Node. More about DOM interfaces [here](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) ::: ## Finding elements @@ -31,13 +30,13 @@ document.querySelector(".not-found"); // null - This method is also available on all DOM nodes. If you want to look within a specific element, just use `ele.querySelector()` on the parent element. + Besides Document, this method is also available on Element and DocumentFragment.
    + If you want to look within a specific element, just use ele.querySelector() on the parent element.
    + If you want to look within a specific fragment, just use df.querySelector() on the parent fragment. ```js - // Example - .outer > .inner - outerEle.addEventListener((ev) => { - let innerEle = ev.target.querySelector(".inner"); - }); + // Example - outer is a parent element/fragment. + let innerEle = outer.querySelector(".inner"); ```
    @@ -66,6 +65,19 @@ for (let p of paras) { } ``` + + + Besides Document, this method is also available on Element and DocumentFragment.
    + If you want to look for list of elements within specific element, just use ele.querySelectorAll() on the parent element.
    + If you want to look for list of elements within specific fragment, just use df.querySelectorAll() on the parent fragment. + + ```js + // Example - outer is a parent element/fragment. + let innerEles = outer.querySelectorAll(".inner"); + ``` +
    +
    + ## Create / insert element @@ -132,13 +144,13 @@ eleDiv.appendChild(eleH1) - If newElement is already a child of another element, + If newNode is already a child of another node, then it is removed from its existing parent and then added to the new parent. - If newElement is a DocumentFragment, then - instead of adding the fragment itself as a child, - the entire content of the fragment is added as children of the parent element. + If newNode is a DocumentFragment, then - instead of adding the fragment itself as a child, + the entire content of the fragment is added as children of the parent node. From 36969c140f92de55f1ad36a03f869218e246f8a9 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 16:58:42 +0530 Subject: [PATCH 03/20] Admonition.jsx - Allow custom id to link to a note --- components/Admonition.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Admonition.jsx b/components/Admonition.jsx index 83bf86d..7182b8b 100644 --- a/components/Admonition.jsx +++ b/components/Admonition.jsx @@ -2,7 +2,7 @@ import React, { Component } from "react"; export default class Admonition extends Component { render() { - const { type, iconType, title, children, addIfmClass } = this.props; + const { type, iconType, title, id, children, addIfmClass } = this.props; let wrapperClasses = ["admonition", `admonition-${type}`]; if (addIfmClass) { @@ -11,7 +11,7 @@ export default class Admonition extends Component { } return ( -
    +
    {returnIcon(type, iconType)}
    From 07de9b138cd9ca93148d690a921ec7996ef549dd Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 18:45:51 +0530 Subject: [PATCH 04/20] Accordion - Handle auto-open if inner element is linked to --- components/Accordion.jsx | 61 +++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/components/Accordion.jsx b/components/Accordion.jsx index b8a8916..860c449 100644 --- a/components/Accordion.jsx +++ b/components/Accordion.jsx @@ -1,10 +1,57 @@ -import React from "react"; +import React, { useRef, useEffect } from "react"; -const Accordion = ({ children, title = "More" }) => ( -
    - {title} - {children} -
    -); +const Accordion = ({ children, title = "More" }) => { + const detailsRef = useRef(null); + const summaryRef = useRef(null); + + function openAccordionOnHash() { + const hash = location.hash.substring(1); + if (hash.length === 0) { + return; + } + let targetElement; + targetElement = document.getElementById(hash); + if (targetElement === null) { + return; + } + + // 1. If target is within current details element + const detailsElement = detailsRef.current; + const summaryElement = summaryRef.current; + if ( + detailsElement !== null && + summaryElement.current !== null && + detailsElement.contains(targetElement) + ) { + // 2. and it is not open, + if (!detailsElement.open) { + // 3. Then open it + detailsElement.open = true; + // 4. and scroll into view, focus on summary + summaryElement.focus(); + targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); + } + } + } + + useEffect(() => { + // 1. Add event listener for future hash changes + window.addEventListener("hashchange", openAccordionOnHash); + // 2. Do it anyway now if initial url has hash + openAccordionOnHash() + + // Cleanup - remove listener + return () => { + window.removeEventListener("hashchange", openAccordionOnHash); + }; + }, []); + + return ( +
    + {title} + {children} +
    + ); +}; export default Accordion; From 43995cccf970bcb3ce6e53d34323523318a012c2 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 18:47:51 +0530 Subject: [PATCH 05/20] create-modify-element - qsAll point back to other interfaces note in qs --- docs/create-modify-element.mdx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index ed6b5cf..19e973c 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -29,7 +29,7 @@ document.querySelector(".not-found"); // null ``` - + Besides Document, this method is also available on Element and DocumentFragment.
    If you want to look within a specific element, just use ele.querySelector() on the parent element.
    If you want to look within a specific fragment, just use df.querySelector() on the parent fragment. @@ -65,18 +65,7 @@ for (let p of paras) { } ``` - - - Besides Document, this method is also available on Element and DocumentFragment.
    - If you want to look for list of elements within specific element, just use ele.querySelectorAll() on the parent element.
    - If you want to look for list of elements within specific fragment, just use df.querySelectorAll() on the parent fragment. - - ```js - // Example - outer is a parent element/fragment. - let innerEles = outer.querySelectorAll(".inner"); - ``` -
    -
    +`querySelectorAll` is also available on Element and DocumentFragment, in the [same way as querySelector](#element-has-qs). From 8217dc3f042f3c7c6b3f11e0c8e5d1f4b71ea462 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 19:06:18 +0530 Subject: [PATCH 06/20] create-modify-element - From fragment, link back to appendChild note To describe how it can be actually rendered to DOM --- docs/create-modify-element.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index 19e973c..6e29b3b 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -137,7 +137,7 @@ eleDiv.appendChild(eleH1) then it is removed from its existing parent and then added to the new parent.
    - + If newNode is a DocumentFragment, then - instead of adding the fragment itself as a child, the entire content of the fragment is added as children of the parent node. @@ -179,7 +179,9 @@ parentEle.removeChild(childEle) `Node.insertBefore(newEle, refEle)` -This method inserts a new child node before another node within a parent. +This method inserts a new child node before another node within a parent. + +It also works with **DocumentFragment**, by inserting all of its content in that position. `newEle` - The node to be inserted. @@ -220,7 +222,7 @@ This method is used to create a new empty document fragment. DocumentFragment can be considered to be a off-screen lightweight `document` object. It is generally used for batching multiple operations - by doing them in the fragment over time and then rendering the whole content to the visible DOM in one shot . -Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). +Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, [use appendChild](#appendChild-documentFragment) or `insertBefore`. ```js let fragment = document.createDocumentFragment() @@ -234,8 +236,6 @@ outerEle.appendChild(fragment) // This will remove all content from fragment and // insert them within outerEle. -// .appendChild()/.insertBefore() - can be used to move the whole content of the fragment to the actual DOM. - ``` From 6d0e14ec46481526cf5664355da541886d51836d Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 19:14:07 +0530 Subject: [PATCH 07/20] custom.css - In accordion header, make cursor pointer As part of general improvements to Accordion we are adding here --- src/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/css/custom.css b/src/css/custom.css index 5ed4a52..d95ceeb 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -32,4 +32,8 @@ .admonition h5 { text-transform: unset; +} + +summary { + cursor: pointer; } \ No newline at end of file From fcfe3c70b903a52db60634998d7a8e71f2a7f324 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 19:38:30 +0530 Subject: [PATCH 08/20] Admonition - Make container focusable --- components/Admonition.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Admonition.jsx b/components/Admonition.jsx index 7182b8b..53aa382 100644 --- a/components/Admonition.jsx +++ b/components/Admonition.jsx @@ -11,7 +11,7 @@ export default class Admonition extends Component { } return ( -
    +
    {returnIcon(type, iconType)}
    From ebb35a08333865800e8033ce7701b955e0b21dd4 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Fri, 23 Oct 2020 19:40:07 +0530 Subject: [PATCH 09/20] Accordion - focus on note container instead instead of summary tag --- components/Accordion.jsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/components/Accordion.jsx b/components/Accordion.jsx index 860c449..493818f 100644 --- a/components/Accordion.jsx +++ b/components/Accordion.jsx @@ -2,7 +2,6 @@ import React, { useRef, useEffect } from "react"; const Accordion = ({ children, title = "More" }) => { const detailsRef = useRef(null); - const summaryRef = useRef(null); function openAccordionOnHash() { const hash = location.hash.substring(1); @@ -17,18 +16,16 @@ const Accordion = ({ children, title = "More" }) => { // 1. If target is within current details element const detailsElement = detailsRef.current; - const summaryElement = summaryRef.current; if ( detailsElement !== null && - summaryElement.current !== null && detailsElement.contains(targetElement) ) { // 2. and it is not open, if (!detailsElement.open) { // 3. Then open it detailsElement.open = true; - // 4. and scroll into view, focus on summary - summaryElement.focus(); + // 4. and scroll into view and focus + targetElement.focus(); targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); } } @@ -48,7 +45,7 @@ const Accordion = ({ children, title = "More" }) => { return (
    - {title} + {title} {children}
    ); From 829875537314e4bcab2b651887dacc74afaed017 Mon Sep 17 00:00:00 2001 From: Lakshya Thakur Date: Sat, 24 Oct 2020 18:32:45 +0530 Subject: [PATCH 10/20] Added DocWrapper and Link component to address link issues --- components/Accordion.jsx | 6 +++--- components/DocWrapper.jsx | 24 ++++++++++++++++++++++++ components/Link.jsx | 14 ++++++++++++++ docs/create-modify-element.mdx | 16 +++++++++++----- src/css/custom.css | 8 ++++++++ 5 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 components/DocWrapper.jsx create mode 100644 components/Link.jsx diff --git a/components/Accordion.jsx b/components/Accordion.jsx index 493818f..441381e 100644 --- a/components/Accordion.jsx +++ b/components/Accordion.jsx @@ -24,10 +24,10 @@ const Accordion = ({ children, title = "More" }) => { if (!detailsElement.open) { // 3. Then open it detailsElement.open = true; - // 4. and scroll into view and focus - targetElement.focus(); - targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); } + // 4. and scroll into view and focus + targetElement.focus(); + targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); } } diff --git a/components/DocWrapper.jsx b/components/DocWrapper.jsx new file mode 100644 index 0000000..129e5c7 --- /dev/null +++ b/components/DocWrapper.jsx @@ -0,0 +1,24 @@ +import React from "react" +import { useEffect } from "react" + +const DocWrapper = ({children})=>{ + + useEffect(()=>{ + let hash = location.hash.substring(1); + // Remove scroll restoration when there is a hash of length > 0. + if (hash.length!==0 && "scrollRestoration" in history) { + history.scrollRestoration = "manual" + } + // Check if the hash type is a Docusauraus link or a reference link within document. + let isDocusaurusLink = (hash.substring(0,4) !== "link") + let targetElement; + targetElement = document.getElementById(hash) + if(!targetElement)return + if(isDocusaurusLink) + targetElement.scrollIntoView(true) + },[]) + + return <>{children} +} + +export default DocWrapper \ No newline at end of file diff --git a/components/Link.jsx b/components/Link.jsx new file mode 100644 index 0000000..a1bd13d --- /dev/null +++ b/components/Link.jsx @@ -0,0 +1,14 @@ +import React from "react" + +const Link = ({hash,title}) =>{ + + const handleLink=(event)=>{ + //manually change hash to trigger hashChange event. + window.location.hash = "#"; + window.location.hash = hash; + } + + return {title} +} + +export default Link \ No newline at end of file diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index 6e29b3b..7d6485a 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -7,7 +7,11 @@ slug: / import Admonition from "../components/Admonition" import Accordion from "../components/Accordion" +import Link from "../components/Link" import MDN from "../components/MDNBadge" +import DocWrapper from "../components/DocWrapper" + + :::note DOM interfaces Every kind of **DOM** node is represented by an interface based on **Node** interface. @@ -29,7 +33,7 @@ document.querySelector(".not-found"); // null ``` - + Besides Document, this method is also available on Element and DocumentFragment.
    If you want to look within a specific element, just use ele.querySelector() on the parent element.
    If you want to look within a specific fragment, just use df.querySelector() on the parent fragment. @@ -65,7 +69,7 @@ for (let p of paras) { } ``` -`querySelectorAll` is also available on Element and DocumentFragment, in the [same way as querySelector](#element-has-qs). +`querySelectorAll` is also available on Element and DocumentFragment, in the . @@ -137,7 +141,7 @@ eleDiv.appendChild(eleH1) then it is removed from its existing parent and then added to the new parent.
    - + If newNode is a DocumentFragment, then - instead of adding the fragment itself as a child, the entire content of the fragment is added as children of the parent node. @@ -222,7 +226,7 @@ This method is used to create a new empty document fragment. DocumentFragment can be considered to be a off-screen lightweight `document` object. It is generally used for batching multiple operations - by doing them in the fragment over time and then rendering the whole content to the visible DOM in one shot . -Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, [use appendChild](#appendChild-documentFragment) or `insertBefore`. +Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, or `insertBefore`. ```js let fragment = document.createDocumentFragment() @@ -243,4 +247,6 @@ outerEle.appendChild(fragment) -------- -In the next section, we'll see how to read information from a DOM element. \ No newline at end of file +In the next section, we'll see how to read information from a DOM element. + +
    \ No newline at end of file diff --git a/src/css/custom.css b/src/css/custom.css index d95ceeb..86277d8 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -34,6 +34,14 @@ text-transform: unset; } +.navlink{ + cursor: pointer; +} + +.navlink:hover{ +text-decoration: underline; +} + summary { cursor: pointer; } \ No newline at end of file From 79569dac8cffb63d9ac80b1de9840778cacdbf03 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Sun, 25 Oct 2020 18:08:05 +0530 Subject: [PATCH 11/20] Remove DocWrapper usage --- components/DocWrapper.jsx | 24 ------------------------ components/Link.jsx | 1 + docs/create-modify-element.mdx | 5 ----- 3 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 components/DocWrapper.jsx diff --git a/components/DocWrapper.jsx b/components/DocWrapper.jsx deleted file mode 100644 index 129e5c7..0000000 --- a/components/DocWrapper.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react" -import { useEffect } from "react" - -const DocWrapper = ({children})=>{ - - useEffect(()=>{ - let hash = location.hash.substring(1); - // Remove scroll restoration when there is a hash of length > 0. - if (hash.length!==0 && "scrollRestoration" in history) { - history.scrollRestoration = "manual" - } - // Check if the hash type is a Docusauraus link or a reference link within document. - let isDocusaurusLink = (hash.substring(0,4) !== "link") - let targetElement; - targetElement = document.getElementById(hash) - if(!targetElement)return - if(isDocusaurusLink) - targetElement.scrollIntoView(true) - },[]) - - return <>{children} -} - -export default DocWrapper \ No newline at end of file diff --git a/components/Link.jsx b/components/Link.jsx index a1bd13d..94c357f 100644 --- a/components/Link.jsx +++ b/components/Link.jsx @@ -8,6 +8,7 @@ const Link = ({hash,title}) =>{ window.location.hash = hash; } + return {title} } diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index 7d6485a..d530195 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -9,9 +9,6 @@ import Admonition from "../components/Admonition" import Accordion from "../components/Accordion" import Link from "../components/Link" import MDN from "../components/MDNBadge" -import DocWrapper from "../components/DocWrapper" - - :::note DOM interfaces Every kind of **DOM** node is represented by an interface based on **Node** interface. @@ -248,5 +245,3 @@ outerEle.appendChild(fragment) -------- In the next section, we'll see how to read information from a DOM element. - - \ No newline at end of file From 686a3e49e4f7a946b65684b6e62582146de875e8 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 12:11:14 +0530 Subject: [PATCH 12/20] Accordion - restore scrollRestoration to "auto" after scroll --- components/Accordion.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/Accordion.jsx b/components/Accordion.jsx index 441381e..2a78543 100644 --- a/components/Accordion.jsx +++ b/components/Accordion.jsx @@ -28,6 +28,9 @@ const Accordion = ({ children, title = "More" }) => { // 4. and scroll into view and focus targetElement.focus(); targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); + if ("scrollRestoration" in history) { + history.scrollRestoration = "auto"; + } } } From 4cf46e250e0e9e0b84f0fcb3ba69addb054c43aa Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 12:12:05 +0530 Subject: [PATCH 13/20] handleScrollRestoration - Add script to head This will set history.scrollRestoration to "manual" on page start, if hash starts with "link-" --- docusaurus.config.js | 6 ++++++ static/scripts/handleScrollRestoration.js | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 static/scripts/handleScrollRestoration.js diff --git a/docusaurus.config.js b/docusaurus.config.js index 69faacd..1c9b7a7 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -102,4 +102,10 @@ module.exports = { }, ], ], + scripts: [ + { + src: + '/scripts/handleScrollRestoration.js', + }, + ] }; diff --git a/static/scripts/handleScrollRestoration.js b/static/scripts/handleScrollRestoration.js new file mode 100644 index 0000000..bd93e7c --- /dev/null +++ b/static/scripts/handleScrollRestoration.js @@ -0,0 +1,8 @@ +var hash = window.location.hash; +var hashName = hash.substring(1, hash.length); + +if (hashName.startsWith("link-")) { + if ("scrollRestoration" in history) { + history.scrollRestoration = "manual"; + } +} From 0f24e566bec8f4c5d1e233fe82abebb8e49ed3d4 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 12:37:28 +0530 Subject: [PATCH 14/20] Accordion - Remove smooth scrolling It is distracting and unlike normal anchor scroll --- components/Accordion.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Accordion.jsx b/components/Accordion.jsx index 2a78543..5f187b5 100644 --- a/components/Accordion.jsx +++ b/components/Accordion.jsx @@ -27,7 +27,7 @@ const Accordion = ({ children, title = "More" }) => { } // 4. and scroll into view and focus targetElement.focus(); - targetElement.scrollIntoView({ behavior: "smooth", block: "center" }); + targetElement.scrollIntoView({ block: "center" }); if ("scrollRestoration" in history) { history.scrollRestoration = "auto"; } From 5a8cbef51747781c5ae20a1f1ae2f968187795f1 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 17:14:41 +0530 Subject: [PATCH 15/20] Accordion - Change scrollRestoration delay to 1sec --- components/Accordion.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/Accordion.jsx b/components/Accordion.jsx index 5f187b5..795538e 100644 --- a/components/Accordion.jsx +++ b/components/Accordion.jsx @@ -28,9 +28,13 @@ const Accordion = ({ children, title = "More" }) => { // 4. and scroll into view and focus targetElement.focus(); targetElement.scrollIntoView({ block: "center" }); - if ("scrollRestoration" in history) { - history.scrollRestoration = "auto"; - } + // Increased for mobile browsers + const scrollRestorationDelay = 1000; // 1s + setTimeout(() => { + if ("scrollRestoration" in history) { + history.scrollRestoration = "auto"; + } + }, scrollRestorationDelay); } } From 4117131c12f2b68bbf954a58feb784b067ebc143 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 17:23:40 +0530 Subject: [PATCH 16/20] Link - reformat --- components/Link.jsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/components/Link.jsx b/components/Link.jsx index 94c357f..9b504a2 100644 --- a/components/Link.jsx +++ b/components/Link.jsx @@ -1,15 +1,17 @@ -import React from "react" +import React from "react"; -const Link = ({hash,title}) =>{ +const Link = ({ hash, title }) => { + const handleLink = (event) => { + //manually change hash to trigger hashChange event. + window.location.hash = "#"; + window.location.hash = hash; + }; - const handleLink=(event)=>{ - //manually change hash to trigger hashChange event. - window.location.hash = "#"; - window.location.hash = hash; - } - - - return {title} -} + return ( + + {title} + + ); +}; -export default Link \ No newline at end of file +export default Link; From c6ad5ff8e3bc334da19a25d382e1f12560dcf199 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 17:25:59 +0530 Subject: [PATCH 17/20] Rename Link to InternalLink and change usage --- components/{Link.jsx => InternalLink.jsx} | 4 ++-- docs/create-modify-element.mdx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename components/{Link.jsx => InternalLink.jsx} (79%) diff --git a/components/Link.jsx b/components/InternalLink.jsx similarity index 79% rename from components/Link.jsx rename to components/InternalLink.jsx index 9b504a2..03b9a8c 100644 --- a/components/Link.jsx +++ b/components/InternalLink.jsx @@ -1,6 +1,6 @@ import React from "react"; -const Link = ({ hash, title }) => { +const InternalLink = ({ hash, title }) => { const handleLink = (event) => { //manually change hash to trigger hashChange event. window.location.hash = "#"; @@ -14,4 +14,4 @@ const Link = ({ hash, title }) => { ); }; -export default Link; +export default InternalLink; diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index d530195..ee9b9fd 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -7,7 +7,7 @@ slug: / import Admonition from "../components/Admonition" import Accordion from "../components/Accordion" -import Link from "../components/Link" +import InternalLink from "../components/InternalLink" import MDN from "../components/MDNBadge" :::note DOM interfaces @@ -66,7 +66,7 @@ for (let p of paras) { } ``` -`querySelectorAll` is also available on Element and DocumentFragment, in the . +`querySelectorAll` is also available on Element and DocumentFragment, in the . From f8c9137b0fab092f64823dd8a95c8c15bd841558 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Mon, 26 Oct 2020 17:42:51 +0530 Subject: [PATCH 18/20] InternalLink - check href startsWith + forward props to To make it more accessible and allow customization. --- components/InternalLink.jsx | 25 ++++++++++++++++--------- docs/create-modify-element.mdx | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/components/InternalLink.jsx b/components/InternalLink.jsx index 03b9a8c..43d0a4b 100644 --- a/components/InternalLink.jsx +++ b/components/InternalLink.jsx @@ -1,17 +1,24 @@ import React from "react"; -const InternalLink = ({ hash, title }) => { - const handleLink = (event) => { - //manually change hash to trigger hashChange event. +/* +InternalLink should be only used to link to fragment urls placed within a Accordion, in the same page. +`href` props should only contain a fragment prefixed with "link-" (start with "#link-") +It allows all the same props as tag. +*/ +const InternalLink = ({ href, className = "navlink", ...otherProps }) => { + if (!href.startsWith("#link-")) { + throw new TypeError( + "InternalLink - href must start with #. It should only be used for same-page fragment links." + ); + } + + const handleLink = () => { + // manually change hash to trigger hashChange event. window.location.hash = "#"; - window.location.hash = hash; + window.location.hash = href; }; - return ( - - {title} - - ); + return ; }; export default InternalLink; diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index ee9b9fd..5c28e90 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -66,7 +66,7 @@ for (let p of paras) { } ``` -`querySelectorAll` is also available on Element and DocumentFragment, in the . +`querySelectorAll` is also available on Element and DocumentFragment, in the same way as querySelector. From 2d2af2e6454f4a5cf59cf001fd38a8ed2a7f34dd Mon Sep 17 00:00:00 2001 From: bendtherules Date: Tue, 27 Oct 2020 16:28:36 +0530 Subject: [PATCH 19/20] create-modify-element - Replace another Link usage --- docs/create-modify-element.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index 5c28e90..a715d7c 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -223,7 +223,7 @@ This method is used to create a new empty document fragment. DocumentFragment can be considered to be a off-screen lightweight `document` object. It is generally used for batching multiple operations - by doing them in the fragment over time and then rendering the whole content to the visible DOM in one shot . -Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, or `insertBefore`. +Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, use appendChild or `insertBefore`. ```js let fragment = document.createDocumentFragment() From 1262c17269fc5bc91518b5e268373ac4e91bf983 Mon Sep 17 00:00:00 2001 From: bendtherules Date: Wed, 28 Oct 2020 00:42:35 +0530 Subject: [PATCH 20/20] create-modify-element - Fix InternalLink props usage --- docs/create-modify-element.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/create-modify-element.mdx b/docs/create-modify-element.mdx index a715d7c..a8f5f0b 100644 --- a/docs/create-modify-element.mdx +++ b/docs/create-modify-element.mdx @@ -223,7 +223,7 @@ This method is used to create a new empty document fragment. DocumentFragment can be considered to be a off-screen lightweight `document` object. It is generally used for batching multiple operations - by doing them in the fragment over time and then rendering the whole content to the visible DOM in one shot . -Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, use appendChild or `insertBefore`. +Because fragment is not rendered, making changes to it doesn't cause any performance impact (no reflow). To **actually "render" the fragment** in the visible document, use appendChild or `insertBefore`. ```js let fragment = document.createDocumentFragment()