(function($) {
    $.atajacks = function(options) {
        var options = jQuery.extend({
            url: null,
            type: "GET",
            form: null,
            elements: null,
            success: null,
            error: null,
            skinHack: false,
            aspnet: false
        }, options);

        var els = [];

        $(options.elements).each(function() {
            if (this.id)
                els.push(this.element ? this : { id: this.id });
            else if (window.console && window.console.log)
                console.log("Element found with " + options.elements + " has no id!");
        });

        function success(data) {
            jQuery.each(els, function() {
                var el = this.element ? this.element : $("#" + this.id);
                if (el.length) {
                    var m = data.match(new RegExp("<!--atajacks id=\"" + this.id + "\"-->([\\s\\S]*?)<!--/atajacks id=\"" + this.id + "\"-->", "i"));
                    if (m) {
                        el.html(m[1]);
                    } else {
                        m = data.match(new RegExp("<([a-z0-9:-]+)[^>]+?id\\s*=\\s*\"" + this.id + "\"[^>]*?>", "i"));
                        if (m) {
                            var elPos = RegExp.leftContext.length;
                            var contentStart = elPos + m[0].length;
                            var level = 1;
                            var re = new RegExp("<\\s*?(/?)\\s*?" + m[1] + "\\s*(/?)[^>]*>", "gi");
                            while (m = re.exec(data)) {
                                var pos = RegExp.leftContext.length;
                                if (pos > elPos) {
                                    if (m[2] != "/")
                                        level += ((m[1] == "/") ? -1 : 1);
                                    if (level == 0) {
                                        el.html(data.substring(contentStart, pos));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            });

            if (options.aspnet) {
                var m;

                if (m = data.match(/<input[^>]+name="__VIEWSTATE"[^>]+value="([^"]*)"/i))
                    $("#__VIEWSTATE").val(m[1]);
            }

            if (options.success)
                options.success();
        }

        var url = (options.url || location.href).replace(/#.*/, "");
        if (options.skinHack)
            url += ((url.indexOf("?") == -1) ? "?" : "&") + "SkinSrc=[L]Skins/empty/empty";

        var data = options.form ? $("input,textarea,select", options.form).serialize() : "";
        if (options.aspnet)
            data += ((data == "") ? "" : "&") + "__VIEWSTATE=" + encodeURIComponent($("#__VIEWSTATE").val());

        $.ajax({ // why, oh why must you torture me with this word, jQuery!?
            dataType: "text",
            type: options.type,
            url: options.url || location.href,
            data: data,
            success: success,
            error: options.error
        });
    };

    $.fn.atajacksUpdate = function(options) {
        return $(this).each(function() {
            var aoptions = jQuery.extend({
                elements: this
            }, options);

            $.atajacks(aoptions);
        });
    };

    $.fn.atajacksForm = function(options) {
        return $(this).each(function() {
            var oSuccess = options ? options.success : null;
            var form = $(this);

            function attach() {
                var aoptions = jQuery.extend({
                    type: "POST",
                    form: form,
                    elements: form,
                    submit: $("input[type=submit],button[type=submit],.submit", form)
                }, options);

                aoptions.success = success;

                $(aoptions.submit).click(function(e) {
                    var submit = $(this);
                    $(".atajacks_fake_submit__", form).remove();
                    var input = $("<input type=\"hidden\" class=\"atajacks_fake_submit__\" />");
                    input.attr("name", submit.attr("name") || submit.attr("id"));
                    input.val(submit.attr("ievalue") || submit.attr("value"));
                    form.append(input);

                    $.atajacks(aoptions);
                    e.preventDefault();
                });
            }

            function success() {
                attach();
                if (oSuccess)
                    oSuccess();
            }

            attach();
        });
    };
})(jQuery);
