javascript: particularidades del lenguaje, dom, eventos y ajax

47
Javascript Javascript Javier Infante <[email protected]> Zamudio :: Bizkaia Enpresa Digitala ::14/12/2009

Upload: irontec-internet-y-sistemas-sobre-gnulinux

Post on 18-Nov-2014

8.070 views

Category:

Technology


3 download

DESCRIPTION

Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX (aka Javascript Clasico)

TRANSCRIPT

Page 1: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Javascript

Javier Infante <[email protected]>

Zamudio :: Bizkaia Enpresa Digitala ::14/12/2009

Page 2: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Incluir Javascript en nuestros documentos HTML– INCLUSIÓN en (X)HTML:

● Inline en el documento:<script type="text/javascript">//<![CDATA[código....//]]></script>

● Separando contenido de estructura:<script type="text/javascript"src="scripts.js"></script>

Particularidades del Lenguaje

Page 3: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Tipos de datos:– var intValue = 1;– var floatValue = 3.0;– var sqString = 'This is also a string'; // Objeto tipo String– var array = [1,2,3]; // Objeto tipo Array– var obj = {1,2,3};– var function = new function() {};

● Javascript es un lenguaje con tipado débil.● Las variables son declaradas con la palabra reservada

“var”, y són válidas en su ámbito de declaración.– Si no se especifica var, la variable será automáticamente

declarada como global.

Particularidades del Lenguaje

Page 4: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Ámbitos de ejecución– Ámbito global o window

● Por defecto siempre estaremos en el ámbito global window.

● Cualquier función o variable declarada, será un método o propiedad del objeto window.

● Algunos métodos/propiedades útiles del objeto window– window.document– window.setTimeout(function,milisegundos)– window.setInterval(function,milisegundos)– window.alert(mensaje)– window.prompt(mensaje)

Particularidades del Lenguaje

Page 5: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– Ámbito de ejecución funcional.● Al entrar en la ejecución de una función, el ámbito de

ejecución (scope), cambia al entorno de esa función. Todas las variables definidas dentro de la función, serán sólo accesibles desde esa función.

– Toda variable no definida, será tomada / seteada en el ámbito global.

● No confundir el scope (ámbito de las variable) con el contexto (objeto sobre el que se ejecuta la función).

Particularidades del Lenguaje

Page 6: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Referencias– Una referencia es un puntero a la localización actual de

un objeto.– Al copiar un objeto, éste se copiará por referencia.– Dos variables pueden apuntar al mismo objeto. La

modificación de una de ellas, tendrá consecuencias para el objeto concreto.

– Si una de las variables apuntada a un mismo objeto, es instanciada (construyendo otro objeto), la referencia se perderá.

Particularidades del Lenguaje

Page 7: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Sobrecarga de funciones y comprobación de tipos– En el contexto de cada función, tenemos disponible una

variable tipo array que contendrá los argumentos con la que la función ha sido llamada.

arguments– Para comprobar el tipo de una función, tenemos dos

posibilidades:● Operador typeof

– Nos devuelve el tipo de variable (string, objeto, numero, boolean...)

– Es imposible determinar el tipo de objeto● Propiedad constructor

– Dado que todas las variables en realidad son objetos, determina el constructor de cada una.

Particularidades del Lenguaje

Page 8: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Tabla comparación typeof – constructor

Variable typeof variable variable.constructor{idx:'valor'} object Object

['uno','dos'] object Array

function() {} funcion Function

'Hola Mundo' string String

55 number Number

true boolean Boolean

new Objeto() object Objeto

Particularidades del Lenguaje

Page 9: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Orientación a Objetos (I)– Objeto = conjunto de métodos y propiedades

encapsuladas.– Javascript es completamente orientado a objetos. Es

imposible escribir código Javascript funcional.– Recordar que siempre estamos bajo el objeto global window.– Creación de un objeto simple:

var obj = new Object();obj.propiedad2 = 'cosa';

var obj = { propiedad2 : 'cosa'

}

Particularidades del Lenguaje

Page 10: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– No existe el concepto de clases. – Javascript es un lenguaje orientado a prototipos.

● Creación de un objecto simple a partir de una función

function Vehiculo(marca) {this.marca = marca;

}

var obj = new Vehiculo();alert(obj.marca);alert(obj.constructor == Vehiculo);

Particularidades del Lenguaje

