Disable Enable unobtrusive validation for specific submit button - asp.net-mvc

I have two submit buttons Back, Continue. What should I to do to disable client validation when I click on Back. I was trying to add cancel class to button attribute but It seams does not help.
UPD. Actually this is working cancel class. But It seams not working if you add it dynamically(by javascript).

I attached an event handler to certain buttons, that altered the settings of the validator object on that particular form.
$(".jsCancel").click(function (e) {
$(e.currentTarget).closest("form").validate().settings.ignore = "*"
});
This has worked like a charm for me in MVC3.
I don't know if this helps you in particular, but since I use ajax form, I had to attach the event to these buttons each time the contents of the ajax form was replaced, by using the event ajax success. The full code that reparses the form and attaches the event to the cancel buttons is:
$(document).ajaxSuccess(function (event, xhr, settings) {
var $jQval = $.validator, adapters, data_validation = "unobtrusiveValidation";
$jQval.unobtrusive.parse(document);
$(".jsCancel").click(function (e) {
$(e.currentTarget).closest("form").validate().settings.ignore = "*"
});
});

Hijack the button click for form submission using JavaScript.
Here is good example with jQuery:
$("#MyButton").click(function(e) {
//submit your form manually here
e.preventDefault();
});

This is really a comment to the answer by tugberk, but comments don't show code examples very well.
Some browser versions do not like the "preventDefault()" function. After being bitten by this a few times, I added a simple utility function:
//Function to prevent Default Events
function preventDefaultEvents(e)
{
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
You call it in place of "preventDefault" like this:
$("#CancelButton").on("click", function(event) {
preventDefaultEvents(event);
return false;
});

You can use "cancel" css class.
Ex: <input type="submit" value="Cancel" name="Cancel" class="cancel" />
JQuery.Validate handle the rest in the following code:
// allow suppresing validation by adding a cancel class to the submit button
this.find("input, button").filter(".cancel").click(function() {
validator.cancelSubmit = true;
});

Related

How to stop jQuery Mobile calling $.mobile.loading('hide') during changePage?

I'm trying to stop jQuery Mobile hiding the loading spinner when changePage is called.
The program flow goes like this, starting with clicking a link, which has its click event defined like this:
$('body').delegate('.library-link', 'click', function() {
$.mobile.loading( 'show' );
$.mobile.changePage($('#page-library'));
return false;
});
Upon clicking the link, the pagebeforeshow event is fired, which triggers a function to populate the page from the local storage, or else make an ajax call to get the data.
$(document).on('pagebeforeshow', '#page-library', function(event){
ui.populate_data();
});
In ui.populate_data() we get the data from local storage or make an ajax call.
ui.populate_data = function() {
if (localdata) {
// populate some ui on the page
$.mobile.loading( 'hide' );
} else {
// make an ajax call
}
};
If the data is there, we load the data into the container and hide the loading spinner. If not it makes the ajax call, which on complete saves the data in local storage, and calls ui.populate_data()
The problem is, after the pagebeforeshow event is finished, changePage is calling $.mobile.loading( 'hide' ), even though the data might not be there yet. I can't find any way to prevent changePage from hiding the spinner, other than by temporarily redefining $.mobile.loading, which feels pretty wrong:
$('body').delegate('.library-link', 'click', function() {
$.mobile.loading( 'show' );
loading_fn = $.mobile.loading;
$.mobile.loading = function() { return; };
$.mobile.changePage($('#page-library'), {showLoadMsg: false});
return false;
});
and before hiding the spinner in my ui function:
ui.populate_data = function() {
if (localdata) {
// populate some ui on the page
if (typeof loading_fn === 'function') {
$.mobile.loading = loading_fn;
}
$.mobile.loading( 'hide' );
} else {
// make an ajax call
}
};
Surely there must be a way to get complete control over the showing and hiding of the loading widget, but I can't find it. I tried passing {showLoadMsg: false} to changePage, but as suggested by the docs it only does things when loading pages over ajax, which I'm not doing.
Maybe it's too much for many, but I found a solution other than the written in the comments (which didn't work for me).
I use the jquery mobile router and in the 'show' event of a page, I do $.mobile.loading("show");, so when the page appears it does with the loading spinner showing.
Though to hide the spinner, I had to use $('.ui-loader').hide();, which is weird, I know...
I use Jquery Mobile Router for a lot more, but it solved this issue.
(Maybe just listening to the proper event and triggering the spinner would also work, as this is what JQMR does...)
I'm using JQM 1.4.2...

jquery mobile trigger click doesn't work the first time

