Click here to Skip to main content
15,886,519 members
Articles / Web Development / HTML

Writing Object-Oriented JavaScript Part 2

Rate me:
Please Sign up or sign in to vote.
4.37/5 (22 votes)
8 Dec 20038 min read 113K   1.1K   58  
Using Cfx to develop a JavaScript control class library.
//////////////////////////////////////////////////////////////////////////////
//	Cfx.js
//
//	Description:
//		JavaScript Class Framework 
//		(c) 2003 Chris Waldron  -- All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

var cfxJs = new _js();
var cfxClass = new _class();
var cfxDom = new _dom();

var Cfx = new Object();
Cfx.Js = cfxJs;
Cfx.Class = cfxClass;
Cfx.Dom = cfxDom;


//////////////////////////////////////////////////////////////////////////////
// Function extensions.
//////////////////////////////////////////////////////////////////////////////
Function.prototype.className = "Function";
Function.prototype.baseClass = null;
Function.prototype.instances = false;
Function.prototype.Method = function( func )
{
    this.prototype[cfxJs.FunctionName( func )] = func;
    return this;
};


//////////////////////////////////////////////////////////////////////////////
// Object extensions.
//////////////////////////////////////////////////////////////////////////////
Object.prototype.className = "Object";
Object.prototype.baseClass = null;
Object.prototype.InstanceOf = cfxClass.InstanceOf;
Object.prototype.InitInstance = function()
{
	// Initialize the instance.
	for ( name in this.constructor )
		this[name] = this.constructor[name];
		
	// Perserve instance if requested.
	if ( this.constructor.instances == true )
		this.constructor.instances = new Array();
	
	if ( Cfx.Js.IsArray( this.constructor.instances ) )
		this.constructor.instances[this.constructor.instances.length] = this;
};


//////////////////////////////////////////////////////////////////////////////
// Date extensions.
//////////////////////////////////////////////////////////////////////////////
Date.prototype.className = "Date";
Date.prototype.baseClass = Object;


//////////////////////////////////////////////////////////////////////////////
// Error extensions.
//////////////////////////////////////////////////////////////////////////////
Error.prototype.className = "Error";
Error.prototype.baseClass = Object;


//////////////////////////////////////////////////////////////////////////////
// RegExp extensions.
//////////////////////////////////////////////////////////////////////////////
RegExp.prototype.className = "RegExp";
RegExp.prototype.baseClass = Object;


//////////////////////////////////////////////////////////////////////////////
// String extensions.
//////////////////////////////////////////////////////////////////////////////
String.prototype.className = "String";
String.prototype.baseClass = Object;
String.prototype.trim = function()
{
	// Remove leading and trailing whitespace.
	return this.replace( /^\s+/, "" ).replace( /\s+$/, "" );
}


