|
|
| Source Type: | Fully formatted code - Best for understanding and editing |
| Source File: | util.js (Right-click and "save as") |
| File size: | 18k |
PLEASE
SUPPORT THIS SITE! Rather than charging money for this site, I rely on
donations from users to help support the site and offset development time. If you find this code useful or if it helped on your project, please consider donating. Any amount is appreciated! Thanks!
/**
* Copyright (c)2005-2007 Matt Kruse (javascripttoolbox.com)
*
* Dual licensed under the MIT and GPL licenses.
* This basically means you can use this code however you want for
* free, but don't claim to have written it yourself!
* Donations always accepted: http://www.JavascriptToolbox.com/donate/
*
* Please do not link to the .js files on javascripttoolbox.com from
* your site. Copy the files locally to your server instead.
*
*/
/* ******************************************************************* */
/* UTIL FUNCTIONS */
/* ******************************************************************* */
var Util = {'$VERSION':1.06};
// Util functions - these are GLOBAL so they
// look like built-in functions.
// Determine if an object is an array
function isArray(o) {
return (o!=null && typeof(o)=="object" && typeof(o.length)=="number" && (o.length==0 || defined(o[0])));
};
// Determine if an object is an Object
function isObject(o) {
return (o!=null && typeof(o)=="object" && defined(o.constructor) && o.constructor==Object && !defined(o.nodeName));
};
// Determine if a reference is defined
function defined(o) {
return (typeof(o)!="undefined");
};
// Iterate over an array, object, or list of items and run code against each item
// Similar functionality to Perl's map() function
function map(func) {
var i,j,o;
var results = [];
if (typeof(func)=="string") {
func = new Function('$_',func);
}
for (i=1; i<arguments.length; i++) {
o = arguments[i];
if (isArray(o)) {
for (j=0; j<o.length; j++) {
results[results.length] = func(o[j]);
}
}
else if (isObject(o)) {
for (j in o) {
results[results.length] = func(o[j]);
}
}
else {
results[results.length] = func(o);
}
}
return results;
};
// Set default values in an object if they are undefined
function setDefaultValues(o,values) {
if (!defined(o) || o==null) {
o = {};
}
if (!defined(values) || values==null) {
return o;
}
for (var val in values) {
if (!defined(o[val])) {
o[val] = values[val];
}
}
return o;
};
/* ******************************************************************* */
/* DEFAULT OBJECT PROTOTYPE ENHANCEMENTS */
/* ******************************************************************* */
// These functions add useful functionality to built-in objects
Array.prototype.contains = function(o) {
var i,l;
if (!(l = this.length)) { return false; }
for (i=0; i<l; i++) {
if (o==this[i]) {
return true;
}
}
};
/* ******************************************************************* */
/* DOM FUNCTIONS */
/* ******************************************************************* */
var DOM = (function() {
var dom = {};
// Get a parent tag with a given nodename
dom.getParentByTagName = function(o,tagNames) {
if(o==null) { return null; }
if (isArray(tagNames)) {
tagNames = map("return $_.toUpperCase()",tagNames);
while (o=o.parentNode) {
if (o.nodeName && tagNames.contains(o.nodeName)) {
return o;
}
}
}
else {
tagNames = tagNames.toUpperCase();
while (o=o.parentNode) {
if (o.nodeName && tagNames==o.nodeName) {
return o;
}
}
}
return null;
};
// Remove a node from its parent
dom.removeNode = function(o) {
if (o!=null && o.parentNode && o.parentNode.removeChild) {
// First remove all attributes which are func references, to avoid memory leaks
for (var i in o) {
if (typeof(o[i])=="function") {
o[i] = null;
}
}
o.parentNode.removeChild(o);
return true;
}
return false;
};
// Get the outer width in pixels of an object, including borders, padding, and margin
dom.getOuterWidth = function(o) {
if (defined(o.offsetWidth)) {
return o.offsetWidth;
}
return null;
};
// Get the outer height in pixels of an object, including borders, padding, and margin
dom.getOuterHeight = function(o) {
if (defined(o.offsetHeight)) {
return o.offsetHeight;
}
return null;
};
// Resolve an item, an array of items, or an object of items
dom.resolve = function() {
var results = new Array();
var i,j,o;
for (var i=0; i<arguments.length; i++) {
var o = arguments[i];
if (o==null) {
if (arguments.length==1) {
return null;
}
results[results.length] = null;
}
else if (typeof(o)=='string') {
if (document.getElementById) {
o = document.getElementById(o);
}
else if (document.all) {
o = document.all[o];
}
if (arguments.length==1) {
return o;
}
results[results.length] = o;
}
else if (isArray(o)) {
for (j=0; j<o.length; j++) {
results[results.length] = o[j];
}
}
else if (isObject(o)) {
for (j in o) {
results[results.length] = o[j];
}
}
else if (arguments.length==1) {
return o;
}
else {
results[results.length] = o;
}
}
return results;
};
dom.$ = dom.resolve;
return dom;
})();
/* ******************************************************************* */
/* CSS FUNCTIONS */
/* ******************************************************************* */
var CSS = (function(){
var css = {};
// Convert an RGB string in the form "rgb (255, 255, 255)" to "#ffffff"
css.rgb2hex = function(rgbString) {
if (typeof(rgbString)!="string" || !defined(rgbString.match)) { return null; }
var result = rgbString.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/);
if (result==null) { return rgbString; }
var rgb = +result[1] << 16 | +result[2] << 8 | +result[3];
var hex = "";
var digits = "0123456789abcdef";
while(rgb!=0) {
hex = digits.charAt(rgb&0xf)+hex;
rgb>>>=4;
}
while(hex.length<6) { hex='0'+hex; }
return "#" + hex;
};
// Convert hyphen style names like border-width to camel case like borderWidth
css.hyphen2camel = function(property) {
if (!defined(property) || property==null) { return null; }
if (property.indexOf("-")<0) { return property; }
var str = "";
var c = null;
var l = property.length;
for (var i=0; i<l; i++) {
c = property.charAt(i);
str += (c!="-")?c:property.charAt(++i).toUpperCase();
}
return str;
};
// Determine if an object or class string contains a given class.
css.hasClass = function(obj,className) {
if (!defined(obj) || obj==null || !RegExp) { return false; }
var re = new RegExp("(^|\\s)" + className + "(\\s|$)");
if (typeof(obj)=="string") {
return re.test(obj);
}
else if (typeof(obj)=="object" && obj.className) {
return re.test(obj.className);
}
return false;
};
// Add a class to an object
css.addClass = function(obj,className) {
if (typeof(obj)!="object" || obj==null || !defined(obj.className)) { return false; }
if (obj.className==null || obj.className=='') {
obj.className = className;
return true;
}
if (css.hasClass(obj,className)) { return true; }
obj.className = obj.className + " " + className;
return true;
};
// Remove a class from an object
css.removeClass = function(obj,className) {
if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
if (!css.hasClass(obj,className)) { return false; }
var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
obj.className = obj.className.replace(re,' ');
return true;
};
// Fully replace a class with a new one
css.replaceClass = function(obj,className,newClassName) {
if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
css.removeClass(obj,className);
css.addClass(obj,newClassName);
return true;
};
// Get the currently-applied style of an object
css.getStyle = function(o, property) {
if (o==null) { return null; }
var val = null;
var camelProperty = css.hyphen2camel(property);
// Handle "float" property as a special case
if (property=="float") {
val = css.getStyle(o,"cssFloat");
if (val==null) {
val = css.getStyle(o,"styleFloat");
}
}
else if (o.currentStyle && defined(o.currentStyle[camelProperty])) {
val = o.currentStyle[camelProperty];
}
else if (window.getComputedStyle) {
val = window.getComputedStyle(o,null).getPropertyValue(property);
}
else if (o.style && defined(o.style[camelProperty])) {
val = o.style[camelProperty];
}
// For color values, make the value consistent across browsers
// Convert rgb() colors back to hex for consistency
if (/^\s*rgb\s*\(/.test(val)) {
val = css.rgb2hex(val);
}
// Lowercase all #hex values
if (/^#/.test(val)) {
val = val.toLowerCase();
}
return val;
};
css.get = css.getStyle;
// Set a style on an object
css.setStyle = function(o, property, value) {
if (o==null || !defined(o.style) || !defined(property) || property==null || !defined(value)) { return false; }
if (property=="float") {
o.style["cssFloat"] = value;
o.style["styleFloat"] = value;
}
else if (property=="opacity") {
o.style['-moz-opacity'] = value;
o.style['-khtml-opacity'] = value;
o.style.opacity = value;
if (defined(o.style.filter)) {
o.style.filter = "alpha(opacity=" + value*100 + ")";
}
}
else {
o.style[css.hyphen2camel(property)] = value;
}
return true;
};
css.set = css.setStyle;
// Get a unique ID which doesn't already exist on the page
css.uniqueIdNumber=1000;
css.createId = function(o) {
if (defined(o) && o!=null && defined(o.id) && o.id!=null && o.id!="") {
return o.id;
}
var id = null;
while (id==null || document.getElementById(id)!=null) {
id = "ID_"+(css.uniqueIdNumber++);
}
if (defined(o) && o!=null && (!defined(o.id)||o.id=="")) {
o.id = id;
}
return id;
};
return css;
})();
/* ******************************************************************* */
/* EVENT FUNCTIONS */
/* ******************************************************************* */
var Event = (function(){
var ev = {};
// Resolve an event using IE's window.event if necessary
// --------------------------------------------------------------------
ev.resolve = function(e) {
if (!defined(e) && defined(window.event)) {
e = window.event;
}
return e;
};
// Add an event handler to a function
// Note: Don't use 'this' within functions added using this method, since
// the attachEvent and addEventListener models differ.
// --------------------------------------------------------------------
ev.add = function( obj, type, fn, capture ) {
if (obj.addEventListener) {
obj.addEventListener( type, fn, capture );
return true;
}
else if (obj.attachEvent) {
obj.attachEvent( "on"+type, fn );
return true;
}
return false;
};
// Get the mouse position of an event
// --------------------------------------------------------------------
// PageX/Y, where they exist, are more reliable than ClientX/Y because
// of some browser bugs in Opera/Safari
ev.getMouseX = function(e) {
e = ev.resolve(e);
if (defined(e.pageX)) {
return e.pageX;
}
if (defined(e.clientX)) {
return e.clientX+Screen.getScrollLeft();
}
return null;
};
ev.getMouseY = function(e) {
e = ev.resolve(e);
if (defined(e.pageY)) {
return e.pageY;
}
if (defined(e.clientY)) {
return e.clientY+Screen.getScrollTop();
}
return null;
};
// Stop the event from bubbling up to parent elements.
// Two method names map to the same function
// --------------------------------------------------------------------
ev.cancelBubble = function(e) {
e = ev.resolve(e);
if (typeof(e.stopPropagation)=="function") { e.stopPropagation(); }
if (defined(e.cancelBubble)) { e.cancelBubble = true; }
};
ev.stopPropagation = ev.cancelBubble;
// Prevent the default handling of the event to occur
// --------------------------------------------------------------------
ev.preventDefault = function(e) {
e = ev.resolve(e);
if (typeof(e.preventDefault)=="function") { e.preventDefault(); }
if (defined(e.returnValue)) { e.returnValue = false; }
};
return ev;
})();
/* ******************************************************************* */
/* SCREEN FUNCTIONS */
/* ******************************************************************* */
var Screen = (function() {
var screen = {};
// Get a reference to the body
// --------------------------------------------------------------------
screen.getBody = function() {
if (document.body) {
return document.body;
}
if (document.getElementsByTagName) {
var bodies = document.getElementsByTagName("BODY");
if (bodies!=null && bodies.length>0) {
return bodies[0];
}
}
return null;
};
// Get the amount that the main document has scrolled from top
// --------------------------------------------------------------------
screen.getScrollTop = function() {
if (document.documentElement && defined(document.documentElement.scrollTop) && document.documentElement.scrollTop>0) {
return document.documentElement.scrollTop;
}
if (document.body && defined(document.body.scrollTop)) {
return document.body.scrollTop;
}
return null;
};
// Get the amount that the main document has scrolled from left
// --------------------------------------------------------------------
screen.getScrollLeft = function() {
if (document.documentElement && defined(document.documentElement.scrollLeft) && document.documentElement.scrollLeft>0) {
return document.documentElement.scrollLeft;
}
if (document.body && defined(document.body.scrollLeft)) {
return document.body.scrollLeft;
}
return null;
};
// Util function to default a bad number to 0
// --------------------------------------------------------------------
screen.zero = function(n) {
return (!defined(n) || isNaN(n))?0:n;
};
// Get the width of the entire document
// --------------------------------------------------------------------
screen.getDocumentWidth = function() {
var width = 0;
var body = screen.getBody();
if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
var rightMargin = parseInt(CSS.get(body,'marginRight'),10) || 0;
var leftMargin = parseInt(CSS.get(body,'marginLeft'), 10) || 0;
width = Math.max(body.offsetWidth + leftMargin + rightMargin, document.documentElement.clientWidth);
}
else {
width = Math.max(body.clientWidth, body.scrollWidth);
}
if (isNaN(width) || width==0) {
width = screen.zero(self.innerWidth);
}
return width;
};
// Get the height of the entire document
// --------------------------------------------------------------------
screen.getDocumentHeight = function() {
var body = screen.getBody();
var innerHeight = (defined(self.innerHeight)&&!isNaN(self.innerHeight))?self.innerHeight:0;
if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
var topMargin = parseInt(CSS.get(body,'marginTop'),10) || 0;
var bottomMargin = parseInt(CSS.get(body,'marginBottom'), 10) || 0;
return Math.max(body.offsetHeight + topMargin + bottomMargin, document.documentElement.clientHeight, document.documentElement.scrollHeight, screen.zero(self.innerHeight));
}
return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight));
};
// Get the width of the viewport (viewable area) in the browser window
// --------------------------------------------------------------------
screen.getViewportWidth = function() {
if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
return document.documentElement.clientWidth;
}
else if (document.compatMode && document.body) {
return document.body.clientWidth;
}
return screen.zero(self.innerWidth);
};
// Get the height of the viewport (viewable area) in the browser window
// --------------------------------------------------------------------
screen.getViewportHeight = function() {
if (!window.opera && document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
return document.documentElement.clientHeight;
}
else if (document.compatMode && !window.opera && document.body) {
return document.body.clientHeight;
}
return screen.zero(self.innerHeight);
};
return screen;
})();var Sort = (function(){
var sort = {};
sort.AlphaNumeric = function(a,b) {
if (a==b) { return 0; }
if (a<b) { return -1; }
return 1;
};
sort.Default = sort.AlphaNumeric;
sort.NumericConversion = function(val) {
if (typeof(val)!="number") {
if (typeof(val)=="string") {
val = parseFloat(val.replace(/,/g,''));
if (isNaN(val) || val==null) { val=0; }
}
else {
val = 0;
}
}
return val;
};
sort.Numeric = function(a,b) {
return sort.NumericConversion(a)-sort.NumericConversion(b);
};
sort.IgnoreCaseConversion = function(val) {
if (val==null) { val=""; }
return (""+val).toLowerCase();
};
sort.IgnoreCase = function(a,b) {
return sort.AlphaNumeric(sort.IgnoreCaseConversion(a),sort.IgnoreCaseConversion(b));
};
sort.CurrencyConversion = function(val) {
if (typeof(val)=="string") {
val = val.replace(/^[^\d\.]/,'');
}
return sort.NumericConversion(val);
};
sort.Currency = function(a,b) {
return sort.Numeric(sort.CurrencyConversion(a),sort.CurrencyConversion(b));
};
sort.DateConversion = function(val) {
// inner util function to parse date formats
function getdate(str) {
// inner util function to convert 2-digit years to 4
function fixYear(yr) {
yr = +yr;
if (yr<50) { yr += 2000; }
else if (yr<100) { yr += 1900; }
return yr;
};
var ret;
// YYYY-MM-DD
if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]);
}
// MM/DD/YY[YY] or MM-DD-YY[YY]
if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
return (fixYear(ret[3])*10000) + (ret[1]*100) + (+ret[2]);
}
return 99999999; // So non-parsed dates will be last, not first
};
return getdate(val);
};
sort.Date = function(a,b) {
return sort.Numeric(sort.DateConversion(a),sort.DateConversion(b));
};
return sort;
})();