Two navbars generated from vue-router, active-class highlighting only one link - javascript

I have two sections with navigation like this:
<ul class="navigation-list">
<li v-for="(route, index) in navRoutes">
<router-link :to="route.path">
<span>{{ route.name }}</span>
</router-link>
</li>
</ul>
and then:
<div class="burger-navbar" v-show="showBurgerMenu">
<ul>
<li v-for="(route, index) in navRoutes" #click="closeBurger">
<router-link :to="route.path">
<span>{{ route.name }}</span>
</router-link>
</li>
</ul>
</div>
in my css i declared .router-link-active{ color: white;}.
What I expect is when I visit the page with url for e.g. '/about', then About link is white. What happens - only link in the second navigation is changing its color. The first one remains black.
How can I apply router-link-active class to both navigations at once? The reason I'm using two navbars - one for normal view, one for RWD (hamburger dropdown)
Thanks.

You could consider refactoring your code and using scss to change the style of your router links based on the viewport size. That way you only need to have one set of router links and the active one will highlight correctly
for example
.my-menu-style {
// burger style menu here
#include media-min($breakpoint-medium) {
//menu style normal menu
}
}
Also, you are using v-show which just hides the code in the DOM, you might find that if you use v-if to toggle between burger menu and normal menu it solves your problem as this actually adds abd removes the html from the DOM. You will then only have one set of router links in your html at one time

Related

How to append a bootstrap dropdown with a div based on ID?

In my angular, I have a dropdown component. Here is how it looks like:
<div dropdown placement="bottom left" #dropdown="bs-dropdown" [autoClose]="true"
[insideClick]="true" [container]="body">
<a class="templates-icon" dropdownToggle (click)="toggleTextTemplates();">
<i #one class="ic-text-templates" aria-hidden="true"></i>
</a>
<ng-container *ngIf="toggle" >
<div *dropdownMenu class="templates-container dropdown-menu"
role="menu" aria-labelledby="button-basic">
</ng-container>
</div>
Here in this example, container attribute is set to body and therefore the dropdown is bind with the body and visible top of each element.
Now let say I have three layer in my app. Layer-one, layer-two and layer-three and they are top of each other. Now I would like to display the dropdown only on layer-two (or imagine in middle layer). So I would like to bind this dropdown with layer-two based on id, so that drodown will be visible on top of layer one and two, but not the layer three:
<div id="layer-one">
some element 1
<div id="layer-two">
some element 2
<div id="layer-three"> some element 3</div>
</div>
</div>
Can someone please give me an idea, or solution how I can achieve that?
Have you tried to just place the dropdown at layer 2? otherwise you can can use javascript like: getElementByID('#33').innerhtml
or make CSS index rules, where there is a attribute called index: (-1) or (1) etc. for the placement of the dropdown

Vue.js: Use aria-controls with conditional rendering in vue.js

I have two buttons which toggle some additional information on screen.
I added the buttons the aria-controls attribute und I render an id for the infobox.
Now I still get an error, when I validate the html, because I show this infobox only if a variable in the vuex store is true.
I render it with v-if.
So that means if the button was not clicked the element is not in the DOM and therefore the corresponding id is missing and I get an error.
I tried to use v-show because this would only hide it.
But this would still only render one infobox instead of 2.
Is the only way to get this right to make two infoboxes in the template and add the v-show to both? Or is there a nicer way to use aria-controls.
Thanks for any help
Best
m
Edit:
These are my buttons which have aria-controls.
<template>
<div>
<ul v-if="nav.items">
<li
v-for="(item, key) in nav.items"
#keyup.esc="closeInfoBox">
<button to="" aria-controls="item.name" aria-expanded="false">Designathon</button>
</li>
</ul>
</div>
</template>
And this is my infobox component:
<template>
<div class="Infobox" v-if="infoboxOpen" id="//should correspond to aria controls">
<span v-html="infoContent">Some content</span>
</div>
</template>
Which is only shown if infoboxOpen === true (from vuex store) and the content is replaced depending on which of the buttons is pressed.
(I left out some of this stuff, to make the code easier to understand and to focus on my question here).
This is where I could replace the v-if with the v-show but that would still render only one content. And I would like to have it as dynamic as possible, because users can add more infoboxes in the backend...
Hope this helps understanding my issue.
You're almost there, just make aria-controls a dynamic attribute using
:aria-controls="infoboxOpen ? item.name : ''":
<template>
<div>
<ul v-if="nav.items">
<li
v-for="(item, key) in nav.items"
#keyup.esc="closeInfoBox">
<button to="" :aria-controls="infoboxOpen ? item.name : ''" aria-expanded="false">Designathon</button>
</li>
</ul>
</div>
</template>

Metro UI CSS: How to achieve class="active" effect?

