<!DOCTYPE html>
<html>

  <head>
    <title>angular2 playground</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.angularjs.org/2.0.0-beta.15/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/tools/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.js"></script>
    <script src="config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/angular2.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/router.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/http.dev.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <my-app>
      loading...
    </my-app>
  </body>

</html>
.collapse {
    display: none;
}

.collapse.in {
    display: block;
}

.collapsing {
    position: relative;
    height: 0;
    overflow: hidden;
    -webkit-transition-timing-function: ease;
    -o-transition-timing-function: ease;
    transition-timing-function: ease;
    -webkit-transition-duration: .35s;
    -o-transition-duration: .35s;
    transition-duration: .35s;
    -webkit-transition-property: height, visibility;
    -o-transition-property: height, visibility;
    transition-property: height, visibility;
}
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src"
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {provide} from 'angular2/core';
import {AppComponent} from './app';
import {ROUTER_PROVIDERS, LocationStrategy, HashLocationStrategy} from 'angular2/router';

bootstrap(AppComponent, [ROUTER_PROVIDERS])
  .catch(err => console.error(err));
//our root app component
import {Component, Directive, Renderer, HostListener, ViewChildren, ElementRef} from 'angular2/core'

import {Collapse} from './collapse.ts';

@Component({
    selector: 'my-app',
    directives: [Collapse],
    template: `
    <style>
      .my-box {
        border: 1px solid red;
        padding: 10px;
        background-color: lightgreen;
      }
      /* Add support for padding animation for smooth hide/show */
      .collapsing {
          -webkit-transition-property: height, visibility, padding;
          -o-transition-property: height, visibility, padding;
          transition-property: height, visibility, padding;
      }
    </style>
    <h1>Native slide toggle / collapse for Angular 2 and Animate</h1>
    <h2>Written as a demo for a <a target="_blank" href="http://blog.assaf.co/native-slide-toggle-for-angular-2-and-animate/">blog post</a> walkthrough.</h2>
     <button (click)="collapsed = !collapsed">Toggle Collapse</button>
     <div class="my-box" [collapse]="collapsed" [duration]="duration">
        <h4>Native slide toggle / collapse for Angular 2 and Animate</h4>
        <h4>Native slide toggle / collapse for Angular 2 and Animate</h4>
        <h4>Native slide toggle / collapse for Angular 2 and Animate</h4>
        <h4>Native slide toggle / collapse for Angular 2 and Animate</h4>
        <h4>Native slide toggle / collapse for Angular 2 and Animate</h4>
        <h4>Native slide toggle / collapse for Angular 2 and Animate</h4>
     </div>
    `,
})
export class AppComponent {
  private collapsed: boolean = false;
  
  // change this value to control animation duration.
  private duration: number = 1000;
  
  constructor() {
  }
  
}
import {Directive, OnChanges, ElementRef, Input} from 'angular2/core';
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
import {CssAnimationBuilder} from 'angular2/src/animate/css_animation_builder';

@Directive({
    selector: '[collapse]',
    host: {
        '[attr.aria-expanded]': '!collapse',
        '[attr.aria-hidden]': 'collapse'
    }
})
export class Collapse implements OnChanges {
  @Input() duration: number = 500;
  @Input() collapse: boolean;
  private _animation: CssAnimationBuilder;

  constructor(animationBuilder:AnimationBuilder, private _element:ElementRef) {
    this._animation = animationBuilder.css();
  }

  ngOnChanges(changes) {
    if (changes.collapse) {
      if (this.collapse) {
        this.hide()
      } else {
        this.show();
      }
    }
  }
  
  hide(): void {
    this._baseSequence
      .setFromStyles({
        height: this._element.nativeElement.scrollHeight + 'px',
        overflow: 'hidden'
      })
      .setToStyles({
        height: '0',
        paddingTop: '0',
        paddingBottom: '0'
      });
      
    let a = this._animation.start(this._element.nativeElement);
    a.onComplete(() => {
      a.removeClasses(['in']); // rapid change will leave in
      a.addClasses(['collapse']);
    });
  }

  show(): void {
    this._animation
      .setDuration(0)
      .addClass('in')
      .setFromStyles({
        overflow: 'hidden'
      })
      .setToStyles({
        paddingTop: '',
        paddingBottom: ''
      })
      .start(this._element.nativeElement)
      .onComplete(() => {
        let a = this._baseSequence
          .setFromStyles({
            height: '0' 
          })
          .setToStyles({
            height: this._element.nativeElement.scrollHeight + 'px'
          })
          .start(this._element.nativeElement);
          
        a.onComplete(() =>  a.addClasses(['collapse', 'in'])  );
    });
  }
    
  private get _elementHeight(): number {
    let el = this._element.nativeElement;
    var height = el.offsetHeight;
    var style = getComputedStyle(el);

    height += parseInt(style.marginTop) + parseInt(style.marginBottom);
    return height;
  }
  
  private get _baseSequence(): CssAnimationBuilder {
    return this._animation
      .setDuration(this.duration)
      .removeClass('collapse')
      .removeClass('in')
      .addAnimationClass('collapsing')
  }
}