/* Copyright 2011 English360 */
/* Allows checking to see if a form has changed and stops the user from leaving with a warning if it has */
(function($) {
    $.fn.extend({
        formChanges: function(parameter, options) {
            var self = this;
            this.init = function(element, settings) {
                settings = $.extend({
                    message: "You have unsaved changes on this page.",
                    checkTinyMce: true,
                    tinyMceClassPrefix: "mce",
                    tinyMceEditors: []
                }, settings || {});

                $element = $(element);
                inputs = $element.find(":input, :radio, :checkbox");

                if (settings.checkTinyMce && typeof tinyMCE != "undefined") {
                    inputs.each(function() {
                        $this = $(this);
                        if (typeof($this.attr("class")) != "undefined" && $this.is(":input") && $this.attr("class").indexOf(settings.tinyMceClassPrefix) >= 0) {
                            settings.tinyMceEditors.push(this);
                        }
                    });
                }

                if (settings.tinyMceEditors.length > 0) {
                    this.waitForTinyMce(settings.tinyMceEditors, function() {
                        $element.formChanges("save", settings);
                    });
                } else {
                    $element.formChanges("save", settings);
                }

                if ($element.is("form")) {
                    $element.submit(function() {
                        $(this).formChanges("save", settings);
                        $element.get(0).allowSubmit = true;
                    });
                }

                function onBeforeUnload(event) {
                    var changed = false;
                    if ($element.is("form") && $element.get(0).allowSubmit) {
                        $element.get(0).allowSubmit = false;
                    } else {
                        inputs.each(function() {
                            if ($(this).formChanges("modified", settings)) {
                                changed = true;
                                return;
                            }
                        });
                    }

                    if (changed) {
                        var cancelHit = false;
                        try {
                            if (event.target.activeElement.text==='Cancel') { // Cancel button was hit
                                cancelHit = true;
                            }
                        } catch (e) {

                        }
                        if (!cancelHit) {
                            event = event || window.event;
                            event.returnValue = settings.message;
                            return settings.message;
                        }else {
                            changed = false;
                        }
                    }
                }

                if (window.attachEvent) {
                    window.attachEvent('onbeforeunload', onBeforeUnload);
                } else if (window.addEventListener) {
                    window.addEventListener('beforeunload', onBeforeUnload, true);
                }

                return element;
            };

            this.waitForTinyMce = function(editors, callback, run, limit) {
                limit = limit || 10;
                run = run || 1;

                var loaded = false;
                $(editors).each(function() {
                    var editor = tinyMCE.get($(this).attr("id"));
                    if (typeof editor != "undefined") {
                        if (editor.__loaded__) {
                            loaded = true;
                        } else {
                            editor.onInit.add(function(ed) {
                                ed.__loaded__ = true;
                            });
                        }
                    }
                });

                if (!loaded && run < limit) {
                    var self = this;
                    setTimeout(function() {
                        self.waitForTinyMce(editors, callback, run, limit);
                    }, 1 * run + 1);
                }

                if (loaded && callback) {
                    callback();
                }
            };

            this.modified = function(settings) {
                var $this = $(this);
                if ($this.is("form")) {
                    var modified = false;
                    $this.find(":input, :radio, :checkbox").each(function() {
                        modified = $(this).formChanges("modified", settings);
                        if (modified) {
                            return;
                        }
                    });
                    return modified;
                }

                var value = $this.data("formChangesValue");
                return (typeof value != "undefined" && value != $this.formChanges("value", settings));
            };

            this.save = function(settings) {
                var $this = $(this);
                if ($this.is("form")) {
                    $this.find(":input, :radio, :checkbox").each(function() {
                        $(this).formChanges("save", settings);
                    });
                    return;
                }

                $this.data("formChangesValue", this.value(settings));
                return this;
            };

            this.value = function(settings) {
                var value = null;
                var $this = $(this.get(0));
                var isTinyMce = false;

                if (settings.tinyMceEditors.length > 0) {
                    $(settings.tinyMceEditors).each(function() {
                        if ($this.attr("id") == $(this).attr("id")) {
                            isTinyMce = true;
                            return;
                        }
                    });
                }

                if (isTinyMce) {
                    var editor = tinyMCE.get($(this).attr("id"));
                    if (typeof editor != "undefined") {
                        return editor.getContent();
                    }
                }

                if ($this.is(":radio, :checkbox")) {
                    value = $this.attr("checked");
                } else if ($this.is(":input")) {
                    value = $this.val();
                }
                return value;
            };

            if (typeof(parameter) == "string") {
                result = this;
                switch(parameter) {
                    case "modified":
                        result = this.modified(options);
                    break;
                    case "save":
                        result = this.save(options);
                    break;
                    case "value":
                        result = this.value(options);
                    break;
                }
                return result;
            }

            return this.each(function() {
                self.init(this, parameter);
            });
        }
    });
})(jQuery);

$(function() {
    $("form.form_changes").formChanges();
});

