Arquivo do autor:andremenegassi

Chamadas XMLHttpRequest (AJAX) enviando JSON para páginas aspx ou GenericHandler – Deserialização manual

json160 csharplogoOlá pessoal,

Realmente é muito simples realizar uma chamada XMLHttpRequest (AJAX) para um WebMethod ASP.NET. E mais fácil ainda é enviar dados no formato JSON para o WebMethod, pois por padrão o WebMethod deserealizada a string JSON conforme seus parâmetros.

Mas quando não temos um WebMethod para receber os dados no formato JSON e fazer todo o trabalho de sujo de deserialização? Por exemplo, ao fazer chamadas XMLHttpRequest para uma página ou um Generic Handler passando dados no formato JSON. Nesta situação é necessário realizar a deserialização dos dados manualmente, vamos a um exemplo.

Chamada XMLHttpRequest no lado cliente:

var request = $.ajax({
type: "POST",
dataType: "json",
url: "/meusite/processa.ashx",
cache: false,
data: JSON.stringify({ p1: "oi", p2: 1000, vet: [{ vp1: {vp2: "xxxx"}},2] })

});

request.done(function (r) {
console.log(r);
});

request.fail(function () {
alert("Não foi possível processar sua requisição.");
});

O código acima utiliza a biblioteca jQuery para encapsular o uso da biblioteca javascript XMLHttpResquest e enviar dados ao servidor. Em sua configuração, a propriedade “URL” indica um GenericHandler no servidor (processa.ashx), mas que também pode ser substituído por uma página aspx. E a propriedade “data” foi configurada com um objeto literal com propriedades simples e complexas, que antes de ser enviado ao servidor será transformando numa string JSON pelo método JSON.stringify.

No lado servidor (no GenericHandler ou no método page_load da página), a recepção dos dados fica assim:

JavaScriptSerializer jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();

Dictionary<string, object> values = jss.Deserialize<Dictionary<string, object>>(json);

string p1 = values["p1"].ToString();
int p2 = Convert.ToInt32(values["p2"]);

var vet = (ArrayList)values["vet"];
var vp1 = ((Dictionary<string, object>)vet[0])["vp1"];
var vp2 = ((Dictionary<string, object>)vp1)["vp2"];

No código de servidor acima, a propriedade InputStream do objeto Request representa o conteúdo do corpo de entrada de conteúdo HTTP vindo do cliente, portanto, representa a string JSON enviada pelo cliente.

O inputString é recuperado e deserializado em um objeto Dictionary (espécie de lista indexada por chaves). Cada propriedade da string JSON torna-se uma chave do dicionário, sendo facilmente acessada:

int p1 = values["p1"].ToString();
int p2 = Convert.ToInt32(values["p2"]);

E também podemos acessar estruturas JSON mais complexas, como é o caso da propriedade “vet”, que mantém um vetor, cujo seu índice 0 (zero) contém outro objeto JSON.

vet: [{ vp1: {vp2: "xxxx"}},2]

Após recuperação do vetor, foi necessário converte o objeto de índíce 0 (zero) em outro Dictionary, desta forma, as propriedades do objeto contido no índice 0 (zero) da propriedade “vet” são acessadas por chaves do Dictionary.

var vp1 = ((Dictionary<string, object>)vet[0])["vp1"];
var vp2 = ((Dictionary<string, object>)vp1)["vp2"];

E fim.

Coleções em C# usando List

csharplogo

Nas linguagens de programação, o termo coleção é utilizado para definir estruturas capazes de agrupar objetos. Um simples vetor/array pode ser definido como uma coleção, neste caso, estática.

Em C# é facilmente possível criar coleções dinâmicas com o classe List<T>, disponível no namespace System.Collections.Generic.

Uma coleção gerada com List<T> fornece uma ótima opção, quando precisamos agrupar tipos de objetos (por exemplo, classes) de forma dinâmica e eficiente, e com métodos que possibilitam filtrar, ordenar e seus itens.

Vamos aos exemplos:

1 – Criando uma classe.

public class Pessoa
{
    int _id;

    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }
    string _nome;

    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }

    public Pessoa()
    {
        _id = 0;
        _nome = &quot;&quot;;
    }

    public Pessoa(int id, string nome)
    {
        this._id = id;
        this._nome = nome;
    }
}

