Reputation: 109
When I click a day in month view, a modal will pop-up.
Inside that modal is a button for adding a new event. When I click that, another modal will pop-up for the Add Event form.
The problem is when I frequently open/close the first modal and try to add an event after that without reloading the page, the AJAX call fires multiple times even if I click the submit only once. Sometimes it multiplies up to 7 times.
I don't know what the problem is.
My code:
$(document).ready(function() {
var calendar = $('#calendar').fullCalendar({
header: {
left: 'today',
center: 'prev title next',
right: 'month,basicWeek,basicDay'
},
eventOrder: 'start',
editable: true,
droppable: true,
eventLimit: true,
selectable: true,
selectHelper: true,
events: 'getEvents.php',
eventRender: function(event, element, view) {
var today = new Date();
var startString = moment(event.start).format('YYYY-MM-DD');
var endString = moment(event.end).format('YYYY-MM-DD');
$(element).each(function () {
$(this).attr('date-num', event.start.format('YYYY-MM-DD'));
});
},
eventAfterAllRender: function(view){
for( cDay = view.start.clone(); cDay.isBefore(view.end) ; cDay.add(1, 'day') ){
var dateNum = cDay.format('YYYY-MM-DD');
var dayEl = $('.fc-day[data-date="' + dateNum + '"]');
var eventCount = $('.fc-event[date-num="' + dateNum + '"]').length;
if(eventCount){
var html = '<span class="event-count">' +
'<i>' +
eventCount +
'</i>' +
' Events' +
'</span>';
dayEl.append(html);
}
}
},
dayClick: function(start, end, event) {
var st = start.format('YYYY-MM-DD HH:mm:ss');
var en = start.format('YYYY-MM-DD HH:mm:ss');
function fetch_data() {
$.ajax({
url: "view-data.php",
data: 'action=view&start=' + st + '&end=' + en,
method: "POST",
success: function(data) {
$('#view-me').html(data);
$('#view-data').modal('show');
}
});
}
fetch_data();
$(document).on('click', '.add-me', function() {
$('#start').val(moment($(this).data('start')).format('YYYY-MM-DD[T]HH:mm:ss'));
$('#end').val(moment($(this).data('end')).format('YYYY-MM-DD[T]HH:mm:ss'));
$('#ModalAdd').modal('show');
$('#myFormAdd').on('submit', function(e) { // add event submit
e.preventDefault();
doAdd(); // send to form submit function
});
function doAdd() { // add event
var title = $('#title').val();
var start = $('#start').val();
var end = $('#end').val();
$.ajax({
url: 'addEvent.php',
data: 'action=add&title=' + title + '&start=' + start + '&end=' + end,
type: "POST",
success: function(json) {
$('#ModalAdd').modal('hide');
fetch_data();
calendar.fullCalendar('refetchEvents');
}
});
}
});
}
);
My PHP Code: view-data.php
if($_POST['action'] == "view") // view event dayClick
{
$start = $_POST['start'];
$end = $_POST['end'];
?>
//Add new button
<button title="add new here" class="add-me" data-start="<?php echo $start; ?>"
data-end="<?php echo $end; ?>" rel="dialog" >ADD</button>
<?php
$sql = "SELECT * FROM events WHERE start BETWEEN '$start' AND '$end' OR end BETWEEN '$start' AND '$end'";
$result = mysqli_query($connect, $sql);
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
?>
<span style="overflow:hidden;text-overflow:ellipsis;white-space: nowrap;"><?php echo $row['title']; ?></span>
<?php
}
} else {
echo "<span>No event</span>";
}
}
?>
Upvotes: 3
Views: 2512
Reputation: 61784
Currently inside your dayClick event handler you've got code to add all your other event handlers, and also defined some functions. This is not a good thing to do, because it means that every time a user clicks on a day, this code will run and keep adding more and more event handlers to your page. Adding an event handler does not overwrite previously added handlers, it just keeps adding more. Then every time the event you add the handler to is triggered, it executes all the event handlers attached to it, simultaneously.
This explains why sometimes you see your ajax calls run again and again - it will be in the cases where you've clicked on a day (or different days) more than once already.
You need to make sure you event handling code only ever runs once, and your functions are only ever declared once. To do this, move all that code outside your calendar config. You then also need to allow some parameters to be passed to the fetch_data function, so that it knows what to fetch without relying on closure scope:
So, in your fullCalendar code:
dayClick: function(start, end, event) {
fetch_data(start, end);
}
That's it, that's all you need inside the calendar config.
Then, outside your calendar config:
function fetch_data(start, end) {
var st = start.format('YYYY-MM-DD HH:mm:ss');
var en = start.format('YYYY-MM-DD HH:mm:ss');
$.ajax({
url: "view-data.php",
data: 'action=view&start=' + st + '&end=' + en,
method: "POST",
success: function(data) {
$('#view-me').html(data);
$('#view-data').modal('show');
}
});
}
$(document).on('click', '.add-me', function() {
$('#start').val(moment($(this).data('start')).format('YYYY-MM-DD[T]HH:mm:ss'));
$('#end').val(moment($(this).data('end')).format('YYYY-MM-DD[T]HH:mm:ss'));
$('#ModalAdd').modal('show');
});
$(document).on("submit", '#myFormAdd', function(e) { // add event submit
e.preventDefault();
doAdd(); // send to form submit function
});
function doAdd() { // add event
var title = $('#title').val();
var start = $('#start').val();
var end = $('#end').val();
$.ajax({
url: 'addEvent.php',
data: 'action=add&title=' + title + '&start=' + start + '&end=' + end,
type: "POST",
success: function(json) {
$('#ModalAdd').modal('hide');
//fetch_data(); //it's not clear why you would need to do this here, since you've just hidden the modal which is populates! Pretty sure you don't need it, so I've commented it out
calendar.fullCalendar('refetchEvents');
}
});
}
Upvotes: 3
Reputation: 171679
Move the $(document).on('click', '.add-me', function(){
out of the dayClick
callback
Every time you click on a day you are adding a new click event listener for the add-me
So clicking on 3 days would add 3 listeners and then a click on add-me
will run the event handler ( and ajax) 3 times
Upvotes: 3