/*______________ | ______ | U I Z E J A V A S C R I P T F R A M E W O R K | / / | --------------------------------------------------- | / O / | MODULE : Uize.Util.Oop Package | / / / | | / / / /| | ONLINE : http://www.uize.com | /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE | /___ | LICENSE : Available under MIT License or GNU General Public License |_______________| http://www.uize.com/license.html */ /* Module Meta Data type: Class importance: 7 codeCompleteness: 80 testCompleteness: 0 docCompleteness: 10 */ /*? Introduction The =Uize.Util.Oop= package provides convenience methods for... *DEVELOPERS:* `Chris van Rensburg` */ Uize.module ({ name:'Uize.Util.Oop', builder:function () { /*** Variables for Scruncher Optimization ***/ var _package = function () {}, _undefined, _isFunction = Uize.isFunction ; /*** General Variables ***/ var _sacredEmptyArray = [], _typicalPackageFunction = function () {}, _implicitMethodNames = {toString:1,valueOf:1} ; /*** Public Static Methods ***/ _package.getFeatures = function (_instanceOrClass) { var _class = _package.resolveToClass (_instanceOrClass), _features = [] ; if (_class) { function _getFeaturesForContext (_contextName) { var _contextIsSetGet = _contextName == 'state', _context = _contextIsSetGet ? _class.get () : _contextName == 'instance' ? _class.prototype : _class, _featureNamePrefix = _contextName == 'static' ? _package.getClassName (_class) + '.' : '', _contextNameCapped = Uize.capFirstChar (_contextName), _propertyValue, _featureIsPublic ; for (var _propertyName in _context) (_featureIsPublic = _propertyName.indexOf ('_') < 0) && _features.push ( Uize.copyInto ( _package.getFeatureInfo (_class,_contextName,_propertyName), { name:_featureNamePrefix + _propertyName, shortName:_propertyName, access:_featureIsPublic ? 'Public' : 'Private', context:_contextNameCapped, type:_contextIsSetGet || !_isFunction (_propertyValue = _context [_propertyName]) ? 'Property' : typeof _propertyValue.moduleName == 'string' ? 'Module' : 'Method' } ) ) ; } _getFeaturesForContext ('instance'); _getFeaturesForContext ('static'); _package.isUizeClass (_class) && _getFeaturesForContext ('state'); /*** sort the features by the keys: access, context, type, name ***/ function _compareTwo (_valueA,_valueB) { return _valueA < _valueB ? -1 : _valueA > _valueB ? 1 : 0; } _features.sort ( function (_featureA,_featureB) { return ( _compareTwo (_featureA.access,_featureB.access) || _compareTwo (_featureA.context,_featureB.context) || _compareTwo (_featureA.type,_featureB.type) || _compareTwo (_featureA.name,_featureB.name) ); } ); } return _features; /*? Static Methods Uize.Util.Oop.getFeatures Returns an array, representing all of the features that can be automatically detected from the specified class (or the class of the specified instance). SYNTAX ............................................................... featuresARRAY = Uize.Util.Oop.getFeatures (instanceOrClassOBJ); ............................................................... Each element of the array returned by the =Uize.Util.Oop.getFeatures= method is an object that describes an individual feature, as would be returned by the related =Uize.Util.Oop.getFeatureInfo= static method. NOTES - see the related =Uize.Util.Oop.getFeatureInfo= static method */ }; _package.inheritsFrom = function (_testInstanceOrClass,_baseInstanceOrClass) { if (_baseInstanceOrClass == _undefined) return _testInstanceOrClass == _undefined; if (_testInstanceOrClass == _undefined) return _baseInstanceOrClass == Object; var _testClass = _isClass (_testInstanceOrClass) ? _testInstanceOrClass : _testInstanceOrClass.constructor, _baseClass = _isClass (_baseInstanceOrClass) ? _baseInstanceOrClass : _baseInstanceOrClass.constructor ; while (_testClass != _baseClass && _isFunction (_testClass = _testClass.superclass)); return _testClass == _baseClass; }; var _isClass = _package.isClass = function (_object) { return ( _object != _undefined && ( _isFunction (_object) || ( typeof _object == 'object' && !_object.constructor /* NOTE: In Internet Explorer, certain DOM object "classes" like HTMLBodyElement are reported as object, rather than function, and the value of their constructor property is undefined. Normally, the value of the constructor property for a non-null object is the constructor function for that object. In the case of the document.body element in IE, the constructor is a reference to HTMLBodyElement. That's all fine and good, but HTMLBodyElement is not a function. Instead, it's an object, whose constructor is undefined. We use this as an indication that the object is really a "class", until a better test is worked out. */ ) ) ); }; _package.isPackage = function (_object) { if (!_isClass (_object)) return false; /*** object must be a function / constructor, so check to see if function has code ***/ var _objectToString = _object.toString, _typicalPackageFunctionToString = _typicalPackageFunction.toString, _toStringOverridden = _objectToString != _typicalPackageFunctionToString ; if (_toStringOverridden) delete _object.toString ; var _hasAnyConstruction = _object.toString () != _typicalPackageFunction.toString (); if (_toStringOverridden) _object.toString = _objectToString ; if (_hasAnyConstruction) return false; /*** check to see if function's prototype has anything beyond what's in typical package function ***/ var _objectPrototype = _object.prototype, _typicalPackageFunctionPrototype = _typicalPackageFunction.prototype ; for (var _propertyName in _objectPrototype) if ( !_implicitMethodNames [_propertyName] && ( !(_propertyName in _typicalPackageFunctionPrototype) || _objectPrototype [_propertyName] != _typicalPackageFunctionPrototype [_propertyName] ) ) return false ; return true; }; _package.isUizeClass = function (_object) { return ( _isClass (_object) && _isFunction (_object.subclass) && _isFunction (_object.superclass) && _isFunction (_object.set) && _isFunction (_object.get) ); }; _package.isUizeClassInstance = function (_value) { return Uize.isObject (_value) && _package.isUizeClass (_value.constructor); }; _package.getClassName = function (_class) { return ( (_class != _undefined && _class.moduleName) || ( ( (_class + '').match ( typeof _class == 'object' ? /\[object\s+([^\]]+)\]/ : /^\s*function\s+([^\(]+)\s*\(/ ) || _sacredEmptyArray ) [1] ) || '' ); }; _package.getFeatureInfo = function (_class,_contextName,_featureName) { function _returnClass () {return _class} function _returnPrototype () {return _class.prototype} function _returnSetGetProperties () {return _class.get ()} var _isInstanceFeature = _contextName == 'instance', _isSetGetFeature = !_isInstanceFeature && _contextName == 'state', _getFeatureContext = _isInstanceFeature ? _returnPrototype : _isSetGetFeature ? _returnSetGetProperties : _returnClass, _feature = _getFeatureContext () [_featureName], _featureContext, _introducedIn = _class, _overriddenIn = _class ; while ( (_class = _class.superclass) && _class.superclass && // ignore the stub superclass of the Uize base class (_featureContext = _getFeatureContext ()) && _featureName in _featureContext ) { if (_introducedIn == _overriddenIn && _featureContext [_featureName] == _feature) _overriddenIn = _class ; _introducedIn = _class; } return {introducedIn:_introducedIn,overriddenIn:_overriddenIn}; /*? Static Methods Uize.Util.Oop.getFeatureInfo SYNTAX ................................................................................... featureInfoOBJ = Uize.Util.Oop.getFeatureInfo (classOBJ,contextSTR,featureNameSTR); ................................................................................... FEATURE INFO OBJECT ......................... name : nameSTR, shortName : shortNameSTR, access : accessSTR, context : contextSTR, type : typeSTR ......................... Properties of the feature object... - *name* - - *shortName* - - *access* - - *context* - - *type* - NOTES - see the related =Uize.Util.Oop.getFeatures= static method */ }; _package.getInheritanceChain = function (_class) { var _inheritanceChain = []; if (_package.isUizeClass (_class)) { var _superclass = _class; while (_superclass.moduleName) { _inheritanceChain.unshift (_superclass); _superclass = _superclass.superclass; } } return _inheritanceChain; }; _package.resolveToClass = function (_instanceOrClass) { return ( _instanceOrClass == _undefined || _isFunction (_instanceOrClass) ? _instanceOrClass || _undefined : _instanceOrClass.constructor ); }; return _package; } });