/**
 * jQuery AJAXify lite
 * 
 * AJAX-'ifies' any <form> or <a> using the specified method of the form.
 * 
 * Also sends the value of the button clicked, and the x/y if using <input type="image"/>
 * 
 * @package jquery-ajaxify-lite
 * @author Dom Hastings
 */
(function ($) {
    /**
    * jQuery.ajaxify
    * 
    * The main wrapper method for the Ajaxify object.
    * 
    * This adds the event handlers to the required elements.
    * 
    * It can accept an options object
    * 
    * @param options object
    * @return object (this)
    * @author Dom Hastings
    */
    $.fn.ajaxify = function (options) {
        /**
        * appendToURL
        * 
        * Appends the specified query string to the URL being requested
        * 
        * @param url string The URL being requested
        * @return string The URL with the query string appended if specified
        * @author Dom Hastings
        */
        var appendToURL = function (url, append) {
            // if the options specify a URL append
            if (append) {
                // if there's a # in the url, strip it off first
                if (url.indexOf('#') != -1) {
                    url = url.substr(0, url.indexOf('#'));
                }

                // add it correctly (using & if ? already appears in the URL)
                url += (url.indexOf('?') == -1 ? '?' : '&') + (typeof append == 'string' ? append : $.param(append));
            }

            return url;
        }


        options = $.extend({
            'append': 'ajax=1',
            'buttons': 'button[type=submit], input[type=submit], input[type=image]',
            'replace': true,  // if set to true, will replace content in the update element, otherwise will just append
            'replaceWith': true, // if set to true, will replace the outer element as well
            'beforeAjax': null,
            'update': null,
            'convertQueryToPost': false,
            // jQuery AJAX options, see http://docs.jquery.com/Ajax/jQuery.ajax#toptions
            'async': true,
            'beforeSend': null,
            'complete': null,
            'contentType': null,
            'dataFilter': null,
            'dataType': 'html',
            'animate': false,
            'animateSpeed': 300,
            'loadingNotification': null,
            'error': function (XHR, textStatus, errorThrown) {
                alert('Error processing data via AJAX:\n' + errorThrown + ' (' + textStatus + ')');
            },
            'success': function (data, textStatus) {
                var redirect = false;
                if (data.indexOf('pageName="account:login"') != -1) redirect = true;
                if (redirect) {
                    window.location.href = "/Course/CourseMaterials.aspx?c=kekula&p=volume";
                }
                else {
                    if (this.replace) {
                        if (this.replaceWith) {
                            if (this.animate) {
                                jQuery(this.update).parent().css('opacity', '0');
                                jQuery(this.update).replaceWith(data);
                                jQuery(this.update).parent().animate({ opacity: 1 }, this.animateSpeed);
                            }
                            else {
                                jQuery(this.update).replaceWith(data);
                            }
                        } else {
                            if (this.animate) {
                                jQuery(this.update).css('opacity', '0');
                                jQuery(this.update).html(data);
                                jQuery(this.update).animate({ opacity: 1 }, this.animateSpeed);
                            }
                            else {
                                jQuery(this.update).html(data);
                            }
                        }
                    } else {
                        jQuery(this.update).append(data);
                    }
                }
                jQuery(this.loadingNotification).css('display', 'none');
            },
            'type': null,
            'url': null
        }, options || {});

        $(this.selector).live('submit click', options, function (event) {
            // clone the options object, so you don't get the same details for each one
            var options = $.extend({}, event.data);

            if ($(this).prop('tagName').toLowerCase() == 'a' && event.type == 'click') {
                // prevent the normal 'default' action (eg. following the link)
                event.preventDefault();

                // set the url to the action attribute or the options url if specified on init
                options.url = options.url || appendToURL($(this).attr('href'), options.append);

                // update the element specified in options, or the parent element if not
                options.update = options.update || $(this).attr('target');

                // set the type to the method attribute or the options type
                options.type = options.type || 'GET';

                // set the content type
                options.contentType = options.contentType || 'application/x-www-form-urlencoded';

                // get the form data
                if (options.data && typeof options.data != 'string') {
                    options.data = $.param(options.data);
                } else if (options.convertQueryToPost) {
                    var urlSplit = options.url.split('?');
                    options.url = urlSplit[0];
                    options.data = urlSplit[1];
                    options.type = 'POST';
                } else {
                    options.data = false;
                }

                if (event.data.loadingNotification != null) {
                    jQuery(event.data.loadingNotification).css('display', 'block');
                }

                if (event.data.beforeAjax) {
                    if (event.data.animate) {
                        jQuery(options.update).animate({ opacity: 0 }, event.data.animateSpeed, function () {
                            event.data.beforeAjax();
                            $.ajax(options);
                        });
                    }
                    else {
                        $.ajax(options);
                    }
                }
                else {
                    if (event.data.animate) {
                        jQuery(options.update).animate({ opacity: 0 }, event.data.animateSpeed, function () {
                            $.ajax(options);
                        });
                    }
                    else {
                        $.ajax(options);
                    }
                }


            } else if ($(this).prop('tagName').toLowerCase() == 'form' && event.type == 'submit') {
                // prevent the normal 'default' action (eg. following the link)
                event.preventDefault();

                // set the url to the action attribute or the options url if specified on init
                options.url = options.url || appendToURL($(this).attr('action'), options.append);

                // update the element specified in options, or the parent element if not
                options.update = options.update || $(this).attr('target');

                // set the type to the method attribute or the options type
                options.type = options.type || $(this).attr('method').toUpperCase();

                // set the content type
                options.contentType = options.contentType || ($(this).attr('enctype') || 'application/x-www-form-urlencoded');

                // get the form data
                if (options.data) {
                    if (typeof options.data == 'string') {
                        options.data = $(this).serialize() + '&' + options.data;

                    } else {
                        options.data = $(this).serialize() + '&' + $.param(options.data);
                    }

                } else {
                    options.data = $(this).serialize();
                }

                if (event.data.beforeAjax) event.data.beforeAjax();
                $.ajax(options);

                // clean up the hidden inputs
                $('input.ajaxify__submitButton__').remove();
            }
        });

        // capture all the submit buttons
        var selectors = this.selector.split(/\s*,\s*/);
        var buttons = options.buttons.split(/\s*,\s*/);

        for (var i = 0; i < selectors.length; i++) {
            for (var j = 0; j < buttons.length; j++) {
                $(selectors[i] + ' ' + buttons[j]).live('mousedown keydown', function (event) {
                    $(this).after('<input type="hidden" name="' + $(this).attr('name') + '" value="' + $(this).val() + '" class="ajaxify__submitButton__"/>');

                    // if it's an imagae, also capture the x/y co-ordinates
                    if ($(this).attr('type') == 'image') {
                        $(this).after('<input type="hidden" name="' + $(this).attr('name') + '_y" value="' + (event.pageY - $(this).offset().top) + '" class="ajaxify__submitButton__"/>');
                        $(this).after('<input type="hidden" name="' + $(this).attr('name') + '_x" value="' + (event.pageX - $(this).offset().left) + '" class="ajaxify__submitButton__"/>');
                    }
                });
            }
        }

        // return the jQuery object for chaining
        return this;
    }
})(jQuery);

