/** * Credox Framework [JavaScript], ver. 0.1 alpha / 29.11.2007 * * * This JavaScript is part of Credox Framework [www.credox.org] * The script is freely distributable under the terms of an MIT license * * * Copyright (c) 2007 Hristo Drumev [www.hdrumev.com] * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * 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. 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. * * * @author Hristo Drumev * @package framework * @license MIT license * @copyright Hristo Drumev [www.hdrumev.com] * @version 0.1 alpha / 29.11.2007 * * * include: * core.js - Standard JS objects extensions - ver. 0.7 / 11.12.2007 alpha * object.event.js - Event [object] - ver. 0.7 / 05.10.2007 beta * object.window.js - Window [object] - ver. 0.2 / 13.07.2007 beta * object.color.js - Color [object] - ver. 0.2 / 17.08.2007 alpha * object.cookie.js - Cookie [object] - ver. 0.2 / 07.09.2007 * object.utils.js - Utils [object] - ver. 0.1 / 05.10.2007 alpha * patches.js - Patches - ver. 0.1 / 17.09.2007 * */ // file: core.js --------------------------------------------------------------- var Namespace = function( name, namespace ) { if( !name ) return window[name] || {}; name = name.split( '.' ); namespace = namespace || window; for( var i = 0, length = name.length; i < length; ++i ) { if( typeof( namespace[name[i]] ) == 'undefined' ) namespace[name[i]] = {}; namespace = namespace[name[i]]; } return namespace; }; var Credox = new Namespace(); var Class = function( superclass, classprototype ) { var subclass = function() { if( typeof this.create == 'function' ) this.create.apply( this, arguments ); } if( superclass ) { function ancestor() {}; ancestor.prototype = superclass.prototype; subclass.prototype = new ancestor(); subclass.prototype.constructor = this; } if( classprototype ) for( var property in classprototype ) subclass.prototype[property] = classprototype[property]; return subclass; } Array.prototype.indexOf = function( value ) { for( var i = 0, length = this.length; i < length; ++i ) if( this[i] == value ) return i; return -1; } Array.prototype.lastIndexOf = function( value ) { for( var i = this.length; --i; ) if( this[i] == value ) return i; return -1; } Array.prototype.contain = function( value ) { return this.indexOf( value ) > -1 ? true : false; } Array.prototype.each = function( callback ) { for( var i = 0, length = this.length; i < length; ++i ) callback( this[i] ); return this; } Array.prototype.random = function() { return this[Math.floor( this.length * Math.random() )]; } Function.prototype.bind = function() { var object = this, args = arguments, target = arguments[0]; return function() { return object.apply( target, args ); } } Function.prototype.bindAsEvent = function( target ) { var object = this; return function( event ) { return object.apply( target, event || window.event ); } } String.prototype.trimLeft = function() { return this.replace( /^\s+/, '' ); } String.prototype.trimRight = function() { return this.replace( /\s+$/, '' ); } String.prototype.trim = function() { return this.replace( /^\s+|\s+$/, '' ); } String.prototype.clean = function() { return this.replace( /^\s+|\s+$|\s{2,}/, '' ); } String.prototype.stripHTMLTags = function() { return this.replace( /<\/?[^>]+>/gi, '' ); } String.prototype.capitalize = function() { return this.charAt( 0 ).toUpperCase() + this.substring( 1 ).toLowerCase(); } Number.prototype.toInt = function() { return parseInt( this, 10 ); } Number.prototype.toFloat = function() { return parseFloat( this ); } Number.prototype.toRange = function( min, max ) { return this < min ? min : ( this > max ? max : this ); } Math.randomInt = function( min, max ) { return parseInt( min + Math.random()*( max - min ), 10 ); } Math.randomFloat = function( min, max ) { return min + Math.random()*( max - min ); } // file: object.event.js ------------------------------------------------------- var Event = {}; Event.KEY_BACKSPACE = 8; Event.KEY_TAB = 9; Event.KEY_ENTER = 13; Event.KEY_PAUSE = 19; Event.KEY_ESC = 27; Event.KEY_PAGEUP = 33; Event.KEY_PAGEDOWN = 34; Event.KEY_END = 35; Event.KEY_HOME = 36; Event.KEY_LEFT = 37; Event.KEY_UP = 38; Event.KEY_RIGHT = 39; Event.KEY_DOWN = 40; Event.KEY_INSERT = 45; Event.KEY_DELETE = 46; Event.KEY_F1 = 112; Event.KEY_F2 = 113; Event.KEY_F3 = 114; Event.KEY_F4 = 115; Event.KEY_F5 = 116; Event.KEY_F6 = 117; Event.KEY_F7 = 118; Event.KEY_F8 = 119; Event.KEY_F9 = 120; Event.KEY_F10 = 121; Event.KEY_F11 = 122; Event.KEY_F12 = 123; Event.DOMLoaded = false; Event.init = function( event ) { this.event = !event ? window.event : event; this.type = this.event.type; this.mouse = this.mouseXY( this.event ); this.client = this.clientXY( this.event ); this.element = this.getElement( this.event ); this.relatedElement = this.getRelatedElement( this.event ); this.shift = this.event.shiftKey; this.ctrl = this.event.ctrlKey; this.alt = this.event.altKey; this.left = this.event.which == null ? this.event.button == 1 : this.event.button == 0; this.middle = this.event.which == null ? this.event.button == 4 : this.event.which == 2; this.right = this.event.which == null ? this.event.button == 2 : this.event.which == 3; this.wheel = /(DOMMouseScroll|mousewheel)/.test( this.type ) ? this.event.wheelDelta ? this.event.wheelDelta / 120 : -( this.event.detail || 0 ) / 3 : 0; this.keyCode = this.event.keyCode || this.event.which; return this; } Event._exec = function( event ) { event = event || window.event; for( var i = 0, len = this._eventList.length; i < len; i++ ) if( this._eventList[i].type == event.type ) this._eventList[i].fn.call( this, event ); } Event._execDOMLoad = function( event ) { event = event || window.event; for( var i = 0, len = this._eventListDOMLoad.length; i < len; i++ ) this._eventListDOMLoad[i].call( this, event ); } Event.add = function( element, type, fn ) { if( element.addEventListener && !window.opera ) element.addEventListener( type == 'mousewheel' ? 'DOMMouseScroll' : type, fn, false ); else if( element['on' + type] ) if( element._eventList ) { for( var i = 0, len = element._eventList.length; i < len; i++ ) if( element._eventList[i].type == type && element._eventList[i].fn === fn ) return; element._eventList[element._eventList.length] = { type: type, fn: fn }; } else { if( element['on' + type] === fn ) return; element._eventList = new Array( { type: type, fn: element['on' + type] }, { type: type, fn: fn } ); element['on' + type] = this._exec; } else element['on' + type] = fn; } Event.remove = function( element, type, fn ) { if( element.removeEventListener && !window.opera ) element.removeEventListener( type == 'mousewheel' ? 'DOMMouseScroll' : type, fn, false ); else if( element._eventList ) for( var i = element._eventList.length, item = null; i--; ) { if( ( item = element._eventList[i] ) && item.type == type && item.fn === fn ) element._eventList[i] = null; } else element['on' + type] = null; } Event.getElement = function( event ) { event = event || window.event; var element = event.target || event.srcElement; return element.nodeType == 3 ? element.parentNode : element; } Event.getRelatedElement = function( event ) { event = event || window.event; if( event.type != 'mouseover' && event.type != 'mouseout' ) return null; var element = event.relatedTarget || ( event.type == 'mouseover' ? event.fromElement : event.toElement ); return element && element.nodeType == 3 ? element.parentNode : element; } Event.mouseXY = function( event ) { event = event || window.event; if( /(click|mouse|menu)/.test( event.type ) ) return { x: event.pageX || event.clientX + document.documentElement.scrollLeft, y: event.pageY || event.clientY + document.documentElement.scrollTop }; else return { x: 0, y: 0 }; } Event.clientXY = function( event ) { event = event || window.event; if( /(click|mouse|menu)/.test( event.type ) ) return { x: event.pageX ? event.pageX - window.pageXOffset : event.clientX, y: event.pageY ? event.pageY - window.pageYOffset : event.clientY }; else return { x: 0, y: 0 }; } Event.onDOMLoad = function( fn ) { if( this.DOMLoaded ) fn.call( this, event || window.event ); if( window.attachEvent || /webkit|safari|khtml/i.test( navigator.userAgent ) ) { if( !this._eventListDOMLoad ) this._eventListDOMLoad = []; var len = this._eventListDOMLoad.length; for( var i = 0; i < len; i++ ) if( this._eventListDOMLoad[i] === fn ) return; this._eventListDOMLoad[len] = fn; if( len > 0 ) return; if( window.attachEvent && !window.opera ) // MSIE { var _timer = window.setInterval( function() { try { document.firstChild.doScroll( 'left' ); window.clearInterval( _timer ); Event._execDOMLoad(); } catch( e ) {} }, 50 ); } else // Safari, Opera { var _timer = window.setInterval( function() { if( /loaded|complete/.test( document.readyState ) ) { window.clearInterval( _timer ); Event._execDOMLoad(); } }, 50 ); } } else if( document.addEventListener ) this.add( document, 'DOMContentLoaded', fn ); else this.add( window, 'load', fn ); } Event.onDOMLoad( function() { Event.DOMLoaded = true; } ); // file: object.window.js ------------------------------------------------------ var Window = {}; Window.width = function() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; } Window.height = function() { return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; } Window.scrollWidth = function() { return document.body.scrollWidth || Math.max( document.documentElement.offsetWidth, document.documentElement.scrollWidth ); } Window.scrollHeight = function() { return document.body.scrollHeight || Math.max( document.documentElement.offsetHeight, document.documentElement.scrollHeight ); } Window.scrollLeft = function() { return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; } Window.scrollTop = function() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } // file: object.color.js ------------------------------------------------------- var Color = {}; Color.byName = function( name ) { switch( name.toLowerCase() ) { case 'aqua' : return '#00ffff'; case 'black' : return '#000000'; case 'blue' : return '#0000ff'; case 'fuchsia' : return '#ff00ff'; case 'gray' : return '#808080'; case 'green' : return '#008000'; case 'lime' : return '#00ff00'; case 'maroon' : return '#800000'; case 'navy' : return '#000080'; case 'olive' : return '#808000'; case 'orange' : return '#ffa500'; case 'purple' : return '#800080'; case 'red' : return '#ff0000'; case 'silver' : return '#c0c0c0'; case 'teal' : return '#008080'; case 'white' : return '#ffffff'; case 'yellow' : return '#ffff00'; default : return null; } } Color.isColor = function( value ) { return /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2});?$/i.test( value ) || /^#([0-9a-f])([0-9a-f])([0-9a-f]);?$/i.test( value ) || /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\);?$/.test( value ) || /^rgb\(\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\);?$/.test( value ) || /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*((?:\d+(?:\.\d+)?)|(?:\.\d+))\s*\);?$/.test( value ) || /^rgba\(\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*((?:\d+(?:\.\d+)?)|(?:\.\d+))\s*\);?$/.test( value ) || Color.byName( value ) !== null; } Color.parse = function( value ) { value = String( value ).toLowerCase(); if( value.indexOf( '#' ) == 0 ) { if( value.length == 7 ) return value; var part = value.slice( 1, 4 ).split( '' ); return '#' + part[0] + part[0] + part[1] + part[1] + part[2] + part[2]; } else if( value.indexOf( 'rgb' ) >= 0 ) { var part = value.replace( /^\s+(rgb|rgba)\s+\(|\)\s+$/, '' ).split( ',' ); return Color.fromRGB( part[0], part[1], part[2] ); } else { var color = Color.byName( value ); if( color ) return color; } return value; } Color.toInteger = function( value ) { return parseInt( '0x' + Color.parse( value ).replace( '#', '' ) ); } Color.toRGB = function( value ) { value = Color.toInteger( value ); return { red : ( value & 0xff0000 ) >>> 16, green: ( value & 0x00ff00 ) >>> 8, blue : ( value & 0x0000ff ) }; } Color.fromRGB = function( red, green, blue ) { if( /%/g.test( red ) ) { red *= 2.55; green *= 2.55; blue *= 2.55; } return '#' + ( 1 << 24 | parseInt( red ) << 16 | parseInt( green ) << 8 | parseInt( blue ) ).toString( 16 ).substr( 1 ); } // file: object.cookie.js ------------------------------------------------------ var Cookie = {}; Cookie.get = function( name ) { return ( !document.cookie.length || ( str = document.cookie.indexOf( name + '=' ) ) == -1 ) ? null : document.cookie.substring( ( str += ( name + '=' ).length ), ( result = document.cookie.indexOf( ';', str ) ) == -1 ? document.cookie.length : result ); } Cookie.set = function( name, value, expires, path, domain, secure ) { if( expires ) { var date = new Date(); expires = date.setTime( date.getTime() + ( expires * 86400000 ) ); // 24*60*60*1000 (ms. in 1 day) } document.cookie += name + '=' + value + ( expires ? '; expires=' + expires.toGMTString() : '' ) + '; path=' + ( path ? path :'/' ) + ( domain ? '; domain=' + domain : '' ) + ( secure ? ';secure' : '' ); } Cookie.unset = function( name ) { if( this.isSet() ) this.save( name, '', -1 ); } Cookie.isSet = function( name ) { return !!( document.cookie.indexOf( name + '=' ) + 1 ); } // file: object.utils.js ------------------------------------------------------- var Utils = {}; // namespace Utils.include = function( src, type, callback ) { if( !type ) { if( /.js/i.test( src ) ) type = 'text/javascript'; if( /.css/i.test( src ) ) type = 'text/css'; } var file; if( type == 'text/javascript' ) { file = document.createElement( 'script' ); file.setAttribute( 'src', src ); } else if( type == 'text/css' ) { file = document.createElement( 'link' ); file.setAttribute( 'rel', 'stylesheet' ); file.setAttribute( 'href', src ); } else return; file.setAttribute( 'type', type ); var head = document.getElementsByTagName( 'head' )[0]; head.appendChild( file ); if( typeof( callback ) == 'function' ) { if( /WebKit|Safari|Khtml/i.test( navigator.userAgent ) && navigator.userAgent.indexOf( 'Version/2' ) >= 0 ) // Safari 2 { var iframe = document.createElement( 'iframe' ); iframe.style.display = 'none'; iframe.setAttribute( 'src', file ); head.appendChild( iframe ); iframe.onload = callback(); } else { if( document.all ) file.onreadystatechange = function() // IE { if( /complete|loaded/.test( file.readyState ) ) callback(); } else file.onload = callback; // FF } } } Utils.clone = function( src ) { var type = String( src.constructor ).match( /\s*function (.*)\(/ )[1]; if( type == 'Object' ) { var instance = function() {}; instance.prototype = src; var object = new instance(); for( property in object ) if( typeof( object[property] ) == 'object' ) object[property] = object[property].clone(); return object; } if( type == 'Array' ) return this.slice( 0 ); if( type == 'Date' ) return new Date( src.getTime() ); // type is Boolean, Function, Number, RegExp, String return src.valueOf ? src.valueOf() : src; } Utils.extend = function() { var target = arguments[0]; for( var i = 1, length = arguments.length; i < length; ++i ) { var source = arguments[i]; if( source && target.prototype && source.prototype ) target.prototype.extend( source.prototype ) else for( var property in source ) target[property] = source[property]; } return target; } // file: patches.js ------------------------------------------------------------ if( /^html$/.test( document.documentElement.tagName ) ) // is XHTML document.writeln = document.write = function( xhtml ) { if ( xhtml.match( /^<\// ) ) return; if ( !window.opera ) xhtml = xhtml.replace( /&(?![#a-z0-9]+;)/g, "&" ); xhtml = xhtml.replace( /<([a-z]+)(.*[^\/])>$/, "<$1$2>$1>"); var XMLNS = 'http:\/\/www.w3.org\/1999\/xhtml'; if ( window.opera || /Apple/.test( navigator.vendor ) ) xhtml = xhtml.replace( /(<[a-z]+)/g, "$1 xmlns='" + XMLNS + "'" ); var element = document; while( element.lastChild && element.lastChild.nodeType == 1 ) // ELEMENT_NODE element = element.lastChild; element = element.parentNode; var parser = new DOMParser(); var XMLdoc = parser.parseFromString( '