Page 11: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– Métodos/Propiedades públicos● Métodos accesibles por cada instancia del objeto en

particular.● La palabra reservada this, hace referencia al objeto

instanciado en cada momento.● Éstos deben añadirse a la propiedad prototype de cada

Objeto.function Vehiculo(marca) {

this.marca = marca;}Vehiculo.prototype.getMarca = function (){

return this.marca;}

Particularidades del Lenguaje

Page 12: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Contextos– En javascript siempre nos encontramos en el ámbito de un

contexto. Es decir, siempre estamos operando bajo el ámbito de un objeto determinado.

– El contexto por defecto en el que se ejecutan las funciones es window.● Salvo en el caso de Métodos Públicos, donde this hará

referencia a cada instancia.

– apply / call● Dos métodos que nos permiten ejecutar funciones

especificando su contexto de ejecución.nFuncion.apply(objeto,[array de argumentos]);nFuncion.call(objeto,arg1,arg2,...);

Particularidades del Lenguaje

Page 13: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Closures / Cierres– Funcionalidad gracias a la cual, una variable del scope

“padre”, estará disponible en el scope hijo, aún cuando termine la ejecución del hilo padre.

– Permite aislar entornos de ejecuciones concurrentes de código -sacar nuestro código del ámbito global- sin peligro de sobreescribir variables.

– Funcionalidad muy útil a la hora de crear listeners para eventos, timers, etc...

Particularidades del Lenguaje

Page 14: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Orientación a Objetos (II)– Herencia de prototipos.

● Es posible conseguir herencia en la definición de nuevos objetos.

● Teniendo en cuenta que los métodos públicos son almacenados en la propiedad “prototype” de cada objeto, bastará con referenciar esa propiedad a un nuevo objeto de tipo “padre”, para que los métodos definidos en este objeto, estén disponibles en el “hijo”.

Particularidades del Lenguaje

Page 15: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

function Padre() {var metodo2 = function() {}

}Padre.prototype.metodo = function() {}

function Hijo() {}Hijo.prototype = new Padre();// Hijo.metodo() e Hijo.metodo2() estarán disponibles en cualquier instancia de Hijo.

Particularidades del Lenguaje

Page 16: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Orientación a Objetos (II)– Métodos/Propiedades Privados: Declaración de métodos

accesibles solamente desde el ámbito de objeto (mucho ojo a los ámbitos).

function Vehiculo(marca) {this.marca = marca; prop. público←var arrancado = false; prop. privada←function encenderMotor() { // SCOPE global← arrancado = true; this == window?←

} encenderMotor.call(this); llamada ←

especif. scope this.arrancar = function() { acc. publico← encenderMotor.call(this); acc.privado← }

}

Particularidades del Lenguaje

Page 17: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Empaquetando código para publicar

● A la hora de poner en producción nuestro código Javascript, tanto para una web concreta, o para la publicación de un código de una funcionalidad determinada, tenemos que tener en cuenta los siguientes aspectos:

– Peso del script: Suele ser el principal cuello de botella en cuanto a rendimiento de nuestros scripts.

– Ámbito de declaración de nuestros métodos / variables: Sobre todo si se pretende convivir con otros códigos / plugins... Es importante “NO PISARSE”.

– Que sea multinavegador (pero esto es otra historia)...

Page 18: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Empaquetando código para publicar

● Optimizando el peso del script.– Existen 2 métodos usados globalmente para optimizar el peso

de nuestros scripts:● JSMin http://www.crockford.com/javascript/jsmin.html

● http://fmarcia.info/jsmin/test.html● Librería portada a multitud de lenguajes (PHP / Python /

.NET/ etc..), que elimina comentarios, espacios en blanco y saltos de línea, consiguiendo notables “ahorros” de ancho de banda.

● Packer http://dean.edwards.name/packer/● Código super potente y muy complicado, que genera a

partir de nuestro script, otro script autoejecutable (y comprimido), que dará como resultado nuestro script inicial.● Poco adecuado para ficheros pequeños.

Page 19: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Empaquetando código para publicar

● Limpiando nuestro código– Sobre todo cuando utilicemos JSMin, nuestro código tiene

que estar correctamente escrito para evitar errores de interpretación sobre el código comprimido.

– Existe la Librería JSLint para comprobar la “calidad” de nuestro código.

http://www.jslint.com/– Errores comunes:

