JQuery selector to negate specific HTML elements within a parent element - javascript

I have HTML label structures generated by a JQuery multiselect dropdown library as shown:
<label for="ui-multiselect-selectedSku-option-1"><input id="ui-multiselect-dropdown-option-1" type="radio" value="DropDownVal1"><span>DropDownText1</span></label>
<label for="ui-multiselect-selectedSku-option-2"><input id="ui-multiselect-dropdown-option-2" type="radio" value="DropDownVal2"><span>DropDownText2</span></label>
My requirement is: except the input element, whenever the user clicks on anywhere else in the
<label></label>
(including the label) area,I need to do event.preventDefault(). I have tried as
$(document).on('click', 'label[for^="ui-multiselect-selectedSku-option-"]',function(event){
event.preventDefault();
});
But the above handler gets triggered even when I click on the <input> within the label as well(which is obvious and I know that!)
How do I write a JQuery selector for to filter this.

The best thing would be to have the input out of the label... But:
I do not have control over this markup structure... (your comment on another answer)
You can use .stopImmediatePropagation() on the <input> elements... So the click event won't bubble up to the label.
See below... Try a click a label, then on a radio.
$(document).on('click', 'label[for^="ui-multiselect-selectedSku-option-"]',function(event){
console.log("Clicked on a label");
event.preventDefault(); // Don't know if that is useful...
});
$(document).on('click', 'label[for^="ui-multiselect-selectedSku-option-"] input',function(event){
console.log("Clicked on a radio input");
event.stopImmediatePropagation();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="ui-multiselect-selectedSku-option-1"><input id="ui-multiselect-dropdown-option-1" type="radio" value="DropDownVal1"><span>DropDownText1</span></label>
<label for="ui-multiselect-selectedSku-option-2"><input id="ui-multiselect-dropdown-option-2" type="radio" value="DropDownVal2"><span>DropDownText2</span></label>

The first problem is your label. You generally should either have your input inside the label OR use the for attribute. Your for attributes are for different controls than the ones inside the labels. I am not sure how browsers will handle this.
If you don't want clicks on the label to trigger an input, don't associate them at all. Consider not using a label at all, use a span instead.
If there is a condition that turns on/off whether the label affects a control, you can use code to set/clear the label's for attribute.

Related

set checkbox and span in the same line and add a clickevent to the span

I am kind of embarrassed that I can't find a solution to this simple task.
It is easy to make a checkbox and a span-tag in the same line, which what I have done liek this:
<label class='checkbox' for='visible_1'>
<input id='visible_1' class='visible' type='checkbox'>
<span>Layer_1</span>
</label>
I set a function to the checkbox, which show/hide the layer_1 and works pretty good.
I also set a event with jQuery to the span-tag, which show some text in the website, but then I got a problem, I can't "touch" the text of span, the checkbox kinda of blocks the text, no matter where I click, as long as I click in the line, which checkbox and span are in, I can only select the checkbox.
It seems like the checkbox takes the whole line and the click event on span-tag is blocked by checkbox.
I don't know how it can be done, cause I don't want the checkbox to take a line and the span-tag another, it's even worse.
One inherent behavior of the label element is to act as a touch target for its associated field:
When a <label> is clicked or tapped, and it is associated with a form control, the resulting click event is also raised for the associated control. -- MDN Element docs
However, the default display attribute of a label element is "inline", which means they will normally appear on the same line as other "inline" elements, like inputs:
<input id='visible_1' class='visible' type='checkbox'>
<label for="visible_1">Layer_1</label>
It may be that your site has some style overrides to make label a block element, which would make sense if your normal use case is to wrap elements and their captions in a label element; it's common to want these controls on separate lines. If that's the case, then you can use CSS to restore the default behavior--something like:
.my-inline-label-section label {
display: inline;
}

Text input inside radio button group loses focus in Firefox when clicked

I'm having a problem in Firefox where if you click the <input type="text"> in Firefox, the focus is diverted immediately to the Radio button sibling.
The behavior works as intended in Chrome. Do I need extra Javascript to fix this up?
Here's the JsFiddle
Seems like Firefox is actually doing the correct thing according to the W3C:
If the for attribute is not specified, but the label element has a
labelable element descendant, then the first such descendant in tree
order is the label element's labeled control.
Your label is wrapping two input elements, so when you click in the text box, the radio (the first such descendant in tree order) receives focus.
Results will vary depending on how the browser has implement this rule, so to ensure cross-browser results yes, you'd need JavaScript to step in.
From MDN:
Permitted content: Phrasing content, but no descendant label elements.
No labelable elements other than the labeled control are allowed.
Basically, putting two inputs within a label is not valid markup. Change your html markup so that the label only wraps the radio input (and any text label)...
<label class="radio">
<input type="radio" name="requestfor" id="optionsRadios2" value="someoneelse" />
Behalf of
</label>
<input type="text" name="behalfof" id="behalfid"/>
...and then use javascript (or in my lazy case, jQuery) to select the radio:
$('#behalfid').click(function(){
$('#optionsRadios2').trigger('click');
});
Here's the fiddle.
Did some digging around and found this jsFiddle with a jQuery solution.
Firing trigger.click();on radio input will select it when clicking on the textbox.

Bind JavaScript jQuery click event on label AND on checkbox simultaneously

I'm using labels for my form, like this :
<label for="foo" id="bar">Label</label>
<input type="checkbox" id="foo" />
I want to hide an element when the user uncheck the box, and show it otherwise.
The problem is, if I bind the click event to "foo", it'll only works when the user clicks on the checkbox itself and not on the label. Therefore, do I also need to bind a click event on the label ? Or should I enclose both elements within a span ?
My HTML already contains 2344 elements, so I'd like to do it without adding anything, and without doubling the JavaScript code or the selector, if possible.
Instead of binding with the click() event, you should bind using the change() event, then however this change is triggered the outcome will be the same:
$('#foo').change(
function(){
// do whatever
});
References:
change().
The change event should fire for the input whether the label or input is clicked:
$("#foo").change(function () { ... });
Example http://jsfiddle.net/andrewwhitaker/6LMXW/

Toggle classes with radio button in jQuery

I have a set of radio buttons where when I click a radio button, I want the label to change color or whatever. But when I click another radio button, the color goes away. Therefore I have something like this:
jQuery('label').mouseup(function(){
jQuery(this).prev().attr('checked', 'checked');
jQuery('input').next().removeClass('selected');
jQuery('input:checked').next().addClass('selected');
});
if you need to see some html:
<input type="radio" id="radio1" name="myRadio" value="option-1" />
<label for="radio1">Label 1</label>
<input type="radio" id="radio2" name="myRadio" value="option-2" />
<label for="radio2">Label 2</label>
This first removes 'selected' class from all the labels and then re-applies to only the checked labels.
It works and is simple, but I was thinking this might not be the most efficient way of doing this. I imagine that javascript is iterating through each input element and using more resources than necessary.
I'm curious if anyone knows of a common way of doing this more efficiently. I seem to be doing this type of thing quite often in my jQuery code. I've just been using jQuery for the past 3 months or so btw.
There are a few things I think are worth mentioning.
Clicking on a <label> will automatically change the value of the <input>. You don't need to set the checked attr manually, and therefore could bind to the change event on the radios instead. This will also allow keyboard events to select/deselect the radios, and will work anytime the radio values change, not just when someone raises their mouse over a label.
Also, you can save the whole collection of radio inputs in its own variable to make referencing them later not have to search through the DOM again.
Suggested code (w/ jsfiddle preview)
var $radios = jQuery('input[type=radio]');
$radios.change(function() {
$radios.next().removeClass('selected');
$radios.filter(':checked').next().addClass('selected');
});
Besides the use of mouseup who seems a little bit unusual in this case (at least, to me), your code is fine.
I'd use click or change.
It actually looks like it works when clicking the label. I wouldn't worry too much about the number of DOM elements searched as long as the performance is ok. Optimize when it becomes a problem and not before. Clarity/readability is probably more important. You might be able to improve it, though, by using some information from the label or its related input to narrow down the selectors. Using end and filter would also allow you to reuse the second query.
$('label').click(function(){
var radio = $(this).prev();
radio.attr('checked', 'checked');
var name = radio.attr('name');
$('input[name=' + name ']').next()
.removeClass('selected')
.end()
.filter(':checked')
.next()
.addClass('selected');
});
Note that using change on the actual radios, as some others suggest might be better. You could use the same techniques with that.
$('input[type=radio]').change( function() {
$('input[type=radio]').next()
.removeClass('selected')
.end()
.filter(':checked')
.next()
.addClass('selected');
});
Use live handlers if you are adding radios dynamically to the page.

How do i make a checkbox fire a function?

I have a checkbox inside a <label> and i want that checkbox, when checked or unchecked, to trigger a function.
I attached a onchange trigger to the checkbox but in IE6 the trigger only fires after the focus is turned away from the checkbox, while in FF3 and Chrome it fires right away.
I removed the onchange trigger and attached a onclick trigger to the <label> but now the trigger fires twice when the label is clicked once (does enyone know why?)...
My question is: how can i make the checkbox fire a function when it is checked or unchecked by a click on it or on it's label.
Thanks.
Assuming you don't want a fancy ASP / JQuery solution, just attaching the function to the onClick of the checkbox itself should work fine.
(Of course, you'll need to inspect the current state of the checkbox in the function if you want to have the function behave differently based on if the checkbox is checked or not.)
As "Electrons_Ahoy" says, you should be able to simply attach an onclick handler to the checkbox element. This handler should also get called when the user clicks on the label instead of the checkbox.
HTML:
<label><input type="checkbox" id="myCheckbox" />My Checkbox</label>
JavaScript:
document.getElementById("myCheckbox").onclick = function() {
if (this.checked) {
alert("Checkbox was checked.");
}
else {
alert("Checkbox wasn't checked.");
}
};
The above code seems to work correctly in Safari 4 and Firefox 3 (I'm not sure how it would work in IE).
Steve
not sure if using Prototype is an option for you, but if so you'd do it this way (this assumes Prototype 1.6. Code written against earlier versions will be slightly different):
HTML:
<label><input type="checkbox" id="myCheckbox" />My Checkbox</label>
JS:
$('myCheckbox').observe('click', function(cbox)
{
var cbox = $('myCheckbox');
//do work in here.
//cbox is the DOM element that represents your checkbox
}
);
Doing it this way is slightly nicer than the "naked" JS approach (in my opinion), and it's a bit safer too.
Thank you for all your responses.
#Electrons_Ahoy and #Steve: You are tight. My problem was that i was putting the checkbox inside the labe, so i did the folowing:
I took the checkbox outside the label, put the onclick trigger on the checkbox only and it works fine.
I also figured out why the trgger fired twice when the checkbox was inside the label and the onclick trigger was on the label :
It was because when i clicked the label a click on the checkbox was simulated and the checkbox being inside the label the click was simulated on the label, duuuuuhhh :)
You probably need to turn on the autopostback property:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.checkbox.autopostback.aspx
<asp:CheckBox id="checkbox1" runat="server"
AutoPostBack="True"
Text="Include 8.6% sales tax"
TextAlign="Right"
OnCheckedChanged="Check_Clicked"/>

Categories