@thednp/shorty 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +340 -0
- package/dist/shorty.esm.js +2540 -0
- package/dist/shorty.esm.min.js +2 -0
- package/dist/shorty.js +2563 -0
- package/dist/shorty.min.js +2 -0
- package/package.json +59 -0
- package/src/attr/getAttribute.js +9 -0
- package/src/attr/getAttributeNS.js +10 -0
- package/src/attr/hasAttribute.js +9 -0
- package/src/attr/hasAttributeNS.js +10 -0
- package/src/attr/removeAttribute.js +9 -0
- package/src/attr/removeAttributeNS.js +10 -0
- package/src/attr/setAttribute.js +10 -0
- package/src/attr/setAttributeNS.js +11 -0
- package/src/blocks/documentBody.js +5 -0
- package/src/blocks/documentElement.js +5 -0
- package/src/blocks/documentHead.js +5 -0
- package/src/boolean/isApple.js +13 -0
- package/src/boolean/isFirefox.js +9 -0
- package/src/boolean/isMobile.js +20 -0
- package/src/boolean/support3DTransform.js +8 -0
- package/src/boolean/supportAnimation.js +8 -0
- package/src/boolean/supportPassive.js +28 -0
- package/src/boolean/supportTouch.js +6 -0
- package/src/boolean/supportTransform.js +8 -0
- package/src/boolean/supportTransition.js +8 -0
- package/src/class/addClass.js +10 -0
- package/src/class/hasClass.js +10 -0
- package/src/class/removeClass.js +10 -0
- package/src/event/off.js +13 -0
- package/src/event/on.js +13 -0
- package/src/event/one.js +26 -0
- package/src/get/getBoundingClientRect.js +33 -0
- package/src/get/getDocument.js +11 -0
- package/src/get/getDocumentBody.js +10 -0
- package/src/get/getDocumentElement.js +11 -0
- package/src/get/getDocumentHead.js +10 -0
- package/src/get/getElementAnimationDelay.js +21 -0
- package/src/get/getElementAnimationDelayLegacy.js +21 -0
- package/src/get/getElementAnimationDuration.js +20 -0
- package/src/get/getElementAnimationDurationLegacy.js +21 -0
- package/src/get/getElementStyle.js +18 -0
- package/src/get/getElementTransitionDelay.js +21 -0
- package/src/get/getElementTransitionDelayLegacy.js +21 -0
- package/src/get/getElementTransitionDuration.js +20 -0
- package/src/get/getElementTransitionDurationLegacy.js +21 -0
- package/src/get/getNodeScroll.js +16 -0
- package/src/get/getParentNode.js +24 -0
- package/src/get/getRectRelativeToOffsetParent.js +30 -0
- package/src/get/getUID.js +34 -0
- package/src/get/getWindow.js +20 -0
- package/src/index.js +475 -0
- package/src/is/isArray.js +9 -0
- package/src/is/isCustomElement.js +8 -0
- package/src/is/isDocument.js +9 -0
- package/src/is/isElement.js +9 -0
- package/src/is/isElementInScrollRange.js +18 -0
- package/src/is/isElementInViewport.js +22 -0
- package/src/is/isElementsArray.js +10 -0
- package/src/is/isFunction.js +9 -0
- package/src/is/isHTMLCollection.js +8 -0
- package/src/is/isHTMLElement.js +8 -0
- package/src/is/isHTMLImageElement.js +8 -0
- package/src/is/isMedia.js +12 -0
- package/src/is/isNode.js +8 -0
- package/src/is/isNodeList.js +8 -0
- package/src/is/isRTL.js +9 -0
- package/src/is/isSVGElement.js +8 -0
- package/src/is/isScaledElement.js +15 -0
- package/src/is/isShadowRoot.js +12 -0
- package/src/is/isString.js +8 -0
- package/src/is/isTableElement.js +7 -0
- package/src/is/isWindow.js +9 -0
- package/src/misc/ArrayFrom.js +8 -0
- package/src/misc/Float32ArrayFrom.js +7 -0
- package/src/misc/Float64ArrayFrom.js +7 -0
- package/src/misc/ObjectAssign.js +7 -0
- package/src/misc/ObjectKeys.js +7 -0
- package/src/misc/ObjectValues.js +7 -0
- package/src/misc/OriginalEvent.js +18 -0
- package/src/misc/createElement.js +25 -0
- package/src/misc/createElementNS.js +26 -0
- package/src/misc/data.js +78 -0
- package/src/misc/dispatchEvent.js +8 -0
- package/src/misc/distinct.js +10 -0
- package/src/misc/emulateAnimationEnd.js +37 -0
- package/src/misc/emulateAnimationEndLegacy.js +38 -0
- package/src/misc/emulateTransitionEnd.js +37 -0
- package/src/misc/emulateTransitionEndLegacy.js +38 -0
- package/src/misc/focus.js +8 -0
- package/src/misc/noop.js +3 -0
- package/src/misc/normalizeOptions.js +49 -0
- package/src/misc/normalizeValue.js +32 -0
- package/src/misc/passiveHandler.js +7 -0
- package/src/misc/passiveHandlerLegacy.js +9 -0
- package/src/misc/reflow.js +9 -0
- package/src/misc/setElementStyle.js +10 -0
- package/src/misc/timer.js +78 -0
- package/src/misc/toLowerCase.js +8 -0
- package/src/misc/toUpperCase.js +8 -0
- package/src/misc/tryWrapper.js +11 -0
- package/src/misc/version.js +9 -0
- package/src/selectors/closest.js +16 -0
- package/src/selectors/documentAll.js +8 -0
- package/src/selectors/elementNodes.js +5 -0
- package/src/selectors/getCustomElements.js +18 -0
- package/src/selectors/getElementById.js +11 -0
- package/src/selectors/getElementsByClassName.js +15 -0
- package/src/selectors/getElementsByTagName.js +15 -0
- package/src/selectors/matches.js +10 -0
- package/src/selectors/matchesLegacy.js +23 -0
- package/src/selectors/parentNodes.js +5 -0
- package/src/selectors/querySelector.js +15 -0
- package/src/selectors/querySelectorAll.js +14 -0
- package/src/strings/DOMContentLoadedEvent.js +6 -0
- package/src/strings/DOMMouseScrollEvent.js +6 -0
- package/src/strings/abortEvent.js +6 -0
- package/src/strings/addEventListener.js +6 -0
- package/src/strings/animationDelay.js +6 -0
- package/src/strings/animationDelayLegacy.js +8 -0
- package/src/strings/animationDuration.js +6 -0
- package/src/strings/animationDurationLegacy.js +8 -0
- package/src/strings/animationEndEvent.js +6 -0
- package/src/strings/animationEndEventLegacy.js +8 -0
- package/src/strings/animationName.js +6 -0
- package/src/strings/animationNameLegacy.js +8 -0
- package/src/strings/ariaChecked.js +6 -0
- package/src/strings/ariaDescribedBy.js +6 -0
- package/src/strings/ariaDescription.js +6 -0
- package/src/strings/ariaExpanded.js +6 -0
- package/src/strings/ariaHasPopup.js +6 -0
- package/src/strings/ariaHidden.js +6 -0
- package/src/strings/ariaLabel.js +6 -0
- package/src/strings/ariaLabelledBy.js +6 -0
- package/src/strings/ariaModal.js +6 -0
- package/src/strings/ariaPressed.js +6 -0
- package/src/strings/ariaSelected.js +6 -0
- package/src/strings/ariaValueMax.js +6 -0
- package/src/strings/ariaValueMin.js +6 -0
- package/src/strings/ariaValueNow.js +6 -0
- package/src/strings/ariaValueText.js +6 -0
- package/src/strings/beforeunloadEvent.js +6 -0
- package/src/strings/bezierEasings.js +33 -0
- package/src/strings/blurEvent.js +6 -0
- package/src/strings/changeEvent.js +6 -0
- package/src/strings/contextmenuEvent.js +6 -0
- package/src/strings/errorEvent.js +6 -0
- package/src/strings/focusEvent.js +6 -0
- package/src/strings/focusEvents.js +6 -0
- package/src/strings/focusinEvent.js +6 -0
- package/src/strings/focusoutEvent.js +6 -0
- package/src/strings/gesturechangeEvent.js +6 -0
- package/src/strings/gestureendEvent.js +6 -0
- package/src/strings/gesturestartEvent.js +6 -0
- package/src/strings/keyAlt.js +7 -0
- package/src/strings/keyArrowDown.js +7 -0
- package/src/strings/keyArrowLeft.js +7 -0
- package/src/strings/keyArrowRight.js +7 -0
- package/src/strings/keyArrowUp.js +7 -0
- package/src/strings/keyBackspace.js +7 -0
- package/src/strings/keyCapsLock.js +7 -0
- package/src/strings/keyControl.js +7 -0
- package/src/strings/keyDelete.js +7 -0
- package/src/strings/keyEnter.js +7 -0
- package/src/strings/keyEscape.js +7 -0
- package/src/strings/keyInsert.js +7 -0
- package/src/strings/keyMeta.js +7 -0
- package/src/strings/keyPause.js +7 -0
- package/src/strings/keyScrollLock.js +7 -0
- package/src/strings/keyShift.js +7 -0
- package/src/strings/keySpace.js +7 -0
- package/src/strings/keyTab.js +7 -0
- package/src/strings/keyboardEventKeys.js +27 -0
- package/src/strings/keydownEvent.js +6 -0
- package/src/strings/keypressEvent.js +6 -0
- package/src/strings/keyupEvent.js +6 -0
- package/src/strings/loadEvent.js +6 -0
- package/src/strings/loadstartEvent.js +6 -0
- package/src/strings/mouseClickEvents.js +6 -0
- package/src/strings/mouseHoverEvents.js +6 -0
- package/src/strings/mouseSwipeEvents.js +8 -0
- package/src/strings/mouseclickEvent.js +6 -0
- package/src/strings/mousedblclickEvent.js +6 -0
- package/src/strings/mousedownEvent.js +6 -0
- package/src/strings/mouseenterEvent.js +6 -0
- package/src/strings/mousehoverEvent.js +6 -0
- package/src/strings/mouseinEvent.js +6 -0
- package/src/strings/mouseleaveEvent.js +6 -0
- package/src/strings/mousemoveEvent.js +6 -0
- package/src/strings/mouseoutEvent.js +6 -0
- package/src/strings/mouseoverEvent.js +6 -0
- package/src/strings/mouseupEvent.js +6 -0
- package/src/strings/mousewheelEvent.js +6 -0
- package/src/strings/moveEvent.js +6 -0
- package/src/strings/nativeEvents.js +108 -0
- package/src/strings/offsetHeight.js +6 -0
- package/src/strings/offsetWidth.js +6 -0
- package/src/strings/orientationchangeEvent.js +6 -0
- package/src/strings/pointercancelEvent.js +6 -0
- package/src/strings/pointerdownEvent.js +6 -0
- package/src/strings/pointerleaveEvent.js +6 -0
- package/src/strings/pointermoveEvent.js +6 -0
- package/src/strings/pointerupEvent.js +6 -0
- package/src/strings/readystatechangeEvent.js +6 -0
- package/src/strings/removeEventListener.js +6 -0
- package/src/strings/resetEvent.js +6 -0
- package/src/strings/resizeEvent.js +6 -0
- package/src/strings/scrollEvent.js +6 -0
- package/src/strings/scrollHeight.js +6 -0
- package/src/strings/scrollWidth.js +6 -0
- package/src/strings/selectEvent.js +6 -0
- package/src/strings/selectendEvent.js +6 -0
- package/src/strings/selectstartEvent.js +6 -0
- package/src/strings/submitEvent.js +6 -0
- package/src/strings/touchEvents.js +8 -0
- package/src/strings/touchcancelEvent.js +6 -0
- package/src/strings/touchendEvent.js +6 -0
- package/src/strings/touchmoveEvent.js +6 -0
- package/src/strings/touchstartEvent.js +6 -0
- package/src/strings/transitionDelay.js +6 -0
- package/src/strings/transitionDelayLegacy.js +8 -0
- package/src/strings/transitionDuration.js +6 -0
- package/src/strings/transitionDurationLegacy.js +8 -0
- package/src/strings/transitionEndEvent.js +6 -0
- package/src/strings/transitionEndEventLegacy.js +8 -0
- package/src/strings/transitionProperty.js +7 -0
- package/src/strings/transitionPropertyLegacy.js +12 -0
- package/src/strings/unloadEvent.js +6 -0
- package/src/strings/userAgent.js +7 -0
- package/src/strings/userAgentData.js +8 -0
- package/types/index.d.ts +252 -0
- package/types/module/shorty.ts +249 -0
- package/types/shorty.d.ts +2317 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import transitionDelay from '../strings/transitionDelay';
|
|
2
|
+
import transitionProperty from '../strings/transitionProperty';
|
|
3
|
+
import getElementStyle from './getElementStyle';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Utility to get the computed `transitionDelay`
|
|
7
|
+
* from Element in miliseconds.
|
|
8
|
+
*
|
|
9
|
+
* @param {HTMLElement | Element} element target
|
|
10
|
+
* @return {number} the value in miliseconds
|
|
11
|
+
*/
|
|
12
|
+
export default function getElementTransitionDelay(element) {
|
|
13
|
+
const propertyValue = getElementStyle(element, transitionProperty);
|
|
14
|
+
const delayValue = getElementStyle(element, transitionDelay);
|
|
15
|
+
|
|
16
|
+
const delayScale = delayValue.includes('ms') ? 1 : 1000;
|
|
17
|
+
const duration = propertyValue && propertyValue !== 'none'
|
|
18
|
+
? parseFloat(delayValue) * delayScale : 0;
|
|
19
|
+
|
|
20
|
+
return !Number.isNaN(duration) ? duration : 0;
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import supportTransition from '../boolean/supportTransition';
|
|
2
|
+
import transitionDelay from '../strings/transitionDelayLegacy';
|
|
3
|
+
import transitionProperty from '../strings/transitionPropertyLegacy';
|
|
4
|
+
import getElementStyle from './getElementStyle';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Utility to get the computed `transitionDelay`
|
|
8
|
+
* from Element in miliseconds.
|
|
9
|
+
*
|
|
10
|
+
* @param {HTMLElement | Element} element target
|
|
11
|
+
* @return {number} the value in miliseconds
|
|
12
|
+
*/
|
|
13
|
+
export default function getElementTransitionDelay(element) {
|
|
14
|
+
const propertyValue = getElementStyle(element, transitionProperty);
|
|
15
|
+
const delayValue = getElementStyle(element, transitionDelay);
|
|
16
|
+
const delayScale = delayValue.includes('ms') ? 1 : 1000;
|
|
17
|
+
const duration = supportTransition && propertyValue && propertyValue !== 'none'
|
|
18
|
+
? parseFloat(delayValue) * delayScale : 0;
|
|
19
|
+
|
|
20
|
+
return !Number.isNaN(duration) ? duration : 0;
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import transitionDuration from '../strings/transitionDuration';
|
|
2
|
+
import transitionProperty from '../strings/transitionProperty';
|
|
3
|
+
import getElementStyle from './getElementStyle';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Utility to get the computed `transitionDuration`
|
|
7
|
+
* from Element in miliseconds.
|
|
8
|
+
*
|
|
9
|
+
* @param {HTMLElement | Element} element target
|
|
10
|
+
* @return {number} the value in miliseconds
|
|
11
|
+
*/
|
|
12
|
+
export default function getElementTransitionDuration(element) {
|
|
13
|
+
const propertyValue = getElementStyle(element, transitionProperty);
|
|
14
|
+
const durationValue = getElementStyle(element, transitionDuration);
|
|
15
|
+
const durationScale = durationValue.includes('ms') ? 1 : 1000;
|
|
16
|
+
const duration = propertyValue && propertyValue !== 'none'
|
|
17
|
+
? parseFloat(durationValue) * durationScale : 0;
|
|
18
|
+
|
|
19
|
+
return !Number.isNaN(duration) ? duration : 0;
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import supportTransition from '../boolean/supportTransition';
|
|
2
|
+
import transitionDuration from '../strings/transitionDurationLegacy';
|
|
3
|
+
import transitionProperty from '../strings/transitionPropertyLegacy';
|
|
4
|
+
import getElementStyle from './getElementStyle';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Utility to get the computed `transitionDuration`
|
|
8
|
+
* from Element in miliseconds.
|
|
9
|
+
*
|
|
10
|
+
* @param {HTMLElement | Element} element target
|
|
11
|
+
* @return {number} the value in miliseconds
|
|
12
|
+
*/
|
|
13
|
+
export default function getElementTransitionDuration(element) {
|
|
14
|
+
const propertyValue = getElementStyle(element, transitionProperty);
|
|
15
|
+
const durationValue = getElementStyle(element, transitionDuration);
|
|
16
|
+
const durationScale = durationValue.includes('ms') ? 1 : 1000;
|
|
17
|
+
const duration = supportTransition && propertyValue && propertyValue !== 'none'
|
|
18
|
+
? parseFloat(durationValue) * durationScale : 0;
|
|
19
|
+
|
|
20
|
+
return !Number.isNaN(duration) ? duration : 0;
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns an `{x,y}` object with the target
|
|
3
|
+
* `HTMLElement` / `Node` scroll position.
|
|
4
|
+
*
|
|
5
|
+
* @see https://github.com/floating-ui/floating-ui
|
|
6
|
+
*
|
|
7
|
+
* @param {HTMLElement | Element | Window} element target node / element
|
|
8
|
+
* @returns {{x: number, y: number}} the scroll tuple
|
|
9
|
+
*/
|
|
10
|
+
export default function getNodeScroll(element) {
|
|
11
|
+
const isWin = 'scrollX' in element;
|
|
12
|
+
const x = isWin ? element.scrollX : element.scrollLeft;
|
|
13
|
+
const y = isWin ? element.scrollY : element.scrollTop;
|
|
14
|
+
|
|
15
|
+
return { x, y };
|
|
16
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import getDocumentElement from './getDocumentElement';
|
|
2
|
+
import isShadowRoot from '../is/isShadowRoot';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the `parentNode` also going through `ShadowRoot`.
|
|
6
|
+
* @see https://github.com/floating-ui/floating-ui
|
|
7
|
+
*
|
|
8
|
+
* @param {Node | HTMLElement | Element} node the target node
|
|
9
|
+
* @returns {Node | HTMLElement | Element} the apropriate parent node
|
|
10
|
+
*/
|
|
11
|
+
export default function getParentNode(node) {
|
|
12
|
+
if (node.nodeName === 'HTML') {
|
|
13
|
+
return node;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// this is a quicker (but less type safe) way to save quite some bytes from the bundle
|
|
17
|
+
return (
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
node.assignedSlot // step into the shadow DOM of the parent of a slotted node
|
|
20
|
+
|| node.parentNode // @ts-ignore DOM Element detected
|
|
21
|
+
|| (isShadowRoot(node) ? node.host : null) // ShadowRoot detected
|
|
22
|
+
|| getDocumentElement(node) // fallback
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import isScaledElement from '../is/isScaledElement';
|
|
2
|
+
import getBoundingClientRect from './getBoundingClientRect';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the rect relative to an offset parent.
|
|
6
|
+
* @see https://github.com/floating-ui/floating-ui
|
|
7
|
+
*
|
|
8
|
+
* @param {HTMLElement | Element} element target
|
|
9
|
+
* @param {HTMLElement | Element | Window} offsetParent the container / offset parent
|
|
10
|
+
* @param {{x: number, y: number}} scroll
|
|
11
|
+
* @returns {SHORTER.OffsetRect}
|
|
12
|
+
*/
|
|
13
|
+
export default function getRectRelativeToOffsetParent(element, offsetParent, scroll) {
|
|
14
|
+
const isParentAnElement = offsetParent instanceof HTMLElement;
|
|
15
|
+
const rect = getBoundingClientRect(element, isParentAnElement && isScaledElement(offsetParent));
|
|
16
|
+
const offsets = { x: 0, y: 0 };
|
|
17
|
+
|
|
18
|
+
if (isParentAnElement) {
|
|
19
|
+
const offsetRect = getBoundingClientRect(offsetParent, true);
|
|
20
|
+
offsets.x = offsetRect.x + offsetParent.clientLeft;
|
|
21
|
+
offsets.y = offsetRect.y + offsetParent.clientTop;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
x: rect.left + scroll.x - offsets.x,
|
|
26
|
+
y: rect.top + scroll.y - offsets.y,
|
|
27
|
+
width: rect.width,
|
|
28
|
+
height: rect.height,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
let elementUID = 0;
|
|
2
|
+
let elementMapUID = 0;
|
|
3
|
+
const elementIDMap = new Map();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a unique identifier for popover, tooltip, scrollspy.
|
|
7
|
+
*
|
|
8
|
+
* @param {HTMLElement | Element} element target element
|
|
9
|
+
* @param {string=} key predefined key
|
|
10
|
+
* @returns {number} an existing or new unique ID
|
|
11
|
+
*/
|
|
12
|
+
export default function getUID(element, key) {
|
|
13
|
+
let result = key ? elementUID : elementMapUID;
|
|
14
|
+
|
|
15
|
+
if (key) {
|
|
16
|
+
const elID = getUID(element);
|
|
17
|
+
const elMap = elementIDMap.get(elID) || new Map();
|
|
18
|
+
if (!elementIDMap.has(elID)) {
|
|
19
|
+
elementIDMap.set(elID, elMap);
|
|
20
|
+
}
|
|
21
|
+
if (!elMap.has(key)) {
|
|
22
|
+
elMap.set(key, result);
|
|
23
|
+
elementUID += 1;
|
|
24
|
+
} else result = elMap.get(key);
|
|
25
|
+
} else {
|
|
26
|
+
const elkey = element.id || element;
|
|
27
|
+
|
|
28
|
+
if (!elementIDMap.has(elkey)) {
|
|
29
|
+
elementIDMap.set(elkey, result);
|
|
30
|
+
elementMapUID += 1;
|
|
31
|
+
} else result = elementIDMap.get(elkey);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the `Window` object of a target node.
|
|
3
|
+
* @see https://github.com/floating-ui/floating-ui
|
|
4
|
+
*
|
|
5
|
+
* @param {(Node | HTMLElement | Element | Window)=} node target node
|
|
6
|
+
* @returns {globalThis}
|
|
7
|
+
*/
|
|
8
|
+
export default function getWindow(node) {
|
|
9
|
+
if (node == null) {
|
|
10
|
+
return window;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!(node instanceof Window)) {
|
|
14
|
+
const { ownerDocument } = node;
|
|
15
|
+
return ownerDocument ? ownerDocument.defaultView || window : window;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
return node;
|
|
20
|
+
}
|