● Cuidado con los operadores de auto incrementar:var j = i++ +3;Al comprimir esa línea, nos quedará lo siguiente:

– var j = i+++3; // Sin espacio, lo cual dará un error de interpretación

– Lo Correcto:var j = (i++)+3;

Page 20: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Empaquetando código para publicar● Punto y coma, después de cada asignación:

var func = function(a,b) {return a+b;

}; // Sin punto y coma funcionará, pero nos dará error si ←comprimimos este código.

function sumar(a,b) {return a+b;

} // Aquí no ponemos punto y coma, ya que es la ←declaración de una función.

Page 21: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Empaquetando código para publicar● Optimizando el peso del script.

– La mayor parte de navegadores serios del mercado, tiene soporte para descomprimir páginas servidas gzipeadas.

Content-encoding: gzip– Existen modulos para Apache 2.0 para servir el contenido de

texto gzipeado:a2enmod deflate

- Simplemente añadiendo estas líneas en el .htaccess (o mejor aun en el fichero de configuración de apache)AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml application/x-javascriptBrowserMatch ^Mozilla/4 gzip-only-text/htmlBrowserMatch ^Mozilla/4\.0[678] no-gzipBrowserMatch \bMSIE !no-gzip !gzip-only-text/html

Page 22: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Empaquetando código para publicar

● Namespacing– Aunque en Javascript no existe como en otros lenguajes

(como Java, Python o PHP 5.3) la técnica de namespacing. Ésta técnica permite “encerrar” fragmentos de código, de manera que variables y funciones globales no se pisen en interactuación con otras librerías.

– En Javascript, la técnica ideal, es encapsular todas nuestras variables y funciones en un objeto único.

– Y nunca (salvo en casos excepcionales), utilizar variables globales.

Page 23: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● DOM– Metodología estándar para representar un documento

XML (aunque existen otras muchas, y posiblemente más eficientes)

– Implementada en varios lenguajes, fue elegida por el W3C como estándar para referenciar al documento HTML.

– El estándar definido, está implementado “parcialmente” por casi todos los navegadores comerciales.

– Los documentos HTML poseen una estructura hereditaría representada como una estructura de árbol.

– Conjunto de propiedades y métodos para recorrer árboles XML (HTML), y examinar o modificar sus nodos.

Document Object Model

Page 24: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

<html><head> <title>Sample Document</title></head><body>

<h1>An HTML Document</h2>

<p>This is a <i>simple</i> document.

</body>

</html>

Document Object Model

Page 25: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

Document Object Model

Page 26: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Árbol Web– Un documento XHTML se compone de un conjunto de

nodos.– Un nodo es un objeto accesible y modificable.– Propiedades:

.nodeType● Propiedad más importante, que nos indica el tipo de nodo

que es:– 1 || ELEMENT_NODE : Nodo de tipo TAG– 3 || TEXT_NODE : Nodo de tipo Texto (CUIDADO!)

.attributtes● Devuelve array con los atributos de un nodo.

Document Object Model

Page 27: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

.nodeName● Propiedad que devuelve el nombre del tag

. innerHTML● Devuelve el contenido HTML dentro del tag

.nodeValue● Devuelve el texto en caso de nodeType == 3

.childNodes● Devuelve un array con todos los nodos hijos de ese nodo.

Document Object Model

Page 28: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– Cada nodo poseé 5 punteros (referencias a otros nodos) que apuntan a sus nodos relacionados

– El acceso a través de puntos, no es muy óptimo.– Relaciona cada nodo con sus familiares.

NodopreviousSibling nextSibling

parentNode

firstChild lastChild

nextSibling

Document Object Model

Page 29: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● window.document– Propiedad del objeto global window de la que heredan

los métodos los nodos disponibles en el DOM.document.documentElementreferencia al nodo raiz <html>document.bodyreferencia al nodo <body>

– Métodos de window.document.getElementById(iden)Devuelve 1 único elemento identificado por el atributo

único “id”;.getElementsByTagName(“tag”)Devuelve un array con todos los nodos cuyo tag coincida

con “tag”.

Document Object Model

Page 30: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Método de nodo.createElement()

Crea un nodo de tipo elementovar oEM = document.createElement(“em”);

.createTextNode()Crea un nodo de tipo Texto

var oTxt = document.createTextNode(“hola”);

.appendChild()Inserta un elemento como último hijo de otro

