<!DOCTYPE html>
<html>
  <head>
    <title>Angular 2 Tabs - Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- CSS file -->
    <link rel="stylesheet" type="text/css" href="style.css">
   <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" >

    <!-- IE polyfills, keep the order please -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.33.3/es6-shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.20/system-polyfills.js"></script>
    
    <!-- Agular 2 -->
    <script src="https://code.angularjs.org/2.0.0-beta.7/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="https://code.angularjs.org/2.0.0-beta.7/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.7/angular2.dev.js"></script>
     
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>
   
     
     <!-- Config Agular 2 and Typescript -->
    <script>
      System.config({
        transpiler: 'typescript', 
        typescriptOptions: { emitDecoratorMetadata: true }, 
        packages: {'app': {defaultExtension: 'ts'}} 
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>

  </head>
 
  <!-- Run the application -->
  <body>
    <h1>Angular 2 Tabs</h1> 
    <my-app class="container" style="display: block">Loading Sample...</my-app>
  
    <div style="padding-top:50px">
    <a target="_blank" href="http://www.angulartypescript.com/angular-2-tutorial/" title="Angular 2 Tutorial"> 
     <img src="http://www.angulartypescript.com/wp-content/uploads/2016/03/learn-more-angular-2.png" alt="Smiley face" height="200" width="500">   
    </a>  
        <ul class="nav nav-pills nav-stacked" >
            <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-tutorial/" title="Angular 2 Home"> Angular 2 Tutorial </a></li>
          <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-introduction/">Angular 2 Introduction</a></li>
          <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-architecture/">Angular 2 Architecture</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-annotations/">Angular 2 Annotations</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-getting-started/">Angular 2 Setup</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-hello-world/">Angular 2 Hello World</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-components/">Angular 2 Components</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-template-syntax/">Angular 2 Template Syntax</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-data-binding/">Angular 2 Data Binding</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-forms/">Angular 2 Forms</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-formbuilder-example/">Angular 2 Formbuilder</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-router-example/">Angular 2 Router</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-http-example-typescript/">Angular 2 HTTP</a></li>
      <li><a target="_blank" href="http://www.angulartypescript.com/angular-2-services/">Angular 2 Service</a></li> 
    
        </ul>
    </div> 
  </body>

</html>
<!-- 
Copyright 2016 angulartypescript.com. All Rights Reserved.
Everyone can use this source code; don’t forget to indicate the source please:
http://www.angulartypescript.com/ 
-->

/* Styles go here */

/**
 * Created by Tareq Boulakjar. from angulartypescript.com
 */
import {bootstrap}  from 'angular2/platform/browser';
import {Angular2Tabs} from './tabs-example';
 
bootstrap(Angular2Tabs);


/*
Copyright 2016 angulartypescript.com. All Rights Reserved.
Everyone can use this source code; don’t forget to indicate the source please:
http://www.angulartypescript.com/ 
*/
/**
 * Created by Tareq Boulakjar. from angulartypescript.com
 */
import {Component, ChangeDetectionStrategy} from 'angular2/core';
import {CORE_DIRECTIVES} from 'angular2/common';
import {Tab} from './tab.directive';
import {Tabset} from './tabset.component';
import {TabHeading} from './tab-heading.directive';

/*Angular 2 Tabs Example*/
@Component({
    selector: 'my-app',
    template: `
                         <div (click)="$event.preventDefault()">
                          <h5>Angular 2 Tabs Example</h5>
                          <hr />
                          <tabset>
                            <tab heading="Home">Home</tab>
                            <tab *ngFor="#aTab of angular2TabsExample"
                                 [heading]="aTab.title"
                                 [active]="aTab.active"
                                 (select)="aTab.active = true"
                                 (deselect)="aTab.active = false"
                                 [disabled]="aTab.disabled"
                                 [removable]="aTab.removable"
                                 (removed)="removeThisTabHandler(aTab)">
                              {{aTab?.content}}
                            </tab>
                            <tab (select)="doOnTabSelect(this)">
                              <template tab-heading>
                                <i class="glyphicon glyphicon-check"></i> On Select Tab!
                              </template>
                              Do action on select a Tab
                            </tab>
                          </tabset>
                          <hr />
                          <p>
                            <button type="button" class="btn btn-primary btn-sm" (click)="angular2TabsExample[0].active = true">Select a Tab from the Array</button>
                         </p>

                        </div>

              `,
    directives: [Tab,Tabset,TabHeading,CORE_DIRECTIVES],
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class Angular2Tabs {
    //dynamic Tabs
    public angular2TabsExample:Array<any> = [
        {title: 'Angular Tab 1', content: 'Angular 2 Tabs are navigable windows, each window (called tab) contains content', disabled: false, removable: true},
        {title: 'Angular Tab 2', content: 'generally we categorize contents depending on the theme', disabled: false, removable: true},
        {title: 'Angular Tab (disabled) X', content: 'Angular 2 Tabs Content', disabled: true, removable: true}
    ];
    //on select a tab do something
    public doOnTabSelect(currentTab:any) {
        console.log("doOnTabSelect"+currentTab);
    };
    //on remove Tab do something
    public removeThisTabHandler(tab:any) {
        console.log('Remove Tab handler'+tab);
    };
}
import {
    Directive,
    OnInit, OnDestroy, DoCheck,
    Input, Output, HostListener, HostBinding,
    TemplateRef, EventEmitter
} from 'angular2/core';
import { NgClass } from 'angular2/common';
import { NgTransclude, IAttribute } from './utils';
import {Tabset} from './tabset.component';

@Directive({selector: 'tab, [tab]'})
export class Tab implements OnDestroy {
    @Input() public heading:string;
    @Input() public disabled:boolean;
    @Input() public removable:boolean;

    @HostBinding('class.active')
    @Input() public get active() {
        return this._active;
    }

    @Output() public select:EventEmitter<Tab> = new EventEmitter();
    @Output() public deselect:EventEmitter<Tab> = new EventEmitter();
    @Output() public removed:EventEmitter<Tab> = new EventEmitter();

    public set active(active) {
        if (this.disabled && active || !active) {
            if (!active) {
                this._active = active;
            }

            this.deselect.emit(this);
            return;
        }

        this._active = active;
        this.select.emit(this);
        this.tabset.tabs.forEach((tab:Tab) => {
            if (tab !== this) {
                tab.active = false;
            }
        });
    }

    @HostBinding('class.tab-pane') private addClass = true;

    private _active:boolean;
    public headingRef:TemplateRef;

    constructor(public tabset:Tabset) {
        this.tabset.addTab(this);
    }

    ngOnInit() {
        this.removable = !!this.removable;
    }

    ngOnDestroy() {
        this.tabset.removeTab(this);
    }
}
import {Directive, TemplateRef} from 'angular2/core';
import {Tab} from './tab.directive';

@Directive({selector: '[tab-heading]'})
export class TabHeading {
    constructor(public templateRef:TemplateRef, tab:Tab) {
        tab.headingRef = templateRef;
    }
}
import {Component, OnInit, Input} from 'angular2/core';
import {NgClass} from 'angular2/common';
import {NgTransclude} from './utils';
import {Tab} from './tab.directive';
@Component({
    selector: 'tabset',
    directives: [NgClass, NgTransclude],
    template: `
    <ul class="nav" [ngClass]="classMap" (click)="$event.preventDefault()">
        <li *ngFor="#tabz of tabs" class="nav-item"
          [class.active]="tabz.active" [class.disabled]="tabz.disabled">
          <a href class="nav-link"
            [class.active]="tabz.active" [class.disabled]="tabz.disabled"
            (click)="tabz.active = true">
            <span [ngTransclude]="tabz.headingRef">{{tabz.heading}}</span>
            <span [hidden]="!tabz.removable">
              <span (click)="$event.preventDefault(); removeTab(tabz);" class="glyphicon glyphicon-remove-circle"></span>
            </span>
          </a>
        </li>
    </ul>
    <div class="tab-content">
      <ng-content></ng-content>
    </div>
  `
})
export class Tabset implements OnInit {
    @Input() private get vertical() {
        return this._vertical;
    };

    @Input() private get justified() {
        return this._justified;
    };

    @Input() private get type() {
        return this._type;
    };

    private set vertical(value) {
        this._vertical = value;
        this.setClassMap();
    }

    private set justified(value) {
        this._justified = value;
        this.setClassMap();
    }

    private set type(value) {
        this._type = value;
        this.setClassMap();
    }

    private setClassMap() {
        this.classMap = {
            'nav-stacked': this.vertical,
            'nav-justified': this.justified,
            ['nav-' + (this.type || 'tabs')]: true
        };
    }

    public tabs:Array<Tab> = [];

    private isDestroyed:boolean;
    private _vertical:boolean;
    private _justified:boolean;
    private _type:string;
    private classMap:any = {};

    constructor() {
    }

    ngOnInit() {
        this.type = this.type !== 'undefined' ? this.type : 'tabs';
    }

    ngOnDestroy() {
        this.isDestroyed = true;
    }

    public addTab(tab:Tab) {
        this.tabs.push(tab);
        tab.active = this.tabs.length === 1 && tab.active !== false;
    }

    public removeTab(tab:Tab) {
        let index = this.tabs.indexOf(tab);
        if (index === -1 || this.isDestroyed) {
            return;
        }
        // Select a new tab if the tab to be removed is selected and not destroyed
        if (tab.active && this.hasAvailableTabs(index)) {
            let newActiveIndex = this.getClosestTabIndex(index);
            this.tabs[newActiveIndex].active = true;
        }

        tab.removed.emit(tab);
        this.tabs.splice(index, 1);
    }

    private getClosestTabIndex (index:number):number {
        let tabsLength = this.tabs.length;
        if (!tabsLength) {
            return -1;
        }

        for (let step = 1; step <= tabsLength; step += 1) {
            let prevIndex = index - step;
            let nextIndex = index + step;
            if (this.tabs[prevIndex] && !this.tabs[prevIndex].disabled) {
                return prevIndex;
            }
            if (this.tabs[nextIndex] && !this.tabs[nextIndex].disabled) {
                return nextIndex;
            }
        }
        return -1;
    }

    private hasAvailableTabs (index:number) {
        let tabsLength = this.tabs.length;
        if (!tabsLength) {
            return false;
        }

        for (let i = 0; i < tabsLength; i += 1) {
            if (!this.tabs[i].disabled && i !== index) {
                return true;
            }
        }
        return false;
    }
}
import {Directive, TemplateRef, ViewContainerRef, Inject} from 'angular2/core';

export interface IAttribute {
    [key: string]: any;
}

@Directive({
    selector: '[ngTransclude]',
    properties: ['ngTransclude']
})
export class NgTransclude {
    private _ngTransclude: TemplateRef;

    private set ngTransclude(templateRef:TemplateRef) {
        this._ngTransclude = templateRef;
        if (templateRef) {
            this.viewRef.createEmbeddedView(templateRef);
        }
    }

    private get ngTransclude() {
        return this._ngTransclude;
    }

    constructor(@Inject(ViewContainerRef) public viewRef:ViewContainerRef) {
    }
}