I am trying to create a dropdown menu that will allow users to select multiple options via checkboxes. I am using jQuery so that the user just has to click within the checkbox container (i.e. the checkbox text or the whitespace around the text) to mark the checkbox as checked or unchecked, w/o solely having to click on the checkbox exclusively: http://jsfiddle.net/nMKt2/
<script type="text/javascript">
$(document).ready(function () {
$(".dropdown-menu li").click(function () {
var cb = $(this).find('input:checkbox');
var chk = cb.prop("checked");
if (!chk) {
cb.prop("checked", true);
}
else {
cb.removeProp("checked");
}
});
});
This works for the checkbox container, but it fails when you actually click on the checkbox itself! Actually clicking on the checkbox doesn't seem to trigger the toggle (you may have to open the jsfiddle in IE or Firefox to see this, as my version of Chrome didn't render this jsfiddle properly).
I am very new to jQuery/javascript, and so I'm sure I'm making an elementary mistake somewhere here. Another issue I don't know how to solve would be how to make the dropdown "sticky," so that it doesn't immediately disappear each time you check an option.
Any help you can offer would be greatly appreciated.
Here: http://jsfiddle.net/umidbek_karimov/y84ne/
1: Wrap Your input[checkbox] in to label:
<label><input type="checkbox" value="App1" />App1</label>
2: Use .stopPropagation() method on click event:
$(document).ready(function () {
$(".dropdown-menu li label").click(function (ev) {
ev.stopPropagation();
});
});
3: I also used display: block css property on labels
#advanced_options label {
font-weight:normal !important;
font-family: Tahoma, Geneva, sans-serif;
display:block;
cursor: pointer;
}
The click event on the checkbox is propagating up to the container so technically the checkbox will get checked, then unchecked right away (or vise versa). You need to stop the event propagation on the click event for the checkbox.
$('.dropdown-menu').on('click', 'input[type="checkbox"]', function(e) {
e.stopPropagation();
});
DEMO
$(document).ready(function(){
// Your code here.
$('.dropdown-menu li input:checkbox').on('click', function(e){
e.stopPropagation();
});
});
Your event attached to the <li> also affects all child elements. So what happens is when you click on the checkbox to check/uncheck it, the event attached to the <li> is triggered, causing it to essentially reverse the check/uncheck action.
To remedy this, we add e.stopPropagation(); to the checkbox to prevent it firing any parent click events.
As an alternative, you may want to consider a non-JavaScript solution, wrapping the contents of the list item in a label as shown below. When you click anywhere inside the label, browsers will natively trigger the check/uncheck action of a nested checkbox.
<li>
<label>
<input type="checkbox" value="...">
Checkbox
</label>
</li>
UPDATE:
Since there are other click events (from Bootstrap) that you want to preserve, what you really want to do is just abort out of the current click event when you click directly on the checkbox.
$(document).ready(function () {
$(".dropdown-menu li").on('click', function (e) {
// If you clicked on the checkbox directly, abort.
if ($(e.target).is('input'))
{
return;
}
var chk = $(this).find('input:checkbox').prop("checked");
if (!chk) $(this).find('input:checkbox').prop("checked", true);
else $(this).find('input:checkbox').removeProp("checked");
});
});
Related
I have a toggle event on a div, and I've seen many questions regarding mine but nothing seems to work for what I'm trying to do, it either makes my div disappear in a few seconds, or it just doesn't work. Here's my jsfiddle.
I have a div that needs to toggle when another <div> is clicked. The toggled div has inputs in it that need to be filled out, and a submit button inside it as well. So I need clicks inside the div to be allowed, but only inside my div. So I want the div to show unless the user clicks outside of this div.
I'm using this query which toggles fine:
$('#MyDiv').click(function (event) {
$("#ToggledDiv").slideToggle();
});
And then this coding to hide it when clicked outside of the div which doesn't work:
$(window).click(function () {
$("ToggledDiv").hide();
});
I've tried solutions with e.preventDefault(); but that doesn't work, or $(document).click, even mousedown but it just doesn't flow how I want, it'll hide it within a few seconds, or it will prevent the toggle from even working so I'm lost.
The reason behind this behavior is Event Bubbling and Capturing of HTML DOM API. You can use event.stopPropagation() OR event.cancelBubble = true to prevents the event from bubbling up to the DOM tree, preventing any parent handlers from being notified of the event.
Another good article: events order
$('#MyDiv').click(function(event) {
$("#ToggledDiv").show();
disabledEventPropagation(event);
//console.log('2nd event');
});
$('#ToggledDiv').click(function(event) {
disabledEventPropagation(event);
//console.log('3rd event');
});
$(document).click(function() {
$("#ToggledDiv").hide();
//console.log('1st event');
});
function disabledEventPropagation(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else if (window.event) {
window.event.cancelBubble = true;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="MyDiv" style="background-color:yellow">
click me to open
</div>
<div id="ToggledDiv" style="display: none;background-color:yellow">
<input type="text" />
<input type="submit" />
</div>
Take a look at the event when you click inside the #targetDiv. There are two properties you can use to evaluate what action to perform: event.target and event.currentTarget. In this case:
$('#ToggledDiv').on('click', function(event) {
console.log(event.target, event.currentTarget);
});
This is a good way to see if what clicked is actual target or a child element in the target.
To add to Chris' answer, you can see here that I check that the e.target is not inside the form using vanilla Node.contains, and also not the button...
https://jsfiddle.net/jmLdp45s/3/
var $button = $('button');
var $form = $('form');
$button.click(function() {
$form.slideToggle();
});
$(window).click(function(event) {
if (
!$form.get(0).contains( event.target ) // target is not inside form
&& event.target !== $button.get(0) // target is not button
) $form.hide();
});
I want to toggle a checkbox that is within a td by clicking the td itself (and / or the checkbox).
I have the following code:
$("[id^=musicCheckboxHoldingTD]").on("click", function (e) {
e.stopPropagation();
$this = $(this);
$this.find('.musicSelectionRoundCheckbox:checkbox').click();
});
$(".musicSelectionRoundCheckbox:checkbox").click(function(e) {
e.stopPropagation();
$this = $(this);
musicCheckboxToggled($this); // this function gets called twice
});
When I click only the td this works perfectly.
If I click the checkbox within the td then the function gets called twice due to an event for the td AND an event for the checkbox.
How do I prevent this happening to only have the function run once?
Thanks :-)
Do you really need two events ? From what i see, having just the event on the td without stoping the propagation would allow you to have an handler for your checkbox + td.
$("#musicCheckboxHoldingTD").on("click", function (e) {
musicCheckboxToggled($(this));
});
If your td have other thing that should not be triggering the event, you can tune the selector and prevent propagation.
$("#musicCheckboxHoldingTD, #musicCheckboxHoldingTD > input[type=checkbox]").on("click", function (e) {
e.stopPropagation();
musicCheckboxToggled($(this));
});
I had a lot of trouble with this and it seems that the browser was 'checking' the checkbox and then my jquery event was reversing that.
I ended up disabling the checkbox by putting disabled="disabled" in line with the HTML input element.
Then I used the following jQuery code:
$("[id^=musicCheckboxHoldingDiv]").on("click", function (event) {
event.stopPropagation(); // stop the event bubble up
$this = $(this);
var obj =$this.find('input');
obj.prop('checked', !obj.is(':checked'));
musicCheckboxToggled();
});
This is working at the moment. If anyone can see any issues with this answer then let me know in the comments or improve on it with another answer. I'll leave it a few days and then mark this as the accepted answer otherwise.
Thanks for everyones help :-)
Was styling the checkboxes of my webpage with jquery using the tutorial here
But i realized that I could not do SelectAll checkbox that will select all the checkboxes in my list. It works in the backend (the checkboxes are selected) but it does not show in my page.
Added a demo to show my problem. May need to port to your system to test it out
Demo
what can I add to the jQuery Custom Radio-buttons and Checkbox javascript file in the to achieve the select all checkbox function
Thank you!
You can try this FIDDLE:
$(function () {
var $chbxs = $('.checkbox');
$('#sel_all_lbl').toggle(
function() {
$chbxs.css('background-position', '50% -50px');
$('#checkboxall .truefalse').prop('checked', true);
},
function() {
$chbxs.css('background-position', '50% 0px');
$('#checkboxall .truefalse').prop('checked', false);
}
);
});
What I've done? First, in your fiddle you need to correct some syntax errors, then add a plugin code to the DOM, and you scripts to the script panel, so they will fire when DOM is ready. (This is all about jsFiddle, so you to understand how it works)
About actually your code, you attached click-handlers (.toggle()) to the checkbox element. But click event does not fire on it. Script simply changed the property of the checkbox, but there is no click. So you need to attach these handler to the element wish user actually clicks, that is square icon. (I added an id="sel_all_lbl" to it)
Try to use event handling on the select all checkbox and manually check all the checkboxes from javascript.
Possibly a silly question, but how do I prevent a select element in a form from showing its drop down menu when it's clicked on? I tried the following:
$('select').click (function (e) {
console.log (e);
return false;
});
and
$('select').click (function (e) {
e.preventDefault ();
console.log (e);
});
But neither worked.
What am I doing wrong?
EDIT: The reason I need to know is for a jquery enhanced select element that needs to degrade gracefully. The idea is the select, when clicked, opens a jquery UI dialog with a nicely maked up list that the user makes their selection from (clicking a list item causes the select's value to update). If JS is disabled then the select should just operate as normally.
The problem is that as well as the dialog opening, the dropdown also appears, which is not what I want. I can't just disable the control, as its value needs to be submitted along with the rest of the form.
This should work:-
$('#select').on('mousedown', function(e) {
e.preventDefault();
this.blur();
window.focus();
});
The problem is that you're using the wrong event.
<select onmousedown="(function(e){ e.preventDefault(); })(event, this)">
<option>Some Option</option>
</select>
JsFiddle
From my experience, if i need to disable something, the easiest way to have another invisible element on it (use absolute positioning). When you want to allow default behavior again, you just hide absolute element.
I believe the best solution would be to replace the select element with something else to click on (a button or a link).
BTW, you may want to look into the CSS 3 property appearance, which theoretically allows you to let that replacement element look like a dropdown. Support is however currently very limited:
http://css-infos.net/property/-webkit-appearance
https://developer.mozilla.org/en/CSS/-moz-appearance
You can, the trick is to cancel the mousedown event, not the click. The event chain is made in such a way that click and mouseup cannot occur if mousedown was cancelled:
function cancelDropDown(ev) {
ev.preventDefault();
}
document.getElementById("selectElement").addEventListener("mousedown", cancelDropDown, false);
Hide the select options on page load (if Javascript enabled). They will not display when the select box is clicked, but the text of the first option ("Select an option", or whatever) will still appear in the select field.
$(document).ready(function() {
$('#idOfSelect option').css('display', 'none');
});
Updated Solution:
$(document).ready(function() {
$('#idOfSelect').focusin(function() {
$(this).css('display', 'none');
$('body').click(function(event) {
$(this).unbind(event);
$('#idOfSelect').css('display', 'block');
});
});
});
I just solved this exact problem, by manipulating the 'size' attribute of select. Not very elegant, but worked. Hope its of some help to you.
<!-- Example select dropdown -->
<select id="select" onclick="tackleDropdown()">
</select>
<!-- The JS function -->
<script>
function tackleDropdown(){
document.getElementById('select').setAttribute('size', 0);
// your code for displaying the jQuery UI dialog (is it colorbox???)
// re-enabling the drop down
document.getElementById('select').setAttribute('size', document.getElementById('select').options.length);
}
</script>
Use disabled
$(this).attr("disabled","disabled");
Some good answers here. But still I had to make some additions.
$(document).on('keydown mousedown touchstart', 'select.disabled', function (e) {
e.preventDefault();
})
A simple solution based on CSS is this small fragment:
select:read-only * {
display: none;
}
This will make the options not available when the select is selected. This action mimics the behavior of the "readonly" attribute of the input.
i have an menu with some values and i got someting hidden and while click on more button it shows like google more menu... if it is clicked out it is not hiding till the more menu is clicked once again
More<small>▼</small><div class="more list" id="one" style="display:none">test <span style="color:#329">|</span> test1 <span style="color:#169">|</span> test4</div></div>
Script:
function toggle(one)
{
var o=document.getElementById(one);
o.style.display=(o.style.display=='none')?'block':'none';
}
how to make it close while the mosuse clicks on any other place other than the menus
Try using the onblur event.
I see you've tagged this with jQuery, if that is an option, you can clear up the link a bit, like this:
More<small>▼</small>
And use unobtrusive script combined with event bubbling to your advantage, like this:
$(function() {
$(".more_link").click(function(e) {
$(this).next(".more").toggle();
e.stopPropagation();
});
$(".more").click(function(e) {
e.stopPropagation();
});
$(document).click(function() {
$(".more").hide();
});
});
You can test it out here, this only closes the menu if you clicked neither the menu of the toggle, e.g. clicking one of the test links will not close it. If you want it to, just remove the $(".more").click(function(e) { e.stopPropagation(); }); portion.
It uses event.stopPropagation() to stop the click from bubbling up to document, which if happens (and would if you clicked anything else) triggers its click handler, closing all the .more elements.
I wouldn't use onBlur because it's not a good accessibility approach (for example if the user is using tab to navigate the page).
Look at this solution instead:
jQuery click event for document but ignore a div
Typically, I let the event bubble up to the 'body' or 'html' doc and check if the target is what i want (and/or isn't contained within what i want). If the event target is not contained within your menu, then perform your desired operation (in this case, hide the div).
i.e.
jQuery(document).ready(function(){
jQuery("html").bind("click", function(evt){
var $target = jQuery(evt.target);
var shouldShowMenu = $target.hasClass("menu_toggle");
shouldShowMenu |= $target.parents(".menu_toggle, .more_list").length;
if(!shouldShowMenu)jQuery(".more_list").hide();
});
});
NOTE: your markup would needs to be extended such that the "more" href becomes has a class attribute, class="menu_toggle"