I have a jquery mobile form with several radio inputs whit the options "DS", "NO" and "YES". I want when I click a button it simulates a click on the "YES" option of all radio buttons.
I use this code:
$("#btn-all-yes").click(function(){
$(".replay-yes").each(function(index, element){
$(element).trigger("click");
//$(element).click();
});
});
But I need to do click two times in the button to achieve the desired result. If I put the line '$(element).trigger("click")' two times it works, but I think it should work with a single call to the click event.
You can see all the code at http://jsfiddle.net/qwLPH/7/
You need to change its' status using .prop and then refresh it .checkboxradio('refresh').
Working demo
Update - Uncheck other buttons
$("#btn-all-yes").click(function () {
$('[data-role="controlgroup"]').find("[type=radio]").each(function () {
if ($(this).hasClass('replay-yes')) {
$(this).prop('checked', true).checkboxradio("refresh");
} else {
$(this).prop('checked', false).checkboxradio("refresh");
}
});
});
Old answer
$("#btn-all-yes").click(function(){
$(".replay-yes").each(function(index, element){
$(element).prop('checked', true).checkboxradio("refresh");
});
});
Reference
Similar issue
Try to initialize the click on page load:
$(".replay-yes").each(function (index, element) {
$(element).trigger("click");
//$(element).click();
}).click();
//-^^^^^^^----------this way
Tryout in fiddle here

jQuery ButtonSet() Hover State Override

