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');
});
Related
I have a following piece of code which works fine, when i check or uncheck the checkbox, but when i initially loads my page and some of my checkboxes are already checked, i want to show the div box to be visible but the code is not doing so, am i missing anything
please guide through the following code
Thanks
$(document).ready(function() {
//check the state of the checkox
$(".showinvoice").is(':checked') {
var stats = $(this).attr('data-id');
$("#"+stats).css('display','block');
}
//check the code only when the click button is triggered
$(".showinvoice").click(function(e) {
var getStudent = $(this).attr('data-id');
if ($(this).is(':checked')) {
$("#"+getStudent).css('display','block');
} else {
$("#"+getStudent).css('display','none');
}
});
});
Firstly you're missing the if statement around the .showinvoice state condition.
Secondly you should use the data() method to access data-* attributes. You should also use the change method when dealing with radio and checkbox inputs so that the events are still raised by users who navigate using the keyboard. Lastly you can remove the if statement and just use toggle() instead.
To achieve what you require all you need to do is raise a change event on the checkboxes on load of the page. Try this;
// check the state of the checkox
if ($(".showinvoice").is(':checked')) {
var stats = $(this).data('id');
$("#" + stats).show();
}
// check the code only when the click button is triggered
$(".showinvoice").change(function(e) {
var getStudent = $(this).data('id');
$("#" + getStudent).toggle(this.checked);
}).change(); // < to run this code when the page loads
Try changing your first part to...
//check the state of the checkox
$(".showinvoice:checked").each(function() {
var stats = $(this).data('id');
$("#"+stats).css('display','block');
});
Edit3: Before more people keep downvoting this, please note this is not a duplicate question.
I'm working on a site that needs a table full of checkboxes and each one needs to be toggled on/off. Sometimes toggling one on needs to toggle others off and so on.
I did not build the base code, but since it was rather messy with all the logic going on, I decided to make some work like radios so we only have one base function to make much of the logic work.
I also have a function to enable/disable some checkboxes. It all works nicely, no problems at all.
But now there's another thing in play which is a text input. If a certain value is selected in it, some checkboxes automatically get turned on/off and locked in. The same base function is used to do this. But when a checkbox gets disabled with this, and then re-enabled, the following function keeps returning always true only for that checkbox:
$('input[type="checkbox"]').change(function() {
// Make checkboxes with names work like radios (radios can't be toggled off)
if ($(this).attr("name")) {
// Save clicked toggle value
var selected_toggle = $(this).attr('value');
// disable all and then toggle clicked one on
if ($('input[value="'+selected_toggle+'"]').prop("checked")) {
console.log("This is checked");
$('input:checkbox[name='+$(this).attr('name')+']').each(function() {
toggle_checkbox($(this).attr('value'), 'disabled');
});
toggle_checkbox(selected_toggle, 'enabled', 'on');
}
// Enable them all back if unchecking
else {
console.log("This is unchecked");
$('input:checkbox[name='+$(this).attr('name')+']').each(function() {
toggle_checkbox($(this).attr('value'), 'enabled');
});
$(this).parent().toggleClass("on");
}
}
else {
// Toggle them on or off
$(this).parent().toggleClass("on");
}
});
The obvious thing would be to say "something is different when locking/unlocking that checkbox", but it's all the same function and same way all other toggles get disabled, this is used from toggle_checkbox function:
function toggle_checkbox(toggle, value, on, lock) {
// Disable the toggle completely
if (value == 'disabled') {
$('input[value="'+toggle+'"]').attr('disabled', 'disabled');
$('input[value="'+toggle+'"]').parents('li').addClass('disabled');
$('input[value="'+toggle+'"]').parent().removeClass('on');
$('input[value="'+toggle+'"]').prop('checked', false);
}
// Enable a toggle back
if (value == 'enabled') {
$('input[value="'+toggle+'"]').parents('li').removeClass('disabled');
// Turn it on
if (on == 'on') {
$('input[value="'+toggle+'"]').parent().addClass('on');
$('input[value="'+toggle+'"]').prop('checked', true);
}
// Lock it on or remove disabled
if (lock == 'lock') {
$('input[value="'+toggle+'"]').attr('disabled', 'disabled');
}
else {
$('input[value="'+toggle+'"]').removeAttr('disabled');
}
}
}
When I remove the above code for name attributes, the checkbox works fine. Yet though every other checkbox returns Checked/unchecked properly, when clicking that specific un-disabled one, it always returns "this is checked".
I was using is(":checked") before, changing to prop made no difference.
Edit: As said in the comments, using prop or attr didn't make a difference. This is the code that is locking the checkbox that gets "stuck":
function set_hint_toggles(type, state) {
if (type == 'apples') { // Set when you select something with apples
toggle_checkbox('pears', 'disabled');
toggle_checkbox('apples', 'enabled', 'on', 'lock');
toggle_checkbox('oranges', 'disabled');
}
if (state == 'off') { // This is set when a reset button is pressed
var toggles_type = $('#hidden-input-with-value').val();
toggle_checkbox(toggles_type, 'enabled'); // This checkbox gets stuck, all others continue working
$('#text-input').removeAttr("disabled"); // Allows to type something again
}
}
Edit2: After trying Marvin answer I got a slighly different result that could help finding what's wrong:
This stuck checkbox has a "checked" and "disabled" state. When the reset button is clicked, disabled gets removed, but it remains checked (or should). When I tried to click the checkbox with the above code after reset, it was like it got re-checked once, and then kept stuck with checked.
Using [0].disabled = false, I can then keep toggling the checkbox on and off, but no js gets activated for it, and every click still returns checked.
Edit4: When attempting to use
toggle_checkbox(toggles_type, 'disabled');
toggle_checkbox(toggles_type, 'enabled');
In the code that makes the checkbox get stuck (set_hint_toggles(off) function above), it gets disabled only. Afterwards, this checkbox keeps returning always false instead of always true.
Theres a litle tip that you can use to improve your code.. Without a jsfiddle or some example, i'm afraid that i can't help you more than this. You should try using the DOM native api to set the disabled item
$('input[value="'+toggle+'"]')[0].disabled //returns if the element is disabled
$('input[value="'+toggle+'"]')[0].disabled = true //set element as disabled or not
The same works for the checked attribute.
$('input[value="'+toggle+'"]')[0].checked //returns if the element is checked
$('input[value="'+toggle+'"]')[0].checked = true //set element as checked or not
It truly was something wrong in the first block of code I posted. I'm now using this based off Adeneo's suggestion on changing the selectors and it's working perfectly:
// Search checkbox toggles
$('input[type="checkbox"]').change(function() {
// Make checkboxes with names work like radios (radios can't be toggled off)
if ($(this).attr("name")) {
if (this.checked) {
$('[name='+ this.name +']').each(function() {
toggle_disabled( this.value, 'disabled');
});
toggle_disabled( this.value, 'enabled', 'on');
}
else {
$('[name='+ this.name +']').each(function() {
toggle_disabled( this.value, 'enabled');
});
$(this).parent().toggleClass("on");
}
}
// Else if no name, just toggle on class
else {
$(this).parent().toggleClass("on");
}
});
I believe the problem was in the selector used for testing if the checkbox was on.
I'm also using prop on everything else now, but this did not change anything and does not seem like it had to do with the problem at all. The other suggestions also did not do anything.
I'm using a form with various checkbox groups and I would like the next button at the bottom of the page to appear only if any of the checkboxes is checked.
I found a working solution using jQuery here:
var checkboxes = $("input[type='checkbox']"),
submitButt = $("input[type='submit']");
checkboxes.click(function() {
submitButt.attr("disabled", !checkboxes.is(":checked"));
});
http://jsfiddle.net/BPhZe/1937/
I'm looking for a way to do this with MooTools and I would prefer a solution where the button state is not "disabled" but hidden via CSS.
MooTools has the property Element.checked to see whether the specified element is set to "checked" or not. MooTools also allows you to add ":checked" to your selector to get only the selected elements that match. This means you can do something like this to determine whether any checkboxes are checked:
if ($$("input[type=checkbox]:checked").length > 0)
Or this to determine that no checkboxes are currently checked:
if ($$("input[type=checkbox]:checked").length < 1)
Given the sample form you linked to, here is one way to do it:
$$("input[type=checkbox]").each(function(checkboxInput) {
checkboxInput.addEvent("click", function() {
// show submit button if at least 1 checkbox is checked
if (checkboxInput.checked) {
$$("input[type=submit]").each(function(submitButton) {
submitButton.removeProperty("disabled");
});
}
// hide submit button if no checkboxes are checked
if ($$("input[type=checkbox]:checked").length < 1) {
$$("input[type=submit]").each(function(submitButton) {
submitButton.set("disabled", "disabled");
});
}
});
});
If your submit button had an id attribute – say, id="formSubmitButton" – you could reference it that way and accomplish the same thing using slightly less code, instead of having to use $$("input[type=submit]").each(function(submitButton) { ... } :
$("formSubmitButton").removeProperty("disabled");
To change from disabling / re-enabling the button to showing / hiding the button, you could initiate the form with the button set with property style="display:none;", and then call submitButton.removeProperty("style") when checkboxes are checked, and submitButton.setStyle("display", "none") when there are no longer any checked. Full code example for that version, using submit button with an ID:
$$("input[type=checkbox]").each(function(checkboxInput) {
checkboxInput.addEvent("click", function() {
// show submit button if at least 1 checkbox is checked
if (checkboxInput.checked) {
$("formSubmitButton").removeProperty("style");
}
// hide submit button if no checkboxes are checked
if ($$("input[type=checkbox]:checked").length < 1) {
$("formSubmitButton").setStyle("display", "none");
}
});
});
I have a select type dropdown, which upon selection redirects users to another page. I want them to be warned if they try to navigate away without saving when using this select dropdown.
However it needs to ignore this specific select type as one of the input types when determining that an input type has changed. This is my script, but it doesn't perform the desired action, (where .send1 references to the actual select type):
$(document).on('change', '.send1', function(){
if($(":input").not('.send1')){
$(":input").change(function(){
unsaved = true;
});
}
});
If unsaved == true then a users have a warning that there are unsaved changes.
.not() method returns a jQuery object, and an object is considered a truthy value in JavaScript, you should use the length property for checking the length of the collection. But here this is not the main problem, the whole logic doesn't sound promising. If you want to exclude an element from the selection you can use the :not in your selector:
var unsaved = false;
$(document).on('change', '.send1:not("select.specific")', function() {
unsaved = true;
});
$('select.specific').on('change', function() {
if (unsaved) {
// show a modal/alert something...
} else {
// redirect
}
});
I don't really understand what you're asking. It seems you're trying to determine if an input control has the class 'send1' - and if so, you ignore it? Why are you binding all of your inputs to your event handler? Can you post your HTML markup?
The closest I can come to helping is to recommend that you put a class on all of your inputs that COULD have unsaved data in them. Then, write an event handler for your select list that redirects to another page:
$("#ddlThatRedirects").change(function(e){
if (CheckFields()){
//Put whatever alerting you want here
}
else{
//Put redirect or postback logic here
}
});
function CheckFields(){
var UnsavedChanges = false;
$(".ClassNameOfInputs").each(function(){
if ($(this).val().length > 0)
UnsavedChanges = true;
});
return UnsavedChanges;
}
Is it possible to bind javascript (jQuery is best) event to "change" form input value somehow?
I know about .change() method, but it does not trigger until you (the cursor) leave(s) the input field. I have also considered using .keyup() method but it reacts also on arrow keys and so on.
I need just trigger an action every time the text in the input changes, even if it's only one letter change.
There is a simple solution, which is the HTML5 input event. It's supported in current versions of all major browsers for <input type="text"> elements and there's a simple workaround for IE < 9. See the following answers for more details:
jQuery keyboard events
Catch only keypresses that change input?
Example (except IE < 9: see links above for workaround):
$("#your_id").on("input", function() {
alert("Change to " + this.value);
});
Yes, compare it to the value it was before it changed.
var previousValue = $("#elm").val();
$("#elm").keyup(function(e) {
var currentValue = $(this).val();
if(currentValue != previousValue) {
previousValue = currentValue;
alert("Value changed!");
}
});
Another option is to only trigger your changed function on certain keys. Use e.KeyCode to figure out what key was pressed.
You can also store the initial value in a data attribute and check it against the current value.
<input type="text" name="somename" id="id_someid" value="" data-initial="your initial value" />
$("#id_someid").keyup(function() {
return $(this).val() == $(this).data().initial;
});
Would return true if the initial value has not changed.
function checkChange($this){
var value = $this.val();
var sv=$this.data("stored");
if(value!=sv)
$this.trigger("simpleChange");
}
$(document).ready(function(){
$(this).data("stored",$(this).val());
$("input").bind("keyup",function(e){
checkChange($(this));
});
$("input").bind("simpleChange",function(e){
alert("the value is chaneged");
});
});
here is the fiddle http://jsfiddle.net/Q9PqT/1/
You can employ the use of data in jQuery and catch all of the events which then tests it against it's last value (untested):
$(document).ready(function() {
$("#fieldId").bind("keyup keydown keypress change blur", function() {
if ($(this).val() != jQuery.data(this, "lastvalue") {
alert("changed");
}
jQuery.data(this, "lastvalue", $(this).val());
});
});
This would work pretty good against a long list of items too. Using jQuery.data means you don't have to create a javascript variable to track the value. You could do $("#fieldId1, #fieldId2, #fieldId3, #fieldId14, etc") to track many fields.
UPDATE: Added blur to the bind list.
I had to use this kind of code for a scanner that pasted stuff into the field
$(document).ready(function() {
var tId,oldVal;
$("#fieldId").focus(function() {
oldVal = $("#fieldId").val();
tId=setInterval(function() {
var newVal = $("#fieldId").val();
if (oldVal!=newVal) oldVal=newVal;
someaction() },100);
});
$("#fieldId").blur(function(){ clearInterval(tId)});
});
Not tested...
I don't think there's a 'simple' solution. You'll probably need to use both the events onKeyUp and onChange so that you also catch when changes are made with the mouse. Every time your code is called you can store the value you've 'seen' on this.seenValue attached right to the field. This should make a little easier.
You can set events on a combination of key and mouse events, and onblur as well, to be sure. In that event, store the value of the input. In the next call, compare the current value with the lastly stored value. Only do your magic if it has actually changed.
To do this in a more or less clean way:
You can associate data with a DOM element (lookup api.jquery.com/jQuery.data ) So you can write a generic set of event handlers that are assigned to all elements in the form. Each event can pass the element it was triggered by to one generic function. That one function can add the old value to the data of the element. That way, you should be able to implement this as a generic piece of code that works on your whole form and every form you'll write from now on. :) And it will probably take no more than about 20 lines of code, I guess.
An example is in this fiddle: http://jsfiddle.net/zeEwX/
Since the user can go into the OS menu and select paste using their mouse, there is no safe event that will trigger this for you. The only way I found that always works is to have a setInterval that checks if the input value has changed:
var inp = $('#input'),
val = saved = inp.val(),
tid = setInterval(function() {
val = inp.val();
if ( saved != val ) {
console.log('#input has changed');
saved = val;
},50);
You can also set this up using a jQuery special event.