This is something like my code:
<li class="dropdown" id="dropdown1">Dropdown<b class="caret"></b>
<ul class="dropdown-menu">
<li id="li-1">List1</li>
<li id="li-2">List</li>
</ul>
</li>
but when middle click is pressed I want to stop execution of my onclick event.
Something like this disables the onclick whenever the middle button is clicked
$(document).mousedown(function(e) {
if (e.which == 2) {
e.preventDefault();
alert("middle button");
$('a').prop("onclick", null); // disable onclick
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class="dropdown" id="dropdown1">Dropdown<b class="caret"></b>
<ul class="dropdown-menu">
<li id="li-1"><a href="#" onclick='alert("li-1")'>List1</a>
</li>
<li id="li-2"><a href="#" onclick='alert("li-2")'>List</a>
</li>
</ul>
</li>
event.button can have a value of 0,1,2 representing left, middle, and right mouse button respectively. Knowing that, you can take advantage of short circuit evaluation to get the job done.
(event.button !=1 ) && !alert('li-1') Is basically the same as
if(event.button != 1){
return !alert('li-i') // true (just to make sure the event it sent)
return false;
The first li in the snippet will alert() if it wasn't clicked by the middle mouse button, the second li will alert() if it wasn't clicked by the left mouse button.
<li class="dropdown" id="dropdown1">Dropdown<b class="caret"></b>
<ul class="dropdown-menu">
<li id="li-1">List1
</li>
<li id="li-2">List2
</li>
</ul>
</li>
Related
I am trying to create a Bootstrap dropdown menu with two sub-menus. My problem is that the dropdowns are dynamically created after the document is loaded, and don't respond to how I would normally get them to work.
How I would normally go about it would be
$(document).ready(function(){
addItem(); //adds the first instance of the drop down
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
});
But this obviously doesn't work for dynamically created content. I saw elsewhere online that this would work for dynamic content;
//still has first instance of dropdown, just later in the doc
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
but for the life of me, I can't figure out why this doesn't work. What I'm seeing is that it is adding the open class to the sub-menu, but toggle the parent menu(not stopping propagation?) So, my question is, why doesn't the second one execute as expected, and how can I make it?
List structure for reference:
<div class="dropdown open">
<button id="select0" class="btn new-btn" data-toggle="dropdown" aria-expanded="true">Select Your Item <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class="sub" data-toggle="dropdown">Item 1</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="6">Item 1.1</a></li>
<li><a data-def-cost="8">Item 1.2</a></li>
</ul>
</li>
<li><a class="sub" data-toggle="dropdown">Item 2</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="5">Item 2.1</a></li>
<li><a data-def-cost="3">Item 2.2</a></li>
</ul>
</li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 3</a></li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 4</a></li>
<li><a data-plu="xyz" data-def-cost="10.00">Item 5</a></li>
<li class="dropdown-header">Other Items</li>
<li><a data-plu="143">Item 6</a></li>
<li><a data-plu="xyz">Item 7</a></li>
<li><a data-plu="xyz">Item 8</a></li>
</ul>
<input type="text" class="hidden" name="input1">
<input type="text" class="hidden" name="otherinput1">
</div>
$(this).siblings() points to an ul element, however, the .open class is supposed to be added to the parent li : http://getbootstrap.com/javascript/#dropdowns-usage.
Via data attributes or JavaScript, the dropdown plugin toggles hidden content (dropdown menus) by toggling the .open class on the parent list item.
Here is a suggestion (inspired by the following code snippet : Multi-Level Dropdowns) :
$(document).ready(function () {
// this variable keeps track of the last open menus
// in order to close them when another link is clicked
// or when the entire dropdown is closed
var open;
$("#my-dropdown").on("hide.bs.dropdown", function () {
if (open) open.removeClass("open");
});
$(".dropdown-submenu > a").on("click", function (e) {
if (open) open.removeClass("open");
open = $(this).parents(".dropdown-submenu");
open.addClass("open");
e.stopPropagation();
e.preventDefault();
});
});
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div class="dropdown" id="my-dropdown">
<button type="button" data-toggle="dropdown">
Dropdown trigger
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li class="dropdown-submenu">
Submenu 1
<ul class="dropdown-menu">
<li>Action 1.1</li>
<li>Action 1.2</li>
</ul>
</li>
<li class="dropdown-submenu">
Submenu 2
<ul class="dropdown-menu">
<li>Action 2.1</li>
<li>Action 2.2</li>
<li class="dropdown-submenu">
Submenu 2.3
<ul class="dropdown-menu">
<li>Action 2.3.1</li>
<li>Action 2.3.2</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Unsure as to efficiency of my solution, but I rearranged the order a bit, and forced the parent to stay open
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
$(this).siblings().removeClass("open");
$(this).parent().addClass("open");
$(this).parent().parent().parent().addClass("open");
e.stopPropagation();
e.preventDefault();
});
and this solved my issue
use one of these below lines.
$(this).siblings('.dropdown-menu').removeClass('open');
$(this).next('.dropdown-menu').removeClass('open');
So I have a nested bootstrap dropdown in my navbar. Here is the code that prevents the dropdown on click of a nested drop to execute its normal task. This works well.
(function($) {
$(document).ready(function() {
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(event) {
event.preventDefault();
event.stopPropagation();
$(this).parent().siblings().removeClass('open');
$(this).parent().toggleClass('open');
});
});
})(jQuery);
In this code, onclick of the dropdown's <li> does something. When the click is on a normal li of the dropdown it works fine but when it is in a nested dropdown's li the function is executed but when it ends it is executed again (the onClick). The way I've found to avoid that its complete seconde execution is I check in my if statement if $(this) (the clicked li) is null, which it is when it's executed the second time out of nowhere. This way is pretty gross but it works, but does anyone see why the method is called a second time and how to stop it from getting called twice?
$("#dropdownViewModeSelect").on('click', 'li', function() {
selectedViewMode = $(this).attr("viewmode");
if (selectedViewMode != "undefined" && selectedViewMode != null)
{
if (selectedViewMode != previouslySelectedViewMode || currentTimelineMode != previouslySelectedTimelineMode)
{
//Remove glyphicons to all i
var touslesideslis = $("#dropdownViewModeSelect li").find("i").removeClass('glyphicon glyphicon-ok');
//Add glyphicons to clicked i
$(this).find("i").addClass('glyphicon glyphicon-ok');
//Add text to button
currentViewModeSecondary = $(this).attr("viewmodesecondary");
var textBtn;
if (currentViewModeSecondary != "classic")
textBtn = "Ligne du temps - " + $(this).text();
else
textBtn = $(this).text();
$("#dropdownMenuViewMode").text(textBtn);
$("#dropdownMenuViewMode").append('<span class="glyphicon glyphicon-eye-open pull-left"></span>');
$("#dropdownMenuViewMode").append('<span class="caret caret-filter"></span>');
if ($(window).width() >= 768)
Global.Responsiveness();
}
}
});
Here's my HTML for the dropdown.
<li class="dropdown"> <a class="dropdown-toggle" id="dropdownMenuViewMode" data-toggle="dropdown" role="button" aria-expanded="false"><span class="glyphicon glyphicon-eye-open pull-left"></span>Jour<span class="caret"></span></a>
<ul class="dropdown-menu" id="dropdownViewModeSelect" role="menu">
<li viewmode="jour" viewmodesecondary="classic"><a id="linkJour">Jour<i class='dropdownFiltreImage glyphicon glyphicon-ok'></i></a>
</li>
<li viewmode="ressource" viewmodesecondary="classic"><a id="linkRessource">Ressources/Jour<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="week" viewmodesecondary="classic"><a id="linkSemaine">Semaine<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="month" viewmodesecondary="classic"><a id="linkMois">Mois<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="year" viewmodesecondary="classic"><a id="linkAnnee">Année<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="agenda" viewmodesecondary="classic"><a id="linkAgenda">Agenda<i class='dropdownFiltreImage'></i></a>
</li>
<li class="dropdown dropdown-submenu">Ligne du temps
<ul class="dropdown-menu">
<li viewmode="timeline" viewmodesecondary="timeline"><a id="linkTimelineDay">Jour<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="timeline" viewmodesecondary="timeline"><a id="linkTimelineWeek">Semaine<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="timeline" viewmodesecondary="timeline"><a id="linkTimelineMonth">Mois<i class='dropdownFiltreImage'></i></a>
</li>
</ul>
</li>
</ul>
If your click handler is being called twice it is probably being set twice. Try changing your selector. This may not be the ultimate class structure you want but I'll bet if you add the same class to each of your list elements and then use that class in the selector for the click handler your problem goes away.
my dropdown menu is closing when I click/touch the inside links. The dropdown menu is inside a flyout navigation menu. I am using slideToggle. So when you scroll down the page the flyout navigation apears fixed to the top of the page. Inside the flyout nav is a dropdown menu. This is the menu that is closing when links are clicked. The flyMenu, flyNav, flyShop and flyShoplist are the classes involved. How can I stop flyShopList from closing and go to the chosen link?
edit - Im sorry I failed at making my question clear. the main navigation works fine. its the flyout dropdown. so when I click on the flyMenu the flyNav slides out and stays open. then when I click flyShop the flyShopList slides out, then when I try to click the links inside the flyshoplist there is no redirect and the flyshoplist closes. how can I get the links to work and not close the menu?
Here is a jsfiddle http://jsfiddle.net/adod4ycz/6/
Here is the HTML
<div class="menu">Menu</div>
<div class="nav">
<ul>
<li>Home
</li>
<li>About
</li>
<li class="shop"><span>+</span>Shop
<ul class="shopList">
<li>website
</li>
<li>Collection
</li>
<li>Dresses
</li>
<li>Rompers
</li>
<li>Jumpsuits
</li>
<li>Leggings
</li>
</ul>
</li>
<li>On Sale
</li>
<li>Wholesale
</li>
<li>Retailers
</li>
<li>Contact
</li>
</ul>
</div>
<aside>
<div class="flyMenu">Menu</div>
<div class="flyNav">
<ul>
<li>Home
</li>
<li>About
</li>
<li class="flyShop"><span>+</span>Shop
<ul class="flyShopList">
<li>New Arrivals
</li>
<li>Collection
</li>
<li>Dresses
</li>
<li>Rompers
</li>
<li>Jumpsuits
</li>
<li>Leggings
</li>
</ul>
</li>
<li>Wholesale
</li>
<li>Retailers
</li>
<li>Contact
</li>
</ul>
</div>
</aside>
Here is my JS
$(window).scroll(function () {
if ($(this).scrollTop() > 125) {
$('aside').addClass('asideMenu');
} else {
$('aside').removeClass('asideMenu');
}
});
$(document).ready(function () {
//regular nav menu
$('.menu').click(function () {
$('.nav').slideToggle("fast");
});
$('.shop').click(function () {
$('.shopList').slideToggle(30);
$("a span", this).text() == "+" ? $("a span", this).text("-") : $("a span", this).text("+");
});
//flyout nav menu
$('.flyMenu').click(function () {
$('.flyNav').slideToggle("fast");
});
$('.flyShop').click(function () {
$('.flyShopList').slideToggle(30);
$("a span", this).text() == "+" ? $("a span", this).text("-") : $("a span", this).text("+");
return false;
});
});
You need to pass an event to the action and add event.stopPropagation() to prevent the event from bubbling up the DOM and triggering a parent's listener
$('.shop').click(function (event) {
event.stopPropagation();
$('.shopList').slideToggle(30);
$("a span", this).text() == "+" ? $("a span", this).text("-") : $("a span", this).text("+");
});
FIDDLE
See. I have the following html <ul>-<li> lists here.
<ul class="nav">
<li class="active">Home</li>
<li class="dropdown">
About Us<b class="caret"></b>
<ul class="dropdown-menu">
<li>Who we are?</li>
<li>What we stand for?</li>
</ul>
</li>
<li class="dropdown">
Campaigns<b class="caret"></b>
<ul class="dropdown-menu">
<li>Get Involved</li>
</ul>
</li>
<li>News</li>
<li>Donate</li>
</ul>
Then I have the following jquery code
$("#about-us").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#47F514");
});
$("#campaigns").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#F2720A");
});
$("#news").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#0A76F2");
});
$("#donate").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#F7A116");
});
I can see that line $("ul.nav").children("li").children("a").css("background-color", "#0E0E0E") is repeated in many lines. So surely I can take this out and put a new function in each click events to make this same calls this many times.
What should I do to refactor this?
You can do it this way :
var colors_array_by_id = { "about-us" : "#47F514", "campaigns" : "#F2720A", "news" : "#0A76F2", "donate" : "#F7A116" };
$("#about-us, #campaigns, #news, #donate").click(function(){
$("ul.nav > li > a").css("background-color", "#0E0E0E");
$(this).css("background-color", colors_array_by_id[$(this).attr('id')]);
});
The only thing that changes is the color depending of the clicked element. So, I created here an associative array containing id-color couples.
Here's how I would do it -
<ul class="nav">
<li class="active">Home</li>
<li class="dropdown">
About Us<b class="caret"></b>
<ul class="dropdown-menu">
<li>Who we are?</li>
<li>What we stand for?</li>
</ul>
</li>
<li class="dropdown">
Campaigns<b class="caret"></b>
<ul class="dropdown-menu">
<li>Get Involved</li>
</ul>
</li>
<li><a href="#" id="news" class="navLinks" data-bgcolor="#0A76F2" >News</a></li>
<li><a href="#" id="donate" class="navLinks" data-bgcolor="#F7A116" >Donate</a></li>
</ul>
I've added a data attribute to the links called data-bgcolor which has the color value. Next I attach a single click handler to all the links.
$("#about-us, #campaigns, #news, #donate").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color", $(this).attr("data-bgcolor"));
});
You could do this,
In css,
.myClass{ background-color: #OEOEOE;}
on load,
var elm = $("ul.nav").children("li").children("a");
and then,
$("#about-us, #campaigns, #news, #donate").click(function(){
$this = $(this);
elm.addClass("myClass");
$this.css("background-color", $this.data("bgcolor"));
});
You can use the .data() instead of .attr().
<li class="list ">A
<ul class="names">
<li class="list">1
</li>
<li class="list">2
</li>
</ul>
</li>
<li class="list ">B
<ul class="names selected">
<li class="list selected">1
</li>
<li class="list">2
</li>
<li class="list">3
</li>
<li class="list">4
</li>
</ul>
</li>
<li class="list ">C
<ul class="names">
<li class="list">1
</li>
<li class="list">2
</li>
<li class="list">3
</li>
<li class="list">4
</li>
</ul>
</li>
$('.list').click(function () {
var that = this;
$('.list').each(function () {
if (that == this) return true; //continue
$('.names:not(:hidden)', this).slideToggle();
});
$('ul.names', this).slideToggle();
})
ul.names{display: none;}
li.list{
width:150px;
background:#A9FF7A;
}
ul.names {
width:150px;
background:#A9FF7A;
}
ul.selected{
display: block;
}
li.selected{
background:red;
}
online Sample: http://jsfiddle.net/gyYyd/
B's submenu 1 is highlighted. If I click on menu A or C, then A or C section will be opened, but how do I click PAGE BLANK area (outside of the background color) to go back to B section (to open B section)
Thanks in advance
You can capture clicks on the document object and trigger a click on the required list item.
$(document).click(function() {
var selected = $('.selected:first');
if(!selected.closest('ul.names').is(':visible')) {
selected.closest('.list').trigger('click');
}
});
Also, make sure to return false from your current list item click handler - so that normal clicks on list items don't propagate to the above handler.
DEMO: http://jsfiddle.net/gyYyd/2/