Timepicker fields disappear when you select many dates

7

I'm creating an application with dynamic calendar creation.

My application uses:

  • Bootstrap 3
  • jQuery 1.11.0
  • jQuery-ui 1.10.3
  • jQuery Timepicker Addon 1.5.0

I create a calendar on the page (jQuery UI DatePicker), when the person selects the date I create a dynamic field for selection of hours (start and end periods) on that day that can be added.

HTML

<div class="form-group">
    <label for="datas_sel" class="control-label">Datas do evento</label><br>
    <div id="datas_sel" style="float:left;"></div><br class="clear">&nbsp;<br>
    <label>Horas para as datas selecionadas:</label><br>
    <div id="horas_sel" style="width:100%;"></div><br class="clear">&nbsp;<br>
</div>

Javascript

//classe de implementação
var calendario = {
    datas : new Array(),
    padNumero: function(num) {
        return (num.toString().length == 1)?"0"+num.toString():num.toString();
    },
    forDate : function(str){
        return str.substring(6) + "/" + str.substring(4,6) + "/" + str.substring(0,4);
    },
    sorteio: function(a, b) {
        return a.getAttribute('data-date') - b.getAttribute('data-date');
    },
    dataOrganiza: function(){
        var organizar = $("#horas_sel div").toArray().sort(this.sorteio);
        $("#horas_sel div").remove();
        $.each(organizar, function (k, v) {
            $('#horas_sel').append(v);
        });
    },
    addRemData: function(data) {
        var index = jQuery.inArray(data, this.datas);
        if (index >= 0){
            this.removeDate(index);
        }else{
            this.addDate(data);
        }
        this.dataOrganiza();
    },
    addDate: function(data) {
        if (jQuery.inArray(data, this.datas) < 0){
            this.datas.push(data);
        }
        $('#horas_sel').append('<div id="dia_'+data+'" data-date="'+data+'" data-horas="0">\
<span id="data_'+data+'"><b>'+this.forDate(data)+':</b></span>\
<span id="hora_'+data+'"></span>\
<span id="plusicon_'+data+'" class="glyphicon glyphicon-plus-sign" style="padding:3px;border-left:1px solid #CCC;"></span>\
</div>');
        setTimeout(function(){
            $('#plusicon_'+data).click(function(){
                calendario.addHora(data)
            });
            calendario.addHora(data);
        },300);
    },
    removeDate: function(ind) {
        var d = this.datas.splice(ind, 1);
        $('#dia_'+d).remove();
    },
    addHora: function(data){
        var num = $('#dia_'+data).attr('data-horas');
        num = (parseInt(num)>=0)? parseInt(num)+1:1;
        $('#dia_'+data).attr('data-horas',num);
        $('#hora_'+data).append('<span id="ttem_'+data+'_'+num+'">\
Inicio: <input type="text" id="tini_'+data+'_'+num+'" class="form-control" placeholder="12:00"/> \
Final:  <input type="text" id="tfim_'+data+'_'+num+'" class="form-control" placeholder="13:00"/>\
<span id="tmen_'+data+'_'+num+'" class="glyphicon glyphicon-minus-sign" style="margin-right:10px; padding:3px; border-right:1px solid #ccc;"></span>\
</span>');
        if($('#hora_'+data+' input').length >= 6){
            $('#plusicon_'+data).css('display', 'none');
        }else{
            $('#plusicon_'+data).css('display', 'inline-block');
        }
        setTimeout(function(){
            $('#tini_'+data+'_'+num+', #tfim_'+data+'_'+num).timepicker({stepMinute: 5});
            $('#tmen_'+data+'_'+num).click(function(){
                calendario.remHora(data,num);
            });
        },300);
    },
    remHora: function(data, id){
        $('#ttem_'+data+'_'+id).remove();
        if($('#hora_'+data+' input').length >= 8){
            $('#plusicon_'+data).css('display', 'none');
        }else{
            $('#plusicon_'+data).css('display', 'inline-block');
        }
    }
}
//inicia o calendário
$('#datas_sel').datepicker({
    numberOfMonths: [1,3],
    howWeek: true,
    weekHeader: "W",
    onSelect: function (dateText, inst) {
        calendario.addRemData(dateText.split('/').reverse().join(''));
    },
    beforeShowDay: function (date) {
        var year = date.getFullYear();
        var month = calendario.padNumero(date.getMonth() + 1);
        var day = calendario.padNumero(date.getDate());
        var dateString = year.toString() + month.toString() + day.toString();

        var gotDate = jQuery.inArray(dateString, calendario.datas);
        if (gotDate >= 0) {
            return [true, "ui-state-highlight"];
        }
        return [true, ""];
    }
});

It works until the inclusion of dates. The problem is that the more dates I select, or the more hours I include on date X, the timepicker fields of those that were already there begin to be displayed in focus.

I've created a fiddle for viewing it.

Click on the calendar date it will add a field for time selection.

    
asked by anonymous 26.11.2014 / 23:44

2 answers

1

The code is set to remove the date if it has already been selected, you can delete this function by commenting the line:

//this.removeDate(index);

See in JSFiddle

    
27.11.2014 / 00:59
0

Each time you remove elements from the DOM, you lose the event dropper that was bound to that element.

For example:

dataOrganiza: function(){
        var organizar = $("#horas_sel div").toArray().sort(this.sorteio);
        $("#horas_sel div").remove();

In this last line, .remove() removes the elements within that div. I realize the idea of re-organizing the dates but this generates this problem because it breaks the loop between element and its event handler.

Solution:

I suggest delegating these event droppers. You can even remove them from this namespace and put them in the code next to // inicia calendário . That is:

Instead of this code inside the setTimeout:

$('#plusicon_'+data).click(function(){
    calendario.addHora(data)
});

You can have (out of calendário :

$(document).on('click', '[id^="plusicon_"]', function () {
    calendario.addHora(this.id.split('_').pop());
});

In this new code I'm going to search for data to the proper ID using this.id.split('_').pop() that gives me the last bit of the string by the character: _

Example: link

    
27.11.2014 / 09:11