2012-03-11 28 views
5

Usando fullCalendar, permito a un usuario seleccionar una vista de día en mes en un calendario grande (#cal_big) y el calendario pequeño correspondiente en la vista de día, con horas mostradas (#cal_small) se mostrará.fullCalendar 1.5.3 múltiples eventos creados, no se pueden eliminar eventos no seleccionados

Cuando el usuario selecciona un evento (una hora o bloque de horas) en #cal_small, mostraré un modal de confirmación/cancelación. El modal de confirmación/cancelación permite al usuario confirmar la reserva o cancelar la reserva (lo que semánticamente significa que el usuario no quiere realmente reservar esa ranura después de todo).

The confirm or cancel modal window

Si el usuario confirma la reserva, hago una llamada AJAX al servidor y registra la reserva. Una vez que la llamada ajax vuelve exitosamente, simplemente oculto el modal actual y aparece "¡Tu reserva fue exitosa!" mensaje en un nuevo modal. Esta parte funciona sin problemas.

Si el usuario cancela la reserva, el modal de confirmación/cancelación se oculta y trato de desactivar programáticamente la selección actual y aquí es donde comienza el problema. La anulación de selección no funciona y parece que fullCalendar recuerda todas estas selecciones que no están confirmadas y, cuando el usuario finalmente confirma su selección, un montón de selecciones previamente no confirmadas se envían al servidor repetidamente en múltiples llamadas ajax.

Multiple Events created even though the previous two events ought to have been unselected

Por qué es así y cómo puedo prevenir fullCalendar de recordar selecciones sin confirmar?

Aquí está el código: -

$(document).ready(function() { 

    var todayDate = new Date(); 

    var myDate = todayDate.setDate(todayDate.getDate() - 1); 

    var csrfmiddlewaretoken = '{{ csrf_token }}'; 

    var condo_slug = '{{ condo.slug }}'; 

    var facility = $("#id_facility"); 

    var cal_small_options = { 
     titleFormat: { 
      day: 'dddd' 
     }, 
     header: { 
      left: '', 
      center:'title', 
      right:'', 
     }, 
     height: 520, 
     defaultView: 'agendaDay', 
     editable: true, 
     minTime: '10:00', 
     maxTime: '23:00', 
     slotMinutes: 60, 
     selectable: true, 
     select: function(startDate, endDate, allDay, jsEvent, view) { 
      console.log("selection triggered", jsEvent.handleObj.guid) 
      checkAvailability(csrfmiddlewaretoken, condo_slug, facility, startDate, endDate); 
      $('#confirm').click(function(){ 
       confirmBooking(csrfmiddlewaretoken, condo_slug, facility.val(), startDate, endDate) 
      }); 
     }, 
     events: function(start, end, callback) { 
      // start and end marks the current date range shown on the calendar 
      ajaxShowEvents(facility.val(), condo_slug, start, end, callback); 
     }, 
     eventClick: function(event) { 
      console.log(event.title); 
     }, 
     viewDisplay: function(view) { 
      // Clear the calendar and retrieve event objects when user selects a facility. 
      $('#id_facility').change(function(){ 
       ajaxShowEvents(facility_id = $(this).val(), start = view.start, end = view.end); 
      }); 
     } 
    }; 

    var cal_big_options = { 
     header: { 
      left: '', 
      center:'title', 
      right: '' 
     }, 
     dayClick: function(date, allDay, jsEvent, view) { 
      if (date < myDate) { 
       alert('You cannot book on this day!'); 
      } 
      if (allDay) { 
       $('#cal_small').fullCalendar('gotoDate', date); 
      } else { 
       alert('Clicked on the slot: ' + date); 
      } 
     }, 
     selectable: true, 
     unselectCancel: '', 
     events: function(start, end, callback) { 
      // start and end marks the current date range shown on the calendar 
      ajaxShowEvents(facility.val(), condo_slug, start, end, callback); 
     }, 
     viewDisplay: function(view) { 
      // Clear the calendar and retrieve event objects when user selects a facility. 
      $('#id_facility').change(function(){ 
       ajaxShowEvents(facility_id = $(this).val(), start = view.start, end = view.end); 
      }); 
     }, 
     eventClick: function(event, jsEvent, view) { 

      if(event.start < myDate) { 
       alert('You cannot book on this day!'); 
      } else { 
       // check to see if the booking belongs to user 
       ajaxCheckBooking(csrfmiddlewaretoken, event); 
       $('#confirm').click(function(){ 
        ajaxDeleteBooking(csrfmiddlewaretoken, event) 
       }); 
      } 
     } 
    }; 

    $('#cal_small').fullCalendar(cal_small_options); 

    $('#cal_big').fullCalendar(cal_big_options); 

    $('.cancel, .btn_close').click(function() { 
      $('#cal_big, #cal_small').fullCalendar('unselect') 
      $('#modal-window').modal('hide'); 
     }); 

}); // END document ready 

ACTUALIZACIÓN

La función confirmBooking conforme a lo solicitado: -

function confirmBooking(csrfmiddlewaretoken, condo_slug, facility_id, startDate, endDate) { 
    // Given condo slug, facility id and the user selected startDate and endDate, 
    // send an ajax post request to confirm the booking 
    post_data = {csrfmiddlewaretoken: csrfmiddlewaretoken, 
       condo_slug: condo_slug, 
       facility_id: facility_id, 
       start_date: startDate.toUTCString(), 
       end_date: endDate.toUTCString()} 
    $.ajax({ 
     url: '/facility/ajax-confirm-booking/', 
     data: post_data, 
     type: 'POST', 
     dataType: 'json', 
     success: function(data) { 
      if (data['status']=='success') { 
       message = "Your booking is confirmed!" 
       event = new Object(); 
       event.id = data['id']; 
       event.title = "Your Booked Event"; 
       event.start = startDate; 
       event.end = endDate; 
       event.allDay = false; 
       $("#cal_big").fullCalendar('renderEvent', event); 
       $("#cal_small").fullCalendar('renderEvent', event); 
       // TODO: 
       // * disable the submit and reset buttons 
       // * email notification to end user and property manager 
      } else if (data['status']=='not logged in') { 
       message = "You are not yet logged in!" 
       // TODO: 
       // * Provide fb login button so user can login. 
      } else { 
       message = "I am sorry. Something went wrong with your booking" 
       // TODO: 
       // * Work on an email notification to site admin if a booking has failed for some reason 
      } 

      displayModal(message, false); 
     } 
    }); 
}; // END confirmBooking 

Apreciar si alguien podría elaborar por qué el .fullCalendar ('deseleccionar ') llamada no funciona para eliminar eventos no confirmados y cómo puedo resolver este problema.

+2

Esas "selecciones" no me parecen selecciones, parecen ser eventos reales que se agregan al calendario en alguna parte de las funciones que se invocan en el código (como confirmBooking o checkAvailability): ¿hay alguna llamada a 'fullCalendar? ('renderEvent', ... '? – Niko

+0

Espero que la 'selección/evento seleccionado' se destruya cada vez que el usuario hace clic en otra parte, incluido el botón 'cancelar' en el modal. Incluso lo verifico intentando incluir una devolución de llamada 'unselect' explicita que imprime" evento no seleccionado en #cal_small "," evento no seleccionado en #cal_big "cada vez que el usuario hace clic en otra parte que no sea el botón confirmar en el modal; y de hecho, console.log imprime estos registros. Si esos eventos previos no están seleccionados, ¿por qué se los considera más tarde como parte de la selección cuando el usuario finalmente "confirma"? –

+0

@Niko hay una llamada al método 'fullCalendar ('renderEvento', evento)' cuando la llamada confirmBooking ajax al servidor regresa con éxito, con el fin de representar el evento específico que se confirma. Lo que no entiendo es por qué el evento previamente no seleccionado también se representa. –

Respuesta

7

Lo resolvió.

Es un error simple muerto que me perdí por completo.

select: function(startDate, endDate, allDay, jsEvent, view) { 
     console.log("selection triggered", jsEvent.handleObj.guid) 
     checkAvailability(csrfmiddlewaretoken, condo_slug, facility, startDate, endDate); 
     $('#confirm').click(function(){ 
      confirmBooking(csrfmiddlewaretoken, condo_slug, facility.val(), startDate, endDate) 
     }); 
    }, 

provoca un evento de clic en obligarse al botón #confirm cada vez que se selecciona un evento en el calendario. Por lo tanto, si el usuario sigue seleccionando eventos sin confirmar, el botón #confirm seguirá acumulando diferentes eventos de clic con diferentes fechas de inicio y finalización diferentes. Cuando el usuario finalmente golpea el botón #confirm después de una indecisión repetida, todos los eventos de clic se disparan de una vez, lo que provoca que los eventos previamente no seleccionados se envíen al servidor como una publicación de Ajax. Para resolver esto, debo recordar especificar $('#confirm').unbind() cuando el usuario hace clic en el botón .cancel o .close.

Argh ... una solución simple pero me llevó tanto tiempo verla!

0

que tenían el mismo problema, pero lo resolvió usando esto:

$("#confirm").dialog({... 

Si hubiera sabido de unbind anterior, todas las cosas que he tenido que cambiar no habrían sido necesarias :(

Cuestiones relacionadas