jQuery - Expand Tree View up to selected node level - javascript

I am trying to expand the tree view up to selected node level. But I am not getting any idea about this please can any one help me on this.
For example We clicked on 'Parent d' in 'Category list' then expand 'Tree View List' up to 'Parent d' level for more details check Here
HTML
<h3>
Category list
</h3>
When click on any li expand tree list up to selected level
<ul id='category'>
<li li-id='1' id='1'>Parent 1</li>
<li li-id='2' id='2'>Parent 2</li>
<li li-id='3' id='3'>Parent 3</li>
<li li-id='4' id='4'>Parent 4</li>
<li li-id='5' id='5'>Parent c</li>
<li li-id='6' id='6'>Parent d</li>
<li li-id='7' id='7'>Parent a</li>
<li li-id='8' id='8'>Parent b</li>
<li li-id='9' id='9'>Parent e</li>
<li parent-id='5' li-id='10'>Parent x</li>
</ul>
Tree View List
<h3>
Node View
</h3>
<div class='tree'>
<ul id='ulCollapse'>
<li parent-id='0' li-id='1'>Parent 1</li>
<li parent-id='1' li-id='2'>Parent 2</li>
<li parent-id='1' li-id='3'>Parent 3</li>
<li parent-id='1' li-id='4'>Parent 4</li>
<li parent-id='3' li-id='5'>Parent c</li>
<li parent-id='3' li-id='6'>Parent d</li>
<li parent-id='2' li-id='7'>Parent a</li>
<li parent-id='4' li-id='8'>Parent b</li>
<li parent-id='4' li-id='9'>Parent e</li>
<li parent-id='5' li-id='10'>Parent x</li>
</ul>
</div>
jQuery
//$('#ulCollapse li').hide();
$('ul li').click(function(){
var nodeId = $(this).attr('li-id');
alert(nodeId);
})
var $ul = $('ul');
$ul.find('li[parent-id]').each(function() {
$ul.find('li[parent-id=' + $(this).attr('li-id') + ']')
.wrapAll('<ul />')
.parent()
.appendTo(this)
});
DEMO

I am not a javascript developer but, tried to solve your problem, here is the working demo
var $ul = $('ul');
$(document).ready(function() {
$ul.find('li[parent-id]').each(function() {
$ul.find('li[parent-id=' + $(this).attr('li-id') + ']').wrapAll('<ul />').parent().appendTo(this)
// not changed its your code still, but I need this only first time, so moved into document ready
});
});
$('ul#category li').click(function() {
$("#ulCollapse1").html(''); // I have created a new div section
$("ul").removeAttr('class'); // remove active classes
var nodeId = $(this).attr('id');
arrangeNodes(nodeId);
$("#ulCollapse1").html($(".active").parent().clone()); //get the marked elements first parent (which is 'li')
$("#ulCollapse").hide(); // hide the main treeview
});
function arrangeNodes(item) {
$ul.find('li[parent-id=' + item + ']').parent().closest("ul").addClass("active"); // find item and mark the first ul as active (selected)
}
Hope helps,

