domingo, 8 de abril de 2012

Array de objetos en JavaScript

Array de objetos en JavaScript



Objetos en nuestra Array: (Abre la consola de JavaScript para ver el objeto directamente)







Buenas tardes!

Hoy toca explicar como hacer una array de objetos usando JavaScript. Es posible que normalmente estemos acostumbrados a trabajar con un Array de numeros como este:

var array = [0,1,2,3,4,5,6]

Donde cada posición es un numero (integer) o cadenas de caracteres. Pero en ocasiones, los numeros o cadenas de caracteres se nos quedan cortos y debemos crear un objeto en cada posicion. Por lo tanto, en algun momento de la implementacion de nuestro programa nos puede interesar hacer un Array de objetos como los del ejemplo anterior (arriba del todo).

Probad de añadir elementos rellenando los campos de 'Nombre', 'Tipo', 'Texto' con lo que queráis. Una vez rellenados apretad al botón 'Añadir Objeto'.
Podremos ver nuestra Array con sus objetos dentro.

Para eliminar objetos basta con rellenar el campo valor y seleccionar el atributo que queremos usar para decidir qué elemento eliminar. Por ejemplo:
Si en 'valor' especificamos: 'aa'  (sin las comillas)   y en el select dejamos seleccionado 'Nombre' nos eliminará todos los objetos de nuestra Array que contenga en el atributo 'nombre' el valor 'aa'.

El código en si es bien simple, hay algunos elementos secundarios (básicamente estilos de CSS) que no forman parte de la estructura básica del objetivo del snipet.

El código fuente es el siguiente:


<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<style type="text/css">
.muestra-objeto {
display: inline;
float: left;
overflow: auto;
width: 180px;
height: 180px;
background-color: aliceBlue;
border-color: red;
}
</style>

<script>
//Inicializamos el array i el objeto.
var array = new Array();
var objeto = {"nombre": null,"tipo": null, "timestamp": null, "texto": null};


function afegirObjecte(divs) {

console.log("Objeto directamente del formulario:");
console.log(divs);
//Extraemos lo que nos interesa de los divs y definimos el timestamp:
var nombre = divs.childNodes[1].value;
var tipo = divs.childNodes[3].value;
var texto = divs.childNodes[5].value
var timestamp = new Date().getTime();

//Insertamos objeto en Array:
array.push({"nombre": nombre,"tipo": tipo, "timestamp": timestamp, "texto": texto});
console.log("Array despues de añadir este objeto: ");
console.log(array);
mostrarObjetosArray()
}

//Para eliminar un objeto debemos especificar cuál queremos eliminar. Para ello definimos dos parametros en la función
//filtro: sera uno de los atributos del objeto: nombre, tipo, texto o timestamp
//valor: aquel objeto que en el filtro que hemos definido contenga el valor aquí indicado será el elegido para eliminar.

function eliminarObjeto(divs) {

console.log("Objeto directamente del formulario:");
console.log(divs);
var valor = divs.childNodes[1].value;
var filtro = (divs.childNodes[3].value).toLowerCase(); //Recordemos que es sensible a mayusculas y minusculas (lo pasamos a minusculas).
var arrayTemp = new Array();
for (var i = 0; i < array.length; i++) {

if (array[i][filtro] != valor) {
arrayTemp.push(array[i]);
}
}
if (array.length == arrayTemp.length) {
alert("No se ha eliminado nada. \nRecuerda que 'valor' y filtro deben coincidir i existir en la array principal.");
}
array = arrayTemp;
console.log("Array despues de eliminar el objeto: ");
console.log(array);
mostrarObjetosArray()
}

