Make menu parent expand if child is currently active - javascript

I'm currently attempting to make a menu which is expandable when clicked, stays open, until a child is clicked, then user should be taken to that page, and the menu should still be expanded when that site is reached. (currently it collapses).
I have currently got the part down where i have a menu that expands and show childs when clicked. It's currently made in javascript. I'm making the menu with wordpress, and wordpress automatically adds class "current-menu-item" to the li which is being visited (if that helps).
var clickMenu = function() {
var getEls = document.getElementById("menu-shopmenu").getElementsByTagName("LI");
var getAgn = getEls;
for (var i=0; i<getEls.length; i++) {
getEls[i].onclick=function() {
for (var x=0; x<getAgn.length; x++) {
getAgn[x].className=getAgn[x].className.replace("unclick", "");
getAgn[x].className=getAgn[x].className.replace("click", "unclick");
}
if ((this.className.indexOf('unclick'))!=-1) {
this.className=this.className.replace("unclick", "");;
}
else {
this.className+=" click";
}
}
getEls[i].onmouseover=function() {
this.className+=" hover";
}
getEls[i].onmouseout=function() {
this.className=this.className.replace("hover", "");
}
}
}
window.addEventListener("load", clickMenu);
Now I'm just looking for help making it stay expanded once new page is loaded.
Also, will these two functions make a conflict in the design?

You can just check 'parent' of current-menu-item element. And apply display:block or any other css which makes menu element visible.
check below code if it meets your requirements.
$(document).ready(function(){
$(".current-menu-item").parent("your_parent_ul_div").css("display": "block");
});
ref-https://api.jquery.com/parent/
ref->Expand parent menu if child menu is selected
ref->https://webdesignerhut.com/active-class-navigation-menu/

Related

How to change the class of several items and how to make the navbar update according to the page scroll?

This is for a navbar.
The "active" class makes the background of the item in the navbar become darker.
And yes, I made the navbar with "div" instead of "ul".
This code of mine is an attempt, whenever an item in the navbar is selected (and its background is made darker), the other selected items pass their class to "unactive".
The code works perfectly when I don't try the "unactive" part, but doing so it just makes everything I click active.
I would like help with this.
Furthermore, I would like to know how to make the navbar update the parts that are selected according to where I am on the page. Ex.: I am in the voting section and I move to the sponsors section. How do I make the navbar automatically select the session I'm in?
thanks for any help!
HTML
<div class="navigation-header" id="navigation-header">
Votação
Patrocinadores
Redes Sociais
Créditos
</div>
JAVASCRIPT
var navbars = document
.querySelector(".navigation-header")
.querySelectorAll("a");
navbars.forEach(function (item) {
item.addEventListener("click", function (e) {
let classe = this.getAttribute("class");
if (classe != "active") {
navbars.forEach(function (navitem) {
let classe = this.getAttribute("class");
if (classe === "active") {
this.classList.remove(classe);
this.classList.add("unactive");
}
});
this.classList.remove(classe);
this.classList.add("active");
}
});
});
I don't know if I understood well what you need, Check this please and tell me:
var navbars = document
.querySelector(".navigation-header")
.querySelectorAll("a");
navbars.forEach(function (item) {
item.addEventListener("click", function (e) {
let classe = e.target.getAttribute("class");
if (classe != "active") {
navbars.forEach(function (navitem) {
let classe = navitem.getAttribute("class");
if (classe == "active") {
navitem.classList.remove(classe);
navitem.classList.add("unactive");
}
});
e.target.classList.remove(classe);
e.target.classList.add("active");
}
});
});
a.active {
background: #ee0;
}
<div class="navigation-header" id="navigation-header">
Votação
Patrocinadores
Redes Sociais
Créditos
</div>

Dropdowm menu in Vanilla JavaScript - for unknown number of buttons

please, can you give me a hint with Vanilla JS?
I have dropdown menu opening via button click and have 2 issues:
1) Dropdown is opening by clicking on button with unique ID. I need to get it working on Class name, because it have to be working on multiple buttons - and the number of them is unknown (they will load from REST API).
In jQuery is it working, but I need it in Vanilla JS.
If I try to select button by Class name, it will return array of buttons, but I don't know how to select from array, which button was being clicked on.
2) Dropdown menu is opening only on the second click on the button (and then it is toggling like it should), but the first click doesn't do anything.
My code is here:
// select Button - now by ID - but I need unknown number of buttons - from REST API - and the code working for all of them
var btn = document.getElementById("dropBtn1");
// select Dropdown menu - next to the button - to be sure it will open the right menu no matter which button will be pressed
var menu = btn.nextSibling;
while(menu && menu.nodeType != 1) {
menu = menu.nextSibling
}
//toggle dropdown menu open/close
btn.addEventListener("click", function() {
if (menu.style.display == 'none') {
menu.style.display = 'block';
}
else {
menu.style.display = 'none';
}
});
And working prototype is here on Codepen:
https://codepen.io/vlastapolach/pen/EXdLMy
Please, do you have any ideas how to fix this?
Thank you!
Quite easy, you need a general function that works on the context (=this):
//toggle dropdown menu open/close
function toggle() {
var btn=this;
var menu = btn.nextSibling;
while(menu && menu.nodeType != 1) {
menu = menu.nextSibling
}
if(!menu) return;
if (menu.style.display != 'block') {//fix 2)
menu.style.display = 'block';
} else {
menu.style.display = 'none';
}
});
Now you can assign this functions as an event handler onto all your elements:
window.addEventListener("DOMContentLoaded",function(){
document.querySelectorAll(".sth").forEach(function(btn){
btn.addEventListener("click",toggle,true);
});
});
Note that NodeList.forEach is quite new, may use [].slice to create a real array...
And you need to assign the Handlers to the newly added elements manually, or you need to listen on window and trace back the target:
window.onclick=function(event){
if(event.target.classList.contains("sth")){
toggle.call(event.target);
}
};

Remove Class when current toggle is clicked

The title is a bit of a tongue twister. A brief description of the fiddle, is that it's a toggle style accordion where the toggle state changes color when one of the divs is toggled. I've got it working to where if another div is toggled it will close that previous div and open the new div while changing the toggle state.
The issue I am running into is if a user wants to close the current toggle without clicking a different div it will close the current toggle but not change the toggle state back to it's original state. I am currently using this and have tried multiple things including if the container 'is: visible' or hasClass then to remove the toggle class, but nothing seems to work. I've also tried a different slideToggle function, but of course that applied it to the toggled element I've found.
Fiddle: http://jsfiddle.net/NFTFw/1256/
What I am trying to do?
I want the current toggle class to change back to its original state if the user clicks the current toggled div or clicks another div. So essentially I want the user to have either option.
CODE:
$(document).ready(function () {
$('.column').each(function (index) {
$(this).delay(750 * index).fadeIn(1500);
});
$('.column').hide();
$('.body').hide();
$('.column').each(function () {
var $toggle = $(this);
$('.toggle', $toggle).click(function () {
$(".toggle").removeClass("toggle-d");
$(this).addClass('toggle-d');
$body = $('.body', $toggle);
$body.slideToggle();
$('.body').not($body).hide();
});
});
});
Check to see if the thing that you're clicking already has the class. If so, remove it, if not, add it. I suspect the problem you were having with hasClass() is that you were attempting to check the wrong this.
Oooh I did a bad thing and didn't remove the class when a new div was clicked. I've fixed that and updated the jsfiddle
jsfiddle
js:
$(document).ready(function () {
$('.column').each(function (index) {
$(this).delay(750 * index).fadeIn(1500);
});
$('.column').hide();
var width = $(window).width();
if (width <= 600) {
$('.body').hide();
$('.column').each(function () {
var $toggle = $(this);
$('.toggle', $toggle).click(function () {
if($(this).hasClass('toggle-d')){
$(this).removeClass("toggle-d");
}
else{
$('.toggle').removeClass('toggle-d');
$(this).addClass('toggle-d');
}
$body = $('.body', $toggle);
$body.slideToggle();
$('.body').not($body).hide();
});
});
}
});
What i would suggest is to pass the element itself in the function
in the index.html Do this
<a class = 'classname' onclick = toggle(this)>
Your Content Here
</a>
After that in the script.js
what i am saying is in javascript, i believe you can easily convert it to jquery
function toggle(value){
if(value.className == 'the predefined value'){
value.className = value.className + ' Your new class addition'
// remember there should be a space if you are adding an additional class to the present class, else directly change the classname
}
else{
value.className = 'the predefined value'
}}
this will toggle your classname whenever the element is clicked

Showing and hiding items in Windows 8 application

I'm writing my first Windows 8 application, but I'm stuck already.
What I want to do is display an html/winjs element, depending on which index is clicked in a listview.
The current code I've written works to some extent. It will display the first element (albumListView), but after that no other items will show. I've read through the WinJS docs, but I still can't figure out what I'm doing wrong.
What am I doing wrong? And is there an easier way to do what I'm trying to achieve?
Here's the code I've written:
My html:
<div id="albumListView" class="hidden" data-win-control="WinJS.UI.ListView" data-win-options="{itemTemplate:select('#albumTemplate'), layout:{type:WinJS.UI.GridLayout}, selectionMode:'none'}"></div>
<div id="songsListView" class="hidden" data-win-control="WinJS.UI.ListView" data-win-options="{itemTemplate:select('#songsTemplate'), layout:{type:WinJS.UI.ListLayout}}"></div>
My CSS:
.hidden {
display:none;
}
My JS:
function hidePanelViewItems() { //hide all panel items
var items = [albumListView, songsListView];
for (var i = 0; i < items.length; i++) {
WinJS.Utilities.addClass(items[i], "hidden");
}
return true;
}
function showItem(item) { //show a single item in the panel
hidePanelViewItems();
WinJS.Utilities.toggleClass(item, "hidden");
return true;
}
args.setPromise(WinJS.UI.processAll().done(function () {
//hide all panel listviews
hidePanelViewItems();
//show the album view as a default
showItem(albumListView);
//deal with menu item clicks
menuListView.addEventListener("iteminvoked", function (eventInfo) {
switch (eventInfo.detail.itemIndex)
{
case 0:
showItem(albumListView);
break;
case 1:
showItem(songsListView);
break;
}
});
}))
Thanks in advance for any replies :)
I ran into something similar. If you set a listview's style to display:none, you need to call forceLayout() to make it visible again. http://msdn.microsoft.com/en-us/library/windows/apps/hh758352.aspx
Solved! After hours of messing around with this code, I have now discovered that it was fine all along! The problem was that data wasn't actually binding to my listviews, as they were hidden!

more concise jquery for multi button controlling visibility of same div

I have 3 buttons that control the visibility of 1 div.
we want to do following to div:
show the first time any of three buttons are clicked
show if button clicked is different to previously button click
hide if button clicked is the same as previous clicked and if div is currently visible
show if button clicked is the same as previous clicked and if div is currently invisible
currently I have this:
//$('#alert_area') = target div
$button = $('.button')
if ($button.attr('id') != $('#alert_area').attr('showing')){
$('#alert_area').show()
}else{
if ($('#alert_area').is(":visible")){
$('#alert_area').hide();
}else{
$('#alert_area').show();
}
}
$('#alert_area').attr('showing', $button.attr('id'))
It's only a slight improvement, but you can replace your else block with toggle. You can also cache your selector to neaten things up.
var $button = $('.button'), $alertArea = $("#alert_area");
if ($button.attr('id') != $alertArea.attr('showing')) {
$alertArea.show()
} else {
$alertArea.toggle();
}
$alertArea.attr('showing', $button.attr('id'));

Categories