//Défintion des NS intermédiaires : fr.stcsystems.libs.commons.lang.js.js_extend
if (fr == 'undefined' || fr == null){var fr = new Object();}
if (fr.stcsystems == 'undefined' || fr.stcsystems == null){fr.stcsystems = new Object();}
if (fr.stcsystems.libs == 'undefined' || fr.stcsystems.libs == null){fr.stcsystems.libs = new Object();}
if (fr.stcsystems.libs.commons == 'undefined' || fr.stcsystems.libs.commons == null){fr.stcsystems.libs.commons = new Object();}
if (fr.stcsystems.libs.commons.lang == 'undefined' || fr.stcsystems.libs.commons.lang == null){fr.stcsystems.libs.commons.lang = new Object();}
if (fr.stcsystems.libs.commons.lang.js == 'undefined' || fr.stcsystems.libs.commons.lang.js == null){fr.stcsystems.libs.commons.lang.js = new Object();}
if (fr.stcsystems.libs.commons.lang.js.js_extend == 'undefined' || fr.stcsystems.libs.commons.lang.js.js_extend == null){fr.stcsystems.libs.commons.lang.js.js_extend = new Object();}


//Contenu du fichier
// Extending JS capabilities for STC Commons JS Framework

// Function
/*Function.prototype.extends_2 = function(parent){		
	var FN = this;
	if(arguments.length > 1){
		parent = Function.prototype.extends.apply(parent,[].slice.call(arguments,1));
	}
	
	var newFN = function(){
		parent.apply(this, arguments);
		this.__super = this.__super ? {__super:this.__super} : {};
		for(var i in this){
			if(typeof this[i] == "function"){
				this.__super[i] = this[i];
			}
		}
		return FN.apply(this, arguments);
	};
 
	var proto = function(){};
	proto.prototype = parent.prototype;
	newFN.prototype = new proto();

	for(var i in FN.prototype){
		newFN.prototype[i] = FN.prototype[i];
	}

	// copie des statiques parents
	for(var i in parent){
		newFN[i] = parent[i];
	}
	
	// copie(+ecrase) des statiques nouveau
	for(var i in FN){
		newFN[i] = FN[i];
	}

	newFN.__PARENT = parent;
	return newFN;
}*/

/*
Extend, code de Willpower - forum Developpez.net
http://www.developpez.net/forums/d1121186/webmasters-developpement-web/javascript/oo-implementation-lheritage-dappels-super/
Le travail a pris un peu moins de 2 mois pour obtenir un élément fonctionnel d'implémentation de certains principes de l'OO sur javascript.
Merci à tous les participants pour leur aide et leur tenacité.
*/
Function.prototype.Extends = function (FN) {
    var parent = this;
	// crée une nouvelle fonction qui exécutera la parente, sauvegardera ses champs dans __super puis exécutera la fonction enfant
    var newFN = function () {
			// applique la fonction parente
            parent.apply(this, arguments);
 
            // Gestion de super
            this.__super = this.__super ? {
                __super: this.__super
            } : {};
 
            // sauvegarde de l'instance courante
            var that = this;
 
            // sauvegarde des fonctions parentes
            for (var i in this) {
                if (typeof this[i] == "function") {
					// exécute une fonction anonyme pour sauvergarder this[i] dans this.__super[i]
                    this.__super[i] = (function (f) {
                        // si la fonction original à déjà été surchargé en imposant le this alors on ne fait rien
                        if (f.__original) return f;
                        // creation d'une nouvelle fonction identique à celle du parent mais qui sera appliqué sur l'objet "that", donc la bonne instance
                        var s = function () {
                            return f.apply(that, arguments);
                        };
                        // copie des statiques de la méthode parente "f" dans la nouvelle méthode "s"
                        for (var i in f) {
                            s[i] = f[i];
                        }
                        // on sauvergarde la fonction originale f dans la nouvelle s
                        s.__original = f;
                        // renvoie à "this.__super[i]" la nouvelle méthode "s"
                        return s;
                    })(this[i]);
                }
            }
			// applique la fonction enfant
            return FN.apply(this, arguments);
        };
 
	// attribution du prototype parent à la nouvelle fonction => (instanceof parent == true && instanceof newFN == true)
    var proto = function () {};
    proto.prototype = parent.prototype;
    newFN.prototype = new proto();
 
	// copie des prototypes enfants sur la nouvelle fonction
    for (var i in FN.prototype) {
        newFN.prototype[i] = FN.prototype[i];
    }
 
    // copie des statiques parents
    for (var i in parent) {
        newFN[i] = parent[i];
    }
 
    // copie(+ecrase) des statiques nouveau
    for (var i in FN) {
        newFN[i] = FN[i];
    }
 
    // definition de Super
    newFN.prototype.Super = function (level) {
        var caller = arguments.callee.caller;
        var superieur = this.Self().__super;
		while(--level && superieur)
			superieur = superieur.__super;
		return superieur;
    };
 
	// definition de Self
    newFN.prototype.Self = function () {
        var caller = arguments.callee.caller;
        // si le caller est "super" alors notre fonction "caller" et le caller de "super".
        if (caller == newFN.prototype.Super) 
			caller = caller.caller; 
        var instance = null;
        // vérifie si la fonction "caller" appartient au "this" dans quel cas nous sommes dans une méthode de la dernière classe instanciée (enfant le plus bas)
        for (var i in this)
        if (this[i] == caller) instance = this;
        // sinon on parcours la récursion des objets "__super" pour trouver à quel niveau se trouve la fonction appelante(caller) et retourner l'objet "__super" correspondant.
        for (var obj = this; obj; obj = obj.__super) {
			// pour chaque élément des objets
            for (var i in obj)
				// si la fonction original est notre caller
				if (obj[i].__original != null && obj[i].__original == caller) 
					instance = obj;
        }
		// on retourne la plus haute instance contenant notre méthode appelante 
        return instance;
    };
 
    newFN.__PARENT = parent;
    return newFN;
}

Function.prototype.nEw = function (){
	var instance = new this ();
	instance.__construct.apply(instance, arguments);
	
	return instance;
}

Function.prototype.parent = function(){
	// retourne la classe parente de la classe(fonction/constructeur)
	return this.__PARENT;
}

