Skip to content

Commit

Permalink
feat(overlay): add global container position strategy #5667
Browse files Browse the repository at this point in the history
  • Loading branch information
wnvko authored and Lipata committed Sep 3, 2019
1 parent 269d9c0 commit 117b450
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ For more information about the theming please read our [documentation](https://w
- Drop strategies. Three new drop strategies have been provided - Append, Prepend and Insert. Also an input `dropStrategy` to the `igxDrop` which specify which strategy should be used when dropping an element inside the drop area. Custom one can be specified as well.
- `IgxCheckbox`
- introduced a new `readonly` property that doesn't allow user interaction to change the state, but keeps the default active style. Intended for integration in complex controls that handle the interaction and control the checkbox instead through binding.
- `IgxOverlay`
- introduced a new `ContainerPositionStrategy`. The new strategy positions the element inside the containing outlet based on the directions passed in trough PositionSettings.

### General
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
@extend %overlay-wrapper--flex !optional;
}

@include e(wrapper, $m: flex-container) {
@extend %overlay-wrapper !optional;
@extend %overlay-wrapper--flex-container !optional;
}

@include e(content) {
@extend %overlay-content !optional;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
display: flex;
}

%overlay-wrapper--flex-container {
display: flex;
position: absolute;
}

%overlay-content {
position: absolute;
pointer-events: all;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { IgxGridCellComponent } from './cell.component';
import { IColumnVisibilityChangedEventArgs } from './column-hiding-item.directive';
import { IgxColumnComponent, IgxColumnGroupComponent } from './column.component';
import { ISummaryExpression } from './summaries/grid-summary';
import { DropPosition, ContainerPositioningStrategy, IgxDecimalPipeComponent, IgxDatePipeComponent } from './grid.common';
import { DropPosition, RowEditPositionStrategy, IgxDecimalPipeComponent, IgxDatePipeComponent } from './grid.common';
import { IgxGridToolbarComponent } from './grid-toolbar.component';
import { IgxRowComponent } from './row.component';
import { IgxGridHeaderComponent } from './grid-header.component';
Expand Down Expand Up @@ -2557,7 +2557,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
private _cellSelectionMode = GridSelectionMode.multiple;
private _rowSelectionMode = GridSelectionMode.none;

private rowEditPositioningStrategy = new ContainerPositioningStrategy({
private rowEditPositioningStrategy = new RowEditPositionStrategy({
horizontalDirection: HorizontalAlignment.Right,
verticalDirection: VerticalAlignment.Bottom,
horizontalStartPoint: HorizontalAlignment.Left,
Expand Down
6 changes: 3 additions & 3 deletions projects/igniteui-angular/src/lib/grids/grid.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -714,17 +714,17 @@ export class IgxDecimalPipeComponent extends DecimalPipe implements PipeTransfor
/**
* @hidden
*/
export interface ContainerPositionSettings extends PositionSettings {
export interface RowEditPositionSettings extends PositionSettings {
container?: HTMLElement;
}

/**
* @hidden
*/
export class ContainerPositioningStrategy extends ConnectedPositioningStrategy {
export class RowEditPositionStrategy extends ConnectedPositioningStrategy {
isTop = false;
isTopInitialPosition = null;
public settings: ContainerPositionSettings;
public settings: RowEditPositionSettings;
position(contentElement: HTMLElement, size: { width: number, height: number }, document?: Document, initialCall?: boolean): void {
const container = this.settings.container; // grid.tbody
const target = <HTMLElement>this.settings.target; // current grid.row
Expand Down
41 changes: 41 additions & 0 deletions projects/igniteui-angular/src/lib/services/overlay/overlay.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { IgxDatePickerComponent, IgxDatePickerModule } from '../../date-picker/d
import { IPositionStrategy } from './position/IPositionStrategy';
import { IgxCalendarContainerComponent } from '../../date-picker/calendar-container.component';
import { BaseFitPositionStrategy } from './position/base-fit-position-strategy';
import { ContainerPositionStrategy } from './position';

const CLASS_OVERLAY_CONTENT = 'igx-overlay__content';
const CLASS_OVERLAY_CONTENT_MODAL = 'igx-overlay__content--modal';
Expand Down Expand Up @@ -2407,6 +2408,46 @@ describe('igxOverlay', () => {
expect(overlay.hide).toHaveBeenCalledTimes(0);
}));

// 1.5 GlobalContainer.
it('Should center the shown component in the outlet.', fakeAsync(() => {
const fixture = TestBed.createComponent(EmptyPageComponent);

const outlet = fixture.componentInstance.divElement;
const outletElement = outlet.nativeElement;
outletElement.style.width = '800px';
outletElement.style.height = '600px';
outletElement.style.position = 'fixed';
outletElement.style.top = '100px';
outletElement.style.left = '200px';
outletElement.style.overflow = 'hidden';

fixture.detectChanges();
const overlaySettings: OverlaySettings = {
outlet: outlet,
positionStrategy: new ContainerPositionStrategy()
};

const id = fixture.componentInstance.overlay.attach(SimpleDynamicComponent);
fixture.componentInstance.overlay.show(id, overlaySettings);
tick();

const overlayDiv = outletElement.children[0];
const overlayDivRect = overlayDiv.getBoundingClientRect();
expect(overlayDivRect.width).toEqual(800);
expect(overlayDivRect.height).toEqual(600);

const overlayWrapper = overlayDiv.children[0] as HTMLElement;
const componentEl = overlayWrapper.children[0].children[0];
const componentRect = componentEl.getBoundingClientRect();

// left = outletLeft + (outletWidth - componentWidth) / 2
// left = 200 + (800 - 100 ) / 2
expect(componentRect.left).toEqual(550);
// top = outletTop + (outletHeight - componentHeight) / 2
// top = 100 + (600 - 100 ) / 2
expect(componentRect.top).toEqual(350);
}));

// 3. Interaction
// 3.1 Modal
it('Should apply a greyed-out mask layers when is modal.', fakeAsync(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,26 @@ Position strategies determine where to display the component in the provided Igx
|:---------------------------|:-------------------------|
| HorizontalAlignment.Center | VerticalAlignment.Middle |

2) **Container** - Positions the element inside the containing outlet based on the directions passed in trough PositionSettings. These are Top/Middle/Bottom for verticalDirection and Left/Center/Right for horizontalDirection. Defaults to:

2) **Connected** - Positions the element based on the directions and start point passed in trough PositionSettings. It is possible to either pass a start point or an HTMLElement as a positioning base. Defaults to:
| horizontalDirection | verticalDirection |
|:---------------------------|:-------------------------|
| HorizontalAlignment.Center | VerticalAlignment.Middle |


3) **Connected** - Positions the element based on the directions and start point passed in trough PositionSettings. It is possible to either pass a start point or an HTMLElement as a positioning base. Defaults to:

| target | horizontalDirection | verticalDirection | horizontalStartPoint | verticalStartPoint |
|:----------------|:--------------------------|:-------------------------|:-------------------------|:-------------------------|
| new Point(0, 0) | HorizontalAlignment.Right | VerticalAlignment.Bottom | HorizontalAlignment.Left | VerticalAlignment.Bottom |

3) **Auto** - Positions the element as in **Connected** positioning strategy and re-positions the element in the view port (calculating a different start point) in case the element is partially getting out of view. Defaults to:
4) **Auto** - Positions the element as in **Connected** positioning strategy and re-positions the element in the view port (calculating a different start point) in case the element is partially getting out of view. Defaults to:

| target | horizontalDirection | verticalDirection | horizontalStartPoint | verticalStartPoint |
|:----------------|:--------------------------|:-------------------------|:-------------------------|:-------------------------|
| new Point(0, 0) | HorizontalAlignment.Right | VerticalAlignment.Bottom | HorizontalAlignment.Left | VerticalAlignment.Bottom |

4) **Elastic** - Positions the element as in **Connected** positioning strategy and resize the element to fit in the view port in case the element is partially getting out of view. Defaults to:
5) **Elastic** - Positions the element as in **Connected** positioning strategy and resize the element to fit in the view port in case the element is partially getting out of view. Defaults to:

| target | horizontalDirection | verticalDirection | horizontalStartPoint | verticalStartPoint | minSize |
|:----------------|:--------------------------|:-------------------------|:-------------------------|:-------------------------|-------------------------|
Expand Down Expand Up @@ -58,6 +64,7 @@ import {AutoPositionStrategy, GlobalPositionStrategy, ConnectedPositioningStrate
| Position Strategy | Name | Description |
|:------------------|:-------------------------------------------------------|:----------------------------------------------------------------------------------|
| Global | `position(contentElement)` | Positions the element, based on the horizontal and vertical directions. |
| Container | `position(contentElement)` | Positions the element inside the containing outlet based on the directions passed in trough PositionSettings. |
| Connected | `position(contentElement, size{})` | Positions the element, based on the position strategy used and the size passed in.|
| Auto | `position(contentElement, size{}, document?)` | Positions the element, based on the position strategy used and the size passed in.|
| Elastic | `position(contentElement, size{}, document?, minSize?)`| Positions the element, based on the position strategy used and the size passed in.|
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PositionSettings, Size } from '../utilities';
import { GlobalPositionStrategy } from './global-position-strategy';

/**
* Positions the element inside the containing outlet based on the directions passed in trough PositionSettings.
* These are Top/Middle/Bottom for verticalDirection and Left/Center/Right for horizontalDirection
*/
export class ContainerPositionStrategy extends GlobalPositionStrategy {
constructor(settings?: PositionSettings) {
super(settings);
}

/** @inheritdoc */
position(contentElement: HTMLElement, size?: Size, document?: Document, initialCall?: boolean): void {
contentElement.classList.add('igx-overlay__content--relative');
contentElement.parentElement.classList.add('igx-overlay__wrapper--flex-container');
this.setPosition(contentElement, this.settings);
}
}

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { IPositionStrategy } from './IPositionStrategy';
import { PositionSettings, HorizontalAlignment, VerticalAlignment, Size, Util } from './../utilities';
import { PositionSettings, HorizontalAlignment, VerticalAlignment, Size, Util, OverlaySettings } from './../utilities';
import { fadeIn, fadeOut } from '../../../animations/main';

/**
* Positions the element based on the directions passed in trough PositionSettings.
* These are Top/Middle/Bottom for verticalDirection and Left/Center/Right for horizontalDirection
*/
export class GlobalPositionStrategy implements IPositionStrategy {
private _defaultSettings: PositionSettings = {
protected _defaultSettings: PositionSettings = {
horizontalDirection: HorizontalAlignment.Center,
verticalDirection: VerticalAlignment.Middle,
horizontalStartPoint: HorizontalAlignment.Center,
Expand All @@ -24,9 +24,14 @@ export class GlobalPositionStrategy implements IPositionStrategy {
this.settings = Object.assign({}, this._defaultSettings, settings);
}

/** @inheritdoc */
position(contentElement: HTMLElement, size?: Size, document?: Document, initialCall?: boolean): void {
contentElement.classList.add('igx-overlay__content--relative');
contentElement.parentElement.classList.add('igx-overlay__wrapper--flex');
this.setPosition(contentElement, this.settings);
}

protected setPosition(contentElement: HTMLElement, settings: PositionSettings) {
switch (this.settings.horizontalDirection) {
case HorizontalAlignment.Left:
contentElement.parentElement.style.justifyContent = 'flex-start';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

// Export position strategies
export * from './IPositionStrategy';
export * from './global-position-strategy';
export * from './container-position-strategy';
export * from './connected-positioning-strategy';
export * from './auto-position-strategy';
export * from './elastic-position-strategy';
1 change: 0 additions & 1 deletion src/app/hierarchical-grid/hierarchical-grid.sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ export class HierarchicalGridSampleComponent {

cellClick($evt: IGridCellEventArgs) {
console.log('Cell Click', $evt);
// console.log($evt.context);
}

public LoadMoreColumns() {
Expand Down
4 changes: 3 additions & 1 deletion src/app/overlay/overlay.sample.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@
.outlet {
width: 600px;
height: 500px;
perspective: 1px;
margin: 0;
padding: 0;
position: relative;
}
19 changes: 16 additions & 3 deletions src/app/overlay/overlay.sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import {
CloseScrollStrategy,
NoOpScrollStrategy,
ElasticPositionStrategy,
IgxDragDirective
IgxDragDirective,
ContainerPositionStrategy
} from 'igniteui-angular';
import { templateJitUrl } from '@angular/compiler';

@Component({
// tslint:disable-next-line:component-selector
Expand Down Expand Up @@ -54,7 +54,7 @@ export class OverlaySampleComponent implements OnInit {
verticalStartPoints = ['Top', 'Middle', 'Bottom'];
verticalStartPoint = 'Top';

positionStrategies = ['Auto', 'Connected', 'Global', 'Elastic'];
positionStrategies = ['Auto', 'Connected', 'Global', 'Container', 'Elastic'];
positionStrategy = 'Global';

scrollStrategies = ['Absolute', 'Block', 'Close', 'NoOp'];
Expand Down Expand Up @@ -119,6 +119,18 @@ export class OverlaySampleComponent implements OnInit {
document.getElementById('mcd').classList.add('selected');
document.getElementById('mcsp').classList.add('selected');
break;
case 'Container':
this._overlaySettings.positionStrategy = new ContainerPositionStrategy();
this.horizontalDirection = 'Center';
this.verticalDirection = 'Middle';
this.horizontalStartPoint = 'Center';
this.verticalStartPoint = 'Middle';
this.closeOnOutsideClick = true;
this.modal = true;
this.useOutlet = true;
document.getElementById('mcd').classList.add('selected');
document.getElementById('mcsp').classList.add('selected');
break;
case 'Elastic':
this._overlaySettings = {
positionStrategy: new ElasticPositionStrategy({
Expand Down Expand Up @@ -173,6 +185,7 @@ export class OverlaySampleComponent implements OnInit {
'Auto': new AutoPositionStrategy(),
'Connected': new ConnectedPositioningStrategy(),
'Global': new GlobalPositionStrategy(),
'Container': new ContainerPositionStrategy(),
'Elastic': new ElasticPositionStrategy({
minSize: { width: 150, height: 150 }
}),
Expand Down

0 comments on commit 117b450

Please sign in to comment.