Skip to content

Commit e790196

Browse files
authored
fix(positioning): fix errors on invalid position (#5212)
* fix(positioning): fix errors on invalid position
1 parent bd9c72e commit e790196

File tree

14 files changed

+98
-98
lines changed

14 files changed

+98
-98
lines changed

src/datepicker/themes/bs/bs-datepicker-container.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export class BsDatepickerContainerComponent extends BsDatepickerAbstractComponen
4646
flip: {
4747
enabled: this._config.adaptivePosition
4848
}
49-
}
49+
},
50+
allowedPositions: ['top', 'bottom']
5051
});
5152

5253
this.isOtherMonthsActive = this._config.selectFromOtherMonth;

src/datepicker/themes/bs/bs-daterangepicker-container.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ export class BsDaterangepickerContainerComponent extends BsDatepickerAbstractCom
4949
flip: {
5050
enabled: this._config.adaptivePosition
5151
}
52-
}
52+
},
53+
allowedPositions: ['top', 'bottom']
5354
});
5455

5556
this.containerClass = this._config.containerClass;

src/dropdown/bs-dropdown.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
240240
(typeof this.dropup !== 'undefined' && this.dropup);
241241
this._state.direction = _dropup ? 'up' : 'down';
242242
const _placement =
243-
this.placement || (_dropup ? 'top left' : 'bottom left');
243+
this.placement || (_dropup ? 'top start' : 'bottom start');
244244

245245
// show dropdown
246246
this._dropdown

src/positioning/models/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ export interface Options {
3636
enabled: boolean;
3737
};
3838
};
39+
allowedPositions?: string[];
3940
}

src/positioning/modifiers/flip.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,7 @@ export function flip(data: Data): Data {
4141
const target = data.instance.target;
4242
const host = data.instance.host;
4343

44-
const adaptivePosition = variation
45-
? computeAutoPlacement('auto', offsetsHost, target, host, ['top', 'bottom'])
46-
: computeAutoPlacement('auto', offsetsHost, target, host);
47-
44+
const adaptivePosition = computeAutoPlacement('auto', offsetsHost, target, host, data.options.allowedPositions);
4845
const flipOrder = [placement, adaptivePosition];
4946

5047
/* tslint:disable-next-line: cyclomatic-complexity */

src/positioning/modifiers/initData.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,29 @@ export function initData(
1111
): Data {
1212

1313
const hostElPosition = getReferenceOffsets(targetElement, hostElement);
14+
15+
if (!position.match(/^(auto)*\s*(left|right|top|bottom)*$/)
16+
&& !position.match(/^(left|right|top|bottom)*\s*(start|end)*$/)) {
17+
/* tslint:disable-next-line: no-parameter-reassignment */
18+
position = 'auto';
19+
}
20+
1421
const placementAuto = !!position.match(/auto/g);
1522

1623
// support old placements 'auto left|right|top|bottom'
17-
let placement = !!position.match(/auto\s(left|right|top|bottom)/g)
18-
? position.split(' ')[1] || ''
24+
let placement = position.match(/auto\s(left|right|top|bottom)/)
25+
? position.split(' ')[1] || 'auto'
1926
: position;
2027

2128
const targetOffset = getTargetOffsets(targetElement, hostElPosition, placement);
22-
placement = computeAutoPlacement(placement, hostElPosition, targetElement, hostElement);
29+
30+
placement = computeAutoPlacement(
31+
placement,
32+
hostElPosition,
33+
targetElement,
34+
hostElement,
35+
options ? options.allowedPositions : undefined
36+
);
2337

2438
return {
2539
options,

src/positioning/modifiers/preventOverflow.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ export function preventOverflow(data: Data) {
7171
? 'primary'
7272
: 'secondary';
7373

74-
data.offsets.target = { ...data.offsets.target, ...(check as any)[side](placement) };
74+
data.offsets.target = {
75+
...data.offsets.target,
76+
...(check as any)[side](placement)
77+
};
7578

7679
});
7780

src/positioning/modifiers/shift.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ export function shift(data: Data): Data {
1212
const measurement = isVertical ? 'width' : 'height';
1313

1414
const shiftOffsets = {
15-
left: { [side]: host[side] },
16-
right: {
17-
[side]: host[side] + host[measurement] - host[measurement]
15+
start: { [side]: host[side] },
16+
end: {
17+
[side]: host[side] + host[measurement] - target[measurement]
1818
}
1919
};
2020

src/positioning/ng-positioning.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
import { Renderer2 } from '@angular/core';
66

7-
import { getReferenceOffsets, setAllStyles } from './utils';
7+
import { getOffsets, getReferenceOffsets, updateContainerClass, setStyles } from './utils';
88

99
import { arrow, flip, preventOverflow, shift, initData } from './modifiers';
1010
import { Data, Offsets, Options } from './models';
@@ -54,5 +54,18 @@ export function positionElements(
5454
options
5555
);
5656

57-
setAllStyles(data, renderer);
57+
const offsets = getOffsets(data);
58+
59+
setStyles(targetElement, {
60+
'will-change': 'transform',
61+
top: '0px',
62+
left: '0px',
63+
transform: `translate3d(${offsets.left}px, ${offsets.top}px, 0px)`
64+
}, renderer);
65+
66+
if (data.instance.arrow) {
67+
setStyles(data.instance.arrow, data.offsets.arrow, renderer);
68+
}
69+
70+
updateContainerClass(data, renderer);
5871
}

src/positioning/utils/computeAutoPlacement.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export function computeAutoPlacement(
1414
refRect: Offsets,
1515
target: HTMLElement,
1616
host: HTMLElement,
17-
allowedPositions: any[] = ['top', 'left', 'bottom', 'right'],
17+
allowedPositions: any[] = ['top', 'bottom', 'right', 'left'],
1818
boundariesElement = 'viewport',
1919
padding = 0
2020
) {
@@ -52,22 +52,27 @@ export function computeAutoPlacement(
5252
.sort((a, b) => b.area - a.area);
5353

5454
let filteredAreas: any[] = sortedAreas.filter(
55-
({ width, height }) =>
56-
width >= target.clientWidth && height >= target.clientHeight
55+
({ width, height }) => {
56+
return width >= target.clientWidth
57+
&& height >= target.clientHeight;
58+
}
5759
);
5860

59-
filteredAreas = allowedPositions
60-
.reduce((obj, key) => {
61-
return { ...obj, [key]: filteredAreas[key] };
62-
}, {});
61+
filteredAreas = filteredAreas.filter((position: any) => {
62+
return allowedPositions
63+
.some((allowedPosition: string) => {
64+
return allowedPosition === position.key;
65+
});
66+
});
6367

6468
const computedPlacement: string = filteredAreas.length > 0
6569
? filteredAreas[0].key
6670
: sortedAreas[0].key;
6771

6872
const variation = placement.split(' ')[1];
6973

70-
target.className = target.className.replace(/auto/g, computedPlacement);
74+
// for tooltip on auto position
75+
target.className = target.className.replace(/bs-tooltip-auto/g, `bs-tooltip-${computedPlacement}`);
7176

7277
return computedPlacement + (variation ? `-${variation}` : '');
7378
}

0 commit comments

Comments
 (0)