Jquery Nested Accordion to Show Only one Level - javascript

Suppose I have a following structure:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3
<ul>
<li>Item11</li>
<li>Item12</li>
<li>Item13</li>
</ul>
</li>
This tree structure can have many levels.
Initially, I want to show following list:
Item 1
Item 2
Item 3 +
When I click on + list becomes
Item 3 -
Item 11
Item 12
Item 13
So, parent list disappears and sublist is shown.
If I click -, then everything is returned to the previous list.
Is there some jquery plugin for doing this?
Perhaps, some options in accordion?
Thanks in advance.

Used Dkouk his version to create what you need.
EDIT 1: Hide other menu items
EDIT 2: Second level menu
$(function () {
$('ul li').each(function () {
if ( $(this).find('ul').length > 0 ){
$(this).addClass('child');
}
});
$('ul li.child span').click(function() {
$(this).parent().toggleClass('open').find('ul').first().slideToggle();
$(this).parent().siblings().slideToggle();
});
});
ul {
list-style:none;
}
ul li.child span:after {
content:"+";
}
ul li.child.open span:after {
content:"-";
}
li ul { display:none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul class="main">
<li>Item 1</li>
<li>Item 2</li>
<li>
<span>Item 3</span>
<ul>
<li>Item 1</li>
<li>
<span>Item 2</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</li>
<li>Item 3</li>
</ul>
</li>
</ul>

You can add a class to your list when it's have a sublist, and toggle the list and toggle another class for parent of list so can change the '+' to '-'.
You can as many levels, and the code will work,
I've add a span to the list have child, but so can trigger the click only at text, if you trigger click for LI list and have sublist open then will close again.
You can style the content.
Here a simple example :
$(function () {
$('ul li').each(function () {
if ( $(this).find('ul').length > 0 ){
$(this).addClass('child');
}
});
$('ul li.child span').click(function() {
$(this).toggleClass('open').parent().find('ul:first').slideToggle();
$(this).parent().siblings().slideToggle();
});
});
ul {
list-style:none;
}
ul li.child span:after {
content:"+";
}
ul li.child span.open:after {
content:"-";
}
ul li ul { display:none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>
<span>Item 3</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>
<span>Item 3</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</li>
</ul>
</li>
</ul>

Related

Disable mouseenter when over element on page load

I'm trying to find a way to disable mouseenter when the top-level navigation item is clicked & on pageload and re-enable again when the mouse leaves and enters the element again.
User hovers over element = show submenu
User clicks menu = hide submenu and only show submenu when user leaves menu elements and enters again.
If user is over the element onLoad then only show submenu when user leaves element and enters again.
$('.navmenu li').on('mouseenter', function(e) {
$(e.target).next().addClass('js-hover')
}).on('mouseleave', function(e) {
$(e.target).next().removeClass('js-hover')
});
$('.navmenu').on('click', function(e) {
$(e.target).next().removeClass('js-hover')
location.reload(true);
})
.navmenu .submenu {
display:none;
}
.navmenu li {
display: inline;
}
.navmenu .submenu {
position:absolute;
top:40px;
left:0
}
.navmenu li:hover .js-hover {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu">
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
<li>
Menu 2
<nav class="submenu">
<ul>
<li>Submenu 4</li>
<li>Submenu 5</li>
<li>Submenu 6</li>
</ul>
</nav>
</li>
</ul>
</nav>
this could be done using variables and storing a state of element (if it should be hidden or not). But since you tried to do this through class attributes, I did the same. Here is simle example of one menu item, everything should be clear.
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu" hidden>
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
</ul>
</nav>
and javascript:
$menuLink = $("nav.navmenu li > a");
$menuLink.click(function () {
$(this).addClass("dontHide");
});
$menuLink.mouseenter(function () {
$(this).next("nav.submenu").removeAttr("hidden");
$(this).removeClass("dontHide");
});
$menuLink.mouseleave(function () {
if(!$(this).hasClass("dontHide")) {
$(this).next("nav.submenu").attr("hidden", true);
}
});
Live demo: https://jsfiddle.net/g3fua461/24/

jquery add tag around unnested text

This is a really hard question to find a title for, but here is it.
I got this HTML, that I can't change
<ul>
<li>
First part of the list
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</li>
<li>
Second part of the list
<ul>
<li>item 3</li>
</ul>
</li>
</ul>
And I'd like to apply things to the "first part of the list" and "Second part of the list" part, but not the nested ul part, like CSS transform scaleY, and a custom Jquery onClick method.
So, the solution I'd like would be a way to JQueryly add around those.
Is this possible?
Thank you a lot
To achieve this you can filter() the li contents() to retrieve the text nodes within it, then wrap that in a span and apply the needed CSS rules. Something like this:
$('#container > ul > li').each(function() {
var foo = $(this).contents().filter(function() {
return this.nodeType == 3 && this.textContent
}).wrap('<span />');
});
#container > ul > li > span {
color: red;
display: inline-block;
transform: scaleY(2);
margin: 0 0 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<ul>
<li>
First part of the list
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</li>
<li>
Second part of the list
<ul>
<li>item 3</li>
</ul>
</li>
</ul>
</div>

JS using onclick event on li to display block

HTML:
<script>function dropdown()
{ console.getElementById("").style.display="block";
}</script>
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
Css:
#dropdown ul{
display: block;
}
#dropdown ul li {
display: block;
background-color: #558c89;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover > ul { /*this is what the onclick event should do*/
display: block;
}
The onclick should start the function "dropdown()" which needs to: "display: block;" on #dropdown ul li
You're missing the list ID and you're calling the selector on the console (when you want to be selecting on the document).
<script>
function dropdown()
{
document.getElementById("Menuitems").style.display="block";
}
</script>
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
JSFiddle: http://jsfiddle.net/tmaB9/
Try:
<li onClick="dropDown(this);">
This is important, so your function knows which element you clicked on. Then...
function dropDown(li) {
var submenu = li.getElementsByTagName('ul')[0];
if( submenu) {
submenu.style.display = submenu.style.display == "block" ? "" : "block";
}
}
This will toggle the visibility of the submenu :)
here is a quick example of what i think you want (provided you can use JQuery):
$(document).ready(function () {
$('#dropdown ul li').on('click', function dropdown() {
//console.getElementById("").style.display = "block";
});
});
<div id="dropdown" class="dropdown">
<ul>
<li>menu 1</li>
<li>menu 2</li>
<li>menu 3</li>
<li>menu 4</li>
</ul>
</div>

