Selecionando um intervalo de datas no Datepicker a partir do JSON

Durante o desenvolvimento Front-end nos deparamos constantemente com o desafio de relacionar o retorno de dados da aplicação com a interface que o usuário acessa efetivamente. Neste artigo apresentamos uma solução JavaScript para selecionar um determinado intervalo de datas no Datepicker a partir do JSON.

Introdução

JSON é um formato leve que pode ser interpretado ou gerado com facilidade e é completamente independente da linguagem utilizada. Estas qualidades fazem com que ele seja ideal para troca de dados. O primeiro passo é analisar a estrutura do objeto que foi criado para o estudo:

[
   {
      "title":"Evento 1",
      "start":"22/05/2015",
      "end":"25/05/2015"
   },
   {
      "title":"Evento 2",
      "start":"28/05/2015",
      "end":"30/05/2015"
   },
   {
      "title":"Evento 3",
      "start":"03/06/2015",
      "end":"03/06/2015"
   }
]

Os itens delimitados entre chaves representam eventos hipotéticos e possuem os mesmos parâmetros com valores diferentes associados. Tendo em vista que temos o título do evento assinalado como title, uma data de início assinalada como start e uma data de término assinalada como end; nosso objetivo é apresentar em destaque as datas dentro do intervalo indicado pelos valores de start e end. Antes de acessar o arquivo precisamos enviar uma requisição para o servidor, o getJSON facilita o processo permitindo definir o URL e o callback para manipular os dados em uma única linha de código; lembrando que o parse acontece automaticamente quando utilizamos este método:

$.getJSON("//emancipa.com.br/tutorial/datepicker/eventos/", function(data) { customCode.setupDatepicker(data) });

O Datepicker

Após enviar os dados da requisição como um parâmetro do método setupDatepicker, temos acesso à informação necessária para iniciar a configuração do nosso componente de calendário:

setupDatepicker: function(data) {
var ranges = data;
		    $("#datepicker").datepicker({
		    	// Evento para o clique na data
		        onSelect: function(date, inst) {
		            alert('Data selecionada:'+date);
		        },

		        // Callback para tratar o retorno antes de exibir o dia 
		        beforeShowDay: function(date) {
		            var startDate = ''
		            , endDate = ''
		            , currentDate = date.getDate() + '/' + Math.round(date.getMonth() + 1)
		            , currentTooltip = this.tooltip + ' ' + currentDate
		            , myStartMonths = ''
		            , myEndMonths = ''
		            , myMonths = ''
		            , currentMonth = Math.round(date.getMonth());

		            for (i = 0; i < ranges.length; i++) {
		                // Cria uma nova data a partir dos valores obtidos na iteração
		                startDate = new Date(ranges[i].start.split('/')[2], Math.round(ranges[i].start.split('/')[1] - 1), ranges[i].start.split('/')[0]);
		                endDate = new Date(ranges[i].end.split('/')[2], Math.round(ranges[i].end.split('/')[1] - 1), ranges[i].end.split('/')[0]);

		                // Define um novo formato de data
		                checkStart = $.datepicker.formatDate('yy-mm-dd', startDate);
		                checkEnd = $.datepicker.formatDate('yy-mm-dd', endDate);
		                checkDate = $.datepicker.formatDate('yy-mm-dd', date);

		                // Retorna em destaque os dias dentro do intervalo
		                if ((checkDate >= checkStart) && (checkDate <= checkEnd))
		                    return [true, "ui-state-highlight", currentTooltip];
		            }

		            // Retorna falso para os dias fora do intervalo
		            return [false, "", currentDate];

		        },

		        // Define intervalo de datas
		        minDate: customCode.getDateRange(ranges, 'min')
		      , maxDate: customCode.getDateRange(ranges, 'max')

		    });
}

Observe que dentro do plugin datepicker foram definidos alguns parâmetros da API, são eles:

Para retornar o dia em destaque de acordo com o intervalo desejado utilizamos a seguinte condicional dentro da função beforeShowDay:

if ((checkDate >= checkStart) && (checkDate <= checkEnd))
    return [true, "ui-state-highlight", currentTooltip];

