fabiandev / css-animator

Animate elements using CSS classes with support for Angular.

Home Page:https://fabiandev.github.io/css-animator/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

css-animator animation not working Internet Explorer 11/10

pinku-4132 opened this issue · comments

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());
  }

}

I am considering to not reject the promise if an animation is aborted in a next version of css-animator, however, currently if an animation could not be finished entirely, or it is replaced by a new animation, an error is thrown. I've also experienced that this sometimes causes unexpected exceptions.

Anyway, in the meantime you can make use of a custom error handler for your Angular app, as it can be seen in angular2-quiz-app. You can take a look at src/js/facades/error_handler.ts, which defines a custom error handler, and src/js/modules/app.module.ts, where the error handler is provided to the app. Basically it ignores exceptions with the message animation_aborted globally. Feel free to adjust the code to your needs.

Thank you for the quick response.I wanted to use your custom error handler .But how do i get this dependency.
import { WrappedError } from '@angular/core/src/facade/errors';

The API of Angular has changed (see angular/error_handler.ts), which you have to align to. You could try something like the following:

import { Injectable, ErrorHandler } from '@angular/core';

@Injectable()
export class AppErrorHandler extends ErrorHandler {

  constructor() {
    super();
  }

  public handleError(error: any): void {
    if (this.isAnimationAbortedError(error)) {
      return;
    }
    
    super.handleError(error);
  }

  private isAnimationAbortedError(error: any): boolean {
    return !!error
      && typeof error.message === 'string'
      && error.message.indexOf('animation_aborted') !== -1;
  }

}

I'm currently updating angular2-quiz-app to the latest Angular version and was running into issues when omitting the constructor, so you may also want to add it:

@Injectable()
class AppErrorHandler extends ErrorHandler {
  constructor() {
    super();
  }
}

I've updated my previous comment accordingly.

Thank you for all your responses . By doing this we are able to handle our error in IE.But i am not able to keep these animations in Internet Explorer.
Does your quiz app: https://github.com/fabiandev/angular2-quiz-app works on internet explorer 11?

IE 11 requires polyfills that were not included in this package, but I've just pushed an update to this repo. Can you try if https://fabiandev.github.io/css-animator/ works in IE 11 for you? I have no possibility to test.

Still it is not working. I am able to load this https://fabiandev.github.io/css-animator/ . But when i tried to click on shake/hide/show ,then it is showing me an error of like this.
Unable to get property 'apply' of undefined or null reference.
if possible ,include these also
Run: npm i mdn-polyfills --save
Use: import 'mdn-polyfills/Object.assign';
Probably this may save our problem.Referred from this url,
https://stackoverflow.com/questions/41276692/angular2-ie11-unable-to-get-property-apply-of-undefined-or-null-reference.

And My polyfills.ts looks like this,
`/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import "core-js/client/shim";
// import 'core-js/shim';
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/promise';
// import 'es6-shim/es6-shim.js';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/typed';
import 'core-js/es6/weak-map';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
import 'classlist.js'; // Run npm install --save classlist.js.
// import 'es6-shim/es6-shim.js';

/** IE10 and IE11 requires the following to support @angular/animation. */
import 'web-animations-js'; // Run npm install --save web-animations-js.

/** Evergreen browsers require these. **/
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'core-js/es7/observable';

/** ALL Firefox browsers require the following to support @angular/animation. **/
import 'web-animations-js'; // Run npm install --save web-animations-js.

/***************************************************************************************************

  • Zone JS is required by Angular itself.
    */
    import 'zone.js/dist/zone'; // Included with Angular CLI.

/***************************************************************************************************

  • APPLICATION IMPORTS
    */

/**

  • Date, currency, decimal and percent pipes.
  • Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
    */
    import 'intl'; // Run npm install --save intl.
    `

Can you please provide the stack trace of the error Unable to get property 'apply' of undefined or null reference.?

Since I cannot test in IE11, it would be great if you could determine which polyfill is missing for the demo. Currently the following are imported:

import 'classlist.js/classList';
import 'core-js/es6/map';
import 'core-js/es6/promise';
import 'core-js/fn/object/assign';

Also these polyfills are just bundled in the demo and will be provided as a separate file in a future release of this package, as I do not want to add any hard dependencies that may not be required in certain situations.

@pinku-4132 could you identify which polyfills are required for IE11?

Closing this issue as I think this library should be kept as small as possible and therefore polyfills should not be bundled but provided by developers if required. Feel free to start a new discussion on this topic.