/**
 * jQuery custom event "outerClick".
 * @author David Brockman Smoliansky http://littleroom.se/
 * @license GNU Lesser General Public License: http://creativecommons.org/licenses/LGPL/2.1/
 * @version 1.1
 * 2009/02/27
 * 
 * The outerClick event is fired when an element outside of the target element is clicked.
 * 
 * Usage:
 * $(selector).bind("outerClick", fn);   // Bind the function fn to the outerClick event on each of the matched elements.
 * $(selector).outerClick(fn);           // Bind the function fn to the outerClick event on each of the matched elements.
 * $(selector).trigger("outerClick");    // Trigger the outerClick event on each of the matched elements.
 * $(selector).outerClick();             // Trigger the outerClick event on each of the matched elements.
 * $(selector).unbind("outerClick", fn); // Unbind the function fn from the outerClick event on each of the matched elements.
 * $(selector).unbind("outerClick");     // Unbind all outerClick events from each of the matched elements.
 */

/*global jQuery */
(function ($, elements, OUTER_CLICK) {
    
    /**
     * Check if the event should be fired.
     * @param {Object} event  The click event.
     * @private
     */
    function check(event) {
        for (var i = 0, l = elements.length, target = event.target, el; i < l; i++) {
            el = elements[i];
            if (el !== target && !(el.contains ? el.contains(target) : el.compareDocumentPosition ? el.compareDocumentPosition(target) & 16 : 1)) {
                $.event.trigger(OUTER_CLICK, event, el);
            }
        }
    }
    
    
    $.event.special[OUTER_CLICK] = {
        
        setup: function () {
            var i = elements.length;
            if (!i) {
                $.event.add(document, 'click', check);
            }
            if ($.inArray(this, elements) < 0) {
                elements[i] = this;
            }
        },
        
        teardown: function () {
            var i = $.inArray(this, elements);
            if (i >= 0) {
                elements.splice(i, 1);
                if (!elements.length) {
                    $.event.remove(document, 'click', check);
                }
            }
        }
        
    };
    
    
    /**
     * Event helper outerClick
     * 
     * @param  {Function} [fn]  A function to bind to the outerClick event on each of the matched elements.
     *                          If fn is omitted the event is triggered.
     * @return {jQuery}         Returns the jQuery object.
     */
    $.fn[OUTER_CLICK] = function (fn) {
        return fn ? this.bind(OUTER_CLICK, fn) : this.trigger(OUTER_CLICK);
    };
    
})(jQuery, [], 'outerClick');