function mostrarObjetosArray() {

var content = document.getElementById("mostrar-array");
while (content.hasChildNodes() == true) { //Eliminamos todo lo que hay en pantalla, del objeto y lo generaremos de nuevo.
content.removeChild(content.childNodes[0])
}
for (var i = 0; i < array.length; i++) { //Para cada elemento existente en la array
var div = document.createElement("fieldset"); //Creamos un div (cuadrado azulado en la pantalla);
div.className = "muestra-objeto"
var divNombre = document.createElement("div");
divNombre.textContent = "-Nombre: "+array[i].nombre;
var divTipo = document.createElement("div");
divTipo.textContent = "-Tipo: "+array[i].tipo;
var divTimestamp = document.createElement("div");
divTimestamp.textContent = "-Dia/Hora: "+new Date(array[i].timestamp).toUTCString();
var divTexto = document.createElement("div");
divTexto.textContent = "-Texto: "+array[i].texto;
div.appendChild(divNombre);
div.appendChild(document.createElement("hr"));
div.appendChild(divTipo);
div.appendChild(document.createElement("hr"));
div.appendChild(divTimestamp);
div.appendChild(document.createElement("hr"));
div.appendChild(divTexto);
content.appendChild(div);
}
}
</script>
</head>
<body>
<div style="width: 100%">
<fieldset style="display: inline;float:left;">
<div id="formulario">
<input type="text" placeholder="Nombre" id="nombre" />
<input type="text" placeholder="Tipo" id="tipo" />
<input type="text" placeholder="Texto" id="texto" />
<input type="button" value="Añadir objeto" onclick="afegirObjecte(document.getElementById('formulario'))" />
</div>
</fieldset>
<fieldset style="display: inline;float:left;">
<div id="formulario-eliminar">
<input type="text" placeholder="Valor" id="valor" />
<select>
<option>Nombre</option>
<option>Tipo</option>
<option>Texto</option>
</select>
<input type="button" value="Eliminar Objetos" onclick="eliminarObjeto(document.getElementById('formulario-eliminar'))" />
</div>
</fieldset>
</div>
<br />
<fieldset style="float:left;display: block;width:100%;">
<div>
<p>Objetos en nuestra Array: (Abre la consola de JavaScript para ver el objeto directamente) </p>
<div id="mostrar-array"></div>
</div>
</fieldset>
</body>
</html>

sábado, 7 de abril de 2012

"Capicua" o "Palindromo" en JavaScript

"Capicua" o "Palindromo" en JavaScript


Buenas tardes a todos!

Después de un tiempo sin redactar nada.. vuelvo a la carga con un pequeño snipet que puede ayudar a los mas nobeles en programación.
Como comprobar si una palabra es capicua (palindromo) usando una función de JavaScript.

La forma humana de resolver este problema es intentar leer la palabra al revés y fijarnos si el orden de las letras es el mismo que si se lee normal. Pues eso mismo se puede implementar usando la programación.

Para ello declaramos el método .reverse para las cadenas de caracteres (palabras), ya que por defecto JavaScript no trae esta función. Para ello se usa la propiedad prototype que nos permite construir métodos para un tipo de dato.

Llegados a este punto, lo demás es muy sencillo, simplemente comprobar si la palabra al revés es igual que la palabra normal.

Codigo fuente:




<html>
<head>
<script>

     //Definimos un metodo para el tipo de datos "string", que lo unico que hace es devolver nuestra palabra en orden inverso.
String.prototype.reverse=function(){return this.split("").reverse().join("");}

function testCapCua(word) {


//Una vez definido, ya lo tenemos practicamente hecho.
var inverseWord = word.reverse();
if (word == inverseWord) { //Si la palabra es igual a la palabra girada.
alert("La palabra '"+word+"' SI es cap i cua");
return(true); //Es capicua/palindromo.
}
else {
alert("La palabra '"+word+"' NO es cap i cua: '"+inverseWord+"'");
return(false); //NO es capicua/palindromo.
}
}
</script>
</head>

<body>
<input type="text" placeholder="Introducir palabra." id="input-word" />
<input type="button" onclick="testCapCua(document.getElementById('input-word').value)" value="Comprobar"/>
</body>
</html>

