Skip to content

Commit 5411bf7

Browse files
committed
clean up measurement logic
1 parent c516e52 commit 5411bf7

File tree

2 files changed

+14
-52
lines changed

2 files changed

+14
-52
lines changed

src/lib/select/select.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<div #trigger #origin="cdkOverlayOrigin" cdk-overlay-origin class="mat-select-trigger"
22
aria-hidden="true" (click)="toggle()">
33
<div class="mat-select-value">
4-
<div #measureFontSize class="mat-select-measure-font-size" aria-hidden="true"></div>
54
<ng-container *ngIf="empty">&nbsp;</ng-container>
65
<span class="mat-select-value-text" *ngIf="!empty" [ngSwitch]="!!customTrigger">
76
<span *ngSwitchDefault>{{ triggerValue }}</span>
@@ -20,7 +19,7 @@
2019
[origin]="origin"
2120
[open]="panelOpen"
2221
[positions]="_positions"
23-
[minWidth]="_triggerWidth"
22+
[minWidth]="_triggerRect?.width"
2423
[offsetY]="_offsetY"
2524
(backdropClick)="close()"
2625
(attach)="_onAttached()"

src/lib/select/select.ts

Lines changed: 13 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ import {SelectionModel} from '../core/selection/selection';
5555
import {getMdSelectDynamicMultipleError, getMdSelectNonArrayValueError} from './select-errors';
5656
import {CanDisable, mixinDisabled} from '../core/common-behaviors/disabled';
5757
import {MdOptgroup, MdOption, MdOptionSelectionChange} from '../core/option/index';
58-
import {Platform} from '@angular/cdk/platform';
5958
import {MdFormFieldControl} from '../form-field/index';
6059
import {Subject} from 'rxjs/Subject';
6160

@@ -95,13 +94,6 @@ export const SELECT_MULTIPLE_PANEL_PADDING_X = SELECT_PANEL_PADDING_X * 1.5 + 20
9594
*/
9695
export const SELECT_PANEL_VIEWPORT_PADDING = 8;
9796

98-
/**
99-
* Default minimum width of the trigger based on the CSS.
100-
* Used as a fallback for server-side rendering.
101-
* @docs-private
102-
*/
103-
const SELECT_TRIGGER_MIN_WIDTH = 112;
104-
10597
/** Injection token that determines the scroll handling while a select is open. */
10698
export const MD_SELECT_SCROLL_STRATEGY =
10799
new InjectionToken<() => ScrollStrategy>('md-select-scroll-strategy');
@@ -208,8 +200,8 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
208200
/** Tab index for the element. */
209201
private _tabIndex: number;
210202

211-
/** The cached height of the trigger element. */
212-
private _triggerHeight: number;
203+
/** The last measured value for the trigger's client bounding rect. */
204+
_triggerRect: ClientRect;
213205

214206
/** The aria-describedby attribute on the select for improved a11y. */
215207
_ariaDescribedby: string;
@@ -220,12 +212,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
220212
/** Deals with the selection logic. */
221213
_selectionModel: SelectionModel<MdOption>;
222214

223-
/**
224-
* The width of the trigger. Must be saved to set the min width of the overlay panel
225-
* and the width of the selected value.
226-
*/
227-
_triggerWidth: number;
228-
229215
/** Manages keyboard events for options in the panel. */
230216
_keyManager: FocusKeyManager<MdOption>;
231217

@@ -290,9 +276,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
290276
/** Trigger that opens the select. */
291277
@ViewChild('trigger') trigger: ElementRef;
292278

293-
/** Element used to measure the font-size of the trigger element. */
294-
@ViewChild('measureFontSize') _measureFontSizeEl: ElementRef;
295-
296279
/** Overlay pane containing the options. */
297280
@ViewChild(ConnectedOverlayDirective) overlayDir: ConnectedOverlayDirective;
298281

@@ -314,9 +297,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
314297
set placeholder(value: string) {
315298
this._placeholder = value;
316299
this.stateChanges.next();
317-
318-
// Must wait to record the trigger width to ensure placeholder width is included.
319-
Promise.resolve(null).then(() => this._setTriggerWidth());
320300
}
321301

322302
/** Whether the component is required. */
@@ -404,7 +384,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
404384
constructor(
405385
private _viewportRuler: ViewportRuler,
406386
private _changeDetectorRef: ChangeDetectorRef,
407-
private _platform: Platform,
408387
private _ngZone: NgZone,
409388
renderer: Renderer2,
410389
elementRef: ElementRef,
@@ -469,9 +448,10 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
469448
return;
470449
}
471450

