npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nawawishkid/cloneable

v1.0.5

Published

Make specific HTMLElement cloneable.

Downloads

3

Readme

Cloneable.js

Make specific HTMLElement cloneable via user interface e.g. <button> element, or clone programmatically via JavaScript API.

TODO:

Improvements:

  • [ ] Change option name from maxCloneable to just max
  • ~~[x] Remove button disability mechanism. If one prefers to disable button when number of cloned elements reach its maximum number allowed, use uncloneable event to disable it manually.~~
  • [ ] Try changing from using class to function to decrease bundle size.
  • [ ] Allow user to set default classname of the created elements e.g. .tray, .controllers, .clone-btn, or .remove-btn.

Installation

NPM

npm i @nawawishkid/cloneable

CDN

On npm: https://cdn.jsdelivr.net/npm/@nawawishkid/cloneable@latest/dist/cloneable.min.js
On GitHub: https://cdn.jsdelivr.net/gh/nawawishkid/cloneable.js@latest/dist/cloneable.min.js

NPM Scripts

  • build -- Build (bundle) this library.
  • test -- Run test suite.

Quick start

In your index.html:

<div id="cloneable-container"><p>Clone me!</p></div>

<script src="src/index.js"></script>

In your src/index.js:

// For NPM only
// import Cloneable from "@nawawishkid/cloneable.js"

const container = document.getElementById("cloneable-container");
const cloneable = new Cloneable(container);

cloneable.init();

Now the #cloneable-container will be like:

<div id="cloneable-container">
  <div class="tray">
    <p>Clone me!</p>
    <div class="cloned" data-cloned-id="1">
      <p>Clone me!</p>
      <button class="remove-btn">Remove</button>
    </div>
  </div>
  <div class="controllers"><button class="clone-btn">Clone</button></div>
</div>

Now, you can click .clone-btn button to clone <p>Clone me!</p> or clicking .remove-btn button to remove cloned element.

API

Types

CloneableEvents

Object of events that Cloneable accepts.

| name | type | default | isRequired | explanation | | ------------------- | ------------ | ---------------- | ---------- | --------------------------------------------------------------------------- | | load | function[] | [] Empty array | false | Array of event listeners (callback function) for load event | | beforeStateChange | function[] | [] Empty array | false | Array of event listeners (callback functions) for beforeStateChange event | | afterStateChange | function[] | [] Empty array | false | Array of event listeners (callback functions) for afterStateChange event | | uncloneable | function[] | [] Empty array | false | Array of event listeners (callback functions) for uncloneable event |

CloneableOptions

Object of options for Cloneable instance.

| name | type | default | isRequired | explanation | | -------------- | ----------------- | ----------------- | ---------- | --------------------------------------------------------------------------------- | | maxCloneable | number | Infinity | false | Maximum number of cloned element | | isAppend | bool | true | false | Whether the cloned element will be append or prepend to the source element | | cloneButton | HTMLElement | null | false | HTMLElement to be used as clone button | | removeButton | HTMLElement | null | false | HTMLElement to be cloned and then used as remove button for each cloned element | | middlewares | function[] | [] Empty array | false | Array of callback functions to be called with cloned element as an argument | | events | CloneableEvents | {} Empty object | false | CloneableEvents object |


Instantiation

Cloneable(HTMLElement container, CloneableOptions options = {})

Instantiate cloneable object.

Parameters

| name | type | default | isRequired | explanation | | ----------- | ------------------ | ----------------- | ---------- | -------------------------------------------------------------- | | container | HTMLElement | undefined | true | Any HTMLElement that its firstElementChild will be cloned. | | options | CloneableOptions | {} Empty object | false | CloneableOptions object |

Example

const options = {
  maxCloneable: 10,
  isAppend: false,
  cloneButton: document.querySelector(".my-clone-button"),
  removeButton: document.querySelector(".my-remove-button")
};
const container = document.getElementById("cloneable-container");
const cloneable = new Cloneable(container, options);

Properties

| key | type | explanation | | ------------- | ------------------ | ----------------------------------------------------------------------------------------- | | container | HTMLElement | Container element. | | middlewares | array | Array of registered middlewares. | | cloneButton | HTMLElement | Clone button element. An element, e.g. HTMLButtonElement, for triggering element cloning. | | options | CloneableOptions | CloneableOptions object of current Cloneable instance. | | events | CloneableEvents | CloneableEvents object of current Cloneable instance. |


Methods

Cloneable.init()

Initialize manipulation of given container element.

Note: You can't clone element without calling this method first.

This method will:

  1. Create .tray element.
  2. Move firstElementChild of the given container (the source element to be cloned) to the .tray element.
  3. Create .controllers element.
  4. Get/create .clone-btn button then append to the .controllers element.
  5. Append the .tray and .controllers elements to the given container.

Return

this

Example

// Nothing in document changes at this point
const cloneable = new Cloneable(container);

// DOM manipulated! Ready to clone element.
cloneable.init();

Cloneable.clone()

Clone the element programmatically.

Clone the element, wrap it with wrapper element, then inject them into the given container element. The wrapper element has been assigned data-cloned-id attribute so that it can be refered to later e.g. used by Cloneable.removeClonedElement() method.

Return

this


Cloneable.removeClonedElement(Number id)

Remove the cloned element programmatically.

Remove cloned element with specified ID. Cloned element ID is a sequential number of cloning order. The first cloned element's ID is 1, the second is 2, and so on.

This method will find element using Cloneable.tray.querySelector('[data-cloned-id="${id}"]') then remove it.

Parameters

| name | type | default | isRequired | explanation | | ---- | -------- | ----------- | ---------- | ---------------------------------- | | id | number | undefined | true | ID of cloned element to be removed |

Return

this

Example

const cloneable = new Cloneable(container);

// Clone element 2 times. Now, we have 2 cloned elements.
cloneable
  .init()
  .clone()
  .clone();

// Remove first cloned element. Now, there is only 1 cloned element.
cloneable.removeClonedElement(1);

Cloneable.middleware(...callbacks)

Register middleware function to be called with cloned element as an argument. Use to alter the cloned element.
This method accepts argument list.

Parameters

| name | type | default | isRequired | explanation | | ---------- | ---------- | ----------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------- | | callback | function | undefined | true | Middleware function which accepts the cloned element as the first argument and cloned element's index or ID as a second argument |

Return

this

Example

Change textContent of the cloned element.

const cloneable = new Cloneable(container);

cloneable
  .middleware((cloned, index) => {
    cloned.textContent = `Cloned #${index}`;

    return cloned;
  })
  .init();

Cloneable.on(String eventName, ...eventListener)

Add event listener to the Cloneable object. Similar to Node.js EventEmitter class.

This method accepts argument list.

Parameters

| name | type | default | isRequired | explanation | | --------------- | ---------- | ----------- | ---------- | --------------------------------------------------------------- | | eventName | string | undefined | true | Event name. See available event at CloneableEvents. | | eventListener | function | undefined | true | Event listener callback function to be called on event occurred |

Return

this

Example

const cloneable = new Cloneable(container);

cloneable.on("beforeStateChange", () => {
  console.log("State is gonna change!");
});

cloneable.init();

Cloneable.isCloneable()

Check if it's still cloneable.

Return

| type | value | when | | ------ | ------- | -------------------------------------------------------------------------- | | bool | true | Number of cloned elements is less than maxCloneable value | | bool | false | Number of cloned elements is greater than or equal to maxCloneable value |

Example

const cloneable = new Cloneable(container, { maxCloneable: 2 });

cloneable.init();
cloneable.clone().isCloneable(); // -> true
cloneable.clone().isCloneable(); // -> false