(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 ($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);
					});
				}

				function onBeforeUnload(event) {
					var changed = false;
					inputs.each(function() {
						if ($(this).formChanges("modified", settings)) {
							changed = true;
							return;
						}

					});
					if (changed) {
						event = event || window.event;
						event.returnValue = settings.message;
					}
				}

				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();
});
