event is only triggered when fired twice - javascript

I don't know why but the first time I click the event target, it doesn't take effect, you have to click the event target twice to take effect but the result is opposite. Consider this experiment that I created using checkbox:
$('.label-button').on('click', checkboxStatus);
function checkboxStatus(e) {
var $evt = $(e.target);
if($evt.next().is(':checked')) {
$('.message').find('.status').text('checked');
} else {
$('.message').find('.status').text('not checked');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cbox" class="label-button" style="display:inline-block;padding:0.5rem 0.7rem;color:#fff;background:#21a1e1;cursor:pointer;">Click to check</label>
<input type="checkbox" id="cbox" />
<div class="message" style="display:block; margin-top:10px;">Checkbox is "<span class="status">not checked</span>"</div>
The first time you click the button, the .status says it's still "not checked" though the checkbox is actually checked. The second time you click the button, it shows the changes, but opposite. The checkbox is checked but the status is "not checked"; the checkbox is unchecked but the status is "checked". I tried to add e.stopPropagation() but it didn't work.
How can I make this right?

By the time click event on label is invoked, input state is not changed hence you are observing such inconsistency.
Bind change event on the input element instead of click event on the label!
$('#cbox').on('change', checkboxStatus);
function checkboxStatus() {
$('.message').find('.status').text(this.checked ? 'checked' : 'not checked');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cbox" class="label-button" style="display:inline-block;padding:0.5rem 0.7rem;color:#fff;background:#21a1e1;cursor:pointer;">Click to check</label>
<input type="checkbox" id="cbox" />
<div class="message" style="display:block; margin-top:10px;">Checkbox is "<span class="status">not checked</span>"</div>

Change the event with change instead of click.
And apply the change event on input:checkbox not with label
finally change the checking if condition like this $evt.is(':checked')
$('#cbox').on('change', checkboxStatus);
function checkboxStatus(e) {
var $evt = $(e.target);
if($evt.is(':checked')) {
$('.message').find('.status').text('checked');
} else {
$('.message').find('.status').text('not checked');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cbox" class="label-button" style="display:inline-block;padding:0.5rem 0.7rem;color:#fff;background:#21a1e1;cursor:pointer;">Click to check</label>
<input type="checkbox" id="cbox" />
<div class="message" style="display:block; margin-top:10px;">Checkbox is "<span class="status">not checked</span>"</div>

$(function(){
$('.label-button').on('click', checkboxStatus);
function checkboxStatus(e) {
var $evt = $(e.target).next();
if( $evt.prop('checked') ) {
$('.message').find('.status').text('not checked');
} else {
$('.message').find('.status').text('checked');
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cbox" class="label-button" style="display:inline-block;padding:0.5rem 0.7rem;color:#fff;background:#21a1e1;cursor:pointer;">Click to check</label>
<input type="checkbox" id="cbox" />
<div class="message" style="display:block; margin-top:10px;">Checkbox is "<span class="status">not checked</span>"</div>

Related

jQuery toggle won't work for checkbox, div remains display:block

I have an input checkbox field and when the checkbox changes (user clicks or unclicks) the div below should toggle. In my style sheet I have the div paypalInputArea as display:none and when the checkbox in clicked, it should toggle, however I can't seem to get it to work. Can anyone see what is wrong with my code?
Here is my html:
<div class="checkbox-row" id="paypalCheckbox">
<input type="checkbox" maxlength="2147483647" value="true" name="paypalPaymentCheckbox" id="paypalPaymentCheckbox" class="checkinput styled" />
<label class="paymentMethodTitle"></label>
</div>
<div class="paypalInputArea">
<isinclude template="includes/paymentmethodsinclude" />
</div>
And here is my jQuery:
$("#paypalCheckbox.checkbox-row .areaExpander").on('change', function() {
$(".paypalInputArea").toggle();
if ($('.paypalInputArea').is(':visible')) {
app.paymentAndReview.setCOContinueBtn(true);
$("#paypalPaymentCheckbox").attr('checked','true');
$('#paypalCheckbox.checkbox-row .areaExpander').addClass('open');
} else {
$("#paypalPaymentCheckbox").removeAttr('checked');
$('#paypalCheckbox.checkbox-row .areaExpander').removeClass('open');
app.paymentAndReview.setCOContinueBtn(false);
}
});
$("#paypalCheckbox.checkbox-row input").attr('checked') && app.paymentAndReview.setCOContinueBtn(true);
$("#paypalCheckbox").on('change', function() {
$(".paypalInputArea").toggle();
if ($('.paypalInputArea').is(':visible')) {
//app.paymentAndReview.setCOContinueBtn(true);
$('#paypalCheckbox.checkbox-row .areaExpander').addClass('open');
} else {
$('#paypalCheckbox.checkbox-row .areaExpander').removeClass('open');
//app.paymentAndReview.setCOContinueBtn(false);
}
});
$("#paypalCheckbox.checkbox-row input").attr('checked') && app.paymentAndReview.setCOContinueBtn(true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="checkbox-row" id="paypalCheckbox">
<input type="checkbox" maxlength="2147483647" value="true" name="paypalPaymentCheckbox" id="paypalPaymentCheckbox" class="checkinput styled" />
<label class="paymentMethodTitle"></label>
</div>
<div class="paypalInputArea" style="display:none">
blabla
</div>
just replace the line:
$("#paypalCheckbox.checkbox-row .areaExpander").on('change', function() {
with:
$("#paypalCheckbox").on('change', function() {
As you have an ID (which has to be unique) you dont have to use other classes or else to reach it!
you can also remove those lines as the attrribute checked is set as the user clicks on the checkbox
$("#paypalPaymentCheckbox").attr('checked','true');
$("#paypalPaymentCheckbox").removeAttr('checked');
Hope this helps!
It looks like you're missing the class areaExpander from your checkbox

Can't Limit Number of Checked Checkboxes

Not sure why the script doesn't work. Want it to uncheck one box when you try to select more than two. For example if you select CHEAP and FAST and then try and select GOOD, FAST is then unchecked.
document.querySelector('body').className = 'has-js';
var checked = [];
[].forEach.call(document.querySelectorAll('input[type="checkbox"]'), function (checkbox) {
checkbox.addEventListener('change', function (e) {
ga('send', 'event', 'checkbox', 'trigger');
if (checkbox.checked && checked.length === 2) {
var uncheckTarget = checked[Math.floor(Math.random() * checked.length)];
uncheckTarget.checked = false;
}
checked = document.querySelectorAll('input[type="checkbox"]:checked');
});
});
<div class="container">
<input type="checkbox" id="fast">
<label class="red" for="fast">FAST</label>
<input type="checkbox" id="good">
<label class="green" for="good">GOOD</label>
<input type="checkbox" id="cheap">
<label class="blue" for="cheap">CHEAP</label>
</div>
Your solution seems to be overly complicated. Also, you should use the click event instead of the change event for your callback because by the time change occurs, the checkmark is already present in the checkbox, so now you'd have to remove it. With click, you can just cancel the event, which occurs prior to the checkmark going into the checkbox.
var boxes = Array.prototype.slice.call(document.querySelectorAll('input[type="checkbox"]'));
boxes.forEach(function(chk) {
chk.addEventListener('click', function (e) {
if (document.querySelectorAll("input[type=checkbox]:checked").length > 2) {
e.preventDefault();
alert("You already have 2 checkboxes checked. Uncheck one and try again!");
}
});
});
<div class="container">
<input type="checkbox" id="fast"><label class="red" for="fast">FAST</label>
<input type="checkbox" id="good"><label class="green" for="good">GOOD</label>
<input type="checkbox" id="cheap"><label class="blue" for="cheap">CHEAP</label>
</div>

Javascript to enable/disable radio buttons when text field is cleared or chars are present

I'm working on a little script that will disable a form field if certain radio button are ticked or if the input filed has characters to disable the radio buttons
So what I'm wanting my code to do is when the User enters the text field and adds at least one character of any type to disable the radio buttons and if that field is cleared to re-enable the radio buttons
For some reason when I'm doing either or, my "Enabled" alert keeps showing and the radio buttons aren't being disabled
to get the alert to pop, need to click outside of the input field, I would like this to be a mouseout if possible but I can work on that later
If the value is entered within the form directly, the radio buttons are disabled but I can't get them enabled once the filed is cleared
Steps:
Enter text in text field, if value isn't set in the form. Radio buttons stay disabled
Enter Value within the form, the text buttons stay disabled when the text field is cleared
Working Parts:
If radio btn "Yes" is ticked display "test" string and disable text field
If Radio btn "No" is ticked then enable text field
jQuery version in use: 1.9
Below is my JavaScript and below that is the HTML
Script:
$(function() {
var tlHeader = 'Test';
var f2 = $('#field_2').val();
// This function controls inpput box toggling on/off radio buttons
$( '#field_2' ).change(function() {
if(f2.length != 0) {
alert( "Disabled" )
$("input[name=toggle]").prop('disabled', true)
} else if(f2.length == 0) {
alert( "Enabled" )
$("input[name=toggle]").removeProp('disabled')
};
});
window.invalidate_input = function() {
// This function controls radio btn actions
if ($('input[name=toggle]:checked').val() == "Yes") {
$('#field_2').attr('disabled', 'disabled'),
$('#thgtLdr').html( tlHeader );
$('#thgtLdr').not("No").show();
} else if ($('input[name=toggle]:checked').val() == "No") {
$('#field_2').removeAttr('disabled'),
$('#thgtLdr').not("Yes").hide();
}
};
$("input[name=toggle]").change(invalidate_input);
invalidate_input();
});
</script>
HTML:
<body>
<div id=rdTest>
<div class="inputField">
<label>Focal Image:</label>
<input name="FocalImage" type="text" id="field_2" class='textbox' value="" />
</div> <!-- End input field -->
<div class="radioGroup">
<label>Test Page:</label>
<input type='radio' name='toggle' value='Yes' id="tglyes"/>Yes
<input type='radio' name='toggle' value='No' id="tglno"/>No
</div>
<div id="thgtLdr">
</div>
</div>
</body>
Your use case isnt entirely clear but I'll show you how to achieve the basic goal.
First, I would avoid the mouse events and use keyup with a timer so that my function is only called when the user stops typing and not after each typed letter. Then it's just a mater of checking the text and acting to enable or disable the elements. Here is an example:
var keyupDelay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
$('#field_2').keyup(function() {
var $this=$(this);
keyupDelay(function(){
var val=$this.val();
console.log(val);
if(val=='') $('#tglyes, #tglno').prop('disabled',true);
else $('#tglyes, #tglno').prop('disabled',false);
}, 400 ); // triggered after user stops typing for .4 seconds, adjust value as needed
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=rdTest>
<div class="inputField">
<label>Focal Image:</label>
<input name="FocalImage" type="text" id="field_2" class='textbox' value="" />
</div>
<!-- End input field -->
<div class="radioGroup">
<label>Test Page:</label>
<input type='radio' name='toggle' value='Yes' id="tglyes" disabled="true"/>Yes
<input type='radio' name='toggle' value='No' id="tglno" disabled="true"/>No
</div>
<div id="thgtLdr">
</div>
</div>
Try this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(document).on('click','.choice',function(){
if($(this).val() == 'yes')
{
$('.textfield').prop('disabled',true);
$('#string').html('Test Welcome');
}
else
{
$('.textfield').prop('disabled',false);
$('#string').html('');
}
});
$(document).on('keyup','.textfield',function(){
if($(this).val().length > 0)
{
$('.choice').each(function()
{
if($(this).is(':checked'))
{
$(this).attr('checked',false);
}
$(this).prop('disabled',true);
});
}
else
{
$('.choice').prop('disabled',false);
}
});
});
</script>
<body>
<form>
<input type="text" class="textfield" placeholder="enter text"/>
Yes<input type="radio" name="choice" class="choice" value="yes" />
No<input type="radio" name="choice" class="choice" value="no" />
<p id="string" ></p>
</form>
</body>
You can simplify your code in many ways.
The keyup event will be triggered every time the user releases a key on the text field. Inside the callback, you can get the value of the text field with this.value. From experience, it is best to use .prop() method when toggling certain input-related attributes like disabled and checked. You can enable/disable these attributes using booleans.
// cache the elements to avoid having retrieve the same elements many times
var $textbox = $('#field_2'),
$radios = $('input[name=toggle]'),
$div = $('#thgtLdr');
// everytime user presses a key...
$textbox.on('keyup', function() {
// check if a value was entered or not
// if so, disabled the radio buttons; otherwise enable the radio buttons
$radios.prop('disabled', this.value);
});
// when radio buttons change...
$radios.on('change', function () {
// check if value is Yes or No
if (this.value === 'Yes') {
$textbox.prop('disabled', true);
$div.text(this.value);
} else {
$textbox.prop('disabled', false);
$div.empty();
}
});
<div id=rdTest>
<div class="inputField">
<label>Focal Image:</label>
<input name="FocalImage" type="text" id="field_2" class="textbox" value="">
</div>
<div class="radioGroup">
<label>Test Page:</label>
<input type="radio" name="toggle" value="Yes" id="tglyes">Yes
<input type="radio" name="toggle" value='No' id="tglno">No
</div>
<div id="thgtLdr"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script> // place code here </script>
Also, get into the habit of caching your jQuery objects.

jQuery On click wont fire

I have a textbox, a checkbox and a span tag. When I click on the checkbox, it should show its state in the span tag. When textbox is updated, it reinserts the checkbox block. When you click on the checkbox now, it fails to update the state.
I am using the on event handler for checkbox click event, so I expect it to work.
Any idea why this is not working as expected?
$('div[role] input[type=checkbox]').on('click', chg);
$('div[role] input[type=text]').on('input', sourceChanged);
function chg() {
var istiki = $(this).is(":checked");
$('#upd').html(istiki);
}
function sourceChanged() {
$('span', $(this).closest('.input-group')).html('<input type="checkbox">');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div role="Tiki" class="input-group">
<input type="text" class="form-control" />
<span class="input-group-addon"><input type="checkbox" /></span>
</div>
<span id="upd"></span>
As you're dynamically creating a new checkbox when the value changes, you need to delegate the event to your checkbox by assigning it to a non-dynamic ancestor:
$('div[role]').on('change', 'input[type=checkbox]', chg);
Note how I've used change instead of click as this is more appropriate for checkboxes.
In the below snippet I've also changed $(this).is(":checked") to just this.checked.
$('div[role]').on('change', 'input[type=checkbox]', chg);
$('div[role] input[type=text]').on('input', sourceChanged);
function chg() {
var istiki = this.checked;
$('#upd').html(istiki);
}
function sourceChanged() {
$('span', $(this).closest('.input-group')).html('<input type="checkbox">');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div role="Tiki" class="input-group">
<input type="text" class="form-control" />
<span class="input-group-addon"><input type="checkbox" /></span>
</div>
<span id="upd"></span>
Note also that if you want it to say false you should convert your istiki variable to a string:
$('#upd').html('' + isticki);

hiding div based on unchecking checkboxes

I have multiple checkboxes in a form. Based on clicking those checkboxes, I show a div section. But if I uncheck even one checkbox, that div section gets hidden. How do I make sure that div section is hidden only if all checkboxes are unchecked. Crude way can be to write my own 'display' method which will check if all checkboxes are unchecked and then hide the div section. Any easier solution??
HTML:
<input type="checkbox" class="group" name="check1">
<input type="checkbox" class="group" name="check2">
<input type="checkbox" class="group" name="check3">
<input type="checkbox" class="group" name="check4">
jQuery:
$(function() {
var $checks = $('input:checkbox.group');
$checks.click(function() {
if($checks.filter(':checked').length == 0) {
$('#div').hide();
} else {
$('#div').show();
}
});
});
The following code will show the div if one or more checkboxes has been checked:
jQuery
Version 1:
$("input[name='mycheckboxes']").change(function() {
$("#showme").toggle($("input[name='mycheckboxes']:checked").length>0);
});
Version 2 (more efficient):
var MyCheckboxes=$("input[name='mycheckboxes']");
MyCheckboxes.change(function() {
$("#showme").toggle(MyCheckboxes.is(":checked"));
});
HTML
<input type="checkbox" name="mycheckboxes" />
<input type="checkbox" name="mycheckboxes" />
<input type="checkbox" name="mycheckboxes" />
<input type="checkbox" name="mycheckboxes" />
<div id="showme" style="display: none">Show me</div>
Code in action (Version 1).
Code in action (Version 2).
--- Different Checkbox Names Version ---
For different named checkboxes, wrap them in a DIV with an identifier. E.g.
jQuery
var MyCheckboxes=$("#checkboxgroup :checkbox");
MyCheckboxes.change(function() {
$("#showme").toggle(MyCheckboxes.is(":checked"));
});
HTML
<div id="checkboxgroup">
<input type="checkbox" name="mycheckbox1" />
<input type="checkbox" name="mycheckbox2" />
<input type="checkbox" name="mycheckbox3" />
<input type="checkbox" name="mycheckbox4" />
</div>
<div id="showme" style="display: none">Show me</div>
This code in action.
Not really, you need Javascript for this one... Or maybe... Let's say:
<html>
<head>
<style type="text/css">
#input_container > input + input + input + div {display:none}
#input_container > input:checked + input:checked + input:checked + div {display:block}
</style>
</head>
<div id="input_container">
<input type="checkbox">blah1
<input type="checkbox">blah2
<input type="checkbox">blah3
<div>To show/hide</div>
</div>
</body>
</html>
I'd create a function that uses a variable that tracks the number of checkboxes checked:
var numberOfChecks = 0;
function display(ev) {
var e = ev||window.event;
if (this.checked) {
numberOfChecks++;
} else {
numberOfChecks--;
}
if (!numberOfChecks) {
//hide div code
} else {
//display div code
}
}
Use that function for each onClick event for every checkbox. In the ideal world this would be done inside some initialization function so that numberOfChecks and display aren't in the global namespace.
Plain Javascript:
HTML
<div id="checkboxes">
<input type="checkbox" name="check1">
<input type="checkbox" name="check2">
<input type="checkbox" name="check3">
<input type="checkbox" name="check4">
</div>
<div id="hiddendiv"><!-- more stuff --></div>
Javascript
(function() { //Create clousre to hide the checked variable
var checked = 0;
var inputs = document.getElementById('checkboxes').getElementsByTagName('input');
for (var i=0, l=inputs.length; i<l; i++) {
if (inputs[i].type == 'checkbox') {
if (inputs[i].checked) checked++; //Count checkboxes that might be checked on page load
inputs[i].onchange = function() {
checked += this.checked ? 1 : -1;
var hiddendiv = document.getElementById('hiddendiv');
if (!checked) hiddendiv.style.display = "none";
else hiddendiv.style.display = "";
};
}
}
}());
The other option is to simply iterate through each checkbox every time the change event is fired rather than relying on counting, which is probably more error prone. Obviously jQuery is more concise, but a little verbosity never hurt anyone.
function toggleCheckbox(id) {
if ($("input[id=" + id + "]").is(':checked')) {
$( "#"+id ).prop( "checked", false );
} else {
$( "#"+id ).prop( "checked", true );
}
}
Just pass the id of your checkbox

Categories