ferics2
ferics2

Reputation: 5442

How to create a javascript library using a closure

I have written some javascript that I would to encapsulate in a closure so I can use it elsewhere. I would like do do this similar to the way jQuery has done it. I would like to be able to pass in an id to my closure and invoke some functions on it, while setting some options. Similar to this:

<script type="text/javascript">
    _snr("#canvas").draw({
        imageSrc : someImage.png
    });
</script>

I have read a lot of different posts on how to use a closure to do this but am still struggling with the concept. Here is where I left off:

_snr = {};
(function (_snr) {

    function merge(root){
        for ( var i = 1; i < arguments.length; i++ )
            for ( var key in arguments[i] )
                root[key] = arguments[i][key];
        return root;
    }

    _snr.draw = function (options) {

        var defaults = {
            canvasId : 'canvas',
            imageSrc : 'images/someimage.png'
        }

        var options = merge(defaults, options)

        return this.each(function() {
            //More functions here
        });
    };

    _snr.erase = function () {};

})(_snr);

When ever I try to call the draw function like the first code section above, I get the following error, '_snr is not a function'. Where am I going wrong here?

EDIT Here is what I ended up doing:

function _snr(id) {

    // About object is returned if there is no 'id' parameter
    var about = {
        Version: 0.2,
        Author: "ferics2",
        Created: "Summer 2011",
        Updated: "3 September 2012"
    };

    if (id) {

        if (window === this) {
            return new _snr(id);
        }

        this.e = document.getElementById(id);
        return this;
    } else {
        // No 'id' parameter was given, return the 'about' object
        return about;
    }
};

_snr.prototype = (function(){

    var merge = function(root) {
        for ( var i = 1; i < arguments.length; i++) {
            for ( var key in arguments[i] ) {
                root[key] = arguments[i][key];
            }
        }
        return root;
    };

    return {
        draw: function(options) {

            var defaults = {
                canvasId : 'canvas',
                imageSrc : 'images/someimage.png'
            };

            options = merge(defaults, options);

            return this;
        },

        erase: function() {
            return this;
        }
    };
})();

I can now call:

<script type="text/javascript">
    _snr("#canvas").draw({
        imageSrc : someImage.png
    });
</script>

Upvotes: 3

Views: 686

Answers (5)

yilmazhuseyin
yilmazhuseyin

Reputation: 6612

Here you have a snr object and that has erase and draw methods. What you intend to do is to write a _snr function which will get an id and return a wrapper object. That returned object should have erase and draw methods. so you can do var returnedObject = _snr("my_id"); returnedObject.draw("image.png");

Upvotes: 0

EaterOfCode
EaterOfCode

Reputation: 2222

You are going wrong at the first line _snr = {}

It needs to be

_snr = function(){
    selector = arguments[0]||false;
    //snr init on dom object code
    return _snrChild;
}

Im on a mobile phone but when im on a pc I will maybe fix the whole code c:

Upvotes: 0

richoffrails
richoffrails

Reputation: 1033

When you do _snr('#canvas') that is a function call which is why you're getting that error. _snr is an object with some methods attached to it such as draw() and erase(). The reason jQuery is able to pass arguments into the $ is because they return the $ as a function object which is why we're able to pass it various selectors as arguments.

Upvotes: 0

Florian Laplantif
Florian Laplantif

Reputation: 56

Because you declared _snr as an object and not a function. Functions can have properties and methods, so there's various ways to achieve what you want, for example one of them would be say...

_snr = function(tag) {
this.tag = tag;
}

_snr.foo = function() {
//Code goes here
}

You can also pass the outer context into a closure to hide your variables from accidentally polluting the global namespace, so like...

(function(global) {
var _snr = function(tag) {
this.tag = tag;
}

_snr.foo = function() {
//Code goes here
}

//export the function to the window context:
global._snr = _snr;
})(window);

window._snr('#tag').foo('wat');

Happy coding.

Upvotes: 4

Marc
Marc

Reputation: 6771

Because your _snr is an object, not a function. You have to call it like this:

_snr.draw({
    canvasId: '#canvas',
    imageSrc: 'someImage.png'
});

Upvotes: 2

Related Questions