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

chainable-object

v1.2.0

Published

Create objects with chainable properties

Downloads

5

Readme

Chainable Object

Build Status npm version

Create objects with chainable properties

Allows the creation of D3-style chainable objects.

Usage

Creating chainable objects

var chainable = require('chainable-object');

// create chainable object
var instance = chainable( {
    foo: {
        bar: {
            qux: 'a value for qux' //initial value for `foo().bar().qux()`
        },
        baz: 'a value for baz' //initial value for `foo().baz()`
    }
} );

// now use it

//retrieve a value
console.log(instance.foo().bar().qux()); //outputs: "a value for qux"

//set a value directly
instance.foo().bar().qux('other value'); //sets the value of `qux` to "other value"
console.log(instance.foo().bar().qux()); //outputs: "other value"

//set a nested value through the use of an object
instance.foo().bar({qux: 'yet another value'}); //sets the value of `qux` to "yet another value"
console.log(instance.foo().bar().qux()); //outputs: "yet another value"

Processing of values

If you need to process the value before it's set, you can provide a processor function:

// create chainable object
var instance = chainable( {
    foo: {
        bar: function processBar(value){
            return value.toUpperCase() + '!!!';
        }
    }
} );

instance.foo().bar('burn motherfucker, burn');
console.log(instance.foo().bar()); //outputs: "BURN MOTHERFUCKER, BURN !!!"

v1.2.0 and up

Processors receive the name of the property as a second argument:

var instance = chainable({
  foo: function(value, name){
    console.log('name:', name);
    return value;
  }
});
instance.foo('a value for foo'); //output: 'name: foo'

Combining processors and initial values

Just wrap 'm in an Array. The processor always goes first!

// create chainable object
var instance = chainable( {
    foo: {
        bar: [ 
            function processBar(value){
                return value.toUpperCase() + '!!!';
            }, 
            "initial value"
        ]
    }
} );

console.log(instance.foo().bar()); //outputs: "initial value"
instance.foo().bar('burn motherfucker, burn');
console.log(instance.foo().bar()); //outputs: "BURN MOTHERFUCKER, BURN !!!"

CAVEAT: if you want to set a function or an object as an initial value, you HAVE TO use the Array syntax:

// create chainable object
var instance = chainable( {
    foo: {
        bar: [
            'value',  // tells `chainable-object` no processing is necessary, `falsy` values will have the same effect
            function(){ // initial value of `foo().bar()`
                return 10;
            }
        ]
    }
} );

console.log(instance.foo().bar()); //outputs: "[Function]"
console.log(instance.foo().bar()()); //outputs: "10"

Existing objects and prototypes

You can mix chainable properties into an already existing object:

var instance = {
    output: function(){
        console.log('Heads will roll!');
    }
}

// mixin
chainable( instance, {
    foo: {
        bar: 'bar'
    }
} );

console.log(instance.foo().bar()); //outputs: "bar"
console.log(instance.output()); //outputs: "Heads will roll!"

The same applies to prototypes:

function AwesomeClass(){
}

// mixin
chainable( AwesomeClass.prototype, {
    foo: {
        bar: 'Too drunk to fuck'
    }
} );

var instance = new AwesomeClass();
console.log(instance.foo().bar()); //outputs: "Too drunk to fuck"

Setting multiple root values at once

v1.1.0 and up

Nested objects can be updated by passing a vanilla object to the setters:

instance = chainable({
    foo:{
        bar: 'a value for bar'
    },
    qux: 'a value for qux',
    baz: 'a value for baz'
});

//set a nested value through the use of an object
instance.foo({bar: 'yet another value'}); //sets the value of `bar` to "yet another value"
console.log(instance.foo().bar()); //outputs: "yet another value"

However, what if you'd want to set the value of foo and the other root properties qux and baz? chainable-object adds a values accessor especially for this purpose:

instance.values({
    foo: {
        bar: 'a'
    },
    qux: 'b',
    baz: 'c'
});
console.log(instance.qux()); //outputs: 'b'

You can use it to retrieve a vanilla object with all the values too (aliased to toObject, since that's what it really does):

console.log(instance.values());
//outputs:
{
    foo: {
        bar: 'a'
    },
    qux: 'b',
    baz: 'c'
}

get and set

v1.2.0 and up

Another way to access the properties (with a bit more leeway) is to use get and set:

var instance = chainable(); 
instance.set('foo', 900); // creates a 'foo' method
console.log(instance.foo()); // output: 900
console.log(instance.get('foo')); // output: 900

get allows you to pass default values, in case the property has not been set yet:

var instance = chainable(); 
var value = instance.get('foo', 'a default value for foo');
console.log(value); // outputs: 'a default value for foo'

get will not create a property, i.e. this will throw:

var instance = chainable();
instance.get('foo', 'a default value for foo');
instance.foo(); // throws: TypeError: instance.foo is not a function

Installation and other shizzle

Use bower or npm to install chainable-object. You can use it on the front- and backend, but for clientside you'll need webpack or browserify to get it going. We'll have none of that global variable shizzle.

Dependencies: lodash

If you don't want to pull in lodash entirely or you prefer underscore you can configure webpack to swap lodash with Your Preference (TM).

//file: webpack.config.js or some such
resolve: {
    alias: {
        "lodash": "underscore/underscore.min"
    }
}

ATM chainable-object uses the following lodash functions: isObject, isArray, isFunction and each, i.e. just replace "underscore/underscore.min" in the above example with the location of your file where you provide those functions.

License

MIT