Skip to content

Commit

Permalink
Mvenkov/dropdown scroll fix (#3546)
Browse files Browse the repository at this point in the history
* fix(igxOverlay): restore correctly element original style, #3527

* chore(igxOverlay): onPosition added, WIP

* fix(igxOverlay): set element scrollTop is setTimeOut, #3527

Setting the scrollTop forces the dropdown's element to flicker. When we set it
just one ms latter animation has time to start and we prevent flickering.

* chore(igxOverla): remove bug fix leftovers

* chore(igxOverlay): use time out only for IE

* fix(igxOverlay): fix elastic pos. + absolute scroll, #3527
  • Loading branch information
wnvko authored and rkaraivanov committed Jan 14, 2019
1 parent fa9379b commit d720e4f
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 24 deletions.
15 changes: 13 additions & 2 deletions projects/igniteui-angular/src/lib/drop-down/drop-down.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
QueryList, ViewChild, Output, EventEmitter, ChangeDetectorRef
} from '@angular/core';

import { CancelableEventArgs } from '../core/utils';
import { CancelableEventArgs, isIE } from '../core/utils';
import { IgxSelectionAPIService } from '../core/selection';
import { OverlaySettings } from '../services';
import { IToggleView } from '../core/navigation';
Expand Down Expand Up @@ -461,7 +461,18 @@ export abstract class IgxDropDownBase implements OnInit, IToggleView {
*/
protected scrollToItem(item: IgxDropDownItemBase) {
const itemPosition = this.calculateScrollPosition(item);
this.scrollContainer.scrollTop = (itemPosition);

// in IE11 setting sctrollTop is somehow slow and forces dropdown
// to appear on screen before animation start. As a result dropdown
// flickers badly. This is why we set scrollTop just a little later
// allowing animation to start and prevent dropdown flickering
if (isIE()) {
setTimeout(() => {
this.scrollContainer.scrollTop = (itemPosition);
}, 1);
} else {
this.scrollContainer.scrollTop = (itemPosition);
}
}

protected scrollToHiddenItem(newItem: IgxDropDownItemBase) {
Expand Down
19 changes: 16 additions & 3 deletions projects/igniteui-angular/src/lib/services/overlay/overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { AnimationBuilder, AnimationReferenceMetadata, AnimationMetadataType, An
import { fromEvent, Subject } from 'rxjs';
import { take, filter, takeUntil } from 'rxjs/operators';
import { IAnimationParams } from '../../animations/main';
import { ElasticPositionStrategy } from './position';

/**
* [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/overlay_main.html)
Expand Down Expand Up @@ -166,7 +167,10 @@ export class IgxOverlayService implements OnDestroy {
this.updateSize(info);
this._overlayInfos.push(info);

info.originalElementStyle = info.elementRef.nativeElement.style;
const elementStyle = info.elementRef.nativeElement.style;
if (settings.positionStrategy instanceof ElasticPositionStrategy) {
info.originalElementStyleSize = { width: elementStyle.width, height: elementStyle.height };
}
settings.positionStrategy.position(
info.elementRef.nativeElement.parentElement,
{ width: info.initialSize.width, height: info.initialSize.height },
Expand Down Expand Up @@ -260,7 +264,10 @@ export class IgxOverlayService implements OnDestroy {

overlayInfo.settings.positionStrategy.position(
overlayInfo.elementRef.nativeElement.parentElement,
{ width: overlayInfo.initialSize.width, height: overlayInfo.initialSize.height },
{
width: overlayInfo.elementRef.nativeElement.parentElement.clientWidth,
height: overlayInfo.elementRef.nativeElement.parentElement.clientHeight
},
this._document,
false,
overlayInfo.settings.positionStrategy.settings.minSize);
Expand Down Expand Up @@ -403,7 +410,13 @@ export class IgxOverlayService implements OnDestroy {
this._overlayElement.parentElement.removeChild(this._overlayElement);
this._overlayElement = null;
}
info.elementRef.nativeElement.style = info.originalElementStyle;

// restore the element's original width and height if any
if (info.originalElementStyleSize) {
info.elementRef.nativeElement.style.height = info.originalElementStyleSize.height;
info.elementRef.nativeElement.style.width = info.originalElementStyleSize.width;
}

this.onClosed.emit({ id: info.id, componentRef: info.componentRef });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,52 @@ import { Size, HorizontalAlignment, VerticalAlignment, PositionSettings } from '

export class ElasticPositionStrategy extends BaseFitPositionStrategy implements IPositionStrategy {
fitHorizontal(element: HTMLElement, settings: PositionSettings, innerRect: ClientRect, outerRect: ClientRect, minSize: Size) {
let extend = 0;
switch (settings.horizontalDirection) {
case HorizontalAlignment.Left: {
let extend = outerRect.left - innerRect.left;
extend = outerRect.left - innerRect.left;
if (extend > innerRect.width - minSize.width) {
extend = innerRect.width - minSize.width;
}
const translateX = `translateX(${innerRect.left + extend}px)`;
element.style.transform = element.style.transform.replace(/translateX\([.-\d]+px\)/g, translateX);
(<any>element.firstChild).style.width = `${innerRect.width - extend}px`;
break;
}
case HorizontalAlignment.Right: {
let extend = innerRect.right - outerRect.right;
extend = innerRect.right - outerRect.right;
if (extend > innerRect.width - minSize.width) {
extend = innerRect.width - minSize.width;
}

(<any>element.firstChild).style.width = `${innerRect.width - extend}px`;
break;
}
}

element.style.width = `${innerRect.width - extend}px`;
(<any>element.firstChild).style.width = `${innerRect.width - extend}px`;
}

fitVertical(element: HTMLElement, settings: PositionSettings, innerRect: ClientRect, outerRect: ClientRect, minSize: Size) {
let extend = 0;
switch (settings.verticalDirection) {
case VerticalAlignment.Top: {
let extend = outerRect.top - innerRect.top;
extend = outerRect.top - innerRect.top;
if (extend > innerRect.height - minSize.height) {
extend = innerRect.height - minSize.height;
}
const translateY = `translateY(${innerRect.top + extend}px)`;
element.style.transform = element.style.transform.replace(/translateY\([.-\d]+px\)/g, translateY);
(<any>element.firstChild).style.height = `${innerRect.width - extend}px`;
break;
}
case VerticalAlignment.Bottom: {
let extend = innerRect.bottom - outerRect.bottom;
extend = innerRect.bottom - outerRect.bottom;
if (extend > innerRect.height - minSize.height) {
extend = innerRect.height - minSize.height;
}

(<any>element.firstChild).style.height = `${innerRect.height - extend}px`;
break;
}
}

element.style.height = `${innerRect.height - extend}px`;
(<any>element.firstChild).style.height = `${innerRect.height - extend}px`;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,5 @@ export interface OverlayInfo {
closeAnimationPlayer?: AnimationPlayer;
openAnimationInnerPlayer?: any;
closeAnimationInnerPlayer?: any;
originalElementStyle?: string;
originalElementStyleSize?: Size;
}
2 changes: 1 addition & 1 deletion src/app/overlay/overlay.sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
</div>
<button #button igxButton="raised" igxRipple (click)="toggleDropDown()" [style.position]="'absolute'" [style.top]="buttonTop + '%'"
[style.left]="buttonLeft + '%'">Toggle</button>
<igx-drop-down>
<igx-drop-down height="200px" width="200px">
<igx-drop-down-item *ngFor="let item of items">
<div class="igx-drop-down__item-template">
{{ item }}
Expand Down
14 changes: 7 additions & 7 deletions src/app/overlay/overlay.sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export class OverlaySampleComponent {
modal: true,
closeOnOutsideClick: true
};
items = [
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5'
];
constructor() {
for (let item = 0; item < 100; item++) {
this.items.push(`Item ${item}`);
}
}

items = [];

buttonLeft = 90;
buttonTop = 35;
Expand Down

0 comments on commit d720e4f

Please sign in to comment.