mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-05 09:02:26 +03:00
add box-sizing change detection to size observer
This commit is contained in:
@@ -19,5 +19,10 @@ export const createTrinsicLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =>
|
||||
height: heightIntrinsic ? 'auto' : '100%',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
_sizeChanged: heightIntrinsicChanged,
|
||||
_contentMutation: heightIntrinsicChanged,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
ResizeObserverConstructor,
|
||||
isArray,
|
||||
isBoolean,
|
||||
removeClass,
|
||||
} from 'support';
|
||||
import { getEnvironment } from 'environment';
|
||||
import {
|
||||
@@ -64,7 +65,7 @@ const directionIsRTL = (elm: HTMLElement): boolean => style(elm, 'direction') ==
|
||||
const domRectHasDimensions = (rect?: DOMRectReadOnly) => rect && (rect.height || rect.width);
|
||||
|
||||
/**
|
||||
* Creates a size observer which observes any size, padding, margin and border changes of the target element. Depending on the options also direction and appear can be observed.
|
||||
* Creates a size observer which observes any size, padding, border, margin and box-sizing changes of the target element. Depending on the options also direction and appear can be observed.
|
||||
* @param target The target element which shall be observed.
|
||||
* @param onSizeChangedCallback The callback which gets called after a size change was detected.
|
||||
* @param options The options for size detection, whether to observe also direction and appear.
|
||||
@@ -193,10 +194,11 @@ export const createSizeObserver = (
|
||||
const directionIsRTLCacheValues = updateDirectionIsRTLCache();
|
||||
const { _value, _changed } = directionIsRTLCacheValues;
|
||||
if (_changed) {
|
||||
removeClass(listenerElement, 'ltr rtl');
|
||||
if (_value) {
|
||||
style(listenerElement, { left: 'auto', right: 0 });
|
||||
addClass(listenerElement, 'rtl');
|
||||
} else {
|
||||
style(listenerElement, { left: 0, right: 'auto' });
|
||||
addClass(listenerElement, 'ltr');
|
||||
}
|
||||
onSizeChangedCallbackProxy(directionIsRTLCacheValues);
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
@import './trinsicobserver.scss';
|
||||
|
||||
.os-environment {
|
||||
--css-custom-prop: -1;
|
||||
--os-css-custom-prop: -1;
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
overflow: scroll;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
z-index: var(--css-custom-prop);
|
||||
z-index: var(--os-css-custom-prop);
|
||||
|
||||
div {
|
||||
width: 200%;
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
.os-padding,
|
||||
.os-viewport {
|
||||
box-sizing: border-box;
|
||||
box-sizing: inherit;
|
||||
position: relative;
|
||||
flex: auto !important;
|
||||
height: auto;
|
||||
@@ -106,6 +106,7 @@
|
||||
border: none;
|
||||
overflow: visible;
|
||||
max-width: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.os-viewport {
|
||||
@@ -123,3 +124,7 @@
|
||||
height: var(--viewport-arrange-height);
|
||||
}
|
||||
}
|
||||
|
||||
.os-content {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
$scrollbar-cushion: 100px;
|
||||
$inflate-margin: 200px;
|
||||
|
||||
.os-size-observer,
|
||||
.os-size-observer-listener {
|
||||
direction: inherit;
|
||||
padding: inherit;
|
||||
border: inherit;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
@@ -23,10 +21,34 @@ $scrollbar-cushion: 100px;
|
||||
}
|
||||
|
||||
.os-size-observer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 3%;
|
||||
width: 3%;
|
||||
z-index: -1;
|
||||
contain: strict;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
padding: inherit;
|
||||
border: inherit;
|
||||
box-sizing: inherit;
|
||||
margin: 0;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
flex: none;
|
||||
box-sizing: inherit;
|
||||
}
|
||||
&::before {
|
||||
padding: 1px;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
padding: inherit;
|
||||
border: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.os-size-observer-appear {
|
||||
@@ -35,9 +57,19 @@ $scrollbar-cushion: 100px;
|
||||
}
|
||||
|
||||
.os-size-observer-listener {
|
||||
display: block;
|
||||
height: 500%;
|
||||
width: 500%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
flex: auto;
|
||||
margin: -#{$inflate-margin};
|
||||
|
||||
&.ltr {
|
||||
margin-right: -#{$inflate-margin * 2};
|
||||
margin-left: 0;
|
||||
}
|
||||
&.rtl {
|
||||
margin-left: -#{$inflate-margin * 2};
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
// lets assume no scrollbar is 100px wide
|
||||
& > .os-size-observer-listener-item {
|
||||
|
||||
+47
-2
@@ -2,17 +2,24 @@ import 'styles/overlayscrollbars.scss';
|
||||
import './index.scss';
|
||||
|
||||
import { resize } from '@/testing-browser/Resize';
|
||||
import { generateClassChangeSelectCallback, iterateSelect } from '@/testing-browser/Select';
|
||||
import { OverlayScrollbars } from 'overlayscrollbars';
|
||||
import { style } from 'support';
|
||||
import { from, style } from 'support';
|
||||
|
||||
const targetElm = document.querySelector('#target') as HTMLElement;
|
||||
const osInstance = (window.os = OverlayScrollbars({ target: targetElm, content: false }));
|
||||
const osInstance = (window.os = OverlayScrollbars({ target: targetElm, content: true }));
|
||||
|
||||
const target: HTMLElement | null = document.querySelector('#target');
|
||||
const comparison: HTMLElement | null = document.querySelector('#comparison');
|
||||
const targetRes: HTMLElement | null = document.querySelector('#target .resize');
|
||||
const comparisonRes: HTMLElement | null = document.querySelector('#comparison .resize');
|
||||
|
||||
const resizeElms = document.querySelectorAll('.resize');
|
||||
const percentElms = document.querySelectorAll('.percent');
|
||||
const endElms = document.querySelectorAll('.end');
|
||||
const envElms = document.querySelectorAll<HTMLElement>('.env');
|
||||
const containerElms = document.querySelectorAll<HTMLElement>('#target, #comparison');
|
||||
|
||||
resize(target!).addResizeListener((width, height) => style(comparison, { width, height }));
|
||||
//resize(comparison!).addResizeListener((width, height) => style(target, { width, height }));
|
||||
resize(targetRes!).addResizeListener((width, height) => style(comparisonRes, { width, height }));
|
||||
@@ -23,3 +30,41 @@ target!.querySelector('.os-viewport')?.addEventListener('scroll', (e) => {
|
||||
comparison!.scrollLeft = viewport.scrollLeft;
|
||||
comparison!.scrollTop = viewport.scrollTop;
|
||||
});
|
||||
|
||||
const envWidthSelect = document.querySelector<HTMLSelectElement>('#envWidth');
|
||||
const envHeightSelect = document.querySelector<HTMLSelectElement>('#envHeight');
|
||||
const selectCallbackEnv = generateClassChangeSelectCallback(from(envElms));
|
||||
const containerWidthSelect = document.querySelector<HTMLSelectElement>('#width');
|
||||
const containerHeightSelect = document.querySelector<HTMLSelectElement>('#height');
|
||||
const containerFloatSelect = document.querySelector<HTMLSelectElement>('#float');
|
||||
const containerPaddingSelect = document.querySelector<HTMLSelectElement>('#padding');
|
||||
const containerBorderSelect = document.querySelector<HTMLSelectElement>('#border');
|
||||
const containerMarginSelect = document.querySelector<HTMLSelectElement>('#margin');
|
||||
const containerBoxSizingSelect = document.querySelector<HTMLSelectElement>('#boxSizing');
|
||||
const containerDirectionSelect = document.querySelector<HTMLSelectElement>('#direction');
|
||||
const containerMinMaxSelect = document.querySelector<HTMLSelectElement>('#minMax');
|
||||
const selectCallbackContainer = generateClassChangeSelectCallback(from(containerElms));
|
||||
|
||||
envWidthSelect?.addEventListener('change', selectCallbackEnv);
|
||||
envHeightSelect?.addEventListener('change', selectCallbackEnv);
|
||||
containerWidthSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerHeightSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerFloatSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerPaddingSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerBorderSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerMarginSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerBoxSizingSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerDirectionSelect?.addEventListener('change', selectCallbackContainer);
|
||||
containerMinMaxSelect?.addEventListener('change', selectCallbackContainer);
|
||||
|
||||
selectCallbackEnv(envWidthSelect);
|
||||
selectCallbackEnv(envHeightSelect);
|
||||
selectCallbackContainer(containerWidthSelect);
|
||||
selectCallbackContainer(containerHeightSelect);
|
||||
selectCallbackContainer(containerFloatSelect);
|
||||
selectCallbackContainer(containerPaddingSelect);
|
||||
selectCallbackContainer(containerBorderSelect);
|
||||
selectCallbackContainer(containerMarginSelect);
|
||||
selectCallbackContainer(containerBoxSizingSelect);
|
||||
selectCallbackContainer(containerDirectionSelect);
|
||||
selectCallbackContainer(containerMinMaxSelect);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div id="controls">
|
||||
<label for="evnHeight">evnHeight</label>
|
||||
<select name="evnHeight" id="evnHeight">
|
||||
<label for="envHeight">envHeight</label>
|
||||
<select name="envHeight" id="envHeight">
|
||||
<option value="envHeightAuto">auto</option>
|
||||
<option value="envHeightHundred">100%</option>
|
||||
</select>
|
||||
@@ -35,9 +35,9 @@
|
||||
</select>
|
||||
<label for="border">border</label>
|
||||
<select name="border" id="border">
|
||||
<option value="borderNone">none</option>
|
||||
<option value="borderSmall">small</option>
|
||||
<option value="borderLarge">large</option>
|
||||
<option value="borderNone">none</option>
|
||||
</select>
|
||||
<label for="margin">margin</label>
|
||||
<select name="margin" id="margin">
|
||||
@@ -50,11 +50,6 @@
|
||||
<option value="boxSizingBorderBox">border-box</option>
|
||||
<option value="boxSizingContentBox">content-box</option>
|
||||
</select>
|
||||
<label for="display">display</label>
|
||||
<select name="display" id="display">
|
||||
<option value="displayBlock">block</option>
|
||||
<option value="displayNone">none</option>
|
||||
</select>
|
||||
<label for="direction">direction</label>
|
||||
<select name="direction" id="direction">
|
||||
<option value="directionLTR">ltr</option>
|
||||
|
||||
+141
-69
@@ -36,21 +36,45 @@ body {
|
||||
.column {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.env {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#target,
|
||||
#comparison {
|
||||
position: relative;
|
||||
border: 2px solid red;
|
||||
min-height: 100px;
|
||||
min-width: 200px;
|
||||
max-height: 300px;
|
||||
max-width: 320px;
|
||||
padding: 5px 50px 15px 20px;
|
||||
|
||||
.os-viewport::before,
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
border: 2px dotted red;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
* {
|
||||
font-size: medium;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
#target::before {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
#comparison {
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.resize {
|
||||
@@ -73,7 +97,6 @@ body {
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.end::before {
|
||||
@@ -89,68 +112,6 @@ body {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.padding0 {
|
||||
padding: 0;
|
||||
}
|
||||
.padding10 {
|
||||
padding: 10px;
|
||||
}
|
||||
.padding50 {
|
||||
padding: 50px;
|
||||
}
|
||||
|
||||
.border2 {
|
||||
border: 2px solid red;
|
||||
}
|
||||
.border10 {
|
||||
border: 10px solid red;
|
||||
}
|
||||
.border0 {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.heightAuto {
|
||||
height: auto;
|
||||
}
|
||||
.height200 {
|
||||
height: 200px;
|
||||
}
|
||||
.heightHundred {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.widthAuto {
|
||||
width: auto;
|
||||
float: left;
|
||||
}
|
||||
.width200 {
|
||||
width: 200px;
|
||||
}
|
||||
.widthHundred {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.boxSizingBorderBox {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.boxSizingContentBox {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.displayNone {
|
||||
display: none;
|
||||
}
|
||||
.displayBlock {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.directionltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.directionRTL {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.resizer {
|
||||
position: relative;
|
||||
}
|
||||
@@ -165,6 +126,117 @@ body {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.widthAuto,
|
||||
.envWidthAuto {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
#target.widthAuto {
|
||||
display: inline-flex;
|
||||
}
|
||||
.widthHundred,
|
||||
.envWidthHundred {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.heightAuto,
|
||||
.envHeightAuto {
|
||||
height: auto;
|
||||
}
|
||||
.heightHundred,
|
||||
.envHeightHundred {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.width200 {
|
||||
width: 200px;
|
||||
}
|
||||
.height200 {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.floatNone {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.floatLeft {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.floatRight {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.paddingNone {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.paddingSmall {
|
||||
padding: 5px 50px 15px 20px;
|
||||
}
|
||||
|
||||
.paddingLarge {
|
||||
padding: 12px 22px 53px 33px;
|
||||
}
|
||||
|
||||
.borderNone {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.borderSmall {
|
||||
border-color: darkorange;
|
||||
border-style: solid;
|
||||
border-width: 2px 5px 3px 4px;
|
||||
}
|
||||
|
||||
.borderLarge {
|
||||
border-color: darkorange;
|
||||
border-style: solid;
|
||||
border-width: 9px 6px 7px 3px;
|
||||
}
|
||||
|
||||
.marginNone {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.marginSmall {
|
||||
margin: 21px 16px 4px 33px;
|
||||
}
|
||||
|
||||
.marginLarge {
|
||||
margin: 33px 46px 69px 23px;
|
||||
}
|
||||
|
||||
.boxSizingBorderBox {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.boxSizingContentBox {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.directionLTR {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.directionRTL {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.minMaxFixed {
|
||||
min-height: 180px;
|
||||
min-width: 180px;
|
||||
max-height: 420px;
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
.minMaxNone {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
max-height: none;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/*
|
||||
.os-environment::-webkit-scrollbar,
|
||||
.os-viewport::-webkit-scrollbar,
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'styles/overlayscrollbars.scss';
|
||||
import './index.scss';
|
||||
import './handleEnvironment';
|
||||
import should from 'should';
|
||||
import { generateClassChangeSelectCallback, iterateSelect } from '@/testing-browser/Select';
|
||||
import { generateClassChangeSelectCallback, iterateSelect, selectOption } from '@/testing-browser/Select';
|
||||
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
|
||||
import { timeout } from '@/testing-browser/timeout';
|
||||
import { hasDimensions, offsetSize, WH, style } from 'support';
|
||||
@@ -60,6 +60,7 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
currOffsetSize: WH<number>;
|
||||
currContentSize: WH<number>;
|
||||
currDir: string;
|
||||
currBoxSizing: string;
|
||||
}
|
||||
|
||||
await iterateSelect<IterateSelect>(select, {
|
||||
@@ -69,6 +70,7 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
const currOffsetSize = offsetSize(targetElm as HTMLElement);
|
||||
const currContentSize = contentBox(targetElm as HTMLElement);
|
||||
const currDir = style(targetElm as HTMLElement, 'direction');
|
||||
const currBoxSizing = style(targetElm as HTMLElement, 'box-sizing');
|
||||
|
||||
return {
|
||||
currSizeIterations,
|
||||
@@ -76,15 +78,18 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
currOffsetSize,
|
||||
currContentSize,
|
||||
currDir,
|
||||
currBoxSizing,
|
||||
};
|
||||
},
|
||||
async check({ currSizeIterations, currDirectionIterations, currOffsetSize, currContentSize, currDir }) {
|
||||
async check({ currSizeIterations, currDirectionIterations, currOffsetSize, currContentSize, currDir, currBoxSizing }) {
|
||||
const newOffsetSize = offsetSize(targetElm as HTMLElement);
|
||||
const newContentSize = contentBox(targetElm as HTMLElement);
|
||||
const newDir = style(targetElm as HTMLElement, 'direction');
|
||||
const newBoxSizing = style(targetElm as HTMLElement, 'box-sizing');
|
||||
const offsetSizeChanged = currOffsetSize.w !== newOffsetSize.w || currOffsetSize.h !== newOffsetSize.h;
|
||||
const contentSizeChanged = currContentSize.w !== newContentSize.w || currContentSize.h !== newContentSize.h;
|
||||
const dirChanged = currDir !== newDir;
|
||||
const boxSizingChanged = currBoxSizing !== newBoxSizing;
|
||||
const dimensions = hasDimensions(targetElm as HTMLElement);
|
||||
const observerElm = targetElm?.firstElementChild as HTMLElement;
|
||||
|
||||
@@ -102,9 +107,9 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
);
|
||||
}
|
||||
|
||||
if (dimensions && (offsetSizeChanged || contentSizeChanged || dirChanged)) {
|
||||
if (dimensions && (offsetSizeChanged || contentSizeChanged || dirChanged || boxSizingChanged)) {
|
||||
await waitForOrFailTest(() => {
|
||||
if (offsetSizeChanged || contentSizeChanged) {
|
||||
if (offsetSizeChanged || contentSizeChanged || boxSizingChanged) {
|
||||
should.equal(sizeIterations, currSizeIterations + 1, 'Size change was detected correctly.');
|
||||
}
|
||||
if (dirChanged) {
|
||||
@@ -159,6 +164,36 @@ const iterateDisplay = async (afterEach?: () => any) => {
|
||||
const iterateDirection = async (afterEach?: () => any) => {
|
||||
await iterate(directionSelect, afterEach);
|
||||
};
|
||||
const cleanBoxSizingChange = async () => {
|
||||
selectOption(heightSelect as HTMLSelectElement, 'heightAuto');
|
||||
selectOption(widthSelect as HTMLSelectElement, 'widthAuto');
|
||||
selectOption(paddingSelect as HTMLSelectElement, 'padding0');
|
||||
selectOption(borderSelect as HTMLSelectElement, 'border0');
|
||||
|
||||
await timeout(250);
|
||||
|
||||
await iterateDirection(async () => {
|
||||
await iterateBoxSizing();
|
||||
});
|
||||
|
||||
selectOption(heightSelect as HTMLSelectElement, 'height200');
|
||||
selectOption(widthSelect as HTMLSelectElement, 'width200');
|
||||
|
||||
await timeout(250);
|
||||
|
||||
await iterateDirection(async () => {
|
||||
await iterateBoxSizing();
|
||||
});
|
||||
|
||||
selectOption(heightSelect as HTMLSelectElement, 'heightHundred');
|
||||
selectOption(widthSelect as HTMLSelectElement, 'widthHundred');
|
||||
|
||||
await timeout(250);
|
||||
|
||||
await iterateDirection(async () => {
|
||||
await iterateBoxSizing();
|
||||
});
|
||||
};
|
||||
const start = async () => {
|
||||
setTestResult(null);
|
||||
|
||||
@@ -180,6 +215,7 @@ const start = async () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
await cleanBoxSizingChange();
|
||||
|
||||
sizeObserver._destroy();
|
||||
should.equal(targetElm?.children.length, preInitChildren, 'Destruction removes all generated elements.');
|
||||
|
||||
@@ -34,6 +34,7 @@ body {
|
||||
// prevent container from reaching 0x0 dimensions for testing purposes
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.padding0 {
|
||||
|
||||
@@ -10,22 +10,25 @@ const noop = <T>(): T => {
|
||||
const getSelectOptions = (selectElement: HTMLSelectElement) => Array.from(selectElement.options).map((option) => option.value);
|
||||
|
||||
export const generateSelectCallback = (
|
||||
targetElm: HTMLElement | null,
|
||||
targetElms: HTMLElement[] | HTMLElement | null,
|
||||
callback: (targetAffectedElm: HTMLElement, possibleValues: string[], selectedValue: string) => any
|
||||
) => (event: Event | HTMLSelectElement | null) => {
|
||||
const target: HTMLSelectElement | null = isEvent(event) ? (event.target as HTMLSelectElement) : event;
|
||||
if (target) {
|
||||
const selectedOption = target.value;
|
||||
const selectOptions = getSelectOptions(target);
|
||||
const elmsArr = Array.isArray(targetElms) ? targetElms : [targetElms];
|
||||
|
||||
if (targetElm) {
|
||||
callback(targetElm, selectOptions, selectedOption);
|
||||
}
|
||||
elmsArr.forEach((elm) => {
|
||||
if (elm) {
|
||||
callback(elm, selectOptions, selectedOption);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const generateClassChangeSelectCallback = (targetElm: HTMLElement | null) =>
|
||||
generateSelectCallback(targetElm, (targetAffectedElm, possibleValues, selectedValue) => {
|
||||
export const generateClassChangeSelectCallback = (targetElms: HTMLElement[] | HTMLElement | null) =>
|
||||
generateSelectCallback(targetElms, (targetAffectedElm, possibleValues, selectedValue) => {
|
||||
possibleValues.forEach((clazz) => targetAffectedElm.classList.remove(clazz));
|
||||
targetAffectedElm.classList.add(selectedValue);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user