JavaScript expandable treeview lightweight - javascript

I wanted a lightweight solution so i found this one, however it only expands on clicking plus sign "+" next to the name of expandable category. I replaced + for red square and - for blue square for this demonstration to work.
Live code at: http://jsfiddle.net/2VXuk/2/
I need help modifying it to make any sub level that is expandable to be category that's not a link and upon clicking on its name expand its content.
Would be great to have option to make it a category - expand on click or link expand on + click and redirect on name click.
e.g.
<ul id="sitemap">
<li><a class="category" href="#">expands only</a>
<ul>
<li>Sample</li>
<li>Sample</li>
<li><a class="category_and_link" href="psy.html">Link to page or expand on + button</a>
<ul>
<li>Sample</li>
<li>Sample</li>
<li>Sample</li>
<li>Sample</li>
<li>Sample</li>
</ul>
</li>
<li>Fourth link</li>
<li>Fifth link</li>
</ul>
</li>
</ul>
<script type="text/javascript">
this.sitemapstyler = function(){
var sitemap = document.getElementById("sitemap")
if(sitemap){
this.listItem = function(li){
if(li.getElementsByTagName("ul").length > 0){
var ul = li.getElementsByTagName("ul")[0];
ul.style.display = "none";
var span = document.createElement("span");
span.className = "collapsed";
span.onclick = function(){
ul.style.display = (ul.style.display == "none") ? "block" : "none";
this.className = (ul.style.display == "none") ? "collapsed" : "expanded";
};
li.appendChild(span);
};
};
var items = sitemap.getElementsByTagName("li");
for(var i=0;i<items.length;i++){
listItem(items[i]);
};
};
};
window.onload = sitemapstyler;
</script>

See my fork of your jsFiddle. The basic idea is to grab the a element...
var a = li.getElementsByTagName("a")[0];
and add an event handler to it as well.
if (!a.hasAttribute("href"))
a.onclick = showHide;
For non-links, just leave out the href attribute.

Related

How to hide a menu when clicked on any menu-item?

I can not find where is the problem. Any idea about hiding on clicking any menu-item?
var button = document.getElementById("#1");
var menu = document.getElementById("#menu");
button.addEventListener('click', function(event) {
if (menu.style.display == "block") {
menu.style.display = "none";
} else {
menu.style.display == "block";
}
});
<ul id="menu">
<li>Home</li>
<li>Model S</li>
<li>Model 3</li>
<li>Model X</li>
<li>Model Y</li>
</ul>
You cannot get document.getElementById("#1") with #. getElementById is already an id selector, so you don't need to have #.
menu.style.display, you don't have inline styles for menu, your condition won't pass for the first time.
You also cannot have multiple id in your elements because id should be unique. In that case, you should use class instead (I added menu-item classes for element selectors)
I've tried to change your code with some comments
//get all menu items
var menuItems = document.querySelectorAll(".menu-item");
var menu = document.getElementById("menu");
for (const menuItem of menuItems) {
//add click events to menu items
menuItem.addEventListener('click', function(event) {
//hide menu if click on menu item
menu.style.display = "none";
});
}
<ul id="menu">
<li>Home</li>
<li>Model S</li>
<li>Model 3</li>
<li>Model X</li>
<li>Model Y</li>
</ul>

How do I change background color of each list item with JavaScript?

I'm struggling trying to change the background color of each item of a list when I move the mouse over it.
I have a list more or less like this:
<ul id="ul_menu">
<li>
Text
</li>
<li>
Text
</li>
<li>
Text
</li>
</ul>
I'm trying to do it with Javascript as the following:
var list = document.getElementByID("ul_menu");
var listItems = ul.getElementsByTagName("li");
function mouseOver() {
for (li in listItems){
li.style.backgroundColor = "yellow";
}
}
function mouseOut() {
for (li in listItems){
li.style.backgroundColor = null;
}
}
I'm generating this HTML code dynamically with XSLT from a XML file, so I'm unable to choose an specific ID for each list item.
Could you help me?
Thanks all.
If I'm reading this correctly (please let me know if I'm not), you just want to change the background color of the text when the mouse pointer hovers over a list item, correct?
If so, you can do this really easily with a little CSS:
.yellow:hover {
background-color: yellow;
}
<ul>
<li>
Text
</li>
<li>
Text
</li>
<li>
Text
</li>
</ul>
If you really want to use JavaScript, it's still possible, but you'll need to specify the width of the highlighted area. Try something like this:
function yellowa1(x) {
a1.style.backgroundColor = "yellow";
a1.style.width = "5px";
}
function yellowb2(x) {
b2.style.backgroundColor = "yellow"
b2.style.width = "5px";
}
function yellowc3(x) {
c3.style.backgroundColor = "yellow"
c3.style.width = "5px";
}
function nulla1(x) {
a1.style.backgroundColor = "transparent";
}
function nullb2(x) {
b2.style.backgroundColor = "transparent";
}
function nullc3(x) {
c3.style.backgroundColor = "transparent";
}
<body>
<ul>
<li onmouseover="yellowa1(this)" onmouseout="nulla1(this)" id="a1">a</li>
<li onmouseover="yellowb2(this)" onmouseout="nullb2(this)" id="b2">b</li>
<li onmouseover="yellowc3(this)" onmouseout="nullc3(this)" id="c3">c</li>
</ul>
</body>
Also, for future reference, be aware that an id is used to identify one element, whereas a class can be used to identify several. As well, Only the I in the Id part of the DOM method .getElementById should be capitalized, not both letters. And make sure that your <ul> element is defined.
#ul_menu li:hover{
background-color: yellow;
}
//Try using just CSS to achieve the result if you don't mind
<ul id="ul_menu">
<li>
<a href="#ref" title="go to ref" id="menu_selector" >Text</a>
</li>
<li>
<a href="#ref" title="go to ref" id="menu_selector" >Text</a>
</li>
<li>
Text
</li>
</ul>

