Skip to content

Commit 6ad4788

Browse files
committed
Merge branch 'master' into dialog-animation
# Conflicts: # src/lib/dialog/dialog-container.ts # src/lib/dialog/dialog-ref.ts # src/lib/dialog/dialog.spec.ts # src/lib/dialog/dialog.ts
2 parents b5faeec + 37e4bad commit 6ad4788

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+963
-948
lines changed

e2e/components/dialog/dialog.e2e.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ describe('dialog', () => {
3535
});
3636
});
3737

38+
it('should close by pressing escape when the first tabbable element has lost focus', () => {
39+
element(by.id('default')).click();
40+
41+
waitForDialog().then(() => {
42+
clickElementAtPoint('md-dialog-container', { x: 0, y: 0 });
43+
pressKeys(Key.ESCAPE);
44+
expectToExist('md-dialog-container', false);
45+
});
46+
});
47+
3848
it('should close by clicking on the "close" button', () => {
3949
element(by.id('default')).click();
4050

package.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,26 @@
2525
"node": ">= 5.4.1 < 7"
2626
},
2727
"dependencies": {
28-
"@angular/common": "^2.2.0",
29-
"@angular/compiler": "^2.2.0",
30-
"@angular/core": "^2.2.0",
31-
"@angular/forms": "^2.2.0",
32-
"@angular/http": "^2.2.0",
33-
"@angular/platform-browser": "^2.2.0",
28+
"@angular/common": "^2.3.0",
29+
"@angular/compiler": "^2.3.0",
30+
"@angular/core": "^2.3.0",
31+
"@angular/forms": "^2.3.0",
32+
"@angular/http": "^2.3.0",
33+
"@angular/platform-browser": "^2.3.0",
3434
"core-js": "^2.4.1",
35-
"rxjs": "5.0.0-beta.12",
35+
"rxjs": "^5.0.1",
3636
"systemjs": "0.19.43",
37-
"zone.js": "^0.6.23"
37+
"zone.js": "^0.7.2"
3838
},
3939
"devDependencies": {
40-
"@angular/compiler-cli": "^2.2.0",
41-
"@angular/platform-browser-dynamic": "^2.2.0",
42-
"@angular/platform-server": "^2.2.0",
43-
"@angular/router": "^3.2.0",
40+
"@angular/compiler-cli": "^2.3.0",
41+
"@angular/platform-browser-dynamic": "^2.3.0",
42+
"@angular/platform-server": "^2.3.0",
43+
"@angular/router": "^3.3.0",
4444
"@types/glob": "^5.0.30",
4545
"@types/gulp": "^3.8.32",
4646
"@types/hammerjs": "^2.0.34",
47-
"@types/jasmine": "^2.5.41",
47+
"@types/jasmine": "2.5.41",
4848
"@types/merge2": "^0.3.29",
4949
"@types/minimist": "^1.2.0",
5050
"@types/node": "^7.0.4",

scripts/release/publish-docs-content.sh

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ cd "$(dirname $0)/../../"
88
docsPath="/dist/docs"
99
repoPath="/tmp/material2-docs-content"
1010
repoUrl="https://github.com/DevVersion/material2-docs-content"
11+
examplesSource="/dist/docs/examples"
1112

1213
# If the docs directory is not present, generate docs
1314
if [ ! -d $docsPath ]; then
@@ -21,47 +22,46 @@ commitAuthorEmail="$(git --no-pager show -s --format='%ae' HEAD)"
2122
commitMessage="$(git log --oneline -n 1)"
2223

2324
# create directory and clone test repo
24-
rm -rf "/tmp/"
25-
mkdir "/tmp/" $repoPath
25+
rm -rf /tmp/
26+
mkdir -p $repoPath
2627
git clone $repoUrl $repoPath
2728

2829
# Clean out repo directory and copy contents of dist/docs into it
2930
rm -rf $repoPath/*
3031
mkdir $repoPath/overview
3132
mkdir $repoPath/guides
3233
mkdir $repoPath/api
33-
# mkdir $repoPath/examples
34+
mkdir $repoPath/examples
3435

3536
# Move api files over to $repoPath/api
3637
cp -r $docsPath/api/* $repoPath/api
3738

38-
# Move guide files over to $repoPath/guides
39-
for filename in $overviewFiles*
40-
do
41-
if [ -f $filename ]; then
42-
cp -r $filename $repoPath/guides
43-
fi
44-
done
45-
4639
# Flatten the markdown docs structure and move it into $repoPath/overview
4740
overviewFiles=$docsPath/markdown/
48-
targetFile="OVERVIEW.html"
4941
for filename in $overviewFiles*
5042
do
5143
if [ -d $filename ]; then
5244
for _ in $filename/*
5345
do
54-
if [ -f $filename/$targetFile ]; then
55-
name=${filename#$overviewFiles}
56-
cp -r $filename/$targetFile $repoPath/overview/
57-
mv $repoPath/overview/$targetFile $repoPath/overview/$name.html
46+
markdownFile=${filename#$overviewFiles}.html
47+
# Filename should be same as folder name with .html extension
48+
if [ -e $filename/$markdownFile ]; then
49+
cp -r $filename/$markdownFile $repoPath/overview/
5850
fi
5951
done
6052
fi
6153
done
6254

63-
# src/examples should be added to the $repoPath after they have been moved into
64-
# the material2 repo from material.angular.io
55+
# Move guide files over to $repoPath/guides
56+
for filename in $overviewFiles*
57+
do
58+
if [ -f $filename ]; then
59+
cp -r $filename $repoPath/guides
60+
fi
61+
done
62+
63+
# Move highlighted examples into $repoPath
64+
cp -r $examplesSource/* $repoPath/examples
6565

6666
# Push content to repo
6767
cd $repoPath

src/demo-app/ripple/ripple-demo.html

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,18 @@
2121
<section>
2222
Speed
2323
<md-radio-group [(ngModel)]="rippleSpeed">
24-
<md-radio-button name="demo-ripple-options" value="0.1">Slow</md-radio-button>
24+
<md-radio-button name="demo-ripple-options" value="0.4">Slow</md-radio-button>
2525
<md-radio-button name="demo-ripple-options" value="1">Normal</md-radio-button>
26-
<md-radio-button name="demo-ripple-options" value="4">Fast</md-radio-button>
26+
<md-radio-button name="demo-ripple-options" value="2.5">Fast</md-radio-button>
2727
</md-radio-group>
2828
</section>
2929
<section>
3030
<md-input-container>
31-
<input mdInput placeholder="Max radius" aria-label="radius" [(ngModel)]="maxRadius">
31+
<input mdInput placeholder="Ripple radius" aria-label="radius" [(ngModel)]="radius">
3232
</md-input-container>
3333
<md-input-container>
3434
<input mdInput placeholder="Ripple color" aria-label="color" [(ngModel)]="rippleColor">
3535
</md-input-container>
36-
<md-input-container>
37-
<input mdInput
38-
placeholder="Ripple background"
39-
aria-label="background"
40-
[(ngModel)]="rippleBackgroundColor">
41-
</md-input-container>
4236
</section>
4337
<section>
4438
<button md-raised-button (click)="doManualRipple()">Manual ripple</button>
@@ -51,9 +45,8 @@
5145
[mdRippleCentered]="centered"
5246
[mdRippleDisabled]="disabled"
5347
[mdRippleUnbounded]="unbounded"
54-
[mdRippleMaxRadius]="maxRadius"
48+
[mdRippleRadius]="radius"
5549
[mdRippleColor]="rippleColor"
56-
[mdRippleBackgroundColor]="rippleBackgroundColor"
5750
[mdRippleSpeedFactor]="rippleSpeed">
5851
Click me
5952
</div>

src/demo-app/ripple/ripple-demo.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,22 @@ import {MdRipple} from '@angular/material';
99
styleUrls: ['ripple-demo.css'],
1010
})
1111
export class RippleDemo {
12-
@ViewChild(MdRipple) manualRipple: MdRipple;
12+
@ViewChild(MdRipple) ripple: MdRipple;
1313

1414
centered = false;
1515
disabled = false;
1616
unbounded = false;
1717
rounded = false;
18-
maxRadius: number = null;
18+
radius: number = null;
1919
rippleSpeed = 1;
2020
rippleColor = '';
21-
rippleBackgroundColor = '';
2221

2322
disableButtonRipples = false;
2423

2524
doManualRipple() {
26-
if (this.manualRipple) {
27-
window.setTimeout(() => this.manualRipple.start(), 10);
28-
window.setTimeout(() => this.manualRipple.end(0, 0), 500);
25+
if (this.ripple) {
26+
this.ripple.launch(0, 0, { centered: true });
2927
}
3028
}
29+
3130
}

src/demo-app/style/style-demo.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<button (click)="b.focus()">focus programmatically</button>
33

44
<button (click)="fom.focusVia(b, renderer, 'mouse')">focusVia: mouse</button>
5+
<button (click)="fom.focusVia(b, renderer, 'touch')">focusVia: touch</button>
56
<button (click)="fom.focusVia(b, renderer, 'keyboard')">focusVia: keyboard</button>
67
<button (click)="fom.focusVia(b, renderer, 'program')">focusVia: program</button>
78

src/demo-app/style/style-demo.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@
1313
.demo-button.cdk-program-focused {
1414
background: blue;
1515
}
16+
17+
.demo-button.cdk-touch-focused {
18+
background: purple;
19+
}

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
NgZone,
99
Optional,
1010
OnDestroy,
11-
QueryList,
1211
ViewContainerRef,
1312
} from '@angular/core';
1413
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
@@ -23,7 +22,6 @@ import {ENTER, UP_ARROW, DOWN_ARROW} from '../core/keyboard/keycodes';
2322
import {Dir} from '../core/rtl/dir';
2423
import {Subscription} from 'rxjs/Subscription';
2524
import {Subject} from 'rxjs/Subject';
26-
import 'rxjs/add/observable/of';
2725
import 'rxjs/add/observable/merge';
2826
import 'rxjs/add/operator/startWith';
2927
import 'rxjs/add/operator/switchMap';
@@ -258,33 +256,20 @@ export class MdAutocompleteTrigger implements AfterContentInit, ControlValueAcce
258256
* stream every time the option list changes.
259257
*/
260258
private _subscribeToClosingActions(): void {
261-
const initialOptions = this._getStableOptions();
262-
263259
// When the zone is stable initially, and when the option list changes...
264-
Observable.merge(initialOptions, this.autocomplete.options.changes)
260+
Observable.merge(this._zone.onStable.first(), this.autocomplete.options.changes)
265261
// create a new stream of panelClosingActions, replacing any previous streams
266262
// that were created, and flatten it so our stream only emits closing events...
267-
.switchMap(options => {
263+
.switchMap(() => {
268264
this._resetPanel();
269-
// If the options list is empty, emit close event immediately.
270-
// Otherwise, listen for panel closing actions...
271-
return options.length ? this.panelClosingActions : Observable.of(null);
265+
return this.panelClosingActions;
272266
})
273267
// when the first closing event occurs...
274268
.first()
275269
// set the value, close the panel, and complete.
276270
.subscribe(event => this._setValueAndClose(event));
277271
}
278272

279-
/**
280-
* Retrieves the option list once the zone stabilizes. It's important to wait until
281-
* stable so that change detection can run first and update the query list
282-
* with the options available under the current filter.
283-
*/
284-
private _getStableOptions(): Observable<QueryList<MdOption>> {
285-
return this._zone.onStable.first().map(() => this.autocomplete.options);
286-
}
287-
288273
/** Destroys the autocomplete suggestion panel. */
289274
private _destroyPanel(): void {
290275
if (this._overlayRef) {
@@ -364,6 +349,7 @@ export class MdAutocompleteTrigger implements AfterContentInit, ControlValueAcce
364349
private _resetPanel() {
365350
this._resetActiveItem();
366351
this._positionStrategy.recalculateLastPosition();
352+
this.autocomplete._setVisibility();
367353
}
368354

369355
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="mat-autocomplete-panel" role="listbox" [id]="id" [ngClass]="_getPositionClass()" #panel>
2+
<div class="mat-autocomplete-panel" role="listbox" [id]="id" [ngClass]="_getClassList()" #panel>
33
<ng-content></ng-content>
44
</div>
55
</template>

src/lib/autocomplete/autocomplete.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ $mat-autocomplete-panel-above-offset: -24px !default;
1414

1515
.mat-autocomplete-panel {
1616
@include mat-menu-base();
17+
visibility: hidden;
1718

1819
max-height: $mat-autocomplete-panel-max-height;
1920
position: relative;
@@ -25,4 +26,12 @@ $mat-autocomplete-panel-above-offset: -24px !default;
2526
&.mat-autocomplete-panel-above {
2627
top: $mat-autocomplete-panel-above-offset;
2728
}
29+
30+
&.mat-autocomplete-visible {
31+
visibility: visible;
32+
}
33+
34+
&.mat-autocomplete-hidden {
35+
visibility: hidden;
36+
}
2837
}

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,30 @@ describe('MdAutocomplete', () => {
165165
.toEqual('', `Expected closing programmatically to close the panel.`);
166166
});
167167

168-
it('should close the panel when the options list is empty', async(() => {
168+
it('should hide the panel when the options list is empty', async(() => {
169169
dispatchEvent('focus', input);
170-
fixture.detectChanges();
171170

172171
fixture.whenStable().then(() => {
172+
fixture.detectChanges();
173+
174+
const panel =
175+
overlayContainerElement.querySelector('.mat-autocomplete-panel') as HTMLElement;
176+
expect(panel.classList)
177+
.toContain('mat-autocomplete-visible', `Expected panel to start out visible.`);
178+
173179
// Filter down the option list such that no options match the value
174180
input.value = 'af';
175181
dispatchEvent('input', input);
176182
fixture.detectChanges();
177183

178-
expect(fixture.componentInstance.trigger.panelOpen)
179-
.toBe(false, `Expected panel to close when options list is empty.`);
180-
expect(overlayContainerElement.textContent)
181-
.toEqual('', `Expected panel to close when options list is empty.`);
184+
fixture.whenStable().then(() => {
185+
fixture.detectChanges();
186+
187+
expect(fixture.componentInstance.trigger.panelOpen)
188+
.toBe(true, `Expected panel to stay open when options list is empty.`);
189+
expect(panel.classList)
190+
.toContain('mat-autocomplete-hidden', `Expected panel to hide itself when empty.`);
191+
});
182192
});
183193
}));
184194

src/lib/autocomplete/autocomplete.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export class MdAutocomplete {
3434
/** Whether the autocomplete panel displays above or below its trigger. */
3535
positionY: AutocompletePositionY = 'below';
3636

37+
/** Whether the autocomplete panel should be visible, depending on option length. */
38+
showPanel = false;
39+
3740
@ViewChild(TemplateRef) template: TemplateRef<any>;
3841
@ViewChild('panel') panel: ElementRef;
3942
@ContentChildren(MdOption) options: QueryList<MdOption>;
@@ -54,11 +57,18 @@ export class MdAutocomplete {
5457
}
5558
}
5659

60+
/** Panel should hide itself when the option list is empty. */
61+
_setVisibility() {
62+
Promise.resolve().then(() => this.showPanel = !!this.options.length);
63+
}
64+
5765
/** Sets a class on the panel based on its position (used to set y-offset). */
58-
_getPositionClass() {
66+
_getClassList() {
5967
return {
6068
'mat-autocomplete-panel-below': this.positionY === 'below',
61-
'mat-autocomplete-panel-above': this.positionY === 'above'
69+
'mat-autocomplete-panel-above': this.positionY === 'above',
70+
'mat-autocomplete-visible': this.showPanel,
71+
'mat-autocomplete-hidden': !this.showPanel
6272
};
6373
}
6474

src/lib/button-toggle/_button-toggle-theme.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,9 @@
1818
.mat-button-toggle-disabled {
1919
background-color: map_get($mat-grey, 200);
2020
color: mat-color($foreground, disabled-button);
21+
22+
&.mat-button-toggle-checked {
23+
background-color: mat-color($mat-grey, 400);
24+
}
2125
}
2226
}

0 commit comments

Comments
 (0)