import { Component } from '@angular/core';
import { HomePage } from './home.page';

@Component({
  template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class AppComponent {

  rootPage = HomePage;

}


/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IonicApp, IonicModule } from 'ionic-angular';

import { AppComponent } from './app.component';
import { ElasticTextArea } from './elastic-text-area';
import { HomePage } from './home.page';

@NgModule({
  imports: [ BrowserModule, IonicModule.forRoot(AppComponent) ],
  declarations: [ AppComponent, ElasticTextArea, HomePage ],
  entryComponents: [ HomePage ],
  bootstrap: [ IonicApp ]
})
export class AppModule { }


/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);


/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<!DOCTYPE html>
<html>
  <head>
    <title>Ionic 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- 1. Load libraries -->
     <!-- Polyfill(s) for older browsers -->
    <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>

    <script src="https://unpkg.com/zone.js@0.6.26?main=browser"></script>
    <script src="https://unpkg.com/systemjs@0.19.40/dist/system.src.js"></script>

    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <link href="https://unpkg.com/ionic-angular@3.1.1/css/ionic.css" rel="stylesheet">
  </head>

  <!-- 3. Display the application -->
  <body>
    <ion-app></ion-app>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
  </body>
</html>


<!-- 
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
### Ionic 2 Plunk

Basic Ionic 2 plunk based on the Angular QuickStart plunk.
/**
 * PLUNKER VERSION
 * (based on systemjs.config.js in angular.io)
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    typescriptOptions: {
      tsconfig: true
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    paths: {
      // paths serve as alias
      'npm:': 'https://unpkg.com/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',

      // angular bundles
      '@angular/core': 'npm:@angular/core@4.0.2/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common@4.0.2/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler@4.0.2/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser@4.0.2/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic@4.0.2/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http@4.0.2/bundles/http.umd.js',
      '@angular/forms': 'npm:@angular/forms@4.0.2/bundles/forms.umd.js',
  
      'ionic-angular': 'npm:ionic-angular@3.1.1',
      'rxjs': 'npm:rxjs@5.1.1',
      'ts': 'npm:plugin-typescript@5.2.7/lib/plugin.js',
      'typescript': 'npm:typescript@2.2.1/lib/typescript.js',

    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.ts',
        defaultExtension: 'ts'
      },
      rxjs: {
        defaultExtension: 'js'
      },
      'ionic-angular': {
        main: './umd/index.js',
        defaultExtension: 'js'
      }
    }
  });
})(this);


/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true
  }
}
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'app/home.page.html'
})
export class HomePage {
  appName = 'Ionic 2 Elastic TextArea';
  description: string;

  constructor(public navController: NavController) {
    this.description1 = 'Ionic apps are created and developed primarily through the Ionic command line utility (the “CLI”), and use Cordova to build and deploy as a native app.\n\nThis means we need to install a few utilities to get developing.\n\n\For those building native apps for iOS and Android (most of you!), each platform has certain features and installation requirements before you can get the most out of your Ionic and Cordova development.';
    this.description2 = 'Ionic apps are created and developed primarily through the Ionic command line utility (the “CLI”), and use Cordova to build and deploy as a native app.\n\nThis means we need to install a few utilities to get developing.\n\n\For those building native apps for iOS and Android (most of you!), each platform has certain features and installation requirements before you can get the most out of your Ionic and Cordova development.';
  }
}
<ion-header>
  <ion-navbar>
    <ion-title>{{ appName }}</ion-title>
  </ion-navbar>
</ion-header>
<ion-content>
  <ion-list>
    <ion-item>
      <ion-label floating>Default</ion-label>
      <ion-textarea [(ngModel)]="description1">
      </ion-textarea>
    </ion-item>
    <ion-item>
      <ion-label floating>Elastic</ion-label>
      <ion-textarea elasticTextArea [(ngModel)]="description2">
      </ion-textarea>
    </ion-item>
  </ion-list>
</ion-content>
import { Directive } from '@angular/core';
import { TextInput, Platform } from 'ionic-angular';

@Directive({
    selector: '[elasticTextArea]'
})
export class ElasticTextArea {
    isIos: boolean;
    iosTextAreaMinHeight = 40;
    mdTextAreaMinHeight = 38;

    constructor(private textInput: TextInput, private platform: Platform) {
        this.isIos = this.platform.is('ios');
    }

    ngOnInit() {
        // Wait for TextInput _native property to initialize.
        setTimeout(() => {
            this.textInput._native.valueChange.subscribe((inputValue: any) => {
                this.resize();
            });

            this.resize();
        });
    }

    resize() {
        let height = this.getTextAreaHeight(this.textInput, this.isIos ? this.iosTextAreaMinHeight : this.mdTextAreaMinHeight);
        this.textInput._native._elementRef.nativeElement.style.height = height + 'px';
    }

    getTextAreaHeight(textArea: TextInput, minHeight: number): number {
        // Get textarea styles.
        let body = <HTMLElement>document.querySelector('body'),
            textAreaElement = textArea._native._elementRef.nativeElement,
            style = window.getComputedStyle(textAreaElement, null),
            paddingHeight = parseInt(style.getPropertyValue('padding-top')) + parseInt(style.getPropertyValue('padding-bottom')),
            paddingWidth = parseInt(style.getPropertyValue('padding-left')) + parseInt(style.getPropertyValue('padding-right')),
            borderHeight = parseInt(style.getPropertyValue('border-top-width')) + parseInt(style.getPropertyValue('border-bottom-width')),
            width = parseInt(style.getPropertyValue('width')) - paddingWidth,
            lineHeight = style.getPropertyValue('line-height');

        // IE and Firefox do not support 'font' property, so we need to get it ourselves.
        let font = style.getPropertyValue('font-style') + ' ' +
            style.getPropertyValue('font-variant') + ' ' +
            style.getPropertyValue('font-weight') + ' ' +
            style.getPropertyValue('font-size') + ' ' +
            style.getPropertyValue('font-height') + ' ' +
            style.getPropertyValue('font-family');

        // Prepare a temporary textarea to determine the height for a real one.
        let newTextAreaElement = <HTMLTextAreaElement>document.createElement('TEXTAREA'),
            newTextAreaElementId = '__newTextAreaElementId__';
        newTextAreaElement.setAttribute('rows', '1');
        newTextAreaElement.setAttribute('id', newTextAreaElementId);
        newTextAreaElement.style.font = font;
        newTextAreaElement.style.width = width + 'px';
        newTextAreaElement.style.border = '0';
        newTextAreaElement.style.overflow = 'hidden';
        newTextAreaElement.style.padding = '0';
        newTextAreaElement.style.outline = '0';
        newTextAreaElement.style.resize = 'none';
        newTextAreaElement.style.lineHeight = lineHeight;

        // To measure sizes we need to add the textarea to DOM.
        body.insertAdjacentHTML('beforeend', newTextAreaElement.outerHTML);
        newTextAreaElement = <HTMLTextAreaElement>document.getElementById(newTextAreaElementId);
        newTextAreaElement.value = textArea.value;

        // Measure the height.
        newTextAreaElement.style.height = 'auto';
        newTextAreaElement.style.height = newTextAreaElement.scrollHeight + 'px';
        let height = parseInt(newTextAreaElement.style.height) + paddingHeight + borderHeight;

        if (height < minHeight) {
            height = minHeight;
        }

        // Remove the remporary textarea.
        body.removeChild(newTextAreaElement);

        return height;
    }
}