Menu: animation open/close - css

When I open and close a menu item, there is no animation. I would like to know how to create an animation, please?
HTML file
<div class="wrapper">
<!-- Top Menu -->
<div class="sidebar">
<!-- Menu Item -->
<ul>
<li
*ngFor="let menu of menus; let i = index"
[class.active]="menu.active"
>
<ng-container>
<a class="item" (click)="selectMenu(menu)">
<i [class]="menu.iconClass"></i> {{ menu.name }}
<i class="fa fa-chevron-down"></i>
</a>
<ul *ngIf="menu.active">
<li *ngFor="let submenu of menu.submenu" class="submenu">{{submenu.name}}</li>
</ul>
</ng-container>
</li>
</ul>
</div>
</div>
I don't know if it's possible to do it in Angular or CSS? I made you a reproduction of the project => Stackblitz.

the easer is using Angular animations. add this animation to your component
animations:[
trigger('accordion', [
transition(':enter', [
style({ height: 0 }),
animate('1000ms', style({ "height": '*' })),
]),
transition(':leave', [
animate('100ms', style({ "height": 0 }))
])
]),
]
See that, when "enter" start with style:height=0 and animate to reach style:height=* (the * main that reach the "normal" height) and you use "leave" to animate and change the style to "height=0".
Then just use
<ul #accordion *ngIf="menu.active">
<li *ngFor="let submenu of menu.submenu" class="submenu">
{{submenu.name}}
</li>
</ul>
NOTE1: don't forget import the BrowserAnimationsModule in your module
NOTE2: You need add to your .css
.wrapper ul li ul{
overflow:hidden;
}
Your forked stackblitz

I think you should change app.component.ts like this.
selectMenu(parentMenu: { name: string, active:boolean }): void {
this.menus.forEach((menu) => {
if (menu.name === parentMenu.name) {
menu.active = !menu.active;
}
});
}
}
because Each time active is pressed, the boolean value should change.
have a nice day:)

Related

How to apply style in angular6

