Skip to content

Commit d02495f

Browse files
committed
clean up measurement logic
1 parent 144c249 commit d02495f

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
@@ -60,7 +60,6 @@ import {
6060
} from './select-errors';
6161
import {CanDisable, mixinDisabled} from '../core/common-behaviors/disabled';
6262
import {MdOptgroup, MdOption, MdOptionSelectionChange} from '../core/option/index';
63-
import {Platform} from '@angular/cdk/platform';
6463
import {MdFormFieldControl} from '../form-field/index';
6564
import {Subject} from 'rxjs/Subject';
6665

@@ -100,13 +99,6 @@ export const SELECT_MULTIPLE_PANEL_PADDING_X = SELECT_PANEL_PADDING_X * 1.5 + 20
10099
*/
101100
export const SELECT_PANEL_VIEWPORT_PADDING = 8;
102101

103-
/**
104-
* Default minimum width of the trigger based on the CSS.
105-
* Used as a fallback for server-side rendering.
106-
* @docs-private
107-
*/
108-
const SELECT_TRIGGER_MIN_WIDTH = 112;
109-
110102
/** Injection token that determines the scroll handling while a select is open. */
111103
export const MD_SELECT_SCROLL_STRATEGY =
112104
new InjectionToken<() => ScrollStrategy>('md-select-scroll-strategy');
@@ -216,8 +208,8 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
216208
/** Tab index for the element. */
217209
private _tabIndex: number;
218210

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

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

231-
/**
232-
* The width of the trigger. Must be saved to set the min width of the overlay panel
233-
* and the width of the selected value.
234-
*/
235-
_triggerWidth: number;
236-
237223
/** Manages keyboard events for options in the panel. */
238224
_keyManager: FocusKeyManager<MdOption>;
239225

@@ -298,9 +284,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
298284
/** Trigger that opens the select. */
299285
@ViewChild('trigger') trigger: ElementRef;
300286

301-
/** Element used to measure the font-size of the trigger element. */
302-
@ViewChild('measureFontSize') _measureFontSizeEl: ElementRef;
303-
304287
/** Overlay pane containing the options. */
305288
@ViewChild(ConnectedOverlayDirective) overlayDir: ConnectedOverlayDirective;
306289

@@ -322,9 +305,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
322305
set placeholder(value: string) {
323306
this._placeholder = value;
324307
this.stateChanges.next();
325-
326-
// Must wait to record the trigger width to ensure placeholder width is included.
327-
Promise.resolve(null).then(() => this._setTriggerWidth());
328308
}
329309

330310
/** Whether the component is required. */
@@ -430,7 +410,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
430410
constructor(
431411
private _viewportRuler: ViewportRuler,
432412
private _changeDetectorRef: ChangeDetectorRef,
433-
private _platform: Platform,
434413
private _ngZone: NgZone,
435414
renderer: Renderer2,
436415
elementRef: ElementRef,
@@ -490,9 +469,10 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
490469
return;
491470
}
492471

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

497477
this._calculateOverlayPosition();
498478
this._panelOpen = true;
@@ -593,17 +573,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
593573
return this._dir ? this._dir.value === 'rtl' : false;
594574
}
595575

596-
/**
597-
* Sets the width of the trigger element. This is necessary to match
598-
* the overlay width to the trigger width.
599-
*/
600-
private _setTriggerWidth(): void {
601-
this._triggerWidth = this._platform.isBrowser ? this._getTriggerRect().width :
602-
SELECT_TRIGGER_MIN_WIDTH;
603-
604-
this._changeDetectorRef.markForCheck();
605-
}
606-
607576
/** Handles the keyboard interactions of a closed select. */
608577
_handleClosedKeydown(event: KeyboardEvent): void {
609578
if (!this.disabled) {
@@ -785,10 +754,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
785754
this.stateChanges.next();
786755
}
787756

788-
private _getTriggerRect(): ClientRect {
789-
return this.trigger.nativeElement.getBoundingClientRect();
790-
}
791-
792757
/** Sets up a key manager to listen to keyboard events on the overlay panel. */
793758
private _initKeyManager() {
794759
this._keyManager = new FocusKeyManager<MdOption>(this.options).withTypeAhead();
@@ -934,9 +899,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
934899

935900
/** Calculates the scroll position and x- and y-offsets of the overlay panel. */
936901
private _calculateOverlayPosition(): void {
937-
this._triggerHeight = this.trigger.nativeElement.getBoundingClientRect().height;
938-
this._triggerFontSize = this._measureFontSizeEl.nativeElement.getBoundingClientRect().height;
939-
940902
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
941903

942904
const items = this._getItemCount();
@@ -1043,7 +1005,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
10431005
private _calculateOverlayOffsetY(selectedIndex: number, scrollBuffer: number,
10441006
maxScroll: number): number {
10451007
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
1046-
const optionHeightAdjustment = (itemHeight - this._triggerHeight) / 2;
1008+
const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;
10471009
const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);
10481010
let optionOffsetFromPanelTop: number;
10491011

@@ -1081,20 +1043,21 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
10811043
* If it will not fit, tries to adjust the scroll position and the associated
10821044
* y-offset so the panel can open fully on-screen. If it still won't fit,
10831045
* sets the offset back to 0 to allow the fallback position to take over.
1046+
*
1047+
* Note: This method
10841048
*/
10851049
private _checkOverlayWithinViewport(maxScroll: number): void {
10861050
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
10871051
const viewportRect = this._viewportRuler.getViewportRect();
1088-
const triggerRect = this._getTriggerRect();
10891052

1090-
const topSpaceAvailable = triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;
1053+
const topSpaceAvailable = this._triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;
10911054
const bottomSpaceAvailable =
1092-
viewportRect.height - triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;
1055+
viewportRect.height - this._triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;
10931056

10941057
const panelHeightTop = Math.abs(this._offsetY);
10951058
const totalPanelHeight =
10961059
Math.min(this._getItemCount() * itemHeight, SELECT_PANEL_MAX_HEIGHT);
1097-
const panelHeightBottom = totalPanelHeight - panelHeightTop - triggerRect.height;
1060+
const panelHeightBottom = totalPanelHeight - panelHeightTop - this._triggerRect.height;
10981061

10991062
if (panelHeightBottom > bottomSpaceAvailable) {
11001063
this._adjustPanelUp(panelHeightBottom, bottomSpaceAvailable);
@@ -1152,7 +1115,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
11521115
/** Sets the transform origin point based on the selected option. */
11531116
private _getOriginBasedOnOption(): string {
11541117
const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;
1155-
const optionHeightAdjustment = (itemHeight - this._triggerHeight) / 2;
1118+
const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;
11561119
const originY = Math.abs(this._offsetY) - optionHeightAdjustment + itemHeight / 2;
11571120
return `50% ${originY}px 0px`;
11581121
}

0 commit comments

Comments
 (0)