/* ocms-extensions.js */

(function ($) {
	//helper function for adding methods
	Function.prototype.method = function (name, func) {
		if (!this.prototype[name]) {
			this.prototype[name]= func;
			return this;
		}
	}
	
	// properly rounds both +ve and -ve numbers
	Number.method('integer', function () {
		return Math[this < 0 ? 'ceil' : 'floor'](this);
	});
	
	/*? wait: already present in Orchestra JavaScript Library 1.0.0 */
	String.method('trim', function () {
		return this.replace(/^\s+|\s+$/g, '');
	});
	/*?*/
	
	// based on source in Crockford's JavaScript: The Good Parts
	// template string fill-er in-ner
	String.method('supplant', function (o) { 
		return this.replace(/{([^{}]*)}/g, 
			function (m, k) {
				var r = o[k];
				return typeof r === 'string' ? r : m;
			}
		);
	});
	
	
	// extend jQuery
	// - call these when fading element has alpha transparency
	// - reverts to show/hide for IE < 9
	
	$.fn.fadIn = function (dur) {
		return this.each(function () {
			if ($.browser.msie && $.browser.version < 9) {
				$(this).show();
			} else {
				$(this).fadeIn(dur || null);
			}
		});
	};
	
	$.fn.fadOut = function (dur) {
		return this.each(function () {
			if ($.browser.msie && $.browser.version < 9) {
				$(this).hide();
			} else {
				$(this).fadeOut(dur || null);
			}
		});
	};	
		
	$.fn.hintText = function (txt, className) {
		className = className || "hintText";
		
		return this.each(function () {
			function toFocus () {
				if (this.value === txt) {
					this.value = "";
					$(this).removeClass(className);
				}
			}
	
			function toBlur () {
				if (this.value.length === 0) {
					this.value = txt;
					$(this).addClass(className);
				}
			}
	
			this.value = txt;
			$(this)
				.addClass(className)
				.focus(toFocus)
				.blur(toBlur);
		});
	};



	if (typeof OCMS === "undefined") {
		/* OCMS becomes a global var */
		OCMS = {};
	}	
	
	
	OCMS.addAuthorClasses = function () {
		OCMS.inPageEditor = window.location.href.indexOf("/apex/Edit?") > 0;
		OCMS.inPagePreview = window.location.href.indexOf("/apex/Preview?") > 0;

		if (OCMS.inPageEditor) {
			$("body").addClass("OCMS-Edit");
		} else {
			if (OCMS.inPagePreview) {
				$("body").addClass("OCMS-Preview");
			}
		}
	};
	
	// OCMS.addBrowserClasses
	//
	// - add browser-identifying class name when requested
	// - will NOT add browser-specific class unless browser in question is requested or {all: true}
	// - most frequently we only care about the travesty that is IE7
	// - use IE conditional comments instead of this JavaScript-based solution when possible
	// - for more detailed browser/version sniffing, do it yourself, use $.support,
	//	 but most importantly reconsider the need to know!
	// - examples:
	//		- OCMS.addBrowserClasses()
	//				if IE7 => body.IE7
	//		- OCMS.addBrowserClasses({selector: "div.pg", all: true})		
	//				if Safari, Chrome, OmniWeb, etc. => div.pg.WEBKIT
	//		- OCMS.addBrowserClasses({mozilla: true, opera: true})
	//				if Safari or IE8 => no change
	OCMS.addBrowserClasses = function (args) {
		var	settings = {
				selector: "body",
				ie: false,
				ie7: true,		// typically, this is the most dangerous browser to look out for
				ie8: false,
				webkit: false,
				mozilla: false,
				opera: false,
				all: false		// show all we detect, even if not specifically asked
			},
			classList = "";
			
		$.extend(settings, args);
		
		if ((settings.ie || settings.ie7 || settings.ie8 || settings.all) && $.browser.msie) {
			if (settings.ie || settings.all) {
				classList = "IE";
			}
			if (settings.ie7 && parseInt($.browser.version) === 7) {
				classList += " IE7";
			} else if (settings.ie8 && parseInt($.browser.version) === 8) {
				classList += " IE8";
			}
		} else if ((settings.webkit || settings.all) && $.browser.webkit) {
			classList = "WEBKIT";
		} else if ((settings.mozilla || settings.all) && $.browser.mozilla) {
			classList = "MOZILLA";
		} else if ((settings.opera || settings.all) && $.browser.opera) {
			classList = "OPERA";
		}
	
		if (classList !== "") {
			$(settings.selector).addClass(classList);
		}
	};
	
	(function () {
		if (OCMS.boundsChecker === undefined) {
			OCMS.boundsChecker = function ($args) {
				var bounds = [];

				function _init () {
					function tlbr (el) {
						var $this = $(el);
						
						// if object isn't currently visible, set nulls but include object
						// in order to build tlbr co-ordinates later when asked about a point
						if ($this.is(":visible")) {
							return {
								t: $this.offset().top,
								l: $this.offset().left,
								b: $this.offset().top + $this.height(),
								r: $this.offset().left + $this.width()
							}
						} else {
							return {
								t: null,
								l: null,
								b: null,
								r: null,
								$that: $this
							}
						}
					}

					for (var i = 0; i < $args.size(); ++i) {
						var reck = tlbr($args.eq(i));
						bounds.push(reck);
					}
					
//					dump();
				}

				function isInside (pt) {
					// pt must have pageX and pageY properties, as found in an event object
					var r,
						bInside = false,
						rect;
						
					for (r = 0; !bInside && r < bounds.length; ++r) {
						rect = bounds[r];
						
						if (rect.t !== null) {
							bInside = 	pt.pageX >= rect.l &&
										pt.pageX <= rect.r &&
										pt.pageY >= rect.t &&
										pt.pageY <= rect.b;
						} else {
							if (rect.$that.is(":visible")) {
								rect.t = rect.$that.offset().top;
								rect.l = rect.$that.offset().left;
								rect.b = rect.$that.offset().top + rect.$that.height();
								rect.r = rect.$that.offset().left + rect.$that.width();
									
								bInside = 	pt.pageX >= rect.l &&
											pt.pageX <= rect.r &&
											pt.pageY >= rect.t &&
											pt.pageY <= rect.b;
								dump();
							}
						}
					}
					
/*
					if (bInside) {
						window.status += "(" + pt.pageX + " o " + pt.pageY + ") ";
					} else {
						window.status += "(" + pt.pageX + " x " + pt.pageY + ") ";
					}
*/
					return bInside;
				}
		
				function isOutside (args) {
					return !isInside(args);
				}
		
				function dump () {
					var r;
					for (r = 0; r < bounds.length; ++r) {
						window.status += 	"{" + bounds[r].l + "->" + bounds[r].r +
											"|" + bounds[r].t + "vv" + bounds[r].b + "} ";
					}
				}
				
				_init();
				
				return {
						isInside: isInside,
						isOutside: isOutside
				}
			}
		}
	})();
		
})(jQuery);