2 – Criando e manipulando uma coleção da classe Pessoa (deve referenciar o namespace System.Collections.Generic).

using System.Collections.Generic;

//Criando uma lista que agrupará objetos da classe Pessoa.
List&lt;Pessoa&gt; pessoas = new List&lt;Pessoa&gt;();

//Adicionando objetos (tipo Pessoa) na lista.
pessoas.Add(new Pessoa(1, &quot;Andre&quot;));
pessoas.Add(new Pessoa(2, &quot;Brenda&quot;));

//Percorrendo a lista.
foreach (Pessoa p in pessoas)
{
   Console.WriteLine(p.Nome);
}

//Localizando uma pessoa.
Pessoa pessoa = pessoas.Find(delegate(Pessoa p1) { return p1.Id == 2; });

//Localizando várias pessoas que contenham no nome as letras &quot;nd&quot; (neste caso, o retorno é uma outra List&lt;Pessoas&gt; com as pessoas localizadas).
List&lt;Pessoa&gt; pessoasLocalizadas = pessoas.FindAll(delegate(Pessoa p1) { return p1.Nome.Contains(&quot;nd&quot;); });


//Removendo um item da lista pela sua posição.
pessoas.RemoveAt(0);

Mais detalhes em http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx.

Até…

Gerando estruturas JSON em C# e ASP.NET

json160Dando continuidade ao post Introdução ao JSON – Javascript Object Notation, mostro agora como construir em C# as estruturas dos exemplos utilizados no post anterior.

No C# podemos criar objetos de tipo anônimos (anonymous types) para definir a estrutura e dados, e depois realizar a serialização para o formato JSON.

Vamos aos exemplos:

1 – Criando um objeto.

public static string retornaObjetoJSON()
{
    //{“nome” : “Bill”, “idade” : 32, “salario”: 121232.67}

    var obj = new { nome = "Bill", idade = 32, salario = 121232.67};

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(obj);
    return strJson;
}

2 – Criando um array.

public static string retornaArrayJSON()
{
    //["Huguinho","Zezinho","Luizinho", 3]

    var objVet = new object[] { "Huguinho", "Zezinho", "Luizinho", 3 };

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(objVet);
    return strJson;
}

3 – Criando um array de objetos.

public static string retornaVetorDeObjetoJSON()
{
    /*
        [{ "nome" : "Huguinho", "idade" : 10 },
        { "nome" : "Zezinho", "idade" : 12 },
        { "nome" : "Luizinho", "idade" : 10 }]
    */

    var objVet = new object[] { new { nome = "Huguinho", idade = 10 },
                                new { nome = "Zezinho", idade = 12 },
                                new { nome = "Luizinho", idade = 10 }};

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(objVet);
    return strJson;
}

4 – Criando um objeto contendo um propriedade array de objetos.

public static string retornaObjetoComVetorJSON()
{
    /*
        {"tio" : "Pato Donald",
        "idade" : 40,
        "sobrinhos" :
                [{ "nome" : "Huguinho",     "idade" : 10 },
                { "nome" : "Zezinho", "idade" : 12 },
                { "nome" : "Luizinho", "idade" : 10 }]
        }
    */

    var obj = new {tio = "Pato Donald",
                    idade = 40,
                    sobrinhos = new object[] { new { nome = "Huguinho", idade = 10 },
                                                new { nome = "Zezinho", idade = 12 },
                                                new { nome = "Luizinho", idade = 10 }}
                    };

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(obj);
    return strJson;
}

A biblioteca System.Web.Script.Serialization é a responsável por realizar a serialização dos objetos anônimos.

Logo mais num outro post mostro como realizar chamadas assíncronas por Javascript ao JSON gerado no C# no servidor.

Até…

Validações customizadas com HTML5

HTML5_Logo_512Quando as validações prontas do HTML5 não são suficientes, temos que fazer as nossas.

Em HTML5 temos um novo evento, oninput,  que pode ser associado a um input, e é disparado quando seu valor é modificado. Seu disparo deve ser associado a uma função Javascript para fazer a validação do valor informado no input.

Na função de validação o método setCustomValidity do input recebe uma string. Se vazia, significa que o dado está válido, caso contrário, o navegador mostrará a mensagem informada ao método.

Vamos a um exemplo:

