Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

can-key-tree

Package Overview
Dependencies
Maintainers
3
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

can-key-tree

Add and remove items to a tree

  • 1.0.2
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
1.5K
decreased by-46.71%
Maintainers
3
Weekly downloads
 
Created
Source

can-key-tree

Build Status

can-key-tree can be used to store items in a tree-like structure where the nodes of the tree can be any type that works with can-reflect.

Use

Import the KeyTree constructor from can-key-tree:

import KeyTree from  "can-key-tree";

Create an instance of KeyTree with an array of types. An instance of each type will be used as the nodes of the tree. The following creates a tree structure 3 levels deep:

const keyTree = new KeyTree( [ Object, Object, Array ], { onFirst, onEmpty } );

Once you've created a keyTree, you can .add, .delete and .get values from it.

.add(keys)

The following adds three handlers:

function handler1() {}
function handler2() {}
function handler3() {}

keyTree.add( [ "click", "li", handler1 ] );
keyTree.add( [ "click", "li", handler2 ] );
keyTree.add( [ "click", "span", handler3 ] );

The keyTree data structure will look like:

{
	"click": {
		"li": [ handler1, handler2 ],
		"span": [ handler3 ]
	}
}
.get(keys)

To get all the li click handlers, use .get:

keyTree.get( [ "click", "li" ] ); //-> [handler1, handler2]

To get all click handlers, you can also use .get:

keyTree.get( [ "click" ] ); //-> [handler1, handler2, handler3]
.delete(keys)

To delete a handler, use .delete:

keyTree.delete( [ "click", "li", handler1 ] );

The keyTree data structure will look like:

{
	"click": {
		"li": [ handler2 ],
		"span": [ handler3 ]
	}
}

To delete the remaining click handlers:

keyTree.delete( [ "click" ] );

The keyTree data structure will look like:

{}

Advanced Use

Often, when a node is created, there needs to be some initial setup, and when a node is empty, some teardown.

This can be achieved by creating custom types. For example, perhaps we want to build an event delegation system where we can delegate from an element like:

eventTree.add( [ document.body, "click", "li", handler ] );

And remove that handler like:

eventTree.delete( [ document.body, "click", "li", handler ] );

We can do that as follows:

// Create an event handler type.
const Delegator = function( parentKey ) {

	// Custom constructors get called with their parentKey.
	// In this case, the `parentKey` is the element we will
	// delegate from.
	this.element = parentKey;

	// the nested data `{click: [handlers...], dblclick: [handlers...]}`
	this.events = {};

	// the callbacks added for each handler.
	this.delegated = {};
};
canReflect.assignSymbols( Delegator.prototype, {

	// when a new event happens, setup event delegation.
	"can.setKeyValue": function( eventName, handlersBySelector ) {

		this.delegated[ eventName ] = function( ev ) {
			canReflect.each( handlersBySelector, function( handlers, selector ) {
				let cur = ev.target;
				do {
					if ( cur.matches( selector ) ) {
						handlers.forEach( function( handler ) {
							handler.call( cur, ev );
						} );
					}
					cur = cur.parentNode;
				} while ( cur && cur !== ev.currentTarget );
			} );
		};
		this.events[ eventName ] = handlersBySelector;
		this.element.addEventListener( eventName, this.delegated[ eventName ] );
	},
	"can.getKeyValue": function( eventName ) {
		return this.events[ eventName ];
	},

	// when an event gets removed, teardown event delegation and clean up.
	"can.deleteKeyValue": function( eventName ) {
		this.element.removeEventListener( eventName, this.delegated[ eventName ] );
		delete this.delegated[ eventName ];
		delete this.events[ eventName ];
	},

	// we need to know how many items at this node
	"can.getOwnEnumerableKeys": function() {
		return Object.keys( this.events );
	}
} );

// create an event tree that stores:
// - "element being delegated" ->
//   - A "delegator" instance for an event ->
//     - The "selectors" we are delegating ->
//       - The handlers to call
const eventTree = new KeyTree( [ Map, Delegator, Object, Array ] );


// to listen to an event:
function handler() {
	console.log( "an li clicked" );
}

eventTree.add( [ document.body, "click", "li", handler ] );

// to stop listening:
eventTree.delete( [ document.body, "click", "li", handler ] );

// to stop listening to all clicks on the body:
eventTree.delete( [ document.body, "click" ] );

// to stop listening to all events on the body:
eventTree.delete( [ document.body ] );

Keywords

FAQs

Package last updated on 16 Feb 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc