AngularJS ng-show directive showing elements before hiding elements - javascript

So I'm trying to create a slide effect for some bootstrap badges I am using to display some hierarchical data relationships using AngularJS.
I have a slider-effect for showing new sub-categories, and hiding sub-categories that are already open. Now this is all working well, except it seems to do the "showing slide" first, and then the "hiding slide" second, which is the opposite of what you would like.
ie. When you hit a badge for a different category, it should first slide closed the already showing other sub-categories, and then open the new sub-categories to be shown.
The html looks like this:
<div ng-controller="MainController">
<ul ng-repeat="category in categories">
<li ng-if="category.category_type=='parent'" ng-show="category.category_show">
<span class="badge badge-p" ng-click="updateResults(category)">{{category.category_name}}</span>
</li>
<li ng-if="category.category_type == 'child'" ng-show="category.category_show" class="badge-slider">
<span class="badge badge-c">{{category.category_name}}</span>
</li>
</ul>
</div>
The relevant CSS looks like this:
.badge-slider {
max-height: 100px;
-webkit-transition: max-height linear 0.2s;
-moz-transition: max-height linear 0.2s;
-o-transition: max-height linear 0.2s;
transition: max-height linear 0.2s;
overflow:hidden;
}
.badge-slider.ng-hide {
max-height: 0px;
}
I have mocked up a simplified plnkr example to demonstrate what is happening here: http://plnkr.co/edit/S255yk0N2wAXrfq7Mqd6
EDIT 1: Thanks to the help of sbedulin I was able to get this working beautifully. I've also updated the code so that the subcategories dynamically indent based on how far down the tree they are. You can find my newly mocked up version here: http://plnkr.co/edit/5I1pU0TZo6AjHJTbBuG9

I was able to achieve the desired effect by only modifying your CSS:
/* Styles go here */
.badge-slider {
max-height: 100px;
-webkit-transition: max-height linear 1.2s;
-moz-transition: max-height linear 1.2s;
-o-transition: max-height linear 1.2s;
transition: max-height linear 1.2s;
transition-delay: 0.0s;
overflow:hidden;
}
.badge-slider.ng-hide {
-webkit-transition: max-height linear 0.0s;
-moz-transition: max-height linear 0.0s;
-o-transition: max-height linear 0.0s;
transition: max-height linear 0.0s;
max-height: 0px;
}
I set your transition lengths to 1.2s in .badge-slider just so you can clearly see that it is working. The key is adding in transition-delay: 0.0s; to .badge-slider and adding transition lengths of 0.0s to .badge-slider.ng-hide. Hope this helps!

Main problem is that <ul ng-repeat="category in categories"> generates multiple <ul> elements, ngRepeat should be placed on <li>s.
After some refactoring HTML will look like:
<ul>
<li ng-repeat="category in categories"
ng-init="isChild = category.category_type == 'child'"
ng-show="category.category_show"
class="badge-slider">
<span ng-click="isChild || updateResults(category)"
ng-bind="category.category_name"
class="badge {{ isChild ? 'badge-c' : 'badge-p' }}">
</span>
</li>
</ul>
CSS
.badge-slider {
-webkit-transition: all 0.2s linear 0.2s;
-moz-transition: all 0.2s linear 0.2s;
-o-transition: all 0.2s linear 0.2s;
transition: all 0.2s linear 0.2s;
line-height: 30px;
overflow:hidden;
max-height: 30px;
}
.badge-slider.ng-hide {
transition-delay: 0.0s;
max-height: 0px;
}
Working plunk is here

Related

hovering parent div changes 0-width child div to match contained image width

I have several divs, each containing an icon and a tooltip-type image:
The container is square, height=135px and width=135px.
The icon div is mostly square, has height=135px, width=auto, it's image height=100% and width=autoto keep aspect ratio. The width is smaller than the height.
The tooltip is rectangular, height=135px, width=auto, it's image height=100% and width=auto. The width is usually at least two times larger than the height.
The images are aligned with Bootstrap 4 classes.
Together, the container divs form up a kind of mosaic of services. When each icon image is hovered, the corresponding tooltip-like image appears with a "book opening" animation, from the center of the icon. What I mean is, the child div has width:0; until the parent is hovered, then it animates to width:[width of contained image];. The markup is as follows:
<!-- container div -->
<div class="int_Sicon mx-2 my-2">
<!-- div containing the icon -->
<a href="corresponding service page">
<div class="d-block dLarge">
<img height="100%" src="the icon url">
</div>
</a>
<!-- div containing the tooltip -->
<div class="int_Stooltip dLarge">
<img height="100%" src="the tooltip url">
</div>
</div>
I had a buggy css animation doing what I wanted for a specific "tooltip" image, for layout testing purposes (the following css code), but it all broke apart when I finished testing and started adding the rest of the images. I had specific widths set, and utilized the left property to achieve what I intended, but right now I'm finishing development and wanted to allow the user to change images without breaking the layout. Each tooltip is a different image with the same height but varying widths. This is the CSS I have right now:
.dLarge { height: 135px; }
/* for different viewports I also have different heights for the icons and tooltips, but for the sake of clarity, let's focus on "dLarge" - 135px height */
.int_Sicon { position:relative; }
.int_Sicon .int_Stooltip {
visibility: hidden;
position: absolute;
z-index: 1;
overflow: hidden;
pointer-events: none;
top:0;
left: 0;
margin:0;
-webkit-transition: width 0.3s ease-out, left 0.3s ease-out;
-moz-transition: width 0.3s ease-out, left 0.3s ease-out;
-o-transition: width 0.3s ease-out, left 0.3s ease-out;
transition: width 0.3s ease-out, left 0.3s ease-out;
}
.int_Sicon .int_Stooltip::after {
content: "";
position: absolute;
}
.int_Sicon:hover .int_Stooltip {
visibility: visible;
left: -100%;
}
So I started messing around with javascript and this is where I ended up, unsucessfully:
var getWidth = $('.int_Stooltip>img').outerWidth();
$('.int_Stooltip').css({'width' : 0});
$('.int_Sicon').hover( $('.int_Sicon>.int_Stooltip').css({'width' : getWidth}); );
I looked everywhere for a solution, but nothing I find quite suits what I want to accomplish.
I based myself on this StackOverflow question: Expand div from the middle instead of just top and left using CSS
Essentially, I wanted to make something on the lines of this https://codepen.io/wintr/pen/wWoRVW except with an image covering the button instead of a background animation.
I'm using Bootstrap 4.0 beta 2 and Jquery 3.2.1.
I'm self taught, and eager to learn more. What am I missing? Or at least, where should I look?
If your trying to achieve the effect in the code pen example. You'll want to have your tooltip centered by default with a width of 0. You can center an absolutely positioned element by setting its top, right, bottom, and left properties to 0, then setting its margins to auto. Then when you hover, the width should change to 100%. Check out the code below. I added some colors and text just to help visualize it since there were no actual images.
.int_Slogo {position:relative; display:inline-block;}
.int_Slogo .int_Stooltip {
width: 0;
position: absolute;
z-index: 1;
pointer-events: none;
overflow: hidden;
top:0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
-webkit-transition: width 0.3s ease-out, left 0.3s ease-out;
-moz-transition: width 0.3s ease-out, left 0.3s ease-out;
-o-transition: width 0.3s ease-out, left 0.3s ease-out;
transition: width 0.3s ease-out, left 0.3s ease-out;
}
.int_Slogo:hover .int_Stooltip {
width: 100%;
}
<div class="int_Slogo mx-2 my-2">
<a href="Services">
<div class="d-block dLarge">
<img src="http://lorempixel.com/400/200/sports/1/Dummy-Text/">
</div>
</a>
<div class="int_Stooltip dLarge">
<img src="http://lorempixel.com/400/200/sports/Dummy-Text/">
</div>
</div>
I woke up especially inspired this morning and came up with the solution. The answer wasn't in defining the widths of the divs, but specifying css for the images themselves. This is what I came up with.
Markup:
<div class="dLarge int_Sicon mx-2 my-2">
<a href="corresponding service page">
<div class="d-block">
<img class="dLargeImg m-auto d-block" src="imgsrc">
</div>
</a>
<div class="int_Stooltip">
<img class="dLargeImgs m-auto d-block" src="imgsrc">
</div>
</div>
Styles:
.dLarge {
height: 135px;
width: 135px;
}
.dLargeImgs { height:135px; }
.int_Sicon {
position:relative;
display: inline-block;
}
.int_Sicon .int_Stooltip {
position: absolute;
top:0;
right:0;
bottom:0;
left: 0;
margin:0;
z-index: 1;
pointer-events: none;
overflow: hidden;
-webkit-transition: left 0.3s ease-in-out, right 0.3s ease-in-out;
-moz-transition: left 0.3s ease-in-out, right 0.3s ease-in-out;
-o-transition: left 0.3s ease-in-out, right 0.3s ease-in-out;
transition: left 0.3s ease-in-out, right 0.3s ease-in-out;
}
.int_Sicon:hover .int_Stooltip {
left:-50%;
right:-50%;
}
.int_Sicon .int_Stooltip img {
width:0;
-webkit-transition: width 0.3s ease-in-out;
-moz-transition: width 0.3s ease-in-out;
-o-transition: width 0.3s ease-in-out;
transition: width 0.3s ease-in-out}
.int_Sicon:hover .int_Stooltip img { width:100%; }

css transitions not working on firefox

