CRUD
- Create:
- Method (POST):
- Respuesta 200 - OK
- Respuesta 204 - Sin contenido
- Respuesta 404 - No encontrado
- Respuesta 409 - Conflicto, ya existe
- Method (POST):
- Read:
- Method (GET):
- Respuesta 200 - OK
- Respuesta 404 - No encontrado
- Method (GET):
- Update:
- Method (PUT):
- Respuesta 200 - OK
- Respuesta 204 - Sin contenido
- Respuesta 404 - No encontrado
- Method (PUT):
- Delete:
- Method (DELETE):
- Respuesta 200 - OK
- Respuesta 404 - No encontrado
- Method (DELETE):
-
Por tipología:
- 1xx Informativas
- 2xx Peticiones Correctas
- 3xx Redirecciones
- 4xx Errores Cliente
- 5xx Errores Servidor
Con Jquery
function peticionJqueryAjax (url) {
$.ajax({
dataType: "json",
url: url,
})
.done(function( data, textStatus, jqXHR ) {
if ( console && console.log ) {
console.log( "La solicitud se ha completado correctamente." );
console.log( data );
}
})
.fail(function( jqXHR, textStatus, errorThrown ) {
if ( console && console.log ) {
console.log( "La solicitud a fallado: " + textStatus);
}
});
}
peticionJqueryAjax ("<---URL---->");
Vainilla JS
- readyState:
- 0 es uninitialized
- 1 es loading
- 2 es loaded
- 3 es interactive
- 4 es complete
function peticionAjax(url) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
console.info(JSON.parse(xmlHttp.responseText));
} else if (xmlHttp.readyState === 4 && xmlHttp.status === 404) {
console.error("ERROR! 404");
console.info(JSON.parse(xmlHttp.responseText));
}
};
xmlHttp.open("GET", url, true);
xmlHttp.send();
}
peticionAjax("<---URL---->");
Ejercicios
1 - Sacar en el html la respuesta de OMDB para la pelicula Hackers
function peticionAjax (movieName) {
var xmlHttp = new XMLHttpRequest(),
cURL = 'http://www.omdbapi.com/?t='+movieName+'&y=&plot=short&r=json';
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
var datos = (JSON.parse(xmlHttp.responseText));
var contenido = "";
contenido += "<h1>"+datos.Title+"</h1>"
contenido += "<p>"+datos.Plot+"</p>"
document.body.innerHTML = contenido;
} else if (xmlHttp.readyState === 4 && xmlHttp.status === 404) {
console.error("ERROR! 404");
console.info(JSON.parse(xmlHttp.responseText));
}
};
xmlHttp.open( "GET", cURL, true );
xmlHttp.send();
}
peticionAjax("Hackers");
2 - Sacar en el html el tiempo meteorológico de Madrid, Barcelona y Valencia. Nota: http://openweathermap.org te será de gran ayuda, busca la solución al error 401
var contenido = "";
function temperaturaCiudad (ciudad) {
var xmlHttp = new XMLHttpRequest(),
APIKey = '<---- TU API ---->', // Puedes usar una cuenta gratuita -> http://openweathermap.org/price
cURL = 'http://crossorigin.me/http://api.openweathermap.org/data/2.5/weather?q='+ciudad+'&APPID='+APIKey;
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
var datos = (JSON.parse(xmlHttp.responseText));
contenido += "<h1>"+datos.name+"</h1>"
contenido += "<p>"+datos.weather[0].description+"</p>"
document.body.innerHTML = contenido;
} else if (xmlHttp.readyState === 4 && xmlHttp.status === 404) {
datos = JSON.parse(xmlHttp.responseText);
console.error("ERROR! 404");
console.info(datos);
}
};
xmlHttp.open( "GET", cURL, true );
xmlHttp.send();
}
temperaturaCiudad("Madrid");
temperaturaCiudad("Barcelona");
temperaturaCiudad("Valencia");
3 - Jugando con datos abiertos, saquemos los detalles de todos los cuadros eléctricos de Gijón por consola.
function peticionAjax (url) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
var datos = (JSON.parse(xmlHttp.responseText));
console.log(datos)
} else if (xmlHttp.readyState === 4 && xmlHttp.status === 404) {
console.error("ERROR! 404");
console.info(JSON.parse(xmlHttp.responseText));
}
};
xmlHttp.open( "GET", url, true );
xmlHttp.send();
}
// Utilizamos un proxy como http://crossorigin.me para solucionar el problema de CORS
peticionAjax("http://crossorigin.me/http://opendata.gijon.es/descargar.php?id=163&tipo=JSON");
// Podemos encontrar errores en las respuestas.
// cuadromando[5] ...
calle: "Faustina Álvarez García"
latitud: 43.526376045
longitud: -5.685764873
numero: ""
potencia_w_: 17321
// ...
4 - Desarrolla una versión mejorada de MovieFire (JS puro) incluyendo llamadas AJAX a la base de datos de IMBD para enriquecer los datos, usando OMDb API.
-
Precisión:
- Wi-fi (MAC)
- Ethernet (IP)
- Triangulación (3G y 4G)
- GPS (máxima precisión, pero tardará más en cargar)
-
Métodos de geolocation
- getCurrentPosition():
// Posición Actual navigator.geolocation.getCurrentPosition();
- watchPosition():
// Seguimiento como un GPS navigator.geolocation.watchPosition();
- clearWatch():
// Para el seguimiento navigator.geolocation.clearWatch();
-
Propiedades de geolocation
- Latitud (en base 10):
console.info(position.coords.latitude);
- Longitud (en base 10):
console.info(position.coords.longitude);
- Precisión en posicionamiento:
console.info(position.coords.accuracy);
- Altitud (metros por encima del nivel del mar):
console.info(position.coords.altitude);
- Precisión de altitud:
console.info(position.coords.altitudeAccuracy);
- Rumbo (Grados respectos al norte):
console.info(position.coords.heading);
- Velocidad (m/s):
console.info(position.coords.speed);
- Timestamp:
console.info(position.timestamp);
-
Ajustes de geolocation
-
enableHighAccuracy:
- Mejora los datos para conexiones no GPS, pero aumenta drásticamente el consumo de batería del dispositivo.
- False por defecto
-
timeout:
- Tiempo (ms) de espera antes de lanzar el error.
- 0 por defecto
-
maximumAge:
- Tiempo (ms) para el almacenamiento en memoria cache de la posición actual
- 0 por defecto
-
Ejemplo:
var opciones = { enableHighAccuracy: true, maximumAge: 1000, // 1s timeout: 2000 // 2s }
-
-
Trabajando con geolocation
- Comprobando la compatibildiad de geolocation
if ("geolocation" in navigator) { console.info("Podemos usar Geolocation! :-) "); } else { console.warn("Geolocation no soportado :-( "); }
- Probando la geolocalización:
if ("geolocation" in navigator) { navigator.geolocation.getCurrentPosition(function(position) { // Consola console.info("Latitud: " + position.coords.latitude + "\nLongitud: "+ position.coords.longitude); // HTML var datos = "<h1>Te pille!</h1>" datos += "Latitud: " + position.coords.latitude.toFixed(4) + "<br>" datos += "Longitud: "+ position.coords.longitude.toFixed(4) document.body.innerHTML = datos; }); } else { console.warn("Geolocation no soportado :-( "); }
- Mostrar la localización en una imagen estatica usando Gogole Maps:
if ("geolocation" in navigator) { navigator.geolocation.getCurrentPosition(function(position) { var latlon = position.coords.latitude + "," + position.coords.longitude; var img_url = "http://maps.googleapis.com/maps/api/staticmap?center="+latlon+"&zoom=14&size=400x300&sensor=false"; document.body.innerHTML = "<img src='"+img_url+"'>"; }); } else { console.warn("Geolocation no soportado :-( "); }
- Gestionar los Errores y rechazos:
navigator.geolocation.getCurrentPosition(geo_success, geo_error); function geo_success(position) { console.info(position.coords.latitude+","+ position.coords.longitude); } function geo_error(error) { switch(error.code) { case error.PERMISSION_DENIED: document.body.innerHTML = "El usuario ha rechazado la petición."; console.warn(error); break; case error.POSITION_UNAVAILABLE: document.body.innerHTML = "La posición de usuario no es correcta."; console.warn(error); break; case error.TIMEOUT: document.body.innerHTML = "No hay respuesta en el tiempo limite previsto."; console.warn(error); break; case error.UNKNOWN_ERROR: document.body.innerHTML = "Error Desconocido"; console.warn(error); break; } }
- Trabajando con ajustes personalizados:
navigator.geolocation.getCurrentPosition(geo_exito, geo_error, opciones); var opciones = { enableHighAccuracy: true, maximumAge: 1000, // 1s timeout: 2000 // 2s } function geo_exito(position) { console.info(position.coords.latitude+","+ position.coords.longitude); } function geo_error(error) { console.warn("Error! - "+error); }
- Convirtiendo las coordenadas a hexadecimal:
/** * From Isabel Castillo * http://isabelcastillo.com/convert-latitude-longitude-decimal-degrees * Convert longitude/latitude decimal degrees to degrees and minutes * DDD to DMS, no seconds * @param lat, latitude degrees decimal * @param lng, longitude degrees decimal */ function convertDMS( lat, lng ) { var convertLat = Math.abs(lat); var LatDeg = Math.floor(convertLat); var LatSec = (Math.floor((convertLat - LatDeg) * 60)); var LatCardinal = ((lat > 0) ? "n" : "s"); var convertLng = Math.abs(lng); var LngDeg = Math.floor(convertLng); var LngSec = (Math.floor((convertLng - LngDeg) * 60)); var LngCardinal = ((lng > 0) ? "e" : "w"); return LatDeg + LatCardinal + LatSec + "<br />" + LngDeg + LngCardinal + LngSec; }
- Sigue a un usuario:
navigator.geolocation.watchPosition(geo_exito, geo_error); function geo_exito(position) { console.info(position.coords.latitude +", "+ position.coords.longitude); } function geo_error(error) { console.warn("Error! - "+error); }
Google Maps
- Librería
<script type='text/javascript' src="http://maps.googleapis.com/maps/api/js?sensor=false&extension=.js&output=embed"></script>
- Centrar el mapa
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 8,
center: {lat: -3.8199647, lng: 40.4381307}
});
}
- Markers ( Demo )
// In the following example, markers appear when the user clicks on the map.
// Each marker is labeled with a single alphabetical character.
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var labelIndex = 0;
function initialize() {
var bangalore = { lat: 12.97, lng: 77.59 };
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: bangalore
});
// This event listener calls addMarker() when the map is clicked.
google.maps.event.addListener(map, 'click', function(event) {
addMarker(event.latLng, map);
});
// Add a marker at the center of the map.
addMarker(bangalore, map);
}
// Adds a marker to the map.
function addMarker(location, map) {
// Add the marker at the clicked location, and add the next-available label
// from the array of alphabetical characters.
var marker = new google.maps.Marker({
position: location,
label: labels[labelIndex++ % labels.length],
map: map
});
}
google.maps.event.addDomListener(window, 'load', initialize);
- Markers Personalizados ( Demo )
// This example adds a marker to indicate the position of Bondi Beach in Sydney,
// Australia.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -33, lng: 151}
});
var image = 'images/beachflag.png';
var beachMarker = new google.maps.Marker({
position: {lat: -33.890, lng: 151.274},
map: map,
icon: image
});
}
- InfoWindows ( Demo )
// This example displays a marker at the center of Australia.
// When the user clicks the marker, an info window opens.
function initMap() {
var uluru = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: uluru
});
var contentString = '<div id="content">'+
'<div id="siteNotice">'+
'</div>'+
'<h1 id="firstHeading" class="firstHeading">Uluru</h1>'+
'<div id="bodyContent">'+
'<p><b>Uluru</b>, also referred to as <b>Ayers Rock</b>, is a large ' +
'sandstone rock formation in the southern part of the '+
'Northern Territory, central Australia. It lies 335 km (208 mi) '+
'south west of the nearest large town, Alice Springs; 450 km '+
'(280 mi) by road. Kata Tjuta and Uluru are the two major '+
'features of the Uluru - Kata Tjuta National Park. Uluru is '+
'sacred to the Pitjantjatjara and Yankunytjatjara, the '+
'Aboriginal people of the area. It has many springs, waterholes, '+
'rock caves and ancient paintings. Uluru is listed as a World '+
'Heritage Site.</p>'+
'<p>Attribution: Uluru, <a href="https://en.wikipedia.org/w/index.php?title=Uluru&oldid=297882194">'+
'https://en.wikipedia.org/w/index.php?title=Uluru</a> '+
'(last visited June 22, 2009).</p>'+
'</div>'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: uluru,
map: map,
title: 'Uluru (Ayers Rock)'
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
}
- Notas sobre GMaps:
Ejercicios:
1 - Utiliza Google Maps para posicionar al usuario.
<!DOCTYPE html>
<html lang="es">
<head>
<title>Demo: Geolocalización</title>
<meta charset="utf-8" />
<style>
#mapa {
width: 100%;
height: 300px;
margin: 0;
}
</style>
</head>
<body>
<div id="mapa"></div>
<div id="datos"></div>
<a id="recarga" href="#">Recargar!</a>
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type='text/javascript' src="http://maps.googleapis.com/maps/api/js?sensor=false&extension=.js&output=embed"></script>
<script type="text/javascript">
(function() {
// Google Maps
google.maps.visualRefresh = true; // Refresco Constante
var map;
function initialize() {
var mapOptions = {
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('mapa'),
mapOptions);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Te pille! :-)'
});
map.setCenter(pos);
//datos Primer Arranque
muestraDatos(x ,position);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: El Servicio de Geolocalización esta fallando.';
} else {
var content = 'Error: Tu navegador no soprota la Geolocalización.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
// Datos (Core)
var x = document.getElementById("datos");
var a = document.getElementById("recarga");
function muestraDatos(div, position){
x.innerHTML = "Latitud: " + position.coords.latitude +
"<br>Longitud: " + position.coords.longitude +
"<br>Precisión: " + position.coords.accuracy +
"<br>Altitud: " + position.coords.altitude +
"<br>Altitud Precisa: " + position.coords.altitudeAccuracy +
"<br>Grados Norte: " + position.coords.heading +
"<br>Velocidad m/s: " + position.coords.speed +
"<br>Última Conexión: " + position.timestamp;
};
//datos Actualizacion
a.onclick = function() {
initialize();
return false;
}
})();
</script>
</body>
</html>
2 - RETO: Partiendo de este Gist, adapta el script a lo que aprendimos en estos días y compartelo usando Gist. - Nota: Recuerda que con Gist también puedes hacer Forks - Objetivos: - Reconstruir el script usando solo js, sin Jquery - Mejorar la representación visual de los datos - Utiliza las opciones avanzadas de Geolocation para mejorar la usabilidad
// Tu solución aquí
3 - Utiliza Ajax para posicionar al usuario y las estaciones de BiciMad en un mapa:
// Tu solución aquí
4 - Utiliza esta librería para posicionar al usuario, los cascos de StarWars con sus característicos iconos y la distancia estimada
- Nota:
// Tu solución aquí
-
Podemos escuchar eventos y enlazar funciones (event handler)
-
Propagación:
- Capturing desde document hasta el elemento
- Target impacta el elemento
- Bubbling sube desde el elemento hasta document
-
Usando Eventos (Tradicional)
- Solo una función por evento
<button onclick="cambiarFondo()">Cambia el fondo</button>
function cambiarFondo() { // color = 'rgb(0-255,0-255,0-255' var color = 'rgb(' + Math.floor((Math.random() * 255))+ ','; color += Math.floor((Math.random() * 255)) + ','; color += Math.floor((Math.random() * 255)) + ')'; document.body.style.backgroundColor= color; }
-
Usando Eventos (Callbacks)
- Multiples funciones por evento
- Necesidad de compatibilizar para IE8
// Callback - Manejador de Eventos function manejadorEventos(elEvento) { // Compatibilizar el evento var evento = elEvento || window.event; // Imprimir detalles console.log("-----------------------------") console.log("Type: "+evento.type); // Tipo console.log("Bubbles: "+evento.bubbles); // sube por el DOM console.log("Cancelable: "+evento.cancelable); console.log("CurrentTarget: ", evento.currentTarget); console.log("DefaultPrevented: "+evento.defaultPrevented); console.log("EventPhase: "+evento.eventPhase); console.log("Target: ", evento.target); console.log("TimeStamp: "+evento.timeStamp); console.log("IsTrusted: "+evento.isTrusted); // true - Usuario o false - Script console.log("=============================") // Desactivamos if (document.removeEventListener){ document.removeEventListener('click', manejadorEventos, false); console.info("Listener quitado con exito"); } else { // IE8 document.detachEvent('onclick', manejadorEventos); console.info("Listener quitado con exito"); } } // Añadimos Listener if (document.addEventListener){ document.addEventListener('click', manejadorEventos, false); console.info("Listener añadido con exito"); } else if (document.attachEvent){ // IE8 document.attachEvent('onclick', manejadorEventos); console.info("Listener añadido con exito"); } else { document.onclick = manejadorEventos; console.info("Listener añadido con exito"); }
-
Deteniendo el flujo
- .preventDefault() evita el comportamiento por defecto (ex: Link -> nueva URL)
- .stopPropagation() evita la propagación por el DOM
-
Gestión vs. Delegación de eventos
- Gestión (asociar un evento por elemento)
<ul id="miNav"> <li><a href="#nosotros">¿Quienes Somos?</a></li> <li><a href="#objetivos">Los objetivos</a></li> <li><a href="#equipo">Nuestro Equipo</a></li> <li><a href="#detalles">Más detalles</a></li> <li><a href="#contacta">Contactanos</a></li> </ul>
var miNav = document.getElementById("miNav"); var miNavLinks = miNav.getElementsByTagName("a"); for (var i = 0; i < miNavLinks.length; i++) { miNavLinks[i].onclick = function(){ console.info(this.innerHTML); } }
- Delegación (asociar un único evento al padre de los elementos)
<ul id="miNav"> <li><a href="#nosotros">¿Quienes Somos?</a></li> <li><a href="#objetivos">Los objetivos</a></li> <li><a href="#equipo">Nuestro Equipo</a></li> <li><a href="#detalles">Más detalles</a></li> <li><a href="#contacta">Contactanos</a></li> </ul>
var miNav = document.getElementById("miNav"); miNav.onclick = function(evento){ var evento = evento || window.event; var elemento = evento.target || evento.srcElement; console.info(elemento.innerHTML); }
-
Convencional:
- getElementById():
// <tag id = x > document.getElementById("id");
- getElementsByName():
// <tag name = x > document.getElementsByName("fname");
- getElementsByTagName():
// <tag > document.getElementsByTagName("input");
-
Selectores CSS3:
- URL que empieza con "javascript:"
a[href^="javascript:"] {color:blue;}
- URL que contiene "google.es"
a[href*="google.es"] {color:orange;}
- URL que termina con ".pdf"
a[href$=".pdf"] {color:red;}
-
Comprobando disponibilidad del API:
// op.1 - Positivo
if( document.querySelector && document.querySelectorAll ){
console.info("querySelector() y querySelectorAll() estan soportados!!")
}
// op.2 - Negativo
if( typeof document.querySelector !== "function" && typeof document.querySelectorAll !== "function" ){
console.warn("querySelector() y querySelectorAll() no estan soportados!!")
}
- querySelector(): Devuelve el primer elemento que coincida con el selector
<div id="miDiv">
<span id="miId5" class="miClase" title="cinco"></span>
<span id="miId4" class="miClase" title="cuatro"></span>
<span id="miId3" class="miClase" title="tres"></span>
<span id="miId2" class="miClase" title="dos"></span>
<span id="miId1" class="miClase" title="uno"></span>
</div>
document.getElementById('miId1').title // uno
document.querySelector('#miDiv .miClase').title // cinco
document.querySelector('#miDiv #miId1.miClase').title // uno
document.querySelector('#miDiv .inventado').title // ERROR -> undefined
document.querySelector('#miDiv .miClase[title^=u]').title // uno
- querySelectorAll(): Devuelve todos los elementos que coincida con el selector en un array
document.querySelectorAll('#miDiv .miClase') // [<span id="miId5" ... ]
document.querySelectorAll('p') // todos los parrafos
document.querySelectorAll('div, img') // todos los divs e imágenes
document.querySelectorAll('a > img') // todos las imágenes contenidas en enlaces
-
Convencional:
- Cookies:
- Espacio limitado (4kb)
- Por cada petición HTTP se envia y recibe todo el contenido
- Caducidad
-
Tipos:
- SessionStorage (Solo se almacenan los datos durante la sesión)
- LocalStorage (Almacenamiento persistente)
- GlobalStorage (Experimental - No usar)
-
Uso y limitaciones:
- 5-10Mb según navegador
- Almacenamiento local
- Sin caducidad
- Funcionamiento clave/valor
- Solo se permite el almacenamiento de cadenas de texto.
-
Problemas Conocidos:
- IE 8 y 9 almacena los datos basandose unicamente en el hostname, ignorando el protocolo (http/https) y el puerto.
- En iOS 5 y 6 los datos se almacenan en una localización que puede ser borrada ocasionalmente por el SO.
- Usando el modo "navegación privada" Safari, Safari para IOs y Navegadores Android no soportan sessionStorage o localStorage.
- En IE al acceder a LocalStorage desde local, el objeto localStorage pasa a ser undefined.
- Internet Explorer no soporta el almacenamiento de casi ninguna cadena de carácteres ASCII con una logitud menor a 20.
- En IE el evento "storage" genera errores:
- IE10 : Se dispara el evento al usar iframes.
- IE11 : Se confunden el valor antiguo con el nuevo valor (actualizado).
- IE10 en Windows 8 puede presentar el siguiente mensaje de error "SCRIPT5: Access is denied" if "integrity" settings are not set correctly.
- Chrome en Local no funciona correctamente
-
Métodos de LocalStorage
- setItem() Guardando datos
localStorage.setItem('clave', 'valor');
- getItem() Recuperar un valor
console.info(localStorage.getItem('clave'));
- length() Total de elementos
console.info(localStorage.length);
- removeItem() Eliminar un elemento
localStorage.removeItem('clave');
-
Comprobación
if (window.localStorage) {
console.info("La función Html5 localStorage está soportada");
} else {
console.warn('Su navegador no soporta localStorage');
}
if (window.sessionStorage) {
console.info('La función Html5 sessionStorage está soportada');
} else {
console.warn('Su navegador no soporta sessionStorage');
}
- Usando json en LocalStorage
var objeto = {
numero: 1,
booleano : true,
array: ["dato", true, 2],
cadena: "dato"
};
localStorage.setItem('clave', JSON.stringify(objeto));
var objetoRecuperado = JSON.parse(localStorage.getItem('clave'));
console.log(objetoRecuperado.booleano);
-
Eventos asociados
- key: es la clave que se modifica
- oldValue: es el valor anterior de la clave que se modifica
- newValue: es el nuevo valor de la clave que se modifica
- url: la página donde se modifica la clave
- storageArea: el objeto donde se modifica la clave
- Usa dos Pestañas
-
Ejercicios:
- Sacar todas las claves guardadas
for (var key in localStorage){ console.log(key) }
- Sacar todos los valores
for ( var i = 0; i < localStorage.length; i++ ) { console.log( localStorage.getItem( localStorage.key( i ) ) ); }
- Utiliza los eventos para monitorizar tu aplicación:
document.addEventListener('storage', function(event){ console.info("Se registran cambios en "+event.key+". El valor pasó de ser "+event.oldValue+" a "+event.newValue+".\nRecuerda que estas en "+event.url+" y usando el almacenamiento "+event.storageArea); });
-
Ejercicios
- Libreta de contactos (Básica)
// Tu solución
-
Convencional:
- Campos de texto
- Formularios
-
Comprobación:
if (!document.body.contentEditable) {
console.warn("No se puede utilizar contentEditable :-(");
} else {
console.info("Podemos utilizar contentEditable :-)");
}
-
Usando contentEditable
- Atributo contentEditable (true, false, inherit)
<!-- estilos: [contenteditable] y [contenteditable]:hover --> <!DOCTYPE html> <html> <body> <div contentEditable="true"> Modificame... tanto como quieras! </div> </body> </html
- designMode (editando todo el documento)
window.document.designMode = "on"; // off, por defecto
-
spellcheck (editando todo el documento)
<!DOCTYPE html> <html> <body> <div contentEditable="true" spellcheck="true"> Modificame... tanto como quieras! </div> </body> </html
-
Uso y limitaciones:
- Aplicación disponible independientemente del estado de la conexión
- Se acelera la carga de los archivos
- Disminuyen las consultas al servidor
- En algunos navegadores es necesario que el usuario permita el almacenamiento
-
Comprobación:
if (!window.applicationCache) {
console.warn("No se puede utilizar applicationCache :-(");
} else {
console.info("Podemos utilizar applicationCache :-)");
}
- Verificando la conexión:
if (window.navigator.onLine) {
var detalles = "<h1>Estas Conectado a Internet!!</h1>";
detalles += "<h3>Detalles del navegador:</h3>";
detalles += "<p>CodeName: " + navigator.appCodeName + "</p>";
detalles += "<p>Nombre: " + navigator.appName + "</p>";
detalles += "<p>Versión: " + navigator.appVersion + "</p>";
detalles += "<p>Cookies Habilitadas: " + navigator.cookieEnabled + "</p>";
detalles += "<p>Lenguaje: " + navigator.language + "</p>";
detalles += "<p>Plataforma: " + navigator.platform + "</p>";
detalles += "<p>User-agent header: " + navigator.userAgent + "</p>";
document.body.innerHTML = detalles;
} else {
document.body.innerHTML = "<h1>No estas Conectado!!</h1>"
console.warn("No estamos conectados a Internet!");
}
- Verificando la conexión usando eventos:
window.addEventListener("offline", function(){
console.warn("Estas desconectado!")
});
window.addEventListener("online", function(){
console.info("Estas conectado!")
});
-
Usando Cache (manifest):
-
Uso:
- Los archivos son visibles en la pestaña Resources/Application Cache
- Extensión .appcache (asegurarnos del Content/Type)
- El atributo manifest puede señalar a una URL pero deben tener el mismo origen que la aplicación web
- Los sitios no pueden tener más de 5MB de datos almacenados en caché, pueden ser menos si el usuario lo cambia.
- Si no se puede descargar el archivo de manifiesto o algún recurso especificado en él, fallará todo el proceso de actualización de la caché.
- Añadir la versión del manifest como comentario.
- JAMAS incluir el propio manifest dentro del manifest
- Nuevo sistema de carga:
- Si existe manifest, el navegador carga el documento y sus recursos asociados directamente desde local.
- Se verifica si hubo actualizaciones al manifest.
- Si se actualizo, el navegador descarga la nueva versión del archivo y de los recursos listados en él (segundo plano).
-
Estructura
- CACHE, lo que se cacheará
- NETWORK, lo que NO se cacheará
- FALLBACK, que se visualizará si algo no esta disponible
-
Incluyendo el manifest
<html manifest="ejemplo.appcache"> <!-- ... --> </html>
- Ejemplo de Manifest
CACHE MANIFEST # versión 1.0 # SI CACHEAR CACHE: index.html offline.html css/style.css js/script.js img1.jpg img2.jpg img3.jpg logo.png # Mostraremos offline.html cuando algo falle FALLBACK: offline.html # NO CACHEAR NETWORK: * # * es todo aquello que no este en CACHE
-
-
Estados de Cache (manifest):
var appCache = window.applicationCache;
switch (appCache.status) {
case appCache.UNCACHED: // appCache.status == 0
console.warn('Un objeto caché de la aplicación no se inicializó correctamente o falló.');
break;
case appCache.IDLE: // appCache.status == 1
console.info('La caché no esta en uso.');
break;
case appCache.CHECKING: // appCache.status == 2
console.info('El manifesto se ha obtenido y esta siendo revisado para actualizarse.');
break;
case appCache.DOWNLOADING: // appCache.status == 3
console.info('Se estan descargando nuevos recursos debido a una actualización del manifesto.');
break;
case appCache.UPDATEREADY: // appCache.status == 4
console.info('Hay una nueva versión del manifiesto.');
break;
case appCache.OBSOLETE: // appCache.status == 5
console.info('El caché esta ahora obsoleto');
break;
default:
console.warn('El Caché esta en estado desconocido');
break;
};
- Eventos de Cache:
function eventosCache(){
var appCache = window.applicationCache;
appCache.addEventListener('cached', chivato);
appCache.addEventListener('checking', chivato);
appCache.addEventListener('downloading', chivato);
appCache.addEventListener('error', chivato);
appCache.addEventListener('noupdate', chivato);
appCache.addEventListener('obsolete', chivato);
appCache.addEventListener('progress', chivato);
appCache.addEventListener('updateready', chivato);
function chivato(e) {
var conexion = (navigator.onLine) ? 'sí': 'no';
var type = e.type;
console.log('Conectado: ' + conexion+', Evento: ' + type +", \nMás Información: %O", e);
}
}
- Forzar la actualización (manualmente):
var appCache = window.applicationCache;
appCache.update(); // Intentamos actualizar la versión del usuario con un nuevo manifest
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); // La ctualización es correcta y se cambiado a la nueva versión
}
Ejercicio
1 - Adaptamos una aplicación para que funcione offline
// Tu solución
- Comprobación:
if (!window.history) {
console.warn("No se puede utilizar history :-(");
} else {
console.info("Podemos utilizar history :-)");
}
-
Métodos de History
- length (total de entradas disponibles en el historial)
console.info(window.history.length);
- go (hacia delante o hacia atras en función del numero)
window.history.go(-1);// <- 1 window.history.go(2); // 2 -> window.history.go(0); // refresh // sí te sales de rango, no pasa nada.
- back (retrocede)
window.history.back()
- forward (avanza)
window.history.forward()
-
Métodos Avanzados de History
- pushState (añadir entradas al historial)
// pushState(data, title , url) window.history.pushState({pag: 1}, "titulo 1", "?pag=1"); console.log(history.state)
- replaceState (remplazar entradas en el historial)
// replaceState(data, title , url) window.history.replaceState({pag: 5}, "titulo 5", "?pag=5"); console.log(history.state)
-
Eventos de History
- onpopstate (monitorizar cambios en el historial)
window.onpopstate = function(event) { console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); };