I don't fully understand what you're trying to achieve.
But maybe :lt() is what you're looking for
HTML
<h3>
Category list
</h3>
<ul id='category'>
<li li-id='1' id='1'>Parent 1</li>
<li li-id='2' id='2'>Parent 2</li>
<li li-id='3' id='3'>Parent 3</li>
<li li-id='4' id='4'>Parent 4</li>
<li li-id='5' id='5'>Parent c</li>
<li li-id='6' id='6'>Parent d</li>
<li li-id='7' id='7'>Parent a</li>
<li li-id='8' id='8'>Parent b</li>
<li li-id='9' id='9'>Parent e</li>
<li li-id='10' id='10'>Parent x</li>
</ul>
<br>
<br>
<h3>
Node View
</h3>
<div class='tree'>
<ul id='ulCollapse'>
<li parent-id='1'>
<ul>
<li>Parent 1</li>
</ul>
</li>
<li parent-id='2'>
<ul>
<li>Parent 2</li>
<li>Parent 3</li>
<li>Parent 4</li>
</ul>
</li>
<li parent-id='3'>
<ul>
<li>Parent c</li>
<li>Parent d</li>
<li>Parent a</li>
</ul>
</li>
<li parent-id='4'>
<ul>
<li>Parent b</li>
<li>Parent e</li>
</ul>
</li>
<li parent-id='5'>
<ul>
<li>Parent x</li>
</ul>
</li>
</ul>
</div>
JS
$cats = $("#category");
$tree = $("#ulCollapse");
$tree.children().hide();
$cats.on("click", "li", function() {
var nodeId = $(this).attr('li-id');
console.info("NODE ID: ", nodeId);
$tree.children().hide();
var maxEq = $tree.children("[parent-id='" + nodeId + "']").index();
maxEq < 0 && (maxEq = 0);
maxEq++; //LTE since :lte() doesn't exist
console.info("MAX EQ: ", maxEq);
$tree.children(":lt(" + maxEq + ")").show();
});
FIDDLE ==> https://jsfiddle.net/x45j4fx6/1/

Related

Display parent UL and for the root parent both UL and LI node

