Skip to content

Commit

Permalink
feat(popover): add delay option (#5389) (#5582)
Browse files Browse the repository at this point in the history
* add delay option to popover
* fix(popover): small fix in description
  • Loading branch information
amiram authored and daniloff200 committed Jan 14, 2020
1 parent 93911f0 commit 00037ef
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 21 deletions.
20 changes: 20 additions & 0 deletions cypress/full/popover_page_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,24 @@ describe('Popover demo page test suite', () => {
popover.isPopoverDismiss(popoverContext);
});
});

describe('Popover with delay', () => {
const delayPopover = popover.exampleDemosArr.delayPopover;
it('when user clicks on "Popover with 0.5sec delay", then popover-container appear', () => {
cy.viewport(1440, 900);
popover.clickOnDemoMenu('Popover with delay');
popover.clickOnBtn(delayPopover);
popover.isPopoverAppears(delayPopover);
popover.isPopoverVisible(delayPopover);
});

it('when user clicks on "Popover with 0.5sec delay" again, then popover-container disappeared', () => {
cy.viewport(1440, 900);
popover.clickOnDemoMenu('Popover with delay');
popover.clickOnBtn(delayPopover);
popover.isPopoverAppears(delayPopover);
popover.clickOnBtn(delayPopover);
popover.isPopoverDismiss(delayPopover);
});
});
});
3 changes: 2 additions & 1 deletion cypress/support/popover.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export class PopoverPo extends BaseComponent {
triggerIsOpen: 'demo-popover-trigger-by-isopen',
componentLevelStyling: 'demo-popover-styling-local',
customClass: 'demo-popover-class',
popoverContext: 'demo-popover-context'
popoverContext: 'demo-popover-context',
delayPopover: 'demo-popover-delay'
};

isPopoverPlacementCorrect(baseSelector: string, placement: string) {
Expand Down
3 changes: 2 additions & 1 deletion demo/src/app/components/+popover/demos/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export function getPopoverConfig(): PopoverConfig {
return Object.assign(new PopoverConfig(), {
placement: 'right',
container: 'body',
triggers: 'focus'
triggers: 'focus',
delay: 500
});
}

Expand Down
5 changes: 5 additions & 0 deletions demo/src/app/components/+popover/demos/delay/delay.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<button type="button" class="btn btn-primary"
popover="Vivamus sagittis lacus vel augue laoreet rutrum faucibus." [delay]="500">
Popover with 0.5sec delay
</button>

7 changes: 7 additions & 0 deletions demo/src/app/components/+popover/demos/delay/delay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Component } from '@angular/core';

