I'm struggling to select in the DOM the anchor link that is a direct child of my list item "dropdown-nav. It should change the link when the list item is clicked but doesn't. The active class applies perfectly. What am I doing wrong here?
var acc = document.getElementsByClassName("dropdown-nav");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active-hit");
this.find("a").attr("href", "http://www.google.com/");
});
}
<ul>
<li class="dropdown-nav">
<a href="/about">About
<span class="nav-desc">Our company</span>
</a>
<div class="hide-border"></div>
<ul class="second-tier">
<div class="hide-corner"></div>
<li>Our Mission</li>
<li>Our People</li>
<li>Work with us</li>
<li>High Value Manufacturing</li>
</ul>
</li>
</ul>
You included jQuery so you may update your code to simply use jQuery like this:
$(".dropdown-nav").click(function() {
$(this).toggleClass('active-hit');
$(this).find('a').attr("href", "http://www.google.com/");
})
.active-hit {
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="dropdown-nav">
<a href="/about">About
<span class="nav-desc">Our company</span>
</a>
<div class="hide-border"></div>
<ul class="second-tier">
<div class="hide-corner"></div>
<li>Our Mission</li>
<li>Our People</li>
<li>Work with us</li>
<li>High Value Manufacturing</li>
</ul>
</li>
</ul>
this is not jQuery object. Replace this line:
this.find("a").attr("href", "http://www.google.com/");
With this (this will change href of first link, if you need to change all of them, then iterate):
this.getElementsByTagName('a')[0].setAttribute('href', 'http://www.google.com/');
If you have included jQuery, you can do this too:
$(this).find("a").attr("href", "http://www.google.com/");
Related
I need to append an <li> element to multiple <ul> using a for-loop in jQuery.
Code Snippet:
JQuery:
var lists = $('ul.menu');
for(var i=0; i<lists.length; i++){
var lnk = "<li>All</li>";
lnk = $('<div />').html(lnk).text();
lists[i].prepend(lnk);
}
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Graphics</li>
<li>Videos</li>
<li>Programming</li>
</ul>
<hr>
<ul class="menu">
<li>Our Story</li>
<li>About Us</li>
</ul>
As per code <li> inserts as the proper text, but is been formatted as plain text instead of an <li>.
What am I doing wrong? How to correct my mistakes?
You're calling the raw DOM prepend (which only exists on modern browsers), because lists[i] accesses the raw ul element. You're also just taking the text of what you want to prepend, rather than including any li markup. You probably want to:
Call jQuery's prepend, and
Include the li in what you're prepending
Example:
var lists = $('ul.menu');
for(var i=0; i<lists.length; i++){
var lnk = "<li>All</li>";
lists.eq(i).prepend(lnk);
}
/* No CSS */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Graphics</li>
<li>Videos</li>
<li>Programming</li>
</ul>
<hr>
<ul class="menu">
<li>Our Story</li>
<li>About Us</li>
</ul>
A slightly more jQuery-ish alternative to TJ Crowder's solution...
$('ul.menu').each(function() {
$(this).prepend("<li>All</li>");
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Graphics</li>
<li>Videos</li>
<li>Programming</li>
</ul>
<hr>
<ul class="menu">
<li>Our Story</li>
<li>About Us</li>
</ul>
I am trying to make a collapsible list that changes from a '+' to a '-' and back depending upon whether the list is collapsed or expanded. I can get to the text using this statement:
$(this).children().eq(i).children('span')[0].firstChild.outerText;
But I cannot figure out how to change the value. There's probably a more elegant solution that a JQuery Guru can show me. Here is my JSFiddle.
This answer is the closest answer I could find to my question but I don't know how to implement it or even if there is a better way.
This can be simplified quite a bit. Rather than trying to match index, just use jQuery's find() method to target descendants:
$('#test > li').click(function() {
var $symbol = $(this).find('.symbol');
$(this).find('ul').slideToggle('fast');
if ($symbol.text() === ' +') {
$symbol.text(' -');
} else {
$symbol.text(' +');
}
});
.hideUnorderedList {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="test">
<li id="first">
<span class="Collapsable"><span class="symbol"> +</span>First One</span>
<ul id="myfirstlist" class="hideUnorderedList">
<li>Something to do</li>
<li>Something else to do</li>
</ul>
</li>
<li id="second">
<span class="Collapsable"><span class="symbol"> +</span>Second One</span>
<ul id="mysecondlist" class="hideUnorderedList">
<li>Second thing to do</li>
<li>Second other thing to do</li>
</ul>
</li>
</ul>
</div>
// Make your code clean and readable!
// Don't target #test. Go directly for your "title/heading" elements ("buttons")
$(".Collapsable").on("click", function() {
// Who is my +/- icon element?
var $ico = $(this).find(".symbol");
// Traverse up to LI and than back down to find my UL sub list:
var $subList = $(this).closest("li").find("> ul");
// Realize the current collapsed/expanded state
var isSubListHidden = $subList.is(":hidden");
// OK, time to rock!
// Change teh text +/-
$ico.text(isSubListHidden ? "-" : "+");
// Toggle sub lists:
$subList.stop().slideToggle();
});
.hideUnorderedList {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="test">
<li id="first">
<span class="Collapsable"><span class="symbol">+</span>First One</span>
<ul id="myfirstlist" class="hideUnorderedList">
<li>Something to do</li>
<li>Something else to do</li>
</ul>
</li>
<li id="second">
<span class="Collapsable"><span class="symbol">+</span>Second One</span>
<ul id="mysecondlist" class="hideUnorderedList">
<li>Second thing to do</li>
<li>Second other thing to do</li>
</ul>
</li>
</ul>
</div>
I am working in ASPX, but this is just a straight JQuery call. I have a List item with one child list item inside. I am passing "this" to a function when a List Item is clicked. I am trying to get the child list to not expand when the parent is clicked. Any help would be appreciated. Thanks.
<ul>
<li id="Menu1" class="collapsed">Faculty Resources
<ul id="Faculty_Res">
<li>Archived Courses</li>
<li>College List</li>
<li>Current Courses</li>
<li>Curriculum Outcomes</li>
<li>EM Accreditation Information</li>
<li>EM Competencies and Curricula</li>
<li>EM Job Market Data</li>
<li>Faculty Positions</li>
<li id="Menu2" class="collapsed">Program Start Up Resources
<ul id="Faculty_Res_Prog_Startup">
<li>Needs Assessment</li>
<li>Proposal Examples</li>
</ul>
</li>
<li>Q&A</li>
<li>Research</li>
<li>Syllabi Examples</li>
<li>Synergy Focus Group</li>
<li>Synergy Webinar Slides</li>
<li>Textbooks</li>
<li>Webinars</li>
</ul>
</li>
</ul>
The "collapsed" class has a display: none;
Here is the JS using JQuery:
function expandNavigation(itemClicked) {
$(itemClicked).next().toggle(1);
itemClicked.stopPropagation();
var parentItem = $(itemClicked).parent();
if (parentItem.hasClass("expanded")) {
parentItem.removeClass("expanded").addClass("collapsed");
}
else if (parentItem.hasClass("collapsed")) {
parentItem.removeClass("collapsed").addClass("expanded");
}
}
Here is the CSS:
`ul li.collapsed ul {
display: none;
padding-left:20px;
}`
The issue with your code is that you need to call stopPropragation() on the event that's raised, not the element which created the event.
Also note that you should use unobtrusive JS code to attach your event handlers. As you're using jQuery here's how to do that, along with how to shorten your logic using toggleClass().
$('.collapsed a').click(function(e) {
e.preventDefault();
$(this).next().toggle().parent().toggleClass('expanded collapsed');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="Menu1" class="collapsed">
Faculty Resources
<ul id="Faculty_Res">
<li>Archived Courses</li>
<li>College List</li>
<li>Current Courses</li>
<li>Curriculum Outcomes</li>
<li>EM Accreditation Information</li>
<li>EM Competencies and Curricula</li>
<li>EM Job Market Data</li>
<li>Faculty Positions</li>
<li id="Menu2" class="collapsed">
Program Start Up Resources
<ul id="Faculty_Res_Prog_Startup">
<li>Needs Assessment</li>
<li>Proposal Examples</li>
</ul>
</li>
<li>Q&A</li>
<li>Research</li>
<li>Syllabi Examples</li>
<li>Synergy Focus Group</li>
<li>Synergy Webinar Slides</li>
<li>Textbooks</li>
<li>Webinars</li>
</ul>
</li>
</ul>
One problem with your code is that you are using both $.toggle and setting/unsetting a class to hide these elements yourself.
One option would be to use only the class approach, and to do so by using $.toggleClass rather than your own custom code:
function expandNavigation(target) {
$(target).parent().toggleClass('collapsed');
}
ul li.collapsed ul {
display: none;
padding-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="Menu1" class="collapsed">Faculty Resources
<ul id="Faculty_Res">
<li>Archived Courses</li>
<li>College List</li>
<li>Current Courses</li>
<li>Curriculum Outcomes</li>
<li>EM Accreditation Information</li>
<li>EM Competencies and Curricula</li>
<li>EM Job Market Data</li>
<li>Faculty Positions</li>
<li id="Menu2" class="collapsed">Program Start Up Resources
<ul id="Faculty_Res_Prog_Startup">
<li>Needs Assessment</li>
<li>Proposal Examples</li>
</ul>
</li>
<li>Q&A</li>
<li>Research</li>
<li>Syllabi Examples</li>
<li>Synergy Focus Group</li>
<li>Synergy Webinar Slides</li>
<li>Textbooks</li>
<li>Webinars</li>
</ul>
</li>
</ul>
Seems like your are not calling stopPropagation on the event, but on the element. By passing the event, you can call stopPropagation on it.
Remove the onclick from the a element, add the class toggle-control so it looks like:
your text
And bind to the click event using jQuery:
$('.toggle-control').on('click', function (event) {
var itemClicked = this;
$(itemClicked).next().toggle(1);
event.stopPropagation();
event.preventDefault();
var parentItem = $(itemClicked).parent();
if (parentItem.hasClass("expanded")) {
parentItem.removeClass("expanded").addClass("collapsed");
}
else if (parentItem.hasClass("collapsed")) {
parentItem.removeClass("collapsed").addClass("expanded");
}
});
Trying to make javascript horizontal menu, but can't get second button to open its own items, (when i click the second button it opens the items that are for the first button) here is current code:
JavaScript:
$(document).ready(function() {
$(".menu-button,.menu-button1").click(function() {
$(".menu-bar").toggleClass("open");
});
})
HTML:
<ul class="menu">
<li title="home">menu</li>
<li title="pencil">pencil</li>
<li title="about">about</li>
</ul>
<ul class="menu-bar">
<li>Menu0</li>
<li>Home2000</li>
<li>About</li>
<li>Parent</li>
<li>About</li>
</ul>
<ul class="menu-bar">
<li>Menu1</li>
<li>About</li>
</ul>
Before I start my answer, let me explain jQuery a bit.
$(".menu-button,.menu-button1").click(function() {
$(".menu-bar").toggleClass("open");
});
This broken down:
$(".menu-button,.menu-button1").click(function() { -> When any item with class menu-button OR class menu-button1 is clicked
$(".menu-bar").toggleClass("open"); ->Toggle the "open" class for all elements in your page with class menu-bar.
Since you call all the menus instead of the specific one you want, it opens both of them.
So, be more specific by - for starters - using IDs, or unique/identifying classes:
JS:
$(document).ready(function() {
$(".menu-button.home").click(function() {
$(".menu-bar.home").toggleClass("open");
});
$(".menu-button.pencil").click(function() {
$(".menu-bar.pencil").toggleClass("open");
});
})
HTML:
<ul class="menu">
<li title="home">menu</li>
<li title="pencil">pencil</li>
<li title="about">about</li>
</ul>
<ul class="menu-bar home">
<li>Menu0</li>
<li>Home2000</li>
<li>About</li>
<li>Parent</li>
<li>About</li>
</ul>
<ul class="menu-bar pencil">
<li>Menu1</li>
<li>About</li>
</ul>
I agree with M.Doye's comment about using .each (but sorry, I can't answer directly).
I want to add that, it will be much easier with that kind of HTML structure I think:
<ul class="menu">
<li title="home">
Show Menu 1
<ul class="menu-bar">
<li>Menu1
</li>
</ul>
</li>
<li title="pencil">
Show Menu 2
<ul class="menu-bar">
<li>Menu2
</li>
</ul>
</li>
</ul>
The, click on the link and use .next() or .siblings or closest... to show the right ul.
But of course you'll have to rewrite you CSS :)
Here is updated code
$(document).ready(function () {
$(".menu-button,.menu-button1").click(function () {
$(this).siblings(".menu-bar").toggleClass("open");
})
})
<ul class="menu">
<li title="home">menu
<ul class="menu-bar">
<li>Menu1</li>
<li>About</li>
</ul>
</li>
<li title="pencil">pencil
<ul class="menu-bar">
<li>Menu0</li>
<li>Home2000</li>
<li>About</li>
<li>Parent</li>
<li>About</li>
</ul>
</li>
</ul>
here is a jsfiddle
Basically i want to click on a tab and a drop down menu appears then when you re-click the same tab or any of the others I want it to hide that tab/show the other tab if clicked on the same/other tab.
I tried
$('.click').click(function() {
$(this).find('.sub-nav-list').toggleClass('active');
});
and tried
$('.click').click(function() {
$('.sub-nav-list').removeClass('active');
$(this).find('.sub-nav-list').toggleClass('active');
});
but cant work it out! any insight? Thanks
html:
<nav class="secondary-nav">
<ul class="list clearfix">
<li class="leaders click">Leadership <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Management</li>
<li>Board of Directors</li>
</ul>
</li>
<li class="contact click">Contact Info <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Email Notification</li>
<li>Information Request</li>
</ul>
</li>
<li class="docs click">Documents <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Governance Documents</li>
<li>Press Release</li>
<li>Reports & Presentations</li>
<li>Sec Filings</li>
<li>Frenquently Asked Questions</li>
<li>Tax Information</li>
</ul>
</li>
<li class="research click">Research <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Dividends and Distributions</li>
<li>Stock Information</li>
<li>Analyst Coverage</li>
<li>Market Makers</li>
</ul>
</li>
</ul>
</nav>
I can see at least two possible issues there.
1) sub-nav-list is not a children of click element. If they are on the same level something like that might work:
$('.click').click(function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});
2) You have these elements generated dynamically - so you need use on with selector of any parent element that exists before you dynamically generate your sub-menus (let say nav-list):
$(".click").on("click", ".nav-list", function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});