lunes, 26 de diciembre de 2011

Evitar cache del navegador en Google FT

Seguimos hablando de Google Fusion Tables.

Presentación del problema

A veces podemos encontrarnos con la necesidad de querer actualizar los marcadores de un mapa usando la información actualizada de una tabla de Google Fusion Tables.

El problema que hay, es que si lanzamos una query a la base de datos, si la sentencia es idéntica que en otro caso anterior, el navegador en vez de hacer la llamada al servidor, se pasea por la caché de nuestro navegador en busca del resultado obtenido anteriormente con esa misma sentencia.

Eso puede darnos muchos dolores de cabeza, ya que si estamos haciendo un seguimiento en 'tiempo real' de algún transmisor GPS que nos envía la información en FT, la query puede ser siempre la misma, pero el resultado no debería ser el mismo.

Resumen del problema:
"Hacemos una query a Google Fusion Tables y nos devuelve siempre el mismo resultado aunque la tabla haya sido modificada y sabemos que este resultado no es correcto."

Nuestra query por ahora será algo así:

SELECT lat,lng FROM 2455909 ORDER BY timestamp DESC LIMIT 1
La traducción de esta query a lenguaje humano sería: Seleccionar las columnas Latitud y Longitud de la tabla 2455909 y ordenarla en función de la columna 'timestamp' en decreciente y limita la respuesta a 1 sola fila.

Ahora deberemos añadir alguna fila en nuestra tabla, para ello usaremos la interfaz de Google Fusion Tables y añadiremos manualmente la fila. Tener en cuenta que si usáis mi tabla de prueba, la columna 'timestamp' debéis poner un numero SIEMPRE mayor a cualquier otro. El 'timestamp' es lo que identifica que esa fila añadida sea la última, y si queremos obtener la fila más actualizada, deberemos hacer un SELECT a la fila con un 'timestamp' más grande.

Realizamos otra vez la Query anterior y... Qué observamos? El resultado sigue siendo el mismo que antes de añadir la fila.
Si probamos de borrar la cache del navegador y volver a hacer la query veremos que funciona correctamente.

Solución


Para evitar esto, podemos añadir una condición a la query que SIEMPRE cambie un poco y sobretodo que estemos 100% seguros de que no se repita nunca en cualquiera de los casos.
Para ello podemos jugar con el 'timestamp', en JavaScript podemos usar la funcion Date():
Creamos una función en nuestro JS:
function update() {
    var tempsAct = new Date();
    var milisec = tempsAct.getTime();
    return (milisec);
}

Y en nuestra Query hacemos referencia a nuestra función, para que la llame siempre que hagamos la query:

var query = "SELECT lat,lng FROM 2455909 WHERE lat NOT EQUAL TO "+update()+" ORDER BY timestamp DESC LIMIT 1";

Como veis, hemos añadido la función 'update()' dentro de la query. Esto hará que nuestra Query sea SIEMPRE distinta y de esa forma el navegador nunca podrá usar la caché.

Hay que decir que la variable milisec tendremos que actualizarla cada vez que querramos

Por cierto, 'timestamp' son los milisegundos transcurridos desde el 01/01/1970, con lo cual, como no podemos hacer mas de 1 query por ms en Google FT, esta solución es perfectamente válida.

Espero que os haya servido de ayuda, si tenéis alguna duda poneros en contacto conmigo.

Saludos!

sábado, 24 de diciembre de 2011

SELECT usando JavaScript en Google FT

Google Fusion Tables


Para los que busquen una base de datos simplificada y que esté siempre disponible, Google nos ofrece una solución muy interesante. Google Fusion Tables es una base de datos relacional en la nube.

Las ventajas que nos aporta es despreocuparnos de toda la infraestructura que conlleva dedicar un servidor a una base de datos, ya sea seguridad, configuraciones, averías, gastos de mantenimiento, ...

