diff --git a/components/MDNBadge.jsx b/components/MDNBadge.jsx index df61ed7..71ad64b 100644 --- a/components/MDNBadge.jsx +++ b/components/MDNBadge.jsx @@ -3,8 +3,8 @@ import styles from "./MDNBadge.module.css"; export default function MDNBadge({ title, url, i }) { // i stands for "is inline?" - default false - const wrapperClass = i ? wrapperInline : styles.wrapperBlock; - const imgClass = i ? imgInline : styles.imgBlock; + const wrapperClass = i ? styles.wrapperInline : styles.wrapperBlock; + const imgClass = i ? styles.imgInline : styles.imgBlock; return ( ` element is `"DIV"`. + +```js + + +someImage.tagName // "IMG" +``` + +:::note Text nodes don't have `tagName` + +Text nodes are not elements, so they don't have any tagName. To identify the type of node, use `.nodeType` property. For text nodes, `nodeType` is `3` - same as the constant `Node.TEXT_NODE`. + +::: + + +   + +   + + +### 2. parentNode + +`Node.parentNode: Element | Document | DocumentFragment | null` + +This property returns **the parent node** of the current node. If there is no parent, it returns null. In case of Document and DocumentFragment, `.parentNode` is always null. + +The topmost parentNode in DOM is `document`. This can be used to check if an element is detached from the DOM. + +```js +
+
+
+ +child.parentNode //
+ + + This property returns ** the parent element ** of the current node. If there is no parent, it returns null. + + The topmost parentElement in DOM is the `` element, which is also available as `document.documentElement`. + + ```js +let newEle = document.createElement("div"); +newEle.parentNode // null +newEle.parentElement // null + +// In case of appending to an element +document.body.append(newEle) +newEle.parentNode // ... +newEle.parentElement // ... + +//In case of appending to a document fragment, say, df +df.append(newEle) +newEle.parentNode // document-fragment +newEle.parentElement // null + +``` + + + + + + + + +## Children + +:::note Types of Children + +All elements will *generally* have 2 types of children - an element or a text node. + +You can think of elements as other tags and text node as the text within it. + +```jsx +
+ This is // <- 1. text node + // <- 2. element + some text // 2.1. text node + +
+``` + +If you recall, *Element* extends from *Node* - so element and text node are both actually Node. +This is important because some properties return **only child elements**, whereas some return **all child nodes** (including text nodes). +For ex, `ele.childNodes` returns all child nodes, but `ele.children` returns only child elements. + +**Always use the one which is more suitable for your case**. Remember, even if you haven't added any "text" between a tag, it can still have **invisible text nodes** due to spaces and newline characters. + +```jsx +
+
+
+ +container.childNodes // [text, div, text] +// extra text nodes contain newline and space +``` + +Read more about [other types of nodes](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType) and how [whitespace works in html](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace). +::: + +### 3. children + +`Element.children: HTMLCollection` + +This property returns a live `HTMLCollection` containing all the **child elements** of the node. If there are no child elements, it returns empty HTMLCollection. + +`HTMLCollection` can be converted to an array using `Array.from()` or `[...ele.children]`. HTMLCollection also has a `.length` property. +Here, the HTMLCollection is **live** - meaning if new child elements are added, they will automatically appear in this collection. + +```jsx +
+ Some text + some element +
+ +const children = parent.children; +children // HTMLCollection [span] + +// 1. For-loop using .length +for (let i = 0; i < children.length; i++) { + console.log(children[i].tagName); +} + +// 2. Convert to array +[...children].forEach(ele => { + // do something +}) + +``` + +This property is also available on `Document` and `DocumentFragment`. + +:::note Counting number of child elements + +`Element.childElementCount: number` + +It returns the **number of child elements** of the given element. This is equivalent to `ele.children.length` value. + +::: + + + + +### 4. childNodes + +`Node.childNodes: NodeList` + +This property returns a live `NodeList` containing all the **child nodes** of the current element. If there are no child nodes, it returns a empty NodeList. + +`NodeList` can be converted to a array using `Array.from()` or `[...node.childNodes]`. NodeList also has a `.length` property. +Here, the NodeList is **live** - so the content of NodeList will auto-update. + +```jsx +
+ Some text + some element + and more text +
+ +const {childNodes} = parent; +childNodes // NodeList [text, span, text] + +[...childNodes].forEach(node => { + // do something +}) +``` + +This property is available on all types of `Node` - like Element, text node, etc. + +:::note Check if there is any child node + +`Node.hasChildNodes() : boolean` + +This method checks whether the given node **has child nodes or not** and returns a boolean value. This is equivalent to checking `node.childNodes.length > 0`. + +::: + + + +### 5. firstChild + nextSibling + +`Element.firstChild: Node` + +This property returns the element's **first child** node in the tree. If there is no children, it returns `null`. + +`Element.nextSibling: Node` + +This property returns the node immediately **after the current one** in their parent's childNodes. + +```jsx +
+
+
+
+ +let eleA = document.getElementById("A") + +let eleB = eleA.firstChild //
+let eleC = eleB.nextSibling //
+eleC.nextSibling // null +``` + +There is also a similar `previousSibling` property which returns the previous node. Also, there are element-only variants like `firstElementChild`, `nextElementSibling`, etc. + + + +:::note Easier traversal + +This allows accessing the DOM tree in [Left-child right-sibling](https://en.wikipedia.org/wiki/Left-child_right-sibling_binary_tree) (LCRS) form, which is more memory efficient for usual traversal. + +#### How do you implement dom traversal ? + +The typical approach is to use a queue, push all children to the queue, pop them one-by-one and visit them. This requires **extra memory** because of the queue data structure which holds all the *next items to visit*. +But with the LCRS form, you always have access to the next item **without using extra space**. If current element has child, visit `.firstChild`. Then visit next node using `.nextSibling`. + +```js +// 1. Typical approach +let queue = [root] +while (queue.length > 0) { + const item = queue.shift(); + console.log(item); + if (item.hasChildNodes()) { + queue = queue.concat([...item.childNodes]); + } +} + +// 2. LCRS approach +function traverse(item) { + if (item === null) { + return; + } + + console.log(item); + traverse(item.firstChild) + traverse(item.nextSibling) +} +traverse(root.firstChild) +``` +::: + + + + +   + + + + +## Content + +### 6. innerText + +`Element.innerText: string [= value]` + +Returns the **text content** of the element and its descendants **"as rendered"**. + +Can be set, to **replace the element's children** with the given string. It creates a *text node* for every normal text range, but replaces each line break with a `
` element. + + +**Example 1 -** +`.innerText` tries to return a string which represents the actual visible text, not the text literally written in html. Notice how <br/> tags and the css affects the output - +```jsx + +Some text
then a newline
and another. +
+ + +console.log(text.innerText) +// SOME TEXT +// THEN A NEWLINE +// AND ANOTHER. +``` +:::note +On the other hand, `node.textContent` concatenates the actual text nodes used in the html and returns that string. + +```jsx +console.log(text.textContent) +// Some text then a newline and another. +``` +::: + +**Example 2 -** +As setter, it replaces `\n` and `\r\n` in the input string with <br/> tags and wraps the rest in text nodes. + +```jsx + + +text.innerText = "new text \n and a newline" + +text.childNodes +// NodeList [ +// text "new text ", br, text " and a newline." +// ] + +// result html - +// new text
and a newline
+``` + + +   + +   + + +### 7. innerHTML + +`Element.innerHTML: string [= value]` + +Returns the **html markup contained within the element** as a string. + +Can be set, to replace the **contents of the element with nodes parsed** from the given string. The existing content will be removed. + +**Example 1-** +```jsx +
+
text1
+
text2
+
+ +console.log(parent.innerHTML) +//
text1
+//
text2
+``` + +**Example 2-** +```jsx +
+ +parent.innerHTML = ` +
text1
+
text2
+` + +// result html- +
+
text1
+
text2
+
+``` + +:::note To remove all children + +To clear the content of any element, you can use `ele.innerHTML = ""`. + +::: + + + +### 8. outerHTML + +`Element.outerHTML: string [= value]` + +Returns the html markup of the **element and its contents** as a string. + +Can be set, to **replace the element** itself with nodes parsed from the given string. + +**Example 1-** +```jsx +
+
text1
+
+ +console.log(parent.outerHTML) +//
+//
text1
+//
+``` + +**Example 2-** + +Replacing `parent2` with 2 new nodes - + +```jsx +
+
parent 2
+
parent 3
+
+ +parent2.outerHTML = ` +
child 1
+
child 2
+` + +// result html- +
+
child 1
+
child 2
+
parent 3
+
+``` + + + diff --git a/docs/element-properties.mdx b/docs/element-properties.mdx deleted file mode 100644 index cbe470a..0000000 --- a/docs/element-properties.mdx +++ /dev/null @@ -1,12 +0,0 @@ ---- -id: element-properties -title: Properties of DOM nodes ---- - -## Traversal (and ientification) - -## Attribute, class, id, data - -## Scroll - -## Content - html, text \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 14c8d25..9b32aa7 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -1,6 +1,6 @@ module.exports = { title: 'UI Questions', - tagline: 'Review all frontend topics before a interview', + tagline: 'Review all frontend topics before an interview', url: 'https://UiQuestions.com', baseUrl: '/', onBrokenLinks: 'throw', diff --git a/sidebars.js b/sidebars.js index 645dbcc..8a84af2 100644 --- a/sidebars.js +++ b/sidebars.js @@ -1,8 +1,8 @@ module.exports = { "Quick Guide": { - "DOM and Events": [ + "DOM Manipulation": [ "create-modify-element", - 'element-properties', + 'element-child-content', 'element-position-scroll', ], diff --git a/src/css/custom.css b/src/css/custom.css index 86277d8..a5d92cd 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -23,6 +23,10 @@ } } +.alert--secondary { + --ifm-alert-background-color: var(--ifm-color-secondary-lightest); +} + .docusaurus-highlight-code-line { background-color: rgb(72, 77, 91); display: block; @@ -34,14 +38,17 @@ text-transform: unset; } -.navlink{ +.navlink { cursor: pointer; } -.navlink:hover{ -text-decoration: underline; +.navlink:hover { + text-decoration: underline; } +details { + margin-bottom: var(--ifm-leading); +} summary { cursor: pointer; -} \ No newline at end of file +}