refactor(playground): make playground great again
This commit is contained in:
parent
69f87ca075
commit
3d9d839c6c
@ -13,7 +13,7 @@ describe('hello world', function() {
|
|||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
describe('hello world app', function() {
|
describe('hello world app', function() {
|
||||||
var URL = 'all/playground/src/hello_world/index.html';
|
const URL = 'all/playground/src/hello_world/index.html';
|
||||||
|
|
||||||
it('should greet', function() {
|
it('should greet', function() {
|
||||||
browser.get(URL);
|
browser.get(URL);
|
||||||
@ -31,15 +31,12 @@ describe('hello world', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function getComponentText(selector: any /** TODO #9100 */, innerSelector: any /** TODO #9100 */) {
|
function getComponentText(selector: string, innerSelector: string) {
|
||||||
return browser.executeScript(
|
return browser.executeScript(
|
||||||
'return document.querySelector("' + selector + '").querySelector("' + innerSelector +
|
`return document.querySelector("${selector}").querySelector("${innerSelector}").textContent`);
|
||||||
'").textContent');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickComponentButton(
|
function clickComponentButton(selector: string, innerSelector: string) {
|
||||||
selector: any /** TODO #9100 */, innerSelector: any /** TODO #9100 */) {
|
|
||||||
return browser.executeScript(
|
return browser.executeScript(
|
||||||
'return document.querySelector("' + selector + '").querySelector("' + innerSelector +
|
`return document.querySelector("${selector}").querySelector("${innerSelector}").click()`);
|
||||||
'").click()');
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ describe('http', function() {
|
|||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
describe('fetching', function() {
|
describe('fetching', function() {
|
||||||
var URL = 'all/playground/src/http/index.html';
|
const URL = 'all/playground/src/http/index.html';
|
||||||
|
|
||||||
it('should fetch and display people', function() {
|
it('should fetch and display people', function() {
|
||||||
browser.get(URL);
|
browser.get(URL);
|
||||||
@ -22,8 +22,7 @@ describe('http', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getComponentText(selector: any /** TODO #9100 */, innerSelector: any /** TODO #9100 */) {
|
function getComponentText(selector: string, innerSelector: string) {
|
||||||
return browser.executeScript(
|
return browser.executeScript(
|
||||||
'return document.querySelector("' + selector + '").querySelector("' + innerSelector +
|
`return document.querySelector("${selector}").querySelector("${innerSelector}").textContent.trim()`);
|
||||||
'").textContent.trim()');
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ describe('jsonp', function() {
|
|||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
describe('fetching', function() {
|
describe('fetching', function() {
|
||||||
var URL = 'all/playground/src/jsonp/index.html';
|
const URL = 'all/playground/src/jsonp/index.html';
|
||||||
|
|
||||||
it('should fetch and display people', function() {
|
it('should fetch and display people', function() {
|
||||||
browser.get(URL);
|
browser.get(URL);
|
||||||
@ -22,8 +22,7 @@ describe('jsonp', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getComponentText(selector: any /** TODO #9100 */, innerSelector: any /** TODO #9100 */) {
|
function getComponentText(selector: string, innerSelector: string) {
|
||||||
return browser.executeScript(
|
return browser.executeScript(
|
||||||
'return document.querySelector("' + selector + '").querySelector("' + innerSelector +
|
`return document.querySelector("${selector}").querySelector("${innerSelector}").textContent.trim()`);
|
||||||
'").textContent.trim()');
|
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
import {verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
import {verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
||||||
|
|
||||||
function waitForElement(selector: any /** TODO #9100 */) {
|
function waitForElement(selector: string) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
const EC = protractor.ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@ describe('relative assets relative-app', () => {
|
|||||||
|
|
||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
var URL = 'all/playground/src/relative_assets/';
|
const URL = 'all/playground/src/relative_assets/';
|
||||||
|
|
||||||
it('should load in the templateUrl relative to the my-cmp component', () => {
|
it('should load in the templateUrl relative to the my-cmp component', () => {
|
||||||
browser.get(URL);
|
browser.get(URL);
|
||||||
@ -31,10 +31,9 @@ describe('relative assets relative-app', () => {
|
|||||||
browser.get(URL);
|
browser.get(URL);
|
||||||
|
|
||||||
waitForElement('my-cmp .inner-container');
|
waitForElement('my-cmp .inner-container');
|
||||||
var elem = element(by.css('my-cmp .inner-container'));
|
const elem = element(by.css('my-cmp .inner-container'));
|
||||||
var width = browser.executeScript(function(e: any /** TODO #9100 */) {
|
const width = browser.executeScript(
|
||||||
return parseInt(window.getComputedStyle(e).width);
|
(e: Element) => parseInt(window.getComputedStyle(e).width), elem.getWebElement());
|
||||||
}, elem.getWebElement());
|
|
||||||
|
|
||||||
expect(width).toBe(432);
|
expect(width).toBe(432);
|
||||||
});
|
});
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
import {verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
import {verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
||||||
|
|
||||||
function waitForElement(selector: any /** TODO #9100 */) {
|
function waitForElement(selector: string) {
|
||||||
var EC = (<any>protractor).ExpectedConditions;
|
const EC = protractor.ExpectedConditions;
|
||||||
// Waits for the element with id 'abc' to be present on the dom.
|
// Waits for the element with id 'abc' to be present on the dom.
|
||||||
browser.wait(EC.presenceOf($(selector)), 20000);
|
browser.wait(EC.presenceOf($(selector)), 20000);
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ describe('routing inbox-app', () => {
|
|||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
describe('index view', () => {
|
describe('index view', () => {
|
||||||
var URL = 'all/playground/src/routing/';
|
const URL = 'all/playground/src/routing/';
|
||||||
|
|
||||||
it('should list out the current collection of items', () => {
|
it('should list out the current collection of items', () => {
|
||||||
browser.get(URL);
|
browser.get(URL);
|
||||||
|
@ -22,13 +22,13 @@ describe('WebWorker Router', () => {
|
|||||||
|
|
||||||
let contentSelector = 'app main h1';
|
let contentSelector = 'app main h1';
|
||||||
let navSelector = 'app nav ul';
|
let navSelector = 'app nav ul';
|
||||||
var baseUrl = 'all/playground/src/web_workers/router/index.html';
|
const baseUrl = 'all/playground/src/web_workers/router/index.html';
|
||||||
|
|
||||||
it('should route on click', () => {
|
it('should route on click', () => {
|
||||||
browser.get(baseUrl);
|
browser.get(baseUrl);
|
||||||
|
|
||||||
waitForElement(contentSelector);
|
waitForElement(contentSelector);
|
||||||
var content = element(by.css(contentSelector));
|
let content = element(by.css(contentSelector));
|
||||||
expect(content.getText()).toEqual('Start');
|
expect(content.getText()).toEqual('Start');
|
||||||
|
|
||||||
let aboutBtn = element(by.css(navSelector + ' .about'));
|
let aboutBtn = element(by.css(navSelector + ' .about'));
|
||||||
@ -66,13 +66,13 @@ describe('WebWorker Router', () => {
|
|||||||
function waitForElementText(contentSelector: string, expected: string): void {
|
function waitForElementText(contentSelector: string, expected: string): void {
|
||||||
browser.wait(() => {
|
browser.wait(() => {
|
||||||
let deferred = protractor.promise.defer();
|
let deferred = protractor.promise.defer();
|
||||||
var elem = element(by.css(contentSelector));
|
const elem = element(by.css(contentSelector));
|
||||||
elem.getText().then((text) => deferred.fulfill(text === expected));
|
elem.getText().then((text) => deferred.fulfill(text === expected));
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitForUrl(regex: any /** TODO #9100 */): void {
|
function waitForUrl(regex: RegExp): void {
|
||||||
browser.wait(() => {
|
browser.wait(() => {
|
||||||
let deferred = protractor.promise.defer();
|
let deferred = protractor.promise.defer();
|
||||||
browser.getCurrentUrl().then((url) => deferred.fulfill(url.match(regex) !== null));
|
browser.getCurrentUrl().then((url) => deferred.fulfill(url.match(regex) !== null));
|
||||||
|
@ -63,26 +63,26 @@ import {Component, animate, keyframes, state, style, transition, trigger} from '
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AnimateApp {
|
export class AnimateApp {
|
||||||
public items: any[] /** TODO #9100 */ = [];
|
public items: number[] = [];
|
||||||
private _state: any /** TODO #9100 */;
|
private _state: ('start'|'active'|'void'|'default');
|
||||||
|
|
||||||
public bgStatus = 'focus';
|
public bgStatus = 'focus';
|
||||||
|
|
||||||
remove(item: any) {
|
remove(item: number) {
|
||||||
var index = this.items.indexOf(item);
|
const index = this.items.indexOf(item);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
this.items.splice(index, 1);
|
this.items.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reorderAndRemove() {
|
reorderAndRemove() {
|
||||||
this.items = this.items.sort((a: any, b: any) => Math.random() - 0.5);
|
this.items = this.items.sort((a, b) => Math.random() - 0.5);
|
||||||
this.items.splice(Math.floor(Math.random() * this.items.length), 1);
|
this.items.splice(Math.floor(Math.random() * this.items.length), 1);
|
||||||
this.items.splice(Math.floor(Math.random() * this.items.length), 1);
|
this.items.splice(Math.floor(Math.random() * this.items.length), 1);
|
||||||
this.items[Math.floor(Math.random() * this.items.length)] = 99;
|
this.items[Math.floor(Math.random() * this.items.length)] = 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
bgStatusChanged(data: {[key: string]: any}, phase: string) {
|
bgStatusChanged(data: {[key: string]: string}, phase: string) {
|
||||||
alert(`backgroundAnimation has ${phase} from ${data['fromState']} to ${data['toState']}`);
|
alert(`backgroundAnimation has ${phase} from ${data['fromState']} to ${data['toState']}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ class AsyncApplication {
|
|||||||
val2: number = 0;
|
val2: number = 0;
|
||||||
val3: number = 0;
|
val3: number = 0;
|
||||||
val4: number = 0;
|
val4: number = 0;
|
||||||
timeoutId: any /** TODO #9100 */ = null;
|
timeoutId: any = null;
|
||||||
multiTimeoutId: any /** TODO #9100 */ = null;
|
multiTimeoutId: any = null;
|
||||||
intervalId: any /** TODO #9100 */ = null;
|
intervalId: any = null;
|
||||||
|
|
||||||
increment(): void { this.val1++; };
|
increment(): void { this.val1++; };
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ class AsyncApplication {
|
|||||||
multiDelayedIncrements(i: number): void {
|
multiDelayedIncrements(i: number): void {
|
||||||
this.cancelMultiDelayedIncrements();
|
this.cancelMultiDelayedIncrements();
|
||||||
|
|
||||||
var self = this;
|
const self = this;
|
||||||
function helper(_i: any /** TODO #9100 */) {
|
function helper(_i: number) {
|
||||||
if (_i <= 0) {
|
if (_i <= 0) {
|
||||||
self.multiTimeoutId = null;
|
self.multiTimeoutId = null;
|
||||||
return;
|
return;
|
||||||
|
@ -41,15 +41,10 @@
|
|||||||
'@angular/upgrade': '/packages-dist/upgrade/bundles/upgrade.umd.js',
|
'@angular/upgrade': '/packages-dist/upgrade/bundles/upgrade.umd.js',
|
||||||
'@angular/upgrade/static': '/packages-dist/upgrade/bundles/upgrade-static.umd.js',
|
'@angular/upgrade/static': '/packages-dist/upgrade/bundles/upgrade-static.umd.js',
|
||||||
'rxjs': '/all/playground/vendor/rxjs',
|
'rxjs': '/all/playground/vendor/rxjs',
|
||||||
|
|
||||||
// TODO(i): remove once playground apps no longer use facades directly
|
|
||||||
'@angular/core/src/facade': '/all/@angular/core/src/facade'
|
|
||||||
},
|
},
|
||||||
packages: {
|
packages: {
|
||||||
'app': {defaultExtension: 'js'},
|
'app': {defaultExtension: 'js'},
|
||||||
'rxjs': {defaultExtension: 'js'},
|
'rxjs': {defaultExtension: 'js'},
|
||||||
// TODO(i): remove once playground apps no longer use facades directly
|
|
||||||
'@angular/core/src/facade': {defaultExtension: 'js'}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
import {Component, NgModule} from '@angular/core';
|
import {Component, NgModule} from '@angular/core';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
// TODO: remove deep import by reimplementing the event name serialization
|
|
||||||
import {KeyEventsPlugin} from '@angular/platform-browser/src/dom/events/key_events';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'key-events-app',
|
selector: 'key-events-app',
|
||||||
@ -28,17 +26,48 @@ class KeyEventsApp {
|
|||||||
lastKey: string = '(none)';
|
lastKey: string = '(none)';
|
||||||
shiftEnter: boolean = false;
|
shiftEnter: boolean = false;
|
||||||
|
|
||||||
onKeyDown(event: any /** TODO #9100 */): void {
|
onKeyDown(event: KeyboardEvent): void {
|
||||||
this.lastKey = KeyEventsPlugin.getEventFullKey(event);
|
this.lastKey = KeyEventsApp._getEventFullKey(event);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
onShiftEnter(event: any /** TODO #9100 */): void {
|
onShiftEnter(event: KeyboardEvent): void {
|
||||||
this.shiftEnter = true;
|
this.shiftEnter = true;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
resetShiftEnter(): void { this.shiftEnter = false; }
|
resetShiftEnter(): void { this.shiftEnter = false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a more readable version of current pressed keys.
|
||||||
|
* @see KeyEventsPlugin.getEventFullKey
|
||||||
|
*/
|
||||||
|
private static _getEventFullKey(event: KeyboardEvent): string {
|
||||||
|
const modifierKeys = ['alt', 'control', 'meta', 'shift'];
|
||||||
|
const modifierKeyGetters: {[key: string]: (event: KeyboardEvent) => boolean} = {
|
||||||
|
'alt': (event: KeyboardEvent) => event.altKey,
|
||||||
|
'control': (event: KeyboardEvent) => event.ctrlKey,
|
||||||
|
'meta': (event: KeyboardEvent) => event.metaKey,
|
||||||
|
'shift': (event: KeyboardEvent) => event.shiftKey
|
||||||
|
};
|
||||||
|
|
||||||
|
let fullKey = '';
|
||||||
|
let key = event.key.toLowerCase();
|
||||||
|
if (key === ' ') {
|
||||||
|
key = 'space'; // for readability
|
||||||
|
} else if (key === '.') {
|
||||||
|
key = 'dot'; // because '.' is used as a separator in event names
|
||||||
|
}
|
||||||
|
modifierKeys.forEach(modifierName => {
|
||||||
|
if (modifierName != key) {
|
||||||
|
const modifierGetter = modifierKeyGetters[modifierName];
|
||||||
|
if (modifierGetter(event)) {
|
||||||
|
fullKey += modifierName + '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fullKey + key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({declarations: [KeyEventsApp], bootstrap: [KeyEventsApp], imports: [BrowserModule]})
|
@NgModule({declarations: [KeyEventsApp], bootstrap: [KeyEventsApp], imports: [BrowserModule]})
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, Host, NgModule} from '@angular/core';
|
import {Component, Host, NgModule} from '@angular/core';
|
||||||
import {isPresent, print} from '@angular/core/src/facade/lang';
|
|
||||||
import {AbstractControl, FormBuilder, FormGroup, FormGroupDirective, ReactiveFormsModule, Validators} from '@angular/forms';
|
import {AbstractControl, FormBuilder, FormGroup, FormGroupDirective, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
@ -18,7 +17,7 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
|||||||
* Custom validator.
|
* Custom validator.
|
||||||
*/
|
*/
|
||||||
function creditCardValidator(c: AbstractControl): {[key: string]: boolean} {
|
function creditCardValidator(c: AbstractControl): {[key: string]: boolean} {
|
||||||
if (isPresent(c.value) && /^\d{16}$/.test(c.value)) {
|
if (c.value && /^\d{16}$/.test(c.value)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return {'invalidCreditCard': true};
|
return {'invalidCreditCard': true};
|
||||||
@ -48,17 +47,17 @@ function creditCardValidator(c: AbstractControl): {[key: string]: boolean} {
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
class ShowError {
|
class ShowError {
|
||||||
formDir: any /** TODO #9100 */;
|
formDir: FormGroupDirective;
|
||||||
controlPath: string;
|
controlPath: string;
|
||||||
errorTypes: string[];
|
errorTypes: string[];
|
||||||
|
|
||||||
constructor(@Host() formDir: FormGroupDirective) { this.formDir = formDir; }
|
constructor(@Host() formDir: FormGroupDirective) { this.formDir = formDir; }
|
||||||
|
|
||||||
get errorMessage(): string {
|
get errorMessage(): string {
|
||||||
var form: FormGroup = this.formDir.form;
|
const form: FormGroup = this.formDir.form;
|
||||||
var control = form.get(this.controlPath);
|
const control = form.get(this.controlPath);
|
||||||
if (isPresent(control) && control.touched) {
|
if (control && control.touched) {
|
||||||
for (var i = 0; i < this.errorTypes.length; ++i) {
|
for (let i = 0; i < this.errorTypes.length; ++i) {
|
||||||
if (control.hasError(this.errorTypes[i])) {
|
if (control.hasError(this.errorTypes[i])) {
|
||||||
return this._errorMessage(this.errorTypes[i]);
|
return this._errorMessage(this.errorTypes[i]);
|
||||||
}
|
}
|
||||||
@ -68,8 +67,11 @@ class ShowError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _errorMessage(code: string): string {
|
private _errorMessage(code: string): string {
|
||||||
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
const config: {[key: string]: string} = {
|
||||||
return (config as any /** TODO #9100 */)[code];
|
'required': 'is required',
|
||||||
|
'invalidCreditCard': 'is invalid credit card number',
|
||||||
|
};
|
||||||
|
return config[code];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +136,7 @@ class ShowError {
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
class ReactiveForms {
|
class ReactiveForms {
|
||||||
form: any /** TODO #9100 */;
|
form: FormGroup;
|
||||||
countries = ['US', 'Canada'];
|
countries = ['US', 'Canada'];
|
||||||
|
|
||||||
constructor(fb: FormBuilder) {
|
constructor(fb: FormBuilder) {
|
||||||
@ -151,8 +153,8 @@ class ReactiveForms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSubmit(): void {
|
onSubmit(): void {
|
||||||
print('Submitting:');
|
console.log('Submitting:');
|
||||||
print(this.form.value);
|
console.log(this.form.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, EventEmitter, Injectable, Input, NgModule, Output} from '@angular/core';
|
import {Component, EventEmitter, Injectable, Input, NgModule, Output} from '@angular/core';
|
||||||
import {ListWrapper} from '@angular/core/src/facade/collection';
|
|
||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule} from '@angular/forms';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
@ -40,7 +39,7 @@ class Order {
|
|||||||
|
|
||||||
// ---- services
|
// ---- services
|
||||||
|
|
||||||
var _nextId = 1000;
|
let _nextId = 1000;
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class DataService {
|
class DataService {
|
||||||
orderItems: OrderItem[];
|
orderItems: OrderItem[];
|
||||||
@ -70,7 +69,7 @@ class DataService {
|
|||||||
this.orderItems.push(new OrderItem(_nextId++, order.orderId, '', 0, 0));
|
this.orderItems.push(new OrderItem(_nextId++, order.orderId, '', 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteItem(item: OrderItem): void { ListWrapper.remove(this.orderItems, item); }
|
deleteItem(item: OrderItem): void { this.orderItems.splice(this.orderItems.indexOf(item), 1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import {Component, Injectable} from '@angular/core';
|
import {Component, Injectable} from '@angular/core';
|
||||||
import {isPresent} from '@angular/core/src/facade/lang';
|
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
|
|
||||||
import * as db from './data';
|
import * as db from './data';
|
||||||
@ -32,7 +31,7 @@ export class InboxRecord {
|
|||||||
lastName: string,
|
lastName: string,
|
||||||
date: string, draft?: boolean
|
date: string, draft?: boolean
|
||||||
} = null) {
|
} = null) {
|
||||||
if (isPresent(data)) {
|
if (data) {
|
||||||
this.setData(data);
|
this.setData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,42 +45,42 @@ export class InboxRecord {
|
|||||||
lastName: string,
|
lastName: string,
|
||||||
date: string, draft?: boolean
|
date: string, draft?: boolean
|
||||||
}) {
|
}) {
|
||||||
this.id = record['id'];
|
this.id = record.id;
|
||||||
this.subject = record['subject'];
|
this.subject = record.subject;
|
||||||
this.content = record['content'];
|
this.content = record.content;
|
||||||
this.email = record['email'];
|
this.email = record.email;
|
||||||
this.firstName = (record as any /** TODO #9100 */)['first-name'];
|
this.firstName = record.firstName;
|
||||||
this.lastName = (record as any /** TODO #9100 */)['last-name'];
|
this.lastName = record.lastName;
|
||||||
this.date = record['date'];
|
this.date = record.date;
|
||||||
this.draft = record['draft'] == true;
|
this.draft = record.draft === true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DbService {
|
export class DbService {
|
||||||
getData(): Promise<any[]> { return Promise.resolve(db.data); }
|
getData(): Promise<InboxRecord[]> {
|
||||||
|
return Promise.resolve(db.data.map((entry: {[key: string]: any}) => new InboxRecord({
|
||||||
drafts(): Promise<any[]> {
|
id: entry['id'],
|
||||||
return this.getData().then(
|
subject: entry['subject'],
|
||||||
(data: any[]): any[] =>
|
content: entry['content'],
|
||||||
data.filter(record => isPresent(record['draft']) && record['draft'] == true));
|
email: entry['email'],
|
||||||
|
firstName: entry['first-name'],
|
||||||
|
lastName: entry['last-name'],
|
||||||
|
date: entry['date'],
|
||||||
|
draft: entry['draft'],
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
emails(): Promise<any[]> {
|
drafts(): Promise<InboxRecord[]> {
|
||||||
return this.getData().then(
|
return this.getData().then((data) => data.filter(record => record.draft));
|
||||||
(data: any[]): any[] => data.filter(record => !isPresent(record['draft'])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
email(id: any /** TODO #9100 */): Promise<any> {
|
emails(): Promise<InboxRecord[]> {
|
||||||
return this.getData().then((data: any[]) => {
|
return this.getData().then((data) => data.filter(record => !record.draft));
|
||||||
for (var i = 0; i < data.length; i++) {
|
}
|
||||||
var entry = data[i];
|
|
||||||
if (entry['id'] == id) {
|
email(id: string): Promise<InboxRecord> {
|
||||||
return entry;
|
return this.getData().then((data) => data.find((entry) => entry.id == id));
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,17 +91,15 @@ export class InboxCmp {
|
|||||||
|
|
||||||
constructor(public router: Router, db: DbService, route: ActivatedRoute) {
|
constructor(public router: Router, db: DbService, route: ActivatedRoute) {
|
||||||
route.params.forEach(p => {
|
route.params.forEach(p => {
|
||||||
const sortType = p['sort'];
|
const sortEmailsByDate = p['sort'] === 'date';
|
||||||
const sortEmailsByDate = isPresent(sortType) && sortType == 'date';
|
|
||||||
|
|
||||||
db.emails().then((emails: any[]) => {
|
db.emails().then((emails) => {
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
this.items = emails.map(data => new InboxRecord(data));
|
this.items = emails;
|
||||||
|
|
||||||
if (sortEmailsByDate) {
|
if (sortEmailsByDate) {
|
||||||
this.items.sort(
|
this.items.sort(
|
||||||
(a: InboxRecord, b: InboxRecord) =>
|
(a, b) => new Date(a.date).getTime() < new Date(b.date).getTime() ? -1 : 1);
|
||||||
new Date(a.date).getTime() < new Date(b.date).getTime() ? -1 : 1);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -116,9 +113,9 @@ export class DraftsCmp {
|
|||||||
private ready: boolean = false;
|
private ready: boolean = false;
|
||||||
|
|
||||||
constructor(private router: Router, db: DbService) {
|
constructor(private router: Router, db: DbService) {
|
||||||
db.drafts().then((drafts: any[]) => {
|
db.drafts().then((drafts) => {
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
this.items = drafts.map(data => new InboxRecord(data));
|
this.items = drafts;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import {Component, Directive, Host, NgModule} from '@angular/core';
|
import {Component, Directive, Host, NgModule} from '@angular/core';
|
||||||
import {isPresent, print} from '@angular/core/src/facade/lang';
|
import {FormControl, FormGroup, FormsModule, NG_VALIDATORS, NgForm} from '@angular/forms';
|
||||||
import {FormGroup, FormsModule, NG_VALIDATORS, NgForm} from '@angular/forms';
|
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
@ -33,8 +32,8 @@ class CheckoutModel {
|
|||||||
/**
|
/**
|
||||||
* Custom validator.
|
* Custom validator.
|
||||||
*/
|
*/
|
||||||
function creditCardValidator(c: any /** TODO #9100 */): {[key: string]: boolean} {
|
function creditCardValidator(c: FormControl): {[key: string]: boolean} {
|
||||||
if (isPresent(c.value) && /^\d{16}$/.test(c.value)) {
|
if (c.value && /^\d{16}$/.test(c.value)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return {'invalidCreditCard': true};
|
return {'invalidCreditCard': true};
|
||||||
@ -74,17 +73,17 @@ class CreditCardValidator {
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
class ShowError {
|
class ShowError {
|
||||||
formDir: any /** TODO #9100 */;
|
formDir: NgForm;
|
||||||
controlPath: string;
|
controlPath: string;
|
||||||
errorTypes: string[];
|
errorTypes: string[];
|
||||||
|
|
||||||
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
||||||
|
|
||||||
get errorMessage(): string {
|
get errorMessage(): string {
|
||||||
var form: FormGroup = this.formDir.form;
|
const form: FormGroup = this.formDir.form;
|
||||||
var control = form.get(this.controlPath);
|
const control = form.get(this.controlPath);
|
||||||
if (isPresent(control) && control.touched) {
|
if (control && control.touched) {
|
||||||
for (var i = 0; i < this.errorTypes.length; ++i) {
|
for (let i = 0; i < this.errorTypes.length; ++i) {
|
||||||
if (control.hasError(this.errorTypes[i])) {
|
if (control.hasError(this.errorTypes[i])) {
|
||||||
return this._errorMessage(this.errorTypes[i]);
|
return this._errorMessage(this.errorTypes[i]);
|
||||||
}
|
}
|
||||||
@ -94,8 +93,11 @@ class ShowError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _errorMessage(code: string): string {
|
private _errorMessage(code: string): string {
|
||||||
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
const config: {[key: string]: string} = {
|
||||||
return (config as any /** TODO #9100 */)[code];
|
'required': 'is required',
|
||||||
|
'invalidCreditCard': 'is invalid credit card number',
|
||||||
|
};
|
||||||
|
return config[code];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,8 +165,8 @@ class TemplateDrivenForms {
|
|||||||
countries = ['US', 'Canada'];
|
countries = ['US', 'Canada'];
|
||||||
|
|
||||||
onSubmit(): void {
|
onSubmit(): void {
|
||||||
print('Submitting:');
|
console.log('Submitting:');
|
||||||
print(this.model);
|
console.log(this.model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {ListWrapper, Predicate} from '@angular/core/src/facade/collection';
|
|
||||||
|
|
||||||
// base model for RecordStore
|
// base model for RecordStore
|
||||||
export abstract class KeyModel {
|
export abstract class KeyModel {
|
||||||
@ -36,20 +35,9 @@ export class Store<T extends KeyModel> {
|
|||||||
|
|
||||||
add(record: T): void { this.list.push(record); }
|
add(record: T): void { this.list.push(record); }
|
||||||
|
|
||||||
remove(record: T): void { this._spliceOut(record); }
|
remove(record: T): void { this.removeBy((item) => item === record); }
|
||||||
|
|
||||||
removeBy(callback: Predicate<T>): void {
|
removeBy(callback: (record: T) => boolean): void {
|
||||||
var records = this.list.filter(callback);
|
this.list = this.list.filter((record) => !callback(record));
|
||||||
ListWrapper.removeAll(this.list, records);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _spliceOut(record: T) {
|
|
||||||
var i = this._indexFor(record);
|
|
||||||
if (i > -1) {
|
|
||||||
return this.list.splice(i, 1)[0];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _indexFor(record: T) { return this.list.indexOf(record); }
|
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,16 @@ class TodoApp {
|
|||||||
|
|
||||||
constructor(public todoStore: Store<Todo>, public factory: TodoFactory) {}
|
constructor(public todoStore: Store<Todo>, public factory: TodoFactory) {}
|
||||||
|
|
||||||
enterTodo(inputElement: any /** TODO #9100 */): void {
|
enterTodo(inputElement: HTMLInputElement): void {
|
||||||
this.addTodo(inputElement.value);
|
this.addTodo(inputElement.value);
|
||||||
inputElement.value = '';
|
inputElement.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
editTodo(todo: Todo): void { this.todoEdit = todo; }
|
editTodo(todo: Todo): void { this.todoEdit = todo; }
|
||||||
|
|
||||||
doneEditing($event: any /** TODO #9100 */, todo: Todo): void {
|
doneEditing($event: KeyboardEvent, todo: Todo): void {
|
||||||
var which = $event.which;
|
const which = $event.which;
|
||||||
var target = $event.target;
|
const target = $event.target as HTMLInputElement;
|
||||||
if (which === 13) {
|
if (which === 13) {
|
||||||
todo.title = target.value;
|
todo.title = target.value;
|
||||||
this.todoEdit = null;
|
this.todoEdit = null;
|
||||||
@ -43,8 +43,8 @@ class TodoApp {
|
|||||||
|
|
||||||
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
||||||
|
|
||||||
toggleAll($event: any /** TODO #9100 */): void {
|
toggleAll($event: MouseEvent): void {
|
||||||
var isComplete = $event.target.checked;
|
const isComplete = ($event.target as HTMLInputElement).checked;
|
||||||
this.todoStore.list.forEach((todo: Todo) => { todo.completed = isComplete; });
|
this.todoStore.list.forEach((todo: Todo) => { todo.completed = isComplete; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ import {Component, EventEmitter, Input, NgModule, Output, forwardRef} from '@ang
|
|||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {UpgradeAdapter} from '@angular/upgrade';
|
import {UpgradeAdapter} from '@angular/upgrade';
|
||||||
|
|
||||||
declare var angular: any;
|
declare const angular: any;
|
||||||
|
|
||||||
|
|
||||||
var styles = [`
|
const styles = [`
|
||||||
.border {
|
.border {
|
||||||
border: solid 2px DodgerBlue;
|
border: solid 2px DodgerBlue;
|
||||||
}
|
}
|
||||||
@ -27,10 +27,10 @@ var styles = [`
|
|||||||
}
|
}
|
||||||
`];
|
`];
|
||||||
|
|
||||||
var adapter = new UpgradeAdapter(forwardRef(() => Ng2AppModule));
|
const adapter = new UpgradeAdapter(forwardRef(() => Ng2AppModule));
|
||||||
var ng1module = angular.module('myExample', []);
|
const ng1module = angular.module('myExample', []);
|
||||||
|
|
||||||
ng1module.controller('Index', function($scope: any /** TODO #9100 */) { $scope.name = 'World'; });
|
ng1module.controller('Index', function($scope: any) { $scope.name = 'World'; });
|
||||||
|
|
||||||
ng1module.directive('ng1User', function() {
|
ng1module.directive('ng1User', function() {
|
||||||
return {
|
return {
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare module 'B64' {
|
declare namespace base64js {
|
||||||
export function fromByteArray(arr: Uint8Array): string;
|
function fromByteArray(arr: Uint8Array): string;
|
||||||
export function toByteArray(str: string): Uint8Array;
|
function toByteArray(str: string): Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export = base64js;
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright 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 https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare class Bitmap {
|
|
||||||
constructor(width: number, height: number);
|
|
||||||
|
|
||||||
subsample(n: number): void;
|
|
||||||
dataURL(): string;
|
|
||||||
|
|
||||||
pixel: [any];
|
|
||||||
}
|
|
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2011 Andrey Zholos
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Bitmap(width, height) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.pixel = new Array(width);
|
|
||||||
for (var x = 0; x < width; x++) {
|
|
||||||
this.pixel[x] = new Array(height);
|
|
||||||
for (var y = 0; y < height; y++) this.pixel[x][y] = [0, 0, 0, 0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap.prototype.subsample =
|
|
||||||
function(n) {
|
|
||||||
var width = ~~(this.width / n);
|
|
||||||
var height = ~~(this.height / n);
|
|
||||||
var pixel = new Array(width);
|
|
||||||
for (var x = 0; x < width; x++) {
|
|
||||||
pixel[x] = new Array(height);
|
|
||||||
for (var y = 0; y < height; y++) {
|
|
||||||
var q = [0, 0, 0, 0];
|
|
||||||
for (var i = 0; i < n; i++)
|
|
||||||
for (var j = 0; j < n; j++) {
|
|
||||||
var r = this.pixel[x * n + i][y * n + j];
|
|
||||||
q[0] += r[3] * r[0];
|
|
||||||
q[1] += r[3] * r[1];
|
|
||||||
q[2] += r[3] * r[2];
|
|
||||||
q[3] += r[3];
|
|
||||||
}
|
|
||||||
if (q[3]) {
|
|
||||||
q[0] /= q[3];
|
|
||||||
q[1] /= q[3];
|
|
||||||
q[2] /= q[3];
|
|
||||||
q[3] /= n * n;
|
|
||||||
}
|
|
||||||
pixel[x][y] = q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.pixel = pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap.prototype.dataURL = function() {
|
|
||||||
function sample(v) { return ~~(Math.max(0, Math.min(1, v)) * 255); }
|
|
||||||
|
|
||||||
function gamma(v) { return sample(Math.pow(v, .45455)); }
|
|
||||||
|
|
||||||
function row(pixel, width, y) {
|
|
||||||
var data = '\0';
|
|
||||||
for (var x = 0; x < width; x++) {
|
|
||||||
var r = pixel[x][y];
|
|
||||||
data += String.fromCharCode(gamma(r[0]), gamma(r[1]), gamma(r[2]), sample(r[3]));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rows(pixel, width, height) {
|
|
||||||
var data = '';
|
|
||||||
for (var y = 0; y < height; y++) data += row(pixel, width, y);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function adler(data) {
|
|
||||||
var s1 = 1, s2 = 0;
|
|
||||||
for (var i = 0; i < data.length; i++) {
|
|
||||||
s1 = (s1 + data.charCodeAt(i)) % 65521;
|
|
||||||
s2 = (s2 + s1) % 65521;
|
|
||||||
}
|
|
||||||
return s2 << 16 | s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hton(i) { return String.fromCharCode(i >>> 24, i >>> 16 & 255, i >>> 8 & 255, i & 255); }
|
|
||||||
|
|
||||||
function deflate(data) {
|
|
||||||
var len = data.length;
|
|
||||||
return '\170\1\1' + String.fromCharCode(len & 255, len >>> 8, ~len & 255, (~len >>> 8) & 255) +
|
|
||||||
data + hton(adler(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
function crc32(data) {
|
|
||||||
var c = ~0;
|
|
||||||
for (var i = 0; i < data.length; i++)
|
|
||||||
for (var b = data.charCodeAt(i) | 0x100; b != 1; b >>>= 1)
|
|
||||||
c = (c >>> 1) ^ ((c ^ b) & 1 ? 0xedb88320 : 0);
|
|
||||||
return ~c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function chunk(type, data) { return hton(data.length) + type + data + hton(crc32(type + data)); }
|
|
||||||
|
|
||||||
function base64(data) {
|
|
||||||
enc = '';
|
|
||||||
for (var i = 5, n = data.length * 8 + 5; i < n; i += 6)
|
|
||||||
enc += 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
||||||
[(data.charCodeAt(~~(i / 8) - 1) << 8 | data.charCodeAt(~~(i / 8))) >> 7 - i % 8 & 63];
|
|
||||||
for (; enc.length % 4; enc += '=')
|
|
||||||
;
|
|
||||||
return enc;
|
|
||||||
}
|
|
||||||
|
|
||||||
var png = '\211PNG\r\n\32\n' +
|
|
||||||
chunk('IHDR', hton(this.width) + hton(this.height) + '\10\6\0\0\0') +
|
|
||||||
chunk('IDAT', deflate(rows(this.pixel, this.width, this.height))) + chunk('IEND', '');
|
|
||||||
|
|
||||||
return 'data:image/png;base64,' + base64(png);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright 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 https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _FileReader = FileReader;
|
|
||||||
export {_FileReader as FileReader};
|
|
||||||
|
|
||||||
export class Uint8ArrayWrapper {
|
|
||||||
static create(buffer: ArrayBuffer) { return new Uint8Array(buffer); }
|
|
||||||
}
|
|
@ -8,20 +8,19 @@
|
|||||||
|
|
||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
import {FileReader, Uint8ArrayWrapper} from './file_api';
|
|
||||||
import {BitmapService} from './services/bitmap';
|
import {BitmapService} from './services/bitmap';
|
||||||
|
|
||||||
|
|
||||||
@Component({selector: 'image-demo', viewProviders: [BitmapService], templateUrl: 'image_demo.html'})
|
@Component({selector: 'image-demo', viewProviders: [BitmapService], templateUrl: 'image_demo.html'})
|
||||||
export class ImageDemo {
|
export class ImageDemo {
|
||||||
images: any[] /** TODO #9100 */ = [];
|
images: {src: string, buffer: ArrayBuffer, filtering: boolean}[] = [];
|
||||||
fileInput: String;
|
fileInput: String;
|
||||||
|
|
||||||
constructor(private _bitmapService: BitmapService) {}
|
constructor(private _bitmapService: BitmapService) {}
|
||||||
|
|
||||||
uploadFiles(files: any /** TODO #9100 */) {
|
uploadFiles(files: FileList) {
|
||||||
for (var i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
var reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.addEventListener('load', this.handleReaderLoad(reader));
|
reader.addEventListener('load', this.handleReaderLoad(reader));
|
||||||
reader.readAsArrayBuffer(files[i]);
|
reader.readAsArrayBuffer(files[i]);
|
||||||
}
|
}
|
||||||
@ -29,9 +28,9 @@ export class ImageDemo {
|
|||||||
|
|
||||||
handleReaderLoad(reader: FileReader): EventListener {
|
handleReaderLoad(reader: FileReader): EventListener {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
var buffer = reader.result;
|
const buffer = reader.result as ArrayBuffer;
|
||||||
this.images.push({
|
this.images.push({
|
||||||
src: this._bitmapService.arrayBufferToDataUri(Uint8ArrayWrapper.create(reader.result)),
|
src: this._bitmapService.arrayBufferToDataUri(new Uint8Array(buffer)),
|
||||||
buffer: buffer,
|
buffer: buffer,
|
||||||
filtering: false
|
filtering: false
|
||||||
});
|
});
|
||||||
@ -39,16 +38,16 @@ export class ImageDemo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyFilters() {
|
applyFilters() {
|
||||||
for (var i = 0; i < this.images.length; i++) {
|
for (let i = 0; i < this.images.length; i++) {
|
||||||
this.images[i].filtering = true;
|
this.images[i].filtering = true;
|
||||||
|
|
||||||
setTimeout(this._filter(i), 0);
|
setTimeout(this._filter(i), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filter(i: number): (...args: any[]) => void {
|
private _filter(i: number): () => void {
|
||||||
return () => {
|
return () => {
|
||||||
var imageData = this._bitmapService.convertToImageData(this.images[i].buffer);
|
let imageData = this._bitmapService.convertToImageData(this.images[i].buffer);
|
||||||
imageData = this._bitmapService.applySepia(imageData);
|
imageData = this._bitmapService.applySepia(imageData);
|
||||||
this.images[i].src = this._bitmapService.toDataUri(imageData);
|
this.images[i].src = this._bitmapService.toDataUri(imageData);
|
||||||
this.images[i].filtering = false;
|
this.images[i].filtering = false;
|
||||||
|
@ -22,6 +22,7 @@ System.config({
|
|||||||
'@angular/compiler': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/compiler': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/common': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/common': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/platform-browser': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/platform-browser': {main: 'index.js', defaultExtension: 'js'},
|
||||||
|
'@angular/platform-browser-dynamic': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/platform-webworker': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/platform-webworker': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/platform-webworker-dynamic': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/platform-webworker-dynamic': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/router': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/router': {main: 'index.js', defaultExtension: 'js'},
|
||||||
|
@ -6,31 +6,25 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <reference path="../bitmap.d.ts" /> /// <reference path="../b64.d.ts" />
|
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
declare var base64js: any /** TODO #9100 */;
|
import * as base64js from '../b64';
|
||||||
|
|
||||||
// Temporary fix for Typescript issue #4220 (https://github.com/Microsoft/TypeScript/issues/4220)
|
|
||||||
// var _ImageData: (width: number, height: number) => void = <any>postMessage;
|
|
||||||
var _ImageData: {prototype: ImageData, new (width: number, height: number): ImageData;} = ImageData;
|
|
||||||
|
|
||||||
// This class is based on the Bitmap examples at:
|
// This class is based on the Bitmap examples at:
|
||||||
// http://www.i-programmer.info/projects/36-web/6234-reading-a-bmp-file-in-javascript.html
|
// http://www.i-programmer.info/projects/36-web/6234-reading-a-bmp-file-in-javascript.html
|
||||||
// and
|
// and http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
|
||||||
// http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BitmapService {
|
export class BitmapService {
|
||||||
convertToImageData(buffer: ArrayBuffer): ImageData {
|
convertToImageData(buffer: ArrayBuffer): ImageData {
|
||||||
var bmp = this._getBMP(buffer);
|
const bmp = this._getBMP(buffer);
|
||||||
return this._BMPToImageData(bmp);
|
return this._BMPToImageData(bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
applySepia(imageData: ImageData): ImageData {
|
applySepia(imageData: ImageData): ImageData {
|
||||||
var buffer = imageData.data;
|
const buffer = imageData.data;
|
||||||
for (var i = 0; i < buffer.length; i += 4) {
|
for (let i = 0; i < buffer.length; i += 4) {
|
||||||
var r = buffer[i];
|
const r = buffer[i];
|
||||||
var g = buffer[i + 1];
|
const g = buffer[i + 1];
|
||||||
var b = buffer[i + 2];
|
const b = buffer[i + 2];
|
||||||
buffer[i] = (r * .393) + (g * .769) + (b * .189);
|
buffer[i] = (r * .393) + (g * .769) + (b * .189);
|
||||||
buffer[i + 1] = (r * .349) + (g * .686) + (b * .168);
|
buffer[i + 1] = (r * .349) + (g * .686) + (b * .168);
|
||||||
buffer[i + 2] = (r * .272) + (g * .534) + (b * .131);
|
buffer[i + 2] = (r * .272) + (g * .534) + (b * .131);
|
||||||
@ -39,7 +33,7 @@ export class BitmapService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toDataUri(imageData: ImageData): string {
|
toDataUri(imageData: ImageData): string {
|
||||||
var header = this._createBMPHeader(imageData);
|
const header = this._createBMPHeader(imageData);
|
||||||
imageData = this._imageDataToBMP(imageData);
|
imageData = this._imageDataToBMP(imageData);
|
||||||
return 'data:image/bmp;base64,' + btoa(header) + base64js.fromByteArray(imageData.data);
|
return 'data:image/bmp;base64,' + btoa(header) + base64js.fromByteArray(imageData.data);
|
||||||
}
|
}
|
||||||
@ -51,14 +45,14 @@ export class BitmapService {
|
|||||||
|
|
||||||
// returns a UInt8Array in BMP order (starting from the bottom)
|
// returns a UInt8Array in BMP order (starting from the bottom)
|
||||||
private _imageDataToBMP(imageData: ImageData): ImageData {
|
private _imageDataToBMP(imageData: ImageData): ImageData {
|
||||||
var width = imageData.width;
|
const width = imageData.width;
|
||||||
var height = imageData.height;
|
const height = imageData.height;
|
||||||
|
|
||||||
var data = imageData.data;
|
const data = imageData.data;
|
||||||
for (var y = 0; y < height / 2; ++y) {
|
for (let y = 0; y < height / 2; ++y) {
|
||||||
var topIndex = y * width * 4;
|
let topIndex = y * width * 4;
|
||||||
var bottomIndex = (height - y) * width * 4;
|
let bottomIndex = (height - y) * width * 4;
|
||||||
for (var i = 0; i < width * 4; i++) {
|
for (let i = 0; i < width * 4; i++) {
|
||||||
this._swap(data, topIndex, bottomIndex);
|
this._swap(data, topIndex, bottomIndex);
|
||||||
topIndex++;
|
topIndex++;
|
||||||
bottomIndex++;
|
bottomIndex++;
|
||||||
@ -69,7 +63,7 @@ export class BitmapService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _swap(data: Uint8Array|Uint8ClampedArray|number[], index1: number, index2: number) {
|
private _swap(data: Uint8Array|Uint8ClampedArray|number[], index1: number, index2: number) {
|
||||||
var temp = data[index1];
|
const temp = data[index1];
|
||||||
data[index1] = data[index2];
|
data[index1] = data[index2];
|
||||||
data[index2] = temp;
|
data[index2] = temp;
|
||||||
}
|
}
|
||||||
@ -77,9 +71,9 @@ export class BitmapService {
|
|||||||
// Based on example from
|
// Based on example from
|
||||||
// http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
|
// http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
|
||||||
private _createBMPHeader(imageData: ImageData): string {
|
private _createBMPHeader(imageData: ImageData): string {
|
||||||
var numFileBytes = this._getLittleEndianHex(imageData.width * imageData.height);
|
const numFileBytes = this._getLittleEndianHex(imageData.width * imageData.height);
|
||||||
var w = this._getLittleEndianHex(imageData.width);
|
const w = this._getLittleEndianHex(imageData.width);
|
||||||
var h = this._getLittleEndianHex(imageData.height);
|
const h = this._getLittleEndianHex(imageData.height);
|
||||||
return 'BM' + // Signature
|
return 'BM' + // Signature
|
||||||
numFileBytes + // size of the file (bytes)*
|
numFileBytes + // size of the file (bytes)*
|
||||||
'\x00\x00' + // reserved
|
'\x00\x00' + // reserved
|
||||||
@ -99,18 +93,18 @@ export class BitmapService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _BMPToImageData(bmp: BitmapFile): ImageData {
|
private _BMPToImageData(bmp: BitmapFile): ImageData {
|
||||||
var width = bmp.infoHeader.biWidth;
|
const width = bmp.infoHeader.biWidth;
|
||||||
var height = bmp.infoHeader.biHeight;
|
const height = bmp.infoHeader.biHeight;
|
||||||
var imageData = new _ImageData(width, height);
|
const imageData = new ImageData(width, height);
|
||||||
|
|
||||||
var data = imageData.data;
|
const data = imageData.data;
|
||||||
var bmpData = bmp.pixels;
|
const bmpData = bmp.pixels;
|
||||||
var stride = bmp.stride;
|
const stride = bmp.stride;
|
||||||
|
|
||||||
for (var y = 0; y < height; ++y) {
|
for (let y = 0; y < height; ++y) {
|
||||||
for (var x = 0; x < width; ++x) {
|
for (let x = 0; x < width; ++x) {
|
||||||
var index1 = (x + width * (height - y)) * 4;
|
const index1 = (x + width * (height - y)) * 4;
|
||||||
var index2 = x * 3 + stride * y;
|
const index2 = x * 3 + stride * y;
|
||||||
data[index1] = bmpData[index2 + 2];
|
data[index1] = bmpData[index2 + 2];
|
||||||
data[index1 + 1] = bmpData[index2 + 1];
|
data[index1 + 1] = bmpData[index2 + 1];
|
||||||
data[index1 + 2] = bmpData[index2];
|
data[index1 + 2] = bmpData[index2];
|
||||||
@ -121,8 +115,8 @@ export class BitmapService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getBMP(buffer: ArrayBuffer): BitmapFile {
|
private _getBMP(buffer: ArrayBuffer): BitmapFile {
|
||||||
var datav = new DataView(buffer);
|
const datav = new DataView(buffer);
|
||||||
var bitmap: BitmapFile = {
|
const bitmap: BitmapFile = {
|
||||||
fileHeader: {
|
fileHeader: {
|
||||||
bfType: datav.getUint16(0, true),
|
bfType: datav.getUint16(0, true),
|
||||||
bfSize: datav.getUint32(2, true),
|
bfSize: datav.getUint32(2, true),
|
||||||
@ -146,7 +140,7 @@ export class BitmapService {
|
|||||||
stride: null,
|
stride: null,
|
||||||
pixels: null
|
pixels: null
|
||||||
};
|
};
|
||||||
var start = bitmap.fileHeader.bfOffBits;
|
const start = bitmap.fileHeader.bfOffBits;
|
||||||
bitmap.stride =
|
bitmap.stride =
|
||||||
Math.floor((bitmap.infoHeader.biBitCount * bitmap.infoHeader.biWidth + 31) / 32) * 4;
|
Math.floor((bitmap.infoHeader.biBitCount * bitmap.infoHeader.biWidth + 31) / 32) * 4;
|
||||||
bitmap.pixels = new Uint8Array(datav.buffer, start);
|
bitmap.pixels = new Uint8Array(datav.buffer, start);
|
||||||
@ -156,9 +150,9 @@ export class BitmapService {
|
|||||||
// Based on example from
|
// Based on example from
|
||||||
// http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
|
// http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
|
||||||
private _getLittleEndianHex(value: number): string {
|
private _getLittleEndianHex(value: number): string {
|
||||||
var result: any[] /** TODO #9100 */ = [];
|
const result: string[] = [];
|
||||||
|
|
||||||
for (var bytes = 4; bytes > 0; bytes--) {
|
for (let bytes = 4; bytes > 0; bytes--) {
|
||||||
result.push(String.fromCharCode(value & 255));
|
result.push(String.fromCharCode(value & 255));
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export class InputCmp {
|
|||||||
inputVal = '';
|
inputVal = '';
|
||||||
textareaVal = '';
|
textareaVal = '';
|
||||||
|
|
||||||
inputChanged(e: any /** TODO #9100 */) { this.inputVal = e.target.value; }
|
inputChanged(e: Event) { this.inputVal = (e.target as HTMLInputElement).value; }
|
||||||
|
|
||||||
textAreaChanged(e: any /** TODO #9100 */) { this.textareaVal = e.target.value; }
|
textAreaChanged(e: Event) { this.textareaVal = (e.target as HTMLTextAreaElement).value; }
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ export class RedDec {
|
|||||||
constructor(el: ElementRef, renderer: Renderer) {
|
constructor(el: ElementRef, renderer: Renderer) {
|
||||||
renderer.setElementStyle(el.nativeElement, 'color', 'red');
|
renderer.setElementStyle(el.nativeElement, 'color', 'red');
|
||||||
}
|
}
|
||||||
// constructor(renderer: Renderer) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Angular 2.0 supports 2 basic types of directives:
|
// Angular 2.0 supports 2 basic types of directives:
|
||||||
@ -54,7 +53,5 @@ export class HelloCmp {
|
|||||||
|
|
||||||
changeGreeting(): void { this.greeting = 'howdy'; }
|
changeGreeting(): void { this.greeting = 'howdy'; }
|
||||||
|
|
||||||
onKeyDown(event: any /** TODO #9100 */): void {
|
onKeyDown(event: KeyboardEvent): void { this.lastKey = String.fromCharCode(event.keyCode); }
|
||||||
this.lastKey = String.fromCharCode(event.keyCode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,15 +18,15 @@ export class TodoApp {
|
|||||||
hideCompleted: boolean = false;
|
hideCompleted: boolean = false;
|
||||||
isComplete: boolean = false;
|
isComplete: boolean = false;
|
||||||
|
|
||||||
constructor(public todoStore: Store, public factory: TodoFactory) {}
|
constructor(public todoStore: Store<Todo>, public factory: TodoFactory) {}
|
||||||
|
|
||||||
enterTodo(): void {
|
enterTodo(): void {
|
||||||
this.addTodo(this.inputValue);
|
this.addTodo(this.inputValue);
|
||||||
this.inputValue = '';
|
this.inputValue = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
doneEditing($event: any /** TODO #9100 */, todo: Todo): void {
|
doneEditing($event: KeyboardEvent, todo: Todo): void {
|
||||||
var which = $event.keyCode;
|
const which = $event.keyCode;
|
||||||
if (which === 13) {
|
if (which === 13) {
|
||||||
todo.title = todo.editTitle;
|
todo.title = todo.editTitle;
|
||||||
this.todoEdit = null;
|
this.todoEdit = null;
|
||||||
@ -59,7 +59,7 @@ export class TodoApp {
|
|||||||
|
|
||||||
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
deleteMe(todo: Todo): void { this.todoStore.remove(todo); }
|
||||||
|
|
||||||
toggleAll($event: any /** TODO #9100 */): void {
|
toggleAll($event: MouseEvent): void {
|
||||||
this.isComplete = !this.isComplete;
|
this.isComplete = !this.isComplete;
|
||||||
this.todoStore.list.forEach((todo: Todo) => { todo.completed = this.isComplete; });
|
this.todoStore.list.forEach((todo: Todo) => { todo.completed = this.isComplete; });
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {ListWrapper, Predicate} from '@angular/core/src/facade/collection';
|
|
||||||
|
|
||||||
// base model for RecordStore
|
// base model for RecordStore
|
||||||
export class KeyModel {
|
export class KeyModel {
|
||||||
@ -35,25 +34,14 @@ export class TodoFactory {
|
|||||||
|
|
||||||
// Store manages any generic item that inherits from KeyModel
|
// Store manages any generic item that inherits from KeyModel
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Store {
|
export class Store<T extends KeyModel> {
|
||||||
list: KeyModel[] = [];
|
list: T[] = [];
|
||||||
|
|
||||||
add(record: KeyModel): void { this.list.push(record); }
|
add(record: T): void { this.list.push(record); }
|
||||||
|
|
||||||
remove(record: KeyModel): void { this._spliceOut(record); }
|
remove(record: T): void { this.removeBy((item) => item === record); }
|
||||||
|
|
||||||
removeBy(callback: Predicate<KeyModel>): void {
|
removeBy(callback: (record: T) => boolean): void {
|
||||||
var records = this.list.filter(callback);
|
this.list = this.list.filter((record) => !callback(record));
|
||||||
ListWrapper.removeAll(this.list, records);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _spliceOut(record: KeyModel) {
|
|
||||||
var i = this._indexFor(record);
|
|
||||||
if (i > -1) {
|
|
||||||
return this.list.splice(i, 1)[0];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _indexFor(record: KeyModel) { return this.list.indexOf(record); }
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user