I have a similar issue as CSS Transition not firing when adding class to body (Firefox) but I can seem to find a way to solve it targeting the element in different ways or removing classes.
Here is what I have:
Markup:
<div class="ball b40 first">
<a class="ffx-fx" href="javascript:void(0)">
</a>
</div>
css:
.ffx-fx {
-webkit-transition: all 1.5s ease-in-out;
-moz-transition: all 1.5s ease-in-out;
-o-transition: all 1.5s ease-in-out;
-ms-transition: all 1.5s ease-in-out;
transition: all 1.5s ease-in-out;
}
.b40 a {
width:220px;
height:220px;
background: url(../images/temp/1_a.jpg) center center;
background-size: 100% 100% !important;
}
.b40 .b40-rotated {
width:220px;
height:220px;
background: url(../images/temp/1_b.jpg) center center !important;
}
js:
window.setInterval(function() {
$( ".b40 .ffx-fx" ).toggleClass( "b40-rotated" );
}, 5000);
I don't believe you can switch out background-images with transitions. At least I haven't tried it. How I usually handle this situation is have two inner divs--one with the on hover class and one with the off class. Then on hover, I change opacity. Opacity transition works. Sooo something like this...
HTML
<div class="container">
<a href="">
<div class="off_state"></div>
<div class="on_state"></div>
</a>
</div>
CSS
.container{position:relative;}
.off_state, .on_state{
position:absolute;
top:0;
left:0;
transition: all 1s;
}
.off_state, .container:hover .on_state{opacity:0.0;filter:alpha(opacity=0);}
.container:hover .on_state{opacity:1.0;filter:alpha(opacity=100);}
It's a rough version, but that's how I've always done it.
NOTE: jQuery UI also has the ability to add a class slowly. You can view it here: http://jqueryui.com/addClass/. It would probably be easier to use.

Add transition while changing img src with javascript

I have an img tag that I want to change the src when hover and it all works but i would like to add some transition so it doesn't look so rough but since it's an img src i cant target it with css.
http://jsfiddle.net/Ne5zw/1/
html
<img id="bg" src="img/img1.jpg">
<div onmouseover="imgChange('img/img2.jpg'); "onmouseout="imgChange('img/img1.jpg');">
js
function imgChange(im){
document.getElementById('bg').src=(im);
}
You want a crossfade. Basically you need to position both images on top of each other, and set one's opacity to 0 so that it will be hidden:
<div id="container">
<img class="hidden image1" src="http://www.istockphoto.com/file_thumbview_approve/4629609/2/istockphoto_4629609-green-field.jpg">
<img class="image2" src="http://www.istockphoto.com/file_thumbview_approve/9958532/2/istockphoto_9958532-sun-and-clouds.jpg" />
</div>
CSS:
.hidden{
opacity:0;
}
img{
position:absolute;
opacity:1;
transition:opacity 0.5s linear;
}
With a transition set for opacity on the images, all we need to do is trigger it with this script:
$(function(){
debugger;
$(document).on('mouseenter', '#hoverMe', function(){
$('img').toggleClass('hidden');
});
});
http://jsfiddle.net/Ne5zw/12/
Here is a pure css solution using css transition. You can use a div as the container and set the background-image on hover.
.image-container {
background: url(http://placeholder.pics/svg/300x300/DEDEDE/555555/Old%20Image) center center no-repeat;
background-size: contain;
width: 150px;
height: 150px;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.image-container:hover {
background-image: url("http://placeholder.pics/svg/300x300/DEDEDE/555555/New%20Image");
}
<div class="image-container"></div>
Just in case someone is curious how to actually create a transition-like effect when you are actually changing the source attribute of an image, this was the solution I came up with.
Javascript:
var bool = false;
setInterval(() => {
bool = !bool;
let imgSrc = bool ? 'hero-bg2.jpg' : 'hero-bg.jpg'; // Toggle image
$('.parallax-slider').addClass('transitioning-src'); // Add class to begin transition
setTimeout(() => {
$('.parallax-slider').attr('src', `https://website.com/images/${imgSrc}`).removeClass('transitioning-src');
}, 400); // Ensure timeout matches transition time, remove transition class
}, 6000);
CSS:
.parallax-slider {
transition: opacity 0.4s ease-in;
-webkit-transition: opacity 0.4s ease-in;
-moz-transition: opacity 0.4s ease-in;
-ms-transition: opacity 0.4s ease-in;
-o-transition: opacity 0.4s ease-in;
opacity: 1;
}
.transitioning-src {
transition: opacity 0.4s ease-out;
-webkit-transition: opacity 0.4s ease-out;
-moz-transition: opacity 0.4s ease-out;
-ms-transition: opacity 0.4s ease-out;
-o-transition: opacity 0.4s ease-out;
opacity: 0;
}
This will give the illusion of 'fading to black and back' between images - even if you're using something like parallax.js where you have a data-attribute driven component that renders out into a dynamic image. Hope it helps someone.
Fixed Mister Epic solution's images in this jsfiddle.
HTML
<div id="container">
<img class="hidden image1" src="http://placeholder.pics/svg/300x300/DEDEDE/555555/Old%20Image">
<img class="image2" src="http://placeholder.pics/svg/300x300/DEDEDE/555555/New%20Image" />
</div>
<div id="hoverMe">hover me</div>
CSS
div#hoverMe {
background-color:yellow;
width:50px;
height:50px;
position:fixed;
top:300px;
}
div#container{
position:relative;
height:200px;
}
.hidden{
opacity:0;
}
img{
position:absolute;
opacity:1;
transition:opacity 0.5s linear;
}
JS
$(function(){
$(document).on('mouseenter', '#hoverMe', function(){
$('img').toggleClass('hidden');
});
});