JQuery on click <li> interference

Ok, the problem is a little hard to explain but I'll do my best.
when I click on one <li> element everyone else inside him is clicked.
I try to create categories and subcategories.but whenever I click on a category a subcategory is also called!
<li class="has-sub product_type" id="category1"> <a>Lorem1</a>
<ul>
<li class="product_sub_type" id="subcategory1"><a>Lorem2</a></li>
<li class="product_sub_type" id="subcategory2"><a>Lorem2</a></li>
<li class="product_sub_type" id="subcategory3"><a>Lorem2</a></li>
<li class="product_sub_type" id="subcategory4"><a>Lorem2</a></li>
</ul>
</li>
$(document).ready(function(){
var type_id = '';
$(".all_products").fadeOut("fast");
$(".product_type").on("click", function(event) {
alert("Dbg");
type_id = event.currentTarget.id;
$(".big_categoryes").fadeOut("fast");
$(".all_products").fadeIn("smooth");
sortProducts(type_id);
});
var type_sub_id = '';
$(".product_sub_type").on("click", function(event) {
type_sub_id = event.currentTarget.id;
sortSubProducts(type_sub_id);
});
});

Make all direct parent list entries selected in mmenu

I'm working on a project where I'm about to use the jQuery plugin mmenu (http://mmenu.frebsite.nl/).
I already had to do some customisations to fit my needs but I don't know what to do with my current issue. In mmenu, when i click on an list entry I will be navigated to the given href and the clicked item becomes active by mmenus css class ".mm-selected". So far so good.
Now I want to additionally mark the parent list item (and thats parent, and so on until menu root) as selected. This should be so when the user goes one level up in the menu he should be able to see in which category he currently is.
Below is an example of the menus html structure after mmenu was applied. This shows the code for a menu with 4 main pages (index, page1, page2 and page3) and 3 subpages (2.1, 2.2, 2.3).
<nav id="nav" class="mm-menu mm-horizontal mm-offcanvas mm-hasheader mm-current mm-opened">
<ul class="mm-list mm-panel mm-opened mm-current" id="mm-0">
<li class="mm-selected">
Index
</li>
<li>
Page 1
</li>
<li>
<a class="mm-subopen mm-fullsubopen" href="#mm-1"></a>
<span>Page 2</span>
</li>
<li>
Page 3
</li>
</ul>
<ul class="mm-list mm-panel mm-highest" id="mm-1">
<li class="mm-subtitle">
<a class="mm-subclose" href="#mm-0">Page 2</a>
</li>
<li>
Page 2.1
</li>
<li>
Page 2.2
</li>
<li>
Page 2-3
</li>
</ul>
</nav>
It would be great if you had some idea where and how I could achive such functionality.
So, for the moment I did some jQuery hacking. This seems to work for my case mentioned above. It should also work for deeper menus as it's using recursion. If there's a better way to achieve this, please let me know.
var nav = $("#nav");
nav.find("li > a:not(.mm-subopen)").click(function () {
nav.find("li.active").removeClass("active");
selectParentEntry($(this));
});
var selectParentEntry = function (a) {
var li = a.parent(),
ul = li.parent(),
back = ul.find("li > a.mm-subclose").first(),
cID = "#" + ul.attr("id"),
pID = back.length ? back.attr("href") : null;
li.addClass("active");
if (pID != null) {
var subOpen = nav.find("ul" + pID + " > li > a.mm-subopen").filter(function () {
var self = $(this);
if (self.attr("href") === cID) return self;
}).first();
if (subOpen) selectParentEntry(subOpen);
}
};

Keyboard navigation on nested list using only javascript

I have a ul list as follows. I am new to JS and trying to do a keyboard navigation, just the arrow keys using only javascript.
<ul id= nav>
<li class =subnav id =sub1> Companies
<ul id = hidden>
<li> item 1 </li>
<li> item 2 </li>
<li> item 3 </li>
</ul>
</li>
<li class =subnav id =sub2> LINKS
<ul id = hidden>
<li> item 4 </li>
<li> item 5 </li>
<li> item 6 </li>
</ul>
</li>
</ul>
my JS:
ul = document.getElementById("nav");
li = ul.getElementsByClassName("subnav");
ul2 = document.getElementById("hidden");
li = ul.getElementsByTagName("li");
function keyPress(e)
{
var e = e||window.event;
e =e.which||e.keyCode;
for( var i=0; i<li.length; i++)
{
var f = li[i].childNodes[0];
if(li[i].children.length > 0)
{
for(var j=0; j<li2.length; j++)
{
var x = li2[j].childNodes[0];
}
}
else
{
alert("no child nodes");
}
}
}
I am trying to set focus on the first item and then moving to each nodes using keys.
I suggest using jwerty, awesome keyboard events library.
I used jQuery and jWerty plugin.
Here is a quick JSFiddle: (Click the preview window and start hitting the down key)
http://jsfiddle.net/8QZrV/
As a basic idea, you should create an object with all the elements and then iterate through them, my basic example was like this:
var i = 0;
j = jQuery('.navigator li').length;
And then you hook it up in jwerty, I guess you want to make some actions there, so I guess you should also .focus() the current element.
Enjoy!

Categories