sábado, 23 de março de 2013

Como usar objetos JSON com Twitter typeahead Bootstrap

Bootstrap do Twitter esta com tudo nestes dias, e por boas razões. É repleto de widgets com estilo, esteticamente agradáveis, facilmente personalizáveis ​​e úteis. Entre o último que você vai encontrar typeahead, um widget para valores auto-sugerindo possíveis em resposta à entrada do usuário.
Typeahead usando uma matriz de implementação padrão Cordas Bootstrap de typeahead usa uma matriz de strings para fornecer sugestões:
html:
 
    
       
    
Javascript:
var colors = ["red", "blue", "green", "yellow", "brown", "black"];
$('#search').typeahead({source: colors});
Aqui está o que o widget se parece com:

A implementação é simples, limpo, e funciona como esperado. O que mais você poderia querer?
Typeahead Usando uma matriz de objetos:
Bem, às vezes trabalhando com cordas é muito limitante. Por exemplo, considere um cenário onde você quer que o usuário entrar em um estado dos EUA e que você precisa para capturar a sigla do estado de duas letras uma vez que a seleção é feita (se o usuário digitar "California", você vai armazenar "CA"):
Para construir esse recurso podemos usar uma matriz de objetos que contêm o nome do Estado e da abreviatura:
Javascript:
var stateList = [
    {"stateCode": "CA", "stateName": "California"},
    {"stateCode": "AZ", "stateName": "Arizona"},
    {"stateCode": "NY", "stateName": "New York"},
    {"stateCode": "NV", "stateName": "Nevada"},
    {"stateCode": "OH", "stateName": "Ohio"},
   ...
];

Bootstrap expõe um conjunto de opções substituíveis podemos utilizar para implementar typeahead com uma série de objetos:
Source Matcher Sorter Highlighter Updater É importante notar que você pode provavelmente próprias implementações Bootstrap alavancar para praticamente tudo, exceto source e updater. Dito isso, neste exemplo, vamos implementar todos eles usando o modelo abaixo:
$('#search').typeahead({
    source: function (query, process) {
        // implementation
    },
    updater: function (item) {
        // implementation
    },
    matcher: function (item) {
        // implementation
    },
    sorter: function (items) {
        // implementation
    },
    highlighter: function (item) {
       // implementation
    },
});

1. Source

Vamos começar com o source. Esta opção especifica o conjunto de dados para usar a lista de auto-sugestão. Pode demorar um array de strings (que vimos no primeiro exemplo) ou uma função:
source: function (query, process) {
    states = [];
    map = {};
 
    var data = [
        {"stateCode": "CA", "stateName": "California"},
        {"stateCode": "AZ", "stateName": "Arizona"},
        {"stateCode": "NY", "stateName": "New York"},
        {"stateCode": "NV", "stateName": "Nevada"},
        {"stateCode": "OH", "stateName": "Ohio"}
    ];
 
    $.each(data, function (i, state) {
        map[state.stateName] = state;
        states.push(state.stateName);
    });
 
    process(states);
},
Esta função tem dois parâmetros: query e process (vou falar tanto em um pouco). A primeira coisa que fazemos é obter dados, uma série de objetos de estado. Embora eu tenha codificado conteúdo de dados dentro da função neste exemplo, em um aplicativo de produção real que viria a partir do servidor. Em seguida, mapear nomes dos estados para os objetos correspondentes usando duas variáveis ​​globais, map e states. Isto é necessário porque Bootstrap precisa de uma lista de strings para realmente mostrar sugestões automáticas (array states), enquanto que precisamos para obter os objetos originais (armazenado no map). Obviamente, os nomes de seus objetos precisa ser exclusivo para este trabalho. Finalmente, chamamos a função de inicialização do process() com a array de states. Process() organiza o ciclo de eventos para typeahead (chamando matcher, sorter, etc) e define-se a lista de auto-sugestão exibida para o usuário. Você pode ter notado também que não usar o parâmetro de entrada query neste exemplo. Normalmente, query seria usado para implementar filtragem do lado do servidor da lista de auto-sugestão, pois contém a seqüência de pesquisa inseridos pelo usuário.

2. Matcher

Em seguida, vamos implementar o correspondente (). Esta função é usada por Bootstrap para verificar se a cadeia de busca digitado pelo usuário corresponde a qualquer coisa na lista de origem. Sua finalidade é a de filtrar a lista de auto-sugestão para apenas os valores relevantes:
matcher: function (item) {
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
        return true;
    }
}
A implementação acima é bastante trivial. Nós simplesmente tomar a entrada do usuário (contido em this.query) e verificar se ela existe em qualquer lugar do item. Conversão de ambas as strings para minúsculas é necessária porque o usuário é improvável que esperar caso a ser considerado quando a correspondência de termos.

3. Sorter

A função sorter é responsável por classificar a lista de sugestões filtrados pelo matcher:
sorter: function (items) {
    return items.sort();
}
Mais uma vez, devo salientar que a minha implementação é bastante simplista. Classificando sugestões é geralmente um caso mais elaborado. Por exemplo, a implementação própria Bootstrap considera se a entrada do usuário é encontrado no início da cadeia sugeriu e se o jogo foi sensível a maiúsculas.

4. Highlighter

Bootstrap usa marca-texto para destacar a entrada do usuário dentro dos resultados de auto-sugeridas. Podemos usar um jogo de regex simples de encontrar e entrada do usuário em negrito de:
highlighter: function (item) {
    var regex = new RegExp( '(' + this.query + ')', 'gi' );
    return item.replace( regex, "$1" );
}

5. Updater

Finalmente, chegamos ao updater. Esta função é chamada por Bootstrap uma vez que o usuário seleciona um item, o que nos dá uma chance de fazer algo com a seleção. Neste caso, gostaríamos de registrar a sigla do estado selecionado em um selectedState variável global antes de retornar o item:
updater: function (item) {
    selectedState = map[item].stateCode;
    return item;
}
Nota de cautela: é muito importante que você devolver o item porque esse é o valor usado por Bootstrap para definir o input box.