In bootstrap there is a nice css class 'active' to apply to menu elements to indicate on which page a user is.
I assume it will work the same in metro ui but I was wrong
<ul class="app-bar-menu" data-bind="foreach: router.navigationModel">
<li data-bind="css: { active: isActive }">
<a data-bind="attr: { href: hash }, text: title"></a>
</li>
</ul>
The above code (uses Durandal's router) does not make menu items stand out, even if I explicitly set the class without these bindings.
Is there a similiar mechanism in Metro UI CSS for appbar or horizontal menu?
If not, how can I achieve it?
EDIT
I found out that class="active" successfully works with lower level menu items but what about the top level?
I didn't find solution other than to add css override. For app-bar this would be
.app-bar-menu > li.active {
background-color: #005696;
}
If you use non-default colors you'll have to do it specifically for your case, e.g. green:
.app-bar.green .app-bar-menu > li.active {
background-color: #128023;
}

HTML + jquery - menu to change contents in the content DIV

I've been digging around on how to do it, but didn't find any solution which would fulfill my needs.
Got a basic layout of my page with menu on the left, separate div for header and a div in the middle where all the content should be displayed when one of the menu buttons is selected.
I'd like to change the content only of the "content" div dynamically without reloading the page when one of the menu buttons is pressed.
I've managed to do it as per below with jquery:
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
$('#nav ul li a').click(function(){
$('#main').load('contents.html #' + $(this).attr('href'));
return false;
});
});
The menu :
<nav id="nav">
<ul class="menu">
<li class="menu1"></li>
<li class="menu2"></li>
<li class="menu3"></li>
<li class="menu4"></li>
<li class="menu5"></li>
</ul>
</div>
</nav>
contents.html file sample:
<div id="menu1">
<h2>Menu1</h2>
<p>Menu1 page contents</p>
</div>
So when menu1 button is pressed I'm able to change the content of main div to reflect the relevant data - this works.
My questions are:
1) is this the correct way on how to do it ? If not what would you recommend ?
2)I want to display more advanced stuff not only text (e.g What if I want to have another jquery in the div-id="menu1" ? I've tried it and it didn't work.)
P.S - I'm just a beginner so maybe I've missed something basic - but couldn't fix it by myself.
Thanks in advance!
Peter
I think there are a number of ways to achieve what you want. It depends on the nature of the content you want to load.
If there isn't masses of it, you could load it all onto the page on page load within different div's and then just show and hide the relevant div when clicking the menu items. (have a look at twitter bootstrap for some implementations, things like tabbed browsing).
If you do just have text, you could use ajax to load in the data from an external file w3schools.com.
Alternatively as mentioned in a comment above, you could create a single page application using something like angular.js, knockout.js etc.
Hope that helps.

JQuery - setting an "active" class for image-scroll

I have content loading dynamically (using new WP_query loop in WordPress) for a jQuery carousel or image-scroll function -- where the image-scroll is a li list of images, styled to look like a strip of images.
When the image-scroll works properly, one of the images in the li tag has a class of active, which expands the image and makes it look like it's in front of the other images,
... and as the user clicks through this strip of images, the active class changes/moves to the targeted li tag, expanding that image.
What's happening is that none of the li tags are active when the page loads - since the content is dynamic through the WP loop (I didn't want all of the li tags to start with the active class, so I didn't add it to the loop),
...and so the images are just lined up in a consistent strip w/o one of the images being expanded (or having that active class).
It is only if the user happens to click on one of the images that it expands,
...but i need one of the images to be expanded (to have the class of active) before the user clicks so I need the active class added as/after the page loads.
I have tried through the jQuery code to target one of the li tags to add the active class, using filter() or closest() after the page loads, but that didn't work.
Or maybe I should write a new script to add the active class?
Any help much appreciated!
I have the abbreviated html and the jQuery function below.
_Cindy
ps as the code indicates, I also have corresponding article titles that scroll with the images, so perhaps I need to adjust the jQuery there, too.
<div class="articles-scroll">
<ul class="images-scroll">
<li><!-- I need only one of these tags to have a class of active to start -->
<a href="#">
<span class="set-image-border" style="float: none;">
<img class="setborder" src="image-set-by-new-wp_query">
</span>
</a>
</li>
<li>
<a href="#">
<span class="set-image-border">
<img class="setborder" src="image-set-by-new-wp_query">
</span>
</a>
</li>
</ul>
<div class="clear-float"></div>
<!-- in this section of html one of the article titles is active to coordinate with the active li image above to produce a corresponding clickable title, this works, but once again, only when user clicks on an image to begin the jQuery image-scroll function -->
<div class="wrapper">
<ul class="images-content">
<li>
<div class="article-header">
<h2>
<a href="link-set-by-new-wp_query">
</h2>
</div>
</div>
</li>
<li>
<div class="wrapper">
<div class="article-header">
<h2>
<a href="link-set-by-new-wp_query">
</h2>
</div>
</div>
</li>
</ul>
</div>
jQuery(".images-scroll li a").click(function() {
jQuery(this).parent().parent().find("li").removeClass("active");
// tried the following instruction as well as on next line, but no go
// jQuery(this).parent().parent().closest("li").addClass("active");
jQuery(this).parent().addClass("active");
jQuery(this).parent().parent().parent().find(".images-content > li").removeClass("active");
jQuery(this).parent().parent().parent().find(".images-content > li").eq(jQuery(this).parent().index()).addClass("active");
var step = ((-250)*(jQuery(this).parent().index()-1))-60;
//alert(step);
jQuery(this).parent().parent().css("margin-left", step+"px");
return false;
});
The reason why the code you wrote didn't work is that you have it inside a click handler, so nothing happens until you click one of the targeted elements. If you want something to happen on page load you can use $(document).ready() (can be shortened as $()) or $(window).load(). Just add the following lines below or above your existing code.
jQuery(function(){
var $listItems = jQuery('.images-scroll li');
$listItems.first().addClass('active');
// Second list item
$listItems.eq(1).addClass('active');
// Third list item
$listItems.eq(2).addClass('active');
});
Also, please note that (unless it conflicts with a different plugin), writing $ is shorter than jQuery, and it should do the same.

Categories