# Node+ext

[🔰 JS](../../../../js) ⟩ [browser](../../..) ⟩ [DOM](../..) ⟩ [type](..) ⟩ [Node]() ⟩ +ext&#x20;

{% hint style="success" %}
extend [Node]() with custom methods.

:point\_right: [custom](../../../../appendix/custom "mention")
{% endhint %}

{% tabs %}
{% tab title="💾 程式" %}
* replit ⟩ [Node extension](https://replit.com/@pegasusroe/Node-extension#ext/Node_ext.js)

```javascript
// 2023.01.12 - 21:46 - add `elem()`
// 2023.01.12 - 08:35 - first version
// ---------------------------------------------------------

// export
export { $, $all, elem };

// ⭐️ $(): select first element
function $(selector, parent = document){
  return parent.querySelector(selector);
}

// ⭐️ $all(): select all element
function $all(selector, parent = document){
  return parent.querySelectorAll(selector);
}

// ⭐ elem(): create & config element
function elem(tagName, config) {
    const elem = document.createElement(tagName);
    if (config) config(elem);
    return elem;
}

// --------------------------
// ⭐️ Node extension
// --------------------------
// 🔸 node.isTextNode
// 🔸 node.isElementNode
// 🔹 node.$()
// 🔹 node.$all()

Object.defineProperties(Node.prototype, {

    // 🔸 node.isTextNode
    isTextNode: {
        get() {
            return this.nodeType === Node.TEXT_NODE;
        },
    },

    // 🔸 node.isElementNode
    isElementNode: {
        get() {
            return this.nodeType === Node.ELEMENT_NODE;
        },
    },

    // 🔹 node.$()
    $: {
        value: function(selector){
            return $(selector, this);
        }
    },

    // 🔹 node.$all()
    $all: {
        value: function(selector){
            return $all(selector, this);
        }
    },
});
```
{% endtab %}

{% tab title="💈範例" %}
* [draw-dots](../../../event/type/mouse/click/draw-dots "mention")
* replit ⟩ [Node extension](https://replit.com/@pegasusroe/Node-extension#script.js)

```javascript
// import
import { $, $all } from './ext/Node_ext.js'; // Node extension
import { } from './ext/Iterable.js';         // Iterable extension
import { } from './js/Node_methods.js';      // Node custom methods

// -----------------
// 1. insert before
// -----------------

// all paragraphs
let p = document.body.$all("p");

// ⭐️ insert p[2] before p[0]
document.body.insertBefore(p[2], p[0]);
// Three
// One
// Two

// -----------------
// 2. replace child
// -----------------

// event handler
$('button').onclick = function replaceImages() {

    // get all image nodes
    // node list returned from `querySelectorAll` is NOT live.
    let images = $all("img");

    // ☢️ Alert❗
    // The loop starts at the end of the list. This is necessary if 
    // the `images` node list is "live".
    for (let i = images.length - 1; i >= 0; i--) {
        let image = images[i];
        if (image.alt) {
            let text = document.createTextNode(image.alt);
            // ⭐️ replace (image) child with text node.
            image.parentNode.replaceChild(text, image);
        }
    }
};

// -------------------
// 3. create element
// -------------------

// creates an element node and treats the rest of its arguments 
// as children to that node.
function elem(type, ...children) {
    
    // ⭐️ create element
    let node = document.createElement(type);
    
    // ⭐️ append children
    for (let child of children) {
        if (typeof child === "string") child = document.createTextNode(child);
        node.appendChild(child);
    }
    
    // return element
    return node;
}

// add <footer> into <blockquote>
$("#quote").appendChild(
    elem("footer", 
        "— ",
        elem("strong", "Karl Popper"),
        ", preface to the second edition of ",
        elem("em", "The Open Society and Its Enemies"),
        ", 1950"
    )
);

// -------------------
// 4. attributes
// -------------------

$all('p')
    .filter(p => p.getAttribute('data-classified') === 'secret')
    .forEach(p => p.remove());          // ⭐️ remove node
```

{% embed url="https://replit.com/@pegasusroe/Node-extension#script.js" %}
{% endtab %}

{% tab title="👥 相關" %}
* [+ext](../element/+ext "mention")
{% endtab %}

{% tab title="⬇️ 應用" %}
* [objects-to-html-table](../../../../js/val/builtin/arr/ex/objects-to-html-table "mention")
{% endtab %}

{% tab title="🔸 屬性" %}
* [node.isinpage](+ext/node.isinpage "mention")
{% endtab %}

{% tab title="📘 手冊" %}
* MDN ⟩ [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) ⟩ [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)&#x20;
{% endtab %}
{% endtabs %}