<ul id="ul_Book1">
<li id="li_Book1"> Book1 </li>
<ul id="ul_Chap1">
<li id= "li_Chap1"> Chapter 1</li>
<ul>
<li id="li_Sect11" > Section 1.1 </li>
<li id="li_Sect12" > Section 1.2 </li>
<li id="li_Sect13" > Section 1.3 </li>
</ul>
</ul>
<ul id="ul_Chap2">
<LI id= "li_Chap2"> Chapter 2</LI>
<ul>
<li id="li_Sect21" > Section 2.1 </li>
<li id="li_Sect22" > Section 2.2 </li>
<li id="li_Sect23" > Section 2.3 </li>
</ul>
</ul>
<ul id="ul_Chap3">
<li id= "li_Chap3"> Chapter 3</li>
<ul>
<li id="li_Sect31" > Section 3.1 </li>
<li id="li_Sect32" > Section 3.2 </li>
<li id="li_Sect33" > Section 3.3 </li>
</ul>
</ul>
function menuDisplayPath(li_id) {
var idVal = li_id;
var $obj = $('li').filter(function () { return $(this).attr('id') == idVal; }).parents();
$($obj.get().reverse()).each(function () {
if ($(this).is("li")) {
$(this).find('li').each(function () {
$(this).show();
});
$(this).find('Ul').each(function () {
$(this).show();
});
}
});
}
When a LI node is selected , say "Section 3.2" , I would like to expand/show only "Book1-- Chapter3 -- Section 3.2" and rest of the UL nodes under Book1 should not expand.
But my function menuDisplayPath(li_id) is expanding all the UL under Book1 and also display all LI's. What am I missing in the function.
Assuming all is expanded on load.
First, I corrected many missing double-quotes and extra spaces...
So here is your HTML:
<input type="reset" id="reset" value="Expand all">
<ul id="ul_Book1">
<li id="li_Book1"> Book1 </li>
<ul id="ul_Chap1">
<li id="li_Chap1"> Chapter 1</li>
<ul>
<li id="li_Sect11"> Section 1.1 </li>
<li id="li_Sect12"> Section 1.2 </li>
<li id="li_Sect13"> Section 1.3 </li>
</ul>
</ul>
<ul id="ul_Chap2">
<li id="li_Chap2"> Chapter 2</li>
<ul>
<li id="li_Sect21"> Section 2.1 </li>
<li id="li_Sect22"> Section 2.2 </li>
<li id="li_Sect23"> Section 2.3 </li>
</ul>
</ul>
<ul id="ul_Chap3">
<li id="li_Chap3"> Chapter 3</li>
<ul>
<li id="li_Sect31"> Section 3.1 </li>
<li id="li_Sect32"> Section 3.2 </li>
<li id="li_Sect33"> Section 3.3 </li>
</ul>
</ul>
</ul>
And here is the way to hide the other chapters on click of a li with a section id:
$(document).ready(function(){
$("#ul_Book1").on("click","ul ul li", function(){
$(this).parent().parent().siblings("ul").each(function(){
$(this).hide(); // Hides all other chapter
});
});
$("#reset").on("click",function(){
$("#ul_Book1").children("ul").each(function(){
$(this).show();
});
});
});
Fiddle
Now... Can't tell you how to display the <section> since I didn't see the relevant HTML.
The following worked for me:
function open($li) {
$('.content').hide();
$li.children().show();
if ($li.hasClass('section')) $li.parent().parent().children().show();
}
// test driver
$(document).ready(function() {
$('li').click(function (e) { open($(this)); e.stopPropagation(); });
});
.content {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="book">
<li class="chapter">Chapter One
<ul class="chapter content">
<li class="section">Section One<br><i class="content">1.1 contents</i></li>
<li class="section">Section Two<br><i class="content">1.2 contents</i></li>
</ul>
</li>
<li class="chapter">Chapter Two
<ul class="chapter content">
<li class="section">Section One<br><i class="content">2.1 contents</i></li>
<li class="section">Section Two<br><i class="content">2.2 contents</i></li>
</ul>
</li>
</ul>
Basically you put the section element you want to be open inside the open($li) function.
You should also only put <li> elements inside <ul> elements.
I hope this is what you wanted.

jquery onclick parent remove child action

Actually I'm really very sorry about my question, I'm not sure how to make attention or ask question about this kind of problem.
Please see my code 1st.
<div data-model="ABC123" id="product">Select a Product</div>
<ul id="lists">
<li data-product="P1">Product 1
<ul id="sublists">
<li data-item="it1">P1 Item 1</li>
<li data-item="it2">P1 Item 2</li>
<li data-item="it3">P1 Item 3</li>
<li data-item="it4">P1 Item 4</li>
</ul>
</li>
<li data-product="P2">Product 2
<ul>
<li data-item="it1">P2 Item 1</li>
<li data-item="it2">P2 Item 2</li>
<li data-item="it3">P2 Item 3</li>
<li data-item="it4">P2 Item 4</li>
</ul>
</li>
<li data-product="P3">Product 3</li>
<li data-product="P4">Product 4</li>
</ul>
<div id="codes">
<span class="code1"></span>
<span class="code2"></span>
<span class="code3"></span>
</div>
The jquery code is:
<script>$('#product').click(function () {
var pmodel = $(this).data('model');
$('.code1').empty().append(pmodel);
$('.code2').empty();
$('.code3').empty();
});
$('#lists li').click(function () {
var dmodel = $(this).data('product');
$('.code2').empty().append(dmodel);
});
$('#lists li ul li').click(function () {
var item = $(this).data('item');
$('.code3').empty().append(item);
});</script>
You may directly view this at http://codepen.io/alshedupur/pen/YqKGqV
Everything is work fine, but my problem is, when I trigger parent list item like: Product 1 / Product 2 / Product 3
In result I want to empty .code3 span
I try to use $('.code3').empty(); on 2nd action but if I use this, then 3rd action I mean sub list click function not work.
Please see my screenshot for clearly understand what I want:
You need to empty .code3 as well.
$('#product').click(function() {
var pmodel = $(this).data('model');
$('.code1').empty().append(pmodel);
$('.code2').empty();
$('.code3').empty();
});
$('#lists > li').click(function(e) {
e.stopPropagation();
var dmodel = $(this).data('product');
$('.code2').empty().append(dmodel);
$('.code3').empty();
});
$('#lists li ul li').click(function(e) {
e.stopPropagation();
var item = $(this).data('item');
var dmodel = $(this).parents("li").data('product');
$('.code2').empty().append(dmodel);
$('.code3').empty().append(item);
});
#product:hover,
li:hover {
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-model="ABC123" id="product">Select a Product</div>
<ul id="lists">
<li data-product="P1">Product 1
<ul id="sublists">
<li data-item="it1">P1 Item 1</li>
<li data-item="it2">P1 Item 2</li>
<li data-item="it3">P1 Item 3</li>
<li data-item="it4">P1 Item 4</li>
</ul>
</li>
<li data-product="P2">Product 2
<ul>
<li data-item="it1">P2 Item 1</li>
<li data-item="it2">P2 Item 2</li>
<li data-item="it3">P2 Item 3</li>
<li data-item="it4">P2 Item 4</li>
</ul>
</li>
<li data-product="P3">Product 3</li>
<li data-product="P4">Product 4</li>
</ul>
<div id="codes">
<span class="code1"></span>
<span class="code2"></span>
<span class="code3"></span>
</div>

How to open correct sublist in dropdown menu

I got a small Javascript menu problem.
I got a ul list that looks something like this.
<ul class="mainmenu">
<li class="sub-handle">
Item 1
<ul class="submenu">
<li class="sub-li">item 1-1</li>
<li class="sub-li">item 1-2</li>
<li class="sub-li">item 1-1</li>
</ul>
</li>
<li class="sub-handle">
Item 2
<ul class="submenu">
<li class="sub-li">item 2-1</li>
<li class="sub-li">item 2-2</li>
<li class="sub-li">item 2-1</li>
</ul>
</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
I got php to add submenu-i++ and that works just fine. Now I have a Javascript drop down function that looks like this.
var sub_handle = $('.sub-handle');
var sub_nav_ul = $('nav .submenu');
var sub_nav_ul_li = $('nav .mainmenu .sub-li');
$(sub_handle).on('click', function(){
sub_nav_ul.toggleClass('showing-sub');
sub_nav_ul_li.toggleClass('smooth-anchor');
});
sub_nav_ul_li.on('click', function(){
sub_nav_ul.toggleClass('showing-sub');
});
The problem is that when I press any submenu all of my submenus open. I want Javascript somehow to count like php and see if submenu-i++ is pressed only that one expand.
I hope this is clear enough otherwise make a shout and I will try to explain futher.
Thanks in advance!
Get rid of the numbers in the classes, so all the sub-menus have ths same class. Then use DOM navigation methods to find the corresponding menu items to toggle.
var sub_handle = $('.sub-handle');
var sub_nav_ul_li = $('nav .mainmenu .sub-li');
sub_handle.on('click', function() {
$(this).find(".submenu").toggleClass('showing-sub');
$(this).find(".sub-li").toggleClass("smooth-anchor");
});
sub_nav_ul_li.on('click', function() {
$(this).parent().toggleClass('showing-sub');
});
.submenu {
display: none;
}
.submenu.showing-sub {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="mainmenu">
<li class="sub-handle">
Item 1
<ul class="submenu">
<li class="sub-li">item 1-1</li>
<li class="sub-li">item 1-2</li>
<li class="sub-li">item 1-1</li>
</ul>
</li>
<li class="sub-handle">
Item 2
<ul class="submenu">
<li class="sub-li">item 2-1</li>
<li class="sub-li">item 2-2</li>
<li class="sub-li">item 2-1</li>
</ul>
</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
<ul class="mainmenu">
<li class="sub-handle sub-handle-1">
Item 1
<ul class="submenu">
<li class="sub-li">item 1-1</li>
<li class="sub-li">item 1-2</li>
<li class="sub-li">item 1-1</li>
</ul>
</li>
<li class="sub-handle sub-handle-2">
Item 2
<ul class="submenu">
<li class="sub-li">item 2-1</li>
<li class="sub-li">item 2-2</li>
<li class="sub-li">item 2-1</li>
</ul>
</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
var sub_handle = $('.sub-handle');
var sub_nav_ul = $('nav .submenu');
var sub_nav_ul_li = $('.submenu .sub-li');
sub_handle.on('click', function(){
sub_handle.removeClass("showing-sub");
$(this).addClass('showing-sub');
sub_nav_ul_li.toggleClass('smooth-anchor');
});
sub_nav_ul_li.on('click', function(){
$(this).parent().removeClass('showing-sub');
});
Will something like this work:
Note: I had to edit some of the html.
You are toggling the class on all the subitems. What you should do is traverse from the clicked handle to get the corresponding subitems for that. Something like this would suffice:
$(sub_handle).on('click', function(){
$(this).find(sub_nav_ul).toggleClass('showing-sub');
$(this).find(sub_nav_ul_li).toggleClass('smooth-anchor');
});
sub_nav_ul_li.on('click', function(){
$(this).closest(sub_nav_ul).toggleClass('showing-sub');
});
This is in no way the best solution to this, but it should help.

Open Jquery Accordion Menu from exteral link

I am having problems getting my jquery accordion side menu to open up to the correct when I click a link from my top menu. Sorry I switched up my code. Here are my pages:
HERE IS MY JS for side nav :
function initMenu() {
$('#nav ul').hide();
/*$('#nav ul:first').show();*/
$('#nav li a').click(
function() {
var checkElement = $(this).next();
if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
return true;
}
if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
$('#nav ul:visible').slideUp('normal');
checkElement.slideDown('normal');
return false;
}
}
);
}
$(document).ready(function() {initMenu();});
My UL LIST for side nav
<ul id="nav">
<li>Item 1
<ul>
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</li>
<li>Item 2
<ul>
<li>Sub-Item 2 a</li>
<li>Sub-Item 2 b</li>
</ul>
</li>
<li>Item 3
<ul>
<li>Sub-Item 3 a</li>
<li>Sub-Item 3 b</li>
<li>Sub-Item 3 c</li>
<li>Sub-Item 3 d</li>
</ul>
</li>
<li>Item 4
<ul>
<li>Sub-Item 4 a</li>
<li>Sub-Item 4 b</li>
<li>Sub-Item 4 c</li>
</ul>
</li>
</ul>
The page I want to make active
<script type='text/javascript'>
google.load('search', '1', {language: 'en', style: google.loader.themes.V2_DEFAULT});
google.setOnLoadCallback(function() {
var customSearchOptions = {};
customSearchOptions['overlayResults'] = true;
var customSearchControl = new google.search.CustomSearchControl('008189712368144530774:cd8hgx1d4hk', customSearchOptions);
customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
var options = new google.search.DrawOptions();
customSearchControl.draw('cse', options);
}, true);
</head>
<body>
<div id="container">
<div id="topbox">
<div id="topnav"><!--#include file="topnav.html" --></div>
<div id='cse'>Loading</div>
</div>
<div id="leftcol">
<div id="Topleft"><!--#include file="topleftphoto.html" --></div>
<div id="SideNav"><!--#include file="sidenavdistrict.html" --></div>
</div>
<div id="rightcol">
<div id="TopRight">Content for id "topright" Goes Here</div>
<div id="Body">Content for id "body" Goes Here</div>
</div>
<div id="Footer">Content for id "footer" Goes Here</div>
</div>
any thoughts on how to fix this would be great. Im just learning how to use this so if you do help please be specific on where things should go. You can check out live site at www.rsd17.org/test/test/untitled1.shtml Thanks
Sorry been busy couldn't answer earlier.
You could do that this way:
Add ids to both navs:
<div id="container">
<div id="topbox">
<div id="topnav"><ul id="MenuBar1" class="MenuBarHorizontal">
<li id="dis"><a class="MenuBarItemSubmenu" href="#">DISTRICT</a>
<ul>
<li>Item 1.1</li>
<li>Item 1.2</li>
<li>Item 1.3</li>
</ul>
</li>
<li id="sch">SCHOOLS</li>
<li id="stu"><a class="MenuBarItemSubmenu" href="#">STUDENTS</a>
<ul>
<li>Item 3.1 </li>
<li>Item 3.2</li>
<li>Item 3.3</li>
</ul>
</li>
<li id="sta">STAFF</li>
<li>PARENTS</li>
<li>COMMUNITY</li>
<li>CALENDAR</li>
<li>QUICKLINKS</li>
</ul>
( ... )
<ul id="nav">
<li >Item 1
<ul id="i1">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</li>
<li>Item 2
<ul id="i2">
<li>Sub-Item 2 a</li>
<li>Sub-Item 2 b</li>
</ul>
</li>
<li>Item 3
<ul id="i3">
<li><a href="#" >Sub-Item 3 a</a></li>
<li>Sub-Item 3 b</li>
<li>Sub-Item 3 c</li>
<li>Sub-Item 3 d</li>
</ul>
</li>
<li>Item 4
<ul id="i4">
<li>Sub-Item 4 a</li>
<li>Sub-Item 4 b</li>
<li>Sub-Item 4 c</li>
</ul>
</li>
</ul>
And use this javascript:
<script>
var ul = document.getElementById('topnav');
ul.onclick = function(event) {
switch (event.target.parentNode.id){
case "dis" : $('#nav ul:visible').slideUp('normal');
$('#i1').slideDown('normal');
break;
case "sch" : $('#nav ul:visible').slideUp('normal');
$('#i2').slideDown('normal');
break;
case "stu" : $('#nav ul:visible').slideUp('normal');
$('#i3').slideDown('normal');
break;
case "sta" : $('#nav ul:visible').slideUp('normal');
$('#i4').slideDown('normal');
break;
}
};
</script>
This has to be after <script type='text/javascript' src='nav.js'></script>
I tried with your page and with every click on the top menu opens the corresponding item on the side menu. I think that's what you want. However doing this way you have to add new code for each item on the switch. Try it out ;)
EDIT --------------------------------------------------
I will suppose the name of the page number will open the corresponding item. (district1 will open item 1, district2 will open item 2, schools1 will open item 1, etc)
Also always use the ids i1, i2, i3... for the side menu, you don't need i6, i7, etc like you have on students.
If you will always change page you don't need the previous code, just this.
$('#body').ready(function(){
var URL = location.pathname;
for(var i = 0; i < 4; i++){ // 4 = number of items, if you add more increase it
if(URL.indexOf(i) != -1){
$('#nav ul:visible').slideUp('normal');
$('#i'+i).slideDown('normal');
}
}
});
Don't forget this has to be after <script type='text/javascript' src='nav.js'></script>.

Adding level depth to class of nested lists

I have nested lists like this:
<ul>
<li>item 1</li>
<li>item 2
<ul>
<li>subitem 1</li>
<li>subitem 2</li>
<ul>
<li>sub-subitem1</li>
</ul>
</li>
</ul>
</li>
<li>item 3
<ul>
<li>subitem 1</li>
</ul>
</li>
</ul>
Is there any way I could add a class to the based on their depth level so the output is something like this?
<ul class="level-0">
<li>item 1</li>
<li>item 2
<ul class="level-1">
<li>subitem 1</li>
<li>subitem 2</li>
<ul class="level-2">
<li>sub-subitem1</li>
</ul>
</li>
</ul>
</li>
<li>item 3
<ul class="level-1">
<li>subitem 1</li>
</ul>
</li>
</ul>
I am new to jQuery, have tried this:
$("ul").each(function(index, element){$(element).attr("class", "level-" + index);});
...but it only counts the ul's based on their index. Any help is much appreciated!
Try this:
$('ul').each(function() {
var depth = $(this).parents('ul').length;
$(this).addClass('level-' + depth);
});
See http://jsfiddle.net/alnitak/YSZFm/
If you only have 3 levels, try this:
$('ul').addClass('level-0');
$('ul').find('ul').removeClass('level-0').addClass('level-1');
$('ul').find('ul').find('ul').removeClass('level-0').removeClass('level-1').addClass('level-2');
http://jsfiddle.net/fallen888/2rATE/
For a more dynamic solution, try this:
$("ul").each(function(index, element) {
var parents = $(this).parents('ul');
var level = -1;
if (parents.length > 0) {
var parentClass = $(parents.get(0)).attr('class');
level = parseInt(parentClass.substr(parentClass.indexOf('level-') + 6, 1));
}
$(this).addClass('level-' + (level + 1));
});
http://jsfiddle.net/fallen888/2rATE/1/

Categories

Resources