Si decidimos usar esta base de datos en nuestra aplicación Web usando JavaScript, debemos tener en cuenta que aún está en desarrollo y que aún le queda añadir algunas funcionalidades para hacer la vida más cómoda a los programadores. El ejemplo clave es no tener un método definido para hacer queries al servicio usando los metodos GET y POST.

Voy a comentar una manera fácil para solicitar datos a Google Fusion Tables, usando el método GET y con la ayuda de JSONP podremos evitar la limitación del Cross-domain en JavaScript de los navegadores modernos:

Codigo JavaScript
function obtenirDadesFT() {

var queryUrlHead = 'http://www.google.com/fusiontables/api/query?sql=';
    //Tenemos que indicar el nombre de la funcion donde enviaremos los datos obtenidos.
var queryUrlTail = '&jsonCallback=tractarDades';
 
   // escribimos la query normal:
var query = "SELECT name FROM 839090 limit 1";
    var queryurl = encodeURI(queryUrlHead + query + queryUrlTail);

          //Hacemos la peticion GET a Fusion Tables usando JSONP:
$.get(queryurl, dataHandler, "jsonp");
}
         //Los datos obtenidos se almacenan en la variable 'data', y tractarDades es la función que hemos indicado más arriba:
        // La variable 'data' es un objeto JSON, por lo tanto usaremos la mecánica propia del objeto para tratar su información, en este caso representamos las filas obtenidas de la Query:

function tractarDades(data) {

alert(data.table.rows);
}

Hay que tener en cuenta que la función $.get es de jQuery, por lo tanto en el HTML deberemos incluir la siguiente etiqueta:

<html>

<head>
                //El codigo JavaScript anterior lo tengo en un archivo en la misma carpeta, llamado funcions.js.
<script src="funcions.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

</head>
<body>
<div>

<input type="button" value="obtenirDadesFT" onclick="obtenirDadesFT()">

</div>
</body>
</html>

Espero que haya sido de utilidad. Solamente comentar que este método nos servirá para hacer Queries del tipo SELECT. Para hacer Queries del tipo INSERT deberemos esperar un tiempo más, porque en JavaScript no existe la posibilidad de hacerlo por el momento. Pronto tendremos alguna solución.

PD: Felices fiestas a tod@s!

viernes, 23 de diciembre de 2011

Usando PhoneGap

Bueno, para empezar a hablar de algo interesante, hablaré de PhoneGap.

Qué es?

          PhoneGap es un framework basado en HTML5 que nos permite crear aplicaciones web pudiendo acceder a dispositivos del teléfono tales como GPS, agenda, cámara, sistema de archivos, ... como si de una aplicación nativa se tratara.

         Además la principal ventaja que ofrece es que si deseamos hacer una misma aplicación para distintas plataformas (Android, iOS, BlackBerry, Symbian, Windows Phone 7, Web OS) un mismo código nos servirá para todas las plataformas.

Cómo funciona?


          Básicamente tienes que desarrollar una página web teniendo en cuenta que si usas PhoneGap es porqué querrás ejecutarla en un teléfono móvil y por lo tanto deberás tener en cuenta que el tamaño de la pantalla es reducido.

          Hay frameworks como jQuery Mobile que te pueden facilitar mucho el tema de la interfaz y dar la sensación de estar ejecutando una aplicación nativa, hay otros Frameworks como Kendo UI que también ofrece muchas posibilidades.

          Una vez hecha la aplicación web, se empaqueta con PhoneGap para el dispositivo al que vaya destinado. Como ya mencioné antes, el código nos sirve el mismo para todas las plataformas, pero deberemos empaquetarlos de distintas maneras.

Referencia:


http://phonegap.com/


       


Estrenando Blog!

Buenas tardes a tod@s, éste es mi primer mensaje en el Blog.

Espero que el Blog sea una herramienta productiva para mi y todos los que me estéis leyendo ahora.

Un saludo.