jQuery.space

Posted on January 14, 2009. Filed under: JavaScript, jQuery, Software Development |

I continue my search for a good jQuery namespace support with testing jQuery.space by John Resig.

When you visit the plugin page of jQuery.space, you won’t find a download page. In fact, the plugin code was embeded in that page. You have to choose ‘View Source’ from your browser to get the code.

Below is the code fragment showing you the start and end of the jQuery.space code:

(function(jQuery){
    var oldFn, oldInit = jQuery.fn.init, oldPush = jQuery.fn.pushStack;
    var spaces = {};
    ...
    newjQuery.endSpace = function(){
        newjQuery.fn = oldFn;
    }
})(jQuery);

To use jQuery.space, you can embed the code in every HTML page that you want to use jQuery.space. The better way is, of course, saving the code into a separate file, say, jquery.space.js, and refer to it in your HTML page.

To wrap our fictitious textUtil plugin with jQuery.space, we call jQuery.space(“textUtil”) and jQuery.endSpace() respectively before and after our plugin implementation:

jQuery.space("textUtil");
{ ... implementation of textUtil plugin ... }
jQuery.endSpace();

One good thing about jQuery.space is that we can wrap existing plugin into a namespace, that means our plugin methods should be written in the same way as normal plugins. So our charCount() and upperCase() are written as:

$.fn.charCount = function(options){
    return cCount(this[0], options);
};
$.fn.upperCase = function(){
    return this.each(
        function(){
            uCase(this);
        }
    );
};

where cCount() and uCase() are private functions that actually carry out the work.

To call a method in our namespace, simply add the namespace before the method name:

$('.countMe').textUtil.upperCase();

There is a significant difference from other namespacing solutions that, after the call to .textUtil.upperCase(), the return jQuery object actually ‘remains’ in the textUtil namespace. So, if we want to call another method in the same namespace, we don’t need to add textUtil before the method again:

$('.countMe').textUtil.upperCase().charCount();

What about chaining to a jQuery built-in method? Because all methods in the parent namespace are accessible from the child namespace, so we can access those built-in methods as usual:

$('.countMe').textUtil.sentenceCase().addClass('class2').wordCount();

We can ‘exit’ a child namespace and return to the parent namespace with end(). This is necessary if we want to call a method in another namespace:

$('.countMe').textUtil.sentenceCase().addClass('class2').end().anotherSpace.anotherMethod();

I found it a bit tricky to set certain default values and then expose them to users to modify. I want to expose a defaults object with 2 properties, inclPunc and inclHTML. And users could override them with code like this:

$.fn.textUtil.defaults.inclPunc = false;

Since jQuery.space will add my namespace to all methods and properties in my plugin, so I declared the defaults object as:

$.fn.defaults = { inclPunc: true, inclHTML: true };

and hope I could access it with $.fn.textUtil.defaults. But I couldn’t.

In fact, I can only access the defaults object the same way as accessing my plugin methods, i.e. I must select some elements first:

$('*').textUtil.defaults.inclPunc = false;

Maybe there is a better way. But for now, I will go with that.

So far, seems that all my requirements are satisfied!

Source code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">
        <title>jQuery.space</title>
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="jquery.space.js"></script>
        <script type="text/javascript">

        // Begin the textUtil namespace
        jQuery.space("textUtil");

        (function($){
            // Define the public methods the usual way
            $.fn.charCount = function(options){
                return cCount(this[0], options);
            };
            $.fn.wordCount = function(){
                return wCount(this[0]);
            };
            $.fn.paraCount = function(){
                   return pCount(this[0]);
            };
            $.fn.upperCase = function(){
                return this.each(
                    function(){
                        uCase(this);
                    }
                );
            };
            $.fn.sentenceCase = function(){
                return this.each(
                    function(){
                        sCase(this);
                    }
                );
            };

            // Plugin defaults
            $.fn.defaults = { inclPunc: true, inclHTML: true };

            // Private worker functions (with dummy implementation)
            function cCount(ele, options){
                var opts = $.extend({}, $('*').textUtil.defaults, options);
                var c = 0;
                if (ele) {
                    c = ele.innerHTML.length;
                    if (!opts.inclPunc) {
                        c -= 10;
                    }
                    if (!opts.inclHTML) {
                        c -= 20;
                    }
                }
                return Math.max(0, c);
            }

            function wCount(ele){
                return cCount(ele) / 5;
            }

            function pCount(ele){
                return wCount(ele) / 10;
            }

            function uCase(ele){
                ele.innerHTML += " UPPERCASED ";
            }

            function sCase(ele){
                ele.innerHTML += " Sentence Cased ";
            }
        })(jQuery);        

        // End the namespace
        jQuery.endSpace();
        function onButtonClicked(){
            $('#result').html(
                // Test method invocation and chaining
                'Chars: ' + 
                $('.countMe').textUtil.upperCase().charCount() + 
                '<br/>' +
                // Test method invocation with params
                'Chars (excl punc & html)s: ' + 
                $('.countMe').textUtil.charCount({inclPunc: false, inclHTML: false}) + 
                '<br/>' +
                // Chain to a jQuery built-in method
                'Words: ' + 
                $('.countMe').textUtil.sentenceCase().addClass('class2').wordCount() + 
                '<br/>' +
                // or end() a namespace and go into it again
                /*
                'Words: ' + 
                $('.countMe').textUtil.sentenceCase().end().addClass('class2').textUtil.wordCount() + 
                '<br/>' +
                */
                'Paras: ' + 
                $('.countMe').textUtil.paraCount() + 
                '<br/>'
            );
        }
        </script>
        <style type="text/css">
            .countMe { border:1px black solid; margin: 2px; }
            .class2 { background-color: aqua; }
        </style>
    </head>
    <body>
        <div id="div1" class="countMe">This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. </div>
        <div id="div2" class="countMe">This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. This is a sample paragraph.
        This is a sample paragraph. This is a sample paragraph. This is a sample paragraph. </div>

        <div>
            <input type="button" onclick="onButtonClicked();return false;" value="Go" /><br/>
            <span id="result"></span>
        </div>
    </body>
</html>

Make a Comment

Leave a comment

One Response to “jQuery.space”

RSS Feed for Malnotna’s Blog Comments RSS Feed

Thank you for the post about jquery space.
I’m a bit confused about how to use space with a class. i.e.

jQuery.space(“foo”);
var Bar = Class.extend({
init: function(name) {
this.name = name;
}
});
jQuery.endSpace();

How to create new Bar ?
var x = new Bar(‘billy’);
obviously doesn’t work.

I’ve tried
new foo.Bar();
but still the same.

Thank you in advance.

Billy L's avatar

Where's The Comment Form?

Liked it here?
Why not try sites on the blogroll...

Design a site like this with WordPress.com
Get started