&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;&lt;/title&gt;
    &lt;script&gt;

        function validaCPF(input){

            if (input.value.length &gt; 11 || input.value.length &lt; 11)
                input.setCustomValidity('CPF inválido');
            else input.setCustomValidity('');

        }

    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form&gt;

            CPF:
            &lt;input type=&quot;text&quot; id=&quot;cpf&quot; name=&quot;cpf&quot; oninput=&quot;validaCPF(this)&quot;&gt;
            &lt;input type=&quot;submit&quot; id=&quot;enviar&quot; name=&quot;enviar&quot; value=&quot;Enviar&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;

 

Se seu querido navegador der suporte ao novo evento, algo como mostrado na imagem abaixo deve aparecer.

evento_oninput

 

 

Simples e eficiente.

CSS3: font-face

css31Um problema comum no desenvolvimento de um site é a tipografia (tipo da fonte). É normal o uso de fontes comuns (Arial, tahoma, verdana, etc), que existem nos sistemas operacionais dos diversos dispositivos capazes de executar um website.


font-family: Arial, Verdana, Sans-Serif;

Caso a fonte não exista, o navegador tenta assumir uma próxima fonte que foi definida no CSS (font-family). E se também não encontrar, o navegador vai assumir sua fonte padrão, o que pode “estragar” toda aparência do site.

Com CSS3 conseguimos forçar o navegador a baixar uma fonte caso ela não exista no sistema operacional do dispositivo. Isso pode ser implementado com o uso da diretiva @font-face, e é suportada somente nos navegador mais modernos (IE 9, Firefox, Opera, Chrome e Safari). A fonte deve estar disponível em algum servidor, que pode ser o do próprio site.

