Trouble creating an expanding list with jQuery - javascript

I need to make a list for my client's podcast archive page that opens up to reveal links to the different podcasts for the month they click on. I pretty much want exactly something like BlogSpot has for their default blog archive widget on the right side of the page here: http://kimrome.blogspot.com/
I was able to make something like that here: http://thehummingbirdplace.com/test2.html but I'm not sure how to make the arrows that show if a list has been expanded or not. So it needs to change direction when it's clicked and return to the previous direction when it's clicked again to close that section.
My version also has the child elements showing when I open the page, and I don't want them to expand until their parent is clicked on.
I've look online to see if there is jQuery already created to do this, or how I might be able to make it, but since I'm not sure what this whole thing is properly titled, I get mixed results. Any help would be appreciated!!

Try jQuery-UI accordion
$(...).accordion();
, or this: http://jsfiddle.net/5SKLV/1/
$(...).myAccordion();
Just write CSS at your taste.

If you would like to do this yourself (it's fun to write things yourself):
I've added an ID of #tree to the root <ul>, and wrapped the text of the level 1 <li>s in <span>:
<ul id="tree">
<li>
<span>parent1</span>
<ul>
<li>child11</li>
<li>child12</li>
</ul>
</li>
<li>
<span>parent2</span>
<ul>
<li>child21</li>
<li>child22</li>
</ul>
</li>
</ul>
To apply arrows that point left and right to the parent elements, create two CSS classes with backgrounds, for example (you'll need to find the background images elsewhere or make your own):
.opened > span {
background: url('arrow_pointing_down.png') left top;
color: #0a0; /* just to make it easy to know which class it has */
}
.closed > span {
background: url('arrow_pointing_right.png') right top;
color: #00a; /* just to make it easy to know which class it has */
}
To hide all the child elements when the page loads...
$('#tree > li').addClass('closed');
// hide the level 2 ul's
$('#tree > li ul').hide();
Then in your click handler:
$("#tree > li > span").click(function (event) {
event.preventDefault();
// swap the opened and closed classes
$(this).parent().toggleClass('opened closed');
// toggle the level 2 ul instead of li
$(this).parent().find("ul").toggle();
});
Working demo here: http://jsfiddle.net/cTLGN/
ADDITIONAL:
This demo code doesn't make use of caching references to jQuery objects to make it easier to read. In reality instead of doing:
$(this).parent().toggleClass('opened closed');
$(this).parent().find("ul").toggle();
... one should do:
var parent = $(this).parent(); // search the DOM once for this' parent, and remember it
parent.toggleClass('opened closed');
parent.find("ul").toggle();
.. because every time you use jQuery's $() constructor it needs to search thru the entire DOM, which can be quite expensive if you do it repeatedly.

Related

If a parent menu item is clicked, automatically expand a specific submenu item

My e-commerce store requires three tier menu item to achieve the multi-column megamenu appearance that I want, and although its a bit weird I have found a workaround on desktop by simply hiding the "middle" menu item as "shown" here by the red box (as in there are menu items there, but they are display none).
This is honestly fine, as I hover over the parent menu item, and then only see the li menu items. However my issue is actually on mobile, where the expanding of the top menu item requires a click, and then I need to click a second time to expand the "middle" menu item as you can see in the screenshot below:
There is an event attached to both "caret" clicks, and that is:
function(e) {
e.target.closest("li").classList.toggle("dropdown-open"), e.preventDefault()
}
This attaches an event to the menu item as shown in this screenshot:
..and that allows the submenu to appear below "Weighing Categories" like this:
So my goal (on the mobile viewport) is to show all the submenu items (with the exception of the middle one, in this case "weighing categories") when the categories caret is clicked. I have tried a CSS approach (which is what the dropdown-open class is basically adding), but this results in it always showing (whereas I still want to keep the first click, just not the second click requirement).
body .main-navigation ul.menu li.menu-item-has-children > .sub-menu-wrapper { position: inherit; left: auto; opacity: 1; transform: translateX(0); }
I have also tried multiple variations of using JS to insert a class, and I think this is on the right track, but missing something lol.. I must admit that my JS is poor, mainly trying examples I have found during my research and adapting them.
jQuery("nav-menu-item-1247 .caret").click(function() {
jQuery("#nav-menu-item-6721").addClass( "dropdown-open");
});
The above (and note that it is not working) was supposed to add "dropdown-open" proactively to the weighing categories menu item ("6721") when the top menu item (the "1247" is the "categories" one) is clicked. Perhaps the prevent default in the default JS is blocking it, I am not sure and do not have the skill to troubleshoot it lol.
I would really appreciate some help, been fighting with this for almost 4 hours and I am probably doing something stupid lol. I can share the URL if needed, it is just locked behind a user/pass before it goes live, but I can temporarily remove it.
Thanks :)

collapsing an accordion "li" when class is removed

I've been trying to sort through this for a while now, can't seem to get it working 100%. The current code reveals the .content area without any collapse. It also shifts the page down to center on the content (which in this case goes under the fold if you don't).
$(document).ready(function() {
$('.vl-option .vl-toggle-link').click(function(e) {
e.preventDefault();
$(this).closest('li').find('.content').not(':animated').slideToggle();
$(this).closest('li').toggleClass('active');
});
$('.vl-option').bind('click',function(){
var self = this;
setTimeout(function() {
theOffset = $(self).offset();
$('body,html').animate({ scrollTop: theOffset.top - 20 });
}, 310);
});
});
I've attempted a few approaches to no avail. I'll list a few below (concept was to find any siblings and collapse):
$(this).siblings('li').find('.content').slideToggle();
which actually breaks the original functionality. Then I went with the following (to try an make anything without class="active" collapse):
if ( $(this).siblings('li').not('.active').find('.content').slideToggle(); ) //also tried .hide()
which doesn't seem to have any affect on anything.
The HTML is simple
<ul>
<li class="lv-option active"><!-- when toggled, "active" class is applied... -->
Yada
<div class="content"></div>
</li>
<li class="lv-option"><!-- ...when untoggled, "active" class removed -->
Yada yada
<div class="content"></div>
</li>
</ul>
.active is only applied for stylistic reasons. it has no effect on the functionality of anything. Just needed to be able to target the :before / :after when something was selected.
I just can't seem to wrap my head around jquery... argh.
Only one content at a time should be opened in an accordion right, so applying .slideToggle() to all <li> contents will break this rule. I think it's okay with your markup since you only have two <li>, so they just slides alternately. But if you have more I think the active <li> only should be .slideToggle() other should be .slideUp() only.
You can just chain them all:
$('.vl-toggle-link').click(function(e) {
e.preventDefault();
//find the sibling content apply slideToggle, then move to their parent and add active
$(this).siblings('.content').slideToggle().parent('li').addClass('active')
// go through all the siblings of their parent and remove active, then slideUp their child content
.siblings('li').removeClass('active').children('.content').slideUp();
});
I also find your .animate({scrollTop}) not working properly because it's obtaining the old offset().top value. I think you should get the offset().top after the slideToggle() has finished. See this jsfiddle.
Or you can also calculate scrollTop: jsfiddle.

jquery hiding submenu when change from one submenu opition to another

I have a menu with a sub-menu of two options, as you leave one sub-menu item to go to the next the sub-menu disappears. How Do I stop this?
jQuery:
// SHOW TAKE ATTENDANCE SUB MENU
$('#take_attendance').hover(function(){
$('#taskbar_sub ul').fadeIn(100);
});
$('#taskbar_sub').mouseout(function(){
$('#taskbar_sub ul').hide();
});
// /SHOW TAKE ATTENDANCE SUB MENU
It'll be hard to debug without seeing the HTML/CSS.
It sounds like one of three things:
Your submenu is not nested within #take_attendance.
Your submenu ul is positioned outside the parent element (floated or absolutely positioned)
Your submenu li has margins below each item.
To get a better answer, I would suggest using jsfiddle to input sample HTML/CSS/JS so that someone can properly debug it.
As #Justice said, it's easier to do this if your submenus are nested. If you're going to keep the ULs separate, however, take a look at this answer for some help.

Javascript for changing background image depending on area user is in

My navigation has 5 buttons [Home, About, Services, Events, Contact] and each button has a background image of "blue-button.png". I want to switch it to "white-button.png" when the user is in that section. I wish it were as simple as a:active, but it's not and i'll explain why;
All of the content is displayed in an overlay. The way the website is built, you never leave the index page, but the content is loaded into the index page. This is why the a:active doesn't work.
Now for example, when the user opens the "About" page, the content (which I will call "About Main") appears, and has links to "About-Me", "About-You", and "FAQ". I want the "About" button to change background images (to white) whenever the user is in any of the areas that pertain to "About" (About Main, About me, About you, FAQ)... I also want the button to change back to blue when the user goes to a different section (EX: Contact) and then have the Contact button become white.
The only way I've noticed to tell where the user is, is that the overlay they are on has a css style of display:block while all the others are hidden with display:hidden...
So, I was thinking javascript similar to this:
if (About Main, About Me, About You, FAQ) is display:block
{ $(".about").css('background-image', 'url(../img/white-button.png)' }
else
{ $(".about").css('background-image', 'url(../img/blue-button.png)' }
if (contact) is display:block
{ $(".contact").css('background-image', 'url(../img/white-button.png)' }
else
{ $(".contact").css('background-image', 'url(../img/blue-button.png)' }
the navigation buttons have Classes like: <a class="about"><a class="contact">
while the overlays have IDs like: <div class="simple_overlay" id="about"><div class="simple_overlay" id="contact">
I know it's a lot of information but hopefully someone can help me clear up the specifics, I'm not very good with javascript...
Heres a link to the site if you want to look to get a better understanding
Thank you so much for your time in advance, This one is really killing me!
You're better off just adding and removing a .selected class from each of your links when you click on them. Then set the .selected class to have a background image of white-button.png. You would need to add click handlers to your navigation links so it would first remove any existing .selected classes from all of them, and then add .selected to the link you clicked on.
CSS
.navigation a.selected
{
background-image: url(../img/white-button.png);
}
Javascript - I see you're using jQuery so that makes this easy. Add the code below to your initialization section. I haven't tested this script but it should be pretty close.
// Add click event handler to all navigation links
$('.navigation a').click(function() {
// First remove selected class from all navigation links
$('.navigation a').removeClass('selected');
// Now add the selected class to the current link
$(this).addClass('selected');
});
EDIT: I tweaked this a little and added a jsfiddle for you to see it in action:
http://jsfiddle.net/VCaSV/

How to check if an html element is visible or not if it is within an overflowed area of a div with overflow property set to hidden?

I have a set of LI elements with overflow propety set to hidden by the
jCarouselLite plugin. What I would like to do
is to scroll the jCarouselLite'd element in order to scroll to the
LI element I want, since I have it configured to
show only 3 elements.
Looking at the html code generated by the plugin, I can see:
<ul ..>
<li ..style="..overflow:hidden">1</li>
<li ..style="..overflow:hidden">2</li>
<li ..style="..overflow:hidden">3</li>
<li ..style="..overflow:hidden">4</li>
</ul>
So, I have the first 3 LI elements shown by the plugin, but not the last one. What I would like to do is to scroll so that the 4th LI element is shown, or I can do that by myself if I manage to check if that last LI is within the overflow area, so I can see if it's necessary to scroll for it in order to show it or not.
Hope I'm not getting things confused to understand.
If I understand you correctly, you want to check if the last li in that group has the style overflow: hidden.
You can do this with a simple selector.
$(document).ready(function(){
tester = $('li').last().css('overflow');
alert (tester);
});​
That will set the last li's overflow style to the variable "tester", and when it sends the alert box it will alert the current state of overflow. So if overflow is set to hidden, it will say "hidden", if overflow is set to scroll it will say "scroll".
Sorry if I didn't understand properly or answer your question.
I couldn't find an answer for my original question, but as for any jCarouselLite plugin users, what I did in order to make the carouselLite scroll to a particular item, was to modify just the declaration of the private method go of the plugin in order to make it public, as follows:
.. code ..
go = $.fn.jCarouselLite.go = function go(to) {
if(!running) {
.. code ..
}
.. code ..
I'm sure it's not the best, and more importantly, safer solution, but for now it works for me. Just have to call
$().jCarouselLite.go(position);
on my script, considering position as a number starting from 0 (the first position on the carouselLite).

Categories