Image/div flicker on hover in google chrome

I'm animating the images so that when hovered over the opacity goes up to 1, that part is working perfectly fine however when images are hovered over in chrome the 2nd column flickers a tiny bit to the side. I've tested it in IE and Firefox aswell and have no issues.
Check it for yourself here: http://abmenzel.com/work/
HTML:
<body class="blue4">
<div class="content">
<div class="work-item blue4">
<img src="img/Template-2-Intro.png"/>
</div>
</div>
</body>
CSS:
.work-item{
width:25%;
opacity:0.8;
overflow:hidden;
display:block;
float:left;
}
img{
width:100%
}
.work-item:hover{
opacity:1;
-webkit-transition: all 0.2s ease-in-out 0s;
-moz-transition: all 0.2s ease-in-out 0s;
-o-transition: all 0.2s ease-in-out 0s;
-ms-transition: all 0.2s ease-in-out 0s;
transition: all 0.2s ease-in-out 0s;
}
I'm also using a script to set the height equal to the dynamic width, which might have something to do with it but I am unsure..
SCRIPT:
$(function() {
var div = $('.work-item');
var width = div.width();
div.css('height', width-5);
});
First of all, put your transition properties in normal element, not on :hover state.
Then, if you need only transition on opacity, use :
opacity 0.2s ease-in-out 0s
That flicker is a known bug in Webkit browsers, it happens when you animate opacity on fluid elements (here 25%).
Here's a workaround:
-webkit-backface-visibility: hidden;
-webkit-transform: translateX(0);
I know it sounds like a hack, but it works...
I use translate3D instead of translateX:
img {-webkit-transform: translate3D(0,0,0);}

apple style expanding search field in menu bar

I'm coding a website and I'm trying to replicate the effect on the apple.com where when you click to focus the search field in the menu bar, and the search field expands and the rest of the menu bar shrinks to accommodate it.
I've been trying various tricks with jquery kwicks, and also simply expanding a text field using the animate function in jquery but the effect is not the same. If someone could get me on the right track I'd very much appreciate it!
Best
Daniel
this can be done by css only no need for javascript or anything...
#search input {
width: 100px;
-moz-transition: width 0.5s ease-out;
-webkit-transition: width 0.5s ease-out;
transition: width 0.5s ease-out;
}
#search input:focus {
width: 200px;
-moz-transition: width 0.5s ease-out;
-webkit-transition: width 0.5s ease-out;
transition: width 0.5s ease-out;
}
voila, thats it ;)
Taking a quick look at how Apple did it, it looks like their big move is this (I could be wrong - I'm rushing):
#globalheader #globalnav li {
display: table-cell;
width: 100%;
overflow: hidden;
}
This is a pretty unusual CSS display value, and clever on their part, forcing the <li>'s to work like <td>'s. This means that changing the width of one of the "cells" causes the others in the same "row" to adjust how much room they take out.
Long live (fake) table-based layout!
So, assuming that CSS is possible for you, and I'm not off base with my quick glance at their code, your only task is to animate the width of the search box - the rest should follow suit.
Not to over simplify things but what if in your css you float:right; this input box and then on focus you animate the box to the appropriate width like so:
CSS:
#inputtext{
float:right;
width:150px;
}
jQuery:
$("div#inputtext").focus(function(){
$(this).animate({width:'300px'}, 1000);
});
This is a fiddle for this.
http://jsfiddle.net/MenuSo/r4xq9gz2/
HTML:
<form id="expanding-form">
<input type="text" id="expanding-input" placeholder="">
<button type="submit">Search</button>
</form>
and CSS:
#expanding-form input{
width: 30px;
height: 30px;
-o-transition: width .5s ease;
-ms-transition: width .5s ease;
-moz-transition: width 0.5s ease-out;
-webkit-transition: width 0.5s ease-out;
transition: width 0.5s ease-out;
}
#expanding-form input:focus{
width: 200px;
}
CSS would be enough.

Categories