Git Product home page Git Product logo

css-animator's Introduction

css-animator

This package was created out of the need for using CSS animations with a library like animate.css in Angular2 when there was no useful animation builder available yet.

css-animator works with any JavaScript application and takes the pain out of applying CSS animations manually. It also takes care of positioning elements that are being animated, among other useful things.

Feel free to open an issue if you're experiencing issues, or if you have any suggestions or comments.

The package includes ES5 compiled files, alongside TypeScript typings and source maps. Also UMD bundle files are included.

Tutorials

Devdactic - How to Add Animations To Your Ionic App (Tutorial)
Devdactic - How to Add Animations To Your Ionic App (Video Tutorial)
Ionic Academy - Include CSS+JS Files from NPM Packages with Ionic (Tutorial)

TL;DR (if you are having positioning issues)

Question: Other elements jump around during animation or after showing/hiding

Answer: Try to change the pin and useVisibility options (and have a look at all the other customization options)

animator.pin = false;
animator.useVisibility = true;

Usage

You can install css-animator from npm or use one of the available UMD bundles.

Use as dependency

$ yarn add css-animator
$ npm install --save css-animator
$ jspm install npm:css-animator

Use the UMD bundle

Name (to require) Bundle
css-animator/builder bundles/builder.min.js Includes AnimationBuilder only
css-animator bundles/css-animator.min.js Requires @angular/core as peer dependency

See https://jsfiddle.net/4ec57wpb/1/ for a full basic example

<html>
<head>
  <script src="https://unpkg.com/css-animator@latest/bundles/builder.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css"/>
</head>
<body>
  <!-- ... -->

  <script>
    (function() {
      const AnimationBuilder = window['css-animator/builder'].AnimationBuilder;
      const animator = new AnimationBuilder();

      // ...
    })();
  </script>
</body>
</html>

Example

css-animator is being used in the project angular2-quiz-app.

A very basic example can be found in the docs/ folder, which is also hosted on GitHub Pages: https://fabiandev.github.io/css-animator/

Usage

Use this package in combination with CSS animations.
A library like animate.css already offers a lot of great animations out of the box.

You can install both packages by running:

$ yarn add css-animator animate.css

Basic Usage

You can use css-animator without Angular2. Just import the class and animate any HTMLElement.

import { AnimationBuilder } from 'css-animator/builder';

let animator = new AnimationBuilder();

animator.setType('shake').animate(element);

Want to know when an animation has finished? The AnimationBuilder instance returns a promise:

animator
  .setType('shake')
  .animate(element)
  .then(() => {
    // Animation finished
  })
  .catch(() => {
    // Animation interrupted
  });

You may also change the default options for every instance that is created once changed:

import { AnimationBuilder } from 'css-animator/builder';

AnimationBuilder.defaults.pin = false;
AnimationBuilder.defaults.useVisibility = true;

Note: changing pin and useVisibility may be the way to go if you have issues with the possition of other elements during animation

Angular Usage

Before getting started and to make use of the directive and the service provided by css-animator, you have to import its module:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AnimatorModule } from 'css-animator';

