diff --git a/src/actions/element.js b/src/actions/element.js new file mode 100644 index 0000000..f3ef419 --- /dev/null +++ b/src/actions/element.js @@ -0,0 +1,55 @@ +import ActionBase from "./base"; +import debounce from "./../helpers/debounce"; + +class Element extends ActionBase { + add() { + const target = this.targets[0]; + if (!target) return; + + const sourceSelector = this.currentElement.dataset.addSource; + if (!sourceSelector) return; + + const source = document.querySelector(sourceSelector); + if (!source) return; + + const clonedElement = this.#cloneSource(source); + const position = this.currentElement.dataset.addAt || "beforeend"; + + target.insertAdjacentElement(position, clonedElement); + } + + remove() { + const delay = this.currentElement.dataset.delay; + + const removeElements = () => { + this.targets.forEach((target) => target.remove()); + }; + + if (delay) { + debounce(removeElements, parseInt(delay)); + } else { + removeElements(); + } + } + + // private + + #cloneSource(source) { + return source.tagName === "TEMPLATE" + ? source.content.cloneNode(true).firstElementChild + : source.cloneNode(true); + } +} + +export const action = + (method) => + (element, options = {}) => { + const instance = new Element(element, options); + + return instance[method](); + }; + +export default { + add: action("add"), + remove: action("remove") +}; diff --git a/src/actions/index.js b/src/actions/index.js index 68587ce..42ebc06 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -4,6 +4,7 @@ import clipboardActions from "./clipboard"; import confirmActions from "./confirm"; import dataAttributeActions from "./data_attribute"; import dialogActions from "./dialog"; +import elementActions from "./element"; import formActions from "./form"; import intersectionActions from "./intersection"; import reloadActions from "./reload"; @@ -17,6 +18,7 @@ export const actions = { confirm: confirmActions, dataAttribute: dataAttributeActions, dialog: dialogActions, + element: elementActions, form: formActions, intersection: intersectionActions, reload: reloadActions, diff --git a/test/element.html b/test/element.html new file mode 100644 index 0000000..63876f7 --- /dev/null +++ b/test/element.html @@ -0,0 +1,206 @@ + + + + Attractive.js - Element Tests + + + + +

Element

+

← Back to test index

+ +
+

Remove element (self)

+ + +
+ +
+

Remove element with target

+ + + +

+ This element will be removed when the button is clicked. +

+
+ +
+

Remove element with delay

+ + + +

+ This element will be removed 2 seconds after clicking the button. +

+
+ +
+

Remove multiple elements

+ + + +
+
+ Card 1 +
+
+ Card 2 +
+
+ Card 3 +
+
+
+ +
+

Add element - beforeend (default)

+ + + + + + +
+ +
+

Add element - afterbegin

+ + + + + + +
+ +
+

Add element - beforebegin

+ + + +
+ Target Element - New cards appear before this +
+ + +
+ +
+

Add element - afterend

+ + + +
+ Target Element - New cards appear after this +
+ + +
+ +
+

Add from regular element (not template)

+ + + +
+ Source Element - This gets cloned +
+ +
+

Clones appear here:

+
+
+ + diff --git a/test/index.html b/test/index.html index 8b14a6a..b1551ef 100644 --- a/test/index.html +++ b/test/index.html @@ -14,6 +14,7 @@

Attractive.js test suite

  • Confirm
  • Data Attribute
  • Dialog
  • +
  • Element
  • Form
  • Intersection
  • Reload