A especificação do W3C (http://www.w3.org/TR/css3-fonts/) relaciona os seguintes formatos de fontes suportados pelo font-face:

String Font Format Common extensions
“woff” WOFF (Web Open Font Format) .woff
“truetype” TrueType .ttf
“opentype” OpenType .ttf, .otf
“embedded-opentype” Embedded OpenType .eot
“svg” SVG Font .svg, .svgz

O diretiva @font-face deve estar dentro do arquivo CSS do site:


@font-face {
  font-family: 'Open Sans';
  src: local('Open Sans Light'),
       local('OpenSans-Light'),
       url(http://themes.googleusercontent.com/static/fonts/opensans/v6/DXI1ORHCpsQm3Vp6mXoaTXhCUOGz7vYGh680lGh-uXM.woff) format('woff');
}

body { font-family: 'Open Sans', Arial, Verdana, Sans-Serif; }
}

Na diretiva @font-face as propriedades especificão:

  • font-family: o nome a a ser usado na regra font-family dos elementos HTML (no exemplo foi aplicado ao body).
  • src: a origem da fonte, sendo que primeiro será procurada localmente (local(‘..’)) no sistema operacional uma fonte com o nome ‘Open Sans Light’, se não encontrar vai procurar ainda localmente (local(‘..’)) um fonte como o nome ‘OpenSans-Light’, e caso não entre localmente, baixará a fonte no servidor informado em url(…). No exemplo acima a fonte está disponível no servidor do Google, mas poderia estar no próprio servidor do site.

Antes de fazer o font-face, é  necessário verificar a licença da fonte para não ter problemas de uso indevido.

Mais detalhes em:

Até mais.

WebWorkers

HTML5_Logo_512A execução de código Javascript é feita somente usando uma thread pelo navegador cliente. O navegador nunca vai executar dois eventos ao mesmo tempo. Funcões Javascript que tem execução mais longa travam a interface com o usuário até que termine sua execução.

As aplicações Web podem rodar melhor se as partes do código Javascript que exigem maior processamento fossem separadas em mais threads.

Execute dentro de uma página o código Javascript abaixo que simula um processamento demorado e tente usar a interface da página. Tudo estará travado, até que a execução do código termine.


function execucaoDemorada(){

    var tempoDeEspera = 10000; //10 segundos
    var inicio = (new Date()).getTime();
    var i = 0;
    while(((new Date()).getTime() - inicio) &lt;= tempoDeEspera){
        console.log(i);
        i++;
    }
}

Em HTML5 é possível usar Web Workers, que dá poder ao Javascript em executar thread paralelas sem bloquear/travar a interface com o usuário.

Um WebWorker não deve ser usado para operações triviais, e sim para operações complexas e longas:

  • Codificação/decodificação de uma sequência grande;
  • Cálculos matemáticos complexos (por exemplo, números primos, criptografia, simulados, algoritmos de reconhecimentos, etc);
  • Classificando uma grande variedade de dados;
  • Solicitações de rede e processamento de dados;
  • Cálculos e manipulação de dados sobre o local/sessionStorage;
  • Algoritmo de verificação/checagem de sintaxe ou análise outro texto em tempo real (por exemplo, a verificação ortográfica);
  • Manipulação de Imagem;
  • Analisar ou processar vídeo ou dados de áudio (incluindo face e reconhecimento de voz);
  • Processamento de matrizes de grandes dimensões ou respostas JSON enormes;

Um worker nada mais é que um script que irá ser carregado e executado em segundo plano, por exemplo:


var wk1 = new Worker(&quot;worker1.js&quot;);

A função construtura Worker() recebe por parâmetro uma URL especificando o arquivo contendo o código Javascript que será tratado em um nova thread,

O código javascript contido no arquivo carregado pelo worker não tem acesso ao objeto Window, Document e a árvore DOM da página que iniciou sua execução.

A comunicação entre o worker e a página ocorre através de mensagens. Objeto gerado pela classe Work oferece o método postMessage(). É ele que vai enviar solicitações da página para o código dentro do workers.  Além de enviar string, oferece envio de mensagens no no formato JSON. E as mensagens de retorno podem ser capturada associando uma função ao evento  do objeto worker criado.


//Código na página.

var wk1 = new Worker(&quot;worker1.js&quot;); //Criando o worker

//Monitorando as mensagens de retorno.
wk1.onmessage = function (e) {
    if (e.data.acao == &quot;mostrar&quot;)
        document.getElementById(&quot;incrementos&quot;).innerHTML = e.data.incremento;
    else if (e.data.acao == &quot;parar&quot;)
        wk1.terminate();
};

//É aqui que começa a execução do worker
wk1.postMessage(&quot;executar&quot;);

O evento onmessage fica monitorando as mensagens vindas worker para página. A função que vai tratar o evento recebe um parâmetro que possui uma propriedade data que contem a mensagem enviada pelo worker. No exemplo acima, o retorno a mensagem de retorno do worker é um objeto JSON.

O código contido no arquivo (do worker) também tem um evento onmessage e deve ter uma função associada, mas aqui é o worker que vai ficar escutando a página. Quando o método postMessage() na página é usado, é a função onmessage do worker que captura a mensagem que também é acessada pela propriedade data do parâmetro da função.

Para o worker enviar uma mensagem para a página, é também através do método postMessage().


//Código do worker.

// Evento que monita mensagens vindas da página para o worker
onmessage = function (e) {

    //e.data contém o valor enviado pela página.
    if (e.data === &quot;executar&quot;) {

        execucaoDemorada();

        postMessage(&quot;fim&quot;);
    }
};

function execucaoDemorada(){

    var tempoDeEspera = 10000; //10 segundos
    var inicio = (new Date()).getTime();
    var i = 0;
    while(((new Date()).getTime() - inicio) &lt;= tempoDeEspera){
        postMessage({ &quot;acao&quot;: &quot;mostrar&quot;, &quot;incremento&quot;: i }); //envia uma nova mensagem para a página
        i++;
    }
    postMessage({ &quot;acao&quot;: &quot;parar&quot;}); //envia uma nova mensagem para a página
}

Uma boa prática é fazer a liberação da thread na página pelo método terminate() do próprio objeto worker.

Outra informação importante é a possibilidade de ter páginas auto-suficiente, ou seja, o código a ser executado numa nova thread pode estar nela mesmo, sem a necessidade de separar num novo arquivo Javascript.

Até mais e baixe o exemplo aqui.

Introdução ao JSON – Javascript Object Notation

json160JSON é um formato para troca de dados baseado em estruturas de texto, o que lhe dá a característica de ser completamente independente de linguagem. É a mesma ideia do XML, só que mais simples e leve.

No site oficial (http://www.json.org/) o autor ainda afirma:

Para seres humanos, é fácil de ler e escrever.
Para máquinas, é fácil de interpretar e gerar.

A forma simples de representar dados no formato JSON tem difundido seu uso, e vem se tornando uma alternativa ao XML para implementações AJAX.

Em JSON podemos estruturar dados em (1) coleções de pares de nome e valor e também em (2) lista/array ordenadas de valores.

Os valores dos dados são representando em três formas: object, value e array, e ainda podem ser combinadas.

Object: é um conjunto de pares de nome/valores. A sintaxe de um object é


{ "nome da propriedade" : "valor da propriedade" }

O object começa com { e termina com }. E cada par de nome/valores é separado por ,(vírgula), sendo que os valores podem assumir diferente tipos de dados. Exemplo:


{“nome” : “Bill”, “idade” : 32, “salario”: 121232.67}

Array: é uma coleção de valores ordenados. A sintaxe de um array JSON é:


[ "valor1",  "valor2", "valor3" ]

O array começa com [ e termina com ], e cada parte  é separa por , (vírgula) e podem divergir o tipo de dados. Exemplo:


["Huguinho","Zezinho","Luizinho", 3]

Tanto a estrutura object como o array do JSON podem ser combinadas, formando diversas estruturas de dados.

Exemplo – Um array de objects:


[{ "nome" : "Huguinho", "idade" : 10 },
 { "nome" : "Zezinho", "idade" : 12 },
 { "nome" : "Luizinho", "idade" : 10 }]

Exemplo – Object contendo uma propriedade array:


{"tio" : "Pato Donald",
 "idade" : 40,
 "sobrinhos" :
        [{ "nome" : "Huguinho",     "idade" : 10 },
          { "nome" : "Zezinho", "idade" : 12 },
          { "nome" : "Luizinho", "idade" : 10 }]
}

JSON nasceu com um subconjunto da linguagem Javascript para representar objetos e atualmente qualquer linguagem de programação moderna tem suporte (via pacotes de terceiros) a esse formato de troca de informação.

Os sites jsonviewer.stack.hu e  jsonformatter.curiousconcept.com/ são bons lugares para validar a estrutura JSON

Num futuro post demonstrarei o uso do JSON com ASP.NET em chamada assíncronas.

Drag and drop (Dnd) com HTML5

hrml5draganddropUm recurso bacana que é visto em alguns site é o recurso de selecionar um item e arrastá-lo para outra área na mesma página. Este recurso é chamado de Drag and drop, e no HTML5 ele é nativo, dispensando o uso de bibliotecas de terceiros.
Para iniciar, precisamos definir um elemento HTML como “de origem” que será o elemento arrastável, e um elemento de destino, que receberá o elemento de origem.
O elemento HTML que deseja ser arrastável deve manter a propriedade draggable habilitada (true).
Por exemplo, desejo que cada item da lista abaixo seja arrastável:
&lt;ul id=&quot;ulOpcoes&quot;&gt;
    &lt;li draggable=&quot;true&quot;&gt;Opção 1&lt;/li&gt;
    &lt;li draggable=&quot;true&quot;&gt;Opção 2&lt;/li&gt;
    &lt;li draggable=&quot;true&quot;&gt;Opção 3&lt;/li&gt;
    &lt;li draggable=&quot;true&quot;&gt;Opção 4&lt;/li&gt;
    &lt;li draggable=&quot;true&quot;&gt;Opção 5&lt;/li&gt;
    &lt;li draggable=&quot;true&quot;&gt;Opção 6&lt;/li&gt;
&lt;/ul&gt;
Um elemento arrastável (draggable=true) tem os seguintes eventos:
  • dragstart: O elemento começou a ser arrastado. A função que vai tratar o evento recebe um parâmetro, que há uma referência ao elemento sendo arrastado.
  • drag: O objeto está sendo arrastado.
  • dragend: A ação de arrastar terminou.

Esses eventos devem ser associados a uma função para tratá-los.

&lt;/span&gt;&lt;/div&gt;
&lt;ul id=&quot;ulOpcoes&quot;&gt;
    &lt;li draggable=&quot;true&quot; ondragstart=&quot;onDragStart(event)&quot;&gt;Opção 1&lt;/li&gt;
    &lt;li draggable=&quot;true&quot; ondragstart=&quot;onDragStart(event)&quot;&gt;Opção 2&lt;/li&gt;
    ...

Usando Javascript, podemos associar os eventos a cada LI, sem a necessidade de fazer manualmente como acima.

window.onload = function () {

    //Após a carga completa da página, cada LI é associado à função onDragStart.
    var lis = document.querySelectorAll(&quot;#ulOpcoes &gt; li&quot;);
    for (var i = 0; i &lt; lis.length; i++) {

        lis[i].addEventListener(&quot;dragstart&quot;, function (event) { onDragStart(event) });
    }
}

function onDragStart(event) {

    event.dataTransfer.setData(&quot;Text&quot;, event.target.innerHTML);
}

A função que vai tratar o evento ondragstart recebe um parâmetro, que há uma referência ao elemento sendo arrastado através da propriedade target. E a propriedade dataTransfer, com o uso do método setData, oferece meios de armazenar dados a serem transmitidos ao destino. O primeiro parâmetro da função setData é o tipo mime da informação a ser armazenada (no exemplo, Text) e o segundo parâmetro é a informação (no exemplo, guardei o texto contido dentro do LI). Posteriormente será o usado o tipo mime para recuperar a informação.

Com a origem totalmente programa, agora é hora de pensar no destino. O elemento de destino não precisa de nenhuma propriedade específica, como o de origem. Mas precisa de eventos e funções que saibam como receber o que foi arrastado até ele.

O elemento de destino tem os seguintes eventos:
  • dragenter: O objeto sendo arrastado entrou no objeto de destino.
  • dragleave: O objeto sendo arrastado deixou o objeto de destino.
  • dragover: O objeto sendo arrastado se move sobre o objeto de destino.
  • drop: O objeto sendo arrastado foi solto sobre o objeto de destino.

Neste exemplo, o elemento de destino será outra lista, que deverá receber o texto do item da lista de origem que foi arrastado até ela.

&lt;ul id=&quot;ulOpcoesSelecionadas&quot; ondragover=&quot;onDragOver(event)&quot; ondrop=&quot;onDrop(event)&quot;&gt;
&lt;/ul&gt;

O evento ondrop será o responsável por tratar e receber o item arrastável. A função associada ao evento recebe por parâmetro informações sobre o destino, e também a informação guardada na propriedade dataTransfer armazenada anteriormente sob o tipo mime. O método getData precisa do tipo mime armazenado para poder recuperar a informação (como no exemplo a seguir, Text).

function onDrop(event) {
    var li = document.createElement(&quot;li&quot;)
    li.innerHTML = event.dataTransfer.getData(&quot;Text&quot;);
    document.getElementById('ulOpcoesSelecionadas').appendChild(li);
}

E por fim, para que tudo funcione corretamente, é necessário mudar o comportamento padrão do navegador. Por padrão, dados/elementos não podem ser soltos em outros elementos. Para permitir um “drop”, devemos mudar o tratamento padrão do elemento de destino.

E isso é feito na função que trata o evento ondragover do elemento de destino, que é disparada quando o objeto sendo arrastado se move sobre o objeto de destino.

function onDragOver(event)
{
    event.preventDefault();
}

O evento envia a função informações sobre o destino, e o método preventDefault() do parâmetro cancela o comportamento padrão do navegador, e assim permitindo o drop.

O exemplo completo e com exemplos de uso de todos os eventos pode ser baixado aqui.

E é isso….

 

Até mais.

Usando a API WebStorage da Open Web Plataform (HTML5 e seus amigos)

HTML5_Logo_512Em HTML5 é possível armazenar dados no lado do cliente no formato pares de valor de chave, de forma simular como é feito com as Cookies, só que mais fácil. Normalmente é a linguagem de servidor quem cria e envia as Cookies ao cliente.
Com a API de Storage tudo é manipulado diretamente no cliente por Javascript, não há interferência do servidor.
A API WebStorage disponibiliza duas formas para armazenamento no cliente: SessionStorage e LocalStorage.

sessionStorage
: armazenamento de dados independente (não compartilhado entre janelas/guias). Os dados são excluídos quando o usuário fecha a janela/guiado navegador.

localStorage: armazenamento de dados compartilhado entre janelas (comportamento semelhante ao do cookie). Mesmo fechando o navegador, os dados ficam armazenados e somente serão apagados se o cache for limpo ou se solicitada sua exclusão via programação JS.

Vamos aos exemplos.
A ideia aqui é armazenar o que o usuário informou no formulário HTML abaixo usando as duas maneiras apresentadas acima, e depois recuperar a informação.
&lt;textarea id=&quot;texto&quot; rows=&quot;5&quot; cols=&quot;5&quot;&gt;&lt;/textarea&gt;
&lt;br /&gt;
&lt;input type=&quot;button&quot; value=&quot;Salvar no cliente&quot; onclick=&quot;salvar()&quot;/&gt;
&lt;input type=&quot;button&quot; value=&quot;Recuperar no cliente&quot; onclick=&quot;recuperar()&quot;/&gt;

O evento onclick do primeiro input button vai disparar a função salvar(), que tem por objetivo salvar os dados no cliente usando o método setItem da propriedade localStorage. Vamos ao código.

    function salvar() {
        localStorage.setItem('teste', texto.value);
    }

E evento onclick do segundo input button vai disparar a função recuperar(), que vai acessar o valor salvo através do método getItem da propriedade localStorage e devolvê-lo para seu respectivo input.

    function recuperar() {
        document.getElementByI('texto').value = localStorage.getItem('teste');
    }

Usando a Ferramenta de Desenvolvedores do Google Chrome é possível inspecionar o que está armazenado localmente.

localstorage

A nível de programação, para usar a SessionStorage não muda quase nada. Ao invés de usar a propriedade localStorage, deve usar sessionStorage. E os métodos setItem e getItem continuam com o mesmo objetivo, adicionar e remover valores.

Quando usado Cookie, ela é trafegada sempre entre cliente e servidor pelo protocolo HTTP. Isso não ocorre com esta API, a informação é exclusivamente mantida no cliente, e nunca “sobe” para o servidor.

Outros dois métodos importantes disponibilizados são o removeItem, e clear. O primeiro remove o item de nome informado no parâmetro e o segundo, limpa todos os itens do domínio. Ambos funcionam tanto no localStorage como no sessionStorage.

Usando a API de Geolocalização da Open Web Plataform (HTML5 e seus amigos)

HTML5_Logo_512A API Geolocation da Open Web Plataform  permite via Javascript solicitar ao navegador a localização real do usuário. As informações de localização podem ser usadas para exibir mapas, direções e outras informações relevantes a posição global do usuário.

Os navegadores que suportam a API definem a propriedade navigator.geolocation que oferece três métodos:

  1. navigator.geolocation.getCurrentPosition(): solicita a posição atual do usuário.
  2. navigator.geolocation.watchPosition(): solicita a posição atual do usuário e continua a monitorar.
  3. navigator.geolocation.clearWatch(): para de monitorar a posição do usuário.

Abaixo demonstro um pequeno exemplo de como recuperar a geolocalização do usuário e mostrar um mapa no Google e no Bing Maps com a respectiva localização do usuário.


//Usando do método getCurrentPosition para recuperar a localização atual do usuário.
navigator.geolocation.getCurrentPosition(function (posicao) { localizacao(posicao) },
            function (erro) { mostraErro(erro) });

//Função de Callback do sucesso do método getCurrentPosition
function localizacao(posicao) {
    alert('Lat: ' + posicao.coords.latitude + ' ' + 'Lon: ' + posicao.coords.longitude);

    //Abrindo o mapa no bing maps
    window.open(&quot;http://www.bing.com/maps/?v=2&amp;where1=&quot; + posicao.coords.latitude + &quot;,&quot; +
posicao.coords.longitude + &quot;&amp;encType=1&quot;,&quot;&quot;);

    //Abrindo o mapa no google maps
    window.open(&quot;http://maps.googleapis.com/maps/api/staticmap?center=&quot; +
posicao.coords.latitude + &quot;,&quot; + posicao.coords.longitude +
&quot;&amp;zoom=14&amp;size=400x300&amp;sensor=false&quot;);
}

//Função de Callback para falhas método getCurrentPosition
function mostraErro(erro)
{
    switch (erro.code) {
        case erro.PERMISSION_DENIED:
            alert(&quot;user did not share geolocation data&quot;);
            break;
        case erro.POSITION_UNAVAILABLE:
            alert(&quot;could not detect current position&quot;);
            break;
        case erro.TIMEOUT:
            alert(&quot;retrieving position timed out&quot;);
            break;
        default:
            alert(&quot;unknown error&quot;);
            break;
    }
}

Infelizmente não é exato pois, pois a API usa informações dos provedores de internet a qual o usuário está conectado.

E é isso. As possibilidades são várias.