@NgModule({
  imports: [
    BrowserModule,
    AnimatorModule
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [
    AppComponent
  ],
})
export class AppModule { }

Angular Service

There is a little Angular2 service included, that gives you the power of dependency injection out of the box.

import { Component, OnInit } from '@angular/core';
import { AnimationService, AnimationBuilder } from 'css-animator';

@Component({ ... })
export class SomeComponent implements OnInit {

  private animator: AnimationBuilder;

  constructor(animationService: AnimationService, private elementRef: ElementRef) {
    this.animator = animationService.builder();
  }

  ngOnInit() {
    this.animator.setType('fadeInUp').show(this.elementRef.nativeElement);
  }

}

Angular Directive

Feel free to create your own directive around css-animator. For you to get started, there is one included in this package.

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <div animates #animation="animates">
      <span (click)="animation.start({type: 'bounce'})">Click me!</span>
    </div>
  `
})
export class AppComponent {

}

It is possible to default options on the element, that will be used if you call animation.start(). You can pass any option that the interface AnimationOptions supports like this: animation.start({type: 'bounce', duration: 800}).

<div
animates
#animation="animates"
animates="{ type: 'wobble', duration: '2000' }" // default options are optional
animatesInitMode="show" // Can be used with [animatesOnInit] for "show" or "hide"
[animatesOnInit]="{ type: 'fadeInUp' }" // automatically animate on init (optional)
(click)="animation.start()"
(mouseleave)="animation.pause()"
(mouseenter)="animation.resume()"
>
</div>

You can also animate host elements with css-animator!

API

AnimationOptions

Below are all options supported by css-animator. You may notice, that all CSS animation properties are included, so you can look up which values are supported, where the options delay and duration have to be set as numbers in ms (e.g. 1000 for one second).

The animation-name is currently not supported, as type is as set as class.

export interface AnimationOptions {

  // General settings:
  disabled?: boolean;
  fixed?: boolean;
  reject?: boolean;
  useVisibility?: boolean;
  pin?: boolean;

  // Animation type set as class:
  type?: string;

  // Animation settings:
  fillMode?: string;
  timingFunction?: string;
  playState?: string;
  direction?: string;
  duration?: number;
  delay?: number;
  iterationCount?: number|string;

}

The delay option is an exception and won't be set as CSS animation property, as delays are handled via JavaScript timeouts. If you really want to use the CSS rule, you can call applyDelayAsStyle to apply the delay immediately on the element.

Change Options

You can change the options on an AnimationBuilder instance in three different ways. You can also change the defaults for future instances.

Change defaults for future instances

import { AnimationBuilder } from 'css-animator/builder';

AnimationBuilder.defaults.type = 'bounce';
AnimationBuilder.defaults.duration = '1500';

let animator = new AnimationBuilder();

Changing the defaults won't affect instances, that have already been created.

Using chainable set functions

animator
  .setType('bounce')
  .setDuration(1500);

Using setters

animator.type = 'bounce';

if (animator.duration < 1500) {
  animator.duration = 1500;
}

Using setOptions

animator.setOptions({
  type: 'bounce',
  duration: 1500
});

Apply an option

You can apply options, that are related to the animation itself. Supported options are: fillMode, timingFunction, playState, direction, duration and iterationCount.

Settings that are applied are immediately set on the element, without the need for starting an animation or saving them on the instance. css-animator can't take care of resetting the element though, so be careful with this feature.

animator
  .applyIterationCount(element, 3);

You can also save a value and apply it afterwards:

animator
  .setIterationCount(3)
  .applyIterationCount(element);

Options

disabled (default: false)

Setting this option to true on an AnimationBuilder instance bypasses animations and shows or hides an element immediately, while skipping animations entirely. It is also possible to disable animations for all instances by changing the global value:

import { AnimationBuilder } from 'css-animator/builder';

AnimationBuilder.disabled = true;

fixed (default: false)

As mentioned above, elements being animated are positioned absolute. If you want to change the position mode to fixed, set the fixed option to true.

Setting this option to true results in a more accurate positioning, as css-animator won't round to the nearest full pixel (integer instead of float). But keep in mind, that you might experience unexpected behavior when scrolling while an element is being animated.

reject (default: true)

The promise for an animation is rejected with animation_aborted, if it is interrupted somehow. To change this behavior, set the reject option to false.

useVisibility

AnimationBuilder uses the hidden attribute on elements to hide them. If you want to use the visibility CSS rule, set useVisibility to true.

pin (default: true)

By default, an element will be positioned absolute while animating, to enable concurrent animations. Also the relative position (top and left) will be calculated and set on the element and the margin is set to 0px. Furthermore the element's calculated width and height will be set explicitly. If you want css-animator to only apply the animation, without changing the element's style temporarily, set pin to false.

type (default: 'shake')

The class that will be applied to the element alongside animated and animated-show, if the element is being shown, or animated-hide, if the element is being hidden.

fillMode (default: 'none')

See CSS animation properties.

timingFunction (default: 'ease')

See CSS animation properties.

playState (default: 'running')

See CSS animation properties.

direction (default: 'normal')

See CSS animation properties.

duration (default: 1000)

Set the animation duration as integer in ms.

delay (default: 0)

Set a delay, before the animation should start as integer in ms.

iterationCount (default: 1)

See CSS animation properties.

AnimationBuilder

animate

animate(element: HTMLElement, mode = AnimationMode.Animate): Promise<HTMLElement>

Simply animate an element.

show

show(element: HTMLElement): Promise<HTMLElement>

Animate an element, that was previously hidden.

Calling show is equivalent to:

import { AnimationMode } from 'css-animator/builder';
animator.animate(element, AnimationMode.Show);

hide

hide(element: HTMLElement): Promise<HTMLElement>

Adds the attribute hidden to the element after the animation has finished. You may need to add something like [hidden] { display: none; } to your CSS.

Again you can also use the animate function by passing AnimationMode.Hide.

stop

stop(element: HTMLElement, reset = true): Promise<HTMLElement>

setOptions

Stop the current animation on an element, reset it's position, reject the promise and remove the event listener that listens for animation end.

setOptions(options: AnimationOptions): AnimationBuilder

Set multiple options at once.

set{Option}

set{Option}(option: string|number|boolean): AnimationBuilder

You may set options individually like setDuration(500)

addAnimationClass

addAnimationClass(name: string): AnimationBuilder

Adds your custom classes while animating alongside the classes animated animated-{mode} (where mode is show, hide or default, unless you pass another string to the animate method).

removeAnimationClass

removeAnimationClass(name: string): AnimationBuilder

Won't add classes for future animations, previously added with addAnimationClass.

You can also directly apply options without saving it to the animation builder by using apply{Option}(options: string|number)
Also there are getters and setters for each option, you can access with animator.{option}.

reset

reset(element: HTMLElement, removePending = true, rejectTimeouts = false, rejectListeners = false): void

dispose

dispose(): void

Removes all elements, timeouts and listeners. Call if you don't want to use the builder anymore:

let animator = new AnimationBuilder();
animator.dispose();
animator = null;

AnimatesDirective

start

start(options?: AnimationOptions): Promise<HTMLElement>

Animates the element.

show

show(options?: AnimationOptions): Promise<HTMLElement>

Shows an element that was hidden.

hide

hide(options?: AnimationOptions): Promise<HTMLElement>

Hides an element by adding the attribute hidden to the element after the animation has finished. You may need to add something like [hidden] { display: none; } to your CSS.

stop

stop(): void

Stops the current animation on an element, resets it's position, and removes the event listener that listens for animation end.

startOrStop

startOrStop(options?: AnimationOptions)

Calls start if the element was already started and stop otherwise.

pause

pause(): void

Pauses the animation (sets the playState option to paused).

resume

resume(): void

Resumes a previously paused animation (sets the playState option to running).

toggle

toggle(): void

Switches between pause() and resume().

Build css-animator

$ git clone https://github.com/fabiandev/css-animator.git
$ cd css-animator
$ yarn && yarn build

css-animator's People

Contributors

fabiandev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

css-animator's Issues

Cannot find module "css-animator"

Hello,

I followed the installation process and I get this error message when I want to import the module to my Ionic application. Is it a normal behaviour ?

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { AnimatorModule } from 'css-animator';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';



import { MyApp } from './app.component';
import { SigninPage } from '../pages/signin/signin';

@NgModule({
  declarations: [
    MyApp,
    SigninPage
  ],
  imports: [
    AnimatorModule,
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    SigninPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Thanks,
Alex

undefined this.animator

I have done everything as explained on README but I can't get this working because this.animator is always undefined and this.animator.setType troughs an error.

I imported on app.modules.ts:
import { AnimatorModule } from 'css-animator';

and on my component:
import { AnimationService, AnimationBuilder } from 'css-animator';

zone.js not found

Got an error when trying to use the service.

zone.js:101 GET http://localhost:4200/css-animator 404 (Not Found)

this is my import on main component:

import { AnimationService } from 'css-animator';

@Component({
  // ... usual stuff here
  providers: [
    AnimationService
  ]
})

screen shot 2016-06-03 at 18 13 42

ngRepeat animation (feature)

Is there any possible way to animate the elements that we are adding on a ngRepeat?

I found 2 ways:
A) Adding the classes directly on the tag with the ngRepeat. This is the easiest one but not really functional because we will animate it every time we come back to this view and we have no control over this
B) Adding hidden on the ngRepeat and every time we add one element we add a .show() but doesn't work properly. Maybe because sometimes the animation goes faster than the html and the content doesn't exist yet.

I was thinking on a tag property because this should be managed from the html if I'm not wrong.

Problem with Ionic

Testing now with latest version of Ionic.

If you have the hidden property on your slider this one doesn't work properly (you can't swipe and also looks badly):
<div class="slider-container" #slider hidden>...

If you remove it you can animate it and everything else but the problem comes when you need it hide by default

v3.0 roadmap

  • Implement states for elements
  • Add events (start, pause, resume, interrupt, end)
  • Suggest to use interrupt event and to set reject option to false
  • Probably use promise rejection on dispose for pending actions
  • Keep track of all instances by a static member
  • Think about saving the instance id on the element, to retrieve it (e.g. for setting listeners)
  • Revisit browser compatibility check for CSS rules
  • Think about the Angular2 service to return an instance (singleton) already

Firefox: "TypeError: CSS2Properties doesn't have an indexed property setter for '0'"

Tested in Firefox 52.3.0 and 56.0 (64-bit)

When an animation ends I'm getting:

ERROR TypeError: CSS2Properties doesn't have an indexed property setter for '0'
Stack trace:
["../../../../css-animator/builder/animation_builder.js"]/AnimationBuilder.prototype.removeStyles@http://localhost:4200/vendor.bundle.js:86198:17
["../../../../css-animator/builder/animation_builder.js"]/AnimationBuilder.prototype.reset@http://localhost:4200/vendor.bundle.js:85964:9
["../../../../css-animator/builder/animation_builder.js"]/AnimationBuilder.prototype.animate/</delay<@http://localhost:4200/vendor.bundle.js:85942:17
["../../../../zone.js/dist/zone.js"]/</</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.bundle.js:3004:17
forkInnerZoneWithAngularBehavior/zone._inner<.onInvokeTask@http://localhost:4200/vendor.bundle.js:261263:24
["../../../../zone.js/dist/zone.js"]/</</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.bundle.js:3003:17
["../../../../zone.js/dist/zone.js"]/</</Zone.prototype.runTask@http://localhost:4200/polyfills.bundle.js:2771:28
ZoneTask/this.invoke@http://localhost:4200/polyfills.bundle.js:3066:28
timer@http://localhost:4200/polyfills.bundle.js:4270:17
  vendor.bundle.js:258402:5

and promises end prematurely, neither resolving nor rejecting.

css-animator is not working in IE 11..

css-animator is not working in IE 11. No animations are working also page load animation also not working. and no errors are logging in console. Please help

Animate hidden element (SPA)

When we want to go back one page in Ionic we can use either pop() or dismiss(). We have this previous page already loaded as a SPA app but I'm facing an issue with .show().
First time it's ok because the element is hidden in our template so we execute this .show() and we display it as normally, but when we go back to this page again the element is already displayed and we hide and show it again.

Is there any way to fix this or this is a similar issue like the one I commented here?:
#24 (comment)

Unexpected value AnimatesDirective

Using Angular-cli, when I try to build for production, the following error pops up..

ERROR in Unexpected value 'AnimatesDirective in app.module.ts
Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory'

Disable animations

This is not an issue, just a question.

I've got this option in my app:
captura

Is there any option to disable animations? The only thing I found is this way: this.animator.setDuration(0);
but I'm already changing duration in some places so I'd have to double check this parameter many times.

How can I archive this?

css-animator animation not working Internet Explorer 11/10

Hi All,
I am working online quiz web app.The app is running fine in fire fox as well as chrome.
but Internet explorer , it is showing giving me error uncaught Promise error:animation_aborted.
Because of that ,I can move forward in that question set but not in backward direction. I am stuck in this for last 2 days.Please help me.
-->Yes ,I have added web-animations package in polyfill.ts.

Collapsed Source Code
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/timeInterval';
import 'rxjs/add/operator/take';
import { Router } from '@angular/router';

import { Component, OnInit, Input, Output, EventEmitter, ElementRef } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { AnimationService, AnimationBuilder } from 'css-animator';
import { ErrorsService } from './../../../shared/error.service';
import { DataKey, StorageService } from './../../../shared/storage.service';
import { MzModalService } from 'ng2-materialize';
import { ErrorModalComponent } from './../../../error-modal/error-modal.component';
import { NotificationsService } from 'angular2-notifications';

import { QPService } from './../services/qp.service';
import { Page } from './../../../pages/pages';
import { SanitizeHtmlPipe } from './SanitizeHtmlPipe';


@Component({
  selector: 'app-player-card',
  templateUrl: './player-card.component.html',
  styleUrls: ['./player-card.component.css']
})
export class PlayerCardComponent extends Page implements OnInit {

  @Input() public question: any; // Should be of type Question
  @Output() public showNextButton = new EventEmitter();
  @Output() public hideNextButton = new EventEmitter();

  private _animator: AnimationBuilder;

  private _active: boolean = false;
  private _markedAnswer: number = -1;
  private _countdown = 10;
  private _nextTimeout: any = null;
  private _endTestTimeout: any = null;
  private _preTimeout: any = null;

  constructor(
    private router: Router,
    private _elementRef: ElementRef,
    private _qpService: QPService,
    animationService: AnimationService,
    private service: NotificationsService,
    private errorsService: ErrorsService,
    private storageService: StorageService,
    private modalService: MzModalService
  ) {
    super();
    this._router = router;
    this._animator = animationService.builder().setDuration(600);
    this.subscribeToActivate();
    this.subscribeToClose();
    this.subscribeToNext();
    this.subscribeToPrevious();
    this.subscribeToError();
  }

  ngAfterViewInit() {
    //Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
    //Add 'implements AfterViewInit' to the class.
    $('#qcontent').find('*').removeAttr('style');
    $('.qcontent').find('*').removeAttr('style');
    $(".child").css("max-height", ($(".parent").height()-30));
    $(".qcard").css("max-height", ($(document).height() - ($("#headerdiv").height() + $("#footerdiv1").height() + 15)));
    $(".qcard").css("height", ($(document).height() - ($("#headerdiv").height() + $("#footerdiv1").height() + 15)));
    //$(".qcard").css("height", ($(window).height() - ($("#headerdiv").height()+$("#footerdiv").height())));
    $(".child").css("max-height", ($(".parent").height() -30));
  }

  ngOnInit() {
    setTimeout(() => {
      //console.log("In Ready Method...");
      //console.log(this.question);
      if (this.question.slNo === this._qpService.totalItems) {
        setTimeout(() => {
          this._qpService.ready();
          //console.log("Ready Method Init...");
        }, 100);
      }
    }, 1000);
    $('#qcontent').find('*').removeAttr('style');
    $('.qcontent').find('*').removeAttr('style');
    $(".child").css("max-height", ($(".parent").height()-30));
    $(".qcard").css("max-height", ($(document).height() - ($("#headerdiv").height() + $("#footerdiv1").height() - 15)));
    $(".qcard").css("height", ($(document).height() - ($("#headerdiv").height() + $("#footerdiv1").height() - 15)));

    //$(".qcard").css("height", ($(window).height() - ($("#headerdiv").height()+$("#footerdiv").height())));
    $(".child").css("max-height", ($(".parent").height()-30));

    //$( '.area' ).scrollGuard();
  }

  private subscribeToActivate() {
    let subscription = this._qpService
      .onActivateQuestion.subscribe((event) => {
        if (event.questionNumber === this.question.slNo) {
          console.log("i am insubscribeToActivate .activateQuestion");
          this.activateQuestion(event.isBackward);
          
        } else if (this.active) {
          console.log("i am insubscribeToActivate .deactivateQuestion");
          this.deactivateQuestion(event.isBackward);
          console.log("i am insubscribeToActivate .deactivateQuestion");
        }
      });

    this.disposal.push(subscription);
  }

  private subscribeToClose() {
    let subscription = this._qpService
      .onCompleted
      .subscribe((questionNumber) => {
        if (this._active) {
          this.endTest();
        }

      });
    this.disposal.push(subscription);
  }

  private subscribeToError() {
    let subscription = this._qpService.onError.subscribe((questionNumber) => {
      if (this._active) {
        this.modalService.open(ErrorModalComponent);
        this.networkError();
        console.log('got event');
      }
    });
    this.disposal.push(subscription);
  }

  private subscribeToNext() {
    let subscription = this._qpService
      .onNext
      .subscribe((questionNumber) => {
        if (this._active) {
          // this.endTest();
          this.nextQuestion();
        }

      });
    this.disposal.push(subscription);
  }

  private subscribeToPrevious() {
    let subscription = this._qpService
      .onPrevious
      .subscribe((questionNumber) => {
        if (this._active) {
          //this.endTest();
          this.previousQuestion();
        }

      });
    this.disposal.push(subscription);
  }

  private activateQuestion(isBackward: boolean) {
    this._active = true;
    this.question.isActive = true;
    this._animator.setType('fadeInRight').setDelay(400);
    $('#qcontent').find('*').removeAttr('style');

    $('.qcontent').find('*').removeAttr('style');
    $('.qcontent-img').find('img').css('display', 'block');
    $('#qcontent').find('*').removeAttr('style');
    $('.qcontent').find('*').removeAttr('style');
    $(".child").css("max-height", ($(".parent").height()-30));
    $(".qcard").css("max-height", ($(window).height() - ($("#headerdiv").height() + $("#footerdiv1").height()-14)));
    $(".qcard").css("height", ($(window).height() - ($("#headerdiv").height() + $("#footerdiv1").height()-14)));
    $("#sectionName").text(this.question.sectionName);

    //$(".qcard").css("height", ($(window).height() - ($("#headerdiv").height()+$("#footerdiv").height())));
    $(".child").css("max-height", ($(".parent").height()-30));

    //alert(this.question.title);
    //this._animator.setType('pulse').setDelay(900);
    if (this.question.slNo == 1) {
      this._animator.setType('fadeInUp');
      $('.arrow-left-blue').addClass('hide');
      //this._animator.setType('pulse');
    }
    else {
      $('.arrow-left-blue').removeClass('hide');
    }

    if (this.question.slNo === this._qpService.totalItems) {
      $('.arrow-right-blue').addClass('hide');
    }
    else {
      $('.arrow-right-blue').removeClass('hide');
    }



    if (isBackward !== false) {
      console.log("I am in backward");

      this._animator.setType('fadeInLeft').setOptions({
        reject:false
      });
      //this._animator.setType('pulse');
    }
    this._animator.show(this._elementRef.nativeElement);
  }

  private deactivateQuestion(isBackward: boolean) {
    this._animator.setType('fadeOutLeft').setDelay(0).setDuration(500);
    //this._animator.setType('pulse').setDelay(0).setDuration(600);
    //this.question.status.wasCorrect = this.answerIsCorrect();

    if (this.question.slNo === this._qpService.totalItems) {
      //this._animator.setType('pulse');
      this._animator.setType('fadeOutDown');
      //this._qpService.completed();
    }
    if (isBackward !== false) {
      this._animator.setType('fadeOutRight');
      //this._animator.setType('pulse');
    }
    this._animator.hide(this._elementRef.nativeElement);
    this._active = false;
    this.question.isActive = false;
    console.log("i am in deactivateQuestion");
  }

  public nextQuestion() {
    if (this._nextTimeout !== null) {
      clearTimeout(this._nextTimeout);
    }
    if (!this.hasMarkedAnswer) {
      //return;
    }
    if (this.question.slNo === this._qpService.totalItems) {
      return;
    }

    /*
    if (this.answerIsCorrect()) {
      button.classList.add('green');
    } else {
      button.classList.add('red');
    }
    let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
    this._qpService.submitQuestionResponse(tokenDetails.tokenDetails, this.question, this.hasMarkedAnswer).subscribe(
      result => {
        this._nextTimeout = setTimeout(() => {
          this._qpService.activateQuestion(this.question.slNo + 1, false);
          this._nextTimeout = null;
          //button.classList.remove('red');
          //button.classList.remove('green');
        }, 600);
      },
      err => {
        this.errors = this.errorsService.mapErrors(err, 'Login');
        this.notifyError(this.errors[0]);
      });
    */

    this._nextTimeout = setTimeout(() => {
      this._qpService.activateQuestion(this.question.slNo + 1, false);
      this._nextTimeout = null;
      //button.classList.remove('red');
      //button.classList.remove('green');
    }, 600);
  }

  public previousQuestion() {
    if (this._preTimeout !== null) {
      clearTimeout(this._preTimeout);
      console.log("i am inside prev ques1");
    }

    if (!this.hasMarkedAnswer) {
      console.log("i am inside prev ques2");
    } 
    if (this.question.slNo <= 1) {
      console.log("i am inside prev ques");
      return;
    }

    /*if (this.answerIsCorrect()) {
      button.classList.add('green');
    } else {
      button.classList.add('red');
    }
    let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
    this._qpService.submitQuestionResponse(tokenDetails.tokenDetails, this.question, this.hasMarkedAnswer).subscribe(
      result => {
        this._preTimeout = setTimeout(() => {
          this._qpService.activateQuestion(this.question.slNo - 1, true);
          this._preTimeout = null;
          //button.classList.remove('red');
          //button.classList.remove('green');
        }, 600);
      },
      err => {
        this.errors = this.errorsService.mapErrors(err, 'Login');
        this.notifyError(this.errors[0]);
      });*/

    this._preTimeout = setTimeout(() => {
      this._qpService.activateQuestion(this.question.slNo - 1, true);
      // this._preTimeout = null;
      //button.classList.remove('red');
      //button.classList.remove('green');
    }, 600);

  }

  public networkError() {
    let exitTimeout = setTimeout(() => {
      $("body").trigger("click");
      this.storageService.storeToken(DataKey[DataKey.state], "3");
      this.router.navigate(['#/login'], { queryParams: { error: 'yes' } });
    }, 5000);
  }

  public endTest() {
    if (this._endTestTimeout !== null) {
      clearTimeout(this._endTestTimeout);
    }

    if (this.question.isMultipleInteraction) {

      let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
      this._qpService.endTest(tokenDetails.tokenDetails, this.question.playerItemChild[0], this.hasMarkedAnswer, this.question.slNo).subscribe(
        result => {
          this._endTestTimeout = setTimeout(() => {
            this.deactivateQuestion(false);
            this._endTestTimeout = null;
            $("body").addClass('ins-body');
            this.storageService.storeToken(DataKey[DataKey.state], "3");
            this.router.navigate(['/final']);
          }, 600);
        },
        err => {
          console.log('error!!!');
          this._qpService.error();
          this.errors = this.errorsService.mapErrors(err, 'Login');
          this.notifyError(this.errors[0]);
        });
    }
    else {

      let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
      this._qpService.endTest(tokenDetails.tokenDetails, this.question, this.hasMarkedAnswer, this.question.slNo).subscribe(
        result => {
          this._endTestTimeout = setTimeout(() => {
            this.deactivateQuestion(false);
            this._endTestTimeout = null;
            $("body").addClass('ins-body');
            this.storageService.storeToken(DataKey[DataKey.state], "3");
            this.router.navigate(['/final']);
          }, 600);
        },
        err => {
          console.log('error!!!');
          this._qpService.error();
          this.errors = this.errorsService.mapErrors(err, 'Login');
          this.notifyError(this.errors[0]);
        });

    }
  }

  public completeTest() {
    this._qpService.completed();
  }

  public flagQuestion(index) {
    if (!this.question.isMultipleInteraction) {
      if (this.question.flaged) {
        this.question.flaged = false;
      }
      else {
        this.question.flaged = true;
      }
    }
    else {
      if (this.question.playerItemChild[index].flaged) {
        this.question.playerItemChild[index].flaged = false;
      }
      else {
        this.question.playerItemChild[index].flaged = true;
      }
    }

  }

  public answerClicked(index, checked, answer, answerIndex) {
    if (!checked) {
      this._markedAnswer = -1;
      return;
    }
    if (this.question.isMultipleInteraction) {

      this.question.playerItemChild[index].answered = true;
      this.question.playerItemChild[index].status.answered = true;
      this.question.playerItemChild[index].status.selectedAnswer = answerIndex;
      this.question.playerItemChild[index].status.selectedAnswerId = answer.identifier;
      this._markedAnswer = answerIndex;
      let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
      this._qpService.submitQuestionResponse(tokenDetails.tokenDetails, this.question.playerItemChild[index], this.hasMarkedAnswer, this.question.slNo).subscribe(
        result => {
          /* this._nextTimeout = setTimeout(() => {
             this._qpService.activateQuestion(this.question.slNo + 1, false);
             this._nextTimeout = null;
             //button.classList.remove('red');
             //button.classList.remove('green');
           }, 600);*/
        },
        err => {
          console.log('error!!!');
          this._qpService.error();
          this.errors = this.errorsService.mapErrors(err, 'Login');
          this.notifyError(this.errors[0]);
        });

    }
    else {
      this.question.answered = true;
      this.question.status.answered = true;
      this.question.status.selectedAnswer = index;
      this.question.status.selectedAnswerId = answer.identifier;
      this._markedAnswer = index;
      let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
      this._qpService.submitQuestionResponse(tokenDetails.tokenDetails, this.question, this.hasMarkedAnswer, this.question.slNo).subscribe(
        result => {
          /* this._nextTimeout = setTimeout(() => {
             this._qpService.activateQuestion(this.question.slNo + 1, false);
             this._nextTimeout = null;
             //button.classList.remove('red');
             //button.classList.remove('green');
           }, 600);*/
        },
        err => {
          this._qpService.error();
          this.errors = this.errorsService.mapErrors(err, 'Login');
          this.notifyError(this.errors[0]);
        });

    }

  }

  public clearAns(index) {
    if (this.question.isMultipleInteraction) {
      this.question.playerItemChild[index].answered = false;
      this.question.playerItemChild[index].status.answered = false;
      this.question.playerItemChild[index].status.selectedAnswer = "";
      this.question.playerItemChild[index].status.selectedAnswerId = "";
      //this._markedAnswer = -1;
      let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
      this._qpService.submitQuestionResponse(tokenDetails.tokenDetails, this.question.playerItemChild[index], false, this.question.slNo).subscribe(
        result => {
          let res = false;
          $("input[name='answers-rc" + this.question.playerItemChild[index].id + "']").removeAttr('checked');
          $("input[name='answers-rcm" + this.question.playerItemChild[index].id + "']").removeAttr('checked');
          $("input[name='answers-rc" + this.question.playerItemChild[index].id + "']").parent().removeClass('selected_ans');
          $("input[name='answers-rcm" + this.question.playerItemChild[index].id + "']").parent().removeClass('selected_ans');
          //$("input[name='answers"+this.question.id+"']").attr("checked", 'fasle');
          //$("input[name='answersanswersQ2431925']").attr("checked", "false");
        },
        err => {
          console.log('error!!!');
          this._qpService.error();
          this.errors = this.errorsService.mapErrors(err, 'Login');
          this.notifyError(this.errors[0]);
        });
    }
    else {
      this.question.answered = false;
      this.question.status.answered = false;
      this.question.status.selectedAnswer = "";
      this.question.status.selectedAnswerId = "";
      this._markedAnswer = -1;
      let tokenDetails = JSON.parse(this.storageService.getStoredData(DataKey[DataKey.testMeta]));
      this._qpService.submitQuestionResponse(tokenDetails.tokenDetails, this.question, this.hasMarkedAnswer, this.question.slNo).subscribe(
        result => {
          /* this._nextTimeout = setTimeout(() => {
             this._qpService.activateQuestion(this.question.slNo + 1, false);
             this._nextTimeout = null;
             //button.classList.remove('red');
             //button.classList.remove('green');
           }, 600);*/
          let res = false;
          $("input[name='answers" + this.question.id + "']").removeAttr('checked');
          $("input[name='answers" + this.question.id + "']").parent().removeClass('selected_ans');
          //$("input[name='answers"+this.question.id+"']").attr("checked", 'fasle');
          //$("input[name='answersanswersQ2431925']").attr("checked", "false");
        },
        err => {
          console.log('error!!!');
          this._qpService.error();
          this.errors = this.errorsService.mapErrors(err, 'Login');
          this.notifyError(this.errors[0]);
        });
    }
  }

  get hasMarkedAnswer() {
    return this._markedAnswer > -1;
  }

  get markedAnswer() {
    return this._markedAnswer;
  }

  get active() {
    return this._active;
  }

  get countdown() {
    return this._countdown;
  }

  get qpService() {
    return this._qpService;
  }

  ngOnDestroy() {
    // prevent memory leak when component destroyed
    this.disposal.forEach(s => s.unsubscribe());
  }

}

Add an Angular2 demo

please add a demo, we can refer.

Directive

Click me!

ERROR!

'{ selector: string; styles: any[]; templateUrl: string; directives: typeof AnimatesDirective[]; }'

Security Risk ElementRef

Hey,
first thanks for this nice tool. I started to use it and it works great.

But as I looked around I have a look at the angular docs and found that ElementRef could be a security risk. https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html

They suggest to use their Render which is at EXPERIMENTAL state at the moment.

No the question is: Is it possible to use your tool with the renderer? Or are their no security risks if you only use ElementRef for animation?

Animate on ngFor

I've got this ngFor:

<div class="ball-container" *ngFor="let ball of unit.balls; let i = index">
    <div class="ball">{{i + 1}}</div>
</div>

Each value of the array is an empty content (unitBalls.push({});).

How can I add/remove this elements with an animation?

Some animations do not work properly

The point is that when I call some animations (couldn't try with all of them) I face some issues: the html content does like a jump, executes de animation and comes back to his first position.

Let say about tada animation (https://daneden.github.io/animate.css/). It moves like 5px down when it's animating and it comes up 5px back again.

I was inspecting how works animate.css on previous link and I realised that it applies 2 classes: animated and tada.

The only different here using css-animator (as you will know) is that it adds animated, tada and animated-show (nothing happens adding manually this class to my html) BUT also all of this style directly to the html:
style="visibility: visible; position: absolute; top: 0px; left: 0px; width: 201px; height: 39px; margin: 0px; animation-fill-mode: none; animation-timing-function: ease; animation-play-state: running; animation-direction: normal; animation-duration: 1000ms; animation-iteration-count: 1;"

So the problem here comes with this:

position: absolute;  
top: 0px; 
left: 0px; 
width: 201px; 
height: 39px; 
margin: 0px; 

So why we need this code for?

If I add these 2 classes (animated and tada) directly to my element it does the animation properly so that's why I know is not either animate.css or my html/css problem.

Trying with Chrome

v2.0 roadmap

  • Improve gulp tasks
  • Improve positioning and applied styles while animating
  • Fix flickering that sometimes occurs when animating with show
  • Performance improvements
  • Code cleanup
  • Look into staggering animation #6 (use promise of the animation builder to chain animations)
  • Ability to animate invisible elements and keep the space occupied #1
  • Include source files (typings are included, for source files clone from git)
  • Rethink promise rejection if animation is aborted
  • Make available via next tag: yarn add css-animator@next
  • Merge to master
  • Release version v2.0.1

css-animator not working with ng9

When compile/build with Angular 9.1 (latest), the build is failing after adding AnimationService, AnimatorModule into my module. I get an error like below:

This likely means that the library (css-animator) which declares AnimatorModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.