Skip to content

Commit

Permalink
Fix possibly mis-measured text width in DatePicker (palantir#320)
Browse files Browse the repository at this point in the history
* Add containerElement to measureTextWidth function signature

* Create a ref handler for the container element, and pass the element in
  • Loading branch information
cmslewis authored and adidahiya committed Dec 7, 2016
1 parent a77d928 commit 82fda40
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/datetime/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
* Measure width of a string displayed with styles provided by `className`.
* Should only be used if measuring can't be done with existing DOM elements.
*/
export function measureTextWidth(text: string, className = "") {
export function measureTextWidth(text: string, className = "", containerElement = document.body) {
const span = document.createElement("span");
span.classList.add(className);
span.innerHTML = text;

document.body.appendChild(span);
containerElement.appendChild(span);
const spanWidth = span.offsetWidth;
span.remove();

Expand Down
25 changes: 16 additions & 9 deletions packages/datetime/src/datePickerCaption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ export class DatePickerCaption extends React.Component<IDatePickerCaptionProps,
private displayedMonthText: string;
private displayedYearText: string;

private monthArrow: HTMLElement;
private yearArrow: HTMLElement;
private containerElement: HTMLElement;
private monthArrowElement: HTMLElement;
private yearArrowElement: HTMLElement;

public render() {
const { date, locale, localeUtils, minDate, maxDate } = this.props;
Expand Down Expand Up @@ -62,7 +63,10 @@ export class DatePickerCaption extends React.Component<IDatePickerCaptionProps,

const caretClasses = classNames("pt-icon-standard", "pt-icon-caret-down", Classes.DATEPICKER_CAPTION_CARET);
return (
<div className={Classes.DATEPICKER_CAPTION}>
<div
className={Classes.DATEPICKER_CAPTION}
ref={this.containerRefHandler}
>
<div className={Classes.DATEPICKER_CAPTION_SELECT}>
<select
className={Classes.DATEPICKER_MONTH_SELECT}
Expand Down Expand Up @@ -101,16 +105,19 @@ export class DatePickerCaption extends React.Component<IDatePickerCaptionProps,
this.positionArrows();
}

private monthArrowRefHandler = (r: HTMLElement) => this.monthArrow = r;
private yearArrowRefHandler = (r: HTMLElement) => this.yearArrow = r;
private containerRefHandler = (r: HTMLElement) => this.containerElement = r;
private monthArrowRefHandler = (r: HTMLElement) => this.monthArrowElement = r;
private yearArrowRefHandler = (r: HTMLElement) => this.yearArrowElement = r;

private positionArrows() {
// pass our container element to the measureTextWidth utility to ensure
// that we're measuring the width of text as sized within this component.
const textClass = "pt-datepicker-caption-measure";
const monthWidth = Utils.measureTextWidth(this.displayedMonthText, textClass);
this.monthArrow.setAttribute("style", `left:${monthWidth}`);
const monthWidth = Utils.measureTextWidth(this.displayedMonthText, textClass, this.containerElement);
this.monthArrowElement.setAttribute("style", `left:${monthWidth}`);

const yearWidth = Utils.measureTextWidth(this.displayedYearText, textClass);
this.yearArrow.setAttribute("style", `left:${yearWidth}`);
const yearWidth = Utils.measureTextWidth(this.displayedYearText, textClass, this.containerElement);
this.yearArrowElement.setAttribute("style", `left:${yearWidth}`);
}

private handleMonthSelectChange = (e: React.FormEvent<HTMLSelectElement>) => {
Expand Down

0 comments on commit 82fda40

Please sign in to comment.