oEM.appendChild(oTxt);

.appendData(data)Inserta texto dentro de un nodo de texto

oEM.lastChild.appendData(“ ¿Qué tal?”);

.cloneNodeClona un elemento

var oEM2 = oEM.cloneNode(true);

Document Object Model

Page 31: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

. insertBefore()Inserta un nodo, antes de un nodo hijo espefico.

var o = document.createElement(“em”);

o.appendChild(document.createTextNode(“adios”));

document.getElementById(“p1”).insertBefore(o,documnet.getElementById(“s1”));

.removeChild()Elimina un nodo hijo determinado, a partir de su

parentNode.nodoPadre.removeChild(nodoHijo)

.hasChildNodes()Devuelve true/false si un nodo tiene o no, nodos

descendientes.

Document Object Model

Page 32: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

.getAttribute(attrib)Devuelve el atributo de un nodo.

alert(document.getElementById(“p1”).getAttribute(“id”));// Muestra p1

.setAttribute()Cambia el valor de atributo

document.getElementById(“p1”).setAttribute(“class”,”r2”);

.removeAttribute()Elimina un atributo de un nodo

Document Object Model

Page 33: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Manejadores de Eventos– EVENTO: método que se activa asíncronamente tras la

sucesión de un proceso determinado.– Son la esencia principal del Javascript; sin eventos, no hay

interactuación.

– Los eventos lanzan manejadores de eventos, que a su vez, están vinculados a funciones (o callbacks).

– Javascript no tiene hilos (lo más parecido es utilizar timers -setTimeout / setInterval).

– La ejecución es completamente lineal, y simplemente se queda “esperando” a que se lanzar los manejadores de eventos.

Eventos

Page 34: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– TECLADO: keydown / keypress /keydown– RATÓN: click / dblclick / mouse[over|move|out]– INTERFAZ: [un]load / resize / scroll / focus / blur– FORMULARIO: submit / reset / change / select

Eventos

Page 35: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Fases de Evento– Fase de Captura de Eventos

● Cuando un usuario lanza un evento, en realidad está lanzando el evento sobre todos los elementos del árbol DOM que contienen este elemento.

● CAPTURING

Eventos

<body><div>

<p><a href=”http://yahoo.com”>yahoo</a>

</p></div>

</body>

Page 36: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

<body><div>

<p><a href=”http://yahoo.com”>yahoo</a>

</p></div>

</body>

– Fase de Retroceso del evento● Cuando se llega al final de la rama, el evento vuelve hacía

atrás, hasta la raíz del documento.

● BUBBLING

Eventos

Page 37: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Objeto Evento– Objeto disponible en los métodos de captura de eventos.– Es un objeto con propiedades muy útiles a la hora de

interactuar con el evento.– Dependiendo del tipo de evento, el objeto evento tendrá

unas propiedades u otras.– El acceso al objeto evento, así como sus propiedades son

dependientes del navegador.function manejandoEvento(e) {

//en navegadores el objeto evento será recibido como parámetro.

// en IE, hay que consultar al objeto global window, por la propiedad event

var e = e? e:window.event; //WORKAROUND!

}

Eventos

Page 38: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript– Propiedades del evento

e.target (W3C) / e.srcElement (IE)● La propiedad más importante que nos posee un evento es

el objeto origen que lo ha invocado.● Mucho cuidado (Bubbling!!)

e.keyCode● Devuelve el código ASCII de la tecla pulsada.

e.pageX / e.pageY (No IE)● Devuelve las coordinadas x e y del puntero del ratón

relativas al documento.

e.screenX / e.screenY● Devuelve las coordinadas x e y del puntero del ratón

relativas a la pantalla.

e.button● Identifica qué botón del ratón se ha pulsado:

– IE: 1(izda) / 2(dcha) / 4(centro)– W3C: 0(izda) / 1(centro) / 2(dcha)

Eventos

Page 39: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– Métodos del evento

e.stopPropagation();

“Frena” la propagación hacía arriba en el DOM del evento.

En IE: window.event.cancelBubble = true;

e.preventDefault()

“Evita” la acción por defecto del navegador. Esta acción se ejecuta al finalizar la fase de Event Bubbling.

En IE: window.event.returnValue = true;

Eventos

Page 40: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Registrando Eventos– Llamadas de retroceso Asíncronas

(CALLBACKS ASÍNCRONOS)● Se registran funciones a las propiedades de los nodos con

