var jsclassmanager = new function(){
var pending = [];
this.setThisArg = function(thisArg,func){
var newProp = function(){
func.apply(thisArg,arguments);
};
newProp.isThisWrapped = true;
return newProp;
}
this.construct = function(){
var className = arguments.shift();
//within this code block, 'this' refers to the new instance being created
var parent = window[className].prototype;
var hierarchy = [];
while ((typeof parent)=='function'){
hierarchy.push(parent);
if ('parent' in parent){
parent = parent.parent;
}
}
hierarchy.reverse();
for (clazz in hierarchy){
clazz.apply(this,arguments);
}
window[className].apply(this,arguments);
for (var propName in this){
var oldProp = this[propName];
if ((typeof oldProp)==typeof(function(){})){
var newProp = manager.setThisArg(this,oldProp);
this[propName] = newProp;
}
}
}
/** closure is a function, not an object.
* ie, in this sample code, closure is a function
* var closure = function(){};
* and in this sample code, instance is an object
* var instance = new closure();
* The first example (closure) is what should be passed in
*/
this.Class = function(className,instanceClosure,staticClosure){
var constructor = function(){
var className = this.className;
var func = window[this.className];
if (func==undefined){
console.log(this.className);
} else if ('prototype' in func
&&'parent' in func.prototype
&&typeof func.prototype.parent == typeof 'string'){
var parentClassName = func.prototype.parent
parent = window[parentClassName];
this.className = parentClassName;
parent.apply(this,[]);
this.className = className;
var parentObj = new function(){};
manager.apply(parentObj,this);
parentObj.className = func.prototype.parent;
this.parent = parentObj;
}
func.instance.apply(this,[]);
if (typeof this.parent==typeof 'string'){
this.parent = undefined;
}
if ('construct' in this &&typeof this.construct == typeof function(){}){
this.construct.apply(this,arguments);
}
};
constructor.prototype.className = className;
constructor.instance = instanceClosure;
//static extend
constructor.Extend = function(className){
constructor.prototype.parent = className;
}
if (typeof staticClosure == typeof constructor)
manager.apply(constructor,new staticClosure());
window[className] = constructor;
return constructor;
}
this.apply = function(object,instantiatedFunction){
for (var propName in instantiatedFunction){
if (propName in object){
console.log('yes');
if (!('parent' in object)||object.parent==null)object.parent = function(){};
object.parent[propName] = instantiatedFunction[propName];
} else {
object[propName] = instantiatedFunction[propName];
}
}
}
this.setThisRecursive = function(thisArg,fromObject){
for (propName in fromObject){
if ((typeof fromObject[propName]) === (typeof new function(){})){
manager.setThisRecursive(thisArg,fromObject[propName]);
// console.log('recursive thisify '+propName+ ' which has type '+(typeof fromObject[propName]));
} else if ((typeof fromObject[propName]) === (typeof function(){})){
// console.log('thisify '+propName);
fromObject[propName] = manager.setThisArg(thisArg,fromObject[propName]);
} else {
// console.log('no thisify '+propName+ ' which has type '+(typeof fromObject[propName]));
}
}
}
this.override = function(child,parent,thisArg){
for (propName in parent){
//console.log('propName is type: '+typeof parent[propName]);
// console.log('setRaw for '+propName+' with type '+typeof parent[propName]);
child[propName] = parent[propName];
if (typeof child[propName]=== (typeof new function(){}) ){
console.log('setFunc', 'also');
manager.setThisRecursive(thisArg,child[propName]);
}
}
child.parent = parent;
}
this.setClasses = function(rootElement) {
if (rootElement==null)rootElement = document.body;
var elementList = rootElement.getElementsByClassName('jdom');
var funcType = typeof new function() {};
if (elementList.length==0)return;
for (var i = 0; i < elementList.length; i++) {
var element = elementList[i];
var parts = element.className.split("jdom")[1].trim();
var clazz = parts.split(" ")[0];
if (clazz in window)
var newInstance = new window[clazz]();
else {
console.log("Error: class " + clazz + " is not defined");
return;
}
manager.override(element, newInstance, element);
if ('attach' in element &&
typeof element['attach'] == typeof
function() {})
element.attach();
}
manager.setClasses();
}
}
if (window.loaded == 'complete'){
manager.setClasses();
} else if (window.addEventListener != null){
document.addEventListener('DOMContentLoaded',function(){
manager.setClasses();
});
} else {
var oldLoad = window.onload;
window.onload = function(){
if (oldLoad!=null)oldLoad();
manager.setClasses();
}
}