/**
 * InfiniteCMS
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @package    InfiniteCMS
 * @copyright  Copyright (c) 2003-2010 Infinite Networks Pty Ltd (http://www.infinite.net.au)
 * @version    $Id: common.js 138 2010-03-11 03:23:25Z jmclean $
**/

(function($) {
	$.extend({
		disableTextSelection: function() {
			$(document.documentElement).bind("drag selectstart", function() { return false; });
			$(document.body).addClass("no-select");
		},
		enableTextSelection: function() {
			$(document.documentElement).unbind("drag selectstart");
			$(document.body).removeClass("no-select");
		},
		esc: function(s) { return $("<div />").text(s).html(); }
	});
	$.fn.extend({
		any: function(p) {
			for (var i = 0; i < this.length; ++i)
				if (p.call(this[i])) return true;
			return false;
		},
		contains: function(node) {
			return this.any(function() { return this == node; });
		},
		calendar: function() {
			return this.each(function() {
				var dateField = $(this);

				// Create calendar object and bind to a "trigger" icon
				var cal = new Calendar(1, null, function(cal, date) { dateField.val(date); if (cal.dateClicked) { cal.hide(); dateField.click(); } }, function(cal) { cal.hide(); });
				cal.create()
				$(cal.element).bind("click mousedown", function(e) { e.stopPropagation(); }); // Prevent calendar events from escaping
				cal.setDateFormat("%e/%m/%Y");
				cal.yearStep = 1;
				var trigger = $("<a href='#'><img src='/images/calendar-icon.png' /></a>");
				trigger.click(function() {
					cal.parseDate(dateField.val());
					cal.showAtElement(trigger[0], "CR");
					return false;
				});
				dateField.after(trigger).after($("<span>&nbsp;</span>"));
			});
			return this;
		},
		backgroundSubmit: function(callback) {
			// Submit the selected form or forms to a hidden iframe
			return this.each(function() {
				if (this.nodeName != "FORM") throw "Can't backgroundSubmit() something that isn't a form";
				var form = $(this);

				var submitValues = {};

				function doneLoading() {
					if (this.contentWindow.location.href != "about:blank") {
						var successful = true;
						if (this.contentWindow.formErrors)
						{
							// Form submission has validation errors
							form.showErrors(this.contentWindow.formErrors);
							successful = false;

							// Let the page redraw before showing the dialog
							setTimeout(function() { alert("There were some problems with your submission. Please see above for details."); }, 0);
						}

						if (callback) callback.call(form[0], successful, this.contentWindow, submitValues);

						// If the iframe is removed now, Firefox gets stuck showing a loading icon in the tab bar; use a timeout to prevent that
						var iframe = $(this);
						setTimeout(function() { iframe.remove(); }, 0);
					}
				}

				// Make a second form in order to submit without triggering events in Chrome
				var frameName = "bgsubmit_" + (""+Math.random()).substr(2);
				var hiddenFrame = $("<iframe style='display:none' src='about:blank' name='" + $.esc(frameName) + "'></iframe>").load(doneLoading).appendTo($(document.body));
				var surrogateForm = $("<form />").attr({
					action: form.attr("action"),
					method: "post",
					target: frameName,
					enctype: form.attr("enctype")
				}).hide().appendTo(document.body);

				// Copy form values
				$(form.serializeArray()).each(function () {
					surrogateForm.append('<input type=hidden name="'+$.esc(this.name)+'" value="'+$.esc(this.value)+'" />');
					submitValues[this.name] = this.value;
				});

				// Can't copy file fields in IE. *Move* the file fields, submit and move them back.
				var files = [];
				form.find("input[type=file]").each(function() {
					files.push({el: this, parent: this.parentNode, before: this.nextSibling});
					surrogateForm.append(this);
				});

				surrogateForm.submit();
				surrogateForm.remove();

				surrogateForm.find("input[type=file]").remove();
				for (var i = files.length - 1; i >= 0; i--) files[i].parent.insertBefore(files[i].el, files[i].before);
			});
		},
		registerBackgroundSubmit: function(options) {
			return this.submit(function(e) {
				var form = $(this);
				e.preventDefault();
				if (options.flag) var flagField = $("<input type='hidden' value='1' name=\""+$.esc(options.flag)+"\" />").appendTo(form);
				if (options.loader) var loader = $("<span>&nbsp;</span><img src='" + $.esc(options.loader) + "' />").insertAfter(form.find("input[type=submit]").eq(0));
				form.backgroundSubmit(function(successful, contentWindow, vals) {
					if (options.loader) loader.remove();
					if (options.callback) options.callback.call(this, successful, contentWindow, vals);
				});
				if (options.flag) flagField.remove();
			});
		},
		showErrors: function(errors) {
			this.find(".error").hide();
			for (var k in errors) {
				var v = errors[k];
				var node = this.find(".error.error-"+k).show().find(".error-text").text(v);
			}
			return this;
		},
		dragdrop: function() {
			return this.each(function() {
				var list = $(this);
				list.mousedown(function(e) {
					if (e.target.nodeName != "IMG") return;
					var li = $(e.target).closest("li");

					// dragItem is the "floating" image that appears to be dragged around. It's actually a
					// copy of the real image, which is still in place, but hidden. I apply 15% transparency
					// to dragItem by calling fadeTo() rather than using the "opacity" CSS property.
					var dragItem = li.find("img").clone().css({position: "absolute"}).fadeTo(0, 0.85).appendTo("body");

					// Once the drag item is created, Opera triggers an additional mousedown event on it. This causes
					// Opera's built-in image-dragging logic to kick in, unless I call preventDefault() on that event too.
					dragItem.mousedown(function(e) { e.preventDefault(); });

					function reposition(e) {
						// Determine where the top-left corner of dragItem should go.
						var w = dragItem.width(), h = dragItem.height();
						var x = e.pageX - Math.floor(dragItem.width()) / 2, y = e.pageY - Math.floor(dragItem.height()) / 2;

						// Clamp to the list's rectangle
						var listPos = list.offset(), listW = list.width(), listH = list.height();
						x = Math.max(Math.min(x, listPos.left + listW - w), listPos.left);
						y = Math.max(Math.min(y, listPos.top  + listH - h), listPos.top );

						// Reposition the drag item while working around an IE 8 bug
						/*@cc_on if (@_jscript_version == 5.8) { dragItem.hide(); } @*/
						dragItem.css({left: x + "px", top: y + "px"});
						/*@cc_on if (@_jscript_version == 5.8) { dragItem.show(); } @*/

						// Move the hidden LI to a new position.
						// Because of borders, padding and margins, the mouse not be within an LI element.
						// Instead, locate the LI whose center is closest under the 2-norm.
						var closest = null, bestDist = 9999999;
						list.children().each(function() {
							var cur = $(this);
							var curPos = cur.offset();
							var thisDist = Math.pow(curPos.left + cur.width() / 2 - e.pageX, 2) + Math.pow(curPos.top + cur.height() / 2 - e.pageY, 2);
							if (thisDist < bestDist) { bestDist = thisDist; closest = cur; }
						});
						if (closest[0] != li[0]) {
							if (li.nextAll().contains(closest[0]))
								li.insertAfter(closest);  // If moving forwards, insert *after*
							else
								li.insertBefore(closest); // If moving backwards, insert *before*
						}
					}
					reposition(e);
					li.fadeTo(0, 0);
					$.disableTextSelection();
					$(document.documentElement).mousemove(function(e) {
						reposition(e);
						e.preventDefault();
					});
					$(document.documentElement).mouseup(function(e) {
						var targetPos = li.find("img").offset();
						dragItem.animate({left: targetPos.left + "px", top: targetPos.top + "px"}, {duration: 150, complete: function() { li.fadeTo(150, 1, function() { dragItem.remove(); }); }});
						$(document.documentElement).unbind("mousemove mouseup");
						$.enableTextSelection();
					});

					e.preventDefault(); // Prevent default image-dragging behaviour in some browsers
				});
			});
		},
		selectOther: function() {
			function adjustVisibility() {
				if (this.value == "")
					$(this).next().addClass("js_visible").removeClass("js_hidden");
				else
					$(this).next().addClass("js_hidden").removeClass("js_visible");
			}
			return this.each(adjustVisibility).bind("click change keydown", adjustVisibility);
		},
		// Enqueue a jquery method call in the animation queue.
		// Example: $(elem).animate({backgroundColor: "blue"}, 500).then("css", {backgroundColor: "transparent"});
		then: function(name) {
			var args = Array.slice(arguments, 1);
			this.queue(function() {
				var that = $(this);
				that[name].apply(that, args);
				that.dequeue();
			});
		}
	});
	$(function() {
		$("input.date").calendar();
		$("select.other").selectOther();
		/* $('a[href^="#"]').live("click", function(e) {
			e.preventDefault();
			var href = $(this).attr("href");
			if (href != "#") {
				var dest = $($(this).attr("href"));
				if (dest) {
					$('html, body').animate({scrollTop: dest.offset().top}, 500);
				}
			}
		}); */
	});
})(jQuery);

if (window.opera) { document.write('<style type=text/css>.am-image, .am-image-spacer, .article .odd { padding-top: 0; }<\/style>'); }

