<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
a {
cursor: pointer;
cursor: hand;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-top: 10px;
display: inline-block;
background-color: #eee;
border-radius: 4px;
}
nav a:visited, a:link {
color: #607D8B;
}
nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.router-link-active {
color: #039be5;
}
/* items class */
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected:hover {
background-color: #BBD8DC;
color: white;
}
.items .text {
position: relative;
top: -3px;
}
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected {
background-color: #CFD8DC;
color: white;
}
.items li.selected:hover {
background-color: #BBD8DC;
}
.items .text {
position: relative;
top: -3px;
}
.items .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif; font-weight: 800
}
select-tab{
position : absolute;
height : 20px;
left : 10%;
right : 10%;
top : 30px;
background-color: #D2D2D2
}
.handle{
position : absolute;
z-index : 3;
height : 100%;
outline : 1px solid #888888;
width : 3px;
background-color : #1e507d;
}
.handle:hover{
background-color : black;
cursor : col-resize;
}
.handle.start{
margin-left : -4px;
}
.handle.stop{
}
.sequence-zoom-selector, .s-selection{
position : absolute;
top : 0px;
height : 100%;
z-index : 3;
}
.sequence-zoom-selector{
outline : solid 1px rgba(0,0,0, 0.4);
background-color : rgba(0,0,0, 0.2);
/* pointer-events : none; */
}
.s-selection{
outline : solid 1px rgba(0,0,0, 0.4);
background-color : rgba(0,0,0, 0.2);
}
.s-selection:hover {
cursor : move;
outline : solid 1px rgba(0,0,0, 0.7);
background-color : rgba(0,0,0, 0.3);
}
.label{
position : absolute;
font-size : 12px;
}
.selection{
bottom : 100%;
}
.sequence{
top : 100%;
}
.start{
right : 100%;
}
.stop{
left : 100%;
}
display-values{
height: 20px;
position: absolute;
top:80px;
left: 10%;
right: 10%;
}
### Angular2 Starter Plunker - Typescript - RC.0
A simple plunker demonstrating Angular2 usage:
- Uses SystemJS + TypeScript to compile on the fly
- Includes binding, directives, http, pipes, and DI usage.
For opening
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
import {enableProdMode} from '@angular/core';
enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule)
import { Component } from '@angular/core';
import {Element, Values} from './data';
import { LoaderComponent } from './loader';
@Component({
selector: 'my-app',
directives: [LoaderComponent],
template: ' <loader [element]="element" ></loader>'
})
export class AppComponent {
element: Element;
constructor(){
this.element = new Element();
this.element.name = "test bug";
for (let i = 0; i < 1000; i++) {
let val = new Values();
val.v = i;
this.element.dataList.push(val);
}
}
}
import {Component, Input, Output } from '@angular/core';
import {Element, Range} from './data';
import { SelectComponent } from './select';
import { DisplayComponent } from './display';
@Component({
selector: 'loader',
directives: [SelectComponent, DisplayComponent],
template: `
<div class="relativeContainer" >
<select-tab [selection]="selection" ></select-tab>
<display-values [selection]="selection" [element]="element" ></display-values>
</div>
`
})
export class LoaderComponent {
@Input() element : Element;
selection : Range;
constructor(){
this.selection = new Range();
this.selection.start = 0;
this.selection.stop = 1000;
}
}
import {Component, Input, Output } from '@angular/core';
import {Element, Range, Values} from './data';
import { PipeFilter } from './pipe';
@Component({
selector: 'display-values',
pipes: [PipeFilter],
template: `
<div class="positionContainer" >
<svg width="100%" height="25px" viewBox="0 0 100 1" preserveAspectRatio="none" >
<g *ngFor="let p of element.dataList | PipeFilter:selection.start:selection.stop; let f = first ; let i = index; let l = last ">
<rect [attr.x]="getAnnotationX(p, i, f, l)"
height="1" y="0"
[attr.width]="blockWidth"
style="stroke:blue"
>
</rect>
<text [attr.x]="getAnnotationTextX(p)" [attr.width]="blockWidth/2" y="0.7" height=1 fill="#FFFFFF"
style="font-size:0.65px; font-width:800;" > {{p.v}} </text>
</g>
</svg>
</div>
`
})
export class DisplayComponent {
@Input() selection : Range;
@Input() element : Element;
elementStartPos: number = 0;
blockWidth: number = 0;
getAnnotationX(p: Values, i: number, first: boolean, last : boolean) {
if(first)
console.log("first " + i+ " "+p.v);
if(last)
console.log("last " + i + " " +p.v);
this.elementStartPos = this.elementStartPos + this.blockWidth;
if (i == 0) {
this.elementStartPos = 0;
this.blockWidth = 100 / (this.selection.stop - this.selection.start);
}
return this.elementStartPos;
}
getAnnotationTextX(p: Values){
let centerTag = 2;
if(this.blockWidth <= 4){
centerTag = 2.2;
}
return this.elementStartPos + (this.blockWidth/centerTag) ;
}
}
import {Component, Input, Output , ElementRef, OnInit } from '@angular/core';
import {Range} from './data';
import {Observable} from "rxjs/Rx"
@Component({
selector: 'select-tab',
template: `
<div class="positionContainer" >
<div class="s-selection" [style.left]="getSelectionX() + '%'" [style.width]="getSelectionWidth() + '%'" (mousedown)="startMove($event)">
<span class="label selection start" style="; background-color:white" >{{selection.start}}</span>
<span class="label selection stop" style="; background-color:white" >{{selection.stop}}</span>
</div>
<div class="handle start" [style.left]="getSelectionX() + '%'" (mousedown)="startDragLeft($event)"></div>
<div class="handle stop" [style.left]="(getSelectionX() + getSelectionWidth()) + '%'" (mousedown)="startDragRight($event)"></div>
</div>
`
})
export class SelectComponent implements OnInit{
@Input() selection : Range;
element: Element;
root: Element;
constructor(e : ElementRef){
this.root = e.nativeElement;
}
ngOnInit(){
this.element = <Element>this.root;
}
getSelectionX() : number{
return this.selection.start/ (1000)*100;
}
getSelectionWidth() : number{
return 100* (this.selection.stop - this.selection.start + 1) / 1000;
}
startMove(e : MouseEvent){
console.log(this.element)
const box = this.element.getBoundingClientRect();
const selBox = this.element.getElementsByClassName("s-selection")[0].getBoundingClientRect();
const initWidth = selBox.right - selBox.left;
const offset = e.clientX - selBox.left;
const diff = this.selection.stop - this.selection.start
const inputs$ = Observable.fromEvent(window, 'mousemove');
const subMM = inputs$.subscribe(
(e : MouseEvent) => {
const startX = Math.max(Math.min(e.clientX-offset, box.right + 1 - initWidth) - box.left, 0);
const stopX = startX + initWidth;
this.updateSelection(startX, stopX, diff);
return false;
});
const onMouseUp = Observable.fromEvent(window, 'mouseup');
const subMU = onMouseUp.subscribe(
(e : MouseEvent) => {
const startX = Math.max(Math.min(e.clientX-offset, box.right + 1 - initWidth) - box.left, 0);
const stopX = startX + initWidth;
this.updateSelection(startX, stopX, diff);
subMM.unsubscribe();
subMU.unsubscribe();
return false;
});
return false;
}
updateSelection(startX : number, stopX : number, diff: number){
const box = this.element.getBoundingClientRect();
let width = box.width;
let ratio = (1000) / width;
this.selection.start = Math.round(startX * ratio);
this.selection.stop = this.selection.start + diff;
}
startDragRight(e : MouseEvent){
const box = this.element.getBoundingClientRect();
const selBox = this.element.getElementsByClassName("s-selection")[0].getBoundingClientRect();
const offset = e.clientX - selBox.right;
// observable of mousemove events
const inputs$ = Observable.fromEvent(window, 'mousemove');
const subMM = inputs$.subscribe(
(e : MouseEvent) => {
const stopX = Math.max(Math.min(e.clientX-offset, box.right) - box.left, selBox.left- box.left+1);
this.updateStop(stopX);
return false;
});
const onMouseUp = Observable.fromEvent(window, 'mouseup');
const subMU = onMouseUp.subscribe(
(e : MouseEvent) => {
const stopX = Math.max(Math.min(e.clientX-offset, box.right) - box.left, selBox.left- box.left+1);
this.updateStop(stopX);
subMM.unsubscribe();
subMU.unsubscribe();
return false;
});
return false;
}
startDragLeft(e : MouseEvent){
const box = this.element.getBoundingClientRect();
const selBox = this.element.getElementsByClassName("s-selection")[0].getBoundingClientRect();
const offset = e.clientX - selBox.left;
const inputs$ = Observable.fromEvent(window, 'mousemove');
const subMM = inputs$.subscribe(
(e : MouseEvent) => {
const startX = Math.max(Math.min(e.clientX-offset, selBox.right-1) - box.left, 0);
this.updateStart(startX);
return false;
});
const onMouseUp = Observable.fromEvent(window, 'mouseup');
const subMU = onMouseUp.subscribe(
(e : MouseEvent) => {
const startX = Math.max(Math.min(e.clientX-offset, selBox.right-1) - box.left, 0);
this.updateStart(startX);
subMM.unsubscribe();
subMU.unsubscribe();
return false;
});
return false;
}
updateStart(startX : number){
const box = this.element.getBoundingClientRect();
let width = box.width;
let ratio = (1000) / width;
if (ratio >= 80 && startX > 100) {
this.selection.start = Math.round(startX * ratio) + Math.round(ratio / 1.02);
}
else {
this.selection.start = Math.min (Math.max(Math.round(startX * ratio),0),this.selection.stop -1 );
}
}
updateStop(stopX : number){
const box = this.element.getBoundingClientRect();
let width = box.width;
let ratio = (1000) / width;
if (ratio >= 80 && stopX <900) {
this.selection.stop = Math.round(stopX * ratio) - Math.round(ratio/1.04);
}
else {
this.selection.stop = Math.max(Math.round(stopX * ratio),this.selection.start + 1);
}
}
}
export class Element {
name : string;
dataList : Array<Values>=[]
}
export class Values{
v : number;
}
export class Range{
start : number;
stop : number;
}
import {Injectable, Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'PipeFilter',
pure: false
})
export class PipeFilter implements PipeTransform {
transform(data: Array<any>, start: number, stop:number){
console.log('SLICE ON['+start+"-"+stop+"]")
return data.slice(start, stop)
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app';
import { LoaderComponent } from './loader';
import { SelectComponent } from './select';
import { DisplayComponent } from './display';
import { PipeFilter } from './pipe';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, LoaderComponent, DisplayComponent, SelectComponent, PipeFilter ],
bootstrap: [ AppComponent ]
})
export class AppModule { }