For now it seems to work without problems but I was wondering...Let's say you have multiple forms (each on a different page) with each and one of them a different id.
Each form has a button with and id "btnSave". In the masterpage (template) I added all links to the ajax-formhandling-scripts working like this:
$(document).ready(function() {
// ignore the submit
$("#frmNews").submit(function() {
return false;
});
// catch the click-event
$("#btnSave").on("click", function() {
// input control
// ajax-request if input was ok
}
});
Before I continue to build I want to know sure using the same button-id won't give me problems. Am I working wrong here?
Repeated id attribute values are invalid - they must be unique. Use a class instead. Also, from a design point of view you should hang all logic off the submit event of the form. Try something like this:
$(document).ready(function() {
// ignore the submit
$(".frmNews").submit(function(e) {
// input control
if (input_control_ok) {
// $.ajax()...
}
else {
e.preventDefault(); // stop form submission
}
});
});
The .btnSave button should then have the type="submit" attribute added to it, assuming it doesn't already.
I would like to disable the Submit button on a search form that only contains select dropdowns. There are several similar questions here but I most of them deal with fields. The closest thing to my case is Disable submit button if all three of three specific dropdown fields are empty. I modified the solution supplied in JSFiddle to feature an empty option, and did get it working -- but only in JSFiddle, not on my page.
I use the same code from the proposed answer (only changed IDs):
$('#submit').attr('disabled','disabled');
$('select').change(function(){
if ( $(this).hasClass('require_one') ){
$('#submit').removeAttr('disabled');
}
});
$('#submit').click(function() {
$('#searchform').submit();
});
I add the above code right after I include the jquery.js (v. 1.9.1).
I generate the form dynamically, but in JSFiddle I use exactly what is seen in the page source: http://jsfiddle.net/cheeseus/d5xz6aw8/8/
I have no idea why I can't get it to work on the actual page, hope those more knowledgeable can help sort it out.
And, if possible, I would also like the Submit button to be disabled again if all three selects are set to blank values again.
I usually don't like using the ID(3) for CSS selector since you can have only one ID selector with that name on the document and there might be another element already with the same ID. How about using the class hierarchy instead to pinpoint the button element?
In any case you need to re-check the count everytime what you select on what is empty:
var $submitButton=$('.selector .btn');
var $selectors=$('.selector select.require_one');
$submitButton.attr('disabled','disabled');
$('.selector select.require_one').change(function(){
var $empty=$selectors.filter(function() { return this.value == ""; });
if ( $selectors.filter(function() { return this.value == ""; }).length == $selectors.length ){
$submitButton.attr('disabled','disabled');
} else
{
$submitButton.removeAttr('disabled');
}
});
$submitButton.click(function() {
$('#searchform').submit();
});
JSFiddle code here
You can just use a simple count to see if you should display the button or not. Here is jQuery code.
var count = 0;
$('.require_one').change(function() {
count++;
if (count >= 3) {
$('#submit').removeAttr('disabled');
}
});
$('#submit').attr('disabled','disabled');
I think this is because you didn't check is your document ready.
I added few improvements:
caching jquery object in variables, makes your code a bit faster (you don't look for it everytime select is beeing changes).
used recommended way of binding events - 'on' function
'disabled' is property not an attribute, jQuery has dedicated method to use
on select change - check all selects if there is any not selected, it there is - set prop disabled to true, otherwise set false.
instead of disabling submit at initialization, trigger same action you do when selected is beeing changed (if you start with option selected in all select initial state won't be disabled).
$(document).ready(function () {
var $submit = $('#submit');
var $selects = $('select.require_one');
$submit.on("click", function() {
$('#searchform').submit();
});
$selects
.on("change", function(){
var $not_selected = $selects.filter(function() {
return !$(this).val();
});
$submit.prop('disabled', $not_selected.length ? true : false);
})
.first()
.triggerHandler('change');
});
I have a modal dialog in my App that contains about 10 inputs (i.e. text, dates, number and select inputs). I need know if value of any of the widget changed by the user, so that when they click on the cancel button I can prompt them if they like to save changes before closing the dialogue window.
I can do this in two ways, which may not be the smartest way:
1) set a global variable in my javaScript and keep track in "onChange" event.
2) Compare the value of each widget or inputs before and after to determine if any of them changed.
I wonder if there are any other options that I am not aware of since I am new to jQuery and javaScript.
I apologize if this a duplicate question, I searched and found another similar issue but not what I am after.
Best way to track onchange as-you-type in input type="text"?
Thanks
Use a dirty flag:
var dirty = false;
$('#myModalForm input').change(function() {
dirty = true;
});
$('#myModalForm #cancelButton').click(function() {
if (dirty) {
//confirm
}
// exit modal
});
$('#myModalForm #save').click(function() {
// save
dirty = false;
});
I want to write Jquery code in master file, so that if there if user changes page and there is any unsaved changes user should get alert.
I got one answer from this: link
However in most solution I will have to write code on all pages. I want it to write only at one place so that everybody dont have to worry to write it in their modules. My code is like:
<script type="text/javascript">
var isChange;
$(document).ready(function () {
$("input[type='text']").change(function () {
isChange = true;
})
});
$(window).unload(function () {
if (isChange) {
alert('Handler for .unload() called.');
}
});
</script>
But everytime i make changes in text boxes .change() event is not firing.
What can be wrong in the code?
EDIT:
I changed .change() to .click and it is fired. i am using jquery 1.4.1..is it because of jquery version that change() is not working?
This is what i am using, Put all this code in a separate JS file and load it in your header file so you will not need to copy this again and again:
var unsaved = false;
$(":input").change(function(){ //triggers change in all input fields including text type
unsaved = true;
});
function unloadPage(){
if(unsaved){
return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
}
}
window.onbeforeunload = unloadPage;
EDIT for $ not found:
This error can only be caused by one of three things:
Your JavaScript file is not being properly loaded into your page
You have a botched version of jQuery. This could happen because someone edited the core file, or a plugin may have overwritten the $
variable.
You have JavaScript running before the page is fully loaded, and as such, before jQuery is fully loaded.
Make sure all JS code is being placed in this:
$(document).ready(function () {
//place above code here
});
Edit for a Save/Send/Submit Button Exception
$('#save').click(function() {
unsaved = false;
});
Edit to work with dynamic inputs
// Another way to bind the event
$(window).bind('beforeunload', function() {
if(unsaved){
return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
}
});
// Monitor dynamic inputs
$(document).on('change', ':input', function(){ //triggers change in all input fields including text type
unsaved = true;
});
Add the above code in your alert_unsaved_changes.js file.
A version that use serialization of the form :
Execute this code, when dom ready :
// Store form state at page load
var initial_form_state = $('#myform').serialize();
// Store form state after form submit
$('#myform').submit(function(){
initial_form_state = $('#myform').serialize();
});
// Check form changes before leaving the page and warn user if needed
$(window).bind('beforeunload', function(e) {
var form_state = $('#myform').serialize();
if(initial_form_state != form_state){
var message = "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
e.returnValue = message; // Cross-browser compatibility (src: MDN)
return message;
}
});
If the user change a field then manually rollback, no warn is displayed
change event is fired once the user blurs from input not on every single character inputed.
If you need it to be called every time something is changed (even if focus is still in that input field) you would have to rely on combination of keyup and bunch of events to keep track of pasting/cuting using mouse only.
P.S.
I hope you're aware that your approach to detecting changes isn't the best one? If user input some text, leaves the field and then reverts the changes the script would still alert him about modified text.
you should register events for not only inputs but also textareas, if you mean textarea with text box. You can use keyup for isChange, so that you don't wait for user to blur from this area.
$("input[type='text'], textarea").keyup(function () {
isChange = true;
})
This is really just a different version of #AlphaMale's answer but improved in a few ways:
# Message displayed to user. Depending on browser and if it is a turbolink,
# regular link or user-driven navigation this may or may not display.
msg = "This page is asking you to confirm that you want to leave - data you have entered may not be saved."
# Default state
unsaved = false
# Mark the page as having unsaved content
$(document).on 'change', 'form[method=post]:not([data-remote]) :input', -> unsaved = true
# A new page was loaded via Turbolinks, reset state
$(document).on 'page:change', -> setTimeout (-> unsaved = false), 10
# The user submitted the form (to save) so no need to ask them.
$(document).on 'submit', 'form[method=post]', ->
unsaved = false
return
# Confirm with user if they try to go elsewhere
$(window).bind 'beforeunload', -> return msg if unsaved
# If page about to change via Turbolinks also confirm with user
$(document).on 'page:before-change', (event) ->
event.preventDefault() if unsaved && !confirm msg
This is better in the following ways:
It is coffeescript which IMHO automatically makes it better. :)
It is entirely based on event bubbling so dynamic content is automatically handled (#AlphaMale's update also has this).
It only operates on POST forms as GET forms do not have data we typically want to avoid loosing (i.e. GET forms tend to be search boxes and filtering criteria).
It doesn't need to be bound to a specific button for carrying out the save. Anytime the form is submitted we assume that submission is saving.
It is Turbolinks compatible. If you don't need that just drop the two page: event bindings.
It is designed so that you can just include it with the rest of your JS and your entire site will be protected.
Why not simply bind the event to the change callback?
$(":input").change(function()
{
$(window).unbind('unload').bind('unload',function()
{
alert('unsaved changes on the page');
});
});
As an added bonus, you can use confirm and select the last element that triggered the change event:
$(":input").change(function()
{
$(window).unbind('unload').bind('unload',(function(elem)
{//elem holds reference to changed element
return function(e)
{//get the event object:
e = e || window.event;
if (confirm('unsaved changes on the page\nDo you wish to save them first?'))
{
elem.focus();//select element
return false;//in jQuery this stops the event from completeing
}
}
}($(this)));//passed elem here, I passed it as a jQ object, so elem.focus() works
//pass it as <this>, then you'll have to do $(elem).focus(); or write pure JS
});
If you have some save button, make sure that that unbinds the unload event, though:
$('#save').click(function()
{
$(window).unbind('unload');
//rest of your code here
});
Without jQuery:
var unsaved = false;
document.addEventListener("DOMContentLoaded", function() {
var els = document.querySelectorAll('textarea, input, select');
els.forEach( function(el) {
el.addEventListener('change', function() {
unsaved = true;
});
});
window.addEventListener('beforeunload', function(event) {
if(unsaved){
event.returnValue = "string";
}
});
var forms = document.querySelectorAll('form');
forms.forEach( function(form) {
form.addEventListener('submit', function() {
unsaved = false;
});
});
});
The weird 'string' hack explanation can be found here.
I use $('form').change etc. function to set a dirty bit variable. Not suitable to catch all changes (as per previous answers), but catches all that I'm interested in, in my app.
Working on a project where form changes are checked for. I'm having difficulty removing the changes have been made alert when the user submits the form.
$(document).ready(function(){
changes_made = false;
$('input, select, textarea').on('change', function() {
changes_made = true;
});
$(window).bind('beforeunload', function() {
if(changes_made) { return 'You have made changes on this page.'; }
});
$('form').each(function() {
$(this).on('submit', function() {
changes_made = false;
});
});
})
If you want to be able to revert any changes the user has made, you need to store the original contents of the form. That way, instead of waiting for change events, you can just compare the old form contents to the new contents, and replace if necessary.
Other tidbits: you need a var before your variable declaration (otherwise the variable ends up attached to the window object). And unless your form submit is an ajax call, there is no point in setting changes_made back to false. The page will reload and changes_made will be false again anyway.