/**!
* Ajaxify jQuery plugin
* Author: Andrew Rowls
*
* Simple ajaxify plugin.  Relies on server-side (django) validation.
*
*/
(function($){
$.fn.ajaxify = function(options){
    function fieldfocus(f) {
        var $f = $(f),
            val = $.trim($f.siblings("label").text())
        if ($f.data("maintype") == "password") {
            if ($f.data("primary") === true) return
            var replacement = $f.data("swap")
            replacement.insertAfter($f)
            $f.detach()
            $f = replacement
            $f.focus()
            $f.focus()
        }
        if ($f.val() == val)
            $f.val("")
        $f.css({
            color: "#000",
            "font-style": "normal"
        })
    }
    function fieldblur(f){
        var $f = $(f)
        if ($f.val() == "") {
            if ($f.data("maintype") == "password") {
                var replacement = $f.data("swap")
                replacement.insertAfter($f)
                $f.detach()
                $f = replacement
            }
            else {
                $f.val($.trim($f.siblings("label").text()))
                $f.css({
                    color: "#666",
                    "font-style": "italic"
                })
            }
        }
    }
    var o = $.extend({}, $.fn.ajaxify.defaults, options)
    return this.each(function(){
        if (this.nodeName.toLowerCase() != "form") return true

        $(this)
            .delegate(":text, :password, textarea", "focus", function(){fieldfocus(this)})
            .delegate(":text, :password, textarea", "blur", function(){fieldblur(this)})
        $(":text, :password, textarea", this)
        .filter(":not(.exclude)")
        .each(function(){
            if (this.type == "password") {
                $(this).data({
                    primary: true,
                    maintype: "password",
                    swap: $("<input>", {
                                        type: "text",
                                        value: $(this).siblings("label:first").text()
                                        }
                            ).data({
                                primary: false,
                                maintype: "password",
                                swap: $(this)
                            })
                            .css({
                                fontStyle: "italic",
                                color: "#666"
                            })

                })
            }
            $(this).siblings("label").hide()
        })
        .focus().blur()

        $(this).submit(function(){
            // serialize form, ensuring default values aren't mistaken as input.
            var mod = $("input:text, input:password, textarea", this).filter(":not(.exclude)")
            mod.each(function(){fieldfocus(this)})
            o.beforeSubmit.apply(this)
            var data = $(this).serialize()
            mod.each(function(){fieldblur(this)})

            $(".errorlist", this).clearQueue().slideUp({complete: function(){$(this).remove()}})

            $.ajax({
                type: this.getAttribute("method").toUpperCase() || "POST",
                url: this.getAttribute("action")+"?json",
                data: data,
                context: this, // keep the form as the context
                dataType: "json",
                success: function(data, status, xhr){
                    var fields = data[this.id+'_form'], errs = false, redirecting = false
                    for (var field in fields) {
                        var f = fields[field]
                        $("input#id_"+field).css("background-color", "#FFF") // reset colors from errors
                        if (field == "errors" && f.length > 0) {
                            errs = true
                            $("<ul class='errorlist'><li>"+f.join("</li><li>")+"</li></ul>")
                            .hide()
                            .insertBefore($("ul", this).first())
                            .slideDown()
                        }
                        else if (field == "messages" && f.length > 0) {
                            errs = true
                            var msg = $("<ul class='messagelist'><li>"+f.join("</li><li>")+"</li></ul>")
                            .hide()
                            .insertBefore($("ul", this).first())
                            .slideDown()

                            if ("next" in data && typeof data['next'] == "string") {
                                redirecting = true

                                /* google analytics event tracking. */
                                if (('gaOptions' in options) &&  /* We've been given analytics options */
                                    ('trackEvent' in options.gaOptions) &&  
                                    (options.gaOptions.trackEvent === true) && /* We've requested event tracking*/
                                    (_gaq !== undefined)) /* Analytics asynchronous object exists.*/
                                {
                                    var ga_opts = options.gaOptions;
                                    var label = $(ga_opts.labelID).val();
                                    _gaq.push(['_trackEvent', ga_opts.category, ga_opts.action, label]);
                                    /*_gaq.push(function(){ console.log("logged", label) });*/
                                }
                                return false;
                                msg.animate({opacity: 1}, 10, function(){document.location = data['next']})
                            }
                        }
                        else if (f['errors'].length > 0) {
                            errs = true;

                            var field_id = '#id_' + field;
                            var field_ptr = $(field_id, this);

                            try {
                                if (field_ptr.get(0) === undefined)
                                {
                                    // For nullboolean fields.
                                    field_ptr = $(field_id + '_0', this);
                                }

                                $("<ul class='errorlist'><li>"+f['errors'].join("</li><li>")+"</li></ul>")
                                .hide()
                                .prependTo(
                                    field_ptr
                                        .css("background-color", "#FCC")
                                        .get(0).parentNode
                                )
                                .slideDown();
                            }
                            catch(e)
                            {
                                //console.log(field_id, e);
                            }
                        }
                    }

                    if (!errs && !redirecting)
                    {
                        /* google analytics event tracking. */
                        if ((options !== undefined) && ('gaOptions' in options) &&  /* We've been given analytics options */
                            ('trackEvent' in options.gaOptions) &&  
                            (options.gaOptions.trackEvent === true) && /* We've requested event tracking*/
                            (_gaq !== undefined)) /* Analytics asynchronous object exists.*/
                        {
                            var ga_opts = options.gaOptions;
                            var label = $(ga_opts.labelID).val();
                            _gaq.push(['_trackEvent', ga_opts.category, ga_opts.action, label]);
                            /*_gaq.push(function(){ console.log("logged", label) });*/
                        }

                        if ("next" in data && typeof data['next'] == "string")
                        {
                            document.location = data['next'];
                        }
                    }
                },
                error: function(xhr, status, error){
                    err = [
                        "There was an error submitting the form, please try again later."
                    ]
                    $("<ul class='errorlist'><li>"+err.join("</li><li>")+"</li></ul>")
                    .hide()
                    .insertBefore($("ul", this).first())
                    .slideDown()
                    .delay(5000)
                    .animate({opacity: 0}, 1000)
                    .slideUp({duration: 'slow', complete: function(){
                        $(this).remove()
                    }})
                }
            })
            return false
        })
    })
}
$.fn.ajaxify.defaults = {}
$.fn.ajaxify.defaults.beforeSubmit = function(){}
}(jQuery))