I have been tooling around with this all day and can't figure it out...
I have a list of buttons (utilizing the jQuery UI buttonset() functionality) and I am wanting to keep the ui-active class even after I hover off of a button, but for some reason, jQuery UI functionality keeps removing the class and erases the highlight from the button (this is bad because the user then wouldn't know what button they are on).
Here is the code so far:
function showSection(sectionIndex){
$('.listSection').hide();
$('#listSection' + sectionIndex).show();
$('.listSectionHeader.ui-state-active').each(function(){
$(this).removeClass('ui-state-active');
});
$('#listSectionHeader' + sectionIndex).addClass('ui-state-active');
}
var buttons = $( "#listHeader a" );
$.each(buttons, function(){
$(this).bind('mouseleave.button', function(){
if($(this).hasClass('ui-state-active'))
return;
});
});
Something like this: http://jsfiddle.net/4yamQ/ ? Would require an extra class in the css such as:
ui-state-active,
ui-mycustomclass
{
jquery ui styling...
}

jQuery UI autocomplete select event not working with mouse click

I have a list of links, and I have this search box #reportname. When the user types in the search box, autocomplete will show the text of the links in a list.
<div class="inline">
<div class="span-10">
<label for="reportname">Report Name</label>
<input type="text" name="reportname" id="reportname" />
</div>
<div class="span-10 last">
<button type="button" id="reportfind">Select</button>
</div>
</div>
The user can then use the keyboard arrow to select one of the text, and when he press ENTER, browser will go to the address of the link. So far so good.
<script type="text/javascript">
$(document).ready(function () {
$("#reportname").autocomplete({
source: $.map($("a.large"), function (a) { return a.text }),
select: function () { $("#reportfind").click() }
})
$("#reportfind").click(function () {
var reportname = $("#reportname")[0].value
var thelinks = $('a.large:contains("' + reportname + '")').filter(
function (i) { return (this.text === reportname) })
window.location = thelinks[0].href
})
});
</script>
The issue is when the user types, autocomplete shows a list, and then the user use the mouse to click one of the result. With keyboard navigation, the content of the search box is changed, but if the user clicks one of the options, the search box is not modified and the select event is immediately triggered.
How can I make the script work with keyboard selection and mouse selection? How can I differentiate between select events that are triggered by keyboard with the ones triggered by mouse?
To your 2nd question: "How can I differentiate between select events that are triggered by keyboard with the ones triggered by mouse?"
The event object in the jQuery UI events would include a .originalEvent, the original event it wrapped. It could have been wrapped multiple times though, such as in the case of Autocomplete widget. So, you need to trace up the tree to get the original event object, then you can check for the event type:
$("#reportname").autocomplete({
select: function(event, ui) {
var origEvent = event;
while (origEvent.originalEvent !== undefined)
origEvent = origEvent.originalEvent;
if (origEvent.type == 'keydown')
$("#reportfind").click();
},
...
});
Thanks to #William Niu and firebug, I found that the select event parameter 'ui' contains the complete selected value: ui.item.value. So instead of depending on jquery UI to change the text of the textbox, which didn't happen if the user clicks with mouse, I just pick up the selected value from 'ui':
$("#reportname").autocomplete({
select: function (event, ui) {
var reportname = ui.item.value
var thelinks = $('a.large:contains("' + reportname + '")').filter(
function (i) { return (this.text === reportname) })
window.location = thelinks[0].href
};
})
I tested it in all version of IE (inlcuding 9) and always ended up with an empty input-control after I selected the item using the mouse. This caused some headaches. I even went down to the source code of jQuery UI to see what happens there but didn’t find any hints either.
We can do this by setting a timeout, which internally queues an event in the javascript-engine of IE. Because it is guaranteed, that this timeout-event will be queued after the focus event (this has already been triggered before by IE itself).
select: function (event, ui) {
var label = ui.item.label;
var value = ui.item.value;
$this = $(this);
setTimeout(function () {
$('#txtBoxRole').val(value);
}, 1);
},
Had the same issue / problem.
Jquery: 1.11.1
UI: 1.11.0
Question: Do you use bassistance jquery validte plugin simultanously?
If positive: update this to a newest version or just disable it for tests.
I updated from 1.5.5 to 1.13.0
Helped for me. Good luck!
I recently encountered the exact same problem (autocomplete items not clickable, keyboard events working).
Turned out that in my case the answer was not at all JS related. The autocomplete UI was not clickable simply because it was lacking an appropriate value for the z-index CSS property.
.ui-autocomplete {
z-index: 99999; /* adjust this value */
}
That did the trick.
This may be a bit farshot, but I had a similar situation where selecting an autocomplete value left the input field empty. The answer was to ignore the "change" events (as those were handled by default) and replace them with binds to "autocompletechange" events.
The "change" event gets triggered before the value from autocomplete is in the field => the field had "empty" value when handling the normal "change" event.
// ignore the "change" event for the field
var item = $("#"+id); // JQuery for getting the element
item.bind("autocompletechange", function(event, ui) { [call your handler function here] }
I was facing a similar problem. I wanted to submit the form when the user clicked on an option. But the form got submitted even before the value of the input could be set. Hence on the server side the controller got a null value.
I solved it using a modified version of William Niu's answer.
Check this post - https://stackoverflow.com/a/19781850/1565521
I had the same issue, mouse click was not selecting the item which was clicked.My code was supposed to make an ajax call to fetch the data as per the selection item from autocomplete source.
Previous code: mouse click not working.
select: function(event, ui) {
event.preventDefault();
for(i= 0; i< customer.length; i++)
if(document.getElementById('inputBox').value == customer[i].name)
{
$.ajax({
call
})
Changed code :mouse click working
select: function(event, ui) {
// event.preventDefault();
for(i= 0; i< customer.length; i++)
// if(document.getElementById('inputBox').value == customer[i].fields.name)
if(ui.item.value == customer[i].name)
{
$.ajax({
call
})
After inspecting the code in the developer tools console, I noticed there were two list items added. I removed the pairing <li></li> from my response code and oh yeah, the links worked
I also added this function as the click event:
$("#main-search").result(function ()
{
$("#main-search").val("redirecting...."), window.location.href = $("#main-search").attr("href").match(/page=([0-9]+)/)[1];
})
This works and you can test it here: Search for the term dress -->

GLOBAL loading inside each single button with Jquery in ajax calls of asp.net mvc

I have the following scenario:
I have a button\link with a image inside like this:
<button type="submit" id="myButton" class="button"><img src="../../Content/images/check.png" id="defaultImage" />
SaveData!!!</button>
We are OK here! Now what I need to do is:
I want on the click that the image change for a loading element that is previously loaded in the page like this:
<img id="loadingImage" src="../../Content/images/loader.gif" style="display: none;" alt="loading"/>
And then when the load complete turn back the old button image, I ended with this code:
function loader() {
var $button = $('#myButton');
if (btnState == '1') {
$button.find('img').hide();
$button.prepend($('#loadingImage'));
$('#loadingImage').css({ 'display': 'inherit' });
btnState = '0';
}
else {
$button.find('img').hide();
$button.prepend($('#defaultImage'));
$('#defaultImage').show();
btnState = '1';
}
}
This does the trick for ONE SINGLE button(since I pass its ID in the function) but, when I have for example a grid with a button on each line, I found inviable when managing a screen with many buttons do this for each of then. The main question is: How can I make this method general for all buttons/links on one specific class in the page?
The goal is: Click a button, get the image and change it and stop(can be manual). I just don't wanna have to Hook ALL buttons.
You should do something like this, it will prevent the user from double submitting:
$('.button').click(function(evt) {
evt.preventDefault();
var button = this;
hideButton(button);
$('ID or CLASS').load('AJAX FILE URL', function() {
//On success, show button remove image
showButton(button);
});
});
function hideButton(button) {
$(button).hide().after('<img src="../../Content/images/loader.gif" alt="loading"/>');
}
function showButton(button) {
$(button).next('img').hide();
$(button).show();
}
All of the code above should be in the $(document).load
Your HTML should look like:
<button type="submit" class="button"><img src="../../Content/images/check.png" />SaveData!!!</button>
There is no need for Id's now on anything.

Resources