Isso garante que o dia selecionado na iteração é maior ou igual a data de início e menor ou igual a data de término. Podemos retornar os parâmetros:

  • true – Define a disponibilidade de seleção.
  • “ui-state-highlight” – Classe utilizada na marcação.
  • currentTooltip – Define o texto a ser exibido.

Agora vamos definir o intervalo que corresponde ao menor (minDate) ou maior (maxDate) valor a ser exibido. Para atender ambos os casos de acordo com a estrutura do objeto ranges criamos a função getDateRange:

getDateRange: function(ranges, type) {
	        var date = new Date()
	        , dates = []
	        , retDate;

	        if (!type)
	            type = 'min';

	        for (i = 0; i < ranges.length; i++) {
	            dates.push(new Date(ranges[i].start.split('/')[2], Math.round(ranges[i].start                    .split('/')[1] - 1), 
                    ranges[i].start.split('/')[0]));
	            dates.push(new Date(ranges[i].end.split('/')[2], Math.round(ranges[i].end
                    .split('/')[1] - 1), ranges[i].end.split('/')[0]));
	        }

	        if (type == 'max')
	            retDate = new Date(Math.max.apply(null, dates));

	        if (type == 'min')
	            retDate = new Date(Math.min.apply(null, dates));

	        return retDate;
}

Observe que o método apply possibilita o uso de um array como parâmetro em Math.max ou Math.min, dependendo do tipo de retorno definido como type.

Tradução pt-BR

Para que o texto seja exibido em português do Brasil, é necessário configurar a tradução antes de inicializar o componente, como fizemos através do método init:

init: function() {
	    	// Define o texto padrão exibido no tooltip
	        this.tooltip = "Confira a programação para o dia";

	            // Tradução do datepicker para pt-BR (Brasil)
		    $.datepicker.regional['pt-BR'] = {
		        closeText: 'Fechar'
		        , prevText: '< Anterior'
		        , nextText: 'Próximo >'
		        , currentText: 'Hoje'
		        , monthNames: ['Janeiro'
		        , 'Fevereiro'
		        , 'Mar&ccedil;o'
		        , 'Abril'
		        , 'Maio'
		        , 'Junho'
		        , 'Julho'
		        , 'Agosto'
		        , 'Setembro'
		        , 'Outubro'
		        , 'Novembro'
		        , 'Dezembro']
		        , monthNamesShort: ['Jan'
		        , 'Fev'
		        , 'Mar'
		        , 'Abr'
		        , 'Mai'
		        , 'Jun'
		        , 'Jul'
		        , 'Ago'
		        , 'Set'
		        , 'Out'
		        , 'Nov'
		        , 'Dez']
		        , dayNames: ['Domingo'
		        , 'Segunda-feira'
		        , 'Terça-feira'
		        , 'Quarta-feira'
		        , 'Quinta-feira'
		        , 'Sexta-feira'
		        , 'Sábado']
		        , dayNamesShort: ['Dom'
		        , 'Seg'
		        , 'Ter'
		        , 'Qua'
		        , 'Qui'
		        , 'Sex'
		        , 'Sab']
		        , dayNamesMin: ['Dom'
		        , 'Seg'
		        , 'Ter'
		        , 'Qua'
		        , 'Qui'
		        , 'Sex'
		        , 'Sab']
		        , weekHeader: 'Sm'
		        , dateFormat: 'dd/mm/yy'
		        , firstDay: 0
		        , isRTL: false
		        , showMonthAfterYear: false
		        , yearSuffix: ''
		    };

		    // Configura idioma do Datepicker
		    $.datepicker.setDefaults($.datepicker.regional['pt-BR']);

		    // Datepicker
		    $.getJSON("//emancipa.com.br/tutorial/datepicker/eventos/", function(data) { customCode.setupDatepicker(data) });

	    }

Conclusão

jQuery UI é um conjunto de ferramentas baseadas no jQuery. Se você está desenvolvendo aplicações altamente interativas ou precisa adicionar um seletor de datas no seu formulário o jQuery UI é a escolha perfeita.

Veja o código em execução: http://codepen.io/brunochucky/pen/eNdJxz

Links de referência para o tema: