chore(material): clean up old workarounds with new features.

This commit is contained in:
Jeremy Elbourn 2015-08-04 15:32:17 -07:00
parent 7c52bc9768
commit bd498977bd
21 changed files with 223 additions and 227 deletions

View File

@ -1169,7 +1169,7 @@ gulp.task('benchpress.bundle', ['build/clean.benchpress.bundle', 'build.js.cjs']
BENCHPRESS_BUNDLE_CONFIG.dest, BENCHPRESS_BUNDLE_CONFIG.dest,
cb cb
); );
}) });
// register cleanup listener for ctrl+c/kill used to quit any persistent task (autotest or serve tasks) // register cleanup listener for ctrl+c/kill used to quit any persistent task (autotest or serve tasks)

View File

@ -1,6 +1,6 @@
import {Component, View, Attribute, ViewEncapsulation} from 'angular2/angular2'; import {Component, View, Attribute, ViewEncapsulation} from 'angular2/angular2';
import {isPresent} from 'angular2/src/facade/lang'; import {isPresent} from 'angular2/src/facade/lang';
import {KEY_SPACE} from 'angular2_material/src/core/constants'; import {KeyCodes} from 'angular2_material/src/core/key_codes';
import {KeyboardEvent} from 'angular2/src/facade/browser'; import {KeyboardEvent} from 'angular2/src/facade/browser';
import {NumberWrapper} from 'angular2/src/facade/lang'; import {NumberWrapper} from 'angular2/src/facade/lang';
@ -8,11 +8,11 @@ import {NumberWrapper} from 'angular2/src/facade/lang';
selector: 'md-checkbox', selector: 'md-checkbox',
properties: ['checked', 'disabled'], properties: ['checked', 'disabled'],
host: { host: {
'(keydown)': 'onKeydown($event)', 'role': 'checkbox',
'[tabindex]': 'tabindex',
'[attr.role]': '"checkbox"',
'[attr.aria-checked]': 'checked', '[attr.aria-checked]': 'checked',
'[attr.aria-disabled]': 'disabled' '[attr.aria-disabled]': 'disabled',
'[tabindex]': 'tabindex',
'(keydown)': 'onKeydown($event)',
} }
}) })
@View({ @View({
@ -25,7 +25,7 @@ export class MdCheckbox {
checked: boolean; checked: boolean;
/** Whether this checkbox is disabled. */ /** Whether this checkbox is disabled. */
_disabled: boolean; disabled_: boolean;
/** Setter for tabindex */ /** Setter for tabindex */
tabindex: number; tabindex: number;
@ -33,19 +33,19 @@ export class MdCheckbox {
constructor(@Attribute('tabindex') tabindex: string) { constructor(@Attribute('tabindex') tabindex: string) {
this.checked = false; this.checked = false;
this.tabindex = isPresent(tabindex) ? NumberWrapper.parseInt(tabindex, 10) : 0; this.tabindex = isPresent(tabindex) ? NumberWrapper.parseInt(tabindex, 10) : 0;
this._disabled = false; this.disabled_ = false;
} }
get disabled() { get disabled() {
return this._disabled; return this.disabled_;
} }
set disabled(value) { set disabled(value) {
this._disabled = isPresent(value) && value !== false; this.disabled_ = isPresent(value) && value !== false;
} }
onKeydown(event: KeyboardEvent) { onKeydown(event: KeyboardEvent) {
if (event.keyCode == KEY_SPACE) { if (event.keyCode == KeyCodes.SPACE) {
event.preventDefault(); event.preventDefault();
this.toggle(event); this.toggle(event);
} }

View File

@ -16,7 +16,7 @@ import {ObservableWrapper, Promise, PromiseWrapper} from 'angular2/src/facade/as
import {isPresent, Type} from 'angular2/src/facade/lang'; import {isPresent, Type} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter';
import {MouseEvent, KeyboardEvent} from 'angular2/src/facade/browser'; import {MouseEvent, KeyboardEvent} from 'angular2/src/facade/browser';
import {KEY_ESC} from 'angular2_material/src/core/constants'; import {KeyCodes} from 'angular2_material/src/core/key_codes';
// TODO(jelbourn): Opener of dialog can control where it is rendered. // TODO(jelbourn): Opener of dialog can control where it is rendered.
// TODO(jelbourn): body scrolling is disabled while dialog is open. // TODO(jelbourn): body scrolling is disabled while dialog is open.
@ -44,7 +44,6 @@ export class MdDialog {
* Opens a modal dialog. * Opens a modal dialog.
* @param type The component to open. * @param type The component to open.
* @param elementRef The logical location into which the component will be opened. * @param elementRef The logical location into which the component will be opened.
* @param parentInjector
* @param options * @param options
* @returns Promise for a reference to the dialog. * @returns Promise for a reference to the dialog.
*/ */
@ -69,11 +68,6 @@ export class MdDialog {
var dialogElement = containerRef.location.nativeElement; var dialogElement = containerRef.location.nativeElement;
DOM.appendChild(DOM.query('body'), dialogElement); DOM.appendChild(DOM.query('body'), dialogElement);
// TODO(jelbourn): Use hostProperties binding to set these once #1539 is fixed.
// Configure properties on the host element.
DOM.addClass(dialogElement, 'md-dialog');
DOM.setAttribute(dialogElement, 'tabindex', '0');
// TODO(jelbourn): Do this with hostProperties (or another rendering abstraction) once // TODO(jelbourn): Do this with hostProperties (or another rendering abstraction) once
// ready. // ready.
if (isPresent(config.width)) { if (isPresent(config.width)) {
@ -119,11 +113,11 @@ export class MdDialog {
} }
alert(message: string, okMessage: string): Promise<any> { alert(message: string, okMessage: string): Promise<any> {
throw "Not implemented"; throw 'Not implemented';
} }
confirm(message: string, okMessage: string, cancelMessage: string): Promise<any> { confirm(message: string, okMessage: string, cancelMessage: string): Promise<any> {
throw "Not implemented"; throw 'Not implemented';
} }
} }
@ -209,9 +203,14 @@ export class MdDialogConfig {
*/ */
@Component({ @Component({
selector: 'md-dialog-container', selector: 'md-dialog-container',
host: {'(body:^keydown)': 'documentKeypress($event)'}, host: {
'class': 'md-dialog',
'tabindex': '0',
'(body:^keydown)': 'documentKeypress($event)',
},
}) })
@View({ @View({
encapsulation: ViewEncapsulation.NONE,
templateUrl: 'package:angular2_material/src/components/dialog/dialog.html', templateUrl: 'package:angular2_material/src/components/dialog/dialog.html',
directives: [forwardRef(() => MdDialogContent)] directives: [forwardRef(() => MdDialogContent)]
}) })
@ -232,7 +231,7 @@ class MdDialogContainer {
} }
documentKeypress(event: KeyboardEvent) { documentKeypress(event: KeyboardEvent) {
if (event.keyCode == KEY_ESC) { if (event.keyCode == KeyCodes.ESCAPE) {
this.dialogRef.close(); this.dialogRef.close();
} }
} }
@ -243,7 +242,9 @@ class MdDialogContainer {
* location * location
* for where the dialog content will be loaded. * for where the dialog content will be loaded.
*/ */
@Directive({selector: 'md-dialog-content'}) @Directive({
selector: 'md-dialog-content',
})
class MdDialogContent { class MdDialogContent {
constructor(@Host() @SkipSelf() dialogContainer: MdDialogContainer, elementRef: ElementRef) { constructor(@Host() @SkipSelf() dialogContainer: MdDialogContainer, elementRef: ElementRef) {
dialogContainer.contentRef = elementRef; dialogContainer.contentRef = elementRef;
@ -253,9 +254,11 @@ class MdDialogContent {
/** Component for the dialog "backdrop", a transparent overlay over the rest of the page. */ /** Component for the dialog "backdrop", a transparent overlay over the rest of the page. */
@Component({ @Component({
selector: 'md-backdrop', selector: 'md-backdrop',
host: {'(click)': 'onClick()'}, host: {
'(click)': 'onClick()',
},
}) })
@View({template: ''}) @View({template: '', encapsulation: ViewEncapsulation.NONE})
class MdBackdrop { class MdBackdrop {
dialogRef: MdDialogRef; dialogRef: MdDialogRef;

View File

@ -16,7 +16,14 @@ import {Math} from 'angular2/src/facade/math';
// TODO(jelbourn): Conditional (responsive) column count / row size. // TODO(jelbourn): Conditional (responsive) column count / row size.
// TODO(jelbourn): Re-layout on window resize / media change (debounced). // TODO(jelbourn): Re-layout on window resize / media change (debounced).
// TODO(jelbourn): gridTileHeader and gridTileFooter. // TODO(jelbourn): gridTileHeader and gridTileFooter.
// TODO(jelbourn): rowHeightMode enum (after TS conversion).
/** Row hieght mode options. Use a static class b/c TypeScript enums are strictly number-based. */
class RowHeightMode {
static FIT = 'fit';
static FIXED = 'fixed';
static RATIO = 'ratio';
}
@Component({ @Component({
selector: 'md-grid-list', selector: 'md-grid-list',
@ -64,19 +71,19 @@ export class MdGridList {
/** Set internal representation of row height from the user-provided value. */ /** Set internal representation of row height from the user-provided value. */
set rowHeight(value) { set rowHeight(value) {
if (value === 'fit') { if (value === RowHeightMode.FIT) {
this.rowHeightMode = 'fit'; this.rowHeightMode = RowHeightMode.FIT;
} else if (StringWrapper.contains(value, ':')) { } else if (StringWrapper.contains(value, ':')) {
var ratioParts = value.split(':'); let ratioParts = value.split(':');
if (ratioParts.length !== 2) { if (ratioParts.length !== 2) {
throw `md-grid-list: invalid ratio given for row-height: "${value}"`; throw `md-grid-list: invalid ratio given for row-height: "${value}"`;
} }
this.rowHeightMode = 'ratio'; this.rowHeightMode = RowHeightMode.RATIO;
this.rowHeightRatio = this.rowHeightRatio =
NumberWrapper.parseFloat(ratioParts[0]) / NumberWrapper.parseFloat(ratioParts[1]); NumberWrapper.parseFloat(ratioParts[0]) / NumberWrapper.parseFloat(ratioParts[1]);
} else { } else {
this.rowHeightMode = 'fixed'; this.rowHeightMode = RowHeightMode.FIXED;
this.fixedRowHeight = value; this.fixedRowHeight = value;
} }
} }
@ -87,20 +94,13 @@ export class MdGridList {
/** Computes and applies the size and position for all children grid tiles. */ /** Computes and applies the size and position for all children grid tiles. */
layoutTiles() { layoutTiles() {
var tracker = new TileCoordinator(this.cols, this.tiles); let tracker = new TileCoordinator(this.cols, this.tiles);
this.rows = tracker.rowCount; this.rows = tracker.rowCount;
for (var i = 0; i < this.tiles.length; i++) { for (let i = 0; i < this.tiles.length; i++) {
var pos = tracker.positions[i]; let pos = tracker.positions[i];
var tile = this.tiles[i]; let tile = this.tiles[i];
var style = this.getTileStyle(tile, pos.row, pos.col); tile.style = this.getTileStyle(tile, pos.row, pos.col);
tile.styleWidth = style.width;
tile.styleHeight = style.height;
tile.styleTop = style.top;
tile.styleLeft = style.left;
tile.styleMarginTop = style.marginTop;
tile.stylePaddingTop = style.paddingTop;
} }
} }
@ -164,55 +164,50 @@ export class MdGridList {
/** Gets the style properties to be applied to a tile for the given row and column index. */ /** Gets the style properties to be applied to a tile for the given row and column index. */
getTileStyle(tile: MdGridTile, rowIndex: number, colIndex: number): TileStyle { getTileStyle(tile: MdGridTile, rowIndex: number, colIndex: number): TileStyle {
// Percent of the available horizontal space that one column takes up. // Percent of the available horizontal space that one column takes up.
var percentWidthPerTile = 100 / this.cols; let percentWidthPerTile = 100 / this.cols;
// Fraction of the vertical gutter size that each column takes up. // Fraction of the vertical gutter size that each column takes up.
// For example, if there are 5 columns, each column uses 4/5 = 0.8 times the gutter width. // For example, if there are 5 columns, each column uses 4/5 = 0.8 times the gutter width.
var gutterWidthFractionPerTile = (this.cols - 1) / this.cols; let gutterWidthFractionPerTile = (this.cols - 1) / this.cols;
// Base horizontal size of a column. // Base horizontal size of a column.
var baseTileWidth = this.getBaseTileSize(percentWidthPerTile, gutterWidthFractionPerTile); let baseTileWidth = this.getBaseTileSize(percentWidthPerTile, gutterWidthFractionPerTile);
// The width and horizontal position of each tile is always calculated the same way, but the // The width and horizontal position of each tile is always calculated the same way, but the
// height and vertical position depends on the rowMode. // height and vertical position depends on the rowMode.
var tileStyle = new TileStyle(); let tileStyle = new TileStyle();
tileStyle.left = this.getTilePosition(baseTileWidth, colIndex); tileStyle.left = this.getTilePosition(baseTileWidth, colIndex);
tileStyle.width = this.getTileSize(baseTileWidth, tile.colspan); tileStyle.width = this.getTileSize(baseTileWidth, tile.colspan);
// TODO: make cases enums when we support enums if (this.rowHeightMode == RowHeightMode.FIXED) {
switch (this.rowHeightMode) {
case 'fixed':
// In fixed mode, simply use the given row height. // In fixed mode, simply use the given row height.
tileStyle.top = this.getTilePosition(this.fixedRowHeight, rowIndex); tileStyle.top = this.getTilePosition(this.fixedRowHeight, rowIndex);
tileStyle.height = this.getTileSize(this.fixedRowHeight, tile.rowspan); tileStyle.height = this.getTileSize(this.fixedRowHeight, tile.rowspan);
break; }
case 'ratio': if (this.rowHeightMode == RowHeightMode.RATIO) {
var percentHeightPerTile = percentWidthPerTile / this.rowHeightRatio; let percentHeightPerTile = percentWidthPerTile / this.rowHeightRatio;
var baseTileHeight = this.getBaseTileSize(percentHeightPerTile, gutterWidthFractionPerTile); let baseTileHeight = this.getBaseTileSize(percentHeightPerTile, gutterWidthFractionPerTile);
// Use paddingTop and marginTop to maintain the given aspect ratio, as // Use paddingTop and marginTop to maintain the given aspect ratio, as
// a percentage-based value for these properties is applied versus the *width* of the // a percentage-based value for these properties is applied versus the *width* of the
// containing block. See http://www.w3.org/TR/CSS2/box.html#margin-properties // containing block. See http://www.w3.org/TR/CSS2/box.html#margin-properties
tileStyle.marginTop = this.getTilePosition(baseTileHeight, rowIndex); tileStyle.marginTop = this.getTilePosition(baseTileHeight, rowIndex);
tileStyle.paddingTop = this.getTileSize(baseTileHeight, tile.rowspan); tileStyle.paddingTop = this.getTileSize(baseTileHeight, tile.rowspan);
break; }
case 'fit': if (this.rowHeightMode == RowHeightMode.FIT) {
// Percent of the available vertical space that one row takes up. // Percent of the available vertical space that one row takes up.
var percentHeightPerTile = 100 / this.cols; let percentHeightPerTile = 100 / this.cols;
// Fraction of the horizontal gutter size that each column takes up. // Fraction of the horizontal gutter size that each column takes up.
var gutterHeightFractionPerTile = (this.rows - 1) / this.rows; let gutterHeightFractionPerTile = (this.rows - 1) / this.rows;
// Base vertical size of a column. // Base vertical size of a column.
var baseTileHeight = let baseTileHeight = this.getBaseTileSize(percentHeightPerTile, gutterHeightFractionPerTile);
this.getBaseTileSize(percentHeightPerTile, gutterHeightFractionPerTile);
tileStyle.top = this.getTilePosition(baseTileHeight, rowIndex); tileStyle.top = this.getTilePosition(baseTileHeight, rowIndex);
tileStyle.height = this.getTileSize(baseTileHeight, tile.rowspan); tileStyle.height = this.getTileSize(baseTileHeight, tile.rowspan);
break;
} }
return tileStyle; return tileStyle;
@ -223,13 +218,13 @@ export class MdGridList {
selector: 'md-grid-tile', selector: 'md-grid-tile',
properties: ['rowspan', 'colspan'], properties: ['rowspan', 'colspan'],
host: { host: {
'[style.height]': 'styleHeight', 'role': 'listitem',
'[style.width]': 'styleWidth', '[style.height]': 'style.height',
'[style.top]': 'styleTop', '[style.width]': 'style.width',
'[style.left]': 'styleLeft', '[style.top]': 'style.top',
'[style.marginTop]': 'styleMarginTop', '[style.left]': 'style.left',
'[style.paddingTop]': 'stylePaddingTop', '[style.marginTop]': 'style.marginTop',
'[attr.role]': '"listitem"' '[style.paddingTop]': 'style.paddingTop',
}, },
lifecycle: [LifecycleEvent.onDestroy, LifecycleEvent.onChange] lifecycle: [LifecycleEvent.onDestroy, LifecycleEvent.onChange]
}) })
@ -242,13 +237,7 @@ export class MdGridTile {
_rowspan: number; _rowspan: number;
_colspan: number; _colspan: number;
styleHeight: string; style: TileStyle;
styleWidth: string;
styleTop: string;
styleLeft: string;
styleMarginTop: string;
stylePaddingTop: string;
isRegisteredWithGridList: boolean; isRegisteredWithGridList: boolean;
constructor(@SkipSelf() @Host() gridList: MdGridList) { constructor(@SkipSelf() @Host() gridList: MdGridList) {
@ -257,6 +246,7 @@ export class MdGridTile {
// Tiles default to 1x1, but rowspan and colspan can be changed via binding. // Tiles default to 1x1, but rowspan and colspan can be changed via binding.
this.rowspan = 1; this.rowspan = 1;
this.colspan = 1; this.colspan = 1;
this.style = new TileStyle();
} }
set rowspan(value) { set rowspan(value) {
@ -330,7 +320,7 @@ class TileCoordinator {
this.tracker = ListWrapper.createFixedSize(numColumns); this.tracker = ListWrapper.createFixedSize(numColumns);
ListWrapper.fill(this.tracker, 0); ListWrapper.fill(this.tracker, 0);
this.positions = ListWrapper.map(tiles, tile => this._trackTile(tile)); this.positions = tiles.map(tile => this._trackTile(tile));
} }
/** Gets the number of rows occupied by tiles. */ /** Gets the number of rows occupied by tiles. */
@ -345,8 +335,8 @@ class TileCoordinator {
} }
// Start index is inclusive, end index is exclusive. // Start index is inclusive, end index is exclusive.
var gapStartIndex = -1; let gapStartIndex = -1;
var gapEndIndex = -1; let gapEndIndex = -1;
// Look for a gap large enough to fit the given tile. Empty spaces are marked with a zero. // Look for a gap large enough to fit the given tile. Empty spaces are marked with a zero.
do { do {
@ -389,7 +379,7 @@ class TileCoordinator {
this.rowIndex++; this.rowIndex++;
// Decrement all spaces by one to reflect moving down one row. // Decrement all spaces by one to reflect moving down one row.
for (var i = 0; i < this.tracker.length; i++) { for (let i = 0; i < this.tracker.length; i++) {
this.tracker[i] = Math.max(0, this.tracker[i] - 1); this.tracker[i] = Math.max(0, this.tracker[i] - 1);
} }
} }
@ -399,7 +389,7 @@ class TileCoordinator {
* The gap ends when a non-zero value is found. * The gap ends when a non-zero value is found.
*/ */
_findGapEndIndex(gapStartIndex: number): number { _findGapEndIndex(gapStartIndex: number): number {
for (var i = gapStartIndex + 1; i < this.tracker.length; i++) { for (let i = gapStartIndex + 1; i < this.tracker.length; i++) {
if (this.tracker[i] != 0) { if (this.tracker[i] != 0) {
return i; return i;
} }
@ -411,7 +401,7 @@ class TileCoordinator {
/** Update the tile tracker to account for the given tile in the given space. */ /** Update the tile tracker to account for the given tile in the given space. */
_markTilePosition(start, tile) { _markTilePosition(start, tile) {
for (var i = 0; i < tile.colspan; i++) { for (let i = 0; i < tile.colspan; i++) {
this.tracker[start + i] = tile.rowspan; this.tracker[start + i] = tile.rowspan;
} }
} }

View File

@ -10,8 +10,10 @@ import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
@Directive({ @Directive({
selector: 'md-input-container', selector: 'md-input-container',
lifecycle: [LifecycleEvent.onAllChangesDone], lifecycle: [LifecycleEvent.onAllChangesDone],
host: host: {
{'[class.md-input-has-value]': 'inputHasValue', '[class.md-input-focused]': 'inputHasFocus'} '[class.md-input-has-value]': 'inputHasValue',
'[class.md-input-focused]': 'inputHasFocus',
}
}) })
export class MdInputContainer { export class MdInputContainer {
// The MdInput or MdTextarea inside of this container. // The MdInput or MdTextarea inside of this container.
@ -59,7 +61,7 @@ export class MdInputContainer {
selector: 'md-input-container input', selector: 'md-input-container input',
events: ['mdChange', 'mdFocusChange'], events: ['mdChange', 'mdFocusChange'],
host: { host: {
'[class.md-input]': 'yes', 'class': 'md-input',
'(input)': 'updateValue($event)', '(input)': 'updateValue($event)',
'(focus)': 'setHasFocus(true)', '(focus)': 'setHasFocus(true)',
'(blur)': 'setHasFocus(false)' '(blur)': 'setHasFocus(false)'
@ -67,7 +69,6 @@ export class MdInputContainer {
}) })
export class MdInput { export class MdInput {
value: string; value: string;
yes: boolean;
// Events emitted by this directive. We use these special 'md-' events to communicate // Events emitted by this directive. We use these special 'md-' events to communicate
// to the parent MdInputContainer. // to the parent MdInputContainer.
@ -76,9 +77,6 @@ export class MdInput {
constructor(@Attribute('value') value: string, @SkipSelf() @Host() container: MdInputContainer, constructor(@Attribute('value') value: string, @SkipSelf() @Host() container: MdInputContainer,
@Attribute('id') id: string) { @Attribute('id') id: string) {
// TODO(jelbourn): Remove this when #1402 is done.
this.yes = true;
this.value = value == null ? '' : value; this.value = value == null ? '' : value;
this.mdChange = new EventEmitter(); this.mdChange = new EventEmitter();
this.mdFocusChange = new EventEmitter(); this.mdFocusChange = new EventEmitter();

View File

@ -1,16 +1,26 @@
import {Component, LifecycleEvent, View, ViewEncapsulation, Attribute} from 'angular2/angular2'; import {Component, LifecycleEvent, View, ViewEncapsulation, Attribute} from 'angular2/angular2';
import {CONST} from 'angular2/src/facade/lang';
import {isPresent, isBlank} from 'angular2/src/facade/lang'; import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {Math} from 'angular2/src/facade/math'; import {Math} from 'angular2/src/facade/math';
/** Different display / behavior modes for progress-linear. */
@CONST()
class ProgressMode {
@CONST() static DETERMINATE = 'determinate';
@CONST() static INDETERMINATE = 'indeterminate';
@CONST() static BUFFER = 'buffer';
@CONST() static QUERY = 'query';
}
@Component({ @Component({
selector: 'md-progress-linear', selector: 'md-progress-linear',
lifecycle: [LifecycleEvent.onChange], lifecycle: [LifecycleEvent.onChange],
properties: ['value', 'bufferValue'], properties: ['value', 'bufferValue'],
host: { host: {
'[attr.role]': '"progressbar"', 'role': 'progressbar',
'[attr.aria-valuemin]': '"0"', 'aria-valuemin': '0',
'[attr.aria-valuemax]': '"100"', 'aria-valuemax': '100',
'[attr.aria-valuenow]': 'value' '[attr.aria-valuenow]': 'value'
} }
}) })
@ -35,11 +45,11 @@ export class MdProgressLinear {
/** CSS `transform` property applied to the secondary bar. */ /** CSS `transform` property applied to the secondary bar. */
secondaryBarTransform: string; secondaryBarTransform: string;
constructor(@Attribute('md-mode') mode: string) { constructor(@Attribute('mode') mode: string) {
this.primaryBarTransform = ''; this.primaryBarTransform = '';
this.secondaryBarTransform = ''; this.secondaryBarTransform = '';
this.mode = isPresent(mode) ? mode : Mode.DETERMINATE; this.mode = isPresent(mode) ? mode : ProgressMode.DETERMINATE;
} }
get value() { get value() {
@ -54,14 +64,15 @@ export class MdProgressLinear {
onChange(_) { onChange(_) {
// If the mode does not use a value, or if there is no value, do nothing. // If the mode does not use a value, or if there is no value, do nothing.
if (this.mode == Mode['QUERY'] || this.mode == Mode['INDETERMINATE'] || isBlank(this.value)) { if (this.mode == ProgressMode.QUERY || this.mode == ProgressMode.INDETERMINATE ||
isBlank(this.value)) {
return; return;
} }
this.primaryBarTransform = this.transformForValue(this.value); this.primaryBarTransform = this.transformForValue(this.value);
// The bufferValue is only used in buffer mode. // The bufferValue is only used in buffer mode.
if (this.mode == Mode['BUFFER']) { if (this.mode == ProgressMode.BUFFER) {
this.secondaryBarTransform = this.transformForValue(this.bufferValue); this.secondaryBarTransform = this.transformForValue(this.bufferValue);
} }
} }
@ -69,8 +80,8 @@ export class MdProgressLinear {
/** Gets the CSS `transform` property for a progress bar based on the given value (0 - 100). */ /** Gets the CSS `transform` property for a progress bar based on the given value (0 - 100). */
transformForValue(value) { transformForValue(value) {
// TODO(jelbourn): test perf gain of caching these, since there are only 101 values. // TODO(jelbourn): test perf gain of caching these, since there are only 101 values.
var scale = value / 100; let scale = value / 100;
var translateX = (value - 100) / 2; let translateX = (value - 100) / 2;
return `translateX(${translateX}%) scale(${scale}, 1)`; return `translateX(${translateX}%) scale(${scale}, 1)`;
} }
@ -79,11 +90,3 @@ export class MdProgressLinear {
return Math.max(0, Math.min(100, v)); return Math.max(0, Math.min(100, v));
} }
} }
/** @enum {string} Progress-linear modes. */
var Mode = {
'DETERMINATE': 'determinate',
'INDETERMINATE': 'indeterminate',
'BUFFER': 'buffer',
'QUERY': 'query'
};

View File

@ -15,7 +15,7 @@ import {ListWrapper} from 'angular2/src/facade/collection';
import {Event, KeyboardEvent} from 'angular2/src/facade/browser'; import {Event, KeyboardEvent} from 'angular2/src/facade/browser';
import {MdRadioDispatcher} from 'angular2_material/src/components/radio/radio_dispatcher'; import {MdRadioDispatcher} from 'angular2_material/src/components/radio/radio_dispatcher';
import {KEY_UP, KEY_DOWN, KEY_SPACE} from 'angular2_material/src/core/constants'; import {KeyCodes} from 'angular2_material/src/core/key_codes';
// TODO(jelbourn): Behaviors to test // TODO(jelbourn): Behaviors to test
// Disabled radio don't select // Disabled radio don't select
@ -37,12 +37,12 @@ var _uniqueIdCounter: number = 0;
events: ['change'], events: ['change'],
properties: ['disabled', 'value'], properties: ['disabled', 'value'],
host: { host: {
'role': 'radiogroup',
'[attr.aria-disabled]': 'disabled',
'[attr.aria-activedescendant]': 'activedescendant',
// TODO(jelbourn): Remove ^ when event retargeting is fixed. // TODO(jelbourn): Remove ^ when event retargeting is fixed.
'(^keydown)': 'onKeydown($event)', '(^keydown)': 'onKeydown($event)',
'[tabindex]': 'tabindex', '[tabindex]': 'tabindex',
'[attr.role]': '"radiogroup"',
'[attr.aria-disabled]': 'disabled',
'[attr.aria-activedescendant]': 'activedescendant'
} }
}) })
@View({ @View({
@ -141,11 +141,11 @@ export class MdRadioGroup {
} }
switch (event.keyCode) { switch (event.keyCode) {
case KEY_UP: case KeyCodes.UP:
this.stepSelectedRadio(-1); this.stepSelectedRadio(-1);
event.preventDefault(); event.preventDefault();
break; break;
case KEY_DOWN: case KeyCodes.DOWN:
this.stepSelectedRadio(1); this.stepSelectedRadio(1);
event.preventDefault(); event.preventDefault();
break; break;
@ -154,7 +154,7 @@ export class MdRadioGroup {
// TODO(jelbourn): Replace this with a findIndex method in the collections facade. // TODO(jelbourn): Replace this with a findIndex method in the collections facade.
getSelectedRadioIndex(): number { getSelectedRadioIndex(): number {
for (var i = 0; i < this.radios_.length; i++) { for (let i = 0; i < this.radios_.length; i++) {
if (this.radios_[i].id == this.selectedRadioId) { if (this.radios_[i].id == this.selectedRadioId) {
return i; return i;
} }
@ -165,12 +165,12 @@ export class MdRadioGroup {
/** Steps the selected radio based on the given step value (usually either +1 or -1). */ /** Steps the selected radio based on the given step value (usually either +1 or -1). */
stepSelectedRadio(step) { stepSelectedRadio(step) {
var index = this.getSelectedRadioIndex() + step; let index = this.getSelectedRadioIndex() + step;
if (index < 0 || index >= this.radios_.length) { if (index < 0 || index >= this.radios_.length) {
return; return;
} }
var radio = this.radios_[index]; let radio = this.radios_[index];
// If the next radio is line is disabled, skip it (maintaining direction). // If the next radio is line is disabled, skip it (maintaining direction).
if (radio.disabled) { if (radio.disabled) {
@ -191,15 +191,15 @@ export class MdRadioGroup {
@Component({ @Component({
selector: 'md-radio-button', selector: 'md-radio-button',
lifecycle: [LifecycleEvent.onChange], lifecycle: [LifecycleEvent.onInit],
properties: ['id', 'name', 'value', 'checked', 'disabled'], properties: ['id', 'name', 'value', 'checked', 'disabled'],
host: { host: {
'(keydown)': 'onKeydown($event)', 'role': 'radio',
'[id]': 'id', '[id]': 'id',
'[tabindex]': 'tabindex', '[tabindex]': 'tabindex',
'[attr.role]': 'role',
'[attr.aria-checked]': 'checked', '[attr.aria-checked]': 'checked',
'[attr.aria-disabled]': 'disabled' '[attr.aria-disabled]': 'disabled',
'(keydown)': 'onKeydown($event)',
} }
}) })
@View({ @View({
@ -231,8 +231,6 @@ export class MdRadioButton {
tabindex: number; tabindex: number;
role: string;
constructor(@Optional() @SkipSelf() @Host() radioGroup: MdRadioGroup, @Attribute('id') id: string, constructor(@Optional() @SkipSelf() @Host() radioGroup: MdRadioGroup, @Attribute('id') id: string,
@Attribute('tabindex') tabindex: string, radioDispatcher: MdRadioDispatcher) { @Attribute('tabindex') tabindex: string, radioDispatcher: MdRadioDispatcher) {
// Assertions. Ideally these should be stripped out by the compiler. // Assertions. Ideally these should be stripped out by the compiler.
@ -241,8 +239,6 @@ export class MdRadioButton {
this.radioGroup = radioGroup; this.radioGroup = radioGroup;
this.radioDispatcher = radioDispatcher; this.radioDispatcher = radioDispatcher;
this.value = null; this.value = null;
this.role = 'radio';
this.checked = false; this.checked = false;
this.id = isPresent(id) ? id : `md-radio-${_uniqueIdCounter++}`; this.id = isPresent(id) ? id : `md-radio-${_uniqueIdCounter++}`;
@ -269,7 +265,7 @@ export class MdRadioButton {
} }
/** Change handler invoked when bindings are resolved or when bindings have changed. */ /** Change handler invoked when bindings are resolved or when bindings have changed. */
onChange(_) { onInit() {
if (isPresent(this.radioGroup)) { if (isPresent(this.radioGroup)) {
this.name = this.radioGroup.getName(); this.name = this.radioGroup.getName();
} }
@ -311,7 +307,7 @@ export class MdRadioButton {
/** Handles pressing the space key to select this focused radio button. */ /** Handles pressing the space key to select this focused radio button. */
onKeydown(event: KeyboardEvent) { onKeydown(event: KeyboardEvent) {
if (event.keyCode == KEY_SPACE) { if (event.keyCode == KeyCodes.SPACE) {
event.preventDefault(); event.preventDefault();
this.select(event); this.select(event);
} }

View File

@ -14,7 +14,7 @@ export class MdRadioDispatcher {
/** Notify other nadio buttons that selection for the given name has been set. */ /** Notify other nadio buttons that selection for the given name has been set. */
notify(name: string) { notify(name: string) {
ListWrapper.forEach(this.listeners_, (f) => f(name)); this.listeners_.forEach(listener => listener(name));
} }
/** Listen for future changes to radio button selection. */ /** Listen for future changes to radio button selection. */

View File

@ -1,19 +1,17 @@
import {Component, View, ViewEncapsulation, Attribute} from 'angular2/angular2'; import {Component, View, ViewEncapsulation, Attribute} from 'angular2/angular2';
import {isPresent} from 'angular2/src/facade/lang'; import {MdCheckbox} from "../checkbox/checkbox";
import {KEY_SPACE} from 'angular2_material/src/core/constants';
import {KeyboardEvent} from 'angular2/src/facade/browser';
import {NumberWrapper} from 'angular2/src/facade/lang';
// TODO(jelbourn): without gesture support, this is identical to MdCheckbox. // TODO(jelbourn): add gesture support
// TODO(jelbourn): clean up CSS.
@Component({ @Component({
selector: 'md-switch', selector: 'md-switch',
properties: ['checked', 'disabled'], properties: ['checked', 'disabled'],
host: { host: {
'(keydown)': 'onKeydown($event)', 'role': 'checkbox',
'[attr.aria-checked]': 'checked', '[attr.aria-checked]': 'checked',
'[attr.aria-disabled]': 'disabled_', '[attr.aria-disabled]': 'disabled_',
'[attr.role]': '"checkbox"' '(keydown)': 'onKeydown($event)',
} }
}) })
@View({ @View({
@ -21,41 +19,8 @@ import {NumberWrapper} from 'angular2/src/facade/lang';
directives: [], directives: [],
encapsulation: ViewEncapsulation.NONE encapsulation: ViewEncapsulation.NONE
}) })
export class MdSwitch { export class MdSwitch extends MdCheckbox {
/** Whether this switch is checked. */
checked: boolean;
/** Whether this switch is disabled. */
disabled_: boolean;
tabindex: number;
constructor(@Attribute('tabindex') tabindex: string) { constructor(@Attribute('tabindex') tabindex: string) {
this.checked = false; super(tabindex);
this.tabindex = isPresent(tabindex) ? NumberWrapper.parseInt(tabindex, 10) : 0;
}
get disabled() {
return this.disabled_;
}
set disabled(value) {
this.disabled_ = isPresent(value) && value !== false;
}
onKeydown(event: KeyboardEvent) {
if (event.keyCode === KEY_SPACE) {
event.preventDefault();
this.toggle(event);
}
}
toggle(event) {
if (this.disabled) {
event.stopPropagation();
return;
}
this.checked = !this.checked;
} }
} }

View File

@ -1,7 +0,0 @@
// TODO: switch to proper enums when we support them.
// Key codes
export const KEY_ESC = 27;
export const KEY_SPACE = 32;
export const KEY_UP = 38;
export const KEY_DOWN = 40;

View File

@ -0,0 +1,10 @@
import {CONST} from 'angular2/src/facade/lang';
// Can't use an enum because Dart doesn't support enum initializers.
@CONST()
export class KeyCodes {
@CONST() static ESCAPE = 27;
@CONST() static SPACE = 32;
@CONST() static UP = 38;
@CONST() static DOWN = 40;
}

View File

@ -1,10 +0,0 @@
import {Directive} from 'angular2/angular2';
@Directive({selector: '[md-theme]'})
export class MdTheme {
color: string;
constructor() {
this.color = 'sky-blue'
}
}

View File

@ -1,11 +1,17 @@
import {bootstrap, Component, View, NgFor} from 'angular2/bootstrap'; import {bootstrap, Component, View, NgFor, ViewEncapsulation} from 'angular2/bootstrap';
import {MdButton, MdAnchor} from 'angular2_material/src/components/button/button'; import {MdButton, MdAnchor} from 'angular2_material/src/components/button/button';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app'}) @Component({
@View({templateUrl: './demo_app.html', directives: [MdButton, MdAnchor, NgFor]}) selector: 'demo-app',
})
@View({
templateUrl: './demo_app.html',
directives: [MdButton, MdAnchor, NgFor],
encapsulation: ViewEncapsulation.NONE
})
class DemoApp { class DemoApp {
previousClick: string; previousClick: string;
action: string; action: string;

View File

@ -1,11 +1,17 @@
import {bootstrap, Component, Directive, View} from 'angular2/bootstrap'; import {bootstrap, Component, Directive, View, ViewEncapsulation} from 'angular2/bootstrap';
import {MdCheckbox} from 'angular2_material/src/components/checkbox/checkbox'; import {MdCheckbox} from 'angular2_material/src/components/checkbox/checkbox';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app'}) @Component({
@View({templateUrl: './demo_app.html', directives: [MdCheckbox]}) selector: 'demo-app',
})
@View({
templateUrl: './demo_app.html',
directives: [MdCheckbox],
encapsulation: ViewEncapsulation.NONE
})
class DemoApp { class DemoApp {
toggleCount: number; toggleCount: number;

View File

@ -1,4 +1,11 @@
import {bootstrap, ElementRef, ComponentRef, Component, View} from 'angular2/bootstrap'; import {
bootstrap,
ElementRef,
ComponentRef,
Component,
View,
ViewEncapsulation
} from 'angular2/bootstrap';
import { import {
MdDialog, MdDialog,
MdDialogRef, MdDialogRef,
@ -17,6 +24,7 @@ import {isPresent} from 'angular2/src/facade/lang';
@View({ @View({
templateUrl: './demo_app.html', templateUrl: './demo_app.html',
directives: [], directives: [],
encapsulation: ViewEncapsulation.NONE,
}) })
class DemoApp { class DemoApp {
dialog: MdDialog; dialog: MdDialog;
@ -62,6 +70,7 @@ class DemoApp {
properties: ['numCoconuts'], properties: ['numCoconuts'],
}) })
@View({ @View({
encapsulation: ViewEncapsulation.NONE,
template: ` template: `
<h2>This is the dialog content</h2> <h2>This is the dialog content</h2>
<p>There are {{numCoconuts}} coconuts.</p> <p>There are {{numCoconuts}} coconuts.</p>

View File

@ -1,11 +1,17 @@
import {bootstrap, Component, View} from 'angular2/bootstrap'; import {bootstrap, Component, View, ViewEncapsulation} from 'angular2/bootstrap';
import {MdGridList, MdGridTile} from 'angular2_material/src/components/grid_list/grid_list'; import {MdGridList, MdGridTile} from 'angular2_material/src/components/grid_list/grid_list';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app'}) @Component({
@View({templateUrl: './demo_app.html', directives: [MdGridList, MdGridTile]}) selector: 'demo-app',
})
@View({
templateUrl: './demo_app.html',
directives: [MdGridList, MdGridTile],
encapsulation: ViewEncapsulation.NONE,
})
class DemoApp { class DemoApp {
tile3RowSpan: number; tile3RowSpan: number;
tile3ColSpan: number; tile3ColSpan: number;

View File

@ -1,11 +1,15 @@
import {bootstrap, Component, View} from 'angular2/bootstrap'; import {bootstrap, Component, View, ViewEncapsulation} from 'angular2/bootstrap';
import {MdInputContainer, MdInput} from 'angular2_material/src/components/input/input'; import {MdInputContainer, MdInput} from 'angular2_material/src/components/input/input';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app'}) @Component({selector: 'demo-app'})
@View({templateUrl: './demo_app.html', directives: [MdInputContainer, MdInput]}) @View({
templateUrl: './demo_app.html',
directives: [MdInputContainer, MdInput],
encapsulation: ViewEncapsulation.NONE
})
class DemoApp { class DemoApp {
constructor() {} constructor() {}
} }

View File

@ -1,36 +1,34 @@
<link>
<div style="width: 500px;"> <div style="width: 500px;">
<h2>Progress-linear demo</h2> <h2>Progress-linear demo</h2>
<p> <p>
Determinate: primary Determinate: primary
<md-progress-linear md-mode="determinate" [value]="progress" class="md-accent"> <md-progress-linear mode="determinate" [value]="progress" class="md-accent">
</md-progress-linear> </md-progress-linear>
</p> </p>
<p> <p>
Determinate: accent Determinate: accent
<md-progress-linear md-mode="determinate" [value]="progress" class="md-primary"> <md-progress-linear mode="determinate" [value]="progress" class="md-primary">
</md-progress-linear> </md-progress-linear>
</p> </p>
<p> <p>
Buffer Buffer
<md-progress-linear md-mode="buffer" <md-progress-linear mode="buffer"
[value]="progress" [buffer-value]="progress + (200 / progress)" class="md-warn"> [value]="progress" [buffer-value]="progress + (200 / progress)" class="md-warn">
</md-progress-linear> </md-progress-linear>
</p> </p>
<p> <p>
Indeterminate Indeterminate
<md-progress-linear md-mode="indeterminate" class="md-primary"> <md-progress-linear mode="indeterminate" class="md-primary">
</md-progress-linear> </md-progress-linear>
</p> </p>
<p> <p>
Query Query
<md-progress-linear md-mode="query" class="md-accent"> <md-progress-linear mode="query" class="md-accent">
</md-progress-linear> </md-progress-linear>
</p> </p>

View File

@ -1,11 +1,17 @@
import {bootstrap, Component, View} from 'angular2/bootstrap'; import {bootstrap, Component, View, ViewEncapsulation} from 'angular2/bootstrap';
import {MdProgressLinear} from 'angular2_material/src/components/progress-linear/progress_linear'; import {MdProgressLinear} from 'angular2_material/src/components/progress-linear/progress_linear';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app'}) @Component({
@View({templateUrl: './demo_app.html', directives: [MdProgressLinear]}) selector: 'demo-app',
})
@View({
templateUrl: './demo_app.html',
directives: [MdProgressLinear],
encapsulation: ViewEncapsulation.NONE,
})
class DemoApp { class DemoApp {
progress: number; progress: number;

View File

@ -1,12 +1,19 @@
import {bootstrap, Component, View} from 'angular2/bootstrap'; import {bootstrap, Component, View, ViewEncapsulation} from 'angular2/bootstrap';
import {MdRadioButton, MdRadioGroup} from 'angular2_material/src/components/radio/radio_button'; import {MdRadioButton, MdRadioGroup} from 'angular2_material/src/components/radio/radio_button';
import {MdRadioDispatcher} from 'angular2_material/src/components/radio/radio_dispatcher'; import {MdRadioDispatcher} from 'angular2_material/src/components/radio/radio_dispatcher';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app', viewBindings: [MdRadioDispatcher]}) @Component({
@View({templateUrl: './demo_app.html', directives: [MdRadioGroup, MdRadioButton]}) selector: 'demo-app',
viewBindings: [MdRadioDispatcher],
})
@View({
templateUrl: './demo_app.html',
directives: [MdRadioGroup, MdRadioButton],
encapsulation: ViewEncapsulation.NONE,
})
class DemoApp { class DemoApp {
thirdValue; thirdValue;
groupValueChangeCount; groupValueChangeCount;

View File

@ -1,11 +1,17 @@
import {bootstrap, Component, View} from 'angular2/bootstrap'; import {bootstrap, Component, View, ViewEncapsulation} from 'angular2/bootstrap';
import {MdSwitch} from 'angular2_material/src/components/switcher/switch'; import {MdSwitch} from 'angular2_material/src/components/switcher/switch';
import {UrlResolver} from 'angular2/src/services/url_resolver'; import {UrlResolver} from 'angular2/src/services/url_resolver';
import {commonDemoSetup, DemoUrlResolver} from '../demo_common'; import {commonDemoSetup, DemoUrlResolver} from '../demo_common';
import {bind} from 'angular2/di'; import {bind} from 'angular2/di';
@Component({selector: 'demo-app'}) @Component({
@View({templateUrl: './demo_app.html', directives: [MdSwitch]}) selector: 'demo-app',
})
@View({
templateUrl: './demo_app.html',
directives: [MdSwitch],
encapsulation: ViewEncapsulation.NONE,
})
class DemoApp { class DemoApp {
toggleCount: number; toggleCount: number;