472-
if (!this._triggerWidth) {
473-
this._setTriggerWidth();
474-
}
451+
this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();
452+
// Note: The computed font-size will be a string pixel value (e.g. "16px").
453+
// `parseInt` ignores the trailing 'px' and converts this to a number.
454+
this._triggerFontSize = parseInt(getComputedStyle(this.trigger.nativeElement)['font-size']);
475455

476456
this._calculateOverlayPosition();
477457
this._panelOpen = true;
@@ -572,17 +552,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
572552
return this._dir ? this._dir.value === 'rtl' : false;
573553
}
574554

575-
/**
576-
* Sets the width of the trigger element. This is necessary to match
577-
* the overlay width to the trigger width.
578-
*/
579-
private _setTriggerWidth(): void {
580-
this._triggerWidth = this._platform.isBrowser ? this._getTriggerRect().width :
581-
SELECT_TRIGGER_MIN_WIDTH;
582-
583-
this._changeDetectorRef.markForCheck();
584-
}
585-
586555
/** Handles the keyboard interactions of a closed select. */
587556
_handleClosedKeydown(event: KeyboardEvent): void {
588557
if (!this.disabled) {
@@ -746,10 +715,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
746715
this.stateChanges.next();
747716
}
748717

749-
private _getTriggerRect(): ClientRect {
750-
return this.trigger.nativeElement.getBoundingClientRect();
751-
}
752-
753718
/** Sets up a key manager to listen to keyboard events on the overlay panel. */
754719
private _initKeyManager() {
755720
this._keyManager = new FocusKeyManager<MdOption>(this.options).withTypeAhead();
@@ -895,9 +860,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
895860

896861
/** Calculates the scroll position and x- and y-offsets of the overlay panel. */
897862
private _calculateOverlayPosition(): void {
898-
this._triggerHeight = this.trigger.nativeElement.getBoundingClientRect().height;
899-
this._triggerFontSize = this._measureFontSizeEl.nativeElement.getBoundingClientRect().height;
900-
901863
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
902864

903865
const items = this._getItemCount();
@@ -1004,7 +966,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
1004966
private _calculateOverlayOffsetY(selectedIndex: number, scrollBuffer: number,
1005967
maxScroll: number): number {
1006968
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
1007-
const optionHeightAdjustment = (itemHeight - this._triggerHeight) / 2;
969+
const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;
1008970
const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);
1009971
let optionOffsetFromPanelTop: number;
1010972

@@ -1042,20 +1004,21 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
10421004
* If it will not fit, tries to adjust the scroll position and the associated
10431005
* y-offset so the panel can open fully on-screen. If it still won't fit,
10441006
* sets the offset back to 0 to allow the fallback position to take over.
1007+
*
1008+
* Note: This method
10451009
*/
10461010
private _checkOverlayWithinViewport(maxScroll: number): void {
10471011
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
10481012
const viewportRect = this._viewportRuler.getViewportRect();
1049-
const triggerRect = this._getTriggerRect();
10501013

1051-
const topSpaceAvailable = triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;
1014+
const topSpaceAvailable = this._triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;
10521015
const bottomSpaceAvailable =
1053-
viewportRect.height - triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;
1016+
viewportRect.height - this._triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;
10541017

10551018
const panelHeightTop = Math.abs(this._offsetY);
10561019
const totalPanelHeight =
10571020
Math.min(this._getItemCount() * itemHeight, SELECT_PANEL_MAX_HEIGHT);
1058-
const panelHeightBottom = totalPanelHeight - panelHeightTop - triggerRect.height;
1021+
const panelHeightBottom = totalPanelHeight - panelHeightTop - this._triggerRect.height;
10591022

10601023
if (panelHeightBottom > bottomSpaceAvailable) {
10611024
this._adjustPanelUp(panelHeightBottom, bottomSpaceAvailable);
@@ -1113,7 +1076,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
11131076
/** Sets the transform origin point based on the selected option. */
11141077
private _getOriginBasedOnOption(): string {
11151078
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
1116-
const optionHeightAdjustment = (itemHeight - this._triggerHeight) / 2;
1079+
const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;
11171080
const originY = Math.abs(this._offsetY) - optionHeightAdjustment + itemHeight / 2;
11181081
return `50% ${originY}px 0px`;
11191082
}

0 commit comments

Comments
 (0)