@Component({
selector: 'demo-popover-delay',
templateUrl: './delay.html'
})
export class DemoPopoverDelayComponent {}
2 changes: 2 additions & 0 deletions demo/src/app/components/+popover/demos/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DemoPopoverConfigComponent } from './config/config';
import { DemoPopoverContainerComponent } from './container/container';
import { DemoPopoverContextComponent } from './popover-context/popover-context';
import { DemoPopoverCustomContentComponent } from './custom-content/custom-content';
import { DemoPopoverDelayComponent } from './delay/delay';
import { DemoPopoverDismissComponent } from './dismiss/dismiss';
import { DemoPopoverDynamicComponent } from './dynamic/dynamic';
import { DemoPopoverDynamicHtmlComponent } from './dynamic-html/dynamic-html';
Expand All @@ -26,6 +27,7 @@ export const DEMO_COMPONENTS = [
DemoPopoverContainerComponent,
DemoPopoverContextComponent,
DemoPopoverCustomContentComponent,
DemoPopoverDelayComponent,
DemoPopoverDismissComponent,
DemoPopoverDynamicComponent,
DemoPopoverDynamicHtmlComponent,
Expand Down
11 changes: 10 additions & 1 deletion demo/src/app/components/+popover/popover-section.list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DemoPopoverConfigComponent } from './demos/config/config';
import { DemoPopoverContainerComponent } from './demos/container/container';
import { DemoPopoverContextComponent } from './demos/popover-context/popover-context';
import { DemoPopoverCustomContentComponent } from './demos/custom-content/custom-content';
import { DemoPopoverDelayComponent } from './demos/delay/delay';
import { DemoPopoverDismissComponent } from './demos/dismiss/dismiss';
import { DemoPopoverDynamicComponent } from './demos/dynamic/dynamic';
import { DemoPopoverDynamicHtmlComponent } from './demos/dynamic-html/dynamic-html';
Expand Down Expand Up @@ -52,7 +53,7 @@ export const demoComponentContent: ContentSection[] = [
anchor: 'placement',
component: require('!!raw-loader!./demos/placement/placement.ts'),
html: require('!!raw-loader!./demos/placement/placement.html'),
description: `<p>Four positioning options are available: <code>top</code>, <code>right</code>,
description: `<p>Four positioning options are available: <code>top</code>, <code>right</code>,
<code>bottom</code>, and <code>left</code>.
Besides that, <code>auto</code> option may be used to detect a position that fits the component on screen.</p>`,
outlet: DemoPopoverPlacementComponent
Expand Down Expand Up @@ -177,6 +178,14 @@ export const demoComponentContent: ContentSection[] = [
component: require('!!raw-loader!./demos/popover-context/popover-context.ts'),
html: require('!!raw-loader!./demos/popover-context/popover-context.html'),
outlet: DemoPopoverContextComponent
},
{
title: 'Popover with delay',
anchor: 'popover-delay',
component: require('!!raw-loader!./demos/delay/delay.ts'),
html: require('!!raw-loader!./demos/delay/delay.html'),
description: `<p>Click on the button to see popover delayed for 0,5 second </p>`,
outlet: DemoPopoverDelayComponent
}
]
},
Expand Down
11 changes: 11 additions & 0 deletions demo/src/ng-api-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2624,6 +2624,12 @@ export const ngdoc: any = {
"defaultValue": "click",
"type": "string",
"description": "<p>Specifies events that should trigger. Supports a space separated list of\nevent names.</p>\n"
},
{
"name": "delay",
"defaultValue": "0",
"type": "number",
"description": "<p>delay before showing the popover</p>\n"
}
]
},
Expand All @@ -2649,6 +2655,11 @@ export const ngdoc: any = {
"type": "string",
"description": "<p>Css class for popover container</p>\n"
},
{
"name": "delay",
"type": "number",
"description": "<p>Delay before showing the popover</p>\n"
},
{
"name": "isOpen",
"type": "boolean",
Expand Down
20 changes: 20 additions & 0 deletions docs/spec/popover/popover.examples.popover-with-delay.use-case.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
9.17: Popover with delay example
==================================
**Primary Actor**: User

**Scope**: Ngx-bootstrap DEMO / BS version 3&4

**Goal**:

Main success scenario:
----------------------
1. User opens Popover demo page
2. User clicks on Popover with delay sub-menu
3. User see button "Popover with 0.5sec delay"
4. When user clicks on "Popover with 0.5sec delay", then popover-container appear above the button with 0.5sec delay
5. When user clicks on "Popover with 0.5sec delay" again, then popover-container disappeared
6. Template src should be written with [delay]="500"

Variations:
-----------
2*. User scroll to Popover with delay sub-menu
2 changes: 2 additions & 0 deletions src/popover/popover.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ export class PopoverConfig {
* A selector specifying the element the popover should be appended to.
*/
container: string;
/** delay before showing the tooltip */
delay = 0;
}
87 changes: 69 additions & 18 deletions src/popover/popover.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { PopoverConfig } from './popover.config';
import { ComponentLoader, ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
import { PopoverContainerComponent } from './popover-container.component';
import { PositioningService } from 'ngx-bootstrap/positioning';
import { timer } from 'rxjs';
import { parseTriggers, Trigger } from 'ngx-bootstrap/utils';

/**
* A lightweight, extensible directive for fancy popover creation.
Expand Down Expand Up @@ -67,6 +69,11 @@ export class PopoverDirective implements OnInit, OnDestroy {
}
}

/**
* Delay before showing the tooltip
*/
@Input() delay: number;

/**
* Emits an event when the popover is shown
*/
Expand All @@ -78,13 +85,17 @@ export class PopoverDirective implements OnInit, OnDestroy {
/* tslint:disable-next-line: no-any */
@Output() onHidden: EventEmitter<any>;

protected _popoverCancelShowFn: Function;

protected _delayTimeoutId: number | any;

private _popover: ComponentLoader<PopoverContainerComponent>;
private _isInited = false;

constructor(
_config: PopoverConfig,
_elementRef: ElementRef,
_renderer: Renderer2,
private _elementRef: ElementRef,
private _renderer: Renderer2,
_viewContainerRef: ViewContainerRef,
cis: ComponentLoaderFactory,
private _positionService: PositioningService
Expand Down Expand Up @@ -119,7 +130,7 @@ export class PopoverDirective implements OnInit, OnDestroy {
* the popover.
*/
show(): void {
if (this._popover.isShown || !this.popover) {
if (this._popover.isShown || !this.popover || this._delayTimeoutId) {
return;
}

Expand All @@ -134,31 +145,71 @@ export class PopoverDirective implements OnInit, OnDestroy {
}
});

this._popover
.attach(PopoverContainerComponent)
.to(this.container)
.position({attachment: this.placement})
.show({
content: this.popover,
context: this.popoverContext,
placement: this.placement,
title: this.popoverTitle,
containerClass: this.containerClass
const showPopover = () => {
if (this._delayTimeoutId) {
this._delayTimeoutId = undefined;
}

this._popover
.attach(PopoverContainerComponent)
.to(this.container)
.position({attachment: this.placement})
.show({
content: this.popover,
context: this.popoverContext,
placement: this.placement,
title: this.popoverTitle,
containerClass: this.containerClass
});

if (!this.adaptivePosition) {
this._positionService.calcPosition();
this._positionService.deletePositionElement(this._popover._componentRef.location);
}

this.isOpen = true;
};

const cancelDelayedTooltipShowing = () => {
if (this._popoverCancelShowFn) {
this._popoverCancelShowFn();
}
};

if (this.delay) {
const _timer = timer(this.delay).subscribe(() => {
showPopover();
cancelDelayedTooltipShowing();
});

if (!this.adaptivePosition) {
this._positionService.calcPosition();
this._positionService.deletePositionElement(this._popover._componentRef.location);
if (this.triggers) {
parseTriggers(this.triggers)
.forEach((trigger: Trigger) => {
this._popoverCancelShowFn = this._renderer.listen(
this._elementRef.nativeElement,
trigger.close,
() => {
_timer.unsubscribe();
cancelDelayedTooltipShowing();
}
);
});
}
} else {
showPopover();
}

this.isOpen = true;
}

/**
* Closes an element’s popover. This is considered a “manual” triggering of
* the popover.
*/
hide(): void {
if (this._delayTimeoutId) {
clearTimeout(this._delayTimeoutId);
this._delayTimeoutId = undefined;
}

if (this.isOpen) {
this._popover.hide();
this.isOpen = false;
Expand Down

0 comments on commit 00037ef

Please sign in to comment.