Skip to content

Commit

Permalink
clean up measurement logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Aug 21, 2017
1 parent 144c249 commit d02495f
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 52 deletions.
3 changes: 1 addition & 2 deletions src/lib/select/select.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<div #trigger #origin="cdkOverlayOrigin" cdk-overlay-origin class="mat-select-trigger"
aria-hidden="true" (click)="toggle()">
<div class="mat-select-value">
<div #measureFontSize class="mat-select-measure-font-size" aria-hidden="true"></div>
<ng-container *ngIf="empty">&nbsp;</ng-container>
<span class="mat-select-value-text" *ngIf="!empty" [ngSwitch]="!!customTrigger">
<span *ngSwitchDefault>{{ triggerValue }}</span>
Expand All @@ -20,7 +19,7 @@
[origin]="origin"
[open]="panelOpen"
[positions]="_positions"
[minWidth]="_triggerWidth"
[minWidth]="_triggerRect?.width"
[offsetY]="_offsetY"
(backdropClick)="close()"
(attach)="_onAttached()"
Expand Down
63 changes: 13 additions & 50 deletions src/lib/select/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import {
} from './select-errors';
import {CanDisable, mixinDisabled} from '../core/common-behaviors/disabled';
import {MdOptgroup, MdOption, MdOptionSelectionChange} from '../core/option/index';
import {Platform} from '@angular/cdk/platform';
import {MdFormFieldControl} from '../form-field/index';
import {Subject} from 'rxjs/Subject';

Expand Down Expand Up @@ -100,13 +99,6 @@ export const SELECT_MULTIPLE_PANEL_PADDING_X = SELECT_PANEL_PADDING_X * 1.5 + 20
*/
export const SELECT_PANEL_VIEWPORT_PADDING = 8;

/**
* Default minimum width of the trigger based on the CSS.
* Used as a fallback for server-side rendering.
* @docs-private
*/
const SELECT_TRIGGER_MIN_WIDTH = 112;

/** Injection token that determines the scroll handling while a select is open. */
export const MD_SELECT_SCROLL_STRATEGY =
new InjectionToken<() => ScrollStrategy>('md-select-scroll-strategy');
Expand Down Expand Up @@ -216,8 +208,8 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
/** Tab index for the element. */
private _tabIndex: number;

/** The cached height of the trigger element. */
private _triggerHeight: number;
/** The last measured value for the trigger's client bounding rect. */
_triggerRect: ClientRect;

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

/**
* The width of the trigger. Must be saved to set the min width of the overlay panel
* and the width of the selected value.
*/
_triggerWidth: number;

/** Manages keyboard events for options in the panel. */
_keyManager: FocusKeyManager<MdOption>;

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

/** Element used to measure the font-size of the trigger element. */
@ViewChild('measureFontSize') _measureFontSizeEl: ElementRef;

/** Overlay pane containing the options. */
@ViewChild(ConnectedOverlayDirective) overlayDir: ConnectedOverlayDirective;

Expand All @@ -322,9 +305,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
set placeholder(value: string) {
this._placeholder = value;
this.stateChanges.next();

// Must wait to record the trigger width to ensure placeholder width is included.
Promise.resolve(null).then(() => this._setTriggerWidth());
}

/** Whether the component is required. */
Expand Down Expand Up @@ -430,7 +410,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
constructor(
private _viewportRuler: ViewportRuler,
private _changeDetectorRef: ChangeDetectorRef,
private _platform: Platform,
private _ngZone: NgZone,
renderer: Renderer2,
elementRef: ElementRef,
Expand Down Expand Up @@ -490,9 +469,10 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
return;
}

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

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

/**
* Sets the width of the trigger element. This is necessary to match
* the overlay width to the trigger width.
*/
private _setTriggerWidth(): void {
this._triggerWidth = this._platform.isBrowser ? this._getTriggerRect().width :
SELECT_TRIGGER_MIN_WIDTH;

this._changeDetectorRef.markForCheck();
}

/** Handles the keyboard interactions of a closed select. */
_handleClosedKeydown(event: KeyboardEvent): void {
if (!this.disabled) {
Expand Down Expand Up @@ -785,10 +754,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
this.stateChanges.next();
}

private _getTriggerRect(): ClientRect {
return this.trigger.nativeElement.getBoundingClientRect();
}

/** Sets up a key manager to listen to keyboard events on the overlay panel. */
private _initKeyManager() {
this._keyManager = new FocusKeyManager<MdOption>(this.options).withTypeAhead();
Expand Down Expand Up @@ -934,9 +899,6 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On

/** Calculates the scroll position and x- and y-offsets of the overlay panel. */
private _calculateOverlayPosition(): void {
this._triggerHeight = this.trigger.nativeElement.getBoundingClientRect().height;
this._triggerFontSize = this._measureFontSizeEl.nativeElement.getBoundingClientRect().height;

const itemHeight = this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;

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

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

const topSpaceAvailable = triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;
const topSpaceAvailable = this._triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;
const bottomSpaceAvailable =
viewportRect.height - triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;
viewportRect.height - this._triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;

const panelHeightTop = Math.abs(this._offsetY);
const totalPanelHeight =
Math.min(this._getItemCount() * itemHeight, SELECT_PANEL_MAX_HEIGHT);
const panelHeightBottom = totalPanelHeight - panelHeightTop - triggerRect.height;
const panelHeightBottom = totalPanelHeight - panelHeightTop - this._triggerRect.height;

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

0 comments on commit d02495f

Please sign in to comment.