JQuery - How to move a li to another position in the ul? (exchange 2 li's)

What is a cool way to apply this? I need a script that exchange two < li>'s position in an < ul>.
It think that should be possible to achieve. Thanks for your response.
HTML
<div id="awesome">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
Pseudo Javascript (JQuery)
$("#awesome ul li:eq(1)").exchangePostionWith("#awesome ul li:eq(3)");
HTML Result
<div id="awesome">
<ul>
<li>Item 1</li>
<li>Item 4</li>
<li>Item 3</li>
<li>Item 2</li>
<li>Item 5</li>
</ul>
</div>
You can use jQuery's .after() for moving elements around. I cloned one of them so the original can remain as a placeholder. It's like if you wanted to switch variables a and b, you'd need a third temporary variable.
$.fn.exchangePositionWith = function(selector) {
var other = $(selector);
this.after(other.clone());
other.after(this).remove();
};
Now your pseudocode $("#awesome ul li:eq(1)").exchangePositionWith("#awesome ul li:eq(3)"); isn't so pseudo :-)
$("ul li a").click(function () {
$(this).parent().insertBefore('ul li:eq(0)');
});
<ul>
<li><a>a</a></li>
<li><a>b</a></li>
<li><a>c</a></li>
<li><a>d</a></li>
<li><a>e</a></li>
<li><a>f</a></li>
</ul>

JQuery - Attach (duplicate, clone) li and put it above a li

Is it possible to clone a specific < li> and put it above an other specific < li>?
Any clue would help me..?
HTML
<div id="main">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
Pseudo Javascript (JQuery)
$('#main ul li:eq(3)').duplicateAndPutAbove('#main ul li:eq(2)');
HTML Result
<div id="main">
<ul>
<li>Item 1</li>
<li>Item 3</li> <!-- Item 3 was duplicated (or cloned) and then putted ABOVE Item 2 -->
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
You were really close, you wanted clone and insertBefore (and remember that eq is zero-based):
$('#main ul li:eq(2)').clone().insertBefore('#main ul li:eq(1)');
Live example
$('#main ul li:eq(3)').clone().insertBefore('#main ul li:eq(2)');
Demo: http://jsfiddle.net/karim79/8LpuN/
var elem = $('li').contains('3').clone(); // make a copy
$('li').contains('Item 3').before(elem); // insert before the cloned element
$('#main ul li:eq(3)').clone().insertBefore('#main ul li:eq(2)');

Categories