//////////////////////////////////////////////////////////////////////////////
//	Js
//////////////////////////////////////////////////////////////////////////////
function _js()
{
	// Naming functions.
	_js.prototype.FunctionName = FunctionName;
	_js.prototype.ObjectName = ObjectName;

	// Type identity function.
	_js.prototype.IsArray = IsArray;
	_js.prototype.IsDefined = IsDefined;
	_js.prototype.IsEmpty = IsEmpty;
	_js.prototype.IsFunction = IsFunction;
	_js.prototype.IsNull = IsNull;
	_js.prototype.IsNumeric = IsNumeric;
	_js.prototype.IsObject = IsObject;
	_js.prototype.IsString = IsString;

	// Conversion functions.
	_js.prototype.ToFunction = ToFunction;
	
	//////////////////////////////////////////////////////////////////////////////
	//	IsArray( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsArray( obj )
	{
		return IsObject( obj ) && obj.constructor == Array;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsDefined( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsDefined( obj )
	{
	    return typeof( obj ) == 'undefined' ? false : true;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsEmpty( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsEmpty( obj )
	{
		retval = true;
		if ( IsObject( obj ) )
		{
			for ( var item in obj )
			{
				retval = false;
				break;
            }
        }
        
		return retval;
	}

	//////////////////////////////////////////////////////////////////////////////
	//	IsFunction( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsFunction( obj )
	{
		return typeof( obj ) == 'function';
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsNull( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsNull( obj )
	{
		return IsObject( obj ) && ( obj == null );
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsNumeric( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsNumeric( obj )
	{
	    return typeof( obj ) == 'number' && isFinite( obj );
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsObject( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsObject( obj )
	{
		return typeof( obj ) == 'object';
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsString( obj )
	//////////////////////////////////////////////////////////////////////////////
	function IsString( obj )
	{
		return typeof( obj ) == 'string';
	}


	//////////////////////////////////////////////////////////////////////////////
	//	ObjectName( obj )
	//////////////////////////////////////////////////////////////////////////////
	function ObjectName( obj )
	{
		var objName = null;
		
		if ( IsObject( obj ) )
		{
			var objName = null;
			var strFunc = obj.constructor.toString();
			var reFuncName = new RegExp( /function\s+(\w+).*/g );
			var result = reFuncName.exec( strFunc );
			objName = result[1];
		}		
		
		return objName;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FunctionName( func )
	//////////////////////////////////////////////////////////////////////////////
	function FunctionName( func )
	{
		var funcName = null;
		if ( IsFunction( func ) )
		{
			var strFunc = func.toString();
			var reFuncName = new RegExp( /function\s+(\w+).*/g );
			var result = reFuncName.exec( strFunc );
			funcName = result[1];
		}
		
		return funcName;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	ToFunction( obj )
	//////////////////////////////////////////////////////////////////////////////
	function ToFunction( obj )
	{
		if ( IsObject( obj ) )
			return obj.constructor;
		else if ( IsFunction( obj ) )
			return obj;
		else
			return null;
	}
}


//////////////////////////////////////////////////////////////////////////////
//	Class
//////////////////////////////////////////////////////////////////////////////
function _class()
{
	_class.prototype.New = New;
	_class.prototype.GetName = GetName;
	_class.prototype.IsDefined = IsDefined;
	_class.prototype.IsInitializing = IsInitializing;
	_class.prototype.InstanceOf = InstanceOf;
	_class.prototype.Reflect = Reflect;
	_class.initializing = true;
	return;


	//////////////////////////////////////////////////////////////////////////////
	//	GetName( classArg )
	//////////////////////////////////////////////////////////////////////////////
	function GetName( classArg )
	{
		var className;

		if ( arguments.length == 0 )
			classArg = this;
	
		if ( cfxJs.IsObject( classArg ) )
			className = cfxJs.ObjectName( classArg );
		else if ( cfxJs.IsFunction( classArg ) )
			className = cfxJs.FunctionName( classArg );
		else
			className = classArg;
			
		return className;
	}
	

	//////////////////////////////////////////////////////////////////////////////
	//	IsDefined( classArg )
	//////////////////////////////////////////////////////////////////////////////
	function IsDefined( thisClass )
	{
		if ( thisClass == Object )
			return true;
		else if ( thisClass.baseClass == null )
			return false;
		else
			return thisClass.className != _class.initializing ? true : false; 
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsInitializing( thisClass )
	//////////////////////////////////////////////////////////////////////////////
	function IsInitializing( thisClass )
	{
		// A class is initializing when the associated prototype is set to true.
		return thisClass.className == _class.initializing ? true : false;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	InstanceOf( thisClass, targClass )
	//////////////////////////////////////////////////////////////////////////////
	function InstanceOf( thisClass, targClass )
	{
		var retval = false;

		// Set up arguments.
		if ( arguments.length == 1 )
		{
			targClass = thisClass;
			thisClass = cfxJs.ToFunction( this );
		}
		
		// Convert arguments to functions.
		thisClass = cfxJs.ToFunction( thisClass );
		targClass = cfxJs.ToFunction( targClass );

		// Validate arguments.
		if ( !cfxJs.IsDefined( thisClass ) )
			throw new Error( "Source class is undefined" );
		else if ( !cfxJs.IsDefined( targClass ) )
			throw new Error( "Target class is undefined" );

		// Find instance of.
		if ( thisClass.className == targClass.className )
			retval = true;
		else if ( targClass == Object )
			retval = true;
		else if ( thisClass.baseClass == Object )
			return false;
		else if ( !cfxJs.IsArray( thisClass.baseClass ) )
			retval = cfxClass.InstanceOf( thisClass.baseClass, targClass );
		else 
		{
			var baseClasses = thisClass.baseClass;
			for ( var ii = 0; ii < baseClasses.length; ++ii )
			{
				retval = cfxClass.InstanceOf( baseClasses[ii], targClass );
				if ( retval == true )
					break;
			}
		}
			
		// Return result.		
		return retval;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	New( thisClass )
	//////////////////////////////////////////////////////////////////////////////
	function New( thisClass )
	{
		// Exit if class is initializing.
		if ( cfxClass.IsInitializing( thisClass ) == true )
			return;
			
		// Inherit from base classes.
		for ( var ii = arguments.length - 1; ii > 0; --ii )
		{
			// Create base class object.
			var baseClass = new arguments[ii];
			
			// Inherit base class methods.
			for ( name in baseClass )
				thisClass.prototype[name] = baseClass[name];
	
			// Inherit base class properties.
			for ( name in baseClass.constructor )
			{
				if ( !cfxJs.IsFunction( baseClass.constructor[name] ) )
					thisClass[name] = baseClass.constructor[name];
			}

			// Setup base class designator used by InstanceOf
			if ( ( arguments.length == 2 ) && ( ii == 1 ) )
			{
				// Set up single inheritance.
				thisClass.baseClass = baseClass;
			}
			else
			{
				// Setup multiple inheritance.
				if ( !cfxJs.IsArray( thisClass.baseClass ) )
					thisClass.baseClass = new Array();

				thisClass.baseClass[ii-1] = baseClass;
			}
		}
		
		// Initialize the class and return.
		thisClass.className = _class.initializing
		var self = new thisClass;
		thisClass.className = cfxClass.GetName( thisClass );
		if ( thisClass.baseClass == null ) thisClass.baseClass = Object;
		return;
	}
	
	
	//////////////////////////////////////////////////////////////////////////////
	//	Reflect( thisClass )
	//////////////////////////////////////////////////////////////////////////////
	function Reflect( thisClass )
	{
		var className = cfxJs.GetName( thisClass );

		for ( name in thisClass.prototype )
			alert( className + ".prototype." + name );

		for ( name in thisClass )
			alert( className + "." + name );

	}
}


//////////////////////////////////////////////////////////////////////////////
//	Dom
//////////////////////////////////////////////////////////////////////////////
function _dom()
{
	// Browser properties.
	this.isIE = IsIE();
	this.isNetscape = IsNetscape();
	this.isMozilla = IsMozilla();
	
	// Document form function.
	_dom.prototype.GetForm = GetForm;

	// Document element functions.
	_dom.prototype.FindElementById = FindElementById;
	_dom.prototype.FindElementByName = FindElementByName;
	_dom.prototype.FindElementSetById = FindElementSetById;
	_dom.prototype.FindElementSetByName = FindElementSetByName;
	_dom.prototype.GetElementById = GetElementById;
	_dom.prototype.GetElementByName = GetElementByName;
	_dom.prototype.GetElementTerms = GetElementTerms;

	// Document image functions.
	_dom.prototype.FindImage = FindImage;
	_dom.prototype.FindImageSet = FindImageSet;
	_dom.prototype.GetImage = GetImage;

	// Document submit functions.
	_dom.prototype.PostBack = PostBack;

	return;


	//////////////////////////////////////////////////////////////////////////////
	//	IsIE()
	//////////////////////////////////////////////////////////////////////////////
	function IsIE()
	{
		var isApp = navigator.appName.indexOf( "Microsoft" ) != -1;
		
		var isVersion = ( arguments.length ) ?
					     navigator.appVersion.substring(0, 1).valueOf() >= arguments[0]
					     : true;
		
		return isApp && isVersion;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsMozilla()
	//////////////////////////////////////////////////////////////////////////////
	function IsMozilla()
	{
		var isApp = IsNetscape() && !document.all && document.getElementById;
		
		var isVersion = ( arguments.length ) ?
					     navigator.appVersion.substring(0, 1).valueOf() >= arguments[0]
					     : true;
					     
		return isApp && isVersion;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	IsNetscape()
	//////////////////////////////////////////////////////////////////////////////
	function IsNetscape()
	{
		var isApp = navigator.appName == "Netscape";
		
		var isVersion = ( arguments.length ) ?
					     navigator.appVersion.substring(0, 1).valueOf() >= arguments[0]
					     : true;
					     
		return isApp && isVersion;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FindElementById( elementName )
	//////////////////////////////////////////////////////////////////////////////
	function FindElementById( elementName )
	{
		var theForm = GetForm( arguments[1] );
		var nElements = theForm.elements.length;
		for ( var ii = 0; ii < nElements; ++ii )
		{
			var theElement = theForm.elements[ii];
			if ( theElement.id.indexOf( elementName ) != -1 ) 
				return theElement;
		}
		
		return null;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FindElementByName( elementName )
	//////////////////////////////////////////////////////////////////////////////
	function FindElementByName( elementName )
	{
		var theForm = GetForm( arguments[1] );
		var nElements = theForm.elements.length;
		for ( var ii = 0; ii < nElements; ++ii )
		{
			var theElement = theForm.elements[ii];
			if ( theElement.name.indexOf( elementName ) != -1 )
				return theElement;
		}
		
		return null;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FindElementSetById( elementName )
	//////////////////////////////////////////////////////////////////////////////
	function FindElementSetById( elementName )
	{
		var theForm = GetForm( arguments[1] );
		var nElements = theForm.elements.length;
		var elementSet = null;

		for ( var ii = 0; ii < nElements; ++ii )
		{
			var theElement = theForm.elements[ii];
			if ( theElement.id.indexOf( elementName ) != -1 )
			{
				if ( elementSet == null ) elementSet = new Array();
				elementSet[elementSet.length] = theElement;
			}
		}
		
		return elementSet;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FindElementSetByName( elementName )
	//////////////////////////////////////////////////////////////////////////////
	function FindElementSetByName( elementName )
	{
		var theForm = GetForm( arguments[1] );
		var nElements = theForm.elements.length;
		var elementSet = null;

		for ( var ii = 0; ii < nElements; ++ii )
		{
			var theElement = theForm.elements[ii];
			if ( theElement.name.indexOf( elementName ) != -1 )
			{
				if ( elementSet == null ) elementSet = new Array();
				elementSet[elementSet.length] = theElement;
			}
		}
		
		return elementSet;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	GetElementById( elementId )
	//////////////////////////////////////////////////////////////////////////////
	function GetElementById( elementId )
	{
		return document.getElementById( elementId );
	}


	//////////////////////////////////////////////////////////////////////////////
	//	GetElementByName( elementName )
	//////////////////////////////////////////////////////////////////////////////
	function GetElementByName( elementName )
	{
		var theForm = GetForm( arguments[1] );
		if ( Cfx.Js.IsDefined( theForm.elements[elementName] ) )
			return theForm.elements[elementName];

		return null;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	GetElementTerms
	//	
	//	Usage:
	//		GetElementTerms( argElement )
	//		GetElementTerms( argElement, splitChar )
	//////////////////////////////////////////////////////////////////////////////
	function GetElementTerms( argElement, splitChar )
	{
		var elementId = null;
		var elementTerms = null;

		// Assume default split character is underscore;
		if ( !Cfx.Js.IsDefined( splitChar ) )
			splitChar = "_";

		if ( Cfx.Js.IsObject( argElement ) )
			elementId = argElement.id;
		else if ( Cfx.Js.IsString( argElement ) )
			elementId = argElement;
		else
			throw new Error( "invalid element parameter" );

		// Perform string split if split character is not underscore.
		if ( splitChar != "_" )
			return thisElement.id.split( splitChar );
			
		// Split the element id with underscore as split character.
		while ( elementId != "" )
		{
			var results = elementId.match( /(_?[a-zA-Z\d]+_?)(\d+_?)?/ );
			if ( results != null )
			{
				var term = results[0];
				var termLen = term.length;
				if ( term.charAt( termLen - 1 ) == "_" )
					term = term.slice( 0, -1 );

				if ( elementTerms == null )
					elementTerms = new Array();

				elementTerms[elementTerms.length] = term;
				elementId = elementId.substr( termLen );
			}
		}

		return elementTerms;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FindImage( imageName )
	//////////////////////////////////////////////////////////////////////////////
	function FindImage( imageName )
	{
		var nImages = document.images.length;
		for( var ii = 0; ii < nImages; ++ii )
		{
			var theImage = document.images[ii];
			if ( theImage.id.indexOf( imageName ) != -1 )
				return theImage;
		}
		
		return null;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	FindImageSet( imageName )
	//////////////////////////////////////////////////////////////////////////////
	function FindImageSet( imageName )
	{
		var nImages = document.images.length;
		var images = document.images;
		var imageSet = null;

		for ( var ii = 0; ii < nImages; ++ii )
		{
			if ( ( images[ii].id != null ) && ( images[ii].id.indexOf( imageName ) != -1 ) )
			{
				if ( imageSet == null ) imageSet = new Array();
					imageSet[imageSet.length] = images[ii];
			}
		}

		return imageSet;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	GetImage( imageId )
	//////////////////////////////////////////////////////////////////////////////
	function GetImage( imageId )
	{
		var nImages = document.images.length;
		for( var ii = 0; ii < nImages; ++ii )
		{
			if ( Cfx.Js.IsDefined( document.images[imageId] ) )
				return document.images[imageId];
		}
		
		return null;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	GetForm( argForm )
	//////////////////////////////////////////////////////////////////////////////
	function GetForm( argForm )
	{
		var theForm = null;

		if ( !Cfx.Js.IsDefined( argForm ) || Cfx.Js.IsNull( argForm ) )
			theForm = document.forms[0];
		else if ( Cfx.Js.IsObject( argForm ) )
		{
			if ( argForm.className == "FORM" )
				theForm = argForm;
		}
		else if ( Cfx.Js.IsNumeric( argForm ) )
			theForm = document.forms[argForm];
		else if ( Cfs.Js.IsString( argForm ) )
		{
			for ( var ii = 0; ii < documents.forms.length; ++ii )
			{
				if ( documents.forms[ii].id == objForm )
				{
					theForm = documents.forms[ii];
					break;
				}
			}
		}

		// Assign class name if we have a form.
		if ( theForm != null )
			 theForm.className = "FORM";

		// Return result.
		return theForm;
	}


	//////////////////////////////////////////////////////////////////////////////
	//	PostBack
	//	
	//	Usage:
	//		PostBack()
	//		PostBack( formIndex )
	//		PostBack( formIndex, eventTarget )
	//		PostBack( formIndex, eventTarget, eventArgument )
	//		PostBack( eventTarget )
	//		PostBack( eventTarget, eventArgument )
	//	
	//////////////////////////////////////////////////////////////////////////////
	function PostBack()
	{
		var theForm = null;
		var eventTarget = null;
		var eventArgument = null;

		for ( var ii = 0; ii < arguments.length; ++ii )
		{
			if ( Cfx.Js.IsNumeric( arguments[ii] ) )
				theForm = Cfx.Dom.GetForm( arguments[0] );
			else if ( Cfx.Js.IsString( arguments[ii] ) )
			{
				if ( eventTarget == null )
					eventTarget = arguments[ii];
				else if ( eventArgument == null )
					eventArgument = arguments[ii];
				else
					throw new Error( "Invalid arguments" );
			}
			else
				throw new Error( "Invalid argument type" );
		}

		if ( theForm == null )
			theForm = Cfx.Dom.GetForm();

		if ( eventTarget == null )
			eventTarget = "";

		if ( eventArgument == null )
			eventArgument = "";

		if ( Cfx.Js.IsDefined( theForm.__EVENTTARGET ) )
			theForm.__EVENTARGET.value = eventTarget.split("$").join(":");

		if ( Cfx.Js.IsDefined( theForm.__EVENTARGUMENT ) )
			theForm.__EVENTARGUMENT.value = eventArgument;

		// Submit the form.
		theForm.submit();
	}
}		

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions