Appearance of a selected menu item in master page - javascript

I have a web application with one master page that contains the menu, and several .aspx pages. The menu is something like https://jsfiddle.net/96bd8y0z/
<style>
a, a:visited { color:black }
a.link.active { color:blue; }
<style>
<script>
$(function () {
$('a.link').click(function () {
$('a.link').removeClass('active');
$(this).addClass('active');
});
});
<ul>
<li>Home</li>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
It works fine in the fiddle: When you select one of the links in the menu, its appearance changes, in the fiddle from black to blue. But when I try to apply this scheme in my web application, the link that I select (say: 'News') becomes blue for a second, the hyperlink page ('News') is loaded, 'News' becomes black again, and the the menu entry 'Home' becomes blue again.
I can understand that this happens because the master page section is re-loaded but I don't know how to solve it.
Is there a way to keep the selected option active (i.e. keep 'News' blue)?
I believe this question is similar to How to make menu by using Master Page with jquery?, but the user that answered this question found this question unclear and his answer did not solve it for me.

It probably would be better to do it in the back-end: keep a variable in aspx that specifies in which page you are, and then in the master page, compare that variable for each menu, and add the "active" class only to the one that you want.
If you want to do it with JavaScript, you could do one thing: when the link is clicked, save the index of the menu element, then when the page is reloaded, mark that element as the active one.
Something like this:
$(function() {
$('a.link').click(function() {
$('a.link').removeClass('active');
$(this).addClass('active');
// save the index for later (notice it's the index of the li, not the a)
localStorage.setItem("active", $(this).parent().index());
});
// read the previous index or initialize to the first one if first time
var active = localStorage.getItem("active") ? localStorage.getItem("active") : 0;
// add the active class to the element
$("ul li:nth-child(" + (parseInt(active)+1) +") a").addClass("active");
});
You can see it working on this JSFiddle: https://jsfiddle.net/96bd8y0z/6/ (rerun or reload the page to see how the blue link remains). But again, doing it in the back-end would be better.

Well, menu is re-rendered on each page request, it`s evident that all classes added on previous page opening would disappear.
So, in order to make needed menu item selected, there should be a check for every link: if it`s href attribute is equal to the route of the loaded page, then add "active" class to it.
Meanwhile, it`s a bad practice to do it with javascript, better do it while building template. But if it has to be done with js, you probably can do something like this (using jquery for links selection):
$(function() {
var links = $('.link');
for (var i = links.length; i--;) {
var _this = $(links[i]);
if (document.URL.split('http://site-domain.net')[1] == _this.attr('href')) {
$('.link').removeClass('active');
_this.addClass('active');
}
}
});
Here is the fiddle example:
https://jsfiddle.net/96bd8y0z/4/

Related

How do you add a span element inside an '<li></li>' menu item in wordpress?

If an li has class menu-item-has-children then insert a span element inside of it with an id of 'menu_toggle[x]' where 'x' will increment depending on the number of id's that already exist named 'menu_toggle[x].
Im basically trying to get the static html version of a menu working correctly on wordpress for mobile.
This is a screenshot of the static html and css of what I'm gunning for in my wordpress menu (which btw is identical, using the same css (slightly modified) but has lost the '+' menu_toggle classes which I'm trying to re-create and add in my wp menu now).
In my wp version, everything works except when i hide the first ul dropdown (display:none) as I wish to only reveal it via click event using jquery code.
What is the best way to go about this, without 'over engineering' or 'over complicating' this ? I just want the easiest hassle free approach thanks.
You can use script like this:
var clickable = $('.mbnav__state').attr('data-clickable');
$('.mbnav li:has(ul)').addClass('has-sub');
$('.mbnav .has-sub>a').after('<em class="mbnav__caret">');
if (clickable == 'true') {
$('.mbnav .has-sub>.mbnav__caret').addClass('trigger-caret');
} else {
$('.mbnav .has-sub>a').addClass('trigger-caret').attr('href', 'javascript:;');
}
/* menu open and close on single click */
$('.mbnav .has-sub>.trigger-caret').click(function () {
var element = $(this).parent('li');
if (element.hasClass('is-open')) {
element.removeClass('is-open');
element.find('li').removeClass('is-open');
element.find('ul').slideUp(200);
}
else {
element.addClass('is-open');
element.children('ul').slideDown(200);
element.siblings('li').children('ul').slideUp(200);
element.siblings('li').removeClass('is-open');
element.siblings('li').find('li').removeClass('is-open');
element.siblings('li').find('ul').slideUp(200);
}
});
https://prnt.sc/1qyjcq8

How can I change the background color of a current page's navigation button/link using JavaScript?

I want to write a JavaScript script (not JQuery, if at all possible) that changes the background color of a navigation button when its page is active. In other words, when I click on the "About" link and load the page, I want the "About" button to have a different background color so the user can see which page s/he is on.
Here is my HTML for the navigation links:
<nav>
<ul class="navbar">
<li class="navbutton">About</li>
<li class="navbutton">Local services</li>
<li class="navbutton">Intercity Services</li>
<li class="navbutton">Transport Circle Overview</li>
<li class="navbutton">Feedback</li>
</ul>
</nav>
Here is the CSS rule I want to apply when the page is active:
.navbutton-active {
background-color: rgb(24, 99, 6);
So far I've come up with this script although it isn't doing much except throw up an error:
document.getElementsByClassName('navbutton').addEventListener("DOMContentLoaded", btnActive());
function btnActive() {
document.getElementsByClassName('navbutton').classList.add('navbutton-active');
};
This is the error I get in the console:
TypeError: document.getElementsByClassName(...).classList is undefined
The behavior I'm aiming for is the following:
The page loads and the corresponding navigation button background changes to the color I've specified in the .navbutton-active CSS declaration.
When the user clicks on another navigation button, the color of the active page's navigation button changes to this color and the other navigation button colors remain their default.
This is probably simple but I can't figure it out.
I think the first step would be to find out which link is the one with an href property that matches the current URL.
// Obtain a collection of all links
var buttons = document.querySelectorAll('.navbutton');
var activeButton, button, link, i;
// Iterate through each link to find if its href matches the URL
for (i = 0; (button = buttons[i]); i++) {
link = button.firstElementChild;
// a console.log(link.href, window.location.href)
// might be useful here to ensure the comparisons will work
if (link.href === window.location.href) {
activeButton = button;
break;
}
}
// If a matching link was found, add the active class
if (activeButton) {
activeButton.classList.add('navbutton-active');
}
This URL comparison step isn't foolproof, and might need improvement. Really this should be done server side if you can.
Also the error in your original example is caused because getElementsByClassName() returns an array-like collection, which you would need to iterate through before interfacing with the classList property on the individual elements (similar to querySelectorAll() in my solution, but this is the newer API).
function btnActive()
{document.getElementById("navbutton").className = "navbutton-active ";}
also check if btnActive() is actually called by using alert("testing control"); in above function

Getting a prev/next | first/last button to work with list.js

I am building a paginated index with search. I have the index paginated and working, however I want to add a prev/next and a first/last button because this has to be scalable.
List.JS does not seem to have one of these out of the box, so I tried to do it by appending/prepending the lis into the pagination div ul. This does work, except for after click they are removed.
Adding into pagination div
$('.pagination').prepend('<li class="btn-next"> 9 </li>');
$('.pagination').append('<li class="btn-prev"> 0 </li>');
Functions to run the buttons
$('.btn-next').on('click', function(){
var list = $('.pagination').find('li');
$.each(list, function(position, element){
if($(element).is('.active')){
$(list[position+1]).trigger('click');
}
})
})
$('.btn-prev').on('click', function(){
var list = $('.pagination').find('li');
$.each(list, function(position, element){
if($(element).is('.active')){
$(list[position-1]).trigger('click');
}
})
After this, Im not sure how I can even get them to stay appended since it seems to rewrite it on click every time. Has anyone else created these buttons using List.JS?
Here is my fiddle.
The problem is the plugin reloads the html every time you change the page, one option to avoid modify the plugin will be create an extra container and style your elements to be next other.
The HTML will be like:
<div class="nav">
<ul class="pagination">
</ul>
</div>
And then append your buttons:
$('.nav').append('<div class="btn-next"> > </div><div class="btn-last"> >> </div>');
$('.nav').prepend('<div class="btn-first"> << </div><div class="btn-prev"> < </div>');
Updated Fiddle
Still searching how to trigger first and last page
For First and Last elements use the show() function:
$('.btn-first').on('click', function(){
monkeyList.show(1,1)
})
$('.btn-last').on('click', function(){
monkeyList.show(monkeyList.size(),1)
})
Updated Fiddle 2

Wordpress dropdown menu - ajaxify plugin removes class 'current-menu-item' from menu items. Is there a way around this?

I'm setting up a WP-page for a client. I have a dropdown menu and the primary menu item is an unclickable link that says "MENU". On every subpage, I need the title of the subpage to display where it usually (only on the startpage) says "MENU".
I've been able to accomplish this with this code that my theme support helped me with:
(function($){
var title = '';
$('.menu-item').each(function(){
if( $(this).hasClass('current-menu-item')){
title = $(this).find('span').text();
}
});
if(title){
$("#menu-item-36 > a span").text(title);
console.log(title);
}
})(jQuery);
#menu-item-36 is the ID for the primary menu item - "MENU".
The problem is that I also need the pages to load smoothly without reloading the header on every page. So I'm using a plugin called Ajaxify Pro that works great for doing this, BUT Ajaxify removes the class 'current-menu-item' from the active menu item, so my code doesn't work any longer.
Is there a way around this? The active/current menu item in the submenu doesn't get any class different from the other items in the menu, so I'm twisting my head around a way to solve this.
Any help would be much appreciated!
Here you can see the page with Ajaxify activated and the code not working: http://test.frankochrakel.se/
As I see the menu always has the ID of menu-item-36 is it your ID ?
Anyway as I see the selected menu has a current_page_item class, so just find it like that:
(function($){
var title = '';
title = $('#menu-item-36').find('.current_page_item').text()
if(title) {
$("#menu-item-36 > a span").text(title);
console.log(title);
}
})(jQuery);

Link changing class of parent <div>, content of two <iframe> elements

Interesting (and rather complex) issue here...
What I have is a page with two iframes and a set of links at the top, each contained inside a div with an image background. What I want is for the contents of both iframes to change (to two separate html documents) when the link is clicked, and for the background image of the link's parent div to also change. I also, however, want the parent div to automatically change back to the original class when a different link is clicked (i.e. I have two classes, 'active' and 'waiting'. When a link is clicked (and its contents subsequently displayed in the iframes) I want it to switch to class 'active'. At all other times, though, (including after a different link might be clicked and become active) I want it to go back to using the 'waiting' class.)
Here's my current code / markup:
Javascript:
function changeFrame(link) {
$('#first iframe').src=link.href;
$('#second iframe').src= (Here would be the second link, not sure how to define that)
link.ParentNode.addclass("activebutton");
HTML:
<div class="waitingbutton">
<a href="yes.html" (Somewhere here would be the second link for the second iframe) class="waitingbutton" onclick="changeFrame(this);
return false;">Button Text</a>
</div>
(After this come four more divs, each identical bar Button Text and links)
As I suspect you can tell, I'm really just guessing here. Still not hugely familiar with Javascript, hoping someone can help me out.
You seem to be using jQuery.
Here's an ugly way to do it; but it works:
Button Text
And your JavaScript:
function changeFrame(link) {
$('#first iframe').attr("src", $(link).attr('href'));
$('#second iframe').attr("src", $(link).attr('secondary-href'));
return false;
}
Note that it'd be more idiomatic jQuery to do this without any onClick handlers, but simply initialise it all in your <head>/<script> from the beginning:
<script type="text/javascript">
$(function() {
$("a.iframe-link").click(function(event) {
$("#first iframe").attr("src", $(link).attr("href"));
$("#second iframe").attr("src", $(link).attr("secondary-href"));
// Whatever used to be the activebutton, make it 'waitingbutton', and remove
// the 'activebutton' class.
$(".activebutton").
addClass("waitingbutton").
removeClass("activebutton");
// Remove .waitingbutton from this, add .activebutton.
$(this).removeClass("waitingbutton").addClass("activebutton");
// Don't allow the link's default action (to follow the href in the normal
// way).
event.preventDefault();
});
});
</script>
Then later:
<a class="iframe-link waitingbutton" href="yes.html" second-href="whatever.html">Hello!</a>

Categories

Resources