(function ($) {

    //================================
    // fields
    //================================

    var selectorInputs = "SELECT,TEXTAREA,INPUT:not([type=CHECKBOX],[type=RADIO],[type=BUTTON],[type=IMAGE],[type=SUBMIT],[type=RESET],[type=FILE],[type=SEARCH])",
        selectorSelect = "INPUT[type=CHECKBOX],INPUT[type=RADIO]";

    //================================
    // main
    //================================

    $.fn.observedForm = function (method) {

        var result = null;

        if (METHODS[method]) {
            return METHODS[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }
        else if (typeof method === 'object' || !method) {
            return METHODS.init.apply(this, arguments);
        }
        else {
            $.error('Method ' + method + ' does not exist on jQuery.dirtyForms');
        }

        return result;

    }

    //================================
    // methods
    //================================

    var METHODS = {

        init: function () {

            $.proxy(METHODS.clear, this)();
            $.proxy(METHODS.setup, this)();

            return this;

        },

        setup: function () {

            if (!$(this).is("FORM")) {
                return;
            }

            this.addClass("observedForm");

            this.off("change.observedForm");
            this.on("change.observedForm", selectorInputs, function (e) {
                $(e.target).addClass("isDirty");
            });

            this.off("click.observedForm");
            this.on("click.observedForm", selectorSelect, function (e) {
                $(e.target).addClass("isDirty");
            });

            $.proxy(METHODS.addTriggers, this)();

        },

        clear: function () {

            this.find(".isDirty").removeClass("isDirty");

        },

        addTriggers: function () {
            
            var that = this;

            $(document).off("click.observedFormCheck");
            $(document).on("click.observedFormCheck", ".observedFormCheck", $.proxy(function (e) {

                if ($.proxy(METHODS.dirty, that)()) {
                    alert("dirty");
                }

            }, this));

        },

        dirty: function () {

            return $(document).find(".isDirty").length > 0;

        },

        destroy: function () {
            this.removeClass("observedForm");
            this.off("change.observedForm");
            this.off("click.observedForm");
        }

    };

})(jQuery);