First, as usual, sorry if this answer exists but I searched and couldn't quite find the answer for which I am looking.
I'm trying to track an action on an input checkbox only once, that is if I have a list of checkboxes I want to only track if user clicked on it once, so even if they deselect a chackbox they've checked only the first click is tracked.
I know there's a way to check if a checkbox has been clicked in JS via querySelector().input type call, but I'm lost as to how to bring that full circle to only have tracking event fire only once regardless of how many times the user toggles it.
Consider the following markup:
<li class="js-form-item form-item form-item__item form-item--checkbox__item">
<span class="checkbox">
<input view_id="explore" display_id="explore_main" data-drupal-selector="edit-category-title-app" type="checkbox" id="edit-category-title-app" name="category[title_app]" value="title_app" class="form-checkbox form-item__textfield">
<label for="edit-category-title-app" class="checkbox__label">
<span class="checkbox__faux"></span><span class="form-item__label">App</span>
</label>
</span>
</li>
Any help would be greatly appreciated. Vanilla JS only, please.
Attach an event listener and remove it when it is triggered.
function addEventListenerOnce(target, type, listener) {
target.addEventListener(type, function fn(event) {
target.removeEventListener(type, fn);
listener(event);
});
}
addEventListenerOnce(document.getElementById("edit-category-title-app"), "change", function (event) {
alert("You'll only see this once!");
// DTM call here
});
See this post
Related
This happens very rarely but it still happens sometimes. I have two buttons next to each others with a jQuery click event on each:
JS:
$("#accepttrade").click(function(){
if(document.getElementById("agreeterms").checked ){
//accept process
$("#acceptdeposit").slideUp(200);
}
});
$("#declinetrade").click(function(){
//decline
$("#acceptdeposit").slideUp(200);
});
HTML:
<div id="acceptdeposit">
<button id="declinetrade" >Decline</button>
<button id="accepttrade" >Accept</button><input type="checkbox" id="agreeterms">
</div>
But sometimes when someone click on decline, it occurs the click of accept button, and go through even if the checkbox is unchecked.
I have never experienced it myself, but is it possible that this could happend? How can I be sure that "accept process" is never reached unless the user checks the box and click on accept?
Try this, cancel your click event:
$("#accepttrade").click(function(e){
if($("#agreeterms").is(':checked') ){
//accept process
$("#acceptdeposit").slideUp(200);
}
e.preventDefault();
});
The problem I am having is that the radio buttons in my scenario are not being selected when they are clicked. I have created a JSFiddle to show the code and the issue.
For whatever reason, I have an entire area that is surrounded in an element.
<a href="/link">
//some stuff
<div class="protected">
<input type="radio" name="b1" value="1" /> Button 1
<input type="radio" name="b1" value="2" /> Button 2
</div>
//some stuff
</a>
There is a small section within this tag that needs to be protected from the default behaviour of the link. This section contains some radio inputs which need to be selectable.
The way I currently have it, I am protecting the "protected" section with an event listener and:
$('.protected').off('click').on('click', function (e) {
e.preventDefault();
});
I also have an event listener on the radio buttons so that I can perform the change of property when they are clicked.
$('.protected > :radio').off('click').on('click', function (e) {
$(this).siblings(':radio').removeAttr('checked');
$(this).attr('checked', 'checked');
});
Unfortunately, this is setting the checked attribute in the dom however the radio button is not being filled in on the screen for the user.
Any help would be greatly appreciated.
You need to add stopPropagation()
$('.protected > :radio').off('click').on('click', function (e) {
e.stopPropagation();
//$(this).siblings(':radio').removeAttr('checked');
//$(this).attr('checked', 'checked');
});
Also, make sure to comment out
$(this).siblings(':radio').removeAttr('checked');
$(this).attr('checked', 'checked');
You don't need them as the browser handles this for you.
DEMO
What was happening is, since you had preventDefault in the container click handler, the nested click event was propagating to that click handler and was preventing the radio button from being set.
I have a very strange issue with jQuery where I am triggering a click on a radio button but it is not firing completely and is not being captured by an on click function, however a similar call to jQuery trigger is being captured.
In the following jQuery I am selecting a <div> and using find to search for the suitable content.
var prev_chosen_d_option = $('#d_options_table .d_option_row[data-option-id="' + d_option_for_jq + '"]');
// this works, and the on click is captured
prev_chosen_d_option.find('.hover_target').trigger("click", true);
// this selects the radio button, but DOES NOT fire the on click function seen below
prev_chosen_d_option.find('#d_standard_use_b_as_s_no').trigger("click", true);
These are my radio buttons:
<input type="radio" value="yes" id="d_standard_use_b_as_s_yes" name="d_standard_use_b_as_s">
<input type="radio" value="no" id="d_standard_use_b_as_s_no" name="d_standard_use_b_as_s">
$("#d_options_table .d_option_row .hover_target").on("click", function(e, isFirstLoad) {
// it comes in here fine!
});
$('input[name=d_standard_use_b_as_s], input[name=d_next_day_use_b_as_s], #del_standard_use_b_as_s_no').on("click", function(e, isFirstLoad) {
// it DOESN'T come in here
});
I can't see how jQuery is able to select the radio button and successfully check it, but the on method doesn't pick it up as a click...especially when I have a very similar setup running in close proximity in the code.
I know for sure that the radio buttons are within the selector as I can dump it out to the console with a console.log. Interestingly, when I dump out the events attached to it to the console I get undefined from this after the trigger:
console.log(prev_chosen_d_option.find("#_standard_use_b_as_s_no").data('events'));
(I am using jQuery 1.7.2 and testing in FF).
Instead of
$('input[name=del_standard_use_b_as_s], input[name=del_next_day_use_b_as_s], #del_standard_use_b_as_s_no').on('click', function(e) {
//
});
Try :
$(document).on('click', 'input[name=del_standard_use_b_as_s], input[name=del_next_day_use_b_as_s], #del_standard_use_b_as_s_no', function(e) {
//
});
The reason for this not working was simply I had the click handler below where I was actually triggering the click in the code.
I'm using checkboxes to toggle the enabled and disabled state of some multi-lists on a registration form. The checkbox is labeled with the category, and the multi-list contains the items that belong to that category.
I'm using jQuery 1.7.2.
$('#sch_cat_hockeyschools').toggle(function(ev) {
ev.stopPropagation();
$("#type_select_hockeyschools").prop("disabled", false);
$("#type_select_hockeyschools").removeProp("disabled", "disabled");
$("#sch_cat_hockeyschools").prop("checked", true);
$("#sch_cat_hockeyschools").prop("checked", "checked");
}, function(ev) {
ev.stopPropagation();
$("#type_select_hockeyschools option:selected").removeAttr("selected");
$("#type_select_hockeyschools").prop("disabled", true);
$("#type_select_hockeyschools").prop("disabled", "disabled");
$("#sch_cat_hockeyschools").prop("checked", false);
$("#sch_cat_hockeyschools").removeProp("checked");
});
Sample of corresponding checkbox HTML:
<input class="catmark" type="checkbox" name="sch_categories[]" id="sch_cat_hockeyschools" value="1" />General Hockey Schools
<input class="catmark" type="checkbox" name="sch_categories[]" id="sch_cat_springhockey" value="2" />Spring Hockey
The problem is that the upon clicking the checkbox, the checkbox does not become ticked or checked; it immediately returns to an unchecked state, which I thought the stopPropagation() function would help with. Apparently not. The multi-lists get enabled and disabled as expected, but the checkbox doesn't get ticked.
The result of this problem is that when the form is submitted, the array containing the selected categories is empty; thus, because at least one checked category is a required field in the form, the PHP script that processes the form throws one of my errors which tells me a required field was left blank.
Any ideas on how to make sure that the checkbox actually gets checked, and by extension, POSTS actual data to the processing script?
Thanks guys.
The problem is the use of toggle -- per the documentation:
The implementation also calls .preventDefault() on the event, so links
will not be followed and buttons will not be clicked if .toggle() has
been called on the element.
toggle itself is calling preventDefault, which is stopping the default behavior of the event, checking/unchecking the box.
Rather than toggle, use bind or on (see edit note below) to add a listener for the change event, in which you can examine the state:
$('#sch_cat_hockeyschools').on('change', function () {
if (this.checked) {
// do stuff for a checked box
console.log('check is on');
} else {
// do stuff for an unchecked box
console.log('check is off');
}
});
Try it out at jsFiddle.
EDIT
Please note, this code shows use of the on method, whereas the jsFiddle example uses bind. As pointed out by Sam Sehnert, on is the preferred method for attaching events with > jQuery 1.7. If you are using an older version of jQuery, use bind as in the jsFiddle example.
Documentation
jQuery.toggle
jQuery.bind
jQuery.on
I have a link inside a label. The problem is, when user clicks 'back' after having read the terms, the checkbox is unchecked, because when they clicked on the link they also unchecked the box at the same time, since the link is inside a label.
<input type="checkbox" id="terms" name="terms" checked="checked" />
<label for="terms">I agree to be bound by the Terms</label>
How can I prevent the checkbox from being checked when link is clicked? Tried doing event.preventDefault() on label click, but that doesn't prevent checkbox from being checked/unchecked.
I could just take out the link from inside a label (which means more CSS styling). But now I'm curious whether the above is possible.
You can cancel the click event by routing it through an onclick event.
The "return false;" part will prevent the click event from moving up to the label.
<input type="checkbox" id="terms" name="terms" checked="checked" />
<label for="terms">I agree to be bound by the Terms</label>
Also good practice to allow opening links with target="_blank" in new tabs.
/*
Fix links inside of labels.
*/
$( 'label a[href]' ).click( function ( e ) {
e.preventDefault();
if ( this.getAttribute( 'target' ) === '_blank' ) {
window.open( this.href, '_blank' );
}
else {
window.location = this.href;
}
});
Why not move the link outside the label?
<label for="terms">I agree to be bound by the</label> Terms
Just add the 'for' attibute and it will prevent from unwanting bubbling
You could have the link open up in a new window so that the page doesn't change.
If you don't want to do that you could check to see if the link has been visited and then automatically check the box.
I have a similar situation, but the link actually opens a new window when clicked. This doesn't check/uncheck the box. I believe it is because the click doesn't bubble up through the link to the label.
So, to extend this, if you want the link to open in the same page, you could make it open using a click handler and preventing the click on the link from bubbling, like so:
$('label a').click(function(ev) { ev.preventDefault(); window.location.href = $(this).attr('href'); }
(It's untested and not the nicest use of JS, but it should solve your issue)
I agree the best way (for usability and ease) would be to open the terms in a new window, but if you wish to open it in the same one you can use this little function:
function stopLabel(e) {
e.preventDefault();
window.location= '/terms';
}
You could also put them straight into your onclick but this is a bit nicer imo.
You would have to pass the event to the function too:
<label for="terms">I agree to be bound by the Terms</label>
If you decide to open it in a new window you can just change the window.location to window.open
The link should be outside the label and not a part of it since clicking on it will trigger two action (opening the link and checking the checkbox).
The user is expecting to trigger only one action,
if the link looks like a link he would expect to be taken to the links target,
or if the text is related to the checkbox the user will expect it to check the checkbox.
If you are ok with opening the link in a new tab (and I think it is better, because maybe the user has already filled some data on the page) then this can be handled even without js
<input type="checkbox" id="agreed" />
<label for="agreed">
I agree with Terms of use and Privacy Policy
</label>
here is js fiddle example
http://jsfiddle.net/davo3/zkcv3L3d/