Linking menu items and jQuery ui tabs together - javascript

I am trying to link navigation menu items and jQuery tabs together. That means I have two submenu items just think those are category and item and also I have 2 tabs in my page, those are My category and My Items.
What I am trying to do using this is I want to open My category tab when I click on the link category from submenu and vice versa. And also I want to open My Item tab when I click on the link item from the submenu and vice versa.
I tried it doing with jQuery but can't get to work correctly.
My HTML -
<ul id="new-menu">
<li class="dropdown-holder" id="">
<a>My Menu</a>
<div class="dropdown">
<div class="menu-container">
<div class="menu-link">
my sub menu 1
</div>
<div class="menu-link">
my sub menu 2
</div>
</div>
</div>
</li>
<li class="dropdown-holder" id="">
<a>Category & Item</a>
<div class="dropdown">
<div class="menu-container">
<div class="menu-link">
Category
</div>
<div class="menu-link">
Item
</div>
</div>
</div>
</li>
</ul>
<div id="main">
<ul>
<li>Category</li>
<li>Item</li>
</ul>
<div id="tabs-1">
<p>On the Insert tab, the galleries include items that are designed to coordinate with the overall look of your document. You can use these galleries to insert tables, headers, footers, lists, cover pages, and other document building blocks. When you create pictures, charts, or diagrams, they also coordinate with your.</p>
</div>
<div id="tabs-2">
<p>On the Insert tab, the galleries include other document building blocks. When you create pictures, charts, or diagrams, they also coordinate with your.</p>
</div>
</div>
This is my jQuery:
function setCurrent(element) {
$('div').removeClass('current');
$(element).parent().addClass('current');
}
$('#cat_link').click(function() {
$('#tabs-1').hide();
$('#tabs-2').show();
setCurrent(this);
$('#ui-id-2').parent().removeClass('ui-tabs-active ui-state-active');
$('#ui-id-2').parent().addClass('ui-state-default ui-corner-top');
$('#ui-id-1').parent().removeClass('ui-state-default ui-corner-top');
$('#ui-id-1').parent().addClass('ui-tabs-active ui-state-active');
return false;
});
$('#item_link').click(function() {
$('#tabs-2').hide();
$('#tabs-1').show();
setCurrent(this);
$('#ui-id-1').parent().removeClass('ui-tabs-active ui-state-active');
$('#ui-id-1').parent().addClass('ui-state-default ui-corner-top');
$('#ui-id-2').parent().removeClass('ui-state-default ui-corner-top');
$('#ui-id-2').parent().addClass('ui-tabs-active ui-state-active');
return false;
});
This is JS Fiddle
You can see it is working in some manner but not perfectly. Reverse order also not working. Reverse order mean I need to select submenu item according to clicks on tabs.
UPDATE -
According to above JSFiddle
If I click on category link from submenu category tab is opening but its content display from item tab.
If I click on item link from submenu item tab is opening but its content from category tab.
Hope someone will help me.
Thank you.

You can make it simpler: Use right methods to do the job. You are not utilizing jquery ui tabs events /methods.
$("#main").tabs({
activate: function (event, ui) { // subscribe to tab activate
var target = '.menu-link [data-target=#' + ui.newTab.attr('aria-controls') + ']'; // Get the ID of the tab activated. aria-controls on the rendered tab div will give the id of the tab anchor. so get the target as the menu link which has the data-target as that of the id of the current tab.
addCurrent(target); // set up corresponding menu link
}
});
$('.menu-link a').click(function (e) {
e.preventDefault(); // This is required to prevent the default action on click of an anchor tab.
var target = $(this).data('target'); // Get the target repsective to the clicked menu. This is jquery data() to retreive data attribute value.
$("#main").tabs("option", { //Use right method to do the job. set which tab to be opened by using the jquery ui tabs option overload.
'active': $(target).index() - 1 // set the index of the tab to be opened. Get the index using .index() on the target which is the tab anchor and set that as active.
});
addCurrent(this); // set up style for the current menu link
});
function addCurrent(elem) {
$('.current'). // select the currently activated elements
not($(elem) // but not this one if clicked on itself
.closest('.menu-link') // get the closest(Use this instead of parent(), closest is recommended to parent)
.addClass('current') // add the class to the new menu
).removeClass('current'); // remove from existing ones.
}
Minor addition to your markup adding a data-target on your menu link to point to the tab:
Category
Demo
References:
tabs.activate
closest()
index()
tab options
.not()

This is all you need:
$("#main").tabs();
$('.menu-container .menu-link a').on("click", function() {
// get the position of the menu we clicked inside
var menu_ind = $(this).parents('.dropdown-holder').index();
// if not in the submenu we care about, go about default behavior
if( menu_ind != 1 ) return;
// get the position of the link
var ind = $(this).parents('.menu-link').index();
// activate the corresponding tab
$("#main").tabs('select', ind);
return false;
});
it's just tweaks based on the link I posted.
Fiddle: http://jsfiddle.net/925at/1/

