I want to create some events on my DayPilot scheduler using my own modal window. It works fine when creating the first event. After that the event gets doubled, tripled and so on along with the new created events. It seems like args is not getting empty.
Here is my code for onTimeRangeSelected:
dp.onTimeRangeSelected = function (args) {
$('#myModal').show();
$('.schedule_option').click(function(){
$('#myModal').hide();
dp.clearSelection();
var txt=this.getAttribute("arg");
var colour = this.style.backgroundColor;
var e = new DayPilot.Event({
start: args.start,
end: args.end,
id: DayPilot.guid(),
resource: args.resource,
text: txt,
backColor:colour
});
var params = {
start: args.start,
end: args.end,
text: txt,
backColor:colour,
id:DayPilot.guid(),
resource: args.resource
};
DayPilot.Http.ajax({
url: "admin/backend_create.php",
method: "POST",
data: params,
success: function(ajax) {
dp.message("succes");
},
error: function(ajax) {
dp.message("Saving failed");
}
});
dp.events.add(e);
});
}
And the effect I am getting is:
The modal contains 3 buttons corresponding to each event to be scheduled type.
If I use DayPilot modal I don't have issues. I can't find an explanation because somehow it worked until last Friday.
Thanks!
Ok. I found the issue. It's the click event handler that it is being added every time a time range it's selected. I will have to get it out of there and find another way to use my own modal.
Related
I am currently facing a strange behavior with my SAPUI5 coding when I do a DELETE with the model (sap.ui.model.odata.v2.ODataModel). I wanted to implement a list, which displays some "Favorites" in a SelectDialog. By pressing the icon, the users can delete a favorite. For the item itself I used a FeedListItem, which is triggering the iconPress-Event _handleIconPressDelete.
<FeedListItem icon="sap-icon://delete" iconActive="true" iconPress="_handleIconPressDelete" text="{Name}" sender="{ID}"/>
The event looks like this:
_handleIconPressDelete: function(oEvent) {
var oModel = oEvent.getSource().getModel();
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
}
But when this event is triggered, two identical delete requests are generated and causing an error, because with the current changeset coding in the backend, I am only allowed to do one request at the same time.
The strange thing is, this behavior only appears when I open the dialog the first. When I close and reopen it, everything works fine.
Do you have any ideas, what I might do wrong here so that two requests are generated? I also checked, if the event is triggered multiple times, but that wasn't the case.
As current workaround I am using deferredGroups as shown in the snipped below so that the two request are separated, but I think there must be better ways to solve this.
_handleIconPressDelete: function(oEvent) {
var oModel = oEvent.getSource().getModel();
oModel.setDeferredGroups(["group1"]);
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
groupId: "group1",
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
oModel.submitChanges({
groupId: "group1"
});
}
I too experienced the same issue where the event associated with iconPress of FeedListItem triggers twice though user click only once..
Following is a workaround which you can implement using custom coding.
Declare the following variable in view controller's onInit()
this._bFirstTrigger = true;//SETTING FOR THE FIRIST TIME
Use this in FeedListItem's iconPress event to ensure that the relevant code executes only once as follows:
_handleIconPressDelete: function(oEvent) {
if (this._bFirstTrigger) {
var oModel = oEvent.getSource().getModel();oModel.setDeferredGroups(["group1"]);
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
groupId: "group1",
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
oModel.submitChanges({
groupId: "group1"
});
}
this._bFirstTrigger = false;
}
else{
this._bFirstTrigger = true;
}
Regards,
Fahad Hamsa
I have the following markup:
I have a instance of fullcalendar.
When clicking on a day (triggering the dayClick-callback), a bootstrap modal is opened, where the user can enter a title, and the start/end date. Once clicking on ok, those values provided, will be added to the calendar. Here's the code for that:
function addTitle(){ //having a button onClick="addTitle()"
var title = $('#add_date_title').val();
var startdate = $('#add_date_startdate').val();
var enddate = $('#add_date_enddate').val();
var end_split = enddate.split('-');
end_split[2]= parseInt(end_split[2])+parseInt("1");
enddate = end_split[0] + "-" + end_split[1] + "-" + end_split[2];
$('#add_date_title').val('');
$('#add_date_startdate').val('');
$('#add_date_enddate').val('');
$('#add_date_modal').modal('hide');
var myCalendar = $('#calendar');
var myEvent = {
title:title,
allDay: true,
start: startdate,
end: enddate
};
myCalendar.fullCalendar( 'renderEvent', myEvent );
}
So the event is now in the calendar. But when e.g. switching the month, or reloading the page, all data is lost, of course, because it's saved nowhere.
Now the question is: How could I save the event directly into the database, and then load it, so where can I bring in php code, to save the event to a db... The problem, why I'm asking, is that the site in between adding events is never reloaded, so I'm not able, to check for GET or POST-Parameters or something similiar... Could I maybe do this with AJAX? If yes, how? Because I'm not really familiar with AJAX.
You can actually save the events in DB.
Use this ajax after your modal trigger.
Get the values like title,startdate, end date in modal and send them in the following ajax
$.ajax({
url: 'add_events.php',
data: 'title='+ title+'&start='+ start2 +'&end='+ end2,
type: "POST",
success: function(json) {
$( "#getReason" ).modal('hide');
$('#mydiv').hide();
$('body').removeClass('blockMask');//calendar.fullCalendar( 'refetchEvents');
$('#calendar').fullCalendar('refetchEvents');
}
});
in add_events.php save the details in db
In your main page use this method for dynamically creating event source
function eventSourceCall(){
eventSourceCall = [
{
url: 'events.php?status=absent',
backgroundColor: 'red',
borderColor: 'white',
textColor: 'white',
rendering: 'background',
cache: false
}
in events.php perform a select operation and retrieve the event parameters as json encoded objects and return them.
In calendar function eventSources: eventSourceCall, add this line for selecting the event source.
I'm a bit lost where is the proper place to make this with the Full Calendar documentation and need some fiddle to point me into the right way. When my calendar loads the events, before them show up on the calendar, I need to make a ajax call into a wordpress db which should return a date of a post. Each post is an event on the calendar. Depending on the response of the database, if the post date is in future time than the current time, then the calendar should show this event in an specific color, if it is past or current time it should be another different specific color.
So basically, before each event renders on the calendar I need to trigger an ajax call for each of them and evaluate the data returned to apply them the right color for past/current events and future events.
Someone experienced with Full Calendar could point me a fiddle with an example how is this done within the Full Calendar documentation?
This is the code I went so far. I am looking to stay in the loop with the calendar refetchEvents and be able to fetch with ajax in the background data from the posts of a WordPress website to use it on the next refetchEvents trigger and so on.
$(function () {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var webData = null; //array() data
$('#calendar-holder').fullCalendar({
eventRender: function(event, element, webData) {
var dataHoje = new Date();
/*
Use webData data taken with ajax on eventAfterAllRender callback option
inside this conditional statements to draw on the event box
colors and text values depending on the status and date of the post returned.
*/
if (event.start < dataHoje && event.end > dataHoje) {
element.css('background-color', '#FFB347');
element.find('.fc-event-inner').append('<span class="fc-event-status">ON AIR</span>');
} else if (event.start < dataHoje && event.end < dataHoje) {
element.css('background-color', '#77DD77');
element.find('.fc-event-inner').append('<span class="fc-event-status">Published</span>');
} else if (event.start > dataHoje && event.end > dataHoje) {
element.css('background-color', '#AEC6CF');
element.find('.fc-event-inner').append('<span class="fc-event-status">Schedued</span>');
}
},
eventAfterAllRender: function () {
webData = '(AJAX CALL TO WEBSITE POSTS I THINK SHOULD GO HERE)';
console.log(webData);
},
eventColor: '#378006',
complete: function() {
},
defaultView: 'basicDay',
googleCalendarApiKey: 'AIzaSyCtEQZsFtsY41kJ1Av5FftgX9kdfkHKH',
events: {
googleCalendarId: 'mywebsite.com_l84tadr5fulc7j0628g3g6oj3k#group.calendar.google.com'
},
header: {
left: 'prev, next',
center: 'title',
right: 'basicDay, basicWeek, month, '
},
lazyFetching: true,
timeFormat: {
agenda: 'h:mmt', // 5:00 - 6:30
'': 'h:mmt' // 7p
},
weekNumbers: false,
lang: 'en',
eventSources: [
{
url: Routing.generate('fullcalendar_loader'),
type: 'POST',
data: {
},
error: function() {
}
}
]
});
});
var refreshRate;
function reloadTime() {
refreshRate = setTimeout(reloadPage, 5000);
}
function reloadPage() {
$("#calendar-holder").fullCalendar("refetchEvents");
reloadTime();
}
$( document ).ready(function() {
reloadTime();
});
Changing the color:
The way you did it works, but the easiest way is to do it in eventDataTransform. Like so:
eventDataTransform: function(eventData){
if(eventData.end.isBefore(moment())){
eventData.color = "black";
}else{
eventData.color = "green";
}
return eventData;
},
Color Demo
Check if event exists
You didn't mention exactly what to do if the database returns false, but I'll assume you don't want nonexistent events rendered.
Since the source for your events is google calendar, this is actually kind of tricky. Normally, you would use the custom events function and do two ajax calls in it (one for the events and one for checking if they are valid). But you can't do this with google cal events.
So instead we will use eventDataTransform and only display the events after we know they exist.
eventDataTransform: function(eventData){
eventData.display = false; //Don't display until we check the server
eventData._uid = idCounter++; //unique ID. Don't need this if they already have unique IDs
ajaxCall(eventData); //check the server (will retroactively update the event to be displayed)
if(eventData.start.isBefore(moment())){ /*...*/ } //colors
return eventData;
},
The top of your eventRender callback should look like:
eventRender: function(event,element){
if(!event.display){ //Render only if the event exists
return false; //return false to stop the event from rendering.
}
/*...your other render code if you have any*/
}
Define your ajaxCall function outside of fullcalendar:
var ajaxCall = function(eventData){
$.get( "ajax/test.html", function( data ) {
setEvent(eventData._uid,data); //data should be a boolean
});
};
var setEvent = function(id,exists){
var fcEvent = $('#calendar').fullCalendar("clientEvents",function(event){ //get the associated event object
if(event._uid === id){
return true;
}
})[0];
if(typeof fcEvent !== "object")$.error("Event id "+id+" doesn't exist!"); //Throw error if it doesn't exist
fcEvent.display = exists; // Store the server response in the event
$('#calendar-holder').fullCalendar("updateEvent",fcEvent); // Updates and re-renders the event
}
JSFiddle Demo (using fake ajax calls)
Some Explanation
Couple of things that might be useful to know:
The word render in fullcalendar refers to actually displaying the events. It's done whenever the view changes (more often than events are fetched from the DB)
Event sources only fetch events when they are needed. They are stored client-side as data that can be rendered as needed.
eventDataTransform is called once after an event source retrieves an event.
So if you put your ajax call in eventAfterAllRender, the ajax call would be done everytime FC decided to render the calendar resulting in more ajax calls that necessary. It also means you would get a delay every time you change the view. It's much better to do it earlier than render-time.
I can't believe nobody asked this. This is driving me insane. Im using FullCalendar to let the user drop external events to the calendar. I´m folliwing the well known approach:
$('#external-events div.external-event').each(function () {
var eventObject = {
type: 2,
id: $(this).attr("data-id"),
title: $(this).attr("data-name"),
duration: $(this).attr("data-duration"),
guid: $(this).attr("data-guid"),
color: $(this).attr("data-color")
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({ zIndex: 999, revert: true, revertDuration: 0 });
});
My calendar is configured like this (drop event):
drop: function(date) {
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date.format();
// render the event on the calendar
//$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
$.ajax({
async: false,
url: '#Url.Action("AddWorkoutToPlan", "Planning")',
data: { 'planId': planId, 'workoutId': copiedEventObject.id, 'date': date.format() },
success: function(data) {
$('#calendar').fullCalendar('refetchEvents');
}
});
},
As you can see, I don't render the event, I just make an ajax call and on success I refetch the events so I can get the DB id, in case the user wants to remove it.
This is how I get my events:
events: {
url: '#Url.Action("GetPlannedActivities", "Planning")',
data: function() { return { planId: '#Model.Id' } },
beforeSend: function(xhr, opts) {
if (!$("#selectedPlan").val()) {
xhr.abort();
unblockContainer($("#calendar"));
}
},
success: function(data) {}
},
This is working nice, but if the user moves from the current month, then the external events wont drag nor the drop callback is triggered... I don't know what is going wrong...
Any ideas?
Finally I rolled back the FullCalendar version from 2.1.0_BETA1 / BETA2 to v2.0.2 and now is working as expected.
So I guess this is a bug in the new version that uses DIVS instead of TABLES.
I am creating a link that changes text when it is clicked. I want the link text to change back to the original text after all the processing is complete. It was working fine, but the code was spread all over my js file, so I am trying to abstract it into a function. This is the function, textToggle. In the textToggle function we are publishing an event. This event is the one that I cannot get to fire off at the right time.
var textToggle = function(data) {
var original_text = $(data.element).text();
var id = data.id;
var $element = $(data.element);
$element.text(data.replacement_text);
$('body').on(data.event, function(e) {
e.preventDefault();
$this.text(original_text);
});
};
Here is the function that sets up the textToggle. At the end of the function, we are triggering another event `clinical.status'.
$('#clinicalPatients').on('click', '[data-role="auth-process"]', function(e) {
e.preventDefault();
var $this = $(this);
var _id = $target.attr('id');
textToggle({
id: _id,
element: $this,
replacement_text: "Processing...",
event: "clinical.status.finished"
});
$('#clinicalPatients').trigger('clinical.status', [{
id: _id,
target: $target,
action: _type
}]);
});
At the end of clinical.status is when I want to fire the event in toggleText, clinical.status.finished. This is the code for that event.
$('body').trigger('clinical.status.finished', [{
id: originalId
}]);
clinical.status.finished is not getting triggered at the right time. There is no other place in the code that is using this, so it has to be the way that I am setting it up. If I leaved that event out of the toggleText function, and drop it in the function where I set up the toggleText function, then everything works like it is supposed to. By putting on event into a separate function, will this cause issues. Please, any help will be appreciated. Thanks.