Contenido

Crea tu propio framework javascript

28 sep

+ 58

El uso de frameworks Javascript aporta muchas ventajas al desarrollo web, facilidad de uso, estandarización, cross-browsing, … pero estas ventajas nos hacer perder el control y el conocimiento del código, sin contar con la carga de funcionalidades extras que no llegamos a usar.

Por estos motivos, llevo ya tiempo pensando en montar un framework Javascript que cubra mis necesidades, algo ligero y completo que me permita tener el completo control sobre el javascript que desarrollo.

Franki.js

Vamos a ver como montar tu propio framework javascript, montando las funciones básicas para posteriormente ir añadiendo las que necesitemos sin alterar el resto del framework.

Franki.js es un nombre que creo le viene que ni pintado, ya que nos vamos a nutrir de trozos de otros scripts con los que montaremos nuestra criatura. Nos sentiremos con el Dr. Frankenstein creando a su criatura :D

var franki = {
   .. opciones ..
};

Extendiendo

La clave de los frameworks Javascript es sin duda la capacidad de extender elementos y así añadir nuevas funcionalidades a los elementos DOM con los que generalmente trabajamos. La función que es capaz de extender cualquier elemento es realmente sencilla, pero a la vez realmente poderosa.

extend: function(el, opt){
        for (var name in opt) el[name] = opt[name];
        return el;
 },
// Ejemplo
franki.extend(document.getElementById("logo"), {option: 'nueva propiedad'});

Como podemos ver, esta función recibe 2 parámetros, el elemento  que queremos extender y las opciones que queremos añadir a dicho elemento.

Recogiendo elementos

La función que usamos más en nuestros scripts es sin duda document.getElementById(); y evidentemente tenemos que reducir el número de letras que hemos de teclear para obtener un elemento pasándole un ID.