You should include at least a snippet of the HTML that would put your jquery code in context so future visitors don't have to rely on jsfiddle.
It looks like you are calling hide/show on the wrong divs.
If #tabs-1 holds your category content, and #tabs-2 holds your item content, shouldn't clicking on #cat-link show #tabs-1 and not hide it?

Related

Show multiple containers with the same class when clicking an item

I have a long page, where one section is tabbed content. However, at the same time as showing tabs, I'd like for other sections further down the page to be visible or hidden, depending on which tab is clicked. Since each tab would display about 4 containers further down the page, I'd like to use classes for this rather than ID's. This is a rough outline of what I have so far (tab content removed, as it's unnecessary):
<div class="horisontal-tabs">
<ul class="tabs">
<li class="tab-label active person-sam" rel="tab1">Sam</li>
<li class="tab-label person-bob" rel="tab2">Bob</li>
<li class="tab-label person-jack" rel="tab3">Jack</li>
<li class="tab-label person-kelly" rel="tab4">Kelly</li>
</ul>
</div>
<div class="container-sam section-visible">Custom content only for Sam</div>
<div class="container-bob section-hidden">Custom content only for Bob</div>
<div class="container-jack section-hidden">Custom content only for Jack</div>
<div class="container-kelly section-hidden">Custom content only for Kelly</div>
<div class="container-sam section-visible">Other content for Sam</div>
<div class="container-bob section-hidden">Other content for Bob</div>
<div class="container-jack section-hidden">Other content for Jack</div>
<div class="container-kelly section-hidden">Other content for Kelly</div>
And I have jquery as per below for each person, but it doesn't seem to be working, and I can't figure out how to simplify it down. The idea is that when you click on one person's tab, all the other people's sections will be hidden and that person's will be visible.
$('.horizontal-tabs ul.tabs li.person-sam').click(function (event) {
$('.container-sam').removeClass('section-hidden').addClass('section-visible');
$('.container-sam.section-visible').removeClass('section-visible').addClass('section-hidden');
event.stopPropagation();
});
I have opted to not use ID on the sections and use a class instead, because multiple will need to show at once, so they wouldn't be unique.
Any tips will be greatly appreciated! :)
So the question is how to make simpler?
What comes to mind is you don't need active and inactive classes, you just need one of them, and then you can make the other be the default state . That is, add a default class .section to all sections and either use .section as the visible state and add .section-hidden to hide it, or use .section as the hidden state and add .section-visible to show it.
Say you go with .section-visible, the css would be something like this:
.section { display: none }
.section.section-visible { display: block }
This would also simplify your javascript because now you can reset all sections and just turn on/off the ones you need.
If you go, again, with .section-visible, run this on click:
$('.section').removeClass('section-visible'); // reset all sections
$('.container-sam').addClass('section-visible'); // add visible class to specific sections
You can see you only need one extra class, not two.
BONUS 1: you can use BEM to make it clearer.
BONUS 2: it looks like you have one click listener for each person, but instead you can use the HTML dataset API and the jQuery .data() function to detect which person's button you're pressing. That way you would have only one click listener, and you can detect which li was clicked by checking the data- attribute. Like <li data-person="sam">sam</li> and const containerSelector = `.container-${$(this).data('person')}`;. $(this) will select the li clicked, and .data('person') will return 'sam'. So the selector will be .container-sam.

Adding an event to a list child node

I have a list in my navigation bar which has a list inside it used as a drop down menu. The overall list is named categories (I know it should have a reference to another page but I am just trying to get the dynamic content working first).
I have an event listener attached to this element which takes the user to a page that displays all categories.
As you hover over this element it displays a list of categories. What i would like to do is to be able to click on one of these and it take the user straight to the category.
This works with my code but only in certain places. In others it takes me to the page which displays all categories.
Here is the code i am using to add the events:
var categoryHeading = document.getElementById('categoriesNav');
dropList = document.createElement("ul");
dropList.setAttribute("id", "categoriesDrop");
categoryHeading.appendChild(dropList);
categoryHeading.addEventListener('click', displayCategoriesPage); //displayCategoriesPage displays a page with all categories listed
categoryHeading.addEventListener("mouseover", function(){
if(dropList){
dropList.style.display = "block";
}
});
categoryHeading.addEventListener("mouseout", function(){
if(dropList){
dropList.style.display = "none";
}
});
var categoryListItems = document.getElementsByClassName("categoryListItem");
for(var i=0; i<categoryListItems.length; i++){
categoryListItems[i].addEventListener("click", function(e){
displaySingleCategory(e); //Displays the page with all items from one category
});
}
Here is the HTML:
<nav>
<ul>
<li id="homeNav"></li>
<li id="categoriesNav">
<a>Categories</a>
<ul id="categoriesDrop">
<li class="categoryListItem">Outdoor</li>
<li class="categoryListItem">Technology</li>
</ul>
</li>
<li id="basket"></li>
<li id="search"></li>
</ul>
</nav>
I am assuming the problem is to do with how my <nav> is laid out. Or where i have added the events.
In Javascript whenever an event is triggered, it's default behaviour is bubbling up through DOM.
In your case, you need to stop the event propagation because you have a click listener in the child li and it's parent that will be executed showing you the categories page instead of specific category page.
Try to put e.stopPropagation(); in your child event listeners.

