I am aware of the following http://docs.telerik.com/kendo-ui/api/javascript/ui/gantt#configuration-editable.template
but it is not what I need.
I need to display a custom modal dialog for task edition that is used in other parts of the app instead of the default kendo dialog.
Here's a possible way:
Implement a handler for the edit event and use e.preventDefault() to cancel kendo's built-in handling. This will prevent their dialog(or the template) from showing.
Now you show your own dialog(however you need to do that) and push in the GanttTask data passed to the edit event.
When your dialog is closed, you push the values of the edited data into the GanttTask...this is important! Since you cancelled the built-in functionality, it is now your responsibility to update the underlying data model.
Example edit handler:
edit: function(e) {
// Cancel the built-in editing functionality
e.preventDefault();
var editResult = showMyDialog(e.task);
if (editResult.ok) {
// User clicked OK instead of Cancel...or whatever mechanism your dialog uses.
e.task.set("title", editResult.data.title);
// other data...
}
}
Example custom dialog:
function showMyDialog(task) {
// Fetch/show your actual window, push in the data from the GanttTask
alert("This is my window: " + task.title);
// Simulate user editing of GanttTask.
var editedTitle = "NeW tAsK!";
// other data...
return {
ok: true, // or false if user clicked cancel.
data: {
title: editedTitle
// other data...
}
};
}
Simple demo: http://dojo.telerik.com/#Stephen/apEYa
I've created a Kendo Scheduler that binds to a remote data source. The remote datasource is actually a combination of two separate data sources. This part is working okay.
Question is... is there any way to prevent certain events from being destroyed?
I've stopped other forms of editing by checking a certain field in the event's properties and calling e.preventDefault() on the edit, moveStart and resizeStart events if it should be read-only. This works fine, but I can't prevent deletes.
Any suggestions greatly appreciated.
Just capture the remove event and process it as you have with the edit, moveStart, and reviseStart events. You should see a remove event option off the kendo scheduler. I can see it and capture it in version 2013.3.1119.340.
I think better way is to prevent user from going to remove event in the first place. Handling the remove event still has its validity as you can delete event for example by pressing "Delete" key).
In example below I'm assuming event has custom property called category and events with category equal to "Holiday" can't be deleted.
remove: function(e)
{
var event = e.event;
if (event.category === "Holiday")
{
e.preventDefault();
e.stopPropagation();
}
},
dataBound: function(e)
{
var scheduler = e.sender;
$(".k-event").each(function() {
var uid = $(this).data("uid");
var event = scheduler.occurrenceByUid(uid);
if (event.category === "Holiday")
{
// use .k-event-delete,.k-resize-handle if you want to prevent also resizing
$(this).find(".k-event-delete").hide();
}
});
},
edit: function (e) {
var event = e.event;
if (event.category === "Holiday")
{
e.container.find(".k-scheduler-delete").hide();
}
}
FYI, you can do this...
#(Html.Kendo().Scheduler<ScheduledEventViewModel>()
.Name("scheduler")
.Editable(e => e.Confirmation(false))
)
which will deactivate the default confirmation prompt for the scheduler. Then you can do your own prompt on items you want.
There is also a
.Editable(e => e.Destroy(false))
that you can do to remove the X on the event window. This particular example would remove it for all of the events, but there might be a way to remove it for specific ones.
I've got a problem with FullCalendar and I was looking for solution without any success.
I use eventClick to open overlay form with data of current event. Everything works great until I change my mind and don't want to edit this event but another one. And that causes ajax send request 2 times, once for opened event (which was ready to edit but form was not submitted) and once for event which was really edited and submitted.
$('#sc-calendar').fullCalendar({
eventClick: function(event) {
//opening overlay form window
$('#submit-event-update').bind('click',function() { //click submit
$.ajax({
type: "GET",
url: "event_update",
data: "id="+event.id+"&title="+event.title+"&start="+event.start+"&end="+event.end,
cache: false,
success: function() {
$('#submit-event-update').unbind();
$('#sc-calendar').fullCalendar('updateEvent',event);
}
});
});
}
});
This is starting to be my nightmare. Please help!
It seems to me like there is a problem with the onclick event listener for #submit-event-update.
You should modify your code in this way:
$('#sc-calendar').fullCalendar({
eventClick: function(event) {
//opening overlay form window
//Assign the event id of this event to the global variable event_id
event_id = event.id;
}
});
$('#submit-event-update').bind('click',function() { //click submit
$.ajax({
type: "GET",
url: "event_update",
data: "id=" + event_id + ..., //Note how event.id is not used anymore
cache: false,
success: function() {
$('#sc-calendar').fullCalendar('updateEvent',event);
}
});
});
I changed it so that you bind the onclick event handler to the button just once as opposed to every time an event is clicked. I also assign a variable event_id that holds the value of the current event's id.
Now, for an explanation. You said:
Everything works great until I change my mind and don't want to edit
this event but another one.
What happens when you click on an event?
You bind the onclick event to the #submit-event-update. Now if you do click the button, then you will go into the success() callback of your AJAX call and then unbind the button. But what if you change your mind and don't click the submit button? Now, you have one onclick listener with the old data already tied to the button. When you pick another event, you have two event listeners tied to the same button and hence, an AJAX request is sent two times.
It might be worth reading up on how JavaScript handles event binding here.
Can I do this:
$('.box').delegate('.edit', 'click', function(edit_event){
...
var input = $('input', this);
input.focus().bind('blur keypress', function(event){
// here disable the first .edit event (don't allow click on that element)?
});
});
the event would be enabled again if certain conditions are met inside the 2nd event (and when a AJAX call is complete)
Since you're using the delegate()[docs] method, which is selector based, you could just add a class to the current .edit that excludes it from the selector.
// only invoke if it has "edit" class and not "disable" class
$('#box').delegate('.edit:not(.disable)', 'click', function (edit_event) {
// add the class to this edit element to disable it
var edit = $(this).addClass('disable');
var input = $('input', this);
input.focus().bind('blur keypress', function (event) {
// here disable the first .edit event (don't allow click on that element)?
// after some work, remove the class to re-enable the click
edit.removeClass('disable');
});
});
I used the not-selector[docs] so that the click event won't fire until the disable class is removed.
I need to avoid the double click submitting behavior. I'm using the client validation with the unobtrusive library. I have the following code for avoiding the double clic:
jQuery.fn.preventDoubleSubmit = function () {
var alreadySubmitted = false;
return jQuery(this).submit(function () {
if (alreadySubmitted)
return false;
else {
alreadySubmitted = true;
}
});
};
jQuery('form').preventDoubleSubmit();
Unfortunately, if my form has some validable fields (for example, a required field), the code above is still being fired, hence, even if I correct any mistakes on the form, I won't be able to submit it again.
How can I fire the double click code after the validation has been succesfully done?
You can also use the JQuery One event.
I have found that I could get past most guards against double-clicks by double-clicking fast. Using the one event is the only true way to make sure the event is only fired once. I don't think this technique will work "out of the box" with an input type=submit tag. Instead, you can simply use an input type=button or JQueryUI's .button().
$("#submitButton").one("click", function(event) {
$('#theForm').submit();
});
If you need to re-wire the event on a validation error (or other circumstance), I recommend that you create a function for the event handler. The function isn't necessary in this example because all the event handler does is submit the form, but in more complicated scenarios you may want to avoid repeating yourself.
function submitClick(event) {
$('#theForm').submit();
}
$("#submitButton").one('click', function(event) {
submitClick(event);
});
// This handler will re-wire the event when the form is invalid.
$('#theForm').submit(function(event) {
if (!$(this).valid()) {
event.preventDefault();
$('#submitButton').one('click', function(event) { submitClick(event); });
}
});
You could obviously add the disabling code here if you wanted to give feedback to the user that the button doesn't work anymore. One great side-effect of using the One event is that you don't actually have to make the button disabled, you can use a style of your own.
function submitClick(event) {
$('#submitButton').addClass('disabledButton');
$('#theForm').submit();
}
$("#submitButton").one('click', function(event) {
submitClick(event);
});
// This handler will re-wire the event when the form is invalid.
$('#theForm').submit(function(event) {
if (!$(this).valid()) {
event.preventDefault();
$('#submitButton').one('click', function(event) { submitClick(event); });
$('#submitButton').removeClass('disabledButton');
}
});
JQuery One Event: http://api.jquery.com/one/
I solved it with the following code:
var tryNumber = 0;
jQuery('input[type=submit]').click(function (event) {
var self = $(this);
if (self.closest('form').valid()) {
if (tryNumber > 0) {
tryNumber++;
alert('Your form has been already submited. wait please');
return false;
}
else {
tryNumber++;
}
};
});
NOTE: You can also replace the:
return false;
line, for:
self.attr('disabled', true);
BUT, if you use the name of your submit buttons on your controller for extra logic, they will be sent as null. (you can use an additional hidden field to charge them before submitting)
that's it, hope it helps
Rodrigo
EDIT: Thanks to these posts:
jquery newbie: combine validate with hidding submit button
Why not just use:
function disableButtons() {
var form = $(this);
var btns = $("input:submit", form);
if (!form.valid()) {
// allow user to correct validation errors and re-submit
btns.removeAttr("disabled");
} else {
btns.attr("disabled", "disabled");
}
}
to disable your buttons and activate it using:
$("form").bind("submit", disableButtons);
Based on Ryan P's popular answer I created the following generic solution that also works with my ajax form.
decorate your custom submit button with the following class:
<button type="button" class="one-click-submit-button">Submit</button>
Add the following to your javascript file:
function OneClickSubmitButton() {
$('.one-click-submit-button').each(function () {
var $theButton = $(this);
var $theForm = $theButton.closest('form');
//hide the button and submit the form
function tieButtonToForm() {
$theButton.one('click', function () {
$theButton.hide();
$theForm.submit();
});
}
tieButtonToForm();
// This handler will re-wire the event when the form is invalid.
$theForm.submit(function (event) {
if (!$(this).valid()) {
$theButton.show();
event.preventDefault();
tieButtonToForm();
}
});
});
}
OneClickSubmitButton();
since this is an ajax form we want to reload the handlers if we fail server validation.
function MyForm_OnSuccess() {
if (true if your form passed validation logic) {
//do something since your form submitted successfully
} else { //validation failed on server
OneClickSubmitButton(); //reinitialize the button logic
}
}
Obviously if you don't have ajax forms you can omit the whole OneClickSubmitButton function business and run $('.one-click-submit-button').each(... directly.
I have a form that uses MVC3 unobtrusive validation, and a viewmodel with a [RemoteAttribute].
It looks to me like the form's submit event only fires after all validation has passed. I'm currently using this, and it seems to work:
<input type="submit" value="Submit the Form"
data-app-disable-on-submit="true" />
$('form').live('submit', function() {
$(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
.attr('disabled', 'disabled');
})
;
I set breakpoints on both the remote attribute validation action method and the HttpPost action method. Clicking the submit button the first time hits the breakpoint on the validation action method. At this point, the button is still enabled. I can click it multiple times, and after resuming the validation method, the HttpPost is hit only once. When the HttpPost is hit, the submit button is disabled.
Update
Right you are Alex. So an updated version of the above would look like this:
$('form').on('submit', function() {
$(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
.attr('disabled', 'disabled');
})
$('form').submit(function () {
$('input[type="submit"]', this).attr('disabled', 'disabled');
});
I use a different approach to this. Not wiring to the click event of the button, but to the submit event of the form. Works like a charm to prevent multiple simultaneous submits of forms.
function initFormsToPreventSimultaneousSubmits(selector) {
if (!selector) {
selector = 'form'; // No selector supplied, apply to all forms on the page
}
// Make sure all forms that conform to selector are marked as not submitting
$(selector).each(function()
{
var $form = $(this);
$form.data('submitting', false);
});
// Attach to submit event of all forms that conform to selector
$(selector).off('submit').on('submit', function (e) {
var $form = $(this);
if (!$form.valid || $form.valid()) { // Make sure to only process when the form is valid or jquery validation is not used
if ($form.data('submitting')) {
// form is already submitting. Classic case of double click on one of the submit buttons of the form. Stop the submit
e.preventDefault();
return false;
} else {
// All ok, mark the form as submitting and let the form perform the submit
$form.data('submitting', true);
return true;
}
}
});
}
On document ready i call initFormsToPreventSimultaneousSubmits() to init all forms on the page.
Only thing to remember is that when u use a ajax form post is to call the initFormsToPreventSimultaneousSubmits('#formId') on the OnComplete event of the AjaxOptions settings. Because otherwise the form will still be marked as submitting when its done. When a 'normal' form post is used this is not an issue.
Extends answers by Alex and Ryan P to accounts for situations where jQuery Validation might be missing and where multiple submit buttons exist in a single form.
oneClickSubmitButton = function () {
$('input[type=submit], button[type=submit], input[type=image]').each(function () {
var $theButton = $(this);
var $theForm = $theButton.closest('form');
//hide the button and submit the form
function tieButtonToForm() {
$theButton.one('click', function () {
$theButton.addClass('ui-state-disabled');
});
}
tieButtonToForm();
$theForm.submit(function (event) {
// Only proceed for the clicked button
if (!$theButton.hasClass("ui-state-disabled"))
return;
// If jQuery Validation is not present or the form is valid, the form is valid
if (!$theForm.valid || $theForm.valid())
return;
// Re-wire the event
$theButton.removeClass('ui-state-disabled');
event.preventDefault();
tieButtonToForm();
});
});
};
I was able to fix a similar issue with a couple of lines of code. I prefer this if you don't want to "alert" to user that they double clicked and just silently ignore the second click.
I just made a global javascript variable that I toggled when my function was executing during a critical section. This kept subsequent function calls from re-executing the same section.
var criticalSection = false;
SomeOnClickEventFired = function () {
if (!criticalSection)
{
criticalSection = true;
//Ajax Time
criticalSection = false;
}
}