From ccea85012e9f262dc2feb0e3b8018eadd2f5ed09 Mon Sep 17 00:00:00 2001 From: Vitaliy Makogon Date: Thu, 25 Apr 2019 15:31:20 +0300 Subject: [PATCH] feat(popover,tooltip): add adaptivePosition option to disable adaptive positioning --- .../adaptive-position/adaptive-position.html | 15 +++++++ .../adaptive-position/adaptive-position.ts | 7 ++++ .../app/components/+popover/demos/index.ts | 40 ++++++++++--------- .../+popover/popover-section.list.ts | 39 +++++++++--------- .../adaptive-position/adaptive-position.html | 13 ++++++ .../adaptive-position/adaptive-position.ts | 7 ++++ .../app/components/+tooltip/demos/index.ts | 30 +++++++------- .../+tooltip/tooltip-section.list.ts | 26 ++++++++---- .../adaptive-position/adaptive-position.html | 2 +- src/popover/popover.config.ts | 2 + src/popover/popover.directive.ts | 23 +++++++---- src/positioning/models/index.ts | 3 ++ src/positioning/modifiers/preventOverflow.ts | 6 ++- src/tooltip/tooltip.config.ts | 2 + src/tooltip/tooltip.directive.ts | 13 ++++++ 15 files changed, 159 insertions(+), 69 deletions(-) create mode 100644 demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.html create mode 100644 demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.ts create mode 100644 demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.html create mode 100644 demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.ts diff --git a/demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.html b/demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.html new file mode 100644 index 0000000000..b7f6e20a93 --- /dev/null +++ b/demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.html @@ -0,0 +1,15 @@ + + + \ No newline at end of file diff --git a/demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.ts b/demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.ts new file mode 100644 index 0000000000..5024cb5467 --- /dev/null +++ b/demo/src/app/components/+popover/demos/adaptive-position/adaptive-position.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'demo-popover-adaptive-position', + templateUrl: './adaptive-position.html' +}) +export class DemoPopoverAdaptivePositionComponent {} diff --git a/demo/src/app/components/+popover/demos/index.ts b/demo/src/app/components/+popover/demos/index.ts index 055df889ba..304265f714 100644 --- a/demo/src/app/components/+popover/demos/index.ts +++ b/demo/src/app/components/+popover/demos/index.ts @@ -1,37 +1,39 @@ +import { DemoPopoverAdaptivePositionComponent } from './adaptive-position/adaptive-position'; import { DemoPopoverBasicComponent } from './basic/basic'; -import { DemoPopoverPlacementComponent } from './placement/placement'; +import { DemoPopoverByIsOpenPropComponent } from './trigger-by-isopen-property/trigger-by-isopen-property'; +import { DemoPopoverClassComponent } from './class/class'; +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 { DemoPopoverDismissComponent } from './dismiss/dismiss'; import { DemoPopoverDynamicComponent } from './dynamic/dynamic'; -import { DemoPopoverCustomContentComponent } from './custom-content/custom-content'; import { DemoPopoverDynamicHtmlComponent } from './dynamic-html/dynamic-html'; -import { DemoPopoverContainerComponent } from './container/container'; -import { DemoPopoverConfigComponent } from './config/config'; +import { DemoPopoverEventsComponent } from './events/events'; +import { DemoPopoverOutsideClickComponent } from './outside-click/outside-click'; +import { DemoPopoverPlacementComponent } from './placement/placement'; import { DemoPopoverStylingGlobalComponent } from './styling-global/styling-global'; import { DemoPopoverStylingLocalComponent } from './styling-local/styling-local'; import { DemoPopoverTriggersCustomComponent } from './triggers-custom/triggers-custom'; import { DemoPopoverTriggersManualComponent } from './triggers-manual/triggers-manual'; -import { DemoPopoverByIsOpenPropComponent } from './trigger-by-isopen-property/trigger-by-isopen-property'; -import { DemoPopoverClassComponent } from './class/class'; -import { DemoPopoverOutsideClickComponent } from './outside-click/outside-click'; -import { DemoPopoverEventsComponent } from './events/events'; -import { DemoPopoverContextComponent } from './popover-context/popover-context'; export const DEMO_COMPONENTS = [ + DemoPopoverAdaptivePositionComponent, DemoPopoverBasicComponent, - DemoPopoverPlacementComponent, + DemoPopoverByIsOpenPropComponent, + DemoPopoverClassComponent, + DemoPopoverConfigComponent, + DemoPopoverContainerComponent, + DemoPopoverContextComponent, + DemoPopoverCustomContentComponent, DemoPopoverDismissComponent, DemoPopoverDynamicComponent, - DemoPopoverCustomContentComponent, DemoPopoverDynamicHtmlComponent, - DemoPopoverContainerComponent, - DemoPopoverConfigComponent, + DemoPopoverEventsComponent, + DemoPopoverOutsideClickComponent, + DemoPopoverPlacementComponent, DemoPopoverStylingGlobalComponent, DemoPopoverStylingLocalComponent, DemoPopoverTriggersCustomComponent, - DemoPopoverTriggersManualComponent, - DemoPopoverByIsOpenPropComponent, - DemoPopoverClassComponent, - DemoPopoverOutsideClickComponent, - DemoPopoverEventsComponent, - DemoPopoverContextComponent + DemoPopoverTriggersManualComponent ]; diff --git a/demo/src/app/components/+popover/popover-section.list.ts b/demo/src/app/components/+popover/popover-section.list.ts index da17c2e6a7..39874cb210 100644 --- a/demo/src/app/components/+popover/popover-section.list.ts +++ b/demo/src/app/components/+popover/popover-section.list.ts @@ -1,20 +1,20 @@ +import { DemoPopoverAdaptivePositionComponent } from './demos/adaptive-position/adaptive-position'; import { DemoPopoverBasicComponent } from './demos/basic/basic'; -import { DemoPopoverPlacementComponent } from './demos/placement/placement'; +import { DemoPopoverByIsOpenPropComponent } from './demos/trigger-by-isopen-property/trigger-by-isopen-property'; +import { DemoPopoverClassComponent } from './demos/class/class'; +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 { DemoPopoverDismissComponent } from './demos/dismiss/dismiss'; import { DemoPopoverDynamicComponent } from './demos/dynamic/dynamic'; -import { DemoPopoverCustomContentComponent } from './demos/custom-content/custom-content'; import { DemoPopoverDynamicHtmlComponent } from './demos/dynamic-html/dynamic-html'; -import { DemoPopoverContainerComponent } from './demos/container/container'; -import { DemoPopoverConfigComponent } from './demos/config/config'; +import { DemoPopoverEventsComponent } from './demos/events/events'; import { DemoPopoverOutsideClickComponent } from './demos/outside-click/outside-click'; +import { DemoPopoverPlacementComponent } from './demos/placement/placement'; +import { DemoPopoverStylingLocalComponent } from './demos/styling-local/styling-local'; import { DemoPopoverTriggersCustomComponent } from './demos/triggers-custom/triggers-custom'; import { DemoPopoverTriggersManualComponent } from './demos/triggers-manual/triggers-manual'; -import { DemoPopoverByIsOpenPropComponent } from './demos/trigger-by-isopen-property/trigger-by-isopen-property'; -import { DemoPopoverStylingLocalComponent } from './demos/styling-local/styling-local'; -import { DemoPopoverClassComponent } from './demos/class/class'; -import { DemoPopoverContextComponent } from './demos/popover-context/popover-context'; -import { DemoPopoverStylingGlobalComponent } from './demos/styling-global/styling-global'; -import { DemoPopoverEventsComponent } from './demos/events/events'; import { ContentSection } from '../../docs/models/content-section.model'; import { DemoTopSectionComponent } from '../../docs/demo-section-components/demo-top-section/index'; @@ -57,6 +57,16 @@ export const demoComponentContent: ContentSection[] = [ Besides that, auto option may be used to detect a position that fits the component on screen.

`, outlet: DemoPopoverPlacementComponent }, + { + title: 'Disable adaptive position', + anchor: 'adaptive-position', + description: ` +

You can disable adaptive position via adaptivePosition input or config option

+ `, + component: require('!!raw-loader?lang=typescript!./demos/adaptive-position/adaptive-position.ts'), + html: require('!!raw-loader?lang=markup!./demos/adaptive-position/adaptive-position.html'), + outlet: DemoPopoverAdaptivePositionComponent + }, { title: 'Dismiss on next click', anchor: 'popover-dismiss', @@ -167,14 +177,7 @@ export const demoComponentContent: ContentSection[] = [ component: require('!!raw-loader?lang=typescript!./demos/popover-context/popover-context.ts'), html: require('!!raw-loader?lang=markup!./demos/popover-context/popover-context.html'), outlet: DemoPopoverContextComponent - }/*, - { - title: 'Global styling', - anchor: 'styling-global', - component: require('!!raw-loader?lang=typescript!./demos/styling-global/styling-global.ts'), - html: require('!!raw-loader?lang=markup!./demos/styling-global/styling-global.html'), - outlet: DemoPopoverStylingGlobalComponent - }*/ + } ] }, { diff --git a/demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.html b/demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.html new file mode 100644 index 0000000000..ceae1cdc59 --- /dev/null +++ b/demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.html @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.ts b/demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.ts new file mode 100644 index 0000000000..83619fe5ac --- /dev/null +++ b/demo/src/app/components/+tooltip/demos/adaptive-position/adaptive-position.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'demo-tooltip-adaptive-position', + templateUrl: './adaptive-position.html' +}) +export class DemoTooltipAdaptivePositionComponent {} diff --git a/demo/src/app/components/+tooltip/demos/index.ts b/demo/src/app/components/+tooltip/demos/index.ts index b066405a7f..a8d1444300 100644 --- a/demo/src/app/components/+tooltip/demos/index.ts +++ b/demo/src/app/components/+tooltip/demos/index.ts @@ -1,31 +1,33 @@ +import { DemoTooltipAdaptivePositionComponent } from './adaptive-position/adaptive-position'; import { DemoTooltipBasicComponent } from './basic/basic'; -import { DemoTooltipPlacementComponent } from './placement/placement'; -import { DemoTooltipDismissComponent } from './dismiss/dismiss'; -import { DemoTooltipDynamicComponent } from './dynamic/dynamic'; +import { DemoTooltipClassComponent } from './class/class'; import { DemoTooltipConfigComponent } from './config/config'; import { DemoTooltipContainerComponent } from './container/container'; +import { DemoTooltipCustomContentComponent } from './custom-content/custom-content'; +import { DemoTooltipDelayComponent } from './delay/delay'; +import { DemoTooltipDismissComponent } from './dismiss/dismiss'; +import { DemoTooltipDynamicComponent } from './dynamic/dynamic'; +import { DemoTooltipDynamicHtmlComponent } from './dynamic-html/dynamic-html'; +import { DemoTooltipPlacementComponent } from './placement/placement'; import { DemoTooltipStylingGlobalComponent } from './styling-global/styling-global'; import { DemoTooltipStylingLocalComponent } from './styling-local/styling-local'; import { DemoTooltipTriggersCustomComponent } from './triggers-custom/triggers-custom'; import { DemoTooltipTriggersManualComponent } from './triggers-manual/triggers-manual'; -import { DemoTooltipDynamicHtmlComponent } from './dynamic-html/dynamic-html'; -import { DemoTooltipClassComponent } from './class/class'; -import { DemoTooltipDelayComponent } from './delay/delay'; -import { DemoTooltipCustomContentComponent } from './custom-content/custom-content'; export const DEMO_COMPONENTS = [ + DemoTooltipAdaptivePositionComponent, DemoTooltipBasicComponent, - DemoTooltipPlacementComponent, - DemoTooltipDismissComponent, + DemoTooltipClassComponent, + DemoTooltipConfigComponent, + DemoTooltipContainerComponent, DemoTooltipCustomContentComponent, + DemoTooltipDelayComponent, + DemoTooltipDismissComponent, DemoTooltipDynamicComponent, DemoTooltipDynamicHtmlComponent, - DemoTooltipContainerComponent, - DemoTooltipConfigComponent, + DemoTooltipPlacementComponent, DemoTooltipStylingGlobalComponent, DemoTooltipStylingLocalComponent, DemoTooltipTriggersCustomComponent, - DemoTooltipTriggersManualComponent, - DemoTooltipClassComponent, - DemoTooltipDelayComponent + DemoTooltipTriggersManualComponent ]; diff --git a/demo/src/app/components/+tooltip/tooltip-section.list.ts b/demo/src/app/components/+tooltip/tooltip-section.list.ts index 223bff5a38..1dc316c5e7 100644 --- a/demo/src/app/components/+tooltip/tooltip-section.list.ts +++ b/demo/src/app/components/+tooltip/tooltip-section.list.ts @@ -1,15 +1,17 @@ +import { DemoTooltipAdaptivePositionComponent } from './demos/adaptive-position/adaptive-position'; import { DemoTooltipBasicComponent } from './demos/basic/basic'; -import { DemoTooltipPlacementComponent } from './demos/placement/placement'; +import { DemoTooltipClassComponent } from './demos/class/class'; +import { DemoTooltipConfigComponent } from './demos/config/config'; +import { DemoTooltipContainerComponent } from './demos/container/container'; +import { DemoTooltipCustomContentComponent } from './demos/custom-content/custom-content'; +import { DemoTooltipDelayComponent } from './demos/delay/delay'; import { DemoTooltipDismissComponent } from './demos/dismiss/dismiss'; import { DemoTooltipDynamicComponent } from './demos/dynamic/dynamic'; import { DemoTooltipDynamicHtmlComponent } from './demos/dynamic-html/dynamic-html'; -import { DemoTooltipContainerComponent } from './demos/container/container'; -import { DemoTooltipConfigComponent } from './demos/config/config'; +import { DemoTooltipPlacementComponent } from './demos/placement/placement'; +import { DemoTooltipStylingLocalComponent } from './demos/styling-local/styling-local'; import { DemoTooltipTriggersCustomComponent } from './demos/triggers-custom/triggers-custom'; import { DemoTooltipTriggersManualComponent } from './demos/triggers-manual/triggers-manual'; -import { DemoTooltipStylingLocalComponent } from './demos/styling-local/styling-local'; -import { DemoTooltipClassComponent } from './demos/class/class'; -import { DemoTooltipStylingGlobalComponent } from './demos/styling-global/styling-global'; import { ContentSection } from '../../docs/models/content-section.model'; import { DemoTopSectionComponent } from '../../docs/demo-section-components/demo-top-section/index'; @@ -20,8 +22,6 @@ import { NgApiDocComponent, NgApiDocConfigComponent } from '../../docs/api-docs'; -import { DemoTooltipDelayComponent } from './demos/delay/delay'; -import { DemoTooltipCustomContentComponent } from './demos/custom-content/custom-content'; export const demoComponentContent: ContentSection[] = [ { @@ -54,6 +54,16 @@ export const demoComponentContent: ContentSection[] = [ used to detect a position that fits the component on the screen.

`, outlet: DemoTooltipPlacementComponent }, + { + title: 'Disable adaptive position', + anchor: 'adaptive-position', + description: ` +

You can disable adaptive position via adaptivePosition input or config option

+ `, + component: require('!!raw-loader?lang=typescript!./demos/adaptive-position/adaptive-position.ts'), + html: require('!!raw-loader?lang=markup!./demos/adaptive-position/adaptive-position.html'), + outlet: DemoTooltipAdaptivePositionComponent + }, { title: 'Dismiss on next click', anchor: 'dismiss', diff --git a/demo/src/app/components/+typeahead/demos/adaptive-position/adaptive-position.html b/demo/src/app/components/+typeahead/demos/adaptive-position/adaptive-position.html index 4cc790c992..168adb1690 100644 --- a/demo/src/app/components/+typeahead/demos/adaptive-position/adaptive-position.html +++ b/demo/src/app/components/+typeahead/demos/adaptive-position/adaptive-position.html @@ -1,5 +1,5 @@
Model: {{selected | json}}
\ No newline at end of file diff --git a/src/popover/popover.config.ts b/src/popover/popover.config.ts index 6b9d4a19c7..b6435e5c7e 100644 --- a/src/popover/popover.config.ts +++ b/src/popover/popover.config.ts @@ -8,6 +8,8 @@ import { Injectable } from '@angular/core'; */ @Injectable() export class PopoverConfig { + /** sets disable adaptive position */ + adaptivePosition = true; /** * Placement of a popover. Accepts: "top", "bottom", "left", "right", "auto" */ diff --git a/src/popover/popover.directive.ts b/src/popover/popover.directive.ts index 0d2362bd32..bffd2227fe 100644 --- a/src/popover/popover.directive.ts +++ b/src/popover/popover.directive.ts @@ -12,6 +12,8 @@ import { PositioningService } from 'ngx-bootstrap/positioning'; */ @Directive({selector: '[popover]', exportAs: 'bs-popover'}) export class PopoverDirective implements OnInit, OnDestroy { + /** sets disable adaptive position */ + @Input() adaptivePosition: boolean; /** * Content to be displayed as popover. */ @@ -94,7 +96,9 @@ export class PopoverDirective implements OnInit, OnDestroy { _renderer ) .provide({provide: PopoverConfig, useValue: _config}); + Object.assign(this, _config); + this.onShown = this._popover.onShown; this.onHidden = this._popover.onHidden; @@ -115,6 +119,17 @@ export class PopoverDirective implements OnInit, OnDestroy { * the popover. */ show(): void { + this._positionService.setOptions({ + modifiers: { + flip: { + enabled: this.adaptivePosition + }, + preventOverflow: { + enabled: this.adaptivePosition + } + } + }); + if (this._popover.isShown || !this.popover) { return; } @@ -165,14 +180,6 @@ export class PopoverDirective implements OnInit, OnDestroy { } this._isInited = true; - this._positionService.setOptions({ - modifiers: { - flip: { - enabled: true - } - } - }); - this._popover.listen({ triggers: this.triggers, outsideClick: this.outsideClick, diff --git a/src/positioning/models/index.ts b/src/positioning/models/index.ts index 4315155a66..ee99ee84d9 100644 --- a/src/positioning/models/index.ts +++ b/src/positioning/models/index.ts @@ -32,5 +32,8 @@ export interface Options { flip?: { enabled: boolean; }; + preventOverflow?: { + enabled: boolean; + }; }; } diff --git a/src/positioning/modifiers/preventOverflow.ts b/src/positioning/modifiers/preventOverflow.ts index 25335bd553..88a851b216 100644 --- a/src/positioning/modifiers/preventOverflow.ts +++ b/src/positioning/modifiers/preventOverflow.ts @@ -1,8 +1,12 @@ -import { getBoundaries } from '../utils'; +import { getBoundaries, isModifierEnabled } from '../utils'; import { Data } from '../models'; export function preventOverflow(data: Data) { + if (!isModifierEnabled(data.options, 'preventOverflow')) { + return data; + } + // NOTE: DOM access here // resets the targetOffsets's position so that the document size can be calculated excluding // the size of the targetOffsets element itself diff --git a/src/tooltip/tooltip.config.ts b/src/tooltip/tooltip.config.ts index 3a456745dd..02c4e993ed 100644 --- a/src/tooltip/tooltip.config.ts +++ b/src/tooltip/tooltip.config.ts @@ -3,6 +3,8 @@ import { Injectable } from '@angular/core'; /** Default values provider for tooltip */ @Injectable() export class TooltipConfig { + /** sets disable adaptive position */ + adaptivePosition = true; /** tooltip placement, supported positions: 'top', 'bottom', 'left', 'right' */ placement = 'top'; /** array of event names which triggers tooltip opening */ diff --git a/src/tooltip/tooltip.directive.ts b/src/tooltip/tooltip.directive.ts index db8ae51a8e..ecaa9d0dee 100644 --- a/src/tooltip/tooltip.directive.ts +++ b/src/tooltip/tooltip.directive.ts @@ -30,6 +30,8 @@ let id = 0; }) export class TooltipDirective implements OnInit, OnDestroy { tooltipId = id++; + /** sets disable adaptive position */ + @Input() adaptivePosition: boolean; /** * Content to be displayed as tooltip. */ @@ -263,6 +265,17 @@ export class TooltipDirective implements OnInit, OnDestroy { * the tooltip. */ show(): void { + this._positionService.setOptions({ + modifiers: { + flip: { + enabled: this.adaptivePosition + }, + preventOverflow: { + enabled: this.adaptivePosition + } + } + }); + if ( this.isOpen || this.isDisabled ||