Javascript - How to highlight the last clicked list item

I have a sidebar list of items in HTML on a bootstrap page and i would like the last clicked item to be highlighted with a "active" class. I was wondering how i can get the whole list (ul) like an array so i could highlight a certain item (li) or highlight the last clicked item.
The list is structured like this:
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar sidebar-style">
<ul class="nav nav-sidebar sidebar-scrollable">
<li class="active">Home</li>
<li>Site 001</li>
<li>Site 002</li>
<li>Site 003</li>
<li>Site 004</li>
<li>Site 005</li>
What i need is some JS code which can set the last clicked li item to class="active" but still have the option to set any of the li items to the active one, for example if i wanted to have a random button and it selected item 4 then 2 etc. I guess the main thing i need is a way to have all list items like an array.
I strongly suggest you use jQuery which is kind of simulating DOM manipulation like an array or more precisely an object.
My suggestion would be the following:
$(".nav-sidebar").on('click', 'li', function(e) {
$(this).parent().find('li.active').removeClass('active');
$(this).addClass('active');
});
This code is removing the active class from all li items, and adding active class to currently clicked li item.
Cheers,
Edit PS:
You could also bind your event directly like this:
$(".nav-sidebar li").click(...);
But the purpose of using .on() is that it will bind the event dynamically, so that if you decide to add a new li to your $(".nav-sidebar") element, it will also trigger the event on that element.
Edit:
To answer #zeddex your question: How to select manually li 4?
You simply use the following:
$("li:eq(3)").trigger('click');
That'll manually trigger a click event for li 4. If you want to select a specific li you can use a method of the like: :eq(x) in which x is the position of the li item you want to reach starting from 0 which corresponds to your first li. Have a look at jQuery DOC on that: jQuery DOC on :eq()

individually hiding drop-downs according to one child-jquery

So I've painfully got multiple drop-downs toggling states(hidden and shown) in JQuery but I have some code which tells the side bar which page is active and gives it the style active and I would like a drop down to not be hidden if there is a child active in it.
The top level link which you click to view the drop-down gets given the id "HAC"(has active child) if it has an active child but I think I might be burning my brain out on this.
Here's a jsfiddle page with the working demo of the problem.
the drop down is set out like this in a nav
<ul id="HAC" class='topLevel'>
<li class='subItem'>
<a class="active" href='thatpage.php'>That page</a>
</li>
<li class='subItem'>
<a href='thatotherpage.php'>That other page</a>
</li>
</ul>
thanks in advance for any help
I think what you are looking for is the jQuery :not selector. Here is an update to your fiddle
function dropDowns() {
//for each toplevel li a
$(".topLevel:not(#HAC) li a").each(function() {
//hide subitems if not HAC (has active children)
$(this).hide();
});
//Toggle show them on click
clickToggle();
}

Expand dropdown menu if one of the sub-menu items is active

I have a dropdown menu which is expanded by clicking. The menu is collapsed by default. I would like the menu to appear to be expanded if one of the sub menu pages is active. I hope that's clear. Here is my code.
HTML
<li class="dropdown">
<a class="disablelink" href="#">Carbohydrates, proteins & fats</a>
<ul class="sub_navigation">
<li>Carbohydrates</li>
<li>Proteins</li>
<li>Fats</li>
</ul>
</li>
jQuery
$(document).ready(function() {
$('.dropdown').click(function() {
// When the event is triggered, grab the current element 'this' and
// find it's children '.sub_navigation' and display/hide them
$(this).find('.sub_navigation').slideToggle();
});
$(".disablelink").click(function(e) {
e.preventDefault();
});
});
So if the user is on carbohydrates.php, proteins.php or fats.php i would like the menu to be expanded. I don't know how to do this though. Can anyone help?
When a page is active you would need to give it's link an additional class, for example;
<li class="current_page">Carbohydrates</li>.
Then you can use jQuery to loop through the menu and expand it if any menu item have the class.
$('.dropdown li').each(function() {
if ($(this).hasClass('current_page')) {
$(this).closest('.sub_navigation').slideDown();
}
});
Demo: http://jsfiddle.net/R7gkw/

Categories