<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>angular 5 + flex layout</title>
    
    <style>
        my-app {
            font-size: 1.2em;
        }
        
        input[type=checkbox] {
            width: 20px;
            height: 20px;
            cursor: pointer;
        }
    </style>
    
     <!-- polyfill(s) for older browsers -->
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>

    <script src="https://unpkg.com/zone.js@0.8.16?main=browser"></script>
    <!--<script src="https://unpkg.com/reflect-metadata@0.1.10"></script>-->
    <script src="https://unpkg.com/systemjs@0.20.18/dist/system.src.js"></script>
    <script src="https://unpkg.com/web-animations-js@2.3.1"></script>
  

    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function (err) { console.error(err); });
    </script>
  </head>

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

</html>
//our root app component
import { Component, NgModule, VERSION} from '@angular/core'
import { BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <p>Enter readonly mode <input type=checkbox [(ngModel)]="isReadOnly"></p>
    <div class="editor" [appDisabled]="isReadOnly">
        <div class="toolBar">
            <app-button><span style="font-weight: bold;">B</span></app-button>
            <app-button><span style="text-style: italic;">I</span></app-button>
            <app-button><span style="text-decoration: underline;">U</span></app-button>
            <app-button [appDisabled] [disabledStopPropagation]="true">Fullscreen</app-button>
        </div>
        <app-edit-area></app-edit-area>
    </div>
  `,
  styles: [`
    .editor {
        width: 300px;
    }
    app-edit-area {
        width: 100%;
        height: 200px;
        margin-top: 5px;
    }
  `]
})
export class AppComponent {
  public isReadOnly: boolean = false;
}
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { ButtonComponent } from './button.component';
import { DisabledDirective } from './disabled.directive';
import { EditAreaComponent } from './editarea.component';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        FormsModule,
    ],
    declarations: [
        AppComponent,
        ButtonComponent,
        DisabledDirective,
        EditAreaComponent
    ],
    providers: [
      
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { 
    Component, 
    NgModule, 
    VERSION, 
    Optional, 
    ChangeDetectorRef
} from '@angular/core'

import {DisabledDirective, resolve} from './disabled.directive';

@Component({
  selector: 'app-button',
  template: `
        <button [disabled]="disabled"><ng-content></ng-content></button>
  `,
  styles: [`
    button {
        min-width: 40px;
        height: 40px;
    }
  `]
})
export class ButtonComponent {
    private disabledDirective: DisabledDirective;
    
    constructor(changeDetector: ChangeDetectorRef, @Optional() optDisabled: DisabledDirective) {
        this.disabledDirective = resolve(optDisabled);
        this.disabledDirective.onChange(this, (newValue) => {
            changeDetector.markForCheck();
        });
    }
    
    get disabled(): boolean {
        return this.disabledDirective.disabled;
    }
}
import {
    ChangeDetectorRef,
    Directive,
    EventEmitter,
    ElementRef,
    Input,
    NgZone,
    OnChanges,
    OnDestroy,
    Optional,
    Output,
    SkipSelf
} from '@angular/core';

@Directive({
    selector: '[appDisabled]',
})
export class DisabledDirective implements OnDestroy, OnChanges {
    @Output() disabledChange: EventEmitter<boolean> = new EventEmitter<boolean>(false);
    @Input() appDisabled: boolean = false;
    @Input() disabledStopPropagation: boolean = false;
    
    private disabled: boolean = false;
    private element: HTMLElement;

    constructor(
        private elementRef: ElementRef,
        @SkipSelf() @Optional() private optParent: DisabledDirective,
        @Optional() private changeDetector: ChangeDetectorRef,
        @Optional() private zone: NgZone,
    ) {
        this.disabledChange = new EventEmitter<boolean>(false);

        if (optParent) {
            optParent.onChange(this, () => this.checkForChanges());
        }
    }
    
    ngOnInit() {
        this.element = this.elementRef.nativeElement;
    }

    private checkForChanges() {
        setTimeout(() => {
            let newValue = false;

            if (this.disabledStopPropagation || !this.optParent) {
                newValue = !!this.appDisabled;
            } else {
                newValue = !!this.appDisabled || this.optParent.disabled;
            }

            if (this.zone && newValue != this.disabled) {
                this.zone.run(() => {
                    if (this.changeDetector) {
                        this.changeDetector.markForCheck();
                    }
                    this.disabled = newValue;
                    this.disabledChange.emit(newValue);
                });
            }
        }, 0);
    }

    ngOnChanges() {
        this.checkForChanges();
    }
    
    /**
     * Alerts the callback when the disabled state changes
     */
    onChange(directive: DisabledDirective, callback: (opt?: boolean) => void) {
        const result = this.disabledChange.subscribe(callback);
    }
}

const defaultDisabled = new DisabledDirective(null, null, null);
export function resolve(optDisabled?: DisabledDirective): DisabledDirective {
    return optDisabled || defaultDisabled;
};

const DISABLED_OPACITY = 0.3;

@Directive({
    selector: '[appDefaultDisabled]',
    host: {
        '[style.opacity]': 'disabled ? ' + DISABLED_OPACITY + ' : undefined',
        '[style.pointerEvents]': 'disabled ? "none" : undefined',
    },
})
export class DefaultDisabledStateDirective {
    disabledDirective: DisabledDirective;
    get disabled(): boolean {
        return this.disabledDirective.disabled;
    }

    constructor(@Optional() optDisabled: DisabledDirective, changeDetector: ChangeDetectorRef) {
        this.disabledDirective = resolve(optDisabled);
    }
}
import { 
    Component, 
    NgModule, 
    VERSION, 
    Optional, 
    ChangeDetectorRef
} from '@angular/core'

import {DisabledDirective, resolve} from './disabled.directive';

@Component({
  selector: 'app-edit-area',
  template: `
        <textarea class="editArea" [disabled]="disabled">
This is a prototype of a simple editor.

Here's some content.
        </textarea>
  `,
  styles: [`
    :host {display: block;}
    .editArea {
        width: 100%;
        height: 100%;
        padding: 10px;
    }
    
  `]
})
export class EditAreaComponent {
    private disabledDirective: DisabledDirective;
    
    constructor(changeDetector: ChangeDetectorRef, @Optional() optDisabled: DisabledDirective) {
        this.disabledDirective = resolve(optDisabled);
        this.disabledDirective.onChange(this, (newValue) => {
            // perform additional actions on this when the disabled status (coming from a directive) changes
            changeDetector.markForCheck();
        });
    }
    
    get disabled(): boolean {
        return this.disabledDirective.disabled;
    }
}
(function (global) {
  var angVer = '5.0.0-beta.6';
 
  System.config({
    transpiler: 'ts',
    typescriptOptions: {
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "lib": [ "es2015", "dom" ],
      "module": "commonjs",
      "moduleResolution": "node",
      "noImplicitAny": true,
      "sourceMap": true,
      "suppressImplicitAnyIndexErrors": true,
      "target": "es5"
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    paths: { 
      'npm:': 'https://unpkg.com/',
      'gh:': 'https://raw.githubusercontent.com/'
    },
    map: {
      "app": "app",
      "rxjs": "npm:rxjs@5.4.3",
      "ts": "npm:plugin-typescript@7.1.0/lib/plugin.js",
      "typescript": "npm:typescript@2.4.2/lib/typescript.js",
      "@angular/core": "npm:@angular/core@" + angVer + "/bundles/core.umd.js",
      "@angular/common": "npm:@angular/common@" + angVer + "/bundles/common.umd.js",
      "@angular/compiler": "npm:@angular/compiler@" + angVer + "/bundles/compiler.umd.js",
      "@angular/platform-browser": "npm:@angular/platform-browser@" + angVer + "/bundles/platform-browser.umd.js",
      "@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@" + angVer + "/bundles/platform-browser-dynamic.umd.js",
      "@angular/http": "npm:@angular/http@" + angVer + "/bundles/http.umd.js",
      "@angular/router": "npm:@angular/router@" + angVer + "/bundles/router.umd.js",
      "@angular/forms": "npm:@angular/forms@" + angVer + "/bundles/forms.umd.js",
      "@angular/animations": "npm:@angular/animations@" + angVer + "/bundles/animations.umd.js",
      "@angular/animations/browser": "npm:@angular/animations@" + angVer + "/bundles/animations-browser.umd.js",
      "@angular/platform-browser/animations": "npm:@angular/platform-browser@" + angVer + "/bundles/platform-browser-animations.umd.js",
      "@angular/flex-layout": "npm:@angular/flex-layout@2.0.0-beta.9"
},
    // 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'
      }
    }
  });

  if (!global.noBootstrap) { bootstrap(); }

  // Bootstrap the `AppModule`(skip the `app/main.ts` that normally does this)
  function bootstrap() {

    // Stub out `app/main.ts` so System.import('app') doesn't fail if called in the index.html
    System.set(System.normalizeSync('app/main.ts'), System.newModule({ }));

    // bootstrap and launch the app (equivalent to standard main.ts)
    Promise.all([
      System.import('@angular/platform-browser-dynamic'),
      System.import('app/app.module')
    ])
    .then(function (imports) {
      var platform = imports[0];
      var app      = imports[1];
      platform.platformBrowserDynamic().bootstrapModule(app.AppModule);
    })
    .catch(function(err){ console.error(err); });
  }
})(this);