I'm trying to add an animation on add/remove on the <a>-Tag, based on the toggleBookmark function. The active class is added when it returns true and works fine.
However, the ng-add or icon__bookmark-add animation does not fire on the <a> tag.
Why? What am I doing wrong?
HTML:
<li ng-repeat="event in events | filter:searchText">
<div ng-click="toggleBookmark(event.id)" class="events-list__icons">
<a ng-class="{active:isBookmarked(event.id)}" class="icon__bookmark"></a>
</div>
</li>
Controller:
$scope.isBookmarked = (id) ->
BookmarkService.isBookmarked(id) // this just returns true or false
$scope.toggleBookmark = (id) ->
BookmarkService.toggleBookmark(id) // returns nothing
CSS:
.icon__bookmark.ng-add,
.icon__bookmark.ng-add-active,
.icon__bookmark-add,
.icon__bookmark-add-active {
animation: flip .6s ease-in-out;
backface-visibility: visible;
}
ng-class="{active:isBookmarked(event.id)}" only adds the class active.
You should redefine your CSS so that 'active' runs the animation. See this jsfiddle: http://jsfiddle.net/nicolasmoise/XaL9r/1/
You can also use the ngAnimate service and create a new directive for .events-list__icons.
$animate.addClass(element, 'active')
Would add active, active-add (to set up the animation), and active-add-active (to run the animation) classes.
Related
Currently I'm working in Vue.js and have a navigation menu that I'd like to animate. What I'm looking to do is show two li elements when a user hovers over one of the navigational buttons.
Currently what I'm doing is setting a data type of showActivities to false by default and setting that to true on mouseenter and false on mouseleave. So this has the items appearing and disappearing on hover but they're not animated. How could animation for this be done?
<ul class="navs">
<li>Schedule</li>
<li #mouseenter="showActivities = true" #mouseleave="showActivities = false">Team Activity</li>
<li v-show="showActivities">tik tak tow</li>
<li v-show="showActivities">Bejewel</li>
<li>Resources</li>
<li class="logout">Logout</li>
</ul>
<script>
export default {
name: 'SideMenu',
data() {
return {
showActivities: false,
};
},
};
</script>
okay if i got you correct you want a type of animation like a slow fade In and Out.
In vuejs transitions, state are attached to CSS classes that can be called and modified ass you want it to be. The doc is clearer about it
Vuejs Transitions
for example if you add this in your css section the transition will be a slow fade In and Out:
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
so i'm a bit confused as why the code im working off isn't working as expected, so any help would be good.
so let me explain im working on an expanding/ collapsing menu, when the a tag is clicked a class is added and css is added to make this happen, and also the class is removed from the other links.
CSS code:
a {
max-height: 0;
overflow: hidden;
transition: 0.5s ease-in-out
}
a.clicked {
max-height: 600px;
}
html code:
<ul>
<li><a onclick='mobileMenu(event)'>link 1</a><li>
<li><a onclick='mobileMenu(event)'>link 2</a><li>
<li><a onclick='mobileMenu(event)'>link 3</a><li>
<li><a onclick='mobileMenu(event)'>link 4</a><li>
</ul>
for this post i kept the html pretty simple but if it needs to be more detailed let me know.
Each link has a onclick attached.
Javascript code:
function mobileMenu(event) {
event.currentTarget.classList.toggle("clicked");
[].forEach.call(document.querySelectorAll('ul li a'), function(a){
a.classList.remove('clicked');
});
}
so this code mostly works where you click a link is adds 'clicked' class and also removes the 'clicked' class from any other links except the current link, which is good because im using this as a collapse-able menu so you click another link it opens it while also closing any other link currently open.
My problem is is the js code above to add the clicked class i'm using a '.toggle' but this only adds the 'clicked' class but does not toggle it. I want to be able to toggle the 'clicked' class and also remove it from others links. so im not sure if its a simple oversight on my part but im not sure where im going wrong and why the '.toggle' isn't actually toggling the class.
Thanks.
You can try a if statement. It will always remove the checked from all links, and if the event.target is not checked, it will add the class checked.
function mobileMenu(event) {
const checked = event.currentTarget.classList.contains('clicked')
[].forEach.call(document.querySelectorAll('ul li a'), function(a){
a.classList.remove('clicked');
});
if (checked) return;
event.currentTarget.classList.toggle("clicked");
}
As per comment the right way to add event listeners is using .addEventListener().
In the event listener you can search for an anchor with a class clicked and if any remove the class. After you can add the class to the current element:
document.querySelectorAll('ul li a').forEach(function(ele, idx) {
ele.addEventListener('click', function(e) {
var clickedEle = document.querySelector('ul li a.clicked');
if (clickedEle != null)
clickedEle.classList.remove('clicked');
this.classList.add('clicked');
})
});
a {
max-height: 0;
overflow: hidden;
transition: 0.5s ease-in-out
}
a.clicked {
max-height: 600px;
color: blue;
}
<ul>
<li><a>link 1</a><li>
<li><a>link 2</a><li>
<li><a>link 3</a><li>
<li><a>link 4</a><li>
</ul>
I'm implementing some animation by adding and removing classes to an element on mouseover and mouseout. I'm using this method as I found using CSS alone was not reliable; the animation would not complete if the mouse exited the element before the animation finished.
So I have the following code:
<div class="one flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
<!-- back content -->
</div>
</div>
</div>
<script>
jQuery(".flip-container").hover(function () {
jQuery(this).addClass("hover");
},function () {
jQuery(this).delay(2000).queue(function(){
jQuery(this).removeClass("hover");
});
});
</script>
<style>
.flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
</style>
This works but sometimes the class 'hover' is not removed, it stays, leaving the element in its animated state. Any idea how to make this more reliable?
Try using mouseenter and then set a timeout function to remove the class that way you wont be adding and removing classes except once each time the mouse enters the area. Also you may want to check to see if the area already has the class to avoid the function from being executed too many times like so:
jQuery(".flip-container").mouseenter(function () {
var el = jQuery(this);
if(!el.hasClass("hover")){
el.addClass("hover");
setTimeout(function(){
el.removeClass("hover");
}, 2000);
}
});
Here is a working fiddle Fiddle Demo
Is it possible to set jQuery up to catch a # link and display an animation based on which one it picks up?
Example:
Click Link 1 > /index.php#1 = pulsate div 1
Click Link 2 > /index.php#2 = pulsate div 2
Click Link 3 > /index.php#3 = pulsate div 3
I currently have a guide/rule page, and it want it to highlight the correct content when people are taken there by a specific link. I understand basic jQuery animations, just not giving them rules from a parent page.
1. Read hash from URI
JS's window.location.hash will read the hash like "#1" which is a valid ID in HTML5
jQuery(function($) {
$( window.location.hash ).addClass("pulsate");
});
where you have DIV elements like
<div id="div1">I'm DIV 1</div>
and a CSS class like
.pulsate {
/* other styles here... */
animation: pulsate 0.5s ease-in-out;
animation-iteration-count: 5; /* Pulsate 5 times */
}
#keyframes pulsate {
0% {transform: scale(1);}
50% {transform: scale(1.2);}
}
2. Read hash from clicked link
If you're not interested in reading the URI's hash but you have simply LInks like
<a class="animateButton" href="#div1">Animate DIV1</a>
than this is all you need:
$(".animateButton").on("click", function(){
$( this.hash ).addClass("pulsate").on("animationend", function(){
$(this).removeClass("pulsate");
});
});
.pulsate {
background: orange;
animation: pulsate 0.5s ease-in-out;
transition:0.5s;
animation-iteration-count: 3;
}
#-webkit-keyframes pulsate {
0% {transform: scale(1);}
50% {transform: scale(1.1);}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="animateButton" href="#1">#1</a>
<a class="animateButton" href="#2">#2</a>
<a class="animateButton" href="#3">#3</a>
<div id="1">I'm DIV #1</div>
<div id="2">I'm DIV #2</div>
<div id="3">I'm DIV #3</div>
It's not rules "from a parent page". You can get the hash parameter from a page's url by using location.hash:
//index.php#1
location.hash //-> will return #1
//index.php#2
location.hash //-> will return #2
Then, you can select it directly in your jQuery selector as $(location.hash). This will enable you to animate the targeted div.
$(document).ready(function() {
//Do your animation
$(location.hash).animate(/*...*/)
});
obs:
Remember that divs with numeric ids are only valid in HTML5
Here is a fiddle that you play with it. I didn't add animations but left it to you as an exercise. =]
HTML
sec1
sec2
sec3
JS
$("a").on('click', function(event){
var t = event.target.toString();
if (t.endsWith('1')){
alert('animation 1');
} else if (t.endsWith('2')){
alert('animation 2');
} else if (t.endsWith('3')){
alert('animation 3');
}
});
You have to listen to the hash changes.
Try to use a plugin like hashchange.
$(window).hashchange((function(){
var hash = window.location.hash.replace("#",'');
// remove previous animation from element if there's one
if(hash) {
// do your animation adding class or with pure jquery
}
return arguments.callee; // return itself as the hashchange handler
})( )); // exec the first time and then at each hash changes
Remeber to remove the class or the javascript animation fron previuos pulsating element.
jQuery hashchange plugin
In the ng-repeat section there are animations event handler for enter, leave and move. But the move event is only triggered when we resort or filter the array used for ng-repeat. What if I only change the attribute values of my objects. Then no event is triggered at all. Is there a way to trigger the event manually after I have changed the object attribute?
Here is a fiddle: http://jsfiddle.net/U3pVM/15002/
Html:
<ul>
<li ng-repeat="d in data">
<div class="lala" style="width: {{d.a}}px">foo</div>
</li>
</ul>
JS:
function TodoCtrl($scope) {
$scope.data = [{a:100}, {a:120}];
// I would like to animate the value changes
$scope.change = function() {
$scope.data[0].a = 110;
$scope.data[1].a = 90;
}
}
your class definitions are wrong.
.lala,
.lala.ng-enter,
.lala.ng-move,
.lala.ng-leave {
background-color: grey;
-webkit-transition:all 1s linear;
-moz-transition:1s linear all;
-o-transition:1s linear all;
transition:all 1s linear;
}
See the working fiddle here.
just add transition to the main class
.lala{
transition:0.5s;
background-color:grey;
}
https://jsfiddle.net/U3pVM/15006/