get: function(id){
        return franki.extend(document.getElementById(id), franki);
},
// Ejemplo
franki.get("logo);

Aprovechando que ya disponemos de extend() devolvemos el elemento extendido con las propiedades que franki.js va a incorporar.

Esta función no hace nada especial, aunque puede extenderse fácilmente con todas las posibilidades que javascript nos ofrece.

Creando e Insercción de Elementos

La creación de elementos DOM es otra funcionalidad que usamos considerablemente en nuestros scripts, por lo que es realmente necesario enmascarar la función document.createElement();

 create: function(type){
        return franki.extend(document.createElement(type), franki);
  },
// Ejemplo
var newDiv = franki.create("div");

insert: function(what) {
        return this.appendChild(what);
},
// Ejemplo
franki.get("logo).insert(newDiv);

Seguimos devolviendo el elemento extendido con las propiedades que poco a poco a ir haciendo crecer.

Atributos y Estilos

Los elementos que hemos extendido, necesitan tener la capacidad de devolver y modificar los atributos y estilos que los componen, para ello crearemos 2 funciones más.

css: function(name, value) {
        if (!value) return this.style[name];
        this.style[name] = value;
        return this;
},
// Ejemplo
var oldBorder = franki.get("logo").css("border");
franki.get("logo").css("border", "1px red solid");

attr: function(name, value) {
        if (!value) return this.getAttribute(name);
        this.setAttribute(name, value);
        return this;
},
// Ejemplo
var oldSrc = franki.get("logo").attr("src");
franki.get("logo").attr("src", "NUEVO_SRC");

Como vemos, disponemos de 2 nuevas propiedades que automáticamente se añadirán a los elementos con los que trabajemos.

Gestión de eventos

Los eventos asociados a los elementos es algo que por comodidad y por compatibilidad con navegadores podemos aprovechar para incluir en nuestro framework.

 addEvent: function(type, fn ) {
      if ( this.attachEvent ) {
        this['e'+type+fn] = fn;
        this[type+fn] = function(){this['e'+type+fn]( window.event );}
        this.attachEvent( 'on'+type, this[type+fn] );
      } else
        this.addEventListener( type, fn, false );
return this;
    },
// Ejemplo
franki.get("logo").addEvent("click", function(){ alert("Click");});

removeEvent: function(type, fn ) {
      if ( this.detachEvent ) {
        this.detachEvent( 'on'+type, this[type+fn] );
        this[type+fn] = null;
      } else
        this.removeEventListener( type, fn, false );
return this;
    },
// Ejemplo
franki.get("logo").removeEvent("click", function(){ alert("Click");});

Estas funciones, sacadas de este post de John Resig, nos sirven para poder trabajar perfectamente con nuestros elementos, aunque podríamos optar por la última revisión de Incoherence Babble.

Encadenamiento

Algo que siempre me ha gustado de los frameworks javascript actuales es la posibilidad de encadenar funcionalidades en la misma línea. Esto además de ayudarte a reducir el peso de nuestros scripts ayuda (a mi por lo menos) a ver más claro el código que estas escribiendo.

La clave de nuestro framework para poder encadenar funcionalidades es SIEMPRE devolver el elemento con el que estamos trabajando. Si nos fijamos en las funciones anteriores, nos devuelven el elemento que estamos usando. De esta forma podemos conseguir cosas como estas.

franki.get("logo").css("border", "2px red solid").addEvent("mouseover", function(){alert("MouseOver");});

Últimos retoques

Necesitamos un alias para evitar la llamada franki.get(), que es la base del framework. Por ello podemos optar por el famoso $(), o cualquier otra combinación que nos guste o nos vaya bien.

window.get = el.get;
get("logo").css("border", "2px red solid");

Aclaraciones

Las funciones son muy básicas y únicamente son para que sirvan de ejemplo de por donde empezar a construir tu propio framework, las posibilidades de extensión son infinitas.

El código

Veamos como quedaría todo juntito :D

var franki = {
    get: function(id){
        return franki.extend(document.getElementById(id), franki);
    },
    extend: function(el, opt){
        for (var name in opt) el[name] = opt[name];
        return el;
    },
    create: function(type){
        return this.extend(document.createElement(type));
    },
    insert: function(what) {
        return this.appendChild(what);
    },
    css: function(name, value) {
        if (!value) return this.style[name];
        this.style[name] = value;
        return this;
    },
    attr: function(name, value) {
        if (!value) return this.getAttribute(name);
        this.setAttribute(name, value);
        return this;
    },
    addEvent: function(type, fn ) {
      if ( this.attachEvent ) {
        this['e'+type+fn] = fn;
        this[type+fn] = function(){this['e'+type+fn]( window.event );}
        this.attachEvent( 'on'+type, this[type+fn] );
      } else
        this.addEventListener( type, fn, false );
    return this;
    },
    removeEvent: function(type, fn ) {
      if ( this.detachEvent ) {
        this.detachEvent( 'on'+type, this[type+fn] );
        this[type+fn] = null;
      } else
        this.removeEventListener( type, fn, false );
    return this;
    }
};
// Alias
window.$ = franki.get;

Promoción

¿Has usado este post para crear tu propio framework? Pues usalo tambien para promocionarlo, usa los comentarios, evitar pegar el código, mejor usar un enlace algún lugar donde ver el código/ejemplos/tutoriales/…

Mejoras

Jose nos comenta el problema que puede provocar que franki disponga de métodos públicos a los que podrían acceder externamente provocando errores al acceder al elemento this.

franki.css("border", "1px red solid");
// --> Error

Este ejemplo nos arrojaría un error al detectar que this (franki) no dispone de las propiedades própias de un HTMLElement, por ese momento Jose nos propone un sistema para sacar lo métodos de franki, haciéndolos privados e innaccesibles desde fuera.

var franki = (function(){
    var metodosExtendidos = {
    get: function(id){
        return franki.extend(document.getElementById(id), franki);
    },
    extend: function(el, opt){
        for (var name in opt) el[name] = opt[name];
        return el;
    },
    create: function(type){
        return this.extend(document.createElemen(type));
    },
    insert: function(what) {
        return this.appendChild(what);
    },
    css: function(name, value) {
        if (!value) return this.style[name];
        this.style[name] = value;
        return this;
    },
    attr: function(name, value) {
        if (!value) return this.getAttribute(name);
        this.setAttribute(name, value);
        return this;
    },
    addEvent: function(type, fn ) {
      if ( this.attachEvent ) {
        this['e'+type+fn] = fn;
        var oThis = this;
        this[type+fn] = function(){oThis['e'+type+fn]( window.event );}
        this.attachEvent( 'on'+type, this[type+fn] );
      } else
        this.addEventListener( type, fn, false );
    return this;
    },
    removeEvent: function(type, fn ) {
      if ( this.detachEvent ) {
        this.detachEvent( 'on'+type, this[type+fn] );
        this[type+fn] = null;
      } else
        this.removeEventListener( type, fn, false );
    return this;
    }
};

    return {
       extend: function(el, opt){
         for (var name in opt) el[name] = opt[name];
         return el;
       },
       get: function(id){
               return franki.extend(document.getElementById(id), metodosExtendidos);
       }
    };
}());

Como podemos ver la variable metodosExtendidos se convierte en privada y es la usada en la función get() para extender el elemento que queremos usar.

Gracias Jose por la corrección, no había pensado en esa posibilidad.

  • Me he quedado alucinado, genial, a pesar de ser un simple y pequeño framework está escrito con mucha elegancia y extensibilidad.

    Voy a pensar en hacerme uno, añadiria metodos para seleccionar por clase y por nombre del tag.

  • :o, genial Andrés, alucinante, muy buen tutorial, me voy a crear el mio propio, paso a paso; aun no conozco mucho javascipt, pero halgo pataleo con el, seria genial que siguieras extendiendo este tutorial. Mil gracias, y enhorabuena ;)

  • No está nada mal para empezar un framework por nuestra cuenta, muy buen post. Me pregunto qué haríamos con funciones símplemente operativas (obtener el máximo de un array de números; la típica función para hallar un número aleatorio entre a y b; o la función trim(), por ejemplo.

    ¿Dónde escribiríamos esas funciones? ¿Necesitaríamos otro objeto como franki? (Podríamos extender los que ya nos da javascript: Array, String, Math…)

  • Hay un par de cuestiones que me gustaría comentarte:

    1. ¿Puede ser que haya una errata en el siguiente fragmento?

    var franki = {
        ...
        create: function(type){
            return this.extend(document.createElemen(type));
        },
        ...
    }

    Me da la impresión de que debería ser

    var franki = {
        ...
        create: function(type){
            return document.createElemen(type);
        },
        ...
    }

    2. Franki tiene “métodos ilegítimos”, métodos que si son invocados sobre franki darán un error: create, insert, css, attr,addEvent, removeEvent. Estas funciones actuarán sobre un this que debe ser HTMLElement y franki no lo es. Dichas funciones están pensadas para ser transferidas a HTMLElements mediante la función franki.extends o franki.get.

    Esto podría evitarse mediante la aplicación del ‘Module pattern’ para encapsular los métodos extendidos de manera que no sean métodos de franki.

    Este sería el esquema:

    var franki = (function(){
        var metodosExtendidos = {
           create: function(tag){
              return document.createElemen(tag);
           },
           insert: function(what) {
              return this.appendChild(what);
           },
           css: function(name, value) {
              ...
           },
           attr: function(name, value) {
              ...
           },
           addEvent: function(type, fn ) {
             ...
           }, 
           removeEvent: function(type, fn ) {
             ...
           }
        };
    
        return {
           extend: function(el, opt){
             for (var name in opt) el[name] = opt[name];
             return el;
           },
           get: function(id){
                   return franki.extend(document.getElementById(id), metodosExtendidos);
           }
        };
    }());
    
    // Alias
    window.$ = franki.get;
    

    De esta manera franki únicamente sería portador de las funciones get y extends.

    Un saludo.

  • Un gran trabajo!! Se hace obvio que una de las pegas de los frameworks es su gran peso y a veces los utilizamos para realizar pequeñas tareas como las que puede hacer franky!!

    Enhorabuena Andrés! (y gracias Jose)

  • Estupendo, cuando no tu Andrés dandonos estos tutoriales y mas a los novatos en javascipt, como son las cosas cuando aprendi php ni lo vi a javascript ya que en su tiempo no se usaba para las validaciones ya que el usuario puede desactivar el javascript pero ahora todo cambio, bueno vamos a practicar con tu framework para ir aprendiendo y a ver si creo algo jeej, un saludooooooo

  • Otro framework!!!? ¿Pero es que no hay bastantes ya, hombre?

    Y por qué no desarrollar en base a lo que hay ya hecho, plugins de jQuery por poner un ejemplo.

  • He detectado un error en el método addEvent para IE6. No sé cómo pegar código exactamente pero ahí va:

    
    addEvent: function(type, fn ) {
      if ( this.attachEvent ) {
    	this['e'+type+fn] = fn;
    	var oThis = this;				// Closure porque this en la siguiente función era un objeto franki, no un HTMLElement.
    	this[type+fn] = function(){ 
    		oThis['e'+type+fn]( window.event );
    	}
    	this.attachEvent( 'on'+type, this[type+fn] );
      } else
    	this.addEventListener( type, fn, false );
    return this;
    }
    

    Espero que salga bien :-S. Así me ha funcionado en IE6.

    Un saludo y sigue así.

  • @derkeNuke: Ha salido perfecto, gracias.

    Ya está corregido.

  • Creo que te has dejado la línea:
    this['e'+type+fn] = fn;
    ;-)

  • He añadido algun extra al framework:

    – hasClass: si existe una clase
    – addClass: añadir una clase
    – removeClass: quitar una clase
    – makeArgumetsToArray: para comvertir el objeto arguments dentro de la funcion en array
    – delegate: para delegar eventos en un padre superior, podeis ver un ejemplo demo

    aqui podeis ver la demo y el enlace a la version modificada: http://beta.wigbee.com/franki/franki.html

  • jdeveloper, me ha gustado ver un hasClass sin RegExp.

    Parece que Franki va cobrando vida. Propongo cambiar el viejo addEvent de Resig por uno más ‘actual’ y más clarito. ¿Queremos que se encargue de ajustar el this para IE?

  • @Jose Bua, casi nunca me acuerdo de que existe RegEx, supongo que mi solución es menos óptima.

    Oye, anie2k, porque no abres una cuenta svn o git o lo que sea y asi se puede participar entre varios, haz algun plan de los features que quieres, el framework a mi me mola mucho.

  • Está increíble….¿Cómo podrías agregarle un evento domready, tipo mootools?

  • Oye Andrés, en la propuesta de José… “create” no debería ir también afuera? junto con get y extend……es pregunta…

  • @Daniel Niquet: Podría ir ahí aunque tendría una funcionalidad diferente. El que vaya dentro, en metodosExtendidos es por que hacen referencia a elementos HTML y extenderán este tipo de elementos. El método get() y extend() son funciones ajenas a los elementos HTML y que le dan al objeto franki la capacidad de devolver un objeto y extenderlo.

  • jdeveloper, me parece refrescante ver algo que use expresiones regulares (no había ironía)

    Andrés, ¿te importaría agregarme al proyecto?

    Insisto en el tema de antes y añado algo más:¿queremos que ‘addListener’ ajuste el this para IE?¿lo preparamos para que evite las leaks en IE?

  • Correción:

    jdeveloper, me parece refrescante ver algo que no use expresiones regulares (no había ironía)

  • He añadido algun extra

    getElementByClassName (version 2008)

    Esta modificada la ultima linea de la version 2008, que lo que hace es devolver un objeto que contiene los metodos de metodosExtendidos que si se llamanan se invocan uno a uno en los objetos de array que devolvia la funcion original tal cual.

    Ahora puedes hacer franki.getElementsByClassName(claseSeleccion).addClass(clase)

    De forma similiar puedes hacer un addEvent

    la modificación al getElementByClassName es solo en el retorno (la ultima linea):

    return ExtendedColection(getElementsByClassName(className, tag, elm));

    Extended colection seria del siguiente modo:

    var ExtendedColection=function(arr){
    	for(var i=0;i<arr.length;i++)
    		arr[i]=franki.extend(arr[i],metodosExtendidos);

    //con el fin de no tener que mapear todas los métodos que vamos añadiendo a metodosExtendidos lo hacemos dinamicamente

    objColection={};
    	
    	for(prop in metodosExtendidos){
    		(function(_prop){
    			objColection[_prop]=function(){
    				for(var i=0;i<arr.length;i++)
    					metodosExtendidos[_prop].apply(arr[i],arguments);
    				return this;
    			}
    		})(prop);
    	}
    	return objColection;
    };

    podéis ver un ejemplo en: http://beta.wigbee.com/franki/franki.html y descargar las fuentes

    anieto2k siento que aun no use el repositorio de google, espero que puedas hacer un merge cómodamente, descarte el js que tiene el enlace en la pag.

    Realmente mucho mas no le falta para que no se vuelva demasiado pesado, un poco de ajax xD

    PD: perdona que no sepa colorear el código

  • @jdeveloper: Yo he hecho unos cambios, los puedes ver aqui
    http://www.anieto2k.com/demo/franki/franki.js

    He quitado la función ExtendedColection ya que he modificado la función getClassName para adaptarla a franki.

    Ahora tenemos 2 getClassName().

    1) Para el objeto franki:

    franki.getClassName("hola");

    2) Para los objetos extendidos:

    franki.get("content").getClassName("hola");

    Además he modificado (de una forma muy rudimentaria, solo para ver si funcionaba) la función get() que ahora permite hacer cosas como estas.

    
    franki.get("content"); // Por IDs
    franki.get(document.body); // Por objetos
    franki.get(".hola"); // Por class (solo controla el carácter 0 == '.').
    
    

    Saludos

  • Que interesante idea, para los que llegamos tarde a los frameworks js poder ver como se crea uno es una gran ayuda para entender el código.

    Me bajé el codigo de googlecode y tiene un par de llamadas a console.log (firebug supongo ) que daran errores en los navegadores que no tengan firebug o firelite.

    saludos y gran trabajo

  • Excelente trabajo!!!
    Coincido con José: hay que cambiar ese addEvent, hasta Jhon Resig está de acuerdo en que no sirve: http://my.opera.com/hallvors/blog/2007/03/28/a-problem-with-john-resigs-addevent

    Algo así sería mejor:

    
    addEvent: function(type, fn ) {
    		if ( this.addEventListener ) {
    			this.addEventListener( type, fn, false );
    			return this;
    		}
    		else if(this.attachEvent){
    		var f=fn.call(this,window.event);
    		this.attachEvent( 'on'+type, f);
    		return this;
    		}else{
    			this['on'+type]=fn;
    			return this;
    		}
    	},

    (No olvidemos que addEvent también funciona en Ópera y no es bueno darlo como primera opción).
    Con respecto a la prevención de memory leak en Explorer 6, mi opinión es que convendría dejarla fuera.

  • @anieto2k, me gusta más tu versión, de todos modos, he visto tu codigo por encima y, igual me equivoco, pero cuando seleccionando por clase, devuelve un array, no pudes llamar a un metodo y que llame a en cada objeto del array al metodo con el mismo nombre, me explico:

    franki.get('.clasedestino').addClass('clasenueva');

    que añadiria a todos los elementos de clase ‘clasedestino‘ la clase ‘clasenueva‘.

    He vuelto a modificar la funcion get de forma que ahora se selecciona parecido a jquery:

    #id (equivale al getElementById
    tag (equivale al getElementsByTagName)
    .clase (selecciona los elementos de las clase especificaga
    tag.clase (selecciona los tags especificado que contengan la clase)

    subo el js a mi ftp para que veas los cambios, no me da tiempo mucho para investigar el svn:

    http://beta.wigbee.com/franki/franki.js

    veo que falla algo los tabulados, lo arreglare otro dia

  • Buen trabajo panino, pero me temo que debe haber alguna errata en esta sentencia (del bloque para IE)

    var f=fn.call(this,window.event);

    fn.call(this,window.event) invoca a fn y asigna el valor obtenido a la variable f. Eso no es lo que queremos: queremos que se invoque desde el event dispatcher del navegador. Seguramente se te habrán olvidado el keyword function sus paréntesis y sus llaves (estas cosas que nos pasan cuando estamos desarrollando en los comentarios de un blog ;-)

    var f=function(){ return fn.call(this,window.event);}
    this.attachEvent( ‘on’+type, f);
  • Andrés ¿que hay que hacer para remarcar el código a la hora de escribir comentarios? Parece que <pre> no lo consigue. El otro día creo que metí una secuencia <pre><code> y tampoco.¿Cómo es?

  • @panino: Perfecto, ya está añadida. Muchas gracias.

    @jdeveloper: He añadido each() que extiende los Array y así podemos hacer cosas asi:

    
    franki.get(".hola").each(function(indice, elemento){
     elemento.css("border", "1px red solid");
    });
    

    No te preocupes, yo tampoco he podido todavía configurar el SVN de Google, voy subiendo diferentes ficheros con diferentes versiones, siempre cogiendo los cambios de la versión anterior.

    Acabo de subir la 0.0.5 :D

    @Jose: Pues es raro, es lo que estoy metiendo, quizas WordPress lo esté filtrando en los comentarios de los usuarios no registrados, este fin de semana lo miro.

  • Es cierto, José, tenía un error mi propuesta, pero le hice un cambio a la tuya para que this se comporte igual en Explorer que en el resto de los navegadores en lugar de hacer referencia a window.
    Aquí va una corrección, ya testeada, y el agregado del removeEvent correspondiente:

    addEvent: function(type, fn ) {
    			if ( this.addEventListener ) {
    				this.addEventListener( type, fn, false );
    			} else if(this.attachEvent){
    					var _this=this;
    					var f= function(){fn.call(_this,window.event);}
    					this.attachEvent( 'on'+type, f);
    					this[fn.toString()]=f;
    			}else{
    				this['on'+type]=fn;
    			}
    			return this;
    		},
        removeEvent: function(type, fn ) {
    	if( this.removeEventListener){
    		
    		this.removeEventListener( type, fn, false );
    	}
        else if(this.detachEvent){
    		this.detachEvent('on'+type,this[fn.toString()]);
    		this[fn.toString()]=null;
    	}
    	else{
    	  this['on'+type]=function(){};
    	}
            
        return this;
        },
    

    De esa manera ya es posible esto:

    var algo=function(){alert(this.id);};//devuelve 'pp'
    var nada=function(){
    $(document.getElementById('pp')).removeEvent('click',algo);
    }
    onload=function(){
    	$(document.getElementById('pp')).addEvent('click',algo);
    	$(document.getElementById('qq')).addEvent('click',nada);
    }
  • Es cierto, José, había un error en mi propuesta, pero en tu corrección, en Explorer this seguía apuntando a window en lugar del elemento extendido, de manera que la modifiqué para que se comporte igual que en el resto de los navegadores. Ahora ya más tranquilo y habiéndolo testeado, agrego una modificación y el removeEvent que le corresponde a la misma:

    addEvent: function(type, fn ) {
    			if ( this.addEventListener ) {
    				this.addEventListener( type, fn, false );
    			} else if(this.attachEvent){
    					var _this=this;
    					var f= function(){fn.call(_this,window.event);}
    					this.attachEvent( 'on'+type, f);
    					this[fn.toString()]=f;
    			}else{
    				this['on'+type]=fn;
    			}
    			return this;
    		},
        removeEvent: function(type, fn ) {
    	if( this.removeEventListener){
    		
    		this.removeEventListener( type, fn, false );
    	}
        else if(this.detachEvent){
    		this.detachEvent('on'+type,this[fn.toString()]);
    		this[fn.toString()]=null;
    	}
    	else{
    	  this['on'+type]=function(){};
    	}
            
        return this;
        },
  • @panino, lo dicho: desarrollando en los comentarios de un blog ;)

  • @Jose: Pero por que queréis, ya he subido la última revisión al SVN y lo podéis descargar directamente desde la página del proyecto.
    http://code.google.com/p/franki/

    He añadido unas cosillas que creo interesantes.

    
    // Posibilidad de enviar objetos JSON a css() y attr()
        franki.get("content").css({
            backgroundColor: 'red',
            border: '1px #333 solid'
        }).removeClass("kk");
    

    each(); devuelve el array una vez ejecutadas todas las functions.

  • Acabo de descubrir otro pequeño fallo: si se asigna una misma función con 2 eventos diferentes, al remover en Explorer la función para un evento, ya no es posible removerla para el segundo. Esto se debe a que nulificamos la referencia a la función cada vez que se ejecuta removeEvent. Así que pido disculpas, pero va una nueva corrección para solventar eso:

    addEvent: function(type, fn ) {
    			if ( this.addEventListener ) {
    				this.addEventListener( type, fn, false );
    			} else if(this.attachEvent){
    					var _this=this;
    					var f= function(){fn.call(_this,window.event);}
    					this.attachEvent( 'on'+type, f);
    					this[fn.toString()+type]=f;
    			}else{
    				this['on'+type]=fn;
    			}
    			return this;
    		},
        removeEvent: function(type, fn ) {
    	if( this.removeEventListener){
    		
    		this.removeEventListener( type, fn, false );
    	}
        else if(this.detachEvent){
    		this.detachEvent('on'+type,this[fn.toString()+type]);
    		this[fn.toString()+type]=null;
    	}
    	else{
    	  this['on'+type]=function(){};
    	}
            
        return this;
        },

    La verdad es que esto promete enseñarnos mucho y me encanta como proyecto.

  • Lo del each esta muy bien, ahora andar con bucles engorosos, aunque yo podria primero elemento y despues indice

    asi pudo hacer each(function(elem){}) cuando no necesite el indice que es lo que ocurre en la mayoria de los casos en que se usa each.

  • Aprovecho la nueva mejora de Andrés para dejar una pregunta filosófica. ¿qué desventajas le veis a la interfaz que utilizo en el siguiente ejemplo?

    franki.get("content").css(
          'backgroundColor', 'red',
          'border' ,'1px #333 solid'
    )

    De esa manera nos ahorramos la creación de un objeto transitorio.

  • @jdeveloper: Tienes toda la razón, es mucho más cómodo. Ya lo he cambiado en el SVN.

    @Jose: Tiene buena pinta, aunque quizás al sistema del objeto le veo una ventaja frente a esto.

    
    var objCSS = {
    ...
    }
    
    // Aplicamos estilos al contenedor.
    franki.get("content").css(objCSS);
    // Los mismos estilos a otro contenedor
    franki.get("otro_content").css(objCSS);
    
    

    Simplemente es por claridad.

  • He añadido esta funcion a metodosExtendidos:

    
    remove: function(){
    		this.parentNode.removeChild(this);
    		return franki;
    	}
    
    //para eliminar un nodo
    franki.get('#identificador').remove();
    

    en each cambia

    return this;

    por

    return franki.get(this) para seguir haciendo chaning

    subo el js de nuevo a mi ftp

    saludos

  • Es decir, esa interfaz no disgusta. ¿Y si sobrecargamos el método de manera que si tiene más de un argumento emplea ese enfoque?

  • a mi me gusta mas el enfoque de pasar un objeto, lo veo mas legible.

  • @jdeveloper: Perfecto, pero si eso subelo al SVN y así no habrá que ir haciendo merges con cada cambio.

    @Jose: Por mi perfecto :D

  • js subido a mi ftp, este finde me pongo con el svn pero antes, no me da tiempo para mirarlo.

  • subido los cambios al svn, no fue tran traumatico xD, deberia estar con el pfc pero supongo que un programador suele hacer primero lo que mas le gusta xD

  • @jdeveloper: Perfecto, he añadido el método add() a franki para poder extender metodosExtendidos desde fuera.

  • @anieto2k mm, muy bueno para añadir plugins, por ejemplo opacity, suponiendo que no lo vaiamos poner nativamente.

    Quiza habria que ponerle un nombre mas explicativo (no se me ocurre por ahora) que haga entender que es para extenter la base.

  • Andrés, si te parece, agregame al proyecto.

  • Echadle un vistazo a ver si le veis algún problema:

    
    css: function() {
           if (arguments.length == 1) {
              var a = arguments[0];
              if (typeof a == 'string') {
                  return this.style[a];
              }
              else {
                  for (var p in a) this.style[p] = a[p];
              }
           }
           else {
             for(var i = 0, l = arguments.length;i<l;) {
                this.style[arguments[i++]] = arguments[i++]
             }
           }
    
        }
    
  • me quito el sombrero. A ver si saco un tiempo entre novatadas y estudios, que llevo unos días off de internet. No se si eso es bueno o malo :P

  • @jdeveloper: Si, tampoco estoy muy contento con el nombre que le he puesto, habría que pensar algo más descriptivo. Quizás un addMethod() o algo parecido.

    @panino: Agregado :D
    @Jose: Solo le ha faltado añadir un return this; para devolver el objeto y así encadenar más opciones.

    He creado un Grupo de Discusión vinculado al proyecto de Google.code y ahí podemos discutir las opciones en vez de hacerlo aqui en los comentarios.

    http://groups.google.com/group/frankijs

    Os he enviado invitaciones, si alguien quiere adherirse que lo diga :D

  • @Jose, mola, te salio guai quitando el return, xD

  • He subido otro commit, ahora tenemovs replace(node) con lo cual podemos reemplazar un elemento.

  • ¿Alguien subio la version css de @Jose?

    Es que hice svn update y no hubo cambios, a ver si tengo que teclear algun comando más no vaia ser que machaque vuestro tabajo.

    De paso, decir, que es un orgullo poder colaborar con cada uno de los miembros, grandes cracks que sois.

  • Por cierto, algo pasa con mi tabulación, ¿donde estara el error?

    No sabia si abrir un hilo en google groups, voi a ello

  • @jdeveloper: Ya lo he añadido yo, le he puesto el return this;.

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.