I'm having trouble figuring out a bug in my accordion. The arrow icons are misbehaving when clicked on. If you go here, you will see some categories hidden by accordions. When you click on one and then close it, it behaves properly. But if you click on one, then click on another below before closing the first one, you'll notice that the arrow for the one above has returned to its "closed" position without closing it.
Here is the HTML that makes up each accordion:
<dl class="accordion">
<dt><strong>Accordion Title:</strong> Details</dt>
<dd>Hidden details</dd>
</dl>
The CSS for the arrows:
.accordion dt:after {
content: "\f125";
color: #ED4F30;
font-family: "Ionicons";
padding-left: 10px;
}
and
.accordion dt.accordion-active:after {
content: "\f123";
color: #ED4F30;
font-family: "Ionicons";
padding-left: 10px;
}
And finally the jQuery that I'm using to expand/collapse:
function ($) {
//Hide all panels
var allPanels = $('.accordion > dd').hide();
//Show first panel
//$('.accordion > dd:first-of-type').show();
//Add active class to first panel
//$('.accordion > dt:first-of-type').addClass('accordion-active');
//Handle click function
jQuery('.accordion > dt').on('click', function () {
var $this = $(this) ,
$target = $this.next();
jQuery('.accordion > dt.accordion-active').not($this.toggleClass('accordion-active')).removeClass('accordion-active');
$this.siblings('dd').not($target.addClass('active').slideToggle()).slideUp();
return false;
});
}
Any ideas what I'm missing?
It looks like you are overcomplicating things a little. You don't need to use the "not()" method to filter anything out. You are only toggling between 2 states (add/remove class, show/hide element) so you only need to use 2 jQuery methods, which were already in your code.
jQuery('.accordion > dt').on('click', function () {
var $this = $(this),
$target = $this.next();
$this.toggleClass('accordion-active');
$target.slideToggle();
return false;
});
Here's a JSFiddle based on the code you provided: http://jsfiddle.net/e5pe5/
Let me know if this is the intended functionality of your accordion.
Related
I'm trying to navigate through an unordered list and having trouble making it work fully.
There are 4 buttons - Up, Down, Left, and Right. Navigating with Up or Down will correctly take you to the previous or next <li> (vertically) on that level, if one exists. Navigating Right will take you to the first list item inside the (down a level) in that <ul>, if an <ul> exists.
The left button should basically reverse that order (go up a level), but it doesn't.
Here is my code:
CSS
<style>
.btn { margin: 10px; padding: 10px; background-color: #999; cursor: pointer; display: inline-block; }
.current > span { color: red; font-weight: bold; }
</style>
HTML
<div class="left btn">Left</div>
<div class="right btn">Right</div>
<div class="up btn">Up</div>
<div class="down btn">Down</div>
<ul id="demo01">
<li class="current"><span>one</span></li>
<li><span>two</span></li>
<li><span>three</span>
<ul>
<li><span>four</span></li>
<li><span>five</span></li>
<li><span>six</span>
<ul>
<li><span>seven</span></li>
<li><span>eight</span></li>
</ul>
</li>
</ul>
</li>
<li><span>nine</span></li>
</ul>
JS / JQuery
<script>
(function($) {
$(document).on('click','.right', function() {
var current = $('#demo01 li.current');
if(current.has("ul").length){
right = current.find('li').first();
current.removeClass('current');
right.addClass('current');
}
});
$(document).on('click','.left', function() {
var current = $('#demo01 li.current');
if( current.parent.has('ul').length) {
left = current.parent('ul li');
current.removeClass('current');
left.addClass('current');
}
});
$(document).on('click','.up', function() {
var current = $('#demo01 li.current');
if( current.prev('li').length) {
up = current.prev('li');
current.removeClass('current');
up.addClass('current');
}
});
$(document).on('click','.down', function() {
var current = $('#demo01 li.current');
if( current.next('li').length) {
down = current.next('li');
current.removeClass('current');
down.addClass('current');
}
});
}(jQuery));
</script>
Current level of functionality:
Using the Up and Right buttons, you can succesfully navigate to "eight". The expectation is that when you click the Left button, to go back to the top, you'd go to "six" (not "four"), then "three" (not "one"). Right now, I'm getting nothing.
I thought using parent() jQuery function would be the way to go, but I must be writing it incorrectly.
I suppose each time I click through, I could add/remove a class ("last-visit"), and when "returning" do a find on that. I'd like to first know what I'm doing wrong with the code I've written.
If someone could point me in the right direction, I'd appreciate it.
You need to change:
if( current.parent.has('ul').length) {
to:
if( current.parent().has('ul').length) {
parent is not a property of the current object. It is the function parent().
You also need to change this line:
left = current.parent('ul li');
to:
left = current.parents('li');
left = current.parent('ul').parent('li'); // params are optional
Your above is selecting a direct (one-level up) ancestor ul and its interior li (which is the current current element). Then, it makes it not current. Therefore, this does not work.
The modified line looks for any ancestors (can be more than one level up) goes up two levels to get to the correct <li> element.
See a working example at JSFiddle.net.
EDIT See the comment below. This is more correct now.
Try this. You need to navigate to the li which parent to ul for 4,5,6 spans
$(document).on('click','.left', function() {
var current = $('#demo01 li.current');
if(current.parent().parent().closest("li").length)
{
left = current.parent().parent().closest("li");
current.removeClass('current');
left.addClass('current');
}
});
http://jsfiddle.net/go0yjoae/1/
I have used jQuery to generate a sequential numbering for my menu items.
When clicked, the hyperlink text becomes red.
However, the problem here is that I want the respective number to turn into red as well when the hyperlink is clicked (active).
Such as when 'WHY YOU NEED IT' is clicked, the text turns red perfectly. But I need the number 1's background color to change into red as well.
I tried replacing classes but it didn't work.
This is the JS.
jQuery(function ($) {
$(".menu-solutions-menus-container ul li").each(function (i, el) { $(this).children('a').prepend("<number>" + (i + 1.) + "</number>");
});
$('.local-scroll').click(function (event) {
event.preventDefault();
var full_url = this.href;
var parts = full_url.split('#');
var trgt = parts[1];
var target_offset = $('#' + trgt).offset();
var target_top = target_offset.top;
$('html, body').animate({
scrollTop: target_top
}, 500);
});
$('.menu-solutions-menus-container a').click(function () {
$('.menu-solutions-menus-container a').removeClass('active');
$(this).addClass('active');
});
$('.number').click(function () {
$('.number').removeClass('active');
$(this).addClass('active');
});
Here's the jsfiddle workspace. (Change jQuery version to jQuery 1.7.2 or above if you don't see the numbers.)
The secondary menu in this site is where I would really want to implement it.
Thanks a lot in advance.
Your class names just need a tweek and this'll work fine
change
number.active {
background: white;
}
To
.active number {
background: red;
}
Edit (explanation)
The CSS selector number.active is looking for an html element number that has a class of active like this <number class="active" /> but what your HTML shows is that you wanted the parent <a> to have the active with a child node of <number>.
So to do that you put the parent class first, followed by a space to note a child node of the parent, followed by the element you want to target.
so:
parentElement.parentClass childElement.childClass {
defs
}
you could write
a.active number {
background: red
}
Edit 2 for top bars:
There's a few things, the first being that the grey areas are actually background colors, as opposed to borders. Second the CSS selector is looking for a parent class of "active" but your "active" is a child of the <li>'s
<li id="menu-item-205" class="local-scroll menu-item menu-item-type-custom menu-item-object-custom menu-item-205">
</li>
what you can do is make the li the get the active class like this
$('.menu-solutions-menus-container a').click(function () {
$('.menu-solutions-menus-container a').removeClass('active');
$(this).parent('li').addClass('active');
});
$('.number').click(function () {
$('.number').removeClass('active');
$(this).parent('li').addClass('active');
});
$('.menu-solutions-menus-container a').click(function(){
$('ul.shortcode_menu.solution-menu li').removeClass('active');
$(this).parent('li').addClass('active');
});
Then change your CSS to reflect the <li> is the element with the active class.
ul.shortcode_menu.solution-menu li.active {
background: black;
}
Again I've changed it to background: black instead of border-top, as I think that's the effect you want.
I want to change my div content on the click of a link, this currently works by using an id to show hide the div on content.
However the screen moves to the top of the clicked div - I am aware thats because its linked to moving to the location of the id, is there a way that no matter how far the user has scrolled down the page when they are able to click that the screen won't shift to the top of the div?
HTML
<li>Wedding Cakes</li>
<li>Birthday Cakes</li>
<li>Christening Cakes</li>
<li>Occasion Cakes</li>
<div id="wedding">
content
</div>
<div id="birthday">
content
</div>
<div id="christening">
content
</div>
<div id="occassion">
content
</div>
JS
$(document).ready(function() {
var h1 = $("#wedding").height();
var h2 = $("#birthday").height();
var h3 = $("#christening").height();
var h4 = $("#occassion").height();
$("#wedding,#birthday,#christening,#occassion").height(Math.max(h1, h2, h3, h4));
$("#birthday").hide();
$("#christening").hide();
$("#occassion").hide();
});
$("#wedding-tab").live('click', function() {
$("#wedding").show();
$("#birthday").hide();
$("#christening").hide();
$("#occassion").hide();
});
$("#celebration-tab").live('click', function() {
$("#wedding").hide();
$("#birthday").show();
$("#christening").hide();
$("#occassion").hide();
});
$("#christening-tab").live('click', function() {
$("#wedding").hide();
$("#birthday").hide();
$("#christening").show();
$("#occassion").hide();
});
$("#cupcakes-tab").live('click', function() {
$("#wedding").hide();
$("#birthday").hide();
$("#christening").hide();
$("#occassion").show();
});
Adding prevent default should sort your problem..
eg:
$("#wedding-tab").live('click', function(e) {
$("#wedding").show();
$("#birthday").hide();
$("#christening").hide();
$("#occassion").hide();
e.preventDefault();
});
you want to preventDefault as part of your click event
$("#christening-tab").live('click', function(e) {
e.preventDefault();
$("#wedding").hide();
$("#birthday").hide();
$("#christening").show();
$("#occassion").hide();
});
$(document).ready(function() {
var h1 = $("#wedding").height();
var h2 = $("#birthday").height();
var h3 = $("#christening").height();
var h4 = $("#occassion").height();
$("#wedding,#birthday,#christening,#occassion").height(Math.max(h1, h2, h3, h4));
$("#birthday, #christening, #occassion").hide();
// });
$("#wedding-tab").live('click', function() {
$("#wedding").show();
$("#birthday, #christening, #occassion").hide();
return false;
});
$("#celebration-tab").live('click', function() {
$("#birthday").show();
$("#wedding, #christening, #occassion").hide();
return false;
});
$("#christening-tab").live('click', function() {
$("#christening").show();
$("#wedding, #birthday, #occassion").hide();
return false;
});
$("#cupcakes-tab").live('click', function() {
$("#occassion").show();
$("#wedding, #birthday, #christening").hide();
return false;
});
});
May I show a slightly more concise version of your wall of script:
$('li > a').click(function(e) {
e.preventDefault();
var id = this.firstChild.nodeValue.toLowerCase().split(/ /)[0];
$('#' + id).toggle().siblings().not('ul').hide();
});
JS Fiddle demo.
This assumes that you only want to show div with the corresponding id when you click a link (clicking the 'wedding-tab' link will show the 'wedding' div, and hide the others?
It prevents the default action of the clicked a, so the window shouldn't move after you click the link.
Also, I fixed a typo in your mark-up, the div id was 'occassion':
<div id="occassion">
content
</div>
This is wrong, and, far more importantly, inconsistent with your own spelling of the word in the link-text in the li element (where it was Occasion Cakes). So I fixed the div's misspelling.
Hopefully this is of some use to you.
References:
Regular JavaScript:
firstChild.
nodeValue.
split().
toLowerCase().
jQuery:
click().
event.preventDefault().
hide().
not().
siblings().
toggle().
Basically I have 2 buttons that when hovered show/hide 2 hidden unordered lists so I use .toggle() for these
What I would also like to do however is when i hover and then click the link the unordered list remains visible, then when i hover and click the other link the previous hidden list is hidden again and the new clicked list is shown? Just not managing to work out how this can be best achieved, at the moment when i hover and then click as soon as i hover off the list disappears.
Hope this makes sense, fiddle is here http://jsfiddle.net/kyllle/D5Lmp/5/
Thanks
EDITED: I see now, updating based on your comment.
Basically, you just have to walk through the set of possibilities:
Hover over something active
Hover over something not active
Click on something active
Click on something not active
It's a logic problem more than anything, and here's the code and the fiddle to solve it:
$('#menu > li > a').hover(function() {
if(!$(this).is('.active')) {
var anyActive = $('#menu > li > a.active');
if (anyActive.length == 0) {
$('ul.inner:visible').hide();
$(this).next().show();
}
}
});
$('#menu > li > a').click(function(e) {
if(!$(this).is('.active')) {
var anyActive = $('#menu > li > a.active');
if (anyActive.length > 0) {
anyActive.next().hide();
anyActive.removeClass('active');
}
$(this).addClass('active');
$(this).next().show();
}
e.preventDefault();
});
Working fiddle: http://jsfiddle.net/D5Lmp/22/
I think I was able to get your desired functionality by excluding the hover toggle based on the active class. You can see it here: http://jsfiddle.net/D5Lmp/9/
code:
$('#menu > li a').hover(function() {
$(this).not(".active").next().toggle();
});
I am struggling with a collapsible vertical menu. The first part of the script below works, so that the upper UL display its sibling LIs, while the other ULs keep their sibling LIs hidden.
My difficult task (to me at least) is to make the parent UL to the active link keep its sibling LIs visible. This is what I tried in the lower part of the script.
My a-links some times get a trailing hash (#) which I want to remove in order to compare i to the active URL. This is done through the trimHash(string)-function--which works when tested on a simple string, but not in this script.
Any good advice out there?
$(document).ready(function() {
// Collapse everything but the first menu:
$(".mainmenu > li > a").not(":first").find("+ ul").slideUp(1);
// Expand or collapse:
$(".mainmenu > li > a").click(function() {
$(this).find("+ ul").slideToggle("fast");
});
$(".mainmenu li").each(function () {
var li = $(this);
var a = rtrimHash(li[0].firstChild);
if (a.href == location.href) {
$(this).find("+ ul").slideDown(1);
}
});
I ended up with this solution. As it is a Wordpress site, while stepping through the menu items in the menu I could check if each link is active by comparing the link to the active post, and insert the class "current" to these menu items:
echo '<li class="child';
if ( $menuPost->ID == $post->ID ) { echo ' current'; }
And then use jQuery to find all instances of the li "current" class, and trigger the parent ul's to slideDown:
$(document).ready(function() {
// Collapse everything:
$("li.cat").find("+ ul").slideUp(1);
// Collapse everything but the first menu:
//$("li.cat").not(":first").find("+ ul").slideUp(1);
// Expand or collapse:
$("li.cat").click(function() {
$(this).find("+ ul").slideToggle("fast");
});
$("li.current").parent().slideDown(1);
});
Sorry I didn't solve this through javascript as I intended, but I achieved what I wanted.