(function($) {
$.widget("dw.ajaxtip", $.ui.tooltip, {
    options: {
        content: undefined,
        items: "*",

        loadingContent: undefined,

        tooltipClass: "ajaxtip",
        position: {
            my: "left top+10",
            at: "left bottom",
            collision: "flipfit flipfit"
        }
    },
    _create: function() {
        // we override completely because we want to control what events trigger this widget
        var self = this;

        // attach (and remove) custom handlers
        this._on({
            ajaxtipopen: function (event, ui) {
                self._on( ui.tooltip, {
                    // we want to bind the events to the tooltip
                    // but we want close() to use this.element
                    // so we have to call this.close() ourselves
                    mouseleave: function() { self.close(); },
                    focusout: function() { self.close(); }
                });
            },
            ajaxtipclose: function(event, ui) {
                self._off( ui.tooltip, "mouseleave focusout" );
            }
        });

        this.tooltips = {};
        this.requests = [];
    },
    // close everything except the target (if it was a tooltip)
    closeinactive: function($target) {
        var target_id = $target.attr( "id" );
        if ( ! this.tooltips[target_id] ) {
            this.close();
        }
    },
    error: function(msg) {
        this.option("content", msg);
        this.open();
    },
    success: function(msg) {
        var self = this;
        self.option("content", msg);
        self.open();

        // this is only a confirmation message. We can fade away quickly
        window.setTimeout( function() { self.close(); }, 1500 );
    },
    sticky: function(msg) {
        var self = this;
        self.option("content", msg);
        self.open();
        $.each(self.tooltips, function(id, element) {
            // auto-close handlers on the tooltip itself:
            self._off($('#' + id), "mouseleave focusout");
            // auto-close handlers on the trigger element:
            element.off("mouseleave focusout");
        });
    },
    abort: function () {
        var self = this;
        if ( self.requests.length ) {
            $.each( self.requests, function (i, req) {
                req.abort();
            });
            self.requests = [];
        }
    },
    load: function(args) {
        /* opts is an object (or array of objects) containing overrides:
         *
         * endpoint : name of the endpoint we wish to use (not the URL)
         *
         * ajax     : options for the AJAX call, in case you want to override the defaults
         *            Here are the moste useful ones:
         *
         *    type      : POST or GET
         *    data      : any additional data to pass to the request
         *                 e.g., POST parameters
         *    context   : the context used for "this" in the callbacks
         *
         *    success   : success callback
         *    error     : error callback
         */

        var self = this;

        // abort and remove any old requests
        self.abort();

        if ( self.options.loadingContent ) {
            self.option("content", self.options.loadingContent);
            self.open();
        }

        $.each( $.isArray( args ) ? args : [ args ], function (i, opts) {
            var endpoint_url = $.endpoint( opts["endpoint"] );

            var deferred = $.ajax( $.extend({
                url : endpoint_url,
                context: self,

                dataType: "json"
            }, opts.ajax ));
            self.requests.push( deferred );

            deferred.fail(function(jqxhr, status, error) {
                if ( status !== "abort" &&          // "abort" status means we cancelled the ajax request
                        ( error && jqxhr.status )   // empty error / status means we probably cilcked
                                                    // away from the page before the ajax request was completed
                    ) {
                    self.error( "Error contacting server: " + error );
                }
            });

            if ( ! self.options.loadingContent ) {
                 // now add the throbber. It will be removed automatically
                $(self.element).throbber( deferred );
            }
        } );

        // clean out requests queue once all requests have successfully completed
        $.when.apply( $, self.requests ).done(function() {
            self.requests = [];
        });

    }
});

$.extend( $.dw.ajaxtip, {
    closeall: function(e) {
        $(":dw-ajaxtip").ajaxtip( "closeinactive", $(e.target).closest(".ajaxtip") );
    }
});
})(jQuery, Site);

jQuery(function($) {
    $(document).click(function(e) {
        $.dw.ajaxtip.closeall(e);
    });
});
