Monitus UI Library

util  4

Monitus UI Library > util > mui_core.js (source view)
Search:
 
Filters
/*!
 * MUI - Monitus UserInterface Javascript Library
 * Copyright (c) 2011-2012 Monitus, LLC - www.monitus.com
 */

/**
 * The util module provides generic utilities for manipulating the DOM, or other general functionalities.
 * 
 * @module util
 * @title util
 * @namespace MUI
 */

if(typeof(MUI) == "undefined") {
	var MUI = {
		_version: 6,
		_objectQueue: {}
	};
	var JSON = JSON || {};
	JSON.stringify = JSON.stringify || function (obj) {
		var t = typeof (obj);
		if (t != "object" || obj === null) {
			// simple data type
			if (t == "string") obj = '"'+obj+'"';
			return String(obj);
		}
		else {
			// recurse array or object
			var n, v, json = [], arr = (obj && obj.constructor == Array);
			for (n in obj) {
				v = obj[n]; t = typeof(v);
				if (t == "string") v = '"'+v+'"';
				else if (t == "object" && v !== null) v = JSON.stringify(v);
				json.push((arr ? "" : '"' + n + '":') + String(v));
			}
			return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
		}
	};
	JSON.parse = JSON.parse || function (str) {
		if (str === "") str = '""';
		eval("var p=" + str + ";");
		return p;
	};
}
if(typeof(MUI.internal) == "undefined") {
	MUI.internal = {
		_test_object: function(pObjectName) {
			try {
				eval("var vObject = window." + pObjectName + ";");
				return vObject;
			} catch(e) {
				return null;
			}
		},
		_wait_object: function(pObjectName) {
			var vInfo = MUI._objectQueue[pObjectName];
if(!window.MDEBUG)window.MDEBUG="";
window.MDEBUG+="[wait["+pObjectName;
if(vInfo) window.MDEBUG+=","+vInfo+","+vInfo.callbacks.length;
window.MDEBUG+="]";
			if(vInfo) {
				var vObject = MUI.internal._test_object(pObjectName);
				if(!vObject) setTimeout("MUI.internal._wait_object('" + pObjectName + "');", 10);
				else {
					delete MUI._objectQueue[pObjectName];
					for(var vLoop = 0; vLoop < vInfo.callbacks.length; vLoop++) MUI.util.dom.wait_object(pObjectName, vInfo.callbacks[vLoop], vInfo.args[vLoop]);
				}
			}
		}
	};
}
if(typeof(MUI.util) == "undefined") {
	/**
	 * These utilities provide generic utilities for manipulating the DOM, or other general functionalities.
	 *
	 * @class util
	 * @namespace MUI
	 * @static
	 */
	MUI.util = {
		kdom_is_ready: false,
		
		/**
		 * Position Top Left.
		 *
		 * @property ktop_left
		 * @type String
		 * @final
		 * @default "tl"
		 */
		ktop_left : "tl",
		/**
		 * Position Top Center.
		 *
		 * @property ktop_center
		 * @type String
		 * @final
		 * @default "tc"
		 */
		ktop_center : "tc",
		/**
		 * Position Top Right.
		 *
		 * @property ktop_right
		 * @type String
		 * @final
		 * @default "tr"
		 */
		ktop_right : "tr",
		/**
		 * Position Bottom Left.
		 *
		 * @property kbottom_left
		 * @type String
		 * @final
		 * @default "bl"
		 */
		kbottom_left : "bl",
		/**
		 * Position Bottom Center.
		 *
		 * @property kbottom_center
		 * @type String
		 * @final
		 * @default "bc"
		 */
		kbottom_center : "bc",
		/**
		 * Position Bottom Right.
		 *
		 * @property kbottom_right
		 * @type String
		 * @final
		 * @default "br"
		 */
		kbottom_right : "br",
		
		/**
		 * Find an item in an Array by value.
		 *
		 * @method indexOfInArray
		 *
		 * @param {anything} pNeedle the object to look for in pHaystack.
		 * @param {array} pHaystack the array to look in.
		 * @param {integer} pFrom thje index at which to start the search. Optional; defaults to 0.
		 *
		 * @return {integer} the index of the object in the array OR -1 if not found.
		 *
		 * @static
		 */
		indexOfInArray: function(pNeedle, pHaystack, pFrom) {
			if(Array.prototype.indexOf) {
				if(typeof(pFrom) == "undefined") return pHaystack.indexOf(pNeedle);
				return pHaystack.indexOf(pNeedle, pFrom);
			}
			var vLength = pHaystack.length;
			var vFrom = Number(arguments[2]) || 0;
			vFrom = (vFrom < 0) ? Math.ceil(vFrom) : Math.floor(vFrom);
			if(vFrom < 0) vFrom += vLength;
			for(; vFrom < vLength; vFrom++) {
				if((vFrom in pHaystack) && (pHaystack[vFrom] === pNeedle)) return vFrom;
			}
			return -1;
		},
		/**
		 * Find out if the currently viewed page is a landing page.
		 * 
		 * <p>A page is considered a landing page if it is not on the same domain as the referrer.</p>
		 *
		 * @method is_landing_page
		 *
		 * @param {array} pIgnoreDomains a list of domains to ignore; domains in this list will, for all intents and purposes, be considered the same domain as the current domain.
		 *
		 * @return {boolean} is the currently viewed page a landing page?
		 *
		 * @static
		 */
		is_landing_page: function(pIgnoreDomains) {
			var vReferringDomain = document.referrer.match(/https?\:\/\/([^/]+)/i);
			if(!vReferringDomain) return true;
			vReferringDomain = vReferringDomain[1];
			for(var vLoop=0; vLoop < pIgnoreDomains.length; vLoop++) {
				if(vReferringDomain.indexOf(pIgnoreDomains[vLoop]) >= 0) return false;
			}
			return true;
		},
		report_error: function(pErrorID, pMessage) {
			var vBeacon = new Image(1,1);
			vBeacon.src = document.location.protocol + "//www.monitus.net/bin/1519330469/merr.php?e=" + encodeURIComponent(pErrorID) + "&u=" + encodeURIComponent(document.location) + "&m=" + encodeURIComponent(pMessage);
		},
		/**
		 * Get a particular parameter from a URL string.
		 * 
		 * @method url_parameter
		 *
		 * @param {string} pURL URL string to anlayze.
		 * @param {string} pParameterName the name of the parameter to extract.
		 * @param {string} pDefault default value, if the parameter value is not found.
		 *
		 * @return {string} the value of the URL parameter, or the default value if the not found.
		 *
		 * @static
		 */
		url_parameter: function(pURL, pParameterName, pDefault) {
			if(!pURL) return pDefault;
			
			var pURL = pURL.split('#')[0];
			var vTokens = pURL.split('?');
			if(vTokens.length <= 1) return pDefault;
			pURL = decodeURI(vTokens[1]);
			
			pParameterName += '=';
			var vParameters = pURL.split('&');
			for(var vLoop = 0, vParameter; vParameter = vParameters[vLoop]; ++vLoop) {
				if(vParameter.indexOf(pParameterName) === 0) return unescape(vParameter.split('=')[1]);
			}
			return pDefault;
		},
		/**
		 * Get the value of a cookie.
		 * 
		 * @method cookie_value
		 *
		 * @param {string} pName name of the cookie to get.
		 * @param {string} pDefault default value, if the cookie value is not found.
		 *
		 * @return {string} the value of the cookie, or the default value if the cookie does not yet exists.
		 *
		 * @static
		 */
		cookie_value: function(pName, pDefault) {
			var vCookies = document.cookie;
			if((vCookies=="") || !pName || (pName=="")) return pDefault;
			
			var vPrefix = pName + "=";
			var vStart = ('' + vCookies).indexOf(vPrefix);
			var vIndex = ('' + vPrefix).indexOf("=")+1;
			if(vStart>=0) {
				var vEnd = ('' + vCookies).indexOf(";", vStart);
				if(vEnd<0) vEnd = ('' + vCookies).length;
				pDefault = ('' + vCookies).substring((vStart+vIndex), vEnd);
			}
			return pDefault;
		},
		/**
		 * Set the value of a cookie, or delete it completely.
		 * 
		 * @method set_cookie_value
		 *
		 * @param {string} pName name of the cookie to set.
		 * @param {string|number} pHours how long should ht ecookie be vlaid for? &quot;-&quot; is forever; &quot;.&quot; is no expiry date; &quot;x&quot; deletes the cookie; a number is hte number of hours the cookie is good for
		 * @param {string} pPath path to set the cookie on.
		 * @param {string} pDomain domain to set the cookie on.
		 * @param {string} pValue value of the cookie to set.
		 *
		 * @static
		 */
		set_cookie_value: function(pName, pHours, pPath, pDomain, pValue) {
			if(pHours == "-") pHours = 43800; // "forever"
			var vExpiry = "";
			if(pHours == "x") {
				vExpiry = " expires=Fri, 02-Jan-1970 00:00:00 GMT;";
			} else if(pHours != ".") {
				vExpiry = new Date((new Date()).getTime() + (pHours * 3600000));
				vExpiry = " expires=" + vExpiry.toGMTString() + ";";
			}
			document.cookie = pName + "=" + pValue + ";" + vExpiry + " path=" + pPath + "; domain=" + pDomain;
		}
	};
	
	/**
	 * These utilities provide generic math utilities.
	 *
	 * @class math
	 * @namespace MUI.util
	 * @static
	 */
	MUI.util.math = {
		/**
		 * Integer division of two numbers.
		 * 
		 * @method int_div
		 *
		 * @param {number} pNumerator
		 * @param {number} pDenominator
		 *
		 * @return {number} result of dividing pNumerator by pDenimoinator (integer).
		 *
		 * @static
		 */
		int_div: function(pNumerator, pDenominator) {
			var vRemainder = pNumerator % pDenominator;
			return ((pNumerator - vRemainder) / pDenominator);
		}
	};
	
	/**
	 * These utilities provide generic utilities for manipulating the DOM.
	 *
	 * @class dom
	 * @namespace MUI.util
	 * @static
	 */
	MUI.util.dom = {
		/**
		 * Execute code when the DOM is ready to be manipulated; this is usually 
		 * faster than waiting for the onload event.
		 *
		 * @method ready
		 *
		 * @param {function} pCallback what to execute when the DOM is ready.
		 *
		 * @static
		 */
		ready: function(pCallback) {
			if(MUI.util.kdom_is_ready) {
				pCallback();
				return;
			}
			if(document.readyState === "complete") {
				pCallback();
				return;
			}
			
			if(document.attachEvent) {
				document.attachEvent("onreadystatechange", function() { 
					if(document.readyState === "complete") {
						document.detachEvent("onreadystatechange", arguments.callee);
						pCallback();
					}
				});
				window.attachEvent("onload", pCallback);
				if(document.documentElement.doScroll && window == window.top)
					(function() { 
							try {
								document.documentElement.doScroll("left"); 
							} catch(error) {
								setTimeout(arguments.callee, 0); 
								return;
							}
							pCallback();
					})();
				return;
			} else {
				if(document.addEventListener) {
					document.addEventListener('DOMContentLoaded', pCallback, false);
					window.addEventListener("load", pCallback, false);
					return;
				}
				if(/KHTML|WebKit|iCab/i.test(navigator.userAgent)) {
					var vTimer = setInterval(function () {
						if (/loaded|complete/i.test(document.readyState)) {
							pCallback();
							clearInterval(vTimer);
						}
					}, 10);
					return;
				}
				window.onload = pCallback;
			}
		},
		/**
		 * Add an event listener to an object.
		 *
		 * @method add_event
		 *
		 * @param {object} pElement the element to listen to.
		 * @param {string} pEventType the event to listen for. Ex: "load", "click", ...
		 * @param {function} pFunction the function to execute when the event fires
		 * @param {boolean} pUseCapture parameter of the same name in the DOM addEventListener function.
		 *
		 * @static
		 */
		add_event: function(pElement, pEventType, pFunction, pUseCapture) {
			if(pElement.addEventListener) { 
				pElement.addEventListener(pEventType, pFunction, pUseCapture); 
				return true;
			} else if(pElement.attachEvent) { 
				var vResult = pElement.attachEvent('on' + pEventType, pFunction); 
				return vResult; 
			} else {
				pElement['on' + pEventType] = pFunction;
			}
		},
		/**
		 * Wait for a javascript object instance to be created in the window.
		 *
		 * @method wait_object
		 *
		 * @param {string} pObjectName the name of the intance to wait for; basicalyl, the name of the variable.
		 * @param {function} pCallBack the code to run when the instance is created.
		 * @param {array} pArguments an array of arguments passed to the callback function.
		 *
		 * @static
		 */
		wait_object: function(pObjectName, pCallBack, pArguments) {
			var vObject = MUI.internal._test_object(pObjectName);
			if(vObject) {
				pArguments.unshift(vObject);
				pCallBack.apply(this, pArguments);
			} else {
				var vInfo = MUI._objectQueue[pObjectName];
				if(!vInfo) {
					vInfo = {callbacks: [], args: []};
					MUI._objectQueue[pObjectName] = vInfo;
				}
				vInfo.callbacks.push(pCallBack);
				vInfo.args.push(pArguments);
				setTimeout("MUI.internal._wait_object('" + pObjectName + "');", 10);
			}
		},
		/**
		 * Rename an element, by adding a suffix, and its dependants, if applicable.
		 * For instance, some form filed might have labels associated with them; this function
		 * will also adjust the "for" attribute of the label.
		 *
		 * @method rename_element
		 *
		 * @param {object} pElement the element to rename.
		 * @param {string} pSuffix the suffix to add to the object's name.
		 * @param {boolean} pDeep also rename all the object's children?
		 *
		 * @static
		 */
		rename_element: function(pElement, pSuffix, pDeep) {
			if(!pElement || !pSuffix) return;
			
			if(pElement.getAttribute) {
				if(pElement.getAttribute("name")) pElement.setAttribute("name", pElement.getAttribute("name") + pSuffix);
				if(pElement.getAttribute("id")) pElement.setAttribute("id", pElement.getAttribute("id") + pSuffix);
				if(pElement.getAttribute("for")) pElement.setAttribute("for", pElement.getAttribute("for") + pSuffix);
			} else {
				if(pElement.name) pElement.name += pSuffix;
				if(pElement.id) pElement.id += pSuffix;
			}
			
			if(pDeep) {
				for(var vLoop = 0; vLoop < pElement.childNodes.length; vLoop++) {
					MUI.util.dom.rename_element(pElement.childNodes[vLoop], pSuffix, pDeep);
				}
			}
		},
		/**
		 * Get a list of objects on the page.
		 * 
		 * <p><strong>Selectors: </strong> supported selectors are:
		 * <ul>
		 * <li><strong>.myClass: </strong> will return all objects whose class contains &quot;myClass&quot;; it's a shortcut for {class=myClass}</li>
		 * <li><strong>.myClass[indices]: </strong> will return, from the list of all objects whose class contains &quot;myClass&quot;, the item(s) at indices &quot;indices&quot; (ex: [1,2])</li>
		 * <li><strong>{anAttribute=aValue}: </strong> will return all objects whose attribute &quot;anAttribute&quot; is equal to &quot;aValue&quot;; the value can be a string, or a RegExp-like string: ##<regex expression##<modifiers>.</li>
		 * <li><strong>{anAttribute=aValue}[indices]: </strong> will return, from the list of all objects whose attribute &quot;anAttribute&quot; is equal to &quot;aValue&quot;, the item(s) at indices &quot;indices&quot; (ex: [1,2])</li>
		 * <li><strong>anythingElse: </strong> will return all objects whose id is equal to &quot;&anythingElsequot;</li>
		 * </ul>
		 * </p>
		 *
		 * @method get_objects
		 *
		 * @param {string} pTag the tag to look for. Ex: &quot;img&quot;, &quot;input&quot;, etc...
		 * @param {string} pSelector the selector; see note above.
		 * @param {object} pRoot the object to look into. Optional; defaults to the whole document.
		 *
		 * @return {array} list of found objects; empty array if none found.
		 *
		 * @static
		 */
		get_objects: function(pTag, pSelector, pRoot) {
			var vObjects = [];
			if(!pRoot) pRoot = document;
			if(!pSelector.match(/^\.|\{/)) return [pRoot.getElementById(pSelector)];
			var vAttribute = vValue = null;
			var vIndices = null;
			var vTokens = pSelector.match(/^(.+?)\[([\d,]+)\]$/);
			if(vTokens) {
				pSelector = vTokens[1];
				vIndices = vTokens[2].split(",");
			}
			if(pSelector.match(/^\./)) {
				vAttribute = (navigator.userAgent.match(/msie/i) ? "className" : "class");
				vValue = new RegExp("(^|\s)" + pSelector.substr(1) + "(\s|$)", "i");
			} else {
				vTokens = pSelector.match(/\{([^\=\s]+?)\s*?\=\s*([^\}]*?)\}/);
				if(vTokens) {
					vAttribute = vTokens[1];
					vValue = vTokens[2];
					vTokens = vValue.match(/^##(.+)\##(.*?)$/);
					if(vTokens) vValue = new RegExp(vTokens[1], vTokens[2]);
				}
			}
			if(vAttribute) {
				var vElements = pRoot.getElementsByTagName(pTag);
				for(var vLoop = 0; vLoop < vElements.length; vLoop++) {
					if(typeof(vValue) == "string") {
						if(vElements[vLoop].getAttribute(vAttribute) == vValue) vObjects.push(vElements[vLoop]);
					} else {
						if(vValue.test(vElements[vLoop].getAttribute(vAttribute))) vObjects.push(vElements[vLoop]);
					}
				}
			}
			if(vIndices) {
				var vTargets = [];
				for(var vLoop = 0; vLoop < vIndices.length; vLoop++) {
					var vIndex = parseInt(vIndices[vLoop]);
					if((vIndex >= 0) && (vIndex < vObjects.length)) vTargets.push(vObjects[vIndex]);
				}
				return vTargets;
			}
			return vObjects;
		},
		/**
		 * Get a the first object on the page, that matches the selector.
		 * 
		 * <p><strong>Selectors: </strong> see MUI.util.dom.get_objects</p>
		 *
		 * @method get_object
		 *
		 * @param {string} pTag the tag to look for. Ex: &quot;img&quot;, &quot;input&quot;, etc...
		 * @param {string} pSelector the selector; see note above.
		 * @param {object} pRoot the object to look into. Optional; defaults to the whole document.
		 *
		 * @return {object} the first object found, or null if none found.
		 *
		 * @static
		 */
		get_object: function(pTag, pSelector, pRoot) {
			var vObjects = MUI.util.dom.get_objects(pTag, pSelector, pRoot);
			return (vObjects && (vObjects.length > 0) ? vObjects[0] : null);
		},
		object_by_name_attribute: function(pTag, pName, pRoot) {
			return MUI.util.dom.get_object(pTag, "{name=" + pName + "}", pRoot);
		}
	};
	
	/**
	 * These utilities provide generic utilities for manipulating strings.
	 *
	 * @class string
	 * @namespace MUI.util
	 * @static
	 */
	MUI.util.string = {
		/**
		 * Easy way to standardize strings; this function will return a default value if the input string is null.
		 *
		 * @method non_null_string
		 *
		 * @param {string} pString the string to test - or null.
		 * @param {string} pDefault the default value to return, if the input string is, indeed, null.
		 *
		 * @return {string} the input string if not null, or else the default value.
		 *
		 * @static
		 */
		non_null_string: function(pString, pDefault) {
			if(!pDefault) pDefault = "";
			return (pString ? pString : pDefault);
		},
		/**
		 * Inflate current form values into a template string. 
		 * You insert special tokens in the template string, and they will be replaced by the equivalent form field value.
		 * 
		 * <p>Tokens are delimited by the percentage character (&quot;%&quot;), as such:<br /><br />
		 * <code>The name field value is: %name%</code><br /><br />
		 * In this case, the token &quot;%name%&quot; will be replaced by the value in the form field whoseid is &quot;name&quot;
		 * </p>
		 *
		 * @method form_inflate
		 *
		 * @param {string} pTemplate the string to inflate.
		 *
		 * @return {string} the template string, with all tokens inflated.
		 *
		 * @static
		 */
		form_inflate: function(pTemplate) {
			if(pTemplate) {
				do {
					var vTokens = ("" + pTemplate).match(/%([^%]+)%/);
					if(vTokens) {
						var vObject = document.getElementById(vTokens[1]);
						var vValue = "";
						try { vValue = vObject.value } catch(e) { }
						var vRE = new RegExp(vTokens[0], "g");
						pTemplate = pTemplate.replace(vRE, vValue);
					}
				} while(pTemplate && vTokens);
			}
			return pTemplate;
		}
	}
	
	/**
	 * These utilities provide ui elments.
	 *
	 * @class ui
	 * @namespace MUI.util
	 * @static
	 */
	MUI.util.ui = {
		/**
		 * Create a pop-up div; these pop-ups are not blocked by pop-up blockers, as they are not in a separate window.
		 * 
		 * @method create_pop_up
		 *
		 * @param {string} pText title of the button to show the pop-up.
		 * @param {url} pImage url of the image used on the button. Optional.
		 * @param {string} pPlaceholderID id of the element into which the button shoudl be placed.
		 * @param {string} pPopUpID id of the div to show as the pop-up content. If the div does not exist, one will be created.
		 * @param {function} pPopUpFc function to be called when the button is clicked.
		 *
		 * @return {button} a reference to the created button; the button will have a &quot;popup&quot; property, for quick access to the popup div.
		 *
		 * @static
		 */
		create_pop_up: function(pText, pImage, pPlaceholderID, pPopUpID, pPopUpFc) {
			var vButton = null;
			try {
				var vPlaceholder = document.getElementById(pPlaceholderID);
				if(vPlaceholder) {
					var vPopUp = document.getElementById(pPopUpID);
					if(!vPopUp) {
						vPopUp = document.createElement("div");
						vPopUp.id = pPopUpID;
						document.getElementsByTagName("body")[0].appendChild(vPopUp);
					}
					vPopUp.style.display = "none";
					
					vButton = document.createElement("a");
					vButton.popup = vPopUp;
					vButton.href = "#";
					vButton.title = pText;
					vButton.style.border = "none";
					if(pImage) {
						var vImage = document.createElement("img");
						vImage.src = pImage;
						vImage.style.border = "none";
						vButton.appendChild(vImage);
					} else vButton.appendChild(document.createTextNode(pText));
					MUI.util.dom.add_event(vButton, "click", pPopUpFc, true);
					
					if(vPlaceholder.nextSibling) vPlaceholder.parentNode.insertBefore(vButton, vPlaceholder.nextSibling);
					else vPlaceholder.parentNode.appendChild(vButton);
				}
			} catch(e) { }
			return vButton;
		},
		/**
		 * Badge an image: adds an image (badge) over another image (target).
		 * 
		 * @method badge_image
		 *
		 * @param {url} pBadgeURL url of the badge image; the image should be a file with a transparent background.
		 * @param {string|node} pSelectorOrNode the selector to find the target image to badge. (See MUI.util.dom.get_objects for a description of selectors) OR the target image directly.
		 * @param {string} pPosition one of: MUI.util.ktop_right (default), MUI.util.ktop_center, MUI.util.ktop_left, MUI.util.kbottom_right, MUI.util.kbottom_center or MUI.util.kbottom_left
		 *
		 * @static
		 */
		badge_image: function(pBadgeURL, pSelectorOrNode, pPosition, pTargetSize, pBadgeSize) {
			if(!pPosition) pPosition = "tr";
			var vTarget = (typeof(pSelectorOrNode) == "string") ? MUI.util.dom.get_object("img", pSelectorOrNode) : pSelectorOrNode;
			if((typeof(pSelectorOrNode) == "string") && !vTarget) setTimeout("MUI.util.ui.badge_image('" + pBadgeURL + "', '" + pSelectorOrNode + "', '" + pPosition + "');");
			else {
				var vWidthProp = "naturalWidth";
				if(typeof(vTarget[vWidthProp]) == "undefined") vWidthProp = "width";
				var vHeightProp = "naturalHeight";
				if(typeof(vTarget[vHeightProp]) == "undefined") vHeightProp = "height";
				
				var vBadgeURL = pBadgeURL;
				var vSelector = pSelectorOrNode;
				var vPosition = pPosition;
				
				if(!pTargetSize) {
					var vImage = new Image();
					vImage.onload = function() {
						MUI.util.ui.badge_image(vBadgeURL, vSelector, vPosition, [vImage[vWidthProp], vImage[vHeightProp]]);
					};
					vImage.src = vTarget.src;
				}else if(!pBadgeSize) {
					var vTargetSize = pTargetSize;
					var vImage = new Image();
					vImage.onload = function() {
						MUI.util.ui.badge_image(vBadgeURL, vSelector, vPosition, vTargetSize, [vImage[vWidthProp], vImage[vHeightProp]]);
					};
					vImage.src = pBadgeURL;
				} else if((pTargetSize.length >= 2) && (pBadgeSize.length >= 2)) {
					var vAlign = vTarget.getAttribute("align");
					var vWrapper = document.createElement("span");
					vWrapper.style.position = "relative";
					vTarget.parentNode.insertBefore(vWrapper, vTarget);
					
					vWrapper.appendChild(vTarget);
					vTarget.style.position = "relative";
					
					var vBadge = document.createElement("img");
					vBadge.className = "__mui_badge";
					vBadge.style.position = "absolute";
					vBadge.style.border = "none";
					vBadge.style.zIndex = 1000000;
					vBadge.style.width = pBadgeSize[0] + "px";
					vBadge.style.height = pBadgeSize[1] + "px";
					
					if(vAlign && (vAlign.match(/left/i) || vAlign.match(/right/i))) {
						vWrapper.style.float = vAlign;
						vTarget.setAttribute("align", "");
					}
					
					if(pPosition.match(/^b/i)) vBadge.style.bottom = (navigator.userAgent.match(/msie/i) ? "0" : "2") + "px";
					else vBadge.style.top = "auto";
					if(navigator.userAgent.match(/msie/i) && pPosition.match(/r$/i)) vBadge.style.left = (pTargetSize[0] - pBadgeSize[0]) + "px";
					else if(pPosition.match(/r$/i)) vBadge.style.right = "0px";
					else if(pPosition.match(/c$/i)) vBadge.style.left = MUI.util.math.int_div((pTargetSize[0] - pBadgeSize[0]), 2) + "px";
					else vBadge.style.left = "0px";
					vBadge.src =  pBadgeURL;
					vWrapper.appendChild(vBadge);
				}
			}
		},
		/**
		 * Badge a collection of images: adds an image (badge) over another image (target).
		 * 
		 * @method badge_images
		 *
		 * @param {url} pBadgeURL url of the badge image; the image should be a file with a transparent background.
		 * @param {string} pPredicate a selector (See MUI.util.dom.get_objects for a description of selectors) or an array of object IDs.
		 * @param {string} pPosition one of: MUI.util.ktop_right (default), MUI.util.ktop_center, MUI.util.ktop_left, MUI.util.kbottom_right, MUI.util.kbottom_center or MUI.util.kbottom_left
		 *
		 * @static
		 */
		badge_images: function(pBadgeURL, pPredicate, pPosition, pNoWait) {
			// pPredicate is either a class name, or an array of IDs
			// pPosition is "tl", "tr", "bl" or "br" -- default is "tr"
			var vHotCache = new Image();
			vHotCache.src = pBadgeURL;
			if(typeof(pPredicate) == "string") {
				if(pNoWait) {
					var vObjects = MUI.util.dom.get_objects("img", pPredicate);
					if(vObjects.length == 1) MUI.util.ui.badge_image(pBadgeURL, pPredicate, pPosition);
					else {
						for(var vLoop = 0; vLoop < vObjects.length; vLoop++) MUI.util.ui.badge_image(pBadgeURL, vObjects[vLoop], pPosition);
					}
				} else {
					var vBadgeURL = pBadgeURL;
					var vPredicate = pPredicate;
					var vPosition = pPosition;
					MUI.util.dom.ready(function() {
						MUI.util.ui.badge_images(vBadgeURL, vPredicate, vPosition, true);
					});
				}
			} else {
				for(var vLoop = 0; vLoop < pPredicate.length; vLoop++) MUI.util.ui.badge_image(pBadgeURL, pPredicate[vLoop], pPosition);
			}
		}
	}
	
	// OBSOLETE
	MUI.utilities = {
		rename_element: function(pElement, pSuffix, pDeep) { MUI.util.dom.rename_element(pElement, pSuffix, pDeep); },
		add_event: function(pElement, pEventType, pFunction, pUseCapture) { MUI.util.dom.add_event(pElement, pEventType, pFunction, pUseCapture); },
		non_null_string: function(pString, pDefault) { return MUI.util.string.non_null_string(pString, pDefault); },
		wait_object: function(pObjectName, pCallBack, pArguments) { MUI.util.dom.wait_object(pObjectName, pCallBack, pArguments); },
		is_landing_page: function(pIgnoreDomains) { return MUI.util.is_landing_page(pIgnoreDomains); },
		object_by_name_attribute: function(pTag, pName, pRoot) { return MUI.util.dom.object_by_name_attribute(pTag, pName, pRoot); },
		form_inflate: function(pString) { return MUI.util.string.form_inflate(pString); },
		create_pop_up: function(pText, pImage, pPlaceholderID, pPopUpID, pPopUpFc) { return MUI.util.ui.create_pop_up(pText, pImage, pPlaceholderID, pPopUpID, pPopUpFc); },
		report_error: function(pErrorID, pMessage) { MUI.util.report_error(pErrorID, pMessage); },
		cookie_value: function(pName, pDefault) { return MUI.util.cookie_value(pName, pDefault); },
		set_cookie_value: function(pName, pHours, pPath, pDomain, pValue) { return MUI.util.set_cookie_value(pName, pHours, pPath, pDomain, pValue); }
	};
	
	MUI.util.dom.ready(function() { MUI.util.kdom_is_ready = true; });
}

Copyright © 2017 Yahoo! Inc. All rights reserved.