el nombre on[evento]:

obj.onclick = function(e) {var e = e? e:window.event; // Soporte para IEthis == obj;

};● Siempre vincula los eventos en la fase de retroceso.● Lo métodos se sobreescriben

Eventos

Page 41: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

– Método propuesto por el W3C● AddEventListener

elemento.addEventListener('click',funcion,true);

El tercer argumento determina en que fase del evento lanzar el handler (Capturing/Bubbling).

No se sobreescriben, aun vinculando varios métodos a un mismo evento.

this == elemento “bindeado”

– Método propuesto por Microsoft● AttachEvent

elemento.attachEvent ('onclick',funcion);

Microsoft sólo da soporte para la fase de retroceso del evento.

No se sobreescriben, aun vinculando varios métodos a un mismo evento.

Eventos

Page 42: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● XMLHttpRequest

– Objeto interno Javascript, encargado de hacer peticiones al servidor web y procesar la salida de éstas.

– Creado como control ActiveX por MS, esta implementado nativamente en otros navegadores (e implementa las mismas funcionalidades).

– AJAX!

AJAX

Page 43: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Instanciando XMLHttpRequest

– Nativamente:var oXML = new XMLHttpRequest();

– ActiveXvar oXML = new ActiveXObject(“Microsoft.XMLHTTP”);

– CrossBrowserif (window.XMLHttpRequest) var oXML = new XMLHttpRequest();else if (window.ActiveXObject) var oXML = new ActiveXObject(“Microsoft.XMLHTTP”);

AJAX

Page 44: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Métodos XMLHttpRequest– abort() - Detiene la petición en curso.– getAllResponseHeaders() - Devuelve todas las cabeceras

de la respuesta (etiquetas y valores) como una cadena.– getResponseHeader(etiqueta)

● Devuelve el valor de la etiqueta en las cabeceras de la respuesta.

– open(método,URL,asíncrona,nombre,password)● Abre una conexión con esa URL mediante ese GET o

POST, aplicando los valores opcionales de la derecha.

– send(contenido) - Envía la petición.– setRequestHeader(etiqueta,valor)

● Establece el valor de las cabeceras de petición.

AJAX

Page 45: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Propiedades XMLHttpRequest– onreadystatechange – Función que se invoca al cambiarse

un estado en la conexión.– readyState - Estado de la conexión:

● 0 : No iniciado● 1: Cargando● 2: Cargado pero sin incorporar el contenido a los objetos

correspondientes.● 3: Incorporando contenido a los objetos correspondientes.● 4: Carga completada

– responseText - Datos devueltos por el servidor en formato string.

– responseXML - Datos devueltos por el servidor en forma de documento XML que puede ser recorrido mediante las funciones del DOM.

– status / statusText - Código respuesta HTTP.

AJAX

Page 46: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Ejemplo GETif (window.XMLHttpRequest) var oXML = new XMLHttpRequest();else if (window.ActiveXObject) var oXML = new ActiveXObject("Microsoft.XMLHTTP");

oXML.open("GET","llamando.php?op1=3");oXML.onreadystatechange = cambiaestado;oXML.send(null);function cambiaestado() { if (oXML.readyState==4) alert(oXML.responseText);}

● Ejemplo POSTvar str = “op1=valor1&op2=valor2”;oXML.open("POST","llamando.php");oXML.onreadystatechange = cambiaestado;oXML.setRequestHeader("Content-Type","application/x-www-form-urlencoded");oXML.setRequestHeader("Content-Length",str.length);oXML.send(str);

Page 47: Javascript: Particularidades del Lenguaje, DOM, Eventos y AJAX

Javascript

● Copyright © 2009 Javier Infante <[email protected]>● Eres libre de:

– Copiar, distribuir y comunicar públicamente la obra– Hacer obras derivadas

● Bajo las condiciones siguientes:– Reconocimiento:

● Debes reconocer los créditos de la obra de la manera especificada por el autor o el licenciador (pero no de una manera que sugiera que tienes su apoyo o apoyan el uso que haces de su obra)

– Compartir bajo la misma licencia● Si transformas o modificas esta obra para crear una obra derivada,

sólo puedes distribuir la obra resultante bajo la misma licencia, una similar o una compatible.

● Más información en:

http://creativecommons.org/licenses/by-sa/3.0/es/

Licencia Copyleft