I want to apply text color when expected id will clicked
<nav class="navbar ">
<ul class="navbar-nav">
<li *ngFor="let item of items">
<a class="nav-link" >{{item.title}}</a>
</li>
</ul>
</nav>
items=[{id:1,title:"a"},{id:2,title:"b"},{id:2,title:"c"},{id:3,title:"d"}]
controller-
private name;
this.routes.params.subscribe((params)=>{
this.data=params['id'];
console.log(this.data);
})
this.Service.getAllItems().subscribe((data)=>{
this.items=data;
for(let i of this.items){
if(i.id == this.data){
this.name=i.title;
}
}
For clicked id I have to apply text color red.How to apply it.Please help
You could have a variable with the active id, which is set when you click:
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public activeId;
setIdActive(id) {
this.activeId = id;
}
}
And in your html:
<nav class="navbar ">
<ul class="navbar-nav">
<li *ngFor="let item of items">
<a (click)="setIdActive(item.id)" class="nav-link" [ngClass]="{'apply-color': item.id == activeId}" >{{item.title}}</a>
</li>
</ul>
</nav>
apply-color it's a class with the color you want
This answer caters to condition where we need to highlight all the options which are clicked
If you want to change the color of all the links which are clicked and not just the last one, I advise you to use a HostListener directive.
consructor(privte elem: ElementRef, private renderer: Renderer) { }
#HostListener('click',['$event']) //in your case, the event parameter can be omitted
Click(event: Event) {
this.renderer.setElementStyle(elem.nativeElement, 'color', 'red');
}
And if just the CSS style for a:visited works for you (not tried by myself), it would be the best solution
You can you [ngClass] for this problem. When you click the link pass the item to the function. this will change the activeId. By using [ngClass] the class will apply to the link.
let activeId:number;
makeALinkActive(item){
this.activeId = item.id;
}
items=[{id:1,title:"a"},{id:2,title:"b"},{id:2,title:"c"},{id:3,title:"d"}]
.red{
color: red;
}
<nav class="navbar ">
<ul class="navbar-nav">
<li *ngFor="let item of items">
<a class="nav-link" [ngClass]="{'red':activeId === item.id}" (click)='makeALinkActive(item)'>{{item.title}}</a>
</li>
</ul>
</nav>
items=[{id:1,title:"a"},{id:2,title:"b"},{id:2,title:"c"},{id:3,title:"d"}]

Custom logo with link to homepage

I have a trouble to add custom logo with link to navbar if we scroll down
is class "dropdown-menu dropdown-inverse"
site: http://its-skin.upgates.com
CSS:
.secondlogo {
background-image: url(http://static.its-skin.upgates.com/m/m57daee4256187-sublogo.png);
width: 250px;
height: 54px;
margin-left: auto;
margin-right: auto;
}
here is the code full code :
<ul class="nav navbar-nav top-menu top-menu-categories">
{else}
<ul class="dropdown-menu dropdown-inverse" data-designer="d1-2-2-1">
{/if}
{foreach $tree as $category}
<li class="ct_{$category['category_id']} lev-{$level}{if $category['active']} active{/if}{if count($category['childs'])} dropdown{if $level > 1} dropdown-submenu{/if}{/if}" data-target-category="{$category['target_category_id']}">
<a href="{$category['url']}"{if $category["blank_yn"]} target="_blank"{/if} class="TopMenuLink">
{$category['name']}
{if (count($category['childs']))}
<i class="caret"></i>
{/if}
</a>
{if count($category['childs'])}
<button class="btn SubcategoriesLink"><i class="fa fa-chevron-right"></i></button>
{/if}
{include #desktopMenu tree => $category['childs'], level => $level + 1, option => false, colsCount => ceil(count($category['childs'])/$itemsInCol)}
</li>
{/foreach}
</ul>
You could add another list element at start of your ul which holds the link
<ul class="nav navbar-nav top-menu top-menu-categories">
<!-- New Element with class logolink -->
<li class="ct_29 lev-1 logolink">
<a href="http://its-skin.upgates.com/" class="TopMenuLink">
Link
</a>
</li>
<li class="ct_29 lev-1" data-target-category="29">
<a href="http://its-skin.upgates.com/krasa-it-s-skin" class="TopMenuLink">
Krása It's Skin
</a>
</li>
...
</ul>
Then just use css to put your logo in front of it
.logolink {
background-image: url(http://placehold.it/16x16/ff0000);
background-position: left center;
background-repeat: no-repeat;
padding-left: 20px; /* Adjust to your logo size*/
}
Example:
In case you want just a clickable logo image without text, wrap it inside the hyperlink <img src="#" /> and forget about the background-image in css.
EDIT:
If you want a fade-in effect when a user scrolls your page have a look at these two excellent jquery libraries which provide this functionality.
http://scrollmagic.io/
http://johnpolacek.github.io/scrollorama/
Alternative you can fade in with some jquery code. Therefore hide the logo (element) by setting it´s opacity to 0, detect the viewport scrolling and fade it in at some point. Find a working example here:
https://jsfiddle.net/mwtebtw9/1/
Code taken from: http://www.ordinarycoder.com/jquery-fade-content-scroll/

Angular 2 change css by id

I'm trying to change the menu css that was clicked by id, and when click on another menu all others lose their style, and only what was clicked wins the style.
But I'm not making to do this, someone could help me?
import { Component } from '#angular/core';
import { NgClass } from '#angular/common';
#Component({
selector: 'my-header',
template: `
<nav class="navbar navbar-default navbar-static-top">
<ul class="nav navbar-nav">
<li><a [ngClass]="{'selectedClass': selected}" (click)="selectId($event)" id="1">Menu 1</a></li>
<li><a [ngClass]="{'selectedClass': selected}" (click)="selectId($event)" id="2">Menu 2</a></li>
<li><a [ngClass]="{'selectedClass': selected}" (click)="selectId($event)" id="3">Menu 3</a></li>
<li><a [ngClass]="{'selectedClass': selected}" (click)="selectId($event)" id="4">Menu 4</a></li>
</ul>
</nav>
`,
styles: [`
.selectedClass {
color: #cc0000;
background-color: #ffffff;
}
`]
})
export class HeaderComponent {
selected = false;
selectId(event) {
console.log(event.currentTarget.id);
selected = true;
}
}
Well, at the moment you're just setting selected (edit: you forget this. in front of your selected btw, just saw that now) to true every time one of your links is clicked so on your first click all of your items get the class selectedClass and after that nothing else changes anymore.
Without modifying your example too much, you could just pass and save an id of your latest clicked item instead of a boolean value. Then just check on the selected id if the item should have selectedClass.
Something like this:
<ul class="nav navbar-nav">
<li><a [ngClass]="{'selectedClass': selected == 1}" (click)="selectId(1)">Menu 1</a></li>
<li><a [ngClass]="{'selectedClass': selected == 2}" (click)="selectId(2)">Menu 2</a></li>
<li><a [ngClass]="{'selectedClass': selected == 3}" (click)="selectId(3)">Menu 3</a></li>
<li><a [ngClass]="{'selectedClass': selected == 4}" (click)="selectId(4)">Menu 4</a></li>
</ul>
export class HeaderComponent {
selected: number;
selectId(id: number) {
this.selected = id;
}
}
A better approach would probably be to use defined objects for your navigation items in the first place so you don't have to worry about which values to pass / check for something like this and make it more dynamic.
For example you could define your links directly in your class (or even via #Input()), let *ngFor build up your navigation and pass around the "navigation item objects" directly:
export class HeaderComponent {
#Input() navigationItems: any[] = [ // defined a default array as example
{
text: 'Menu 1',
selected: false
}
];
onItemClick(item: any) {
this.navigationItems.map((navItem) => {
navItem.selected = navItem === item;
});
}
}
<ul class="nav navbar-nav">
<li *ngFor="let item of navigationItems">
<a [ngClass]="{'selectedClass': item.selected}"
(click)="onItemClick(item)">
{{item.text}}
</a>
</li>
</ul>

D3 Elements are invisible despite existing in DOM

I have a bootstrap tab panel and I want to display a different d3 chart for each tab.
When the document loads, the first D3 chart is present in the DOM but its elements are invisible. Here's an example: http://i.imgur.com/7ATTyhI.png
Here is the setup for my tab pane in bootstrap:
<div role="tabpanel">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#ghg-co2" aria-controls="ghg-co2" role="tab" data-toggle="tab">
<h4>Change in CO<sub>2</sub></h4></a>
</li>
<li role="presentation"><a href="#ghg-ch4" aria-controls="ghg-ch4" role="tab" data-toggle="tab">
<h4>Change in CH4 (Methane)</h4></a>
</li>
<li role="presentation"><a href="#ghg-nos" aria-controls="ghg-nos" role="tab" data-toggle="tab">
<h4>Change in Nitrous Oxide</h4></a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<script src="js/ghg.js"></script>
<div role="tabpanel" class="tab-pane active fade fade-in" id="ghg-co2">
<div id="chart-ghg-co2" class="d3-chart"></div>
</div>
<div role="tabpanel" class="tab-pane fade fade-in" id="ghg-ch4">
<div id="chart-ghg-ch4" class="d3-chart"></div>
</div>
<div role="tabpanel" class="tab-pane fade fade-in" id="ghg-nos">
<div id="chart-ghg-nos" class="d3-chart"></div>
</div>
</div>
</div>
I have had issues with bootstrap displaying content in the tab pane correctly. I am using this hack in my style.css to override some bootstrap properties:
/* bootstrap hack: fix content width inside hidden tabs */
.tab-content > .tab-pane,
.pill-content > .pill-pane {
display: block; /* undo display:none */
height: 0; /* height:0 is also invisible */
overflow-y: hidden; /* no-overflow */
}
.tab-content > .active,
.pill-content > .active {
height: auto; /* let the content decide it */
} /* bootstrap hack end */
I got it from this thread
My D3 function is almost identical to this example: d3 scatterplot
but with different data.
At the bottom of my HTML, I have:
<script>
// Check if DOM is ready for D3
$( document ).ready(ghgco2()); // Names of my three D3 chart functions
$( document ).ready(ghgch4());
$( document ).ready(ghgnos());
</script>
I suspect the problem is that my d3 function, ghgco2() is attempting to render before the div in which it resides, .chart-ghg-co2 is ready. For some reason, the svg has the correct dimensions, and the elements are all present, but it's completely blank. This is resolved when I switch between tabs on the bootstrap pane.
Any and all help is appreciated.

angular-bootstrap dropdown on mouseenter and keep dropdown-menu from hiding before being clicked.

First, I'm aware of this posts:
Activating bootstrap dropdown menu on hover
Bootstrap Dropdown with Hover
How to make twitter bootstrap menu dropdown on hover rather than click
And others, but still not found the correct solution yet, here's what I did so far.
first I used the is-open attribute from the angular-bootstrap dropdown directive like this:
<span class="dropdown" dropdown is-open="status.isopen">
<a
href
class="dropdown-toggle"
ng-mouseenter="status.isopen = true"
ng-mouseleave="status.isopen = false"
>
hover me for a dropdown with angular-bootstrap
</a>
<ul
class="dropdown-menu"
>
<li ng-repeat="choice in items">
<a href>{{choice}}</a>
</li>
</ul>
</span>
that seemed to work but 2 bugs appeared:
the first is when dropdown-toggle element is clicked the dropdown menu is gone clicking again wont bring it back you have to mouseleave then mouse enter the dropdown-tooggle to get the dropdown-menu back.
the second is a css/html problem.
Usually the regular css solution for a dropdown is like this:
<a class="css-dropdown">
hover here with css.
<div class="css-dropdown-menu">
<p>item 1</p>
<p>item 2</p>
<p>item 3</p>
</div>
</a>
Notice the dropdown-menu now is inside the dropdown-toggle element which mean when moving with the mouse from the dropdown-toggle to the dropdown-menu it's moving from parent to child, so basically we still hovering over the dropdown-toggle since we are in it's child, which mean the dropdown-menu will still be visible, on other hand, the bootstrap dropdown works with the click event so having the dropdown-menu as a child of the dropdown-toggle is not needed, but now when someone wants to change the behavior to mouseenter/hover once the mouse leaves the dropdown-toggle the dropdown-menu disappear so we no longer have access to the dropdown-menu elements this is visible in this plunker
To fix the first bug, I just removed the dropdown directive then replaced the is-open with ng-class directive like this.
Change this:
<span class="dropdown" dropdown is-open="status.isopen">
to this:
<span class="dropdown" ng-class="{'open': status.isopen}">
The rest stays the same plunker that fixed the first bug.
The second bug is tricky, since the dropdown-menu is no longer a child of the dropdown-toggle the hover effect wont last while moving from the toggle to the menu, so I did this.
Changed this:
<ul class="dropdown-menu">
to this:
<ul
class="dropdown-menu"
ng-mouseenter="status.isopen = true"
ng-mouseleave="status.isopen = false"
>
That did it but another bug appeared when clicking the dropdown-menu item it stays open, so I kept hacking by doing this.
changed this:
<li ng-repeat="choice in items">
to this:
<li ng-repeat="choice in items" ng-click="status.isopen = false">
That give me the required behavior plunker.
That said, this is not a good solution since a lot of directives are involved here for a simple visual effect, the last plunker I provided contains a css solution with no Bootstrap or AngularJS involved, though it is the required behavior it is not the required html structure or visual result, what I need is to have a space between the dropdown-toggle and the dropdown-menu not a padding of the toggle element just an empty space, which make the css solution not valid in this situation.
So, my question is there a better way of doing this without adding a new plugin/library more clean and easily reusable solution for the hover drop down menu?
First, have the toggling on the top-most parent element (in this case, the <span>)
<span class="btn-group" dropdown is-open="status.isopen" ng-mouseenter="status.isopen = true" ng-mouseleave="status.isopen = false">
<a class="btn btn-primary dropdown-toggle" dropdown-toggle>
Button dropdown <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li>Action</li>
<li>Another action</li>
<li>Something else here</li>
<li class="divider"></li>
<li>Separated link</li>
</ul>
</span>
This will allow the behavior you wanted - while still allowing clicking to show/hide the menu ;-)
However there's an annoyance: if you move the mouse cursor slower and pass the small gap between the toggle and menu, it will hide the menu.
So secondly, add a small CSS to remove the gap
.dropdown-menu {
margin-top: 0;
}
See the action in this plunker.
I know you want a solution without adding a new plugin/library, but you (or others seeking for this behavior) might want to try using No Close from Dropdown Enhancements lib to keep the dropdown open even after clicking in one of its options:
Do not close the menu on click on radio add class .noclose.
<div class="btn-group">
<button data-toggle="dropdown" class="btn btn-default dropdown-toggle">
Checked option <span class="caret"></span>
</button>
<ul class="dropdown-menu noclose">
<li>
<input type="radio" id="gr1_1" name="gr1" value="1">
<label for="gr1_1">Option 1</label>
</li>
<li>
<input type="radio" id="gr1_2" name="gr1" value="2">
<label for="gr1_2">Option 2</label>
</li>
<li>
<input type="radio" id="gr1_3" name="gr1" value="3">
<label for="gr1_3">Option 3</label>
</li>
</ul>
</div>
Also add a CSS solution for the hovering problem:
.btn-group:hover .dropdown-menu.noclose {
display: block;
}
.dropdown-menu.noclose {
margin-top: 0px;
}
And, of course, don't forget to import the libs:
<script src="./js/dropdowns-enhancement.min.js"></script>
<link href="./css/dropdowns-enhancement.css" rel="stylesheet"\>
In your case I suggest you to study the Dropdown Enhancements's source code to see how it works and maybe find a more suitable solution.
Try adding this line to your css:
.btn-group:hover>.dropdown-menu { display: block; margin-top: 0; }
You'll have to remove your is-open, ng-mouseenter and ng-mouseleave directives.
Below is the solution I came up with, while working on the same issue.
I used a simple custom directive that:
binds the mouseenter and mouseleave events to the dropdown in order correctly to show/hide the menu.
dynamically adds a custom CSS class to the dropdown menu in order to prevent the menu from disappearing when moving the cursor from the button to the menu. Note that this solution has the advantage of not removing the visual gap between the button and menu.
prevents the menu from disappearing when the button is clicked.
The CSS rule uses a before pseudo-element to fill the gap between the button and the menu. I added the border property which can be uncommented to easily get a visual feedback.
.dropdown-hover-menu::before {
content: '';
position: absolute;
left: 0;
width: 100%;
top: -3px;
height: 3px;
/*border: 1px solid black;*/
}
The HTML structure of the snippet is based on the available examples in the dropdown section of the angular-ui bootstrap documentation
angular.module('app', ['ui.bootstrap'])
.directive('dropdownHover', function() {
return {
require: 'uibDropdown',
link: function(scope, element, attrs, dropdownCtrl) {
var menu = angular.element(element[0].querySelector('.dropdown-menu')),
button = angular.element(element[0].querySelector('.dropdown-toggle'));
menu.addClass('dropdown-hover-menu');
element.bind('mouseenter', onMouseenter);
element.bind('mouseleave', onMouseleave);
button.bind('click', onClick);
function openDropdown(open) {
scope.$apply(function() {
dropdownCtrl.toggle(open);
});
}
function onMouseenter(event) {
if (!element.hasClass('disabled') && !attrs.disabled) {
openDropdown(true);
}
};
function onMouseleave(event) {
openDropdown(false);
};
function onClick(event) {
event.stopPropagation();
}
scope.$on('$destroy', function() {
element.unbind('mouseenter', onMouseenter);
element.unbind('mouseleave', onMouseleave);
button.unbind('click', onClick);
});
}
};
});
.dropdown-hover-menu::before {
content: '';
position: absolute;
left: 0;
width: 100%;
top: -3px;
height: 3px;
/*border: 1px solid black;*/
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.3/ui-bootstrap-tpls.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="app">
<div class="btn-group" uib-dropdown dropdown-hover>
<button type="button" class="btn btn-primary dropdown-toggle">
Button dropdown <span class="caret"></span>
</button>
<ul class="dropdown-menu" uib-dropdown-menu role="menu">
<li role="menuitem">Action
</li>
<li role="menuitem">Another action
</li>
<li role="menuitem">Something else here
</li>
<li class="divider"></li>
<li role="menuitem">Separated link
</li>
</ul>
</div>
</div>

Resources