From 5827050f2b1485a55609bcb563512d8ae257f3f4 Mon Sep 17 00:00:00 2001 From: Sebastian Schlapkohl Date: Mon, 4 Sep 2023 14:34:52 +0200 Subject: [PATCH] Basic module extended type checking & relative base URLs for createRestfulJsonClient // implemented explicit type checkers for everything isA() supports (except null und undefined, which can be checked with ===) to improve readability and safe on uncompressable strings in source (+unit-tests) // replace occurrences of isA() in source with new explicit type checkers // added "htmlcollection" as newly available type for isA() and getType() // added possibility to set empty or relative baseUrl for createRestfulJsonClient, which get auto-expanded with window.location.origin // upped version to 0.1.6-beta --- dist/animation.js | 2 +- dist/arrays.js | 4 +- dist/arrays.js.map | 2 +- dist/basic.js | 4 +- dist/basic.js.map | 2 +- dist/context.js | 4 +- dist/context.js.map | 2 +- dist/cookies.js | 4 +- dist/cookies.js.map | 2 +- dist/css.js | 4 +- dist/css.js.map | 2 +- dist/elements.js | 4 +- dist/elements.js.map | 2 +- dist/es5-monolith.js | 42 +- dist/events.js | 4 +- dist/events.js.map | 2 +- dist/fonts.js | 2 +- dist/forms.js | 4 +- dist/forms.js.map | 2 +- dist/functions.js | 4 +- dist/functions.js.map | 2 +- dist/images.js | 4 +- dist/images.js.map | 2 +- dist/interaction.js | 4 +- dist/interaction.js.map | 2 +- dist/logging.js | 2 +- dist/navigation.js | 4 +- dist/navigation.js.map | 2 +- dist/objects.js | 4 +- dist/objects.js.map | 2 +- dist/polling.js | 4 +- dist/polling.js.map | 2 +- dist/polyfills.js | 4 +- dist/polyfills.js.map | 2 +- dist/random.js | 4 +- dist/random.js.map | 2 +- dist/requests.js | 4 +- dist/requests.js.map | 2 +- dist/strings.js | 4 +- dist/strings.js.map | 2 +- dist/timers.js | 4 +- dist/timers.js.map | 2 +- dist/urls.js | 2 +- dist/viewport.js | 4 +- dist/viewport.js.map | 2 +- docs/documentation/Animation.html | 4 +- .../Animation_EasingFunctions.html | 4 +- docs/documentation/Animation_transition.html | 4 +- docs/documentation/Arrays.html | 4 +- docs/documentation/Arrays_removeFrom.html | 4 +- docs/documentation/Basic.html | 4 +- docs/documentation/Basic_Deferred.html | 8 +- docs/documentation/Basic_Observable.html | 8 +- docs/documentation/Basic_assert.html | 4 +- docs/documentation/Basic_attempt.html | 4 +- docs/documentation/Basic_getType.html | 9 +- docs/documentation/Basic_hasMembers.html | 4 +- docs/documentation/Basic_hasValue.html | 4 +- docs/documentation/Basic_isA.html | 8 +- docs/documentation/Basic_isArray.html | 292 +++++++++ docs/documentation/Basic_isBigInt.html | 292 +++++++++ docs/documentation/Basic_isBoolean.html | 292 +++++++++ docs/documentation/Basic_isCollection.html | 299 +++++++++ docs/documentation/Basic_isDate.html | 292 +++++++++ docs/documentation/Basic_isDocument.html | 292 +++++++++ docs/documentation/Basic_isElement.html | 8 +- docs/documentation/Basic_isEmpty.html | 4 +- docs/documentation/Basic_isError.html | 292 +++++++++ docs/documentation/Basic_isEventTarget.html | 8 +- docs/documentation/Basic_isFloat.html | 8 +- docs/documentation/Basic_isFunction.html | 292 +++++++++ docs/documentation/Basic_isGenerator.html | 299 +++++++++ docs/documentation/Basic_isInt.html | 8 +- docs/documentation/Basic_isIterator.html | 299 +++++++++ docs/documentation/Basic_isMap.html | 299 +++++++++ docs/documentation/Basic_isNaN.html | 8 +- docs/documentation/Basic_isNodeList.html | 299 +++++++++ docs/documentation/Basic_isNumber.html | 304 ++++++++++ docs/documentation/Basic_isObject.html | 300 +++++++++ docs/documentation/Basic_isPlainObject.html | 8 +- docs/documentation/Basic_isPotentialId.html | 8 +- docs/documentation/Basic_isRegExp.html | 292 +++++++++ docs/documentation/Basic_isSelector.html | 8 +- docs/documentation/Basic_isSet.html | 299 +++++++++ docs/documentation/Basic_isString.html | 292 +++++++++ docs/documentation/Basic_isSymbol.html | 299 +++++++++ docs/documentation/Basic_isWeakMap.html | 299 +++++++++ docs/documentation/Basic_isWeakSet.html | 299 +++++++++ docs/documentation/Basic_isWindow.html | 292 +++++++++ docs/documentation/Basic_minMax.html | 8 +- docs/documentation/Basic_orDefault.html | 4 +- docs/documentation/Basic_size.html | 4 +- docs/documentation/CSS.html | 4 +- docs/documentation/CSS_applyStyles.html | 4 +- docs/documentation/CSS_cssUrlValueToUrl.html | 4 +- docs/documentation/CSS_cssValueToNumber.html | 4 +- docs/documentation/CSS_remByPx.html | 4 +- docs/documentation/Context.html | 4 +- ...xt_browserSupportsHistoryManipulation.html | 4 +- .../Context_contextHasHighDpi.html | 4 +- .../Context_detectAppleDevice.html | 4 +- .../Context_detectInteractionType.html | 4 +- .../Context_getBrowserLanguage.html | 4 +- .../Context_getBrowserLocale.html | 4 +- .../Context_getBrowserScrollbarWidth.html | 4 +- docs/documentation/Context_getLocale.html | 4 +- docs/documentation/Cookies.html | 4 +- docs/documentation/Cookies_getCookie.html | 4 +- docs/documentation/Cookies_getCookies.html | 4 +- docs/documentation/Cookies_removeCookie.html | 4 +- docs/documentation/Cookies_setCookie.html | 4 +- docs/documentation/Elements.html | 4 +- docs/documentation/Elements_createNode.html | 8 +- docs/documentation/Elements_defineNode.html | 8 +- docs/documentation/Elements_find.html | 8 +- docs/documentation/Elements_findOne.html | 8 +- .../documentation/Elements_findTextNodes.html | 8 +- docs/documentation/Elements_getData.html | 8 +- .../Elements_getTextContent.html | 8 +- docs/documentation/Elements_insertNode.html | 8 +- docs/documentation/Elements_isInDom.html | 8 +- .../Elements_measureHiddenDimensions.html | 8 +- docs/documentation/Elements_prime.html | 8 +- docs/documentation/Elements_removeData.html | 8 +- docs/documentation/Elements_replaceNode.html | 8 +- docs/documentation/Elements_setData.html | 8 +- docs/documentation/Events.html | 4 +- docs/documentation/Events_emit.html | 8 +- .../documentation/Events_emitPostMessage.html | 8 +- docs/documentation/Events_fire.html | 8 +- docs/documentation/Events_off.html | 8 +- .../Events_offDetachedElements.html | 8 +- docs/documentation/Events_offPostMessage.html | 8 +- docs/documentation/Events_offSwipe.html | 8 +- docs/documentation/Events_on.html | 8 +- docs/documentation/Events_onDomReady.html | 8 +- docs/documentation/Events_onPostMessage.html | 8 +- docs/documentation/Events_onSwipe.html | 8 +- docs/documentation/Events_once.html | 8 +- docs/documentation/Events_pause.html | 8 +- docs/documentation/Events_resume.html | 8 +- docs/documentation/Fonts.html | 4 +- docs/documentation/Fonts_waitForWebfonts.html | 4 +- docs/documentation/Forms.html | 4 +- .../documentation/Forms_formDataToObject.html | 4 +- .../documentation/Forms_objectToFormData.html | 4 +- docs/documentation/Functions.html | 4 +- docs/documentation/Functions_debounce.html | 4 +- docs/documentation/Functions_defer.html | 4 +- docs/documentation/Functions_kwargs.html | 4 +- docs/documentation/Functions_throttle.html | 4 +- docs/documentation/Images.html | 4 +- docs/documentation/Images_loaded.html | 4 +- docs/documentation/Images_preload.html | 4 +- docs/documentation/Interaction.html | 4 +- .../Interaction_createSelection.html | 4 +- .../Interaction_disableSelection.html | 4 +- .../Interaction_enableSelection.html | 4 +- ...nteraction_obfuscatePrivateMailToLink.html | 4 +- .../Interaction_obfuscatePrivateTelLink.html | 4 +- .../Interaction_removeSelections.html | 4 +- .../Interaction_setTappedState.html | 4 +- .../Interaction_setupAutoTappedStates.html | 4 +- docs/documentation/Logging.html | 4 +- docs/documentation/Logging_err.html | 4 +- docs/documentation/Logging_log.html | 4 +- docs/documentation/Logging_warn.html | 4 +- docs/documentation/Logging_xlog.html | 4 +- docs/documentation/Navigation.html | 4 +- .../Navigation_changeCurrentUrl.html | 4 +- .../Navigation_offHistoryChange.html | 4 +- .../Navigation_onHistoryChange.html | 4 +- docs/documentation/Navigation_openTab.html | 4 +- docs/documentation/Navigation_openWindow.html | 4 +- docs/documentation/Navigation_redirect.html | 4 +- docs/documentation/Navigation_reload.html | 4 +- docs/documentation/Objects.html | 4 +- docs/documentation/Objects_clone.html | 4 +- docs/documentation/Objects_merge.html | 4 +- docs/documentation/Polling.html | 4 +- docs/documentation/Polling_poll.html | 4 +- docs/documentation/Polling_unpoll.html | 4 +- docs/documentation/Polyfills.html | 4 +- .../Polyfills_polyfillArrayAt.html | 4 +- .../Polyfills_polyfillCustomEvent.html | 4 +- .../Polyfills_polyfillElementMatches.html | 4 +- .../Polyfills_polyfillFetch.html | 4 +- docs/documentation/Random.html | 4 +- docs/documentation/Random_randomNumber.html | 4 +- docs/documentation/Random_randomUuid.html | 4 +- docs/documentation/Requests.html | 4 +- .../Requests_createCssRequest.html | 8 +- .../Requests_createFetchRequest.html | 4 +- .../Requests_createHtmlRequest.html | 8 +- .../Requests_createJsRequest.html | 8 +- .../Requests_createJsonRequest.html | 4 +- .../Requests_createRestfulJsonClient.html | 14 +- docs/documentation/Requests_visitUrl.html | 8 +- docs/documentation/Strings.html | 4 +- docs/documentation/Strings_concat.html | 4 +- docs/documentation/Strings_format.html | 4 +- docs/documentation/Strings_maskForHtml.html | 4 +- docs/documentation/Strings_maskForRegEx.html | 4 +- .../Strings_maskForSelector.html | 4 +- docs/documentation/Strings_replace.html | 4 +- docs/documentation/Strings_slugify.html | 4 +- docs/documentation/Strings_truncate.html | 4 +- .../documentation/Strings_unmaskFromHtml.html | 4 +- docs/documentation/Timers.html | 4 +- .../Timers_cancelAnimationFrame.html | 4 +- docs/documentation/Timers_countermand.html | 4 +- docs/documentation/Timers_loop.html | 4 +- docs/documentation/Timers_ploop.html | 4 +- docs/documentation/Timers_pschedule.html | 4 +- .../Timers_requestAnimationFrame.html | 4 +- docs/documentation/Timers_reschedule.html | 4 +- docs/documentation/Timers_schedule.html | 4 +- docs/documentation/Timers_waitForRepaint.html | 4 +- docs/documentation/Urls.html | 4 +- docs/documentation/Urls_addCacheBuster.html | 4 +- docs/documentation/Urls_addNextParameter.html | 4 +- .../Urls_evaluateBaseDomain.html | 4 +- docs/documentation/Urls_urlAnchor.html | 4 +- docs/documentation/Urls_urlParameter.html | 4 +- docs/documentation/Urls_urlParameters.html | 4 +- docs/documentation/Viewport.html | 4 +- docs/documentation/Viewport_isInViewport.html | 4 +- docs/documentation/Viewport_scrollTo.html | 4 +- docs/documentation/animation.js.html | 4 +- docs/documentation/arrays.js.html | 16 +- docs/documentation/basic.js.html | 574 ++++++++++++++++-- docs/documentation/context.js.html | 16 +- docs/documentation/cookies.js.html | 8 +- docs/documentation/css.js.html | 8 +- docs/documentation/elements.js.html | 31 +- docs/documentation/events.js.html | 43 +- docs/documentation/fonts.js.html | 4 +- docs/documentation/forms.js.html | 12 +- docs/documentation/functions.js.html | 14 +- docs/documentation/global.html | 26 +- docs/documentation/images.js.html | 12 +- docs/documentation/index.html | 4 +- docs/documentation/interaction.js.html | 14 +- docs/documentation/logging.js.html | 4 +- docs/documentation/navigation.js.html | 14 +- docs/documentation/objects.js.html | 10 +- docs/documentation/polling.js.html | 14 +- docs/documentation/polyfills.js.html | 12 +- docs/documentation/random.js.html | 12 +- docs/documentation/requests.js.html | 13 +- docs/documentation/strings.js.html | 12 +- docs/documentation/timers.js.html | 20 +- docs/documentation/urls.js.html | 4 +- docs/documentation/viewport.js.html | 10 +- docs/examples/lib/annex/dist/animation.js | 2 +- docs/examples/lib/annex/dist/arrays.js | 4 +- docs/examples/lib/annex/dist/arrays.js.map | 2 +- docs/examples/lib/annex/dist/basic.js | 4 +- docs/examples/lib/annex/dist/basic.js.map | 2 +- docs/examples/lib/annex/dist/context.js | 4 +- docs/examples/lib/annex/dist/context.js.map | 2 +- docs/examples/lib/annex/dist/cookies.js | 4 +- docs/examples/lib/annex/dist/cookies.js.map | 2 +- docs/examples/lib/annex/dist/css.js | 4 +- docs/examples/lib/annex/dist/css.js.map | 2 +- docs/examples/lib/annex/dist/elements.js | 4 +- docs/examples/lib/annex/dist/elements.js.map | 2 +- docs/examples/lib/annex/dist/es5-monolith.js | 42 +- docs/examples/lib/annex/dist/events.js | 4 +- docs/examples/lib/annex/dist/events.js.map | 2 +- docs/examples/lib/annex/dist/fonts.js | 2 +- docs/examples/lib/annex/dist/forms.js | 4 +- docs/examples/lib/annex/dist/forms.js.map | 2 +- docs/examples/lib/annex/dist/functions.js | 4 +- docs/examples/lib/annex/dist/functions.js.map | 2 +- docs/examples/lib/annex/dist/images.js | 4 +- docs/examples/lib/annex/dist/images.js.map | 2 +- docs/examples/lib/annex/dist/interaction.js | 4 +- .../lib/annex/dist/interaction.js.map | 2 +- docs/examples/lib/annex/dist/logging.js | 2 +- docs/examples/lib/annex/dist/navigation.js | 4 +- .../examples/lib/annex/dist/navigation.js.map | 2 +- docs/examples/lib/annex/dist/objects.js | 4 +- docs/examples/lib/annex/dist/objects.js.map | 2 +- docs/examples/lib/annex/dist/polling.js | 4 +- docs/examples/lib/annex/dist/polling.js.map | 2 +- docs/examples/lib/annex/dist/polyfills.js | 4 +- docs/examples/lib/annex/dist/polyfills.js.map | 2 +- docs/examples/lib/annex/dist/random.js | 4 +- docs/examples/lib/annex/dist/random.js.map | 2 +- docs/examples/lib/annex/dist/requests.js | 4 +- docs/examples/lib/annex/dist/requests.js.map | 2 +- docs/examples/lib/annex/dist/strings.js | 4 +- docs/examples/lib/annex/dist/strings.js.map | 2 +- docs/examples/lib/annex/dist/timers.js | 4 +- docs/examples/lib/annex/dist/timers.js.map | 2 +- docs/examples/lib/annex/dist/urls.js | 2 +- docs/examples/lib/annex/dist/viewport.js | 4 +- docs/examples/lib/annex/dist/viewport.js.map | 2 +- docs/examples/lib/annex/source/arrays.js | 12 +- docs/examples/lib/annex/source/basic.js | 570 +++++++++++++++-- docs/examples/lib/annex/source/context.js | 12 +- docs/examples/lib/annex/source/cookies.js | 4 +- docs/examples/lib/annex/source/css.js | 4 +- docs/examples/lib/annex/source/elements.js | 27 +- docs/examples/lib/annex/source/events.js | 39 +- docs/examples/lib/annex/source/forms.js | 8 +- docs/examples/lib/annex/source/functions.js | 10 +- docs/examples/lib/annex/source/images.js | 8 +- docs/examples/lib/annex/source/interaction.js | 10 +- docs/examples/lib/annex/source/navigation.js | 10 +- docs/examples/lib/annex/source/objects.js | 6 +- docs/examples/lib/annex/source/polling.js | 10 +- docs/examples/lib/annex/source/polyfills.js | 8 +- docs/examples/lib/annex/source/random.js | 8 +- docs/examples/lib/annex/source/requests.js | 9 +- docs/examples/lib/annex/source/strings.js | 8 +- docs/examples/lib/annex/source/timers.js | 16 +- docs/examples/lib/annex/source/viewport.js | 6 +- package.json | 2 +- source/arrays.js | 12 +- source/basic.js | 570 +++++++++++++++-- source/context.js | 12 +- source/cookies.js | 4 +- source/css.js | 4 +- source/elements.js | 27 +- source/events.js | 39 +- source/forms.js | 8 +- source/functions.js | 10 +- source/images.js | 8 +- source/interaction.js | 10 +- source/navigation.js | 10 +- source/objects.js | 6 +- source/polling.js | 10 +- source/polyfills.js | 8 +- source/random.js | 8 +- source/requests.js | 9 +- source/strings.js | 8 +- source/timers.js | 16 +- source/viewport.js | 6 +- test/annex/basic.js | 441 +++++++++++++- 341 files changed, 9274 insertions(+), 1044 deletions(-) create mode 100644 docs/documentation/Basic_isArray.html create mode 100644 docs/documentation/Basic_isBigInt.html create mode 100644 docs/documentation/Basic_isBoolean.html create mode 100644 docs/documentation/Basic_isCollection.html create mode 100644 docs/documentation/Basic_isDate.html create mode 100644 docs/documentation/Basic_isDocument.html create mode 100644 docs/documentation/Basic_isError.html create mode 100644 docs/documentation/Basic_isFunction.html create mode 100644 docs/documentation/Basic_isGenerator.html create mode 100644 docs/documentation/Basic_isIterator.html create mode 100644 docs/documentation/Basic_isMap.html create mode 100644 docs/documentation/Basic_isNodeList.html create mode 100644 docs/documentation/Basic_isNumber.html create mode 100644 docs/documentation/Basic_isObject.html create mode 100644 docs/documentation/Basic_isRegExp.html create mode 100644 docs/documentation/Basic_isSet.html create mode 100644 docs/documentation/Basic_isString.html create mode 100644 docs/documentation/Basic_isSymbol.html create mode 100644 docs/documentation/Basic_isWeakMap.html create mode 100644 docs/documentation/Basic_isWeakSet.html create mode 100644 docs/documentation/Basic_isWindow.html diff --git a/dist/animation.js b/dist/animation.js index 4bbebdef..e9992cee 100644 --- a/dist/animation.js +++ b/dist/animation.js @@ -1,5 +1,5 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Animation diff --git a/dist/arrays.js b/dist/arrays.js index 5e0594bb..660e4bc6 100644 --- a/dist/arrays.js +++ b/dist/arrays.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Arrays */ -const MODULE_NAME="Arrays";import{assert,isA,isPlainObject,orDefault}from"./basic.js";export function removeFrom(r,e,s=null){if(assert(isA(r,"array"),"Arrays:remove | target is no array"),isA(e,"number")&&!0!==s){e=parseInt(e,10),s=orDefault(s,null,"int");const t=(r=r.slice(0)).slice((s||e)+1||r.length);return r.length=e<0?r.length+e:e,r.concat(t)}if(isA(e,"string"))return r.reduce(((r,s)=>(`${s}`!==e&&r.push(s),r)),[]);{let t;return t=isPlainObject(e)?Object.values(e):isA(e,"map")||isA(e,"set")?Array.from(e.values()):Array.from(e),t.length>0&&!0!==s?t.reduce(((r,e)=>r=removeFrom(r,e,!0)),[...r]):r.reduce(((r,s)=>(s!==e&&r.push(s),r)),[])}} +const MODULE_NAME="Arrays";import{assert,isArray,isNumber,isString,isMap,isSet,isPlainObject,orDefault}from"./basic.js";export function removeFrom(r,e,s=null){if(assert(isArray(r),"Arrays:remove | target is no array"),isNumber(e)&&!0!==s){e=parseInt(e,10),s=orDefault(s,null,"int");const t=(r=r.slice(0)).slice((s||e)+1||r.length);return r.length=e<0?r.length+e:e,r.concat(t)}if(isString(e))return r.reduce(((r,s)=>(`${s}`!==e&&r.push(s),r)),[]);{let t;return t=isPlainObject(e)?Object.values(e):isMap(e)||isSet(e)?Array.from(e.values()):Array.from(e),t.length>0&&!0!==s?t.reduce(((r,e)=>r=removeFrom(r,e,!0)),[...r]):r.reduce(((r,s)=>(s!==e&&r.push(s),r)),[])}} //# sourceMappingURL=arrays.js.map diff --git a/dist/arrays.js.map b/dist/arrays.js.map index a2b8b029..2297f371 100644 --- a/dist/arrays.js.map +++ b/dist/arrays.js.map @@ -1 +1 @@ -{"version":3,"file":"arrays.js","names":["MODULE_NAME","assert","isA","isPlainObject","orDefault","removeFrom","target","from","to","parseInt","rest","slice","length","concat","reduce","reducedArray","item","push","fromList","Object","values","Array"],"sources":["arrays.js"],"mappings":";;;AAQA,MAAMA,YAAc,gBAMZC,OAAQC,IAAKC,cAAeC,cAAgB,oBA8D7C,SAASC,WAAWC,EAAQC,EAAMC,EAAG,MAG3C,GAFAP,OAAOC,IAAII,EAAQ,SAAU,sCAEzBJ,IAAIK,EAAM,YAAqB,IAAPC,EAAc,CACzCD,EAAOE,SAASF,EAAM,IACtBC,EAAKJ,UAAUI,EAAI,KAAM,OAGzB,MAAME,GADNJ,EAASA,EAAOK,MAAM,IACFA,OAAOH,GAAMD,GAAQ,GAAKD,EAAOM,QAGrD,OAFAN,EAAOM,OAAUL,EAAO,EAAMD,EAAOM,OAASL,EAAQA,EAE/CD,EAAOO,OAAOH,EACtB,CAAO,GAAIR,IAAIK,EAAM,UACpB,OAAOD,EAAOQ,QAAO,CAACC,EAAcC,KAC/B,GAAGA,MAAWT,GACjBQ,EAAaE,KAAKD,GAEZD,IACL,IACG,CACN,IAAIG,EAWJ,OATCA,EADGf,cAAcI,GACNY,OAAOC,OAAOb,GACfL,IAAIK,EAAM,QAEVL,IAAIK,EAAM,OADTc,MAAMd,KAAKA,EAAKa,UAIhBC,MAAMd,KAAKA,GAGlBW,EAASN,OAAS,IAAc,IAAPJ,EACtBU,EAASJ,QAAO,CAACC,EAAcC,IACrCD,EAAeV,WAAWU,EAAcC,GAAM,IAE5C,IAAIV,IAEAA,EAAOQ,QAAO,CAACC,EAAcC,KAC/BA,IAAST,GACZQ,EAAaE,KAAKD,GAEZD,IACL,GAEL,CACD","sourcesContent":["/*!\n * Module Arrays\n */\n\n/**\n * @namespace Arrays\n */\n\nconst MODULE_NAME = 'Arrays';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isA, isPlainObject, orDefault} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Arrays:removeFrom\n */\n\n/**\n * Removes Elements from an Array, where to and from are inclusive.\n * If you only provide \"from\", that exact index is removed.\n *\n * Does not modify the original.\n *\n * Keep in mind, that \"from\" should normally be smaller than \"to\" to slice from left to right. This means that the elements\n * indexed by \"from\" and \"to\" should have the right order. For example: [1,2,3,4]. Here from=-1 and to=-3 are illegal since\n * \"from\" references a later element than \"to\", but there are also viable examples where \"from\" is numerically bigger. If we\n * use from=2 and to=-1, \"from\" is numerically bigger, but references an earlier element than -1 (which is the last element),\n * which is totally okay. Just make sure \"from\" comes before \"to\" in the element's order.\n *\n * If you provide a string for \"from\" everything matching that string with its string representation will be removed\n * (you can provide stringification for objects via the toString method, see:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString).\n *\n * Everything else (except collections) provided for \"from\" will determine the element(s) to remove by identity (===).\n *\n * If you want to remove several elements at once, you may provide an iterable collection as \"from\" and\n * This also makes it possible to actually remove numbers from an array by identity: define the number(s) as an array,\n * to signal, that these are no indices. If you need to remove a collection from the array by reference, either put\n * the collection in an array or set \"to\" to true, to force the collection being treated as a reference.\n *\n * Iterable collections, usable in \"from\" in the sense of this method are:\n * - PlainObject (values)\n * - Array\n * - Set\n * - Map (values)\n * To remove these by reference from target, instead of iterating them, set \"to\" to true.\n *\n * @param {Array} target - the array to remove elements from\n * @param {*} from - numerical index to start removing from (can also be negative to start counting from back), a string to identify elements to remove by their string representation or any other value identifying elements to remove by identity, if this is an iterable collection, the collection is iterated instead of being treated as a reference, enforce treatment as a reference, by setting \"to\" to true\n * @param {?Number|Boolean} [to=null] - index to end removing (can also be negative to end counting from back), if true, \"from\" defines a given iterable collection to be removed by reference, instead of removing the contained values, with this you can remove an array from an array for example\n * @throws error if target is not an array\n * @returns {Array} new array without index/range/matches\n *\n * @memberof Arrays:removeFrom\n * @alias removeFrom\n * @example\n * removeFrom([1, 2, 3, 4, 5], 0, 2);\n * => [4, 5]\n * removeFrom([1, 2, 3, 4, 5], -3, -1);\n * => [1, 2]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], 'b');\n * => [b, 1]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], b);\n * => [{a : 'b', toString(){ return 'b'; }}, 'b', 1]\n * removeFrom([true, true, false, true, true], true)\n * => [false]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1, 2], ['b', b, 2]);\n * => [1]\n */\nexport function removeFrom(target, from, to=null){\n\tassert(isA(target, 'array'), `${MODULE_NAME}:remove | target is no array`);\n\n\tif( isA(from, 'number') && (to !== true) ){\n\t\tfrom = parseInt(from, 10);\n\t\tto = orDefault(to, null, 'int');\n\n\t\ttarget = target.slice(0);\n\t\tconst rest = target.slice((to || from) + 1 || target.length);\n\t\ttarget.length = (from < 0) ? (target.length + from) : from;\n\n\t\treturn target.concat(rest);\n\t} else if( isA(from, 'string') ){\n\t\treturn target.reduce((reducedArray, item) => {\n\t\t\tif( `${item}` !== from ){\n\t\t\t\treducedArray.push(item);\n\t\t\t}\n\t\t\treturn reducedArray;\n\t\t}, []);\n\t} else {\n\t\tlet fromList;\n\t\tif( isPlainObject(from) ){\n\t\t\tfromList = Object.values(from);\n\t\t} else if( isA(from, 'map') ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else if( isA(from, 'set') ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else {\n\t\t\tfromList = Array.from(from);\n\t\t}\n\n\t\tif( (fromList.length > 0) && (to !== true) ){\n\t\t\treturn fromList.reduce((reducedArray, item) => {\n\t\t\t\treducedArray = removeFrom(reducedArray, item, true);\n\t\t\t\treturn reducedArray;\n\t\t\t}, [...target]);\n\t\t} else {\n\t\t\treturn target.reduce((reducedArray, item) => {\n\t\t\t\tif( item !== from ){\n\t\t\t\t\treducedArray.push(item);\n\t\t\t\t}\n\t\t\t\treturn reducedArray;\n\t\t\t}, []);\n\t\t}\n\t}\n}\n"]} \ No newline at end of file +{"version":3,"file":"arrays.js","names":["MODULE_NAME","assert","isArray","isNumber","isString","isMap","isSet","isPlainObject","orDefault","removeFrom","target","from","to","parseInt","rest","slice","length","concat","reduce","reducedArray","item","push","fromList","Object","values","Array"],"sources":["arrays.js"],"mappings":";;;AAQA,MAAMA,YAAc,gBAMZC,OAAQC,QAASC,SAAUC,SAAUC,MAAOC,MAAOC,cAAeC,cAAgB,oBA8DnF,SAASC,WAAWC,EAAQC,EAAMC,EAAG,MAG3C,GAFAX,OAAOC,QAAQQ,GAAS,sCAEpBP,SAASQ,KAAiB,IAAPC,EAAc,CACpCD,EAAOE,SAASF,EAAM,IACtBC,EAAKJ,UAAUI,EAAI,KAAM,OAGzB,MAAME,GADNJ,EAASA,EAAOK,MAAM,IACFA,OAAOH,GAAMD,GAAQ,GAAKD,EAAOM,QAGrD,OAFAN,EAAOM,OAAUL,EAAO,EAAMD,EAAOM,OAASL,EAAQA,EAE/CD,EAAOO,OAAOH,EACtB,CAAO,GAAIV,SAASO,GACnB,OAAOD,EAAOQ,QAAO,CAACC,EAAcC,KAC/B,GAAGA,MAAWT,GACjBQ,EAAaE,KAAKD,GAEZD,IACL,IACG,CACN,IAAIG,EAWJ,OATCA,EADGf,cAAcI,GACNY,OAAOC,OAAOb,GACfN,MAAMM,IAENL,MAAMK,GADLc,MAAMd,KAAKA,EAAKa,UAIhBC,MAAMd,KAAKA,GAGlBW,EAASN,OAAS,IAAc,IAAPJ,EACtBU,EAASJ,QAAO,CAACC,EAAcC,IACrCD,EAAeV,WAAWU,EAAcC,GAAM,IAE5C,IAAIV,IAEAA,EAAOQ,QAAO,CAACC,EAAcC,KAC/BA,IAAST,GACZQ,EAAaE,KAAKD,GAEZD,IACL,GAEL,CACD","sourcesContent":["/*!\n * Module Arrays\n */\n\n/**\n * @namespace Arrays\n */\n\nconst MODULE_NAME = 'Arrays';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isArray, isNumber, isString, isMap, isSet, isPlainObject, orDefault} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Arrays:removeFrom\n */\n\n/**\n * Removes Elements from an Array, where to and from are inclusive.\n * If you only provide \"from\", that exact index is removed.\n *\n * Does not modify the original.\n *\n * Keep in mind, that \"from\" should normally be smaller than \"to\" to slice from left to right. This means that the elements\n * indexed by \"from\" and \"to\" should have the right order. For example: [1,2,3,4]. Here from=-1 and to=-3 are illegal since\n * \"from\" references a later element than \"to\", but there are also viable examples where \"from\" is numerically bigger. If we\n * use from=2 and to=-1, \"from\" is numerically bigger, but references an earlier element than -1 (which is the last element),\n * which is totally okay. Just make sure \"from\" comes before \"to\" in the element's order.\n *\n * If you provide a string for \"from\" everything matching that string with its string representation will be removed\n * (you can provide stringification for objects via the toString method, see:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString).\n *\n * Everything else (except collections) provided for \"from\" will determine the element(s) to remove by identity (===).\n *\n * If you want to remove several elements at once, you may provide an iterable collection as \"from\" and\n * This also makes it possible to actually remove numbers from an array by identity: define the number(s) as an array,\n * to signal, that these are no indices. If you need to remove a collection from the array by reference, either put\n * the collection in an array or set \"to\" to true, to force the collection being treated as a reference.\n *\n * Iterable collections, usable in \"from\" in the sense of this method are:\n * - PlainObject (values)\n * - Array\n * - Set\n * - Map (values)\n * To remove these by reference from target, instead of iterating them, set \"to\" to true.\n *\n * @param {Array} target - the array to remove elements from\n * @param {*} from - numerical index to start removing from (can also be negative to start counting from back), a string to identify elements to remove by their string representation or any other value identifying elements to remove by identity, if this is an iterable collection, the collection is iterated instead of being treated as a reference, enforce treatment as a reference, by setting \"to\" to true\n * @param {?Number|Boolean} [to=null] - index to end removing (can also be negative to end counting from back), if true, \"from\" defines a given iterable collection to be removed by reference, instead of removing the contained values, with this you can remove an array from an array for example\n * @throws error if target is not an array\n * @returns {Array} new array without index/range/matches\n *\n * @memberof Arrays:removeFrom\n * @alias removeFrom\n * @example\n * removeFrom([1, 2, 3, 4, 5], 0, 2);\n * => [4, 5]\n * removeFrom([1, 2, 3, 4, 5], -3, -1);\n * => [1, 2]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], 'b');\n * => [b, 1]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], b);\n * => [{a : 'b', toString(){ return 'b'; }}, 'b', 1]\n * removeFrom([true, true, false, true, true], true)\n * => [false]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1, 2], ['b', b, 2]);\n * => [1]\n */\nexport function removeFrom(target, from, to=null){\n\tassert(isArray(target), `${MODULE_NAME}:remove | target is no array`);\n\n\tif( isNumber(from) && (to !== true) ){\n\t\tfrom = parseInt(from, 10);\n\t\tto = orDefault(to, null, 'int');\n\n\t\ttarget = target.slice(0);\n\t\tconst rest = target.slice((to || from) + 1 || target.length);\n\t\ttarget.length = (from < 0) ? (target.length + from) : from;\n\n\t\treturn target.concat(rest);\n\t} else if( isString(from) ){\n\t\treturn target.reduce((reducedArray, item) => {\n\t\t\tif( `${item}` !== from ){\n\t\t\t\treducedArray.push(item);\n\t\t\t}\n\t\t\treturn reducedArray;\n\t\t}, []);\n\t} else {\n\t\tlet fromList;\n\t\tif( isPlainObject(from) ){\n\t\t\tfromList = Object.values(from);\n\t\t} else if( isMap(from) ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else if( isSet(from) ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else {\n\t\t\tfromList = Array.from(from);\n\t\t}\n\n\t\tif( (fromList.length > 0) && (to !== true) ){\n\t\t\treturn fromList.reduce((reducedArray, item) => {\n\t\t\t\treducedArray = removeFrom(reducedArray, item, true);\n\t\t\t\treturn reducedArray;\n\t\t\t}, [...target]);\n\t\t} else {\n\t\t\treturn target.reduce((reducedArray, item) => {\n\t\t\t\tif( item !== from ){\n\t\t\t\t\treducedArray.push(item);\n\t\t\t\t}\n\t\t\t\treturn reducedArray;\n\t\t\t}, []);\n\t\t}\n\t}\n}\n"]} \ No newline at end of file diff --git a/dist/basic.js b/dist/basic.js index b50dcfdd..b3be1143 100644 --- a/dist/basic.js +++ b/dist/basic.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Basic */ -const MODULE_NAME="Basic";import{log,warn}from"./logging.js";export function assert(t,e){if(!t)throw e=orDefault(e,"assert exception: assertion failed","str"),new Error(e)}export function attempt(t){assert(isA(t,"function"),"Basic:attempt | closure is no function");try{t()}catch(t){return!1}return!0}export function hasValue(){let t=!0;return Array.from(arguments).forEach((e=>{t&&=null!=e})),t}export function size(t,e=!0){if(isA(t?.values,"function"))return Array.from(t.values()).length;let r;switch(getType(t)){case"array":r=t.length;break;case"set":case"map":r=t.size;break;case"iterator":r=Array.from(t).length;break;case"string":r=e?[...t].length:t.length;break;case"object":r=Object.values(t).length;break;default:r=null}return r}export function isEmpty(){let t=!0,e=[void 0,null,"",0];return Array.from(arguments).forEach((t=>{isA(t?.__additionalEmptyValues__,"array")&&(e=e.concat(t.__additionalEmptyValues__))})),e=Array.from(new Set(e)),Array.from(arguments).forEach((r=>{t&&!isA(r?.__additionalEmptyValues__,"array")&&(t=e.includes(r),t||(t=0===size(r)))})),t}export function hasMembers(t,e,r=!1){e=orDefault(e,[],"arr"),r=orDefault(r,!1,"bool");let n=!0;return e.forEach((e=>{hasValue(t[`${e}`])||(r&&log().info(`Basic:hasMembers | missing member ${e}`),n=!1)})),n}export function orDefault(t,e,r=null,n=null){return n=hasValue(n)?[].concat(n):[],hasValue(r)?!isA(r,"function")&&["str","string","int","integer","bool","boolean","float","arr","array"].includes(`${r.toLowerCase()}`)?(r=`${r}`.toLowerCase(),["str","string"].includes(r)?r=function(t){return`${t}`}:["int","integer"].includes(r)?r=function(t){return parseInt(t,10)}:["bool","boolean"].includes(r)?r=function(t){return!!t}:"float"===r?r=function(t){return parseFloat(t)}:["arr","array"].includes(r)&&(r=function(t){return[].concat(t)})):isA(r,"function")||(r=function(t){return t}):r=function(t){return t},!hasValue(t)||n.includes(t)?e:r(t)}export function getType(t){if(!hasValue(t))return`${t}`.toLowerCase();const e=Object.prototype.toString.call(t).slice(8,-1).toLowerCase();return"generatorfunction"===e?"function":"document"===e?"htmldocument":"element"===e||/^html.*element$/.test(e)?"htmlelement":/^.*iterator$/.test(e)?"iterator":e.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/)?e:"object"==typeof t||"function"==typeof t?"object":typeof t}export function isA(t,e){return["undefined","null","boolean","number","bigint","string","symbol","function","object","array","date","error","generator","iterator","regexp","set","weakset","map","weakmap","htmldocument","htmlelement","nodelist","window"].includes(`${e}`.toLowerCase())?getType(t)===`${e}`.toLowerCase():(warn(`Basic:isA | "${e}" is not a recognized type`),!1)}export function isInt(t){return parseInt(t,10)===t}export function isFloat(t){return parseFloat(t)===t}export function isPlainObject(t){return isA(t,"object")&&hasValue(t)&&t.constructor===Object&&"[object Object]"===Object.prototype.toString.call(t)}export function isNaN(t,e=!0){return(e=orDefault(e,!0,"bool"))?t!=t:isNaN(t)}export function isElement(t){return isA(t,"htmlelement")}export function isEventTarget(t){return hasValue(t)&&isA(t.addEventListener,"function")&&isA(t.removeEventListener,"function")&&isA(t.dispatchEvent,"function")}export function isSelector(t){t=orDefault(t,0,"str");const e=document.createDocumentFragment();try{e.querySelector(t)}catch(t){return!1}return!0}export function isPotentialId(t,e="",r="[1-9][0-9]*",n="",s=!0){t=`${t}`,e=orDefault(e,"","str"),r=orDefault(r,"[1-9][0-9]*","str"),n=orDefault(n,"","str");const o=t=>`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&");let i;i=(s=orDefault(s,!0,"bool"))?new RegExp(`^${o(e)}(${r})${o(n)}$`):new RegExp(`^${e}(${r})${n}$`);const a=i.exec(t);return!!hasValue(a)&&a[1]}export function minMax(t,e,r){return assert(t<=r,"Basic:minMax | min can not be larger than max"),er?r:e}export class Deferred{constructor(){const t="fulfilled",e="rejected";this.resolve=null,this.reject=null,this.provision=null,this.status="pending",this.isSettled=()=>[t,e].includes(this.status),this.promise=new Promise(((r,n)=>{this.resolve=e=>{this.status=t,r(e)},this.reject=t=>{this.status=e,n(t)}}))}then(t){return this.promise.then(t)}catch(t){return this.promise.catch(t)}finally(t){return this.promise.finally(t)}}export class Observable{constructor(t){this.__className__="Observable",this._value=t,this._subscriptions=[]}getValue(){return this._value}setValue(t,e=!1){const r=this._value,n=r!==t;this._value=t,(n||e)&&this._subscriptions.forEach((e=>e(t,r)))}subscribe(t){return assert(isA(t,"function"),`Basic:${this.__className__}.subscribe | subscription must be function`),this._subscriptions.indexOf(t)<0&&(this._subscriptions=[...this._subscriptions,t]),t}unsubscribe(t){this._subscriptions=this._subscriptions.filter((e=>e!==t))}toString(){return`${this._value}`}} +const MODULE_NAME="Basic";import{log,warn}from"./logging.js";export function assert(t,e){if(!t)throw e=orDefault(e,"assert exception: assertion failed","str"),new Error(e)}export function attempt(t){assert(isFunction(t),"Basic:attempt | closure is no function");try{t()}catch(t){return!1}return!0}export function hasValue(){let t=!0;return Array.from(arguments).forEach((e=>{t&&=null!=e})),t}export function size(t,e=!0){if(isFunction(t?.values))return Array.from(t.values()).length;let r;switch(getType(t)){case"array":r=t.length;break;case"set":case"map":r=t.size;break;case"iterator":r=Array.from(t).length;break;case"string":r=e?[...t].length:t.length;break;case"object":r=Object.values(t).length;break;default:r=null}return r}export function isEmpty(){let t=!0,e=[void 0,null,"",0];return Array.from(arguments).forEach((t=>{isArray(t?.__additionalEmptyValues__)&&(e=e.concat(t.__additionalEmptyValues__))})),e=Array.from(new Set(e)),Array.from(arguments).forEach((r=>{t&&!isArray(r?.__additionalEmptyValues__)&&(t=e.includes(r),t||(t=0===size(r)))})),t}export function hasMembers(t,e,r=!1){e=orDefault(e,[],"arr"),r=orDefault(r,!1,"bool");let n=!0;return e.forEach((e=>{hasValue(t[`${e}`])||(r&&log().info(`Basic:hasMembers | missing member ${e}`),n=!1)})),n}export function orDefault(t,e,r=null,n=null){return n=hasValue(n)?[].concat(n):[],hasValue(r)?!isFunction(r)&&["str","string","int","integer","bool","boolean","float","arr","array"].includes(`${r.toLowerCase()}`)?(r=`${r}`.toLowerCase(),["str","string"].includes(r)?r=function(t){return`${t}`}:["int","integer"].includes(r)?r=function(t){return parseInt(t,10)}:["bool","boolean"].includes(r)?r=function(t){return!!t}:"float"===r?r=function(t){return parseFloat(t)}:["arr","array"].includes(r)&&(r=function(t){return[].concat(t)})):isFunction(r)||(r=function(t){return t}):r=function(t){return t},!hasValue(t)||n.includes(t)?e:r(t)}export function getType(t){if(!hasValue(t))return`${t}`.toLowerCase();const e=Object.prototype.toString.call(t).slice(8,-1).toLowerCase();return"generatorfunction"===e?"function":"document"===e?"htmldocument":"element"===e||/^html.*element$/.test(e)?"htmlelement":/^.*iterator$/.test(e)?"iterator":e.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/)?e:"object"==typeof t||"function"==typeof t?"object":typeof t}export function isA(t,e){return["undefined","null","boolean","number","bigint","string","symbol","function","object","array","date","error","generator","iterator","regexp","set","weakset","map","weakmap","htmldocument","htmlelement","htmlcollection","nodelist","window"].includes(`${e}`.toLowerCase())?getType(t)===`${e}`.toLowerCase():(warn(`Basic:isA | "${e}" is not a recognized type`),!1)}export function isBoolean(t){return isA(t,"boolean")}export function isNumber(t){return isA(t,"number")}export function isBigInt(t){return isA(t,"bigint")}export function isInt(t){return parseInt(t,10)===t}export function isFloat(t){return parseFloat(t)===t}export function isNaN(t,e=!0){return(e=orDefault(e,!0,"bool"))?t!=t:isNaN(t)}export function isString(t){return isA(t,"string")}export function isSymbol(t){return isA(t,"symbol")}export function isFunction(t){return isA(t,"function")}export function isObject(t){return isA(t,"object")}export function isPlainObject(t){return isObject(t)&&hasValue(t)&&t.constructor===Object&&"[object Object]"===Object.prototype.toString.call(t)}export function isArray(t){return isA(t,"array")}export function isDate(t){return isA(t,"date")}export function isError(t){return isA(t,"error")}export function isGenerator(t){return isA(t,"generator")}export function isIterator(t){return isA(t,"iterator")}export function isRegExp(t){return isA(t,"regexp")}export function isSet(t){return isA(t,"set")}export function isWeakSet(t){return isA(t,"weakset")}export function isMap(t){return isA(t,"map")}export function isWeakMap(t){return isA(t,"weakmap")}export function isDocument(t){return isA(t,"htmldocument")}export function isElement(t){return isA(t,"htmlelement")}export function isCollection(t){return isA(t,"htmlcollection")}export function isNodeList(t){return isA(t,"nodelist")}export function isWindow(t){return isA(t,"window")}export function isEventTarget(t){return hasValue(t)&&isFunction(t.addEventListener)&&isFunction(t.removeEventListener)&&isFunction(t.dispatchEvent)}export function isSelector(t){t=orDefault(t,0,"str");const e=document.createDocumentFragment();try{e.querySelector(t)}catch(t){return!1}return!0}export function isPotentialId(t,e="",r="[1-9][0-9]*",n="",i=!0){t=`${t}`,e=orDefault(e,"","str"),r=orDefault(r,"[1-9][0-9]*","str"),n=orDefault(n,"","str");const o=t=>`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&");let s;s=(i=orDefault(i,!0,"bool"))?new RegExp(`^${o(e)}(${r})${o(n)}$`):new RegExp(`^${e}(${r})${n}$`);const u=s.exec(t);return!!hasValue(u)&&u[1]}export function minMax(t,e,r){return assert(t<=r,"Basic:minMax | min can not be larger than max"),er?r:e}export class Deferred{constructor(){const t="fulfilled",e="rejected";this.resolve=null,this.reject=null,this.provision=null,this.status="pending",this.isSettled=()=>[t,e].includes(this.status),this.promise=new Promise(((r,n)=>{this.resolve=e=>{this.status=t,r(e)},this.reject=t=>{this.status=e,n(t)}}))}then(t){return this.promise.then(t)}catch(t){return this.promise.catch(t)}finally(t){return this.promise.finally(t)}}export class Observable{constructor(t){this.__className__="Observable",this._value=t,this._subscriptions=[]}getValue(){return this._value}setValue(t,e=!1){const r=this._value,n=r!==t;this._value=t,(n||e)&&this._subscriptions.forEach((e=>e(t,r)))}subscribe(t){return assert(isFunction(t),`Basic:${this.__className__}.subscribe | subscription must be function`),this._subscriptions.indexOf(t)<0&&(this._subscriptions=[...this._subscriptions,t]),t}unsubscribe(t){this._subscriptions=this._subscriptions.filter((e=>e!==t))}toString(){return`${this._value}`}} //# sourceMappingURL=basic.js.map diff --git a/dist/basic.js.map b/dist/basic.js.map index 5c4ebcd4..7d1c94a7 100644 --- a/dist/basic.js.map +++ b/dist/basic.js.map @@ -1 +1 @@ -{"version":3,"file":"basic.js","names":["MODULE_NAME","log","warn","assert","condition","message","orDefault","Error","attempt","closure","isA","ex","hasValue","res","Array","from","arguments","forEach","value","size","target","countStringCharacters","values","length","getType","Object","isEmpty","emptyValues","undefined","obj","__additionalEmptyValues__","concat","Set","includes","hasMembers","memberNames","verbose","memberName","info","expression","defaultValue","caster","additionalEmptyValues","toLowerCase","parseInt","parseFloat","deepType","prototype","toString","call","slice","test","match","type","isInt","intVal","isFloat","floatVal","isPlainObject","constructor","isNaN","checkForIdentity","isElement","isEventTarget","addEventListener","removeEventListener","dispatchEvent","isSelector","fragment","document","createDocumentFragment","querySelector","isPotentialId","prefix","idRex","postfix","maskFixes","mask","str","replace","rex","RegExp","matches","exec","minMax","min","max","Deferred","STATUS_FULFILLED","STATUS_REJECTED","this","resolve","reject","provision","status","isSettled","promise","Promise","resolution","rejection","then","f","catch","finally","Observable","initialValue","__className__","_value","_subscriptions","getValue","setValue","newValue","force","oldValue","isNewValue","s","subscribe","subscription","indexOf","unsubscribe","filter"],"sources":["basic.js"],"mappings":";;;AAQA,MAAMA,YAAc,eAMZC,IAAKC,SAAW,sBA0BjB,SAASC,OAAOC,EAAWC,GACjC,IAAKD,EAEJ,MADAC,EAAUC,UAAUD,EAAS,qCAAsC,OAC7D,IAAIE,MAAMF,EAElB,QA0BO,SAASG,QAAQC,GACvBN,OAAOO,IAAID,EAAS,YAAa,0CAEjC,IACCA,GAGD,CAFE,MAAME,GACP,OAAO,CACR,CAEA,OAAO,CACR,QAuBO,SAASC,WACf,IAAIC,GAAM,EAMV,OAJAC,MAAMC,KAAKC,WAAWC,SAAQC,IAC7BL,IAAQ,MAAEK,CAAyC,IAG7CL,CACR,QA+CO,SAASM,KAAKC,EAAQC,GAAsB,GAClD,GAAIX,IAAIU,GAAQE,OAAQ,YAAc,OAAOR,MAAMC,KAAKK,EAAOE,UAAUC,OAEzE,IAAIV,EACJ,OAAQW,QAAQJ,IACf,IAAK,QACJP,EAAMO,EAAOG,OACd,MAEA,IAAK,MACL,IAAK,MACJV,EAAMO,EAAOD,KACd,MAEA,IAAK,WACJN,EAAMC,MAAMC,KAAKK,GAAQG,OAC1B,MAEA,IAAK,SAEJV,EAAMQ,EAAwB,IAAID,GAAQG,OAASH,EAAOG,OAC3D,MAEA,IAAK,SACJV,EAAMY,OAAOH,OAAOF,GAAQG,OAC7B,MAEA,QACCV,EAAM,KAIR,OAAOA,CACR,QA2BO,SAASa,UACf,IACCb,GAAM,EACNc,EAAc,MAACC,EAAW,KAAM,GAAI,GAoBrC,OAjBAd,MAAMC,KAAKC,WAAWC,SAAQY,IACzBnB,IAAImB,GAAKC,0BAA2B,WACvCH,EAAcA,EAAYI,OAAOF,EAAIC,2BACtC,IAEDH,EAAcb,MAAMC,KAAK,IAAIiB,IAAIL,IAEjCb,MAAMC,KAAKC,WAAWC,SAAQY,IACzBhB,IAAQH,IAAImB,GAAKC,0BAA2B,WAC/CjB,EAAMc,EAAYM,SAASJ,GAEtBhB,IACJA,EAAqB,IAAdM,KAAKU,IAEd,IAGMhB,CACR,QAyBO,SAASqB,WAAWL,EAAKM,EAAaC,GAAQ,GACpDD,EAAc7B,UAAU6B,EAAa,GAAI,OACzCC,EAAU9B,UAAU8B,GAAS,EAAO,QAEpC,IAAIvB,GAAM,EAYV,OAVAsB,EAAYlB,SAAQoB,IACdzB,SAASiB,EAAI,GAAGQ,QAChBD,GACHnC,MAAMqC,KAAK,qCAA8CD,KAG1DxB,GAAM,EACP,IAGMA,CACR,QA0BO,SAASP,UAAUiC,EAAYC,EAAcC,EAAO,KAAMC,EAAsB,MAsCtF,OApCCA,EADG9B,SAAS8B,GACY,GAAGX,OAAOW,GAEV,GAGrB9B,SAAS6B,IAEV/B,IAAI+B,EAAQ,aACT,CACH,MAAO,SACP,MAAO,UACP,OAAQ,UACR,QACA,MAAO,SACNR,SAAS,GAAGQ,EAAOE,kBAErBF,EAAS,GAAGA,IAASE,cAEjB,CAAC,MAAO,UAAUV,SAASQ,GAC9BA,EAAS,SAASvB,GAAQ,MAAO,GAAGA,GAAS,EACnC,CAAC,MAAO,WAAWe,SAASQ,GACtCA,EAAS,SAASvB,GAAQ,OAAO0B,SAAS1B,EAAO,GAAK,EAC5C,CAAC,OAAQ,WAAWe,SAASQ,GACvCA,EAAS,SAASvB,GAAQ,QAASA,CAAO,EACrB,UAAXuB,EACVA,EAAS,SAASvB,GAAQ,OAAO2B,WAAW3B,EAAQ,EAC1C,CAAC,MAAO,SAASe,SAASQ,KACpCA,EAAS,SAASvB,GAAQ,MAAO,GAAGa,OAAOb,EAAQ,IAEzCR,IAAI+B,EAAQ,cACvBA,EAAS,SAASvB,GAAQ,OAAOA,CAAO,GAGzCuB,EAAS,SAASvB,GAAQ,OAAOA,CAAO,GAGpCN,SAAS2B,IAAgBG,EAAsBT,SAASM,GACrDC,EAEAC,EAAOF,EAEhB,QAgDO,SAASf,QAAQN,GACvB,IAAKN,SAASM,GAAS,MAAO,GAAGA,IAAQyB,cAEzC,MAAMG,EAAWrB,OAAOsB,UAAUC,SAASC,KAAK/B,GAAOgC,MAAM,GAAG,GAAGP,cAEnE,MAAiB,sBAAbG,EAA0C,WAC7B,aAAbA,EAAiC,eACpB,YAAbA,GACA,kBAAkBK,KAAKL,GADS,cAEhC,eAAeK,KAAKL,GAAmB,WAEpCA,EAASM,MAAM,qHACnBN,EACmB,iBAAV5B,GAAyC,mBAAVA,EAAyB,gBAAkBA,CAEvF,QAsBO,SAASR,IAAIQ,EAAOmC,GAC1B,MACC,CACC,YACA,OACA,UACA,SACA,SACA,SACA,SACA,WACA,SACA,QACA,OACA,QACA,YACA,WACA,SACA,MACA,UACA,MACA,UACA,eACA,cACA,WACA,UACCpB,SAAS,GAAGoB,IAAOV,eAEdnB,QAAQN,KAAW,GAAGmC,IAAOV,eAEpCzC,KAAK,gBAAyBmD,gCACvB,EAET,QAuBO,SAASC,MAAMC,GACrB,OAAOX,SAASW,EAAQ,MAAQA,CACjC,QAwBO,SAASC,QAAQC,GACvB,OAAOZ,WAAWY,KAAcA,CACjC,QA2BO,SAASC,cAAcxC,GAC7B,OAAOR,IAAIQ,EAAO,WACdN,SAASM,IACRA,EAAMyC,cAAgBlC,QACmB,oBAA1CA,OAAOsB,UAAUC,SAASC,KAAK/B,EAEpC,QA2BO,SAAS0C,MAAMrB,EAAYsB,GAAiB,GAGlD,OAFAA,EAAmBvD,UAAUuD,GAAkB,EAAM,SAG7CtB,GAAeA,EAEfqB,MAAMrB,EAEf,QAuBO,SAASuB,UAAU5C,GACzB,OAAOR,IAAIQ,EAAO,cACnB,QAyBO,SAAS6C,cAAc7C,GAC7B,OAAON,SAASM,IACZR,IAAIQ,EAAM8C,iBAAkB,aAC5BtD,IAAIQ,EAAM+C,oBAAqB,aAC/BvD,IAAIQ,EAAMgD,cAAe,WAE9B,QAsBO,SAASC,WAAWjD,GAE1BA,EAAQZ,UAAUY,EAAO,EAAG,OAE5B,MAAMkD,EAAWC,SAASC,yBAE1B,IACCF,EAASG,cAAcrD,EAGxB,CAFE,MAAMP,GACP,OAAO,CACR,CAEA,OAAO,CACR,QA2BO,SAAS6D,cAActD,EAAOuD,EAAO,GAAIC,EAAM,cAAeC,EAAQ,GAAIC,GAAU,GAC1F1D,EAAQ,GAAGA,IACXuD,EAASnE,UAAUmE,EAAQ,GAAI,OAC/BC,EAAQpE,UAAUoE,EAAO,cAAe,OACxCC,EAAUrE,UAAUqE,EAAS,GAAI,OAGjC,MAAME,EAAOC,GAAO,GAAGA,IAAMC,QAAQ,6BAA8B,QAEnE,IAAIC,EAEHA,GANDJ,EAAYtE,UAAUsE,GAAW,EAAM,SAMhC,IAAIK,OAAO,IAAIJ,EAAKJ,MAAWC,KAASG,EAAKF,OAE7C,IAAIM,OAAO,IAAIR,KAAUC,KAASC,MAGzC,MAAMO,EAAUF,EAAIG,KAAKjE,GACzB,QAAON,SAASsE,IAAWA,EAAQ,EACpC,QAyBO,SAASE,OAAOC,EAAKnE,EAAOoE,GAGlC,OAFAnF,OAAOkF,GAAOC,EAAK,iDAEXpE,EAAQmE,EACbA,EAEAnE,EAAQoE,EACNA,EACApE,CAGN,QAyDO,MAAMqE,SACZ5B,cACC,MAEC6B,EAAmB,YACnBC,EAAkB,WAEnBC,KAAKC,QAAU,KACfD,KAAKE,OAAS,KACdF,KAAKG,UAAY,KACjBH,KAAKI,OAPa,UAQlBJ,KAAKK,UAAY,IAAM,CAACP,EAAkBC,GAAiBxD,SAASyD,KAAKI,QACzEJ,KAAKM,QAAU,IAAIC,SAAQ,CAACN,EAASC,KACpCF,KAAKC,QAAUO,IACdR,KAAKI,OAASN,EACdG,EAAQO,EAAW,EAEpBR,KAAKE,OAASO,IACbT,KAAKI,OAASL,EACdG,EAAOO,EAAU,CACjB,GAEH,CAEAC,KAAKC,GACJ,OAAOX,KAAKM,QAAQI,KAAKC,EAC1B,CAEAC,MAAMD,GACL,OAAOX,KAAKM,QAAQM,MAAMD,EAC3B,CAEAE,QAAQF,GACP,OAAOX,KAAKM,QAAQO,QAAQF,EAC7B,SAiCM,MAAMG,WACZ7C,YAAY8C,GACXf,KAAKgB,cAAgB,aACrBhB,KAAKiB,OAASF,EACdf,KAAKkB,eAAiB,EACvB,CAEAC,WACC,OAAOnB,KAAKiB,MACb,CAEAG,SAASC,EAAUC,GAAM,GACxB,MACCC,EAAWvB,KAAKiB,OAChBO,EAAaD,IAAaF,EAE3BrB,KAAKiB,OAASI,GACVG,GAAcF,IACjBtB,KAAKkB,eAAe3F,SAAQkG,GAAKA,EAAEJ,EAAUE,IAE/C,CAEAG,UAAUC,GAMT,OAJAlH,OAAOO,IAAI2G,EAAc,YAAa,SAAkB3B,KAAKgB,2DACzDhB,KAAKkB,eAAeU,QAAQD,GAAgB,IAC/C3B,KAAKkB,eAAiB,IAAIlB,KAAKkB,eAAgBS,IAEzCA,CACR,CAEAE,YAAYF,GACX3B,KAAKkB,eAAiBlB,KAAKkB,eAAeY,QAAOL,GAAKA,IAAME,GAC7D,CAEArE,WACC,MAAO,GAAG0C,KAAKiB,QAChB","sourcesContent":["/*!\n * Module Basic\n */\n\n/**\n * @namespace Basic\n */\n\nconst MODULE_NAME = 'Basic';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {log, warn} from './logging.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Basic:assert\n */\n\n/**\n * Classical assert method. If condition is falsy, throw assert exception.\n *\n * @param {Boolean} condition - defines if an assertion is successful\n * @param {?String} [message='assert exception: assertion failed'] - to display if assertion fails\n * @throws assert exception\n *\n * @memberof Basic:assert\n * @alias assert\n * @example\n * function set(name, value){\n * assert(name.length > 0);\n * assert(isPlainObject(value), 'error: value must be plain object');\n * ...\n * }\n */\nexport function assert(condition, message){\n\tif( !condition ){\n\t\tmessage = orDefault(message, 'assert exception: assertion failed', 'str');\n\t\tthrow new Error(message);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:attempt\n */\n\n/**\n * Attempt to compute contents of closure and catch all occurring exceptions.\n * The boolean result tells you if the operation was successful or not.\n *\n * This is most helpful, when used to test value conversions or other atomic/singluar operations, where it\n * just is important if something isolated works or not.\n *\n * Do not encapsulate complex code in the closure and mind recursively occurring exceptions!\n *\n * @param {Function} closure - the code to test\n * @throws error if closure is not a function\n * @returns {Boolean} true if no exception occurred\n *\n * @memberof Basic:attempt\n * @alias attempt\n * @example\n * if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); }\n */\nexport function attempt(closure){\n\tassert(isA(closure, 'function'), `${MODULE_NAME}:attempt | closure is no function`);\n\n\ttry {\n\t\tclosure();\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:hasValue\n */\n\n/**\n * Check if variable(s) is set, by being neither undefined nor null.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are set\n *\n * @memberof Basic:hasValue\n * @alias hasValue\n * @example\n * function set(name, value){\n * if( hasValue(name, value) ){\n * ...\n * }\n * }\n */\nexport function hasValue(){\n\tlet res = true;\n\n\tArray.from(arguments).forEach(value => {\n\t\tres &&= ((value !== undefined) && (value !== null));\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:size\n */\n\n/**\n * Determine the (value) size of a collection.\n *\n * A collection is an object with countable values:\n * - Arrays return their length\n * - Sets and Maps return their size\n * - Strings return their (character) length\n * - Iterators return the length of their value list\n * - Objects return the length of their value list\n * - any object implementing .values() returns the length of the returned value list\n *\n * @param {Object|Array|Set|Map|String|Iterable} target - a collection to determine the (value) size of\n * @param {?Boolean} [countStringCharacters=true] - if we want to determine the length of a string, we'd normally like to count actual characters, but length normally returns the technical length counting more than one for unicode chars, set this to \"false\" to use technical length instead of characters\n * @returns {Number|null} the size of the collection or null if no size could be determined\n *\n * @memberof Basic:size\n * @alias size\n * @example\n * size('日本国💩👻');\n * => 5\n * size('日本国💩👻', false);\n * => 7\n * size({a : 1, b : new Date(), c : [1, 2, 3]});\n * => 3\n * size(['test', 'test', 'test']);\n * => 3\n * size(new Set(['test1', 'test2', 'test3']));\n * => 3\n * size(new Set(['test1', 'test2', 'test3']).values());\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]));\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]).values());\n * => 3\n * size(null);\n * => null\n * size(undefined);\n * => null\n */\nexport function size(target, countStringCharacters=true){\n\tif( isA(target?.values, 'function') ) return Array.from(target.values()).length;\n\n\tlet res;\n\tswitch( getType(target) ){\n\t\tcase 'array':\n\t\t\tres = target.length;\n\t\tbreak;\n\n\t\tcase 'set':\n\t\tcase 'map':\n\t\t\tres = target.size;\n\t\tbreak;\n\n\t\tcase 'iterator':\n\t\t\tres = Array.from(target).length;\n\t\tbreak;\n\n\t\tcase 'string':\n\t\t\t// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#description\n\t\t\tres = countStringCharacters ? [...target].length : target.length;\n\t\tbreak;\n\n\t\tcase 'object':\n\t\t\tres = Object.values(target).length;\n\t\tbreak;\n\n\t\tdefault:\n\t\t\tres = null;\n\t\tbreak;\n\t}\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:isEmpty\n */\n\n/**\n * Check if variable(s) contain non-empty value\n * (not undefined, null, '', 0, [], {} or an empty Set/Map).\n *\n * You can supply additional non-empty values by providing an object having the key \"__additionalEmptyValues__\" as\n * any single parameter. Multiple occurrences will be merged.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are empty\n *\n * @memberof Basic:isEmpty\n * @alias isEmpty\n * @example\n * function set(name, value){\n * if( isEmpty(fooBar) || isEmpty({'__additionalEmptyValues__' : [false, '0']}, someArray, someSet, someString, value) ){\n * ...\n * }\n * }\n */\nexport function isEmpty(){\n\tlet\n\t\tres = true,\n\t\temptyValues = [undefined, null, '', 0]\n\t;\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( isA(obj?.__additionalEmptyValues__, 'array') ){\n\t\t\temptyValues = emptyValues.concat(obj.__additionalEmptyValues__);\n\t\t}\n\t});\n\temptyValues = Array.from(new Set(emptyValues));\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( res && !isA(obj?.__additionalEmptyValues__, 'array') ){\n\t\t\tres = emptyValues.includes(obj);\n\n\t\t\tif( !res ){\n\t\t\t\tres = (size(obj) === 0);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:hasMembers\n */\n\n/**\n * \"Validates\" an object in a very basic way by checking if all given members are present and are not nullish.\n *\n * @param {Object} obj - the object to check\n * @param {String[]} memberNames - the names of the members to check\n * @param {Boolean} [verbose=false] - defines if method should output missing members to console\n * @returns {Boolean} all memberNames present and not nullish\n *\n * @memberof Basic:hasMembers\n * @alias hasMembers\n * @example\n * function pat(kitten){\n * if( hasMembers(kitten, ['fluff', 'meow', 'scratch']) ){\n * ...\n * }\n * }\n */\nexport function hasMembers(obj, memberNames, verbose=false){\n\tmemberNames = orDefault(memberNames, [], 'arr');\n\tverbose = orDefault(verbose, false, 'bool');\n\n\tlet res = true;\n\n\tmemberNames.forEach(memberName => {\n\t\tif( !hasValue(obj[`${memberName}`]) ){\n\t\t\tif( verbose ){\n\t\t\t\tlog().info(`${MODULE_NAME}:hasMembers | missing member ${memberName}`);\n\t\t\t}\n\n\t\t\tres = false;\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:orDefault\n */\n\n/**\n * If an expression returns a non-value (undefined or null), use the default value instead.\n * Define a caster name, to force expression result/value into certain data type.\n *\n * @param {*} expression - the expression to evaluate\n * @param {*} defaultValue - the default value to use if the expression is considered empty\n * @param {?(String|Function)} [caster=null] - either a default caster by name ('str', 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'arr', 'array') or a function getting the value and returning the transformed value\n * @param {?Array} [additionalEmptyValues=null] - if set, provides a list of additional values to be considered empty, apart from undefined and null\n * @returns {*} expression of defaultValue\n *\n * @memberof Basic:orDefault\n * @alias orDefault\n * @example\n * function set(name, value){\n * name = orDefault(name, 'kittens!', 'string', ['', 'none']);\n * value = orDefault(value, 42, 'int');\n * }\n */\nexport function orDefault(expression, defaultValue, caster=null, additionalEmptyValues=null){\n\tif( hasValue(additionalEmptyValues) ){\n\t\tadditionalEmptyValues = [].concat(additionalEmptyValues);\n\t} else {\n\t\tadditionalEmptyValues = [];\n\t}\n\n\tif( hasValue(caster) ){\n\t\tif(\n\t\t\t!isA(caster, 'function')\n\t\t\t&& ([\n\t\t\t\t'str', 'string',\n\t\t\t\t'int', 'integer',\n\t\t\t\t'bool', 'boolean',\n\t\t\t\t'float',\n\t\t\t\t'arr', 'array'\n\t\t\t].includes(`${caster.toLowerCase()}`))\n\t\t){\n\t\t\tcaster = `${caster}`.toLowerCase();\n\n\t\t\tif( ['str', 'string'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return `${value}`; };\n\t\t\t} else if( ['int', 'integer'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return parseInt(value, 10); };\n\t\t\t} else if( ['bool', 'boolean'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return !!value; };\n\t\t\t} else if( caster === 'float' ){\n\t\t\t\tcaster = function(value){ return parseFloat(value); };\n\t\t\t} else if( ['arr', 'array'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return [].concat(value); };\n\t\t\t}\n\t\t} else if( !isA(caster, 'function') ){\n\t\t\tcaster = function(value){ return value; };\n\t\t}\n\t} else {\n\t\tcaster = function(value){ return value; };\n\t}\n\n\tif( !hasValue(expression) || (additionalEmptyValues.includes(expression)) ){\n\t\treturn defaultValue;\n\t} else {\n\t\treturn caster(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:getType\n */\n\n/**\n * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on\n * useful frontend types like \"htmldocument\", \"htmlelement\" and \"nodelist\"\n *\n * Types:\n * - \"undefined\"\n * - \"null\"\n * - \"boolean\"\n * - \"number\"\n * - \"bigint\"\n * - \"string\"\n * - \"symbol\"\n * - \"function\"\n * - \"object\"\n * - \"array\"\n * - \"date\"\n * - \"error\"\n * - \"generator\"\n * - \"iterator\"\n * - \"regexp\"\n * - \"set\"\n * - \"weakset\"\n * - \"map\"\n * - \"weakmap\"\n * - \"htmldocument\"\n * - \"htmlelement\"\n * - \"nodelist\"\n * - \"window\"\n *\n * @param {*} [value] - variable to check the type of\n * @returns {String} the value type in lower case\n *\n * @memberof Basic:getType\n * @alias getType\n * @example\n * if( getType(cb) === 'function' ){\n * ...\n * }\n */\nexport function getType(value) {\n\tif( !hasValue(value) ) return `${value}`.toLowerCase();\n\n\tconst deepType = Object.prototype.toString.call(value).slice(8,-1).toLowerCase();\n\n\tif( deepType === 'generatorfunction' ) return 'function';\n\tif( deepType === 'document' ) return 'htmldocument';\n\tif( deepType === 'element' ) return 'htmlelement';\n\tif( /^html.*element$/.test(deepType) ) return 'htmlelement';\n\tif( /^.*iterator$/.test(deepType) ) return 'iterator';\n\n\treturn deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/)\n\t\t? deepType\n\t\t: ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isA\n */\n\n/**\n * Short form of \"getType\"-method with a more compact syntax.\n * Can identify all types listed in getType.\n *\n * @param {*} value - variable to check the type of\n * @param {String} type - the name of the type to check for, has to be a standard JS-type, is case insensitive\n * @returns {Boolean} target has type\n *\n * @memberof Basic:isA\n * @alias isA\n * @see getType\n * @example\n * let stringBool = (isA(test, 'boolean') && test) ? 'true' : 'false';\n */\nexport function isA(value, type){\n\tif(\n\t\t[\n\t\t\t'undefined',\n\t\t\t'null',\n\t\t\t'boolean',\n\t\t\t'number',\n\t\t\t'bigint',\n\t\t\t'string',\n\t\t\t'symbol',\n\t\t\t'function',\n\t\t\t'object',\n\t\t\t'array',\n\t\t\t'date',\n\t\t\t'error',\n\t\t\t'generator',\n\t\t\t'iterator',\n\t\t\t'regexp',\n\t\t\t'set',\n\t\t\t'weakset',\n\t\t\t'map',\n\t\t\t'weakmap',\n\t\t\t'htmldocument',\n\t\t\t'htmlelement',\n\t\t\t'nodelist',\n\t\t\t'window'\n\t\t].includes(`${type}`.toLowerCase())\n\t){\n\t\treturn getType(value) === `${type}`.toLowerCase();\n\t} else {\n\t\twarn(`${MODULE_NAME}:isA | \"${type}\" is not a recognized type`);\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isInt\n */\n\n/**\n * Returns if a value is truly a real integer value and not just an int-parsable value for example.\n * Since JS only knows the data type \"number\" all numbers are usable as floats by default, but not the\n * other way round.\n *\n * @param {*} intVal - the value the check\n * @returns {Boolean} true if intVal is a true integer value\n *\n * @memberof Basic:isInt\n * @alias isInt\n * @example\n * if( !isInt(val) ){\n * val = parseInt(val, 10);\n * }\n */\nexport function isInt(intVal){\n\treturn parseInt(intVal, 10) === intVal;\n}\n\n\n\n/**\n * @namespace Basic:isFloat\n */\n\n/**\n * Returns if a value is a numeric value, usable as a float number in any calculation.\n * Any number that fulfills isInt, is also considered a valid float, which lies in JS's\n * nature of not differentiating ints and floats by putting them both into a \"number\"-type.\n * So ints are always floats, but not necessarily the other way round.\n *\n * @param {*} floatVal - the value to check\n * @returns {Boolean} true if floatVal is usable in a float context\n *\n * @memberof Basic:isFloat\n * @alias isFloat\n * @example\n * if( !isFloat(val) ){\n * alert('val can not be calculated with!');\n * }\n */\nexport function isFloat(floatVal){\n\treturn parseFloat(floatVal) === floatVal;\n}\n\n\n\n/**\n * @namespace Basic:isPlainObject\n */\n\n/**\n * Returns if a value is an object literal, so so-called \"plain object.\n * A plain object is something like \"{hello : 'world'}\".\n *\n * This might especially be helpful when dealing with JSON configs, so quickly check if\n * something might even be parsed JSON (which in most cases is a plain object in js).\n *\n * Be aware that this function cannot differentiate between constructor-based simple objects and\n * plain objects declared inline. So, if someone took on the work to instantiate a base object and assign\n * properties either in a function or a constructor, we accept that as a plain object.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value seems to be a plain object\n *\n * @memberof Basic:isPlainObject\n * @alias isPlainObject\n * @example\n * const isParameterConfigObject = isPlainObject(param);\n */\nexport function isPlainObject(value){\n\treturn isA(value, 'object')\n\t\t&& hasValue(value)\n\t\t&& (value.constructor === Object)\n\t\t&& Object.prototype.toString.call(value) === '[object Object]'\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isNaN\n */\n\n/**\n * Returns if an expression is NaN or not.\n * This method employs two different approaches:\n * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something.\n * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being\n * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which\n * inspects the expression, tries to cast or parse a number from it and returns the result.\n *\n * @param {*} expression - the expression to check\n * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality\n * @returns {Boolean} true if expression is NaN\n *\n * @memberof Basic:isNaN\n * @alias isNaN\n * @example\n * if( !isNaN(suspiciousCalculatedValue) ){\n * return suspiciousCalculatedValue * 3;\n * }\n */\nexport function isNaN(expression, checkForIdentity=true){\n\tcheckForIdentity = orDefault(checkForIdentity, true, 'bool');\n\n\tif( checkForIdentity ){\n\t\treturn expression !== expression;\n\t} else {\n\t\treturn isNaN(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isElement\n */\n\n/**\n * Returns if a value is an HTML element.\n * Be aware, that this explicitly means an element, not necessarily any node.\n * So text nodes, comments and such do not qualify.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an HTML element\n *\n * @memberof Basic:isElement\n * @alias isElement\n * @example\n * if( isElement(target) ){\n * target.classList.add('foo');\n * }\n */\nexport function isElement(value){\n\treturn isA(value, 'htmlelement');\n}\n\n\n\n/**\n * @namespace Basic:isEventTarget\n */\n\n/**\n * Returns if a value is an EventTarget, which means that it is able to dispatch and receive events.\n * This is determined via duck-typing and not via class inheritance check, since this method is not\n * about type-safety, but the question if we can use the target for events, which is simply determined\n * by three essential object methods: addEventListener, removeEventListener and dispatchEvent. All\n * objects supporting these are fine with us.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value supports event methods\n *\n * @memberof Basic:isEventTarget\n * @alias isEventTarget\n * @example\n * if( isEventTarget(target) ){\n * target.dispatchEvent(new CustomEvent('foobar'));\n * }\n */\nexport function isEventTarget(value){\n\treturn hasValue(value)\n\t\t&& isA(value.addEventListener, 'function')\n\t\t&& isA(value.removeEventListener, 'function')\n\t\t&& isA(value.dispatchEvent, 'function')\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isSelector\n */\n\n/**\n * Returns if a value is a valid selector, usable in methods such as querySelector\n * and querySelectorAll.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a valid selector\n *\n * @memberof Basic:isSelector\n * @alias isSelector\n * @example\n * if( isSelector(selector) ){\n * document.querySelector(selector)?.style.setProperty('color', 'red');\n * }\n */\nexport function isSelector(value){\n\t// almost all values like \"null\", \"undefined\" and \"NaN\" are accepted querySelectors, numbers are not\n\tvalue = orDefault(value, 0, 'str');\n\n\tconst fragment = document.createDocumentFragment();\n\n\ttry {\n\t\tfragment.querySelector(value);\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:isPotentialId\n */\n\n/**\n * Determines if a given value is potentially a valid id for something, because it matches a format of given\n * prefix, postfix and id regex. \"Potential\", because we can only assume by the format, we do not actually know\n * if the id really matches anything like a database entry for example.\n *\n * @param {(String|Number)} value - the value to test, will be stringified\n * @param {?String} [prefix=''] - a prefix for the id\n * @param {?String} [idRex='[1-9][0-9]*'] - the regex string to use to identify the id part of the value\n * @param {?String} [postfix=''] - a postfix for the id\n * @param {?Boolean} [maskFixes=true] - usually, prefixes are not treated as regexes and are automatically masked, if you'd like to define complex pre- and postfixes using regexes, set this to false\n * @returns {String|Boolean} if value is potential id according to format, the id is returned as a string (still usable as a truthy value), otherwise the return value is false\n *\n * @memberof Basic:isPotentialId\n * @alias isPotentialId\n * @example\n * if( isPotentialId(id, 'test_(', '[0-9]+', ')') ){\n * createJsonRequest(`/backend/${id}`).then(() => { alert('done'); });\n * }\n */\nexport function isPotentialId(value, prefix='', idRex='[1-9][0-9]*', postfix='', maskFixes=true){\n\tvalue = `${value}`;\n\tprefix = orDefault(prefix, '', 'str');\n\tidRex = orDefault(idRex, '[1-9][0-9]*', 'str');\n\tpostfix = orDefault(postfix, '', 'str');\n\tmaskFixes = orDefault(maskFixes, true, 'bool');\n\n\tconst mask = str => `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n\n\tlet rex;\n\tif( maskFixes ){\n\t\trex = new RegExp(`^${mask(prefix)}(${idRex})${mask(postfix)}$`);\n\t} else {\n\t\trex = new RegExp(`^${prefix}(${idRex})${postfix}$`);\n\t}\n\n\tconst matches = rex.exec(value);\n\treturn hasValue(matches) ? matches[1] : false;\n}\n\n\n\n/**\n * @namespace Basic:minMax\n */\n\n/**\n * Checks if a value is within bounds of a minimum and maximum and returns\n * the value or the upper or lower bound respectively.\n *\n * Accepts all values comparable with > and <.\n *\n * @param {*} min - the lower bound\n * @param {*} value - the value to check\n * @param {*} max - the upper bound\n * @throws error if min is not smaller than max\n * @returns {*} value, min or max\n *\n * @memberof Basic:minMax\n * @alias minMax\n * @example\n * let croppedVal = minMax(-100, value, 100);\n */\nexport function minMax(min, value, max){\n\tassert(min <= max, `${MODULE_NAME}:minMax | min can not be larger than max`);\n\n\treturn (value < min)\n\t\t? min\n\t\t: (\n\t\t\t(value > max)\n\t\t\t\t? max\n\t\t\t\t: value\n\t\t)\n\t;\n}\n\n\n\n/**\n * @namespace Basic:Deferred\n */\n\n/**\n * @typedef Deferred\n * @type {Object}\n * @property {Promise} promise - the wrapped promise\n * @property {Function} resolve - resolves the wrapped promise with given value\n * @property {Function} reject - rejects the wrapped promise with given error\n * @property {Function} then - defines a success handler for the wrapped promise and returns its result\n * @property {Function} catch - defines an error handler for the wrapped promise and returns its result\n * @property {Function} finally - defines a \"settled\" handler for the wrapped promise and returns its result\n * @property {String} status - holds the current resolution status, can either be \"pending\", \"fulfilled\" or \"rejected\"\n * @property {Function} isSettled - returns true, if the Deferred is either \"fulfilled\" or \"rejected\"\n * @property {?*} [provision=null] - may contain (a) provisional value(s) to use for a newly instantiated Deferred, before it has resolved to the actual value(s)\n */\n\n/**\n * Class that wraps a Promise, to allow resolving and rejecting outside the\n * Promise's function scope. This allows for decoupled handling of states and\n * handling promises as references in a distributed context, like a class, where\n * a Deferred might then represent an async state.\n *\n * Deferreds also provide accessible status information, normal Promises do not have.\n * Accessing the \"status\" property returns the current status, being either \"pending\",\n * \"fulfilled\" or \"rejected\". You may also check if the Deferred has been settled via\n * \"isSettled()\". If you want to provide a preliminary result, available before the\n * promise has settled, you may set this result as a payload using the \"provision\" property.\n *\n * This follows ideas by jQuery and Q Promises:\n * - https://api.jquery.com/jQuery.Deferred/\n * - https://github.com/kriskowal/q/wiki/Coming-from-jQuery#deferreds-promises-resolvers\n *\n * Keep in mind, that Promises might need a polyfill such as core-js.\n *\n * @memberof Basic:Deferred\n * @name Deferred\n * @example\n * const doStuff = new Deferred();\n * doStuff.provision = 'provisional value';\n * doStuff\n * .then(value => { alert(`yeah, ready with \"${value}\"!`); })\n * .catch(error => { console.error(error); })\n * .finally(() => { console.info('has been settled); })\n * ;\n * if( foobar === 42 ){\n * doStuff.resolve(42);\n * } else {\n * doStuff.reject(new Error('not 42!'));\n * }\n * console.info(doStuff.status);\n */\nexport class Deferred {\n\tconstructor(){\n\t\tconst\n\t\t\tSTATUS_PENDING = 'pending',\n\t\t\tSTATUS_FULFILLED = 'fulfilled',\n\t\t\tSTATUS_REJECTED = 'rejected'\n\t\t;\n\t\tthis.resolve = null;\n\t\tthis.reject = null;\n\t\tthis.provision = null;\n\t\tthis.status = STATUS_PENDING;\n\t\tthis.isSettled = () => [STATUS_FULFILLED, STATUS_REJECTED].includes(this.status);\n\t\tthis.promise = new Promise((resolve, reject) => {\n\t\t\tthis.resolve = resolution => {\n\t\t\t\tthis.status = STATUS_FULFILLED;\n\t\t\t\tresolve(resolution);\n\t\t\t};\n\t\t\tthis.reject = rejection => {\n\t\t\t\tthis.status = STATUS_REJECTED;\n\t\t\t\treject(rejection);\n\t\t\t};\n\t\t});\n\t}\n\n\tthen(f){\n\t\treturn this.promise.then(f);\n\t}\n\n\tcatch(f){\n\t\treturn this.promise.catch(f);\n\t}\n\n\tfinally(f){\n\t\treturn this.promise.finally(f);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:Observable\n */\n\n/**\n * @typedef Observable\n * @type {Object}\n * @property {Function} getValue - returns the current value\n * @property {Function} setValue - sets a new value, which will subsequently trigger all subscriptions\n * @property {Function} subscribe - register a given function to be executed on any value change, the subscription receives the new and the old value on each execution, returns the subscription value, which can later be used to unsubscribe again\n * @property {Function} unsubscribe - removes a given subscription again, use subscription value returned by subscribe here\n */\n\n/**\n * A class offering the bare minimum feature set to observe a value and subscribe to future value changes.\n * No automatic magic going on here, this simply follows a basic subscription pattern, where each subscription is\n * a function, being called with a newly set value. This closely resembles the kind of observables knockout is using.\n *\n * @memberof Basic:Observable\n * @name Observable\n * @example\n * const status = new Observable('ok');\n * const subscription = status.subscribe(s => {\n * console.log(`status changed to: ${s}`);\n * });\n * status.setValue('oh noez');\n * status.unsubscribe(subscription);\n */\nexport class Observable {\n\tconstructor(initialValue){\n\t\tthis.__className__ = 'Observable';\n\t\tthis._value = initialValue;\n\t\tthis._subscriptions = [];\n\t}\n\n\tgetValue(){\n\t\treturn this._value;\n\t}\n\n\tsetValue(newValue, force=false){\n\t\tconst\n\t\t\toldValue = this._value,\n\t\t\tisNewValue = oldValue !== newValue\n\t\t;\n\t\tthis._value = newValue;\n\t\tif( isNewValue || force ){\n\t\t\tthis._subscriptions.forEach(s => s(newValue, oldValue));\n\t\t}\n\t}\n\n\tsubscribe(subscription){\n\t\tconst __methodName__ = 'subscribe';\n\t\tassert(isA(subscription, 'function'), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`);\n\t\tif( this._subscriptions.indexOf(subscription) < 0 ){\n\t\t\tthis._subscriptions = [...this._subscriptions, subscription];\n\t\t}\n\t\treturn subscription;\n\t}\n\n\tunsubscribe(subscription){\n\t\tthis._subscriptions = this._subscriptions.filter(s => s !== subscription);\n\t}\n\n\ttoString(){\n\t\treturn `${this._value}`;\n\t}\n}\n"]} \ No newline at end of file +{"version":3,"file":"basic.js","names":["MODULE_NAME","log","warn","assert","condition","message","orDefault","Error","attempt","closure","isFunction","ex","hasValue","res","Array","from","arguments","forEach","value","size","target","countStringCharacters","values","length","getType","Object","isEmpty","emptyValues","undefined","obj","isArray","__additionalEmptyValues__","concat","Set","includes","hasMembers","memberNames","verbose","memberName","info","expression","defaultValue","caster","additionalEmptyValues","toLowerCase","parseInt","parseFloat","deepType","prototype","toString","call","slice","test","match","isA","type","isBoolean","isNumber","isBigInt","isInt","intVal","isFloat","floatVal","isNaN","checkForIdentity","isString","isSymbol","isObject","isPlainObject","constructor","isDate","isError","isGenerator","isIterator","isRegExp","isSet","isWeakSet","isMap","isWeakMap","isDocument","isElement","isCollection","isNodeList","isWindow","isEventTarget","addEventListener","removeEventListener","dispatchEvent","isSelector","fragment","document","createDocumentFragment","querySelector","isPotentialId","prefix","idRex","postfix","maskFixes","mask","str","replace","rex","RegExp","matches","exec","minMax","min","max","Deferred","STATUS_FULFILLED","STATUS_REJECTED","this","resolve","reject","provision","status","isSettled","promise","Promise","resolution","rejection","then","f","catch","finally","Observable","initialValue","__className__","_value","_subscriptions","getValue","setValue","newValue","force","oldValue","isNewValue","s","subscribe","subscription","indexOf","unsubscribe","filter"],"sources":["basic.js"],"mappings":"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","sourcesContent":["/*!\n * Module Basic\n */\n\n/**\n * @namespace Basic\n */\n\nconst MODULE_NAME = 'Basic';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {log, warn} from './logging.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Basic:assert\n */\n\n/**\n * Classical assert method. If condition is falsy, throw assert exception.\n *\n * @param {Boolean} condition - defines if an assertion is successful\n * @param {?String} [message='assert exception: assertion failed'] - to display if assertion fails\n * @throws assert exception\n *\n * @memberof Basic:assert\n * @alias assert\n * @example\n * function set(name, value){\n * assert(name.length > 0);\n * assert(isPlainObject(value), 'error: value must be plain object');\n * ...\n * }\n */\nexport function assert(condition, message){\n\tif( !condition ){\n\t\tmessage = orDefault(message, 'assert exception: assertion failed', 'str');\n\t\tthrow new Error(message);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:attempt\n */\n\n/**\n * Attempt to compute contents of closure and catch all occurring exceptions.\n * The boolean result tells you if the operation was successful or not.\n *\n * This is most helpful, when used to test value conversions or other atomic/singluar operations, where it\n * just is important if something isolated works or not.\n *\n * Do not encapsulate complex code in the closure and mind recursively occurring exceptions!\n *\n * @param {Function} closure - the code to test\n * @throws error if closure is not a function\n * @returns {Boolean} true if no exception occurred\n *\n * @memberof Basic:attempt\n * @alias attempt\n * @example\n * if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); }\n */\nexport function attempt(closure){\n\tassert(isFunction(closure), `${MODULE_NAME}:attempt | closure is no function`);\n\n\ttry {\n\t\tclosure();\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:hasValue\n */\n\n/**\n * Check if variable(s) is set, by being neither undefined nor null.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are set\n *\n * @memberof Basic:hasValue\n * @alias hasValue\n * @example\n * function set(name, value){\n * if( hasValue(name, value) ){\n * ...\n * }\n * }\n */\nexport function hasValue(){\n\tlet res = true;\n\n\tArray.from(arguments).forEach(value => {\n\t\tres &&= ((value !== undefined) && (value !== null));\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:size\n */\n\n/**\n * Determine the (value) size of a collection.\n *\n * A collection is an object with countable values:\n * - Arrays return their length\n * - Sets and Maps return their size\n * - Strings return their (character) length\n * - Iterators return the length of their value list\n * - Objects return the length of their value list\n * - any object implementing .values() returns the length of the returned value list\n *\n * @param {Object|Array|Set|Map|String|Iterable} target - a collection to determine the (value) size of\n * @param {?Boolean} [countStringCharacters=true] - if we want to determine the length of a string, we'd normally like to count actual characters, but length normally returns the technical length counting more than one for unicode chars, set this to \"false\" to use technical length instead of characters\n * @returns {Number|null} the size of the collection or null if no size could be determined\n *\n * @memberof Basic:size\n * @alias size\n * @example\n * size('日本国💩👻');\n * => 5\n * size('日本国💩👻', false);\n * => 7\n * size({a : 1, b : new Date(), c : [1, 2, 3]});\n * => 3\n * size(['test', 'test', 'test']);\n * => 3\n * size(new Set(['test1', 'test2', 'test3']));\n * => 3\n * size(new Set(['test1', 'test2', 'test3']).values());\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]));\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]).values());\n * => 3\n * size(null);\n * => null\n * size(undefined);\n * => null\n */\nexport function size(target, countStringCharacters=true){\n\tif( isFunction(target?.values) ) return Array.from(target.values()).length;\n\n\tlet res;\n\tswitch( getType(target) ){\n\t\tcase 'array':\n\t\t\tres = target.length;\n\t\tbreak;\n\n\t\tcase 'set':\n\t\tcase 'map':\n\t\t\tres = target.size;\n\t\tbreak;\n\n\t\tcase 'iterator':\n\t\t\tres = Array.from(target).length;\n\t\tbreak;\n\n\t\tcase 'string':\n\t\t\t// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#description\n\t\t\tres = countStringCharacters ? [...target].length : target.length;\n\t\tbreak;\n\n\t\tcase 'object':\n\t\t\tres = Object.values(target).length;\n\t\tbreak;\n\n\t\tdefault:\n\t\t\tres = null;\n\t\tbreak;\n\t}\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:isEmpty\n */\n\n/**\n * Check if variable(s) contain non-empty value\n * (not undefined, null, '', 0, [], {} or an empty Set/Map).\n *\n * You can supply additional non-empty values by providing an object having the key \"__additionalEmptyValues__\" as\n * any single parameter. Multiple occurrences will be merged.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are empty\n *\n * @memberof Basic:isEmpty\n * @alias isEmpty\n * @example\n * function set(name, value){\n * if( isEmpty(fooBar) || isEmpty({'__additionalEmptyValues__' : [false, '0']}, someArray, someSet, someString, value) ){\n * ...\n * }\n * }\n */\nexport function isEmpty(){\n\tlet\n\t\tres = true,\n\t\temptyValues = [undefined, null, '', 0]\n\t;\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( isArray(obj?.__additionalEmptyValues__) ){\n\t\t\temptyValues = emptyValues.concat(obj.__additionalEmptyValues__);\n\t\t}\n\t});\n\temptyValues = Array.from(new Set(emptyValues));\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( res && !isArray(obj?.__additionalEmptyValues__) ){\n\t\t\tres = emptyValues.includes(obj);\n\n\t\t\tif( !res ){\n\t\t\t\tres = (size(obj) === 0);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:hasMembers\n */\n\n/**\n * \"Validates\" an object in a very basic way by checking if all given members are present and are not nullish.\n *\n * @param {Object} obj - the object to check\n * @param {String[]} memberNames - the names of the members to check\n * @param {Boolean} [verbose=false] - defines if method should output missing members to console\n * @returns {Boolean} all memberNames present and not nullish\n *\n * @memberof Basic:hasMembers\n * @alias hasMembers\n * @example\n * function pat(kitten){\n * if( hasMembers(kitten, ['fluff', 'meow', 'scratch']) ){\n * ...\n * }\n * }\n */\nexport function hasMembers(obj, memberNames, verbose=false){\n\tmemberNames = orDefault(memberNames, [], 'arr');\n\tverbose = orDefault(verbose, false, 'bool');\n\n\tlet res = true;\n\n\tmemberNames.forEach(memberName => {\n\t\tif( !hasValue(obj[`${memberName}`]) ){\n\t\t\tif( verbose ){\n\t\t\t\tlog().info(`${MODULE_NAME}:hasMembers | missing member ${memberName}`);\n\t\t\t}\n\n\t\t\tres = false;\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:orDefault\n */\n\n/**\n * If an expression returns a non-value (undefined or null), use the default value instead.\n * Define a caster name, to force expression result/value into certain data type.\n *\n * @param {*} expression - the expression to evaluate\n * @param {*} defaultValue - the default value to use if the expression is considered empty\n * @param {?(String|Function)} [caster=null] - either a default caster by name ('str', 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'arr', 'array') or a function getting the value and returning the transformed value\n * @param {?Array} [additionalEmptyValues=null] - if set, provides a list of additional values to be considered empty, apart from undefined and null\n * @returns {*} expression of defaultValue\n *\n * @memberof Basic:orDefault\n * @alias orDefault\n * @example\n * function set(name, value){\n * name = orDefault(name, 'kittens!', 'string', ['', 'none']);\n * value = orDefault(value, 42, 'int');\n * }\n */\nexport function orDefault(expression, defaultValue, caster=null, additionalEmptyValues=null){\n\tif( hasValue(additionalEmptyValues) ){\n\t\tadditionalEmptyValues = [].concat(additionalEmptyValues);\n\t} else {\n\t\tadditionalEmptyValues = [];\n\t}\n\n\tif( hasValue(caster) ){\n\t\tif(\n\t\t\t!isFunction(caster)\n\t\t\t&& ([\n\t\t\t\t'str', 'string',\n\t\t\t\t'int', 'integer',\n\t\t\t\t'bool', 'boolean',\n\t\t\t\t'float',\n\t\t\t\t'arr', 'array'\n\t\t\t].includes(`${caster.toLowerCase()}`))\n\t\t){\n\t\t\tcaster = `${caster}`.toLowerCase();\n\n\t\t\tif( ['str', 'string'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return `${value}`; };\n\t\t\t} else if( ['int', 'integer'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return parseInt(value, 10); };\n\t\t\t} else if( ['bool', 'boolean'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return !!value; };\n\t\t\t} else if( caster === 'float' ){\n\t\t\t\tcaster = function(value){ return parseFloat(value); };\n\t\t\t} else if( ['arr', 'array'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return [].concat(value); };\n\t\t\t}\n\t\t} else if( !isFunction(caster) ){\n\t\t\tcaster = function(value){ return value; };\n\t\t}\n\t} else {\n\t\tcaster = function(value){ return value; };\n\t}\n\n\tif( !hasValue(expression) || (additionalEmptyValues.includes(expression)) ){\n\t\treturn defaultValue;\n\t} else {\n\t\treturn caster(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:getType\n */\n\n/**\n * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on\n * useful frontend types like \"htmldocument\", \"htmlelement\", \"htmlcollection\" and \"nodelist\"\n *\n * Types:\n * - \"undefined\"\n * - \"null\"\n * - \"boolean\"\n * - \"number\"\n * - \"bigint\"\n * - \"string\"\n * - \"symbol\"\n * - \"function\"\n * - \"object\"\n * - \"array\"\n * - \"date\"\n * - \"error\"\n * - \"generator\"\n * - \"iterator\"\n * - \"regexp\"\n * - \"set\"\n * - \"weakset\"\n * - \"map\"\n * - \"weakmap\"\n * - \"htmldocument\"\n * - \"htmlelement\"\n * - \"htmlcollection\"\n * - \"nodelist\"\n * - \"window\"\n *\n * @param {*} [value] - variable to check the type of\n * @returns {String} the value type in lower case\n *\n * @memberof Basic:getType\n * @alias getType\n * @example\n * if( getType(cb) === 'function' ){\n * ...\n * }\n */\nexport function getType(value) {\n\tif( !hasValue(value) ) return `${value}`.toLowerCase();\n\n\tconst deepType = Object.prototype.toString.call(value).slice(8,-1).toLowerCase();\n\n\tif( deepType === 'generatorfunction' ) return 'function';\n\tif( deepType === 'document' ) return 'htmldocument';\n\tif( deepType === 'element' ) return 'htmlelement';\n\tif( /^html.*element$/.test(deepType) ) return 'htmlelement';\n\tif( /^.*iterator$/.test(deepType) ) return 'iterator';\n\n\treturn deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/)\n\t\t? deepType\n\t\t: ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isA\n */\n\n/**\n * Short form of \"getType\"-method with a more compact syntax.\n * Can identify all types listed in getType.\n *\n * @param {*} value - variable to check the type of\n * @param {String} type - the name of the type to check for, has to be a standard JS-type, is case insensitive\n * @returns {Boolean} target has type\n *\n * @memberof Basic:isA\n * @alias isA\n * @see getType\n * @example\n * let stringBool = (isA(test, 'boolean') && test) ? 'true' : 'false';\n */\nexport function isA(value, type){\n\tif(\n\t\t[\n\t\t\t'undefined',\n\t\t\t'null',\n\t\t\t'boolean',\n\t\t\t'number',\n\t\t\t'bigint',\n\t\t\t'string',\n\t\t\t'symbol',\n\t\t\t'function',\n\t\t\t'object',\n\t\t\t'array',\n\t\t\t'date',\n\t\t\t'error',\n\t\t\t'generator',\n\t\t\t'iterator',\n\t\t\t'regexp',\n\t\t\t'set',\n\t\t\t'weakset',\n\t\t\t'map',\n\t\t\t'weakmap',\n\t\t\t'htmldocument',\n\t\t\t'htmlelement',\n\t\t\t'htmlcollection',\n\t\t\t'nodelist',\n\t\t\t'window'\n\t\t].includes(`${type}`.toLowerCase())\n\t){\n\t\treturn getType(value) === `${type}`.toLowerCase();\n\t} else {\n\t\twarn(`${MODULE_NAME}:isA | \"${type}\" is not a recognized type`);\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isBoolean\n */\n\n/**\n * Returns if a value is a boolean value.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a boolean\n *\n * @memberof Basic:isBoolean\n * @alias isBoolean\n * @example\n * if( isBoolean(val) ){\n * console.log('val must be either true or false');\n * }\n */\nexport function isBoolean(value){\n\treturn isA(value, 'boolean');\n}\n\n\n\n/**\n * @namespace Basic:isNumber\n */\n\n/**\n * Returns if a value is a number.\n *\n * Hint: to check numbers in more detail, use isInt, isFloat and isNaN\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a number\n *\n * @memberof Basic:isNumber\n * @alias isNumber\n * @see isInt\n * @see isFloat\n * @see isNaN\n * @example\n * if( isNumber(val) ){\n * result = val * 5;\n * }\n */\nexport function isNumber(value){\n\treturn isA(value, 'number');\n}\n\n\n\n/**\n * @namespace Basic:isBigInt\n */\n\n/**\n * Returns if a value is a BigInt value.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a BigInt\n *\n * @memberof Basic:isBigInt\n * @alias isBigInt\n * @example\n * if( isBigInt(val) ){\n * console.log('this is a really huge number!');\n * }\n */\nexport function isBigInt(value){\n\treturn isA(value, 'bigint');\n}\n\n\n\n/**\n * @namespace Basic:isInt\n */\n\n/**\n * Returns if a value is truly a real integer value and not just an int-parsable value for example.\n * Since JS only knows the data type \"number\" all numbers are usable as floats by default, but not the\n * other way round.\n *\n * @param {*} intVal - the value the check\n * @returns {Boolean} true if intVal is a true integer value\n *\n * @memberof Basic:isInt\n * @alias isInt\n * @example\n * if( !isInt(val) ){\n * val = parseInt(val, 10);\n * }\n */\nexport function isInt(intVal){\n\treturn parseInt(intVal, 10) === intVal;\n}\n\n\n\n/**\n * @namespace Basic:isFloat\n */\n\n/**\n * Returns if a value is a numeric value, usable as a float number in any calculation.\n * Any number that fulfills isInt, is also considered a valid float, which lies in JS's\n * nature of not differentiating ints and floats by putting them both into a \"number\"-type.\n * So ints are always floats, but not necessarily the other way round.\n *\n * @param {*} floatVal - the value to check\n * @returns {Boolean} true if floatVal is usable in a float context\n *\n * @memberof Basic:isFloat\n * @alias isFloat\n * @example\n * if( !isFloat(val) ){\n * alert('val can not be calculated with!');\n * }\n */\nexport function isFloat(floatVal){\n\treturn parseFloat(floatVal) === floatVal;\n}\n\n\n\n/**\n * @namespace Basic:isNaN\n */\n\n/**\n * Returns if an expression is NaN or not.\n * This method employs two different approaches:\n * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something.\n * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being\n * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which\n * inspects the expression, tries to cast or parse a number from it and returns the result.\n *\n * @param {*} expression - the expression to check\n * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality\n * @returns {Boolean} true if expression is NaN\n *\n * @memberof Basic:isNaN\n * @alias isNaN\n * @example\n * if( !isNaN(suspiciousCalculatedValue) ){\n * return suspiciousCalculatedValue * 3;\n * }\n */\nexport function isNaN(expression, checkForIdentity=true){\n\tcheckForIdentity = orDefault(checkForIdentity, true, 'bool');\n\n\tif( checkForIdentity ){\n\t\treturn expression !== expression;\n\t} else {\n\t\treturn isNaN(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isString\n */\n\n/**\n * Returns if a value is a string.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a string\n *\n * @memberof Basic:isString\n * @alias isString\n * @example\n * if( isString(val) ){\n * return prefix+val;\n * }\n */\nexport function isString(value){\n\treturn isA(value, 'string');\n}\n\n\n\n/**\n * @namespace Basic:isSymbol\n */\n\n/**\n * Returns if a value is a symbol.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a symbol\n *\n * @memberof Basic:isSymbol\n * @alias isSymbol\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol\n * @example\n * if( isSymbol(val) ){\n * return val.description;\n * }\n */\nexport function isSymbol(value){\n\treturn isA(value, 'symbol');\n}\n\n\n\n/**\n * @namespace Basic:isFunction\n */\n\n/**\n * Returns if a value is a function.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a function\n *\n * @memberof Basic:isFunction\n * @alias isFunction\n * @example\n * if( isFunction(val) ){\n * val();\n * }\n */\nexport function isFunction(value){\n\treturn isA(value, 'function');\n}\n\n\n\n/**\n * @namespace Basic:isObject\n */\n\n/**\n * Returns if a value is an object.\n *\n * Hint: if you explicitly want to check for a plain object, use isPlainObject\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an object\n *\n * @memberof Basic:isObject\n * @alias isObject\n * @see isPlainObject\n * @example\n * if( isObject(val) ){\n * val.newProperty = 'foobar';\n * }\n */\nexport function isObject(value){\n\treturn isA(value, 'object');\n}\n\n\n\n/**\n * @namespace Basic:isPlainObject\n */\n\n/**\n * Returns if a value is an object literal, so so-called \"plain object.\n * A plain object is something like \"{hello : 'world'}\".\n *\n * This might especially be helpful when dealing with JSON configs, so quickly check if\n * something might even be parsed JSON (which in most cases is a plain object in js).\n *\n * Be aware that this function cannot differentiate between constructor-based simple objects and\n * plain objects declared inline. So, if someone took on the work to instantiate a base object and assign\n * properties either in a function or a constructor, we accept that as a plain object.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value seems to be a plain object\n *\n * @memberof Basic:isPlainObject\n * @alias isPlainObject\n * @example\n * const isParameterConfigObject = isPlainObject(param);\n */\nexport function isPlainObject(value){\n\treturn isObject(value)\n\t\t&& hasValue(value)\n\t\t&& (value.constructor === Object)\n\t\t&& Object.prototype.toString.call(value) === '[object Object]'\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isArray\n */\n\n/**\n * Returns if a value is an array.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an array\n *\n * @memberof Basic:isArray\n * @alias isArray\n * @example\n * if( isArray(val) ){\n * val.push('foobar');\n * }\n */\nexport function isArray(value){\n\treturn isA(value, 'array');\n}\n\n\n\n/**\n * @namespace Basic:isDate\n */\n\n/**\n * Returns if a value is a date.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a date\n *\n * @memberof Basic:isDate\n * @alias isDate\n * @example\n * if( isDate(val) ){\n * return val.toISOString();\n * }\n */\nexport function isDate(value){\n\treturn isA(value, 'date');\n}\n\n\n\n/**\n * @namespace Basic:isError\n */\n\n/**\n * Returns if a value is an error.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an error\n *\n * @memberof Basic:isError\n * @alias isError\n * @example\n * if( isError(val) ){\n * return val.message;\n * }\n */\nexport function isError(value){\n\treturn isA(value, 'error');\n}\n\n\n\n/**\n * @namespace Basic:isGenerator\n */\n\n/**\n * Returns if a value is a generator.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a generator\n *\n * @memberof Basic:isGenerator\n * @alias isGenerator\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator\n * @example\n * if( isGenerator(val) ){\n * return val.return(val.next().value);\n * }\n */\nexport function isGenerator(value){\n\treturn isA(value, 'generator');\n}\n\n\n\n/**\n * @namespace Basic:isIterator\n */\n\n/**\n * Returns if a value is an iterator.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an iterator\n *\n * @memberof Basic:isIterator\n * @alias isIterator\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator\n * @example\n * if( isIterator(val) ){\n * return val.next().value;\n * }\n */\nexport function isIterator(value){\n\treturn isA(value, 'iterator');\n}\n\n\n\n/**\n * @namespace Basic:isRegExp\n */\n\n/**\n * Returns if a value is a regular expression.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a regular expression\n *\n * @memberof Basic:isRegExp\n * @alias isRegExp\n * @example\n * if( isRegExp(val) ){\n * return val.test('foobar');\n * }\n */\nexport function isRegExp(value){\n\treturn isA(value, 'regexp');\n}\n\n\n\n/**\n * @namespace Basic:isSet\n */\n\n/**\n * Returns if a value is a set.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a set\n *\n * @memberof Basic:isSet\n * @alias isSet\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set\n * @example\n * if( isSet(val) ){\n * return val.has('foobar');\n * }\n */\nexport function isSet(value){\n\treturn isA(value, 'set');\n}\n\n\n\n/**\n * @namespace Basic:isWeakSet\n */\n\n/**\n * Returns if a value is a weak set.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a weak set\n *\n * @memberof Basic:isWeakSet\n * @alias isWeakSet\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet\n * @example\n * if( isWeakSet(val) ){\n * return val.has(someSymbol);\n * }\n */\nexport function isWeakSet(value){\n\treturn isA(value, 'weakset');\n}\n\n\n\n/**\n * @namespace Basic:isMap\n */\n\n/**\n * Returns if a value is a map.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a map\n *\n * @memberof Basic:isMap\n * @alias isMap\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map\n * @example\n * if( isMap(val) ){\n * return val.get('foobar');\n * }\n */\nexport function isMap(value){\n\treturn isA(value, 'map');\n}\n\n\n\n/**\n * @namespace Basic:isWeakMap\n */\n\n/**\n * Returns if a value is a weak map.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a weak map\n *\n * @memberof Basic:isWeakMap\n * @alias isWeakMap\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap\n * @example\n * if( isWeakMap(val) ){\n * return val.get('foobar');\n * }\n */\nexport function isWeakMap(value){\n\treturn isA(value, 'weakmap');\n}\n\n\n\n/**\n * @namespace Basic:isDocument\n */\n\n/**\n * Returns if a value is an HTML document.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an HTML document\n *\n * @memberof Basic:isDocument\n * @alias isDocument\n * @example\n * if( isDocument(val) ){\n * return val.body;\n * }\n */\nexport function isDocument(value){\n\treturn isA(value, 'htmldocument');\n}\n\n\n\n/**\n * @namespace Basic:isElement\n */\n\n/**\n * Returns if a value is an HTML element.\n * Be aware, that this explicitly means an element, not necessarily any node.\n * So text nodes, comments and such do not qualify.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an HTML element\n *\n * @memberof Basic:isElement\n * @alias isElement\n * @example\n * if( isElement(target) ){\n * target.classList.add('foo');\n * }\n */\nexport function isElement(value){\n\treturn isA(value, 'htmlelement');\n}\n\n\n\n/**\n * @namespace Basic:isCollection\n */\n\n/**\n * Returns if a value is a collection of html elements.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a collection of html elements\n *\n * @memberof Basic:isCollection\n * @alias isCollection\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection\n * @example\n * if( isCollection(val) ){\n * return val.item(0);\n * }\n */\nexport function isCollection(value){\n\treturn isA(value, 'htmlcollection');\n}\n\n\n\n/**\n * @namespace Basic:isNodeList\n */\n\n/**\n * Returns if a value is a node list.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a node list\n *\n * @memberof Basic:isNodeList\n * @alias isNodeList\n * @see https://developer.mozilla.org/en-US/docs/Web/API/NodeList\n * @example\n * if( isNodeList(val) ){\n * return val.item(0);\n * }\n */\nexport function isNodeList(value){\n\treturn isA(value, 'nodelist');\n}\n\n\n\n/**\n * @namespace Basic:isWindow\n */\n\n/**\n * Returns if a value is a window.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a window\n *\n * @memberof Basic:isWindow\n * @alias isWindow\n * @example\n * if( isWindow(val) ){\n * return val.location.origin;\n * }\n */\nexport function isWindow(value){\n\treturn isA(value, 'window');\n}\n\n\n\n/**\n * @namespace Basic:isEventTarget\n */\n\n/**\n * Returns if a value is an EventTarget, which means that it is able to dispatch and receive events.\n * This is determined via duck-typing and not via class inheritance check, since this method is not\n * about type-safety, but the question if we can use the target for events, which is simply determined\n * by three essential object methods: addEventListener, removeEventListener and dispatchEvent. All\n * objects supporting these are fine with us.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value supports event methods\n *\n * @memberof Basic:isEventTarget\n * @alias isEventTarget\n * @example\n * if( isEventTarget(target) ){\n * target.dispatchEvent(new CustomEvent('foobar'));\n * }\n */\nexport function isEventTarget(value){\n\treturn hasValue(value)\n\t\t&& isFunction(value.addEventListener)\n\t\t&& isFunction(value.removeEventListener)\n\t\t&& isFunction(value.dispatchEvent)\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isSelector\n */\n\n/**\n * Returns if a value is a valid selector, usable in methods such as querySelector\n * and querySelectorAll.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a valid selector\n *\n * @memberof Basic:isSelector\n * @alias isSelector\n * @example\n * if( isSelector(selector) ){\n * document.querySelector(selector)?.style.setProperty('color', 'red');\n * }\n */\nexport function isSelector(value){\n\t// almost all values like \"null\", \"undefined\" and \"NaN\" are accepted querySelectors, numbers are not\n\tvalue = orDefault(value, 0, 'str');\n\n\tconst fragment = document.createDocumentFragment();\n\n\ttry {\n\t\tfragment.querySelector(value);\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:isPotentialId\n */\n\n/**\n * Determines if a given value is potentially a valid id for something, because it matches a format of given\n * prefix, postfix and id regex. \"Potential\", because we can only assume by the format, we do not actually know\n * if the id really matches anything like a database entry for example.\n *\n * @param {(String|Number)} value - the value to test, will be stringified\n * @param {?String} [prefix=''] - a prefix for the id\n * @param {?String} [idRex='[1-9][0-9]*'] - the regex string to use to identify the id part of the value\n * @param {?String} [postfix=''] - a postfix for the id\n * @param {?Boolean} [maskFixes=true] - usually, prefixes are not treated as regexes and are automatically masked, if you'd like to define complex pre- and postfixes using regexes, set this to false\n * @returns {String|Boolean} if value is potential id according to format, the id is returned as a string (still usable as a truthy value), otherwise the return value is false\n *\n * @memberof Basic:isPotentialId\n * @alias isPotentialId\n * @example\n * if( isPotentialId(id, 'test_(', '[0-9]+', ')') ){\n * createJsonRequest(`/backend/${id}`).then(() => { alert('done'); });\n * }\n */\nexport function isPotentialId(value, prefix='', idRex='[1-9][0-9]*', postfix='', maskFixes=true){\n\tvalue = `${value}`;\n\tprefix = orDefault(prefix, '', 'str');\n\tidRex = orDefault(idRex, '[1-9][0-9]*', 'str');\n\tpostfix = orDefault(postfix, '', 'str');\n\tmaskFixes = orDefault(maskFixes, true, 'bool');\n\n\tconst mask = str => `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n\n\tlet rex;\n\tif( maskFixes ){\n\t\trex = new RegExp(`^${mask(prefix)}(${idRex})${mask(postfix)}$`);\n\t} else {\n\t\trex = new RegExp(`^${prefix}(${idRex})${postfix}$`);\n\t}\n\n\tconst matches = rex.exec(value);\n\treturn hasValue(matches) ? matches[1] : false;\n}\n\n\n\n/**\n * @namespace Basic:minMax\n */\n\n/**\n * Checks if a value is within bounds of a minimum and maximum and returns\n * the value or the upper or lower bound respectively.\n *\n * Accepts all values comparable with > and <.\n *\n * @param {*} min - the lower bound\n * @param {*} value - the value to check\n * @param {*} max - the upper bound\n * @throws error if min is not smaller than max\n * @returns {*} value, min or max\n *\n * @memberof Basic:minMax\n * @alias minMax\n * @example\n * let croppedVal = minMax(-100, value, 100);\n */\nexport function minMax(min, value, max){\n\tassert(min <= max, `${MODULE_NAME}:minMax | min can not be larger than max`);\n\n\treturn (value < min)\n\t\t? min\n\t\t: (\n\t\t\t(value > max)\n\t\t\t\t? max\n\t\t\t\t: value\n\t\t)\n\t;\n}\n\n\n\n/**\n * @namespace Basic:Deferred\n */\n\n/**\n * @typedef Deferred\n * @type {Object}\n * @property {Promise} promise - the wrapped promise\n * @property {Function} resolve - resolves the wrapped promise with given value\n * @property {Function} reject - rejects the wrapped promise with given error\n * @property {Function} then - defines a success handler for the wrapped promise and returns its result\n * @property {Function} catch - defines an error handler for the wrapped promise and returns its result\n * @property {Function} finally - defines a \"settled\" handler for the wrapped promise and returns its result\n * @property {String} status - holds the current resolution status, can either be \"pending\", \"fulfilled\" or \"rejected\"\n * @property {Function} isSettled - returns true, if the Deferred is either \"fulfilled\" or \"rejected\"\n * @property {?*} [provision=null] - may contain (a) provisional value(s) to use for a newly instantiated Deferred, before it has resolved to the actual value(s)\n */\n\n/**\n * Class that wraps a Promise, to allow resolving and rejecting outside the\n * Promise's function scope. This allows for decoupled handling of states and\n * handling promises as references in a distributed context, like a class, where\n * a Deferred might then represent an async state.\n *\n * Deferreds also provide accessible status information, normal Promises do not have.\n * Accessing the \"status\" property returns the current status, being either \"pending\",\n * \"fulfilled\" or \"rejected\". You may also check if the Deferred has been settled via\n * \"isSettled()\". If you want to provide a preliminary result, available before the\n * promise has settled, you may set this result as a payload using the \"provision\" property.\n *\n * This follows ideas by jQuery and Q Promises:\n * - https://api.jquery.com/jQuery.Deferred/\n * - https://github.com/kriskowal/q/wiki/Coming-from-jQuery#deferreds-promises-resolvers\n *\n * Keep in mind, that Promises might need a polyfill such as core-js.\n *\n * @memberof Basic:Deferred\n * @name Deferred\n * @example\n * const doStuff = new Deferred();\n * doStuff.provision = 'provisional value';\n * doStuff\n * .then(value => { alert(`yeah, ready with \"${value}\"!`); })\n * .catch(error => { console.error(error); })\n * .finally(() => { console.info('has been settled); })\n * ;\n * if( foobar === 42 ){\n * doStuff.resolve(42);\n * } else {\n * doStuff.reject(new Error('not 42!'));\n * }\n * console.info(doStuff.status);\n */\nexport class Deferred {\n\tconstructor(){\n\t\tconst\n\t\t\tSTATUS_PENDING = 'pending',\n\t\t\tSTATUS_FULFILLED = 'fulfilled',\n\t\t\tSTATUS_REJECTED = 'rejected'\n\t\t;\n\t\tthis.resolve = null;\n\t\tthis.reject = null;\n\t\tthis.provision = null;\n\t\tthis.status = STATUS_PENDING;\n\t\tthis.isSettled = () => [STATUS_FULFILLED, STATUS_REJECTED].includes(this.status);\n\t\tthis.promise = new Promise((resolve, reject) => {\n\t\t\tthis.resolve = resolution => {\n\t\t\t\tthis.status = STATUS_FULFILLED;\n\t\t\t\tresolve(resolution);\n\t\t\t};\n\t\t\tthis.reject = rejection => {\n\t\t\t\tthis.status = STATUS_REJECTED;\n\t\t\t\treject(rejection);\n\t\t\t};\n\t\t});\n\t}\n\n\tthen(f){\n\t\treturn this.promise.then(f);\n\t}\n\n\tcatch(f){\n\t\treturn this.promise.catch(f);\n\t}\n\n\tfinally(f){\n\t\treturn this.promise.finally(f);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:Observable\n */\n\n/**\n * @typedef Observable\n * @type {Object}\n * @property {Function} getValue - returns the current value\n * @property {Function} setValue - sets a new value, which will subsequently trigger all subscriptions\n * @property {Function} subscribe - register a given function to be executed on any value change, the subscription receives the new and the old value on each execution, returns the subscription value, which can later be used to unsubscribe again\n * @property {Function} unsubscribe - removes a given subscription again, use subscription value returned by subscribe here\n */\n\n/**\n * A class offering the bare minimum feature set to observe a value and subscribe to future value changes.\n * No automatic magic going on here, this simply follows a basic subscription pattern, where each subscription is\n * a function, being called with a newly set value. This closely resembles the kind of observables knockout is using.\n *\n * @memberof Basic:Observable\n * @name Observable\n * @example\n * const status = new Observable('ok');\n * const subscription = status.subscribe(s => {\n * console.log(`status changed to: ${s}`);\n * });\n * status.setValue('oh noez');\n * status.unsubscribe(subscription);\n */\nexport class Observable {\n\tconstructor(initialValue){\n\t\tthis.__className__ = 'Observable';\n\t\tthis._value = initialValue;\n\t\tthis._subscriptions = [];\n\t}\n\n\tgetValue(){\n\t\treturn this._value;\n\t}\n\n\tsetValue(newValue, force=false){\n\t\tconst\n\t\t\toldValue = this._value,\n\t\t\tisNewValue = oldValue !== newValue\n\t\t;\n\t\tthis._value = newValue;\n\t\tif( isNewValue || force ){\n\t\t\tthis._subscriptions.forEach(s => s(newValue, oldValue));\n\t\t}\n\t}\n\n\tsubscribe(subscription){\n\t\tconst __methodName__ = 'subscribe';\n\t\tassert(isFunction(subscription), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`);\n\t\tif( this._subscriptions.indexOf(subscription) < 0 ){\n\t\t\tthis._subscriptions = [...this._subscriptions, subscription];\n\t\t}\n\t\treturn subscription;\n\t}\n\n\tunsubscribe(subscription){\n\t\tthis._subscriptions = this._subscriptions.filter(s => s !== subscription);\n\t}\n\n\ttoString(){\n\t\treturn `${this._value}`;\n\t}\n}\n"]} \ No newline at end of file diff --git a/dist/context.js b/dist/context.js index de852cc8..091bc847 100644 --- a/dist/context.js +++ b/dist/context.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Context */ -const MODULE_NAME="Context";import{hasValue,isA,orDefault,Observable}from"./basic.js";import{throttle}from"./functions.js";import{reschedule}from"./timers.js";const INTERACTION_TYPE_DETECTION={touchHappening:!1,touchEndingTimer:null,touchStartHandler(){INTERACTION_TYPE_DETECTION.touchHappening=!0,"touch"!==CURRENT_INTERACTION_TYPE.getValue()&&CURRENT_INTERACTION_TYPE.setValue("touch")},touchEndHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},blurHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},mouseMoveHandler:throttle(1e3,(function(){CURRENT_INTERACTION_TYPE.getValue("pointer")&&!INTERACTION_TYPE_DETECTION.touchHappening&&CURRENT_INTERACTION_TYPE.setValue("pointer")}))};export let CURRENT_INTERACTION_TYPE;export function browserSupportsHistoryManipulation(){return hasValue(window.history)&&isA(window.history.pushState,"function")&&isA(window.history.replaceState,"function")}export function contextHasHighDpi(){return!!window.matchMedia&&window.matchMedia("only screen and (-webkit-min-device-pixel-ratio: 1.5),only screen and (-o-min-device-pixel-ratio: 3/2),only screen and (min--moz-device-pixel-ratio: 1.5),only screen and (min-device-pixel-ratio: 1.5),only screen and (min-resolution: 144dpi),only screen and (min-resolution: 1.5dppx)").matches}export function getBrowserScrollbarWidth(){const e=document.createElement("div");e.style.visibility="hidden",e.style.opacity="0",e.style.pointerEvents="none",e.style.overflow="scroll",e.style.position="fixed",e.style.top="0",e.style.right="0",e.style.left="0",e.style.height="50px";const t=document.createElement("div");t.style.width="100%",t.style.height="100px",e.appendChild(t),document.body.appendChild(e);const n=e.offsetWidth-t.offsetWidth;return document.body.removeChild(e),n}export function detectInteractionType(e=!1){return e=orDefault(e,!1,"bool"),hasValue(CURRENT_INTERACTION_TYPE)||(CURRENT_INTERACTION_TYPE=new Observable(""),"ontouchstart"in document&&"ontouchend"in document&&window.navigator.maxTouchPoints>0?CURRENT_INTERACTION_TYPE.setValue("touch"):CURRENT_INTERACTION_TYPE.setValue("pointer"),document.addEventListener("touchstart",INTERACTION_TYPE_DETECTION.touchStartHandler),document.addEventListener("touchend",INTERACTION_TYPE_DETECTION.touchEndHandler),window.addEventListener("blur",INTERACTION_TYPE_DETECTION.blurHandler),document.addEventListener("mousemove",INTERACTION_TYPE_DETECTION.mouseMoveHandler)),e?CURRENT_INTERACTION_TYPE:CURRENT_INTERACTION_TYPE.getValue()}export function detectAppleDevice(e=null){let t=/iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),n=null;if(Array.isArray(t)&&t.length>0?t=t[0]:(t=/^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform),Array.isArray(t)&&t.length>0?(t=t[0],"Mac"===t&&(t="Macintosh")):t=null),hasValue(t)){switch("Macintosh"===t&&window.navigator.maxTouchPoints>1&&(t="iPad"),t){case"iPad":n="ipad";break;case"iPhone":n="iphone";break;case"iPod":n="ipod";break;case"Macintosh":n="mac"}isA(e,"function")&&(n=e(n))}return n}export function getBrowserLanguage(e=null){let t=null;if(hasValue(window.navigator.languages)){const e=Array.from(window.navigator.languages);isA(e,"array")&&e.length>0&&(t=`${e[0]}`)}hasValue(t)||["language","browserLanguage","userLanguage","systemLanguage"].forEach((e=>{if(!hasValue(t)){const n=window.navigator[e];t=hasValue(n)?`${n}`:null}})),!hasValue(t)&&hasValue(e)&&(t=`${e}`);const n=t.split("-");t=n[0].toLowerCase().trim();const o=n?.[1]?.toUpperCase()?.trim();return t=hasValue(o)?`${t}-${o}`:t,t}export function getLocale(e=null,t=null){e=orDefault(e,document.documentElement);const n={code:null,country:null,language:null,isFallback:!1};let o=isA(e.getAttribute,"function")?e.getAttribute("lang"):null;if(!hasValue(o)&&hasValue(t)&&(o=`${t}`,n.isFallback=!0),hasValue(o)){const e=`${o}`.split("-");n.country=e?.[1]?.toLowerCase()?.trim(),n.language=e[0].toLowerCase().trim(),n.code=hasValue(n.country)?`${n.language}-${n.country.toUpperCase()}`:n.language}return n}export function getBrowserLocale(e=null){return getLocale({getAttribute:()=>getBrowserLanguage(e)},e)} +const MODULE_NAME="Context";import{hasValue,isFunction,isArray,orDefault,Observable}from"./basic.js";import{throttle}from"./functions.js";import{reschedule}from"./timers.js";const INTERACTION_TYPE_DETECTION={touchHappening:!1,touchEndingTimer:null,touchStartHandler(){INTERACTION_TYPE_DETECTION.touchHappening=!0,"touch"!==CURRENT_INTERACTION_TYPE.getValue()&&CURRENT_INTERACTION_TYPE.setValue("touch")},touchEndHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},blurHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},mouseMoveHandler:throttle(1e3,(function(){CURRENT_INTERACTION_TYPE.getValue("pointer")&&!INTERACTION_TYPE_DETECTION.touchHappening&&CURRENT_INTERACTION_TYPE.setValue("pointer")}))};export let CURRENT_INTERACTION_TYPE;export function browserSupportsHistoryManipulation(){return hasValue(window.history)&&isFunction(window.history.pushState)&&isFunction(window.history.replaceState)}export function contextHasHighDpi(){return!!window.matchMedia&&window.matchMedia("only screen and (-webkit-min-device-pixel-ratio: 1.5),only screen and (-o-min-device-pixel-ratio: 3/2),only screen and (min--moz-device-pixel-ratio: 1.5),only screen and (min-device-pixel-ratio: 1.5),only screen and (min-resolution: 144dpi),only screen and (min-resolution: 1.5dppx)").matches}export function getBrowserScrollbarWidth(){const e=document.createElement("div");e.style.visibility="hidden",e.style.opacity="0",e.style.pointerEvents="none",e.style.overflow="scroll",e.style.position="fixed",e.style.top="0",e.style.right="0",e.style.left="0",e.style.height="50px";const t=document.createElement("div");t.style.width="100%",t.style.height="100px",e.appendChild(t),document.body.appendChild(e);const n=e.offsetWidth-t.offsetWidth;return document.body.removeChild(e),n}export function detectInteractionType(e=!1){return e=orDefault(e,!1,"bool"),hasValue(CURRENT_INTERACTION_TYPE)||(CURRENT_INTERACTION_TYPE=new Observable(""),"ontouchstart"in document&&"ontouchend"in document&&window.navigator.maxTouchPoints>0?CURRENT_INTERACTION_TYPE.setValue("touch"):CURRENT_INTERACTION_TYPE.setValue("pointer"),document.addEventListener("touchstart",INTERACTION_TYPE_DETECTION.touchStartHandler),document.addEventListener("touchend",INTERACTION_TYPE_DETECTION.touchEndHandler),window.addEventListener("blur",INTERACTION_TYPE_DETECTION.blurHandler),document.addEventListener("mousemove",INTERACTION_TYPE_DETECTION.mouseMoveHandler)),e?CURRENT_INTERACTION_TYPE:CURRENT_INTERACTION_TYPE.getValue()}export function detectAppleDevice(e=null){let t=/iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),n=null;if(Array.isArray(t)&&t.length>0?t=t[0]:(t=/^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform),Array.isArray(t)&&t.length>0?(t=t[0],"Mac"===t&&(t="Macintosh")):t=null),hasValue(t)){switch("Macintosh"===t&&window.navigator.maxTouchPoints>1&&(t="iPad"),t){case"iPad":n="ipad";break;case"iPhone":n="iphone";break;case"iPod":n="ipod";break;case"Macintosh":n="mac"}isFunction(e)&&(n=e(n))}return n}export function getBrowserLanguage(e=null){let t=null;if(hasValue(window.navigator.languages)){const e=Array.from(window.navigator.languages);isArray(e)&&e.length>0&&(t=`${e[0]}`)}hasValue(t)||["language","browserLanguage","userLanguage","systemLanguage"].forEach((e=>{if(!hasValue(t)){const n=window.navigator[e];t=hasValue(n)?`${n}`:null}})),!hasValue(t)&&hasValue(e)&&(t=`${e}`);const n=t.split("-");t=n[0].toLowerCase().trim();const o=n?.[1]?.toUpperCase()?.trim();return t=hasValue(o)?`${t}-${o}`:t,t}export function getLocale(e=null,t=null){e=orDefault(e,document.documentElement);const n={code:null,country:null,language:null,isFallback:!1};let o=isFunction(e.getAttribute)?e.getAttribute("lang"):null;if(!hasValue(o)&&hasValue(t)&&(o=`${t}`,n.isFallback=!0),hasValue(o)){const e=`${o}`.split("-");n.country=e?.[1]?.toLowerCase()?.trim(),n.language=e[0].toLowerCase().trim(),n.code=hasValue(n.country)?`${n.language}-${n.country.toUpperCase()}`:n.language}return n}export function getBrowserLocale(e=null){return getLocale({getAttribute:()=>getBrowserLanguage(e)},e)} //# sourceMappingURL=context.js.map diff --git a/dist/context.js.map b/dist/context.js.map index 3297b540..22880d00 100644 --- a/dist/context.js.map +++ b/dist/context.js.map @@ -1 +1 @@ -{"version":3,"file":"context.js","names":["MODULE_NAME","hasValue","isA","orDefault","Observable","throttle","reschedule","INTERACTION_TYPE_DETECTION","touchHappening","touchEndingTimer","touchStartHandler","CURRENT_INTERACTION_TYPE","getValue","setValue","touchEndHandler","blurHandler","mouseMoveHandler","browserSupportsHistoryManipulation","window","history","pushState","replaceState","contextHasHighDpi","matchMedia","matches","getBrowserScrollbarWidth","sandbox","document","createElement","style","visibility","opacity","pointerEvents","overflow","position","top","right","left","height","scrollbarEnforcer","width","appendChild","body","scrollbarWidth","offsetWidth","removeChild","detectInteractionType","returnObservable","navigator","maxTouchPoints","addEventListener","detectAppleDevice","additionalTest","family","exec","userAgent","deviceType","Array","isArray","length","platform","getBrowserLanguage","fallbackLanguage","language","languages","browserLanguages","from","forEach","browserLanguagePropertyKey","browserLanguage","languageParts","split","toLowerCase","trim","country","toUpperCase","getLocale","element","documentElement","locale","code","isFallback","langAttr","getAttribute","localeParts","getBrowserLocale"],"sources":["context.js"],"mappings":";;;AAQA,MAAMA,YAAc,iBAMZC,SAAUC,IAAKC,UAAWC,eAAiB,oBAC3CC,aAAe,wBACfC,eAAiB,cAMzB,MAAMC,2BAA6B,CAClCC,gBAAiB,EACjBC,iBAAmB,KACnBC,oBACCH,2BAA2BC,gBAAiB,EACA,UAAxCG,yBAAyBC,YAC5BD,yBAAyBE,SAAS,QAEpC,EACAC,kBACCP,2BAA2BE,iBAAmBH,WAAWC,2BAA2BE,iBAAkB,MAAM,KAC3GF,2BAA2BC,gBAAiB,CAAK,GAEnD,EACAO,cACCR,2BAA2BE,iBAAmBH,WAAWC,2BAA2BE,iBAAkB,MAAM,KAC3GF,2BAA2BC,gBAAiB,CAAK,GAEnD,EACAQ,iBAAmBX,SAAS,KAAM,WAC5BM,yBAAyBC,SAAS,aAAgBL,2BAA2BC,gBACjFG,yBAAyBE,SAAS,UAEpC,YAGM,IAAIF,gCAuBJ,SAASM,qCACf,OAAOhB,SAASiB,OAAOC,UACnBjB,IAAIgB,OAAOC,QAAQC,UAAW,aAC9BlB,IAAIgB,OAAOC,QAAQE,aAAc,WAEtC,QAsBO,SAASC,oBACf,QAAIJ,OAAOK,YACHL,OAAOK,WACb,8RAMCC,OAIJ,QAwBO,SAASC,2BACf,MAAMC,EAAUC,SAASC,cAAc,OACvCF,EAAQG,MAAMC,WAAa,SAC3BJ,EAAQG,MAAME,QAAU,IACxBL,EAAQG,MAAMG,cAAgB,OAC9BN,EAAQG,MAAMI,SAAW,SACzBP,EAAQG,MAAMK,SAAW,QACzBR,EAAQG,MAAMM,IAAM,IACpBT,EAAQG,MAAMO,MAAQ,IACtBV,EAAQG,MAAMQ,KAAO,IAErBX,EAAQG,MAAMS,OAAS,OAEvB,MAAMC,EAAoBZ,SAASC,cAAc,OACjDW,EAAkBV,MAAMW,MAAQ,OAChCD,EAAkBV,MAAMS,OAAS,QAEjCZ,EAAQe,YAAYF,GACpBZ,SAASe,KAAKD,YAAYf,GAE1B,MAAMiB,EAAiBjB,EAAQkB,YAAcL,EAAkBK,YAI/D,OAFAjB,SAASe,KAAKG,YAAYnB,GAEnBiB,CACR,QAmCO,SAASG,sBAAsBC,GAAiB,GAiBtD,OAhBAA,EAAmB5C,UAAU4C,GAAkB,EAAO,QAEjD9C,SAASU,4BACbA,yBAA2B,IAAIP,WAAW,IACrC,iBAAkBuB,UAAc,eAAgBA,UAAcT,OAAO8B,UAAUC,eAAiB,EACpGtC,yBAAyBE,SAAS,SAElCF,yBAAyBE,SAAS,WAGnCc,SAASuB,iBAAiB,aAAc3C,2BAA2BG,mBACnEiB,SAASuB,iBAAiB,WAAY3C,2BAA2BO,iBACjEI,OAAOgC,iBAAiB,OAAQ3C,2BAA2BQ,aAC3DY,SAASuB,iBAAiB,YAAa3C,2BAA2BS,mBAG5D+B,EAAmBpC,yBAA2BA,yBAAyBC,UAC/E,QA2BO,SAASuC,kBAAkBC,EAAe,MAChD,IACCC,EAAS,6BAA6BC,KAAKpC,OAAO8B,UAAUO,WAC5DC,EAAa,KAmBd,GAhBIC,MAAMC,QAAQL,IAAYA,EAAOM,OAAS,EAC7CN,EAASA,EAAO,IAEhBA,EAAS,0BAA0BC,KAAKpC,OAAO8B,UAAUY,UAErDH,MAAMC,QAAQL,IAAYA,EAAOM,OAAS,GAC7CN,EAASA,EAAO,GAED,QAAXA,IACHA,EAAS,cAGVA,EAAS,MAIPpD,SAASoD,GAAS,CAUrB,OANa,cAAXA,GACGnC,OAAO8B,UAAUC,eAAiB,IAEtCI,EAAS,QAGFA,GACP,IAAK,OACJG,EAAa,OACd,MACA,IAAK,SACJA,EAAa,SACd,MACA,IAAK,OACJA,EAAa,OACd,MACA,IAAK,YACJA,EAAa,MAIXtD,IAAIkD,EAAgB,cACvBI,EAAaJ,EAAeI,GAE9B,CAEA,OAAOA,CACR,QAwBO,SAASK,mBAAmBC,EAAiB,MACnD,IAAIC,EAAW,KAEf,GAAI9D,SAASiB,OAAO8B,UAAUgB,WAAY,CACzC,MAAMC,EAAmBR,MAAMS,KAAKhD,OAAO8B,UAAUgB,WACjD9D,IAAI+D,EAAkB,UAAaA,EAAiBN,OAAS,IAChEI,EAAW,GAAGE,EAAiB,KAEjC,CAEKhE,SAAS8D,IACb,CAAC,WAAY,kBAAmB,eAAgB,kBAAkBI,SAAQC,IACzE,IAAKnE,SAAS8D,GAAW,CACxB,MAAMM,EAAkBnD,OAAO8B,UAAUoB,GACzCL,EAAW9D,SAASoE,GAAmB,GAAGA,IAAoB,IAC/D,MAIGpE,SAAS8D,IAAa9D,SAAS6D,KACnCC,EAAW,GAAGD,KAGf,MAAMQ,EAAgBP,EAASQ,MAAM,KACrCR,EAAWO,EAAc,GAAGE,cAAcC,OAC1C,MAAMC,EAAUJ,IAAgB,IAAIK,eAAeF,OAGnD,OAFAV,EAAW9D,SAASyE,GAAW,GAAGX,KAAYW,IAAYX,EAEnDA,CACR,QAuCO,SAASa,UAAUC,EAAQ,KAAMf,EAAiB,MAExDe,EAAU1E,UAAU0E,EAASlD,SAASmD,iBAEtC,MAAMC,EAAS,CACdC,KAAO,KACPN,QAAU,KACVX,SAAW,KACXkB,YAAa,GAGd,IAAIC,EAAWhF,IAAI2E,EAAQM,aAAc,YAAeN,EAAQM,aAAa,QAAU,KAMvF,IALKlF,SAASiF,IAAajF,SAAS6D,KACnCoB,EAAW,GAAGpB,IACdiB,EAAOE,YAAa,GAGjBhF,SAASiF,GAAW,CACvB,MAAME,EAAc,GAAGF,IAAWX,MAAM,KACxCQ,EAAOL,QAAUU,IAAc,IAAIZ,eAAeC,OAClDM,EAAOhB,SAAWqB,EAAY,GAAGZ,cAAcC,OAC/CM,EAAOC,KAAO/E,SAAS8E,EAAOL,SAAW,GAAGK,EAAOhB,YAAYgB,EAAOL,QAAQC,gBAAkBI,EAAOhB,QACxG,CAEA,OAAOgB,CACR,QAqCO,SAASM,iBAAiBvB,EAAiB,MACjD,OAAOc,UAAU,CAACO,aAAY,IAAWtB,mBAAmBC,IAAuBA,EACpF","sourcesContent":["/*!\n * Module Context\n */\n\n/**\n * @namespace Context\n */\n\nconst MODULE_NAME = 'Context';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {hasValue, isA, orDefault, Observable} from './basic.js';\nimport {throttle} from './functions.js';\nimport {reschedule} from './timers.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst INTERACTION_TYPE_DETECTION = {\n\ttouchHappening : false,\n\ttouchEndingTimer : null,\n\ttouchStartHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchHappening = true;\n\t\tif( CURRENT_INTERACTION_TYPE.getValue() !== 'touch' ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t}\n\t},\n\ttouchEndHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tblurHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tmouseMoveHandler : throttle(1000, function(){\n\t\tif( (CURRENT_INTERACTION_TYPE.getValue('pointer')) && !INTERACTION_TYPE_DETECTION.touchHappening ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\t})\n};\n\nexport let CURRENT_INTERACTION_TYPE;\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Context:browserSupportsHistoryManipulation\n */\n\n/**\n * Detects if the browser supports history manipulation, by checking the most common\n * methods for presence in the history-object.\n *\n * @returns {Boolean} true if browser seems to support history manipulation\n *\n * @memberof Context:browserSupportsHistoryManipulation\n * @alias browserSupportsHistoryManipulation\n * @example\n * if( browserSupportsHistoryManipulation() ){\n * window.history.replaceState(null, 'test', '/test');\n * }\n */\nexport function browserSupportsHistoryManipulation(){\n\treturn hasValue(window.history)\n\t\t&& isA(window.history.pushState, 'function')\n\t\t&& isA(window.history.replaceState, 'function')\n\t;\n}\n\n\n\n/**\n * @namespace Context:contextHasHighDpi\n */\n\n/**\n * Checks if the context would benefit from high DPI graphics.\n *\n * @returns {Boolean} true if device has high DPI, false if not or browser does not support media queries\n *\n * @memberof Context:contextHasHighDpi\n * @alias contextHasHighDpi\n * @example\n * if( contextHasHighDpi() ){\n * document.querySelectorAll('img').forEach(img => {\n * img.setAttribute('src', img.getAttribute('src').replace('.jpg', '@2x.jpg'));\n * });\n * }\n */\nexport function contextHasHighDpi(){\n\tif( window.matchMedia ){\n\t\treturn window.matchMedia(\n\t\t\t'only screen and (-webkit-min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (-o-min-device-pixel-ratio: 3/2),'\n\t\t\t+'only screen and (min--moz-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-resolution: 144dpi),'\n\t\t\t+'only screen and (min-resolution: 1.5dppx)'\n\t\t).matches;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Context:getBrowserScrollbarWidth\n */\n\n/**\n * Returns the current context's scrollbar width. Returns 0 if scrollbar is over content.\n * There are edge cases in which we might want to calculate positions in respect to the\n * actual width of the scrollbar. For example when working with elements with a 100vw width.\n *\n * This method temporarily inserts three elements into the body while forcing the body to\n * actually show scrollbars, measuring the difference between 100vw and 100% on the body and\n * returns the result.\n *\n * @returns {Number} the width of the body scrollbar in pixels\n *\n * @memberof Context:getBrowserScrollbarWidth\n * @alias getBrowserScrollbarWidth\n * @example\n * foobarElement.style.width = `calc(100vw - ${getBrowserScrollbarWidth()}px)`;\n */\nexport function getBrowserScrollbarWidth(){\n\tconst sandbox = document.createElement('div');\n\tsandbox.style.visibility = 'hidden';\n\tsandbox.style.opacity = '0';\n\tsandbox.style.pointerEvents = 'none';\n\tsandbox.style.overflow = 'scroll';\n\tsandbox.style.position = 'fixed';\n\tsandbox.style.top = '0';\n\tsandbox.style.right = '0';\n\tsandbox.style.left = '0';\n\t// firefox needs container to be at least 30px high to display scrollbar\n\tsandbox.style.height = '50px';\n\n\tconst scrollbarEnforcer = document.createElement('div');\n\tscrollbarEnforcer.style.width = '100%';\n\tscrollbarEnforcer.style.height = '100px';\n\n\tsandbox.appendChild(scrollbarEnforcer);\n\tdocument.body.appendChild(sandbox);\n\n\tconst scrollbarWidth = sandbox.offsetWidth - scrollbarEnforcer.offsetWidth;\n\n\tdocument.body.removeChild(sandbox);\n\n\treturn scrollbarWidth;\n}\n\n\n\n/**\n * @namespace Context:detectInteractionType\n */\n\n/**\n * Try to figure out the current type of interaction between the user and the document.\n * This is determined by the input device and is currently limited to either \"pointer\" or \"touch\".\n *\n * On call the function returns an educated guess about the fact what interaction type might be more\n * probable based on browser features and sets up event listeners to update Context module's CURRENT_INTERACTION_TYPE\n * observable (to which you may subscribe to be informed about updates), when interaction type should change while\n * the page is being interacted with. In case a touch occurs we determine touch interaction and\n * on mousemove we determine pointer interaction. If you use this observable to set up a class on your document for\n * example you can even relatively safely handle dual devices like a surface book.\n *\n * Hint: because touch devices also emit a single mousemove after touchend with a single touch we have to block\n * mousemove detection for 1s after the last touchend. Therefore, it takes up to 1s after the last touch event until\n * we are able to detect the change to a pointer device.\n *\n * @param {?Boolean} [returnObservable=false] - if set to true, the call returns Context module's CURRENT_INTERACTION_TYPE observable\n * @returns {String|Observable} interaction type string \"pointer\" or \"touch\", or the CURRENT_INTERACTION_TYPE observable\n *\n * @memberof Context:detectInteractionType\n * @alias detectInteractionType\n * @example\n * let interactionTypeGuess = detectInteractionType();\n * detectInteractionType(true).subscribe(function(type){\n * document.body.classList.toggle('touch', type === 'touch');\n * });\n */\n\nexport function detectInteractionType(returnObservable=false){\n\treturnObservable = orDefault(returnObservable, false, 'bool');\n\n\tif( !hasValue(CURRENT_INTERACTION_TYPE) ){\n\t\tCURRENT_INTERACTION_TYPE = new Observable('');\n\t\tif( ('ontouchstart' in document) && ('ontouchend' in document) && (window.navigator.maxTouchPoints > 0) ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t} else {\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\n\t\tdocument.addEventListener('touchstart', INTERACTION_TYPE_DETECTION.touchStartHandler);\n\t\tdocument.addEventListener('touchend', INTERACTION_TYPE_DETECTION.touchEndHandler);\n\t\twindow.addEventListener('blur', INTERACTION_TYPE_DETECTION.blurHandler);\n\t\tdocument.addEventListener('mousemove', INTERACTION_TYPE_DETECTION.mouseMoveHandler);\n\t}\n\n\treturn returnObservable ? CURRENT_INTERACTION_TYPE : CURRENT_INTERACTION_TYPE.getValue();\n}\n\n\n\n/**\n * @namespace Context:detectAppleDevice\n */\n\n/**\n * Try to determine if the execution context is an Apple device and if so: which type.\n *\n * We use an escalating test starting with the user agent and then, as a fallback, checking the platform value\n * to determine the general device class (iPhone, iPad ,iPod ,Macintosh). If we get a Macintosh, we double check\n * if the device might be a falsely reporting iPad with iPadOS13+.\n *\n * You can hook up additional tests by providing an \"additionalTest\" function as a function parameter,\n * that function takes the evaluated device type at the end of the function and expects a new device type to be\n * returned. Using this, you can tap into the process and handle edge cases yourself.\n *\n * @param {?Function} [additionalTest=null] - if set, is executed after determining the device type, takes the current device type as parameter and is expected to return a new one; use this to add edge case tests to overwrite the result in certain conditions\n * @returns {String} \"ipad\", \"iphone\", \"ipod\" or \"mac\"\n *\n * @memberof Context:detectAppleDevice\n * @alias detectAppleDevice\n * @example\n * const IS_IOS_DEVICE = ['iphone', 'ipod', 'ipad'].includes(detectAppleDevice());\n */\nexport function detectAppleDevice(additionalTest=null){\n\tlet\n\t\tfamily = /iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),\n\t\tdeviceType = null\n\t;\n\n\tif( Array.isArray(family) && (family.length > 0) ){\n\t\tfamily = family[0];\n\t} else {\n\t\tfamily = /^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform);\n\n\t\tif( Array.isArray(family) && (family.length > 0) ){\n\t\t\tfamily = family[0];\n\n\t\t\tif( family === 'Mac' ){\n\t\t\t\tfamily = 'Macintosh';\n\t\t\t}\n\t\t} else {\n\t\t\tfamily = null;\n\t\t}\n\t}\n\n\tif( hasValue(family) ){\n\t\t// If User-Agent reports Macintosh double check this against touch points, since the device might\n\t\t// be a disguised iPad with i(Pad)Os13+\n\t\tif(\n\t\t\t(family === 'Macintosh')\n\t\t\t&& (window.navigator.maxTouchPoints > 1)\n\t\t){\n\t\t\tfamily = 'iPad';\n\t\t}\n\n\t\tswitch( family ) {\n\t\t\tcase 'iPad':\n\t\t\t\tdeviceType = 'ipad';\n\t\t\tbreak;\n\t\t\tcase 'iPhone':\n\t\t\t\tdeviceType = 'iphone';\n\t\t\tbreak;\n\t\t\tcase 'iPod':\n\t\t\t\tdeviceType = 'ipod';\n\t\t\tbreak;\n\t\t\tcase 'Macintosh':\n\t\t\t\tdeviceType = 'mac';\n\t\t\tbreak;\n\t\t}\n\n\t\tif( isA(additionalTest, 'function') ){\n\t\t\tdeviceType = additionalTest(deviceType);\n\t\t}\n\t}\n\n\treturn deviceType;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLanguage\n */\n\n/**\n * Evaluates all available browser languages and tries to return the preferred one.\n *\n * Since browsers could not agree on a uniform way to return language values yet, the returned language\n * will always be \"lowercaselanguage-UPPERCASECOUNTRY\" or just \"lowercaselanguage\", if we have no country.\n *\n * @param {?String} [fallbackLanguage=null] - fallback value to return if no language could be evaluated\n * @returns {String|null} the preferred browser language if available, null if no language can be detected and no fallback has been defined\n *\n * @memberof Context:getBrowserLanguage\n * @alias getBrowserLanguage\n * @see getBrowserLocale\n * @example\n * getBrowserLanguage()\n * => \"en\"\n */\nexport function getBrowserLanguage(fallbackLanguage=null){\n\tlet language = null;\n\n\tif( hasValue(window.navigator.languages) ){\n\t\tconst browserLanguages = Array.from(window.navigator.languages);\n\t\tif( isA(browserLanguages, 'array') && (browserLanguages.length > 0) ){\n\t\t\tlanguage = `${browserLanguages[0]}`;\n\t\t}\n\t}\n\n\tif( !hasValue(language) ){\n\t\t['language', 'browserLanguage', 'userLanguage', 'systemLanguage'].forEach(browserLanguagePropertyKey => {\n\t\t\tif( !hasValue(language) ){\n\t\t\t\tconst browserLanguage = window.navigator[browserLanguagePropertyKey];\n\t\t\t\tlanguage = hasValue(browserLanguage) ? `${browserLanguage}` : null;\n\t\t\t}\n\t\t});\n\t}\n\n\tif( !hasValue(language) && hasValue(fallbackLanguage) ){\n\t\tlanguage = `${fallbackLanguage}`;\n\t}\n\n\tconst languageParts = language.split('-');\n\tlanguage = languageParts[0].toLowerCase().trim();\n\tconst country = languageParts?.[1]?.toUpperCase()?.trim();\n\tlanguage = hasValue(country) ? `${language}-${country}` : language;\n\n\treturn language;\n}\n\n\n\n/**\n * @namespace Context:getLocale\n */\n\n/**\n * Evaluates the document's locale by having a look at the HTML element's lang-attribute.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?HTMLElement} [element=document.documentElement] - the element holding the lang-attribute to evaluate\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if element holds no lang information\n * @returns {Object} the locale as an object, having the lang value as \"code\", the split-up parts in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getLocale\n * @alias getLocale\n * @see getBrowserLocale\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang\n * @example\n * getLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getLocale(document.querySelector('p'), 'en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getLocale(element=null, fallbackLanguage=null){\n\t// document.documentElement not as function default to prevent errors in document-less context on import\n\telement = orDefault(element, document.documentElement);\n\n\tconst locale = {\n\t\tcode : null,\n\t\tcountry : null,\n\t\tlanguage : null,\n\t\tisFallback : false\n\t};\n\n\tlet langAttr = isA(element.getAttribute, 'function') ? element.getAttribute('lang') : null;\n\tif( !hasValue(langAttr) && hasValue(fallbackLanguage) ){\n\t\tlangAttr = `${fallbackLanguage}`;\n\t\tlocale.isFallback = true;\n\t}\n\n\tif( hasValue(langAttr) ){\n\t\tconst localeParts = `${langAttr}`.split('-');\n\t\tlocale.country = localeParts?.[1]?.toLowerCase()?.trim();\n\t\tlocale.language = localeParts[0].toLowerCase().trim();\n\t\tlocale.code = hasValue(locale.country) ? `${locale.language}-${locale.country.toUpperCase()}` : locale.language;\n\t}\n\n\treturn locale;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLocale\n */\n\n/**\n * Evaluates the browser's locale by having a look at the preferred browser language, as reported by `getBrowserLanguage`.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if browser reports no preferred language\n * @returns {Object} the locale as an object, having the in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getBrowserLocale\n * @alias getBrowserLocale\n * @see getBrowserLanguage\n * @example\n * getBrowserLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getBrowserLocale('en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getBrowserLocale(fallbackLanguage=null){\n\treturn getLocale({getAttribute(){ return getBrowserLanguage(fallbackLanguage); }}, fallbackLanguage);\n}\n"]} \ No newline at end of file +{"version":3,"file":"context.js","names":["MODULE_NAME","hasValue","isFunction","isArray","orDefault","Observable","throttle","reschedule","INTERACTION_TYPE_DETECTION","touchHappening","touchEndingTimer","touchStartHandler","CURRENT_INTERACTION_TYPE","getValue","setValue","touchEndHandler","blurHandler","mouseMoveHandler","browserSupportsHistoryManipulation","window","history","pushState","replaceState","contextHasHighDpi","matchMedia","matches","getBrowserScrollbarWidth","sandbox","document","createElement","style","visibility","opacity","pointerEvents","overflow","position","top","right","left","height","scrollbarEnforcer","width","appendChild","body","scrollbarWidth","offsetWidth","removeChild","detectInteractionType","returnObservable","navigator","maxTouchPoints","addEventListener","detectAppleDevice","additionalTest","family","exec","userAgent","deviceType","Array","length","platform","getBrowserLanguage","fallbackLanguage","language","languages","browserLanguages","from","forEach","browserLanguagePropertyKey","browserLanguage","languageParts","split","toLowerCase","trim","country","toUpperCase","getLocale","element","documentElement","locale","code","isFallback","langAttr","getAttribute","localeParts","getBrowserLocale"],"sources":["context.js"],"mappings":"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","sourcesContent":["/*!\n * Module Context\n */\n\n/**\n * @namespace Context\n */\n\nconst MODULE_NAME = 'Context';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {hasValue, isFunction, isArray, orDefault, Observable} from './basic.js';\nimport {throttle} from './functions.js';\nimport {reschedule} from './timers.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst INTERACTION_TYPE_DETECTION = {\n\ttouchHappening : false,\n\ttouchEndingTimer : null,\n\ttouchStartHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchHappening = true;\n\t\tif( CURRENT_INTERACTION_TYPE.getValue() !== 'touch' ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t}\n\t},\n\ttouchEndHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tblurHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tmouseMoveHandler : throttle(1000, function(){\n\t\tif( (CURRENT_INTERACTION_TYPE.getValue('pointer')) && !INTERACTION_TYPE_DETECTION.touchHappening ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\t})\n};\n\nexport let CURRENT_INTERACTION_TYPE;\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Context:browserSupportsHistoryManipulation\n */\n\n/**\n * Detects if the browser supports history manipulation, by checking the most common\n * methods for presence in the history-object.\n *\n * @returns {Boolean} true if browser seems to support history manipulation\n *\n * @memberof Context:browserSupportsHistoryManipulation\n * @alias browserSupportsHistoryManipulation\n * @example\n * if( browserSupportsHistoryManipulation() ){\n * window.history.replaceState(null, 'test', '/test');\n * }\n */\nexport function browserSupportsHistoryManipulation(){\n\treturn hasValue(window.history)\n\t\t&& isFunction(window.history.pushState)\n\t\t&& isFunction(window.history.replaceState)\n\t;\n}\n\n\n\n/**\n * @namespace Context:contextHasHighDpi\n */\n\n/**\n * Checks if the context would benefit from high DPI graphics.\n *\n * @returns {Boolean} true if device has high DPI, false if not or browser does not support media queries\n *\n * @memberof Context:contextHasHighDpi\n * @alias contextHasHighDpi\n * @example\n * if( contextHasHighDpi() ){\n * document.querySelectorAll('img').forEach(img => {\n * img.setAttribute('src', img.getAttribute('src').replace('.jpg', '@2x.jpg'));\n * });\n * }\n */\nexport function contextHasHighDpi(){\n\tif( window.matchMedia ){\n\t\treturn window.matchMedia(\n\t\t\t'only screen and (-webkit-min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (-o-min-device-pixel-ratio: 3/2),'\n\t\t\t+'only screen and (min--moz-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-resolution: 144dpi),'\n\t\t\t+'only screen and (min-resolution: 1.5dppx)'\n\t\t).matches;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Context:getBrowserScrollbarWidth\n */\n\n/**\n * Returns the current context's scrollbar width. Returns 0 if scrollbar is over content.\n * There are edge cases in which we might want to calculate positions in respect to the\n * actual width of the scrollbar. For example when working with elements with a 100vw width.\n *\n * This method temporarily inserts three elements into the body while forcing the body to\n * actually show scrollbars, measuring the difference between 100vw and 100% on the body and\n * returns the result.\n *\n * @returns {Number} the width of the body scrollbar in pixels\n *\n * @memberof Context:getBrowserScrollbarWidth\n * @alias getBrowserScrollbarWidth\n * @example\n * foobarElement.style.width = `calc(100vw - ${getBrowserScrollbarWidth()}px)`;\n */\nexport function getBrowserScrollbarWidth(){\n\tconst sandbox = document.createElement('div');\n\tsandbox.style.visibility = 'hidden';\n\tsandbox.style.opacity = '0';\n\tsandbox.style.pointerEvents = 'none';\n\tsandbox.style.overflow = 'scroll';\n\tsandbox.style.position = 'fixed';\n\tsandbox.style.top = '0';\n\tsandbox.style.right = '0';\n\tsandbox.style.left = '0';\n\t// firefox needs container to be at least 30px high to display scrollbar\n\tsandbox.style.height = '50px';\n\n\tconst scrollbarEnforcer = document.createElement('div');\n\tscrollbarEnforcer.style.width = '100%';\n\tscrollbarEnforcer.style.height = '100px';\n\n\tsandbox.appendChild(scrollbarEnforcer);\n\tdocument.body.appendChild(sandbox);\n\n\tconst scrollbarWidth = sandbox.offsetWidth - scrollbarEnforcer.offsetWidth;\n\n\tdocument.body.removeChild(sandbox);\n\n\treturn scrollbarWidth;\n}\n\n\n\n/**\n * @namespace Context:detectInteractionType\n */\n\n/**\n * Try to figure out the current type of interaction between the user and the document.\n * This is determined by the input device and is currently limited to either \"pointer\" or \"touch\".\n *\n * On call the function returns an educated guess about the fact what interaction type might be more\n * probable based on browser features and sets up event listeners to update Context module's CURRENT_INTERACTION_TYPE\n * observable (to which you may subscribe to be informed about updates), when interaction type should change while\n * the page is being interacted with. In case a touch occurs we determine touch interaction and\n * on mousemove we determine pointer interaction. If you use this observable to set up a class on your document for\n * example you can even relatively safely handle dual devices like a surface book.\n *\n * Hint: because touch devices also emit a single mousemove after touchend with a single touch we have to block\n * mousemove detection for 1s after the last touchend. Therefore, it takes up to 1s after the last touch event until\n * we are able to detect the change to a pointer device.\n *\n * @param {?Boolean} [returnObservable=false] - if set to true, the call returns Context module's CURRENT_INTERACTION_TYPE observable\n * @returns {String|Observable} interaction type string \"pointer\" or \"touch\", or the CURRENT_INTERACTION_TYPE observable\n *\n * @memberof Context:detectInteractionType\n * @alias detectInteractionType\n * @example\n * let interactionTypeGuess = detectInteractionType();\n * detectInteractionType(true).subscribe(function(type){\n * document.body.classList.toggle('touch', type === 'touch');\n * });\n */\n\nexport function detectInteractionType(returnObservable=false){\n\treturnObservable = orDefault(returnObservable, false, 'bool');\n\n\tif( !hasValue(CURRENT_INTERACTION_TYPE) ){\n\t\tCURRENT_INTERACTION_TYPE = new Observable('');\n\t\tif( ('ontouchstart' in document) && ('ontouchend' in document) && (window.navigator.maxTouchPoints > 0) ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t} else {\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\n\t\tdocument.addEventListener('touchstart', INTERACTION_TYPE_DETECTION.touchStartHandler);\n\t\tdocument.addEventListener('touchend', INTERACTION_TYPE_DETECTION.touchEndHandler);\n\t\twindow.addEventListener('blur', INTERACTION_TYPE_DETECTION.blurHandler);\n\t\tdocument.addEventListener('mousemove', INTERACTION_TYPE_DETECTION.mouseMoveHandler);\n\t}\n\n\treturn returnObservable ? CURRENT_INTERACTION_TYPE : CURRENT_INTERACTION_TYPE.getValue();\n}\n\n\n\n/**\n * @namespace Context:detectAppleDevice\n */\n\n/**\n * Try to determine if the execution context is an Apple device and if so: which type.\n *\n * We use an escalating test starting with the user agent and then, as a fallback, checking the platform value\n * to determine the general device class (iPhone, iPad ,iPod ,Macintosh). If we get a Macintosh, we double check\n * if the device might be a falsely reporting iPad with iPadOS13+.\n *\n * You can hook up additional tests by providing an \"additionalTest\" function as a function parameter,\n * that function takes the evaluated device type at the end of the function and expects a new device type to be\n * returned. Using this, you can tap into the process and handle edge cases yourself.\n *\n * @param {?Function} [additionalTest=null] - if set, is executed after determining the device type, takes the current device type as parameter and is expected to return a new one; use this to add edge case tests to overwrite the result in certain conditions\n * @returns {String} \"ipad\", \"iphone\", \"ipod\" or \"mac\"\n *\n * @memberof Context:detectAppleDevice\n * @alias detectAppleDevice\n * @example\n * const IS_IOS_DEVICE = ['iphone', 'ipod', 'ipad'].includes(detectAppleDevice());\n */\nexport function detectAppleDevice(additionalTest=null){\n\tlet\n\t\tfamily = /iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),\n\t\tdeviceType = null\n\t;\n\n\tif( Array.isArray(family) && (family.length > 0) ){\n\t\tfamily = family[0];\n\t} else {\n\t\tfamily = /^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform);\n\n\t\tif( Array.isArray(family) && (family.length > 0) ){\n\t\t\tfamily = family[0];\n\n\t\t\tif( family === 'Mac' ){\n\t\t\t\tfamily = 'Macintosh';\n\t\t\t}\n\t\t} else {\n\t\t\tfamily = null;\n\t\t}\n\t}\n\n\tif( hasValue(family) ){\n\t\t// If User-Agent reports Macintosh double check this against touch points, since the device might\n\t\t// be a disguised iPad with i(Pad)Os13+\n\t\tif(\n\t\t\t(family === 'Macintosh')\n\t\t\t&& (window.navigator.maxTouchPoints > 1)\n\t\t){\n\t\t\tfamily = 'iPad';\n\t\t}\n\n\t\tswitch( family ) {\n\t\t\tcase 'iPad':\n\t\t\t\tdeviceType = 'ipad';\n\t\t\tbreak;\n\t\t\tcase 'iPhone':\n\t\t\t\tdeviceType = 'iphone';\n\t\t\tbreak;\n\t\t\tcase 'iPod':\n\t\t\t\tdeviceType = 'ipod';\n\t\t\tbreak;\n\t\t\tcase 'Macintosh':\n\t\t\t\tdeviceType = 'mac';\n\t\t\tbreak;\n\t\t}\n\n\t\tif( isFunction(additionalTest) ){\n\t\t\tdeviceType = additionalTest(deviceType);\n\t\t}\n\t}\n\n\treturn deviceType;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLanguage\n */\n\n/**\n * Evaluates all available browser languages and tries to return the preferred one.\n *\n * Since browsers could not agree on a uniform way to return language values yet, the returned language\n * will always be \"lowercaselanguage-UPPERCASECOUNTRY\" or just \"lowercaselanguage\", if we have no country.\n *\n * @param {?String} [fallbackLanguage=null] - fallback value to return if no language could be evaluated\n * @returns {String|null} the preferred browser language if available, null if no language can be detected and no fallback has been defined\n *\n * @memberof Context:getBrowserLanguage\n * @alias getBrowserLanguage\n * @see getBrowserLocale\n * @example\n * getBrowserLanguage()\n * => \"en\"\n */\nexport function getBrowserLanguage(fallbackLanguage=null){\n\tlet language = null;\n\n\tif( hasValue(window.navigator.languages) ){\n\t\tconst browserLanguages = Array.from(window.navigator.languages);\n\t\tif( isArray(browserLanguages) && (browserLanguages.length > 0) ){\n\t\t\tlanguage = `${browserLanguages[0]}`;\n\t\t}\n\t}\n\n\tif( !hasValue(language) ){\n\t\t['language', 'browserLanguage', 'userLanguage', 'systemLanguage'].forEach(browserLanguagePropertyKey => {\n\t\t\tif( !hasValue(language) ){\n\t\t\t\tconst browserLanguage = window.navigator[browserLanguagePropertyKey];\n\t\t\t\tlanguage = hasValue(browserLanguage) ? `${browserLanguage}` : null;\n\t\t\t}\n\t\t});\n\t}\n\n\tif( !hasValue(language) && hasValue(fallbackLanguage) ){\n\t\tlanguage = `${fallbackLanguage}`;\n\t}\n\n\tconst languageParts = language.split('-');\n\tlanguage = languageParts[0].toLowerCase().trim();\n\tconst country = languageParts?.[1]?.toUpperCase()?.trim();\n\tlanguage = hasValue(country) ? `${language}-${country}` : language;\n\n\treturn language;\n}\n\n\n\n/**\n * @namespace Context:getLocale\n */\n\n/**\n * Evaluates the document's locale by having a look at the HTML element's lang-attribute.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?HTMLElement} [element=document.documentElement] - the element holding the lang-attribute to evaluate\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if element holds no lang information\n * @returns {Object} the locale as an object, having the lang value as \"code\", the split-up parts in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getLocale\n * @alias getLocale\n * @see getBrowserLocale\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang\n * @example\n * getLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getLocale(document.querySelector('p'), 'en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getLocale(element=null, fallbackLanguage=null){\n\t// document.documentElement not as function default to prevent errors in document-less context on import\n\telement = orDefault(element, document.documentElement);\n\n\tconst locale = {\n\t\tcode : null,\n\t\tcountry : null,\n\t\tlanguage : null,\n\t\tisFallback : false\n\t};\n\n\tlet langAttr = isFunction(element.getAttribute) ? element.getAttribute('lang') : null;\n\tif( !hasValue(langAttr) && hasValue(fallbackLanguage) ){\n\t\tlangAttr = `${fallbackLanguage}`;\n\t\tlocale.isFallback = true;\n\t}\n\n\tif( hasValue(langAttr) ){\n\t\tconst localeParts = `${langAttr}`.split('-');\n\t\tlocale.country = localeParts?.[1]?.toLowerCase()?.trim();\n\t\tlocale.language = localeParts[0].toLowerCase().trim();\n\t\tlocale.code = hasValue(locale.country) ? `${locale.language}-${locale.country.toUpperCase()}` : locale.language;\n\t}\n\n\treturn locale;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLocale\n */\n\n/**\n * Evaluates the browser's locale by having a look at the preferred browser language, as reported by `getBrowserLanguage`.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if browser reports no preferred language\n * @returns {Object} the locale as an object, having the in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getBrowserLocale\n * @alias getBrowserLocale\n * @see getBrowserLanguage\n * @example\n * getBrowserLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getBrowserLocale('en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getBrowserLocale(fallbackLanguage=null){\n\treturn getLocale({getAttribute(){ return getBrowserLanguage(fallbackLanguage); }}, fallbackLanguage);\n}\n"]} \ No newline at end of file diff --git a/dist/cookies.js b/dist/cookies.js index db9aa856..b5939730 100644 --- a/dist/cookies.js +++ b/dist/cookies.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Cookies */ -const MODULE_NAME="Cookies";import{assert,isA,orDefault,hasValue}from"./basic.js";import{warn}from"./logging.js";function encodeCookieValue(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}function decodeCookieValue(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)}function encodeCookieName(e){return encodeURIComponent(`${e}`).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape)}function decodeCookieName(e){return decodeURIComponent(e)}function normalizeCookieOptions(e){e=orDefault(e,{});const o={};for(let t in e)o[t.toLowerCase()]=e[t];return hasValue((e=o).expires)?(isA(e.expires,"date")||(e.expires=new Date(Date.now()+24*Math.round(parseFloat(e.expires))*60*60*1e3)),e.expires=e.expires.toUTCString()):e.expires=null,e["max-age"]=orDefault(e["max-age"],null,"int"),e.path=orDefault(e.path,"/","str"),"auto"===e.path&&(e.path=""),e.domain=orDefault(e.domain,null,"str"),e.httponly=orDefault(e.httponly,!1,"bool"),e.samesite=orDefault(e.samesite,"lax","str").toLowerCase(),["strict","lax","none"].includes(e.samesite)||console.warn(`Cookies:setCookie | unknown samesite mode "${e.samesite}"`),e.secure=orDefault(e.secure,"none"===e.samesite,"bool"),e}export function getCookie(e){const o=hasValue(e)?new Set([].concat(e).map((e=>e.trim()))):new Set,t=new Set;let n=0===o.size?{}:null;if(!hasValue(document.cookie))return n;const i=document.cookie.split(";");for(let e in i)try{const a=i[e].trim().split("="),r=decodeCookieName(a[0]).trim(),s=decodeCookieValue(a.slice(1).join("="));if(""!==r&&(o.has(r)||0===o.size)&&(null===n&&(n={}),n[r]=s,t.add(r),t.size===o.size&&0!==o.size))break}catch(o){warn(`Cookies:getCookie | decoding cookie "${i[e]}" failed with "${o}"`)}return 1===o.size?n?.[e]??null:n}export function getCookies(e){return e=[],Array.from(arguments).forEach((o=>{e=e.concat(o)})),getCookie(e)}export function setCookie(e,o,t){assert(hasValue(e)&&""!==e,"Cookies:setCookie | no usable name"),e=`${e}`.trim(),o=hasValue(o)?encodeCookieValue(orDefault(o,"","str")):null,t=normalizeCookieOptions(t);let n="";for(let e in t){const o=t[e];hasValue(o)&&!1!==o&&(n+=`; ${e}`,!0!==o&&(n+=`=${o.split(";")[0]}`))}return hasValue(o)?document.cookie=`${encodeCookieName(e)}=${o}${n}`:removeCookie(e,t),getCookie(e)}export function removeCookie(e,o){return assert(hasValue(e)&&""!==e,"Cookies:removeCookie | no usable name"),(o=normalizeCookieOptions(o)).expires=-1,null===setCookie(e,"",o)} +const MODULE_NAME="Cookies";import{assert,isDate,orDefault,hasValue}from"./basic.js";import{warn}from"./logging.js";function encodeCookieValue(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}function decodeCookieValue(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)}function encodeCookieName(e){return encodeURIComponent(`${e}`).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape)}function decodeCookieName(e){return decodeURIComponent(e)}function normalizeCookieOptions(e){e=orDefault(e,{});const o={};for(let t in e)o[t.toLowerCase()]=e[t];return hasValue((e=o).expires)?(isDate(e.expires)||(e.expires=new Date(Date.now()+24*Math.round(parseFloat(e.expires))*60*60*1e3)),e.expires=e.expires.toUTCString()):e.expires=null,e["max-age"]=orDefault(e["max-age"],null,"int"),e.path=orDefault(e.path,"/","str"),"auto"===e.path&&(e.path=""),e.domain=orDefault(e.domain,null,"str"),e.httponly=orDefault(e.httponly,!1,"bool"),e.samesite=orDefault(e.samesite,"lax","str").toLowerCase(),["strict","lax","none"].includes(e.samesite)||console.warn(`Cookies:setCookie | unknown samesite mode "${e.samesite}"`),e.secure=orDefault(e.secure,"none"===e.samesite,"bool"),e}export function getCookie(e){const o=hasValue(e)?new Set([].concat(e).map((e=>e.trim()))):new Set,t=new Set;let n=0===o.size?{}:null;if(!hasValue(document.cookie))return n;const i=document.cookie.split(";");for(let e in i)try{const a=i[e].trim().split("="),r=decodeCookieName(a[0]).trim(),s=decodeCookieValue(a.slice(1).join("="));if(""!==r&&(o.has(r)||0===o.size)&&(null===n&&(n={}),n[r]=s,t.add(r),t.size===o.size&&0!==o.size))break}catch(o){warn(`Cookies:getCookie | decoding cookie "${i[e]}" failed with "${o}"`)}return 1===o.size?n?.[e]??null:n}export function getCookies(e){return e=[],Array.from(arguments).forEach((o=>{e=e.concat(o)})),getCookie(e)}export function setCookie(e,o,t){assert(hasValue(e)&&""!==e,"Cookies:setCookie | no usable name"),e=`${e}`.trim(),o=hasValue(o)?encodeCookieValue(orDefault(o,"","str")):null,t=normalizeCookieOptions(t);let n="";for(let e in t){const o=t[e];hasValue(o)&&!1!==o&&(n+=`; ${e}`,!0!==o&&(n+=`=${o.split(";")[0]}`))}return hasValue(o)?document.cookie=`${encodeCookieName(e)}=${o}${n}`:removeCookie(e,t),getCookie(e)}export function removeCookie(e,o){return assert(hasValue(e)&&""!==e,"Cookies:removeCookie | no usable name"),(o=normalizeCookieOptions(o)).expires=-1,null===setCookie(e,"",o)} //# sourceMappingURL=cookies.js.map diff --git a/dist/cookies.js.map b/dist/cookies.js.map index 1210d9ce..5663c8f1 100644 --- a/dist/cookies.js.map +++ b/dist/cookies.js.map @@ -1 +1 @@ -{"version":3,"file":"cookies.js","names":["MODULE_NAME","assert","isA","orDefault","hasValue","warn","encodeCookieValue","value","encodeURIComponent","replace","decodeURIComponent","decodeCookieValue","slice","encodeCookieName","name","escape","decodeCookieName","normalizeCookieOptions","options","normalizedOptions","optionsProp","toLowerCase","expires","Date","now","Math","round","parseFloat","toUTCString","path","domain","httponly","samesite","includes","console","secure","getCookie","names","Set","concat","map","n","trim","foundNames","res","size","document","cookie","cookies","split","i","cookieParts","cookieName","cookieValue","join","has","add","ex","getCookies","Array","from","arguments","forEach","argument","setCookie","cookieOptions","option","removeCookie"],"sources":["cookies.js"],"mappings":"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","sourcesContent":["/*!\n * Module Cookies\n */\n\n/**\n * @namespace Cookies\n */\n\nconst MODULE_NAME = 'Cookies';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isA, orDefault, hasValue} from './basic.js';\nimport {warn} from './logging.js';\n\n\n\n//###[ HELPERS ]########################################################################################################\n\n/*\n * Encodes a string to be stored in a cookie.\n *\n * @private\n */\nfunction encodeCookieValue(value){\n\treturn encodeURIComponent(value).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g, decodeURIComponent);\n}\n\n\n\n/*\n * Decodes a cookie value to be used as a string in JavaScript.\n *\n * @private\n */\nfunction decodeCookieValue(value){\n\tif( value[0] === '\"' ){\n\t\tvalue = value.slice(1, -1);\n\t}\n\treturn value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent);\n}\n\n\n\n/*\n * Makes sure a cookie name conforms to the cookie name rules and translates special chars to % representations.\n *\n * @private\n */\nfunction encodeCookieName(name){\n\treturn encodeURIComponent(`${name}`)\n\t\t.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n\t\t// using escape, because encodeURIComponent, indeed, does _not_ encode brackets\n\t\t.replace(/[()]/g, escape)\n\t;\n}\n\n\n\n/*\n * Decodes a cookie name, set prior with encodeCookieName to a standard JavaScript string again.\n *\n * @private\n */\nfunction decodeCookieName(name){\n\treturn decodeURIComponent(name);\n}\n\n\n\n/**\n * @typedef CookieOptions\n * @type {Object}\n * @property {?Date|Number} [expires=null] - expiry time of the cookie, either a Date object or time in days\n * @property {?Number} [max-age=null] - max age of the cookie in seconds\n * @property {?String} [path='/'] - the cookie path, setting this to \"auto\" or an empty string defines auto-mode, which targets the current site path, which usually is the default, but we use '/' to set a cookie for while site, this being the common use-case\n * @property {?Boolean} [secure=false] - define if the cookie should only be transmitted via https (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?Boolean} [httponly=false] - define this, if cookie should only be sent to servers and not be accessible to javascript (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?String} [samesite=null] - define if this cookie should be included in cross-site requests, may be either \"strict\" (will only ever transmit same-site), \"lax\" (usual browser default, transmits same-site and top-level GET) or \"none\" (no restrictions, will always be sent)\n */\n\n/*\n * Makes sure, that supplied cookie options are in a usable form for setting a cookie.\n *\n * @private\n */\nfunction normalizeCookieOptions(options){\n\toptions = orDefault(options, {});\n\n\tconst normalizedOptions = {};\n\tfor( let optionsProp in options ){\n\t\tnormalizedOptions[optionsProp.toLowerCase()] = options[optionsProp];\n\t}\n\toptions = normalizedOptions;\n\n\tif( hasValue(options.expires) ){\n\t\tif( !isA(options.expires, 'date') ){\n\t\t\toptions.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000));\n\t\t}\n\t\toptions.expires = options.expires.toUTCString();\n\t} else {\n\t\toptions.expires = null;\n\t}\n\n\toptions['max-age'] = orDefault(options['max-age'], null, 'int');\n\n\toptions.path = orDefault(options.path, '/', 'str');\n\tif( options.path === 'auto' ){\n\t\toptions.path = '';\n\t}\n\n\toptions.domain = orDefault(options.domain, null, 'str');\n\n\toptions.httponly = orDefault(options.httponly, false, 'bool');\n\n\toptions.samesite = orDefault(options.samesite, 'lax', 'str').toLowerCase();\n\tif( !['strict', 'lax', 'none'].includes(options.samesite) ){\n\t\tconsole.warn(`${MODULE_NAME}:setCookie | unknown samesite mode \"${options.samesite}\"`);\n\t}\n\n\toptions.secure = orDefault(options.secure, options.samesite === 'none', 'bool');\n\n\treturn options;\n}\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Cookies:getCookie\n */\n\n/**\n * Retrieves a decoded cookie value by name. Automatically decodes the value (assumes, that, if encoded, url/percent\n * encoding has been used).\n *\n * @param {?String|Array} [name] - the name of the cookie (or several names), if empty, all available cookies are returned\n * @returns {String|Object|null} decoded value of the cookie, null, if no such cookie available or a dictionary of found cookies if all or a list are being returned (if a list is requested and non are found, an empty object is returned)\n *\n * @memberof Cookies:getCookie\n * @alias getCookie\n * @see getCookies\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookie('foobar')\n * => 'value'\n * getCookie(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookie(name){\n\tconst\n\t\tnames = hasValue(name) ? new Set([].concat(name).map(n => n.trim())) : new Set(),\n\t\tfoundNames = new Set()\n\t;\n\n\tlet res = (names.size === 0) ? {} : null;\n\tif( !hasValue(document.cookie) ) return res;\n\n\tconst cookies = document.cookie.split(';');\n\tfor( let i in cookies ){\n\t\ttry {\n\t\t\tconst\n\t\t\t\tcookie = cookies[i].trim(),\n\t\t\t\tcookieParts = cookie.split('='),\n\t\t\t\tcookieName = decodeCookieName(cookieParts[0]).trim(),\n\t\t\t\tcookieValue = decodeCookieValue(cookieParts.slice(1).join('='))\n\t\t\t;\n\n\t\t\tif( (cookieName !== '') && (names.has(cookieName) || (names.size === 0)) ){\n\t\t\t\tif( res === null ){\n\t\t\t\t\tres = {};\n\t\t\t\t}\n\n\t\t\t\tres[cookieName] = cookieValue;\n\t\t\t\tfoundNames.add(cookieName);\n\n\t\t\t\tif( (foundNames.size === names.size) && (names.size !== 0) ){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(ex){\n\t\t\twarn(`${MODULE_NAME}:getCookie | decoding cookie \"${cookies[i]}\" failed with \"${ex}\"`)\n\t\t}\n\t}\n\n\tif( names.size === 1 ){\n\t\treturn res?.[name] ?? null;\n\t} else {\n\t\treturn res;\n\t}\n}\n\n\n\n/**\n * @namespace Cookies:getCookies\n */\n\n/**\n * Retrieve decoded cookie values by name. If no name is provided, all available cookie are being returned.\n * Automatically decodes the values (assumes, that, if encoded, url/percent encoding has been used).\n *\n * You can provide names as an array or as comma-separated parameters.\n *\n * @param {?String|Array} [names] - the names of the cookies, if empty or not set, all available cookies are returned\n * @returns {Object} dictionary of named decoded values of the cookies, will be empty if none of the cookies were available\n *\n * @memberof Cookies:getCookies\n * @alias getCookies\n * @see getCookie\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookies(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookies('foobar', 'boofar')\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookies(names){\n\tnames = [];\n\tArray.from(arguments).forEach(argument => {\n\t\tnames = names.concat(argument);\n\t});\n\n\treturn getCookie(names);\n}\n\n\n\n/**\n * @namespace Cookies:setCookie\n */\n\n/**\n * Set a cookie value (if possible) by name. Value will automatically be encoded.\n *\n * If you set a cookie to a nullish value, the method will try to remove the cookie with the given options.\n *\n * @param {String} name - the name of the cookie to set\n * @param {?String} [value] - the value of the cookie to set\n * @param {?CookieOptions} [options] - the cookie options to apply\n * @returns {String|null} returns the set cookie value if available after setting or null if cookie not available (which would also mean, that setting the cookie did not work, or, in case of removal, that the removal worked)\n *\n * @memberof Cookies:setCookie\n * @alias setCookie\n * @see getCookie\n * @see getCookies\n * @see removeCookie\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie\n * @example\n * setCookie('mykittencookie', 'meow meow', {expires : 7, path : '/kittens', secure : true, samesite : 'strict'});\n */\nexport function setCookie(name, value, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:setCookie | no usable name`);\n\n\tname = `${name}`.trim();\n\tvalue = hasValue(value) ? encodeCookieValue(orDefault(value, '', 'str')) : null;\n\toptions = normalizeCookieOptions(options);\n\n\tlet cookieOptions = '';\n\tfor( let optionsProp in options ){\n\t\tconst option = options[optionsProp];\n\n\t\tif( !hasValue(option) || (option === false) ) continue;\n\n\t\tcookieOptions += `; ${optionsProp}`;\n\n\t\tif( option === true ) continue;\n\n\t\t// if the value itself contains a semicolon, according to RFC 6265 section 5.2,\n\t\t// we use everything that comes before the semicolon as the value and drop the rest\n\t\tcookieOptions += `=${option.split(';')[0]}`;\n\t}\n\n\tif( hasValue(value) ){\n\t\tdocument.cookie = `${encodeCookieName(name)}=${value}${cookieOptions}`;\n\t} else {\n\t\tremoveCookie(name, options);\n\t}\n\n\treturn getCookie(name);\n}\n\n\n\n/**\n * @namespace Cookies:removeCookie\n */\n\n/**\n * Removes a cookie (if possible) by name.\n *\n * @param {String} name - the name of the cookie to remove\n * @param {?CookieOptions} [options] - the cookie options to apply (needed for different paths/domains for example)\n * @returns {Boolean} true if cookie is not available anymore after removal, if this is false, cookie removal failed or another cookie of the same name is still available\n *\n * @memberof Cookies:removeCookie\n * @alias removeCookie\n * @see getCookie\n * @see getCookies\n * @see setCookie\n * @example\n * removeCookie('mykittencookie', {path : '/kittens'});\n */\nexport function removeCookie(name, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:removeCookie | no usable name`);\n\n\toptions = normalizeCookieOptions(options);\n\toptions.expires = -1;\n\n\treturn (setCookie(name, '', options) === null);\n}\n"]} \ No newline at end of file +{"version":3,"file":"cookies.js","names":["MODULE_NAME","assert","isDate","orDefault","hasValue","warn","encodeCookieValue","value","encodeURIComponent","replace","decodeURIComponent","decodeCookieValue","slice","encodeCookieName","name","escape","decodeCookieName","normalizeCookieOptions","options","normalizedOptions","optionsProp","toLowerCase","expires","Date","now","Math","round","parseFloat","toUTCString","path","domain","httponly","samesite","includes","console","secure","getCookie","names","Set","concat","map","n","trim","foundNames","res","size","document","cookie","cookies","split","i","cookieParts","cookieName","cookieValue","join","has","add","ex","getCookies","Array","from","arguments","forEach","argument","setCookie","cookieOptions","option","removeCookie"],"sources":["cookies.js"],"mappings":"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","sourcesContent":["/*!\n * Module Cookies\n */\n\n/**\n * @namespace Cookies\n */\n\nconst MODULE_NAME = 'Cookies';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isDate, orDefault, hasValue} from './basic.js';\nimport {warn} from './logging.js';\n\n\n\n//###[ HELPERS ]########################################################################################################\n\n/*\n * Encodes a string to be stored in a cookie.\n *\n * @private\n */\nfunction encodeCookieValue(value){\n\treturn encodeURIComponent(value).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g, decodeURIComponent);\n}\n\n\n\n/*\n * Decodes a cookie value to be used as a string in JavaScript.\n *\n * @private\n */\nfunction decodeCookieValue(value){\n\tif( value[0] === '\"' ){\n\t\tvalue = value.slice(1, -1);\n\t}\n\treturn value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent);\n}\n\n\n\n/*\n * Makes sure a cookie name conforms to the cookie name rules and translates special chars to % representations.\n *\n * @private\n */\nfunction encodeCookieName(name){\n\treturn encodeURIComponent(`${name}`)\n\t\t.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n\t\t// using escape, because encodeURIComponent, indeed, does _not_ encode brackets\n\t\t.replace(/[()]/g, escape)\n\t;\n}\n\n\n\n/*\n * Decodes a cookie name, set prior with encodeCookieName to a standard JavaScript string again.\n *\n * @private\n */\nfunction decodeCookieName(name){\n\treturn decodeURIComponent(name);\n}\n\n\n\n/**\n * @typedef CookieOptions\n * @type {Object}\n * @property {?Date|Number} [expires=null] - expiry time of the cookie, either a Date object or time in days\n * @property {?Number} [max-age=null] - max age of the cookie in seconds\n * @property {?String} [path='/'] - the cookie path, setting this to \"auto\" or an empty string defines auto-mode, which targets the current site path, which usually is the default, but we use '/' to set a cookie for while site, this being the common use-case\n * @property {?Boolean} [secure=false] - define if the cookie should only be transmitted via https (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?Boolean} [httponly=false] - define this, if cookie should only be sent to servers and not be accessible to javascript (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?String} [samesite=null] - define if this cookie should be included in cross-site requests, may be either \"strict\" (will only ever transmit same-site), \"lax\" (usual browser default, transmits same-site and top-level GET) or \"none\" (no restrictions, will always be sent)\n */\n\n/*\n * Makes sure, that supplied cookie options are in a usable form for setting a cookie.\n *\n * @private\n */\nfunction normalizeCookieOptions(options){\n\toptions = orDefault(options, {});\n\n\tconst normalizedOptions = {};\n\tfor( let optionsProp in options ){\n\t\tnormalizedOptions[optionsProp.toLowerCase()] = options[optionsProp];\n\t}\n\toptions = normalizedOptions;\n\n\tif( hasValue(options.expires) ){\n\t\tif( !isDate(options.expires) ){\n\t\t\toptions.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000));\n\t\t}\n\t\toptions.expires = options.expires.toUTCString();\n\t} else {\n\t\toptions.expires = null;\n\t}\n\n\toptions['max-age'] = orDefault(options['max-age'], null, 'int');\n\n\toptions.path = orDefault(options.path, '/', 'str');\n\tif( options.path === 'auto' ){\n\t\toptions.path = '';\n\t}\n\n\toptions.domain = orDefault(options.domain, null, 'str');\n\n\toptions.httponly = orDefault(options.httponly, false, 'bool');\n\n\toptions.samesite = orDefault(options.samesite, 'lax', 'str').toLowerCase();\n\tif( !['strict', 'lax', 'none'].includes(options.samesite) ){\n\t\tconsole.warn(`${MODULE_NAME}:setCookie | unknown samesite mode \"${options.samesite}\"`);\n\t}\n\n\toptions.secure = orDefault(options.secure, options.samesite === 'none', 'bool');\n\n\treturn options;\n}\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Cookies:getCookie\n */\n\n/**\n * Retrieves a decoded cookie value by name. Automatically decodes the value (assumes, that, if encoded, url/percent\n * encoding has been used).\n *\n * @param {?String|Array} [name] - the name of the cookie (or several names), if empty, all available cookies are returned\n * @returns {String|Object|null} decoded value of the cookie, null, if no such cookie available or a dictionary of found cookies if all or a list are being returned (if a list is requested and non are found, an empty object is returned)\n *\n * @memberof Cookies:getCookie\n * @alias getCookie\n * @see getCookies\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookie('foobar')\n * => 'value'\n * getCookie(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookie(name){\n\tconst\n\t\tnames = hasValue(name) ? new Set([].concat(name).map(n => n.trim())) : new Set(),\n\t\tfoundNames = new Set()\n\t;\n\n\tlet res = (names.size === 0) ? {} : null;\n\tif( !hasValue(document.cookie) ) return res;\n\n\tconst cookies = document.cookie.split(';');\n\tfor( let i in cookies ){\n\t\ttry {\n\t\t\tconst\n\t\t\t\tcookie = cookies[i].trim(),\n\t\t\t\tcookieParts = cookie.split('='),\n\t\t\t\tcookieName = decodeCookieName(cookieParts[0]).trim(),\n\t\t\t\tcookieValue = decodeCookieValue(cookieParts.slice(1).join('='))\n\t\t\t;\n\n\t\t\tif( (cookieName !== '') && (names.has(cookieName) || (names.size === 0)) ){\n\t\t\t\tif( res === null ){\n\t\t\t\t\tres = {};\n\t\t\t\t}\n\n\t\t\t\tres[cookieName] = cookieValue;\n\t\t\t\tfoundNames.add(cookieName);\n\n\t\t\t\tif( (foundNames.size === names.size) && (names.size !== 0) ){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(ex){\n\t\t\twarn(`${MODULE_NAME}:getCookie | decoding cookie \"${cookies[i]}\" failed with \"${ex}\"`)\n\t\t}\n\t}\n\n\tif( names.size === 1 ){\n\t\treturn res?.[name] ?? null;\n\t} else {\n\t\treturn res;\n\t}\n}\n\n\n\n/**\n * @namespace Cookies:getCookies\n */\n\n/**\n * Retrieve decoded cookie values by name. If no name is provided, all available cookie are being returned.\n * Automatically decodes the values (assumes, that, if encoded, url/percent encoding has been used).\n *\n * You can provide names as an array or as comma-separated parameters.\n *\n * @param {?String|Array} [names] - the names of the cookies, if empty or not set, all available cookies are returned\n * @returns {Object} dictionary of named decoded values of the cookies, will be empty if none of the cookies were available\n *\n * @memberof Cookies:getCookies\n * @alias getCookies\n * @see getCookie\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookies(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookies('foobar', 'boofar')\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookies(names){\n\tnames = [];\n\tArray.from(arguments).forEach(argument => {\n\t\tnames = names.concat(argument);\n\t});\n\n\treturn getCookie(names);\n}\n\n\n\n/**\n * @namespace Cookies:setCookie\n */\n\n/**\n * Set a cookie value (if possible) by name. Value will automatically be encoded.\n *\n * If you set a cookie to a nullish value, the method will try to remove the cookie with the given options.\n *\n * @param {String} name - the name of the cookie to set\n * @param {?String} [value] - the value of the cookie to set\n * @param {?CookieOptions} [options] - the cookie options to apply\n * @returns {String|null} returns the set cookie value if available after setting or null if cookie not available (which would also mean, that setting the cookie did not work, or, in case of removal, that the removal worked)\n *\n * @memberof Cookies:setCookie\n * @alias setCookie\n * @see getCookie\n * @see getCookies\n * @see removeCookie\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie\n * @example\n * setCookie('mykittencookie', 'meow meow', {expires : 7, path : '/kittens', secure : true, samesite : 'strict'});\n */\nexport function setCookie(name, value, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:setCookie | no usable name`);\n\n\tname = `${name}`.trim();\n\tvalue = hasValue(value) ? encodeCookieValue(orDefault(value, '', 'str')) : null;\n\toptions = normalizeCookieOptions(options);\n\n\tlet cookieOptions = '';\n\tfor( let optionsProp in options ){\n\t\tconst option = options[optionsProp];\n\n\t\tif( !hasValue(option) || (option === false) ) continue;\n\n\t\tcookieOptions += `; ${optionsProp}`;\n\n\t\tif( option === true ) continue;\n\n\t\t// if the value itself contains a semicolon, according to RFC 6265 section 5.2,\n\t\t// we use everything that comes before the semicolon as the value and drop the rest\n\t\tcookieOptions += `=${option.split(';')[0]}`;\n\t}\n\n\tif( hasValue(value) ){\n\t\tdocument.cookie = `${encodeCookieName(name)}=${value}${cookieOptions}`;\n\t} else {\n\t\tremoveCookie(name, options);\n\t}\n\n\treturn getCookie(name);\n}\n\n\n\n/**\n * @namespace Cookies:removeCookie\n */\n\n/**\n * Removes a cookie (if possible) by name.\n *\n * @param {String} name - the name of the cookie to remove\n * @param {?CookieOptions} [options] - the cookie options to apply (needed for different paths/domains for example)\n * @returns {Boolean} true if cookie is not available anymore after removal, if this is false, cookie removal failed or another cookie of the same name is still available\n *\n * @memberof Cookies:removeCookie\n * @alias removeCookie\n * @see getCookie\n * @see getCookies\n * @see setCookie\n * @example\n * removeCookie('mykittencookie', {path : '/kittens'});\n */\nexport function removeCookie(name, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:removeCookie | no usable name`);\n\n\toptions = normalizeCookieOptions(options);\n\toptions.expires = -1;\n\n\treturn (setCookie(name, '', options) === null);\n}\n"]} \ No newline at end of file diff --git a/dist/css.js b/dist/css.js index fb757f48..7adf56db 100644 --- a/dist/css.js +++ b/dist/css.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module CSS */ -const MODULE_NAME="CSS";import{assert,isA,orDefault,isPlainObject,isElement,hasValue,isNaN}from"./basic.js";import{maskForRegEx}from"./strings.js";export function applyStyles(e,t,r=!1,s=!1){const l="applyStyles";r=orDefault(r,!1,"bool"),s=orDefault(s,!1,"bool"),assert(isElement(e),`CSS:${l} | element is not an html element`),assert(isPlainObject(t),`CSS:${l} | styles must be a plain object`);const o=["-webkit-","-moz-","-ms-","-o-","-khtml-"];return r&&Object.entries({...t}).forEach((([e,r])=>{o.forEach((s=>{t[s+e]="transition"===e?r.replace("transform",`${s}transform`):r}))})),Object.entries({...t}).forEach((([r,s])=>{isA(s,"number")&&0!==s?(t[r]=`${s}px`,e.style.setProperty(r,t[r])):hasValue(s)?(t[r]=`${s}`,e.style.setProperty(r,t[r])):(o.forEach((s=>{delete t[s+r],e.style.removeProperty(s+r)})),delete t[r],e.style.removeProperty(r))})),s?e.style:t}export function cssValueToNumber(e){return parseFloat(orDefault(e,"","str"))}export function cssUrlValueToUrl(e,t=null,r=null){e=orDefault(e,"","str"),t=orDefault(t,null,"str"),r=orDefault(r,null,"str");const s=new RegExp("(?:^|\\s|,)url\\((?:'|\")?([^'\"\\n\\r\\t]+)(?:'|\")?\\)","gmi"),l=[];let o;for(;null!==(o=s.exec(e));)o=o[1],hasValue(t,r)&&(o=o.replace(new RegExp(`^${maskForRegEx(t)}`),r)),l.push(o);return 1===l.length?l[0]:l.length>1?l:null}export function remByPx(e,t="html"){if(e=cssValueToNumber(e),t=orDefault(t,"html"),isElement(t))t=cssValueToNumber(t.style.getPropertyValue("font-size"));else{const e=cssValueToNumber(t);if(isNaN(e)){const e=document.querySelector(t);assert(hasValue(e),"CSS:remByPx | selector does not return element"),t=cssValueToNumber(e.style.getPropertyValue("font-size"))}else t=e}const r=e/t;return 0===t||isNaN(r)?null:`${r}rem`} +const MODULE_NAME="CSS";import{assert,isNumber,orDefault,isPlainObject,isElement,hasValue,isNaN}from"./basic.js";import{maskForRegEx}from"./strings.js";export function applyStyles(e,t,r=!1,s=!1){const l="applyStyles";r=orDefault(r,!1,"bool"),s=orDefault(s,!1,"bool"),assert(isElement(e),`CSS:${l} | element is not an html element`),assert(isPlainObject(t),`CSS:${l} | styles must be a plain object`);const o=["-webkit-","-moz-","-ms-","-o-","-khtml-"];return r&&Object.entries({...t}).forEach((([e,r])=>{o.forEach((s=>{t[s+e]="transition"===e?r.replace("transform",`${s}transform`):r}))})),Object.entries({...t}).forEach((([r,s])=>{isNumber(s)&&0!==s?(t[r]=`${s}px`,e.style.setProperty(r,t[r])):hasValue(s)?(t[r]=`${s}`,e.style.setProperty(r,t[r])):(o.forEach((s=>{delete t[s+r],e.style.removeProperty(s+r)})),delete t[r],e.style.removeProperty(r))})),s?e.style:t}export function cssValueToNumber(e){return parseFloat(orDefault(e,"","str"))}export function cssUrlValueToUrl(e,t=null,r=null){e=orDefault(e,"","str"),t=orDefault(t,null,"str"),r=orDefault(r,null,"str");const s=new RegExp("(?:^|\\s|,)url\\((?:'|\")?([^'\"\\n\\r\\t]+)(?:'|\")?\\)","gmi"),l=[];let o;for(;null!==(o=s.exec(e));)o=o[1],hasValue(t,r)&&(o=o.replace(new RegExp(`^${maskForRegEx(t)}`),r)),l.push(o);return 1===l.length?l[0]:l.length>1?l:null}export function remByPx(e,t="html"){if(e=cssValueToNumber(e),t=orDefault(t,"html"),isElement(t))t=cssValueToNumber(t.style.getPropertyValue("font-size"));else{const e=cssValueToNumber(t);if(isNaN(e)){const e=document.querySelector(t);assert(hasValue(e),"CSS:remByPx | selector does not return element"),t=cssValueToNumber(e.style.getPropertyValue("font-size"))}else t=e}const r=e/t;return 0===t||isNaN(r)?null:`${r}rem`} //# sourceMappingURL=css.js.map diff --git a/dist/css.js.map b/dist/css.js.map index 3e835c9a..d30e1dcc 100644 --- a/dist/css.js.map +++ b/dist/css.js.map @@ -1 +1 @@ -{"version":3,"file":"css.js","names":["MODULE_NAME","assert","isA","orDefault","isPlainObject","isElement","hasValue","isNaN","maskForRegEx","applyStyles","element","styles","crossBrowser","returnCssStyleDeclaration","__methodName__","vendorPrefixes","Object","entries","forEach","cssKey","cssValue","vendorPrefix","replace","style","setProperty","removeProperty","cssValueToNumber","value","parseFloat","cssUrlValueToUrl","urlValue","baseUrl","baseUrlSubstitution","urlValueRex","RegExp","matches","match","exec","push","length","remByPx","px","initial","getPropertyValue","document","querySelector","remVal"],"sources":["css.js"],"mappings":";;;AAQA,MAAMA,YAAc,aAMZC,OAAQC,IAAKC,UAAWC,cAAeC,UAAWC,SAAUC,UAAY,oBACxEC,iBAAmB,sBA6CpB,SAASC,YAAYC,EAASC,EAAQC,GAAa,EAAOC,GAA0B,GAC1F,MAAMC,EAAiB,cAEvBF,EAAeT,UAAUS,GAAc,EAAO,QAC9CC,EAA4BV,UAAUU,GAA2B,EAAO,QAExEZ,OAAOI,UAAUK,GAAU,OAAkBI,sCAC7Cb,OAAOG,cAAcO,GAAS,OAAkBG,qCAEhD,MAAMC,EAAiB,CAAC,WAAY,QAAS,OAAQ,MAAO,WA+B5D,OA7BIH,GACHI,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MAC7CL,EAAeG,SAAQG,IAErBV,EAAOU,EAAaF,GADP,eAAXA,EAC4BC,EAASE,QAAQ,YAAa,GAAGD,cAEjCD,CAC/B,GACC,IAIJJ,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MACzClB,IAAIkB,EAAU,WAA2B,IAAbA,GAC/BT,EAAOQ,GAAU,GAAGC,MACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,KAC9Bb,SAASc,IAQpBT,EAAOQ,GAAU,GAAGC,IACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,MARzCJ,EAAeG,SAAQG,WACfV,EAAOU,EAAaF,GAC3BT,EAAQa,MAAME,eAAeJ,EAAaF,EAAO,WAE3CR,EAAOQ,GACdT,EAAQa,MAAME,eAAeN,GAI9B,IAGMN,EAA4BH,EAAQa,MAAQZ,CACpD,QAsBO,SAASe,iBAAiBC,GAChC,OAAOC,WAAWzB,UAAUwB,EAAO,GAAI,OACxC,QA0BO,SAASE,iBAAiBC,EAAUC,EAAQ,KAAMC,EAAoB,MAC5EF,EAAW3B,UAAU2B,EAAU,GAAI,OACnCC,EAAU5B,UAAU4B,EAAS,KAAM,OACnCC,EAAsB7B,UAAU6B,EAAqB,KAAM,OAE3D,MACCC,EAAc,IAAIC,OAAO,2DAA4D,OACrFC,EAAU,GAGX,IAAIC,EACJ,KAAgD,QAAxCA,EAAQH,EAAYI,KAAKP,KAChCM,EAAQA,EAAM,GACV9B,SAASyB,EAASC,KACrBI,EAAQA,EAAMd,QAAQ,IAAIY,OAAO,IAAI1B,aAAauB,MAAaC,IAEhEG,EAAQG,KAAKF,GAGd,OAAuB,IAAnBD,EAAQI,OACJJ,EAAQ,GACLA,EAAQI,OAAS,EACpBJ,EAEA,IAET,QAiCO,SAASK,QAAQC,EAAIC,EAAQ,QAInC,GAHAD,EAAKf,iBAAiBe,GACtBC,EAAUvC,UAAUuC,EAAS,QAEzBrC,UAAUqC,GACbA,EAAUhB,iBAAiBgB,EAAQnB,MAAMoB,iBAAiB,kBACpD,CACN,MAAMhB,EAAQD,iBAAiBgB,GAC/B,GAAInC,MAAMoB,GAAQ,CACjB,MAAMjB,EAAUkC,SAASC,cAAcH,GACvCzC,OAAOK,SAASI,GAAU,kDAC1BgC,EAAUhB,iBAAiBhB,EAAQa,MAAMoB,iBAAiB,aAC3D,MACCD,EAAUf,CAEZ,CAEA,MAAMmB,EAASL,EAAKC,EAEpB,OAAiB,IAAZA,GAAmBnC,MAAMuC,GAGtB,KAFA,GAAGA,MAIZ","sourcesContent":["/*!\n * Module CSS\n */\n\n/**\n * @namespace CSS\n */\n\nconst MODULE_NAME = 'CSS';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isA, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js';\nimport {maskForRegEx} from './strings.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace CSS:applyStyles\n */\n\n/**\n * Applies CSS definitions to an HTMLElement, by providing a plain object of property-value-pairs.\n * Properties may be written as default CSS kebab-case properties such as \"margin-left\" or as JS\n * camel-cased versions such as \"marginLeft\".\n *\n * Providing a real JS number without a unit will be treated as a pixel value, so defining \"'line-height' : 0\" will\n * actually result in a 1px line-height. To actually set a unit-less value, just set the value as a string:\n * \"'line-height' : '0'\".\n *\n * Generally all CSS values are usually strings (this is also the way JS handles this),\n * treating plain numbers as pixels is just a convenience feature, since pixels are most likely to be\n * calculated values, where it is bothersome and error-prone to add the \"px\" all the time.\n *\n * To remove a property, just set the value to a nullish value. Deleting a property also tries to remove all\n * vendor prefixed variants.\n *\n * This function uses CSSStyleDeclaration.setProperty instead of direct style assignments. This means, that the\n * browser itself decides which value to apply, based on the support of the property. This means, the style object\n * will not be polluted with vendor stuff the browser does not support, but this also means, that all non-standard\n * properties might be refused. If you really need to set something out of spec, use direct style assignment instead.\n *\n * @param {HTMLElement} element - the element to apply the styles to, use null or undefined as value to remove a prop\n * @param {Object} styles - the styles to apply, provided as a plain object, defining property-value-pairs\n * @param {?Boolean} [crossBrowser=false] - set this to true, to automatically generate vendor-prefixed versions of all provided properties\n * @param {?Boolean} [returnCssStyleDeclaration=false] - set this to true, return the CSSStyleDeclaration of the element after the style application, rather than the plain object\n * @throws error if element is not an HTMLElement\n * @throws error if styles is not a plain object\n * @returns {Object|CSSStyleDeclaration} the applied/active styles\n *\n * @memberof CSS:applyStyles\n * @alias applyStyles\n * @example\n * applyStyles(document.body, {backgroundColor : red, transition : 'all 200ms'}, true);\n * applyStyles(document.querySelector('main'), {'font-family' : 'serif'}, false, true);\n */\nexport function applyStyles(element, styles, crossBrowser=false, returnCssStyleDeclaration=false){\n\tconst __methodName__ = 'applyStyles';\n\n\tcrossBrowser = orDefault(crossBrowser, false, 'bool');\n\treturnCssStyleDeclaration = orDefault(returnCssStyleDeclaration, false, 'bool');\n\n\tassert(isElement(element), `${MODULE_NAME}:${__methodName__} | element is not an html element`);\n\tassert(isPlainObject(styles), `${MODULE_NAME}:${__methodName__} | styles must be a plain object`);\n\n\tconst vendorPrefixes = ['-webkit-', '-moz-', '-ms-', '-o-', '-khtml-'];\n\n\tif( crossBrowser ){\n\t\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tif(cssKey === 'transition'){\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue.replace('transform', `${vendorPrefix}transform`);\n\t\t\t\t} else {\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\tif( isA(cssValue, 'number') && (cssValue !== 0) ){\n\t\t\tstyles[cssKey] = `${cssValue}px`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t} else if( !hasValue(cssValue) ){\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tdelete styles[vendorPrefix+cssKey];\n\t\t\t\telement.style.removeProperty(vendorPrefix+cssKey);\n\t\t\t});\n\t\t\tdelete styles[cssKey];\n\t\t\telement.style.removeProperty(cssKey);\n\t\t} else {\n\t\t\tstyles[cssKey] = `${cssValue}`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t}\n\t});\n\n\treturn returnCssStyleDeclaration ? element.style : styles;\n}\n\n\n\n/**\n * @namespace CSS:cssValueToNumber\n */\n\n/**\n * Converts a CSS-value to a number without unit. If the base number is an integer the result will also\n * be an integer, float values will also be converted correctly.\n *\n * @param {String} value - the css-value to convert\n * @returns {Number|NaN} true number representation of the given value or NaN if the value is not parsable\n *\n * @memberof CSS:cssValueToNumber\n * @alias cssValueToNumber\n * @example\n * document.querySelector('main').style.setProperty('width', '99vh');\n * cssValueToNumber(document.querySelector('main').style.getPropertyValue('width'));\n * => 99\n */\nexport function cssValueToNumber(value){\n\treturn parseFloat(orDefault(value, '', 'str'));\n}\n\n\n\n/**\n * @namespace CSS:cssUrlValueToUrl\n */\n\n/**\n * Converts a CSS-URL-value (\"url('/foo/bar/baz.jpg')\") to a plain URL usable in requests or src-attributes.\n *\n * @param {String} urlValue - the URL-value from CSS\n * @param {?String} [baseUrl=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace here\n * @param {?String} [baseUrlSubstitution=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace the baseUrl with here\n * @returns {String|Array|null} the extracted URL (or list of URLs if value contained several) with substitutions (if defined) or null if no URL-values were found\n *\n * @memberof CSS:cssUrlValueToUrl\n * @alias cssUrlValueToUrl\n * @example\n * cssUrlValueToUrl('url(\"https://foobar.com/test.jpg\")', 'https://foobar.com', '..');\n * => '../test.jpg'\n * cssUrlValueToUrl(`url(/foo/bar),\n * url('https://google.de') url(\"test.jpg\"),url(omg.svg)\n * url(http://lol.com)`)\n * => ['/foo/bar', 'https://google.com', 'test.jpg', 'omg.svg', 'http://lol.com']\n */\nexport function cssUrlValueToUrl(urlValue, baseUrl=null, baseUrlSubstitution=null){\n\turlValue = orDefault(urlValue, '', 'str');\n\tbaseUrl = orDefault(baseUrl, null, 'str');\n\tbaseUrlSubstitution = orDefault(baseUrlSubstitution, null, 'str');\n\n\tconst\n\t\turlValueRex = new RegExp('(?:^|\\\\s|,)url\\\\((?:\\'|\")?([^\\'\"\\\\n\\\\r\\\\t]+)(?:\\'|\")?\\\\)', 'gmi'),\n\t\tmatches = []\n\t;\n\n\tlet match;\n\twhile( (match = urlValueRex.exec(urlValue)) !== null ){\n\t\tmatch = match[1];\n\t\tif( hasValue(baseUrl, baseUrlSubstitution) ){\n\t\t\tmatch = match.replace(new RegExp(`^${maskForRegEx(baseUrl)}`), baseUrlSubstitution);\n\t\t}\n\t\tmatches.push(match);\n\t}\n\n\tif( matches.length === 1 ){\n\t\treturn matches[0];\n\t} else if( matches.length > 1 ){\n\t\treturn matches;\n\t} else {\n\t\treturn null;\n\t}\n}\n\n\n\n/**\n * @namespace CSS:remByPx\n */\n\n/**\n * Calculates a rem value based on a given px value.\n * As a default this method takes the font-size (supposedly being in px) of the html-container.\n * You can overwrite this behaviour by setting initial to a number to use as a base px value or\n * to a string, which then defines a new selector for an element to get the initial font-size from.\n * You can also provide an HTMLElement directly, but keep in mind that the element's font size definition\n * has to be in pixels, to make this work.\n *\n * In most cases you will have to define the initial value via a constant or a selector to a container\n * with non-changing font-size, since you can never be sure which relative font-size applies atm, even on first\n * call, after dom ready, since responsive definitions might already be active, returning a viewport-specific\n * size.\n *\n * @param {Number} px - the pixel value to convert to rem\n * @param {?(Number|String|HTMLElement)} [initial='html'] - either a pixel value to use as a conversion base, a selector for an element to get the initial font-size from or the element itself; keep in mind, that the element's font-size definition has to be in px\n * @throws error if given selector in initial does not return an element\n * @returns {String|null} the rem value string to use in a css definition or null if the value could not be calculated\n *\n * @memberof CSS:remByPx\n * @alias remByPx\n * @example\n * remByPx(20, 16);\n * => '1.25rem'\n * remByPx('100px', 'p.has-base-fontsize');\n */\nexport function remByPx(px, initial='html'){\n\tpx = cssValueToNumber(px);\n\tinitial = orDefault(initial, 'html');\n\n\tif( isElement(initial) ){\n\t\tinitial = cssValueToNumber(initial.style.getPropertyValue('font-size'));\n\t} else {\n\t\tconst value = cssValueToNumber(initial);\n\t\tif( isNaN(value) ){\n\t\t\tconst element = document.querySelector(initial);\n\t\t\tassert(hasValue(element), `${MODULE_NAME}:remByPx | selector does not return element`);\n\t\t\tinitial = cssValueToNumber(element.style.getPropertyValue('font-size'));\n\t\t} else {\n\t\t\tinitial = value;\n\t\t}\n\t}\n\n\tconst remVal = px / initial;\n\n\tif( (initial !== 0) && !isNaN(remVal) ){\n\t\treturn `${remVal}rem`;\n\t} else {\n\t\treturn null;\n\t}\n}\n"]} \ No newline at end of file +{"version":3,"file":"css.js","names":["MODULE_NAME","assert","isNumber","orDefault","isPlainObject","isElement","hasValue","isNaN","maskForRegEx","applyStyles","element","styles","crossBrowser","returnCssStyleDeclaration","__methodName__","vendorPrefixes","Object","entries","forEach","cssKey","cssValue","vendorPrefix","replace","style","setProperty","removeProperty","cssValueToNumber","value","parseFloat","cssUrlValueToUrl","urlValue","baseUrl","baseUrlSubstitution","urlValueRex","RegExp","matches","match","exec","push","length","remByPx","px","initial","getPropertyValue","document","querySelector","remVal"],"sources":["css.js"],"mappings":";;;AAQA,MAAMA,YAAc,aAMZC,OAAQC,SAAUC,UAAWC,cAAeC,UAAWC,SAAUC,UAAY,oBAC7EC,iBAAmB,sBA6CpB,SAASC,YAAYC,EAASC,EAAQC,GAAa,EAAOC,GAA0B,GAC1F,MAAMC,EAAiB,cAEvBF,EAAeT,UAAUS,GAAc,EAAO,QAC9CC,EAA4BV,UAAUU,GAA2B,EAAO,QAExEZ,OAAOI,UAAUK,GAAU,OAAkBI,sCAC7Cb,OAAOG,cAAcO,GAAS,OAAkBG,qCAEhD,MAAMC,EAAiB,CAAC,WAAY,QAAS,OAAQ,MAAO,WA+B5D,OA7BIH,GACHI,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MAC7CL,EAAeG,SAAQG,IAErBV,EAAOU,EAAaF,GADP,eAAXA,EAC4BC,EAASE,QAAQ,YAAa,GAAGD,cAEjCD,CAC/B,GACC,IAIJJ,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MACzClB,SAASkB,IAA2B,IAAbA,GAC1BT,EAAOQ,GAAU,GAAGC,MACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,KAC9Bb,SAASc,IAQpBT,EAAOQ,GAAU,GAAGC,IACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,MARzCJ,EAAeG,SAAQG,WACfV,EAAOU,EAAaF,GAC3BT,EAAQa,MAAME,eAAeJ,EAAaF,EAAO,WAE3CR,EAAOQ,GACdT,EAAQa,MAAME,eAAeN,GAI9B,IAGMN,EAA4BH,EAAQa,MAAQZ,CACpD,QAsBO,SAASe,iBAAiBC,GAChC,OAAOC,WAAWzB,UAAUwB,EAAO,GAAI,OACxC,QA0BO,SAASE,iBAAiBC,EAAUC,EAAQ,KAAMC,EAAoB,MAC5EF,EAAW3B,UAAU2B,EAAU,GAAI,OACnCC,EAAU5B,UAAU4B,EAAS,KAAM,OACnCC,EAAsB7B,UAAU6B,EAAqB,KAAM,OAE3D,MACCC,EAAc,IAAIC,OAAO,2DAA4D,OACrFC,EAAU,GAGX,IAAIC,EACJ,KAAgD,QAAxCA,EAAQH,EAAYI,KAAKP,KAChCM,EAAQA,EAAM,GACV9B,SAASyB,EAASC,KACrBI,EAAQA,EAAMd,QAAQ,IAAIY,OAAO,IAAI1B,aAAauB,MAAaC,IAEhEG,EAAQG,KAAKF,GAGd,OAAuB,IAAnBD,EAAQI,OACJJ,EAAQ,GACLA,EAAQI,OAAS,EACpBJ,EAEA,IAET,QAiCO,SAASK,QAAQC,EAAIC,EAAQ,QAInC,GAHAD,EAAKf,iBAAiBe,GACtBC,EAAUvC,UAAUuC,EAAS,QAEzBrC,UAAUqC,GACbA,EAAUhB,iBAAiBgB,EAAQnB,MAAMoB,iBAAiB,kBACpD,CACN,MAAMhB,EAAQD,iBAAiBgB,GAC/B,GAAInC,MAAMoB,GAAQ,CACjB,MAAMjB,EAAUkC,SAASC,cAAcH,GACvCzC,OAAOK,SAASI,GAAU,kDAC1BgC,EAAUhB,iBAAiBhB,EAAQa,MAAMoB,iBAAiB,aAC3D,MACCD,EAAUf,CAEZ,CAEA,MAAMmB,EAASL,EAAKC,EAEpB,OAAiB,IAAZA,GAAmBnC,MAAMuC,GAGtB,KAFA,GAAGA,MAIZ","sourcesContent":["/*!\n * Module CSS\n */\n\n/**\n * @namespace CSS\n */\n\nconst MODULE_NAME = 'CSS';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isNumber, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js';\nimport {maskForRegEx} from './strings.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace CSS:applyStyles\n */\n\n/**\n * Applies CSS definitions to an HTMLElement, by providing a plain object of property-value-pairs.\n * Properties may be written as default CSS kebab-case properties such as \"margin-left\" or as JS\n * camel-cased versions such as \"marginLeft\".\n *\n * Providing a real JS number without a unit will be treated as a pixel value, so defining \"'line-height' : 0\" will\n * actually result in a 1px line-height. To actually set a unit-less value, just set the value as a string:\n * \"'line-height' : '0'\".\n *\n * Generally all CSS values are usually strings (this is also the way JS handles this),\n * treating plain numbers as pixels is just a convenience feature, since pixels are most likely to be\n * calculated values, where it is bothersome and error-prone to add the \"px\" all the time.\n *\n * To remove a property, just set the value to a nullish value. Deleting a property also tries to remove all\n * vendor prefixed variants.\n *\n * This function uses CSSStyleDeclaration.setProperty instead of direct style assignments. This means, that the\n * browser itself decides which value to apply, based on the support of the property. This means, the style object\n * will not be polluted with vendor stuff the browser does not support, but this also means, that all non-standard\n * properties might be refused. If you really need to set something out of spec, use direct style assignment instead.\n *\n * @param {HTMLElement} element - the element to apply the styles to, use null or undefined as value to remove a prop\n * @param {Object} styles - the styles to apply, provided as a plain object, defining property-value-pairs\n * @param {?Boolean} [crossBrowser=false] - set this to true, to automatically generate vendor-prefixed versions of all provided properties\n * @param {?Boolean} [returnCssStyleDeclaration=false] - set this to true, return the CSSStyleDeclaration of the element after the style application, rather than the plain object\n * @throws error if element is not an HTMLElement\n * @throws error if styles is not a plain object\n * @returns {Object|CSSStyleDeclaration} the applied/active styles\n *\n * @memberof CSS:applyStyles\n * @alias applyStyles\n * @example\n * applyStyles(document.body, {backgroundColor : red, transition : 'all 200ms'}, true);\n * applyStyles(document.querySelector('main'), {'font-family' : 'serif'}, false, true);\n */\nexport function applyStyles(element, styles, crossBrowser=false, returnCssStyleDeclaration=false){\n\tconst __methodName__ = 'applyStyles';\n\n\tcrossBrowser = orDefault(crossBrowser, false, 'bool');\n\treturnCssStyleDeclaration = orDefault(returnCssStyleDeclaration, false, 'bool');\n\n\tassert(isElement(element), `${MODULE_NAME}:${__methodName__} | element is not an html element`);\n\tassert(isPlainObject(styles), `${MODULE_NAME}:${__methodName__} | styles must be a plain object`);\n\n\tconst vendorPrefixes = ['-webkit-', '-moz-', '-ms-', '-o-', '-khtml-'];\n\n\tif( crossBrowser ){\n\t\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tif(cssKey === 'transition'){\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue.replace('transform', `${vendorPrefix}transform`);\n\t\t\t\t} else {\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\tif( isNumber(cssValue) && (cssValue !== 0) ){\n\t\t\tstyles[cssKey] = `${cssValue}px`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t} else if( !hasValue(cssValue) ){\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tdelete styles[vendorPrefix+cssKey];\n\t\t\t\telement.style.removeProperty(vendorPrefix+cssKey);\n\t\t\t});\n\t\t\tdelete styles[cssKey];\n\t\t\telement.style.removeProperty(cssKey);\n\t\t} else {\n\t\t\tstyles[cssKey] = `${cssValue}`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t}\n\t});\n\n\treturn returnCssStyleDeclaration ? element.style : styles;\n}\n\n\n\n/**\n * @namespace CSS:cssValueToNumber\n */\n\n/**\n * Converts a CSS-value to a number without unit. If the base number is an integer the result will also\n * be an integer, float values will also be converted correctly.\n *\n * @param {String} value - the css-value to convert\n * @returns {Number|NaN} true number representation of the given value or NaN if the value is not parsable\n *\n * @memberof CSS:cssValueToNumber\n * @alias cssValueToNumber\n * @example\n * document.querySelector('main').style.setProperty('width', '99vh');\n * cssValueToNumber(document.querySelector('main').style.getPropertyValue('width'));\n * => 99\n */\nexport function cssValueToNumber(value){\n\treturn parseFloat(orDefault(value, '', 'str'));\n}\n\n\n\n/**\n * @namespace CSS:cssUrlValueToUrl\n */\n\n/**\n * Converts a CSS-URL-value (\"url('/foo/bar/baz.jpg')\") to a plain URL usable in requests or src-attributes.\n *\n * @param {String} urlValue - the URL-value from CSS\n * @param {?String} [baseUrl=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace here\n * @param {?String} [baseUrlSubstitution=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace the baseUrl with here\n * @returns {String|Array|null} the extracted URL (or list of URLs if value contained several) with substitutions (if defined) or null if no URL-values were found\n *\n * @memberof CSS:cssUrlValueToUrl\n * @alias cssUrlValueToUrl\n * @example\n * cssUrlValueToUrl('url(\"https://foobar.com/test.jpg\")', 'https://foobar.com', '..');\n * => '../test.jpg'\n * cssUrlValueToUrl(`url(/foo/bar),\n * url('https://google.de') url(\"test.jpg\"),url(omg.svg)\n * url(http://lol.com)`)\n * => ['/foo/bar', 'https://google.com', 'test.jpg', 'omg.svg', 'http://lol.com']\n */\nexport function cssUrlValueToUrl(urlValue, baseUrl=null, baseUrlSubstitution=null){\n\turlValue = orDefault(urlValue, '', 'str');\n\tbaseUrl = orDefault(baseUrl, null, 'str');\n\tbaseUrlSubstitution = orDefault(baseUrlSubstitution, null, 'str');\n\n\tconst\n\t\turlValueRex = new RegExp('(?:^|\\\\s|,)url\\\\((?:\\'|\")?([^\\'\"\\\\n\\\\r\\\\t]+)(?:\\'|\")?\\\\)', 'gmi'),\n\t\tmatches = []\n\t;\n\n\tlet match;\n\twhile( (match = urlValueRex.exec(urlValue)) !== null ){\n\t\tmatch = match[1];\n\t\tif( hasValue(baseUrl, baseUrlSubstitution) ){\n\t\t\tmatch = match.replace(new RegExp(`^${maskForRegEx(baseUrl)}`), baseUrlSubstitution);\n\t\t}\n\t\tmatches.push(match);\n\t}\n\n\tif( matches.length === 1 ){\n\t\treturn matches[0];\n\t} else if( matches.length > 1 ){\n\t\treturn matches;\n\t} else {\n\t\treturn null;\n\t}\n}\n\n\n\n/**\n * @namespace CSS:remByPx\n */\n\n/**\n * Calculates a rem value based on a given px value.\n * As a default this method takes the font-size (supposedly being in px) of the html-container.\n * You can overwrite this behaviour by setting initial to a number to use as a base px value or\n * to a string, which then defines a new selector for an element to get the initial font-size from.\n * You can also provide an HTMLElement directly, but keep in mind that the element's font size definition\n * has to be in pixels, to make this work.\n *\n * In most cases you will have to define the initial value via a constant or a selector to a container\n * with non-changing font-size, since you can never be sure which relative font-size applies atm, even on first\n * call, after dom ready, since responsive definitions might already be active, returning a viewport-specific\n * size.\n *\n * @param {Number} px - the pixel value to convert to rem\n * @param {?(Number|String|HTMLElement)} [initial='html'] - either a pixel value to use as a conversion base, a selector for an element to get the initial font-size from or the element itself; keep in mind, that the element's font-size definition has to be in px\n * @throws error if given selector in initial does not return an element\n * @returns {String|null} the rem value string to use in a css definition or null if the value could not be calculated\n *\n * @memberof CSS:remByPx\n * @alias remByPx\n * @example\n * remByPx(20, 16);\n * => '1.25rem'\n * remByPx('100px', 'p.has-base-fontsize');\n */\nexport function remByPx(px, initial='html'){\n\tpx = cssValueToNumber(px);\n\tinitial = orDefault(initial, 'html');\n\n\tif( isElement(initial) ){\n\t\tinitial = cssValueToNumber(initial.style.getPropertyValue('font-size'));\n\t} else {\n\t\tconst value = cssValueToNumber(initial);\n\t\tif( isNaN(value) ){\n\t\t\tconst element = document.querySelector(initial);\n\t\t\tassert(hasValue(element), `${MODULE_NAME}:remByPx | selector does not return element`);\n\t\t\tinitial = cssValueToNumber(element.style.getPropertyValue('font-size'));\n\t\t} else {\n\t\t\tinitial = value;\n\t\t}\n\t}\n\n\tconst remVal = px / initial;\n\n\tif( (initial !== 0) && !isNaN(remVal) ){\n\t\treturn `${remVal}rem`;\n\t} else {\n\t\treturn null;\n\t}\n}\n"]} \ No newline at end of file diff --git a/dist/elements.js b/dist/elements.js index 82345eea..3a735825 100644 --- a/dist/elements.js +++ b/dist/elements.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Elements */ -const MODULE_NAME="Elements";import{orDefault,isA,isPlainObject,isSelector,isElement,hasValue,assert,size,Deferred}from"./basic.js";import{randomUuid}from"./random.js";import{clone}from"./objects.js";import{onDomReady}from"./events.js";import{applyStyles}from"./css.js";const NOT_AN_HTMLELEMENT_ERROR="given node/target is not an HTMLElement";let BROWSER_HAS_CSS_SCOPE_SUPPORT;try{document.querySelector(":scope *")}catch(e){BROWSER_HAS_CSS_SCOPE_SUPPORT=!1}export function createNode(e,t=null,n=null){e=orDefault(e,"span","str").trim(),t=isPlainObject(t)?t:null,n=orDefault(n,null,"str");const s=document.createElement("div");/^<[^\/][^<>]*>/.test(e)&&/<\/[^<>\/]+>$/.test(e)?s.innerHTML=e:s.appendChild(document.createElement(e));const r=s.firstChild;if(s.removeChild(r),hasValue(t))for(let e in t)r.setAttribute(e,`${t[e]}`);return hasValue(n)&&(r.textContent=n),r}export function insertNode(e,t,n="beforeend"){switch(assert(isElement(e),`Elements.insertNode | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),n){case"beforebegin":case"before":n="beforebegin";break;case"afterend":case"after":n="afterend";break;case"afterbegin":case"prepend":n="afterbegin";break;default:n="beforeend"}return e.insertAdjacentElement(n,t),t}export function replaceNode(e,t){const n="replaceNode";return assert(isElement(e),`Elements.${n} | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),assert(isElement(e.parentNode),`Elements.${n} | given target does not have a parent)`),insertNode(e,t,"after"),e.parentNode.removeChild(e),t}export function defineNode(e,t,n=null){const s="defineNode";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isPlainObject(t),`Elements:${s} | definitions is not a plain object`);const r="<-";return isElement(n)&&Array.from(n.attributes).forEach((e=>{(t[e.name]===r||!hasValue(t[e.name])&&(t["data*"]===r&&e.name.startsWith("data-")||t["on*"]===r&&e.name.startsWith("on")))&&(t[e.name]=e.value),(t[`+${e.name}`]===r||!hasValue(t[`+${e.name}`])&&(t["+data*"]===r&&e.name.startsWith("data-")||t["+on*"]===r&&e.name.startsWith("on")))&&(hasValue(t[`+${e.name}`])&&t[`+${e.name}`]!==r||(t[`+${e.name}`]=""),t[`+${e.name}`]+=e.value)})),delete t["data*"],delete t["+data*"],delete t["on*"],delete t["+on*"],Object.keys(t).forEach((e=>{t[e]===r&&delete t[e]})),Object.keys(t).sort().reverse().forEach((n=>{const s=t[n],r=n.startsWith("+");r&&(n=n.slice(1)),n.endsWith("*")&&(n=n.slice(0,-1)),"class"===n?(r||e.setAttribute("class",""),[].concat(s).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(`${t.trim()}`)}))}))):"style"===n?(r||e.setAttribute("style",""),[].concat(s).forEach((t=>{if(!isPlainObject(t)){const e=`${t}`.split(";"),n={};e.forEach((e=>{let[t,s]=e.split(":");t=t.trim(),hasValue(s)&&(s=s.trim(),s=s.endsWith(";")?s.slice(0,-1):s,n[t]=s)})),t=n}hasValue(t)&&applyStyles(e,t)}))):r?e.setAttribute(n,`${e.getAttribute(n)??""}${s}`):e.setAttribute(n,`${s}`)})),e}export function getTextContent(e,t=!1){if(t=orDefault(t,!1,"bool"),isA(e,"string")&&(e=createNode(e)),assert(isElement(e),"Elements:getTextContent | target is neither node nor markup"),t){let t="";return e.childNodes.forEach((e=>{3===e.nodeType&&(t+=e.textContent)})),t}return e.textContent}export function isInDom(e){return assert(isElement(e),`Elements:isInDom | ${NOT_AN_HTMLELEMENT_ERROR}`),isA(document.contains,"function")?document.contains(e):document.body.contains(e)}export function getData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:getData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n={};return hasValue(t)?t.forEach((t=>{let s=e.getAttribute(`data-${t}`);if(hasValue(s))try{n[t]=JSON.parse(s)}catch(e){n[t]=s}})):Array.from(e.attributes).forEach((e=>{if(e.name.startsWith("data-")){const t=e.name.replace(/^data-/,"");try{n[t]=JSON.parse(e.value)}catch(s){n[t]=e.value}}})),0===size(n)?n=null:1===t?.length&&(n=n[t[0]]??null),n}export function setData(e,t,n=null){const s="setData";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`);let r=null;hasValue(n)&&(r=`${t}`,t={[r]:n}),assert(isPlainObject(t),`Elements:${s} | dataSet is not a plain object`);const a={};return Object.entries(t).forEach((([t,n])=>{if(isA(n,"function")&&(n=n()),void 0!==n){let s,r;try{s=JSON.stringify(n),r=JSON.parse(s)}catch(e){s=`${n}`,r=s}s=s.replace(/^['"]/,"").replace(/['"]$/,"").trim(),""!==s?(a[t]=r,e.setAttribute(`data-${t}`,s)):e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))}else e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))})),hasValue(r)?r in a?a[r]:null:size(a)>0?a:null}export function removeData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:removeData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n=getData(e,t);return hasValue(n)?setData(e,1===t?.length?{[t[0]]:void 0}:Object.keys(n).reduce(((e,t)=>(e[t]=void 0,e)),{})):n=null,n}export function find(e,t="*",n=!1){const s=/:scope(?![\w-])/gi;if(assert(isElement(e),`Elements:find | ${NOT_AN_HTMLELEMENT_ERROR}`),t=orDefault(t,"*","str").trim(),s.test(t)||(t=`:scope ${t}`),n=orDefault(n,!1,"bool"),BROWSER_HAS_CSS_SCOPE_SUPPORT)return n?e.querySelector(t):Array.from(e.querySelectorAll(t));{const r=`find-scope-${randomUuid()}`;t=t.replace(s,`[${r}]`),e.setAttribute(r,"");const a=n?e.querySelector(t):Array.from(e.querySelectorAll(t));return e.removeAttribute(r),a}}export function findOne(e,t="*"){return find(e,t,!0)}export function findTextNodes(e,t=null,n=!1){t=isA(t,"function")?t:()=>!0,n=orDefault(n,!1,"bool"),assert(isElement(e),`Elements:findTextNodes | ${NOT_AN_HTMLELEMENT_ERROR}`);const s=e=>3===e.nodeType&&""!==e.textContent.trim()&&!!t(e),r=e=>s(e)?[].concat(e):Array.from(e.childNodes).reduce(((e,t)=>s(t)?e.concat(t):n?e:e.concat(r(t))),[]);return r(e)}export function prime(e,t,n=null,s="primed"){const r="prime";n=orDefault(n,{}),s=orDefault(s,"primed","str"),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isA(t,"function"),`Elements:${r} | init is not a function`);const a=new Deferred;return!0!==getData(e,s)?(setData(e,s,!0),onDomReady((()=>{const n=t(e);hasValue(n)&&isA(n.then,"function")&&isA(n.catch,"function")?n.then((e=>{a.resolve(e)})).catch((e=>{a.reject(e)})):a.resolve(n),setData(e,`${s}-ready`,!0)}))):a.resolve(void 0),a.then((()=>{hasValue(n.remove)&&[].concat(n.remove).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.remove(t.trim())}))})),hasValue(n.add)&&[].concat(n.add).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(t.trim())}))})),setData(e,`${s}-resolved`,!0)})),a}export function measureHiddenDimensions(e,t="outer",n=null,s=null){const r="measureHidden",a={offset:{width:"offsetWidth",height:"offsetHeight"},outer:{width:"offsetWidth",height:"offsetHeight"},client:{width:"clientWidth",height:"clientHeight"},inner:{width:"clientWidth",height:"clientHeight"},scroll:{width:"scrollWidth",height:"scrollHeight"}};t=a[orDefault(t,"outer","str")]??a.outer,s=orDefault(s,document.body),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isElement(s),`Elements:${r} | context is no an htmlelement`);const o=createNode("div",{id:`sandbox-${randomUuid()}`,class:"sandbox",style:"display:block; opacity:0; visibility:hidden; pointer-events:none; position:absolute; top:-10000px; left:-10000px;"}),i=clone(e);s.appendChild(o),o.appendChild(i);const l=isSelector(n)?i.querySelector(n):i,c=l?.[t.width]??0,d=l?.[t.height]??0,u={width:c,height:d,toString:()=>`${c}x${d}`};return s.removeChild(o),u} +const MODULE_NAME="Elements";import{orDefault,isString,isFunction,isPlainObject,isSelector,isElement,hasValue,assert,size,Deferred}from"./basic.js";import{randomUuid}from"./random.js";import{clone}from"./objects.js";import{onDomReady}from"./events.js";import{applyStyles}from"./css.js";const NOT_AN_HTMLELEMENT_ERROR="given node/target is not an HTMLElement";let BROWSER_HAS_CSS_SCOPE_SUPPORT;try{document.querySelector(":scope *")}catch(e){BROWSER_HAS_CSS_SCOPE_SUPPORT=!1}export function createNode(e,t=null,n=null){e=orDefault(e,"span","str").trim(),t=isPlainObject(t)?t:null,n=orDefault(n,null,"str");const s=document.createElement("div");/^<[^\/][^<>]*>/.test(e)&&/<\/[^<>\/]+>$/.test(e)?s.innerHTML=e:s.appendChild(document.createElement(e));const r=s.firstChild;if(s.removeChild(r),hasValue(t))for(let e in t)r.setAttribute(e,`${t[e]}`);return hasValue(n)&&(r.textContent=n),r}export function insertNode(e,t,n="beforeend"){switch(assert(isElement(e),`Elements.insertNode | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),n){case"beforebegin":case"before":n="beforebegin";break;case"afterend":case"after":n="afterend";break;case"afterbegin":case"prepend":n="afterbegin";break;default:n="beforeend"}return e.insertAdjacentElement(n,t),t}export function replaceNode(e,t){const n="replaceNode";return assert(isElement(e),`Elements.${n} | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),assert(isElement(e.parentNode),`Elements.${n} | given target does not have a parent)`),insertNode(e,t,"after"),e.parentNode.removeChild(e),t}export function defineNode(e,t,n=null){const s="defineNode";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isPlainObject(t),`Elements:${s} | definitions is not a plain object`);const r="<-";return isElement(n)&&Array.from(n.attributes).forEach((e=>{(t[e.name]===r||!hasValue(t[e.name])&&(t["data*"]===r&&e.name.startsWith("data-")||t["on*"]===r&&e.name.startsWith("on")))&&(t[e.name]=e.value),(t[`+${e.name}`]===r||!hasValue(t[`+${e.name}`])&&(t["+data*"]===r&&e.name.startsWith("data-")||t["+on*"]===r&&e.name.startsWith("on")))&&(hasValue(t[`+${e.name}`])&&t[`+${e.name}`]!==r||(t[`+${e.name}`]=""),t[`+${e.name}`]+=e.value)})),delete t["data*"],delete t["+data*"],delete t["on*"],delete t["+on*"],Object.keys(t).forEach((e=>{t[e]===r&&delete t[e]})),Object.keys(t).sort().reverse().forEach((n=>{const s=t[n],r=n.startsWith("+");r&&(n=n.slice(1)),n.endsWith("*")&&(n=n.slice(0,-1)),"class"===n?(r||e.setAttribute("class",""),[].concat(s).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(`${t.trim()}`)}))}))):"style"===n?(r||e.setAttribute("style",""),[].concat(s).forEach((t=>{if(!isPlainObject(t)){const e=`${t}`.split(";"),n={};e.forEach((e=>{let[t,s]=e.split(":");t=t.trim(),hasValue(s)&&(s=s.trim(),s=s.endsWith(";")?s.slice(0,-1):s,n[t]=s)})),t=n}hasValue(t)&&applyStyles(e,t)}))):r?e.setAttribute(n,`${e.getAttribute(n)??""}${s}`):e.setAttribute(n,`${s}`)})),e}export function getTextContent(e,t=!1){if(t=orDefault(t,!1,"bool"),isString(e)&&(e=createNode(e)),assert(isElement(e),"Elements:getTextContent | target is neither node nor markup"),t){let t="";return e.childNodes.forEach((e=>{3===e.nodeType&&(t+=e.textContent)})),t}return e.textContent}export function isInDom(e){return assert(isElement(e),`Elements:isInDom | ${NOT_AN_HTMLELEMENT_ERROR}`),isFunction(document.contains)?document.contains(e):document.body.contains(e)}export function getData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:getData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n={};return hasValue(t)?t.forEach((t=>{let s=e.getAttribute(`data-${t}`);if(hasValue(s))try{n[t]=JSON.parse(s)}catch(e){n[t]=s}})):Array.from(e.attributes).forEach((e=>{if(e.name.startsWith("data-")){const t=e.name.replace(/^data-/,"");try{n[t]=JSON.parse(e.value)}catch(s){n[t]=e.value}}})),0===size(n)?n=null:1===t?.length&&(n=n[t[0]]??null),n}export function setData(e,t,n=null){const s="setData";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`);let r=null;hasValue(n)&&(r=`${t}`,t={[r]:n}),assert(isPlainObject(t),`Elements:${s} | dataSet is not a plain object`);const a={};return Object.entries(t).forEach((([t,n])=>{if(isFunction(n)&&(n=n()),void 0!==n){let s,r;try{s=JSON.stringify(n),r=JSON.parse(s)}catch(e){s=`${n}`,r=s}s=s.replace(/^['"]/,"").replace(/['"]$/,"").trim(),""!==s?(a[t]=r,e.setAttribute(`data-${t}`,s)):e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))}else e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))})),hasValue(r)?r in a?a[r]:null:size(a)>0?a:null}export function removeData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:removeData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n=getData(e,t);return hasValue(n)?setData(e,1===t?.length?{[t[0]]:void 0}:Object.keys(n).reduce(((e,t)=>(e[t]=void 0,e)),{})):n=null,n}export function find(e,t="*",n=!1){const s=/:scope(?![\w-])/gi;if(assert(isElement(e),`Elements:find | ${NOT_AN_HTMLELEMENT_ERROR}`),t=orDefault(t,"*","str").trim(),s.test(t)||(t=`:scope ${t}`),n=orDefault(n,!1,"bool"),BROWSER_HAS_CSS_SCOPE_SUPPORT)return n?e.querySelector(t):Array.from(e.querySelectorAll(t));{const r=`find-scope-${randomUuid()}`;t=t.replace(s,`[${r}]`),e.setAttribute(r,"");const a=n?e.querySelector(t):Array.from(e.querySelectorAll(t));return e.removeAttribute(r),a}}export function findOne(e,t="*"){return find(e,t,!0)}export function findTextNodes(e,t=null,n=!1){t=isFunction(t)?t:()=>!0,n=orDefault(n,!1,"bool"),assert(isElement(e),`Elements:findTextNodes | ${NOT_AN_HTMLELEMENT_ERROR}`);const s=e=>3===e.nodeType&&""!==e.textContent.trim()&&!!t(e),r=e=>s(e)?[].concat(e):Array.from(e.childNodes).reduce(((e,t)=>s(t)?e.concat(t):n?e:e.concat(r(t))),[]);return r(e)}export function prime(e,t,n=null,s="primed"){const r="prime";n=orDefault(n,{}),s=orDefault(s,"primed","str"),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isFunction(t),`Elements:${r} | init is not a function`);const a=new Deferred;return!0!==getData(e,s)?(setData(e,s,!0),onDomReady((()=>{const n=t(e);hasValue(n)&&isFunction(n.then)&&isFunction(n.catch)?n.then((e=>{a.resolve(e)})).catch((e=>{a.reject(e)})):a.resolve(n),setData(e,`${s}-ready`,!0)}))):a.resolve(void 0),a.then((()=>{hasValue(n.remove)&&[].concat(n.remove).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.remove(t.trim())}))})),hasValue(n.add)&&[].concat(n.add).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(t.trim())}))})),setData(e,`${s}-resolved`,!0)})),a}export function measureHiddenDimensions(e,t="outer",n=null,s=null){const r="measureHidden",a={offset:{width:"offsetWidth",height:"offsetHeight"},outer:{width:"offsetWidth",height:"offsetHeight"},client:{width:"clientWidth",height:"clientHeight"},inner:{width:"clientWidth",height:"clientHeight"},scroll:{width:"scrollWidth",height:"scrollHeight"}};t=a[orDefault(t,"outer","str")]??a.outer,s=orDefault(s,document.body),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isElement(s),`Elements:${r} | context is no an htmlelement`);const o=createNode("div",{id:`sandbox-${randomUuid()}`,class:"sandbox",style:"display:block; opacity:0; visibility:hidden; pointer-events:none; position:absolute; top:-10000px; left:-10000px;"}),i=clone(e);s.appendChild(o),o.appendChild(i);const l=isSelector(n)?i.querySelector(n):i,c=l?.[t.width]??0,d=l?.[t.height]??0,u={width:c,height:d,toString:()=>`${c}x${d}`};return s.removeChild(o),u} //# sourceMappingURL=elements.js.map diff --git a/dist/elements.js.map b/dist/elements.js.map index fa897e6e..dd6302da 100644 --- a/dist/elements.js.map +++ b/dist/elements.js.map @@ -1 +1 @@ -{"version":3,"file":"elements.js","names":["MODULE_NAME","orDefault","isA","isPlainObject","isSelector","isElement","hasValue","assert","size","Deferred","randomUuid","clone","onDomReady","applyStyles","NOT_AN_HTMLELEMENT_ERROR","BROWSER_HAS_CSS_SCOPE_SUPPORT","document","querySelector","ex","createNode","tag","attributes","content","trim","outerNode","createElement","test","innerHTML","appendChild","node","firstChild","removeChild","attribute","setAttribute","textContent","insertNode","target","position","insertAdjacentElement","replaceNode","__methodName__","parentNode","defineNode","definition","boilerplateNode","inheritValue","Array","from","forEach","name","startsWith","value","Object","keys","sort","reverse","addValue","slice","endsWith","concat","split","classList","add","rules","valueObj","rule","key","prop","getAttribute","getTextContent","onlyFirstLevel","childNodes","nodeType","isInDom","contains","body","getData","properties","data","property","attributeValue","JSON","parse","replace","length","setData","dataSet","singleValue","singleKey","appliedValues","entries","undefined","stringifiedValue","getValue","stringify","hasAttribute","removeAttribute","removeData","reduce","removalDataSet","find","selector","onlyOne","scopeRex","querySelectorAll","fallbackScopeAttribute","found","findOne","findTextNodes","filter","isValidTextNode","extractTextNodes","textNodes","childNode","prime","init","classChanges","markerAttributesName","deferred","initResult","then","catch","resolution","resolve","error","reject","remove","removeClass","addClass","measureHiddenDimensions","method","context","methods","offset","width","height","outer","client","inner","scroll","sandbox","id","class","style","measureClone","dimensions","toString"],"sources":["elements.js"],"mappings":"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","sourcesContent":["/*!\n * Module Elements\n */\n\n/**\n * @namespace Elements\n */\n\nconst MODULE_NAME = 'Elements';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {orDefault, isA, isPlainObject, isSelector, isElement, hasValue, assert, size, Deferred} from './basic.js';\nimport {randomUuid} from './random.js';\nimport {clone} from './objects.js';\nimport {onDomReady} from './events.js';\nimport {applyStyles} from './css.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst NOT_AN_HTMLELEMENT_ERROR = 'given node/target is not an HTMLElement';\nlet BROWSER_HAS_CSS_SCOPE_SUPPORT;\ntry {\n\tdocument.querySelector(':scope *');\n} catch(ex){\n\tBROWSER_HAS_CSS_SCOPE_SUPPORT = false;\n}\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Elements:createNode\n */\n\n/**\n * Creates an element on the fly programmatically, based on provided name, attributes and content or markup,\n * without inserting it into the DOM.\n *\n * If you provide markup as \"tag\", make sure that there is one single root element, this method returns exactly one\n * element, not a NodeList. Also be sure to _not_ just pass HTML source from an unsecure source, since this\n * method does not deal with potential security risks.\n *\n * One thing about dynamically creating script tags with this: if you want the script is javascript and you want to\n * actually execute the script upon adding it to the dom, you cannot provide the complete tag as a source string,\n * since scripts created with innerHTML will not execute.\n * (see: https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#security_considerations)\n * Instead, just provide the tag name and define attributes and source via the parameters instead.\n *\n * @param {?String} [tag='span'] - tag of the element to create or markup for root element\n * @param {?Object} [attributes=null] - tag attributes as key/value-pairs, will also be added to provided markup\n * @param {?String} [content=null] - content to insert into the element as textContent, be aware, that this will replace other content in provided markup\n * @returns {HTMLElement} the created DOM-node\n *\n * @memberof Elements:createNode\n * @alias createNode\n * @example\n * document.body.appendChild(\n * createNode('div', {id : 'content', style : 'display:none;'}, 'loading...')\n * );\n * document.body.appendChild(\n * createNode('
loading...
')\n * );\n * document.body.appendChild(\n * createNode('script', {type : 'text/javascript'}, 'alert(\"Hello World\");');\n * );\n */\nexport function createNode(tag, attributes=null, content=null){\n\ttag = orDefault(tag, 'span', 'str').trim();\n\tattributes = isPlainObject(attributes) ? attributes : null;\n\tcontent = orDefault(content, null, 'str');\n\n\t// using anything more generic like template results in non-standard nodes like\n\t// `);\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve(\n\t\t\t\t\t\t(resolveTo === 'element')\n\t\t\t\t\t\t\t? element\n\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t(resolveTo === 'raw')\n\t\t\t\t\t\t\t\t? JSON.stringify(json)\n\t\t\t\t\t\t\t\t: json\n\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createRestfulJsonClient\n */\n\n/**\n * @typedef RestfulJsonClientPathFunction\n * @type {Function}\n * @param {String} path - the current path to request from baseUrl\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientOptionsFunction\n * @type {Function}\n * @param {?Object} options - options plain object to merge with baseOptions to define current request options (see JsonFetchRequest for details and defaults); if nullish, will reset to baseOptions\n * @throws error if given options are not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientHeaderFunction\n * @type {Function}\n * @param {String} key - the header to set for all following requests\n * @param {?String} value - the header's value; nullish value will remove the header again\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientParamsFunction\n * @type {Function}\n * @param {?*} params - query parameters to set on the current URL, this parameter takes all regular definitions for URLSearchParams constructor, as well as flat plain objects, which may also have arrays as values; if nullish, parameters are emptied\n * @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientDataFunction\n * @type {Function}\n * @param {?Object} data - data payload to send with the next POST, PUT or PATCH request, this parameter will set a permanent payload, for one-off payloads, use the verb method's parameter; if nullish, data will be emptied\n * @throws error if given data is not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientGetFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPostFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPutFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPatchFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientDeleteFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClient\n * @type {Object}\n * @property {Object} config - the current configuration state of the client\n * @property {URL} config.url=baseUrl - the current, complete URL to query (baseUrl + path)\n * @property {Object} config.options - the current request options (see JsonFetchRequest for details and defaults)\n * @property {URLSearchParams} config.params - the current searchParams of config.url, with which to query the URL\n * @property {Object} config.data={} - the current data payload object to send with POST, PUT and PATCH (this will persist between requests, set one-off data via verb methods)\n * @property {RestfulJsonClientPathFunction} path - sets the current request path, which will be concatenated after baseUrl\n * @property {RestfulJsonClientOptionsFunction} options - sets the current request options, which will be merged with baseOptions to constitute current request options\n * @property {RestfulJsonClientHeaderFunction} header - sets a header for all subsequent requests\n * @property {RestfulJsonClientParamsFunction} params - sets query parameters to be added to the request URL\n * @property {RestfulJsonClientDataFunction} data - sets data payload for POST, PUT and PATCH requests\n * @property {RestfulJsonClientGetFunction} get - queries the current URL via GET\n * @property {RestfulJsonClientPostFunction} post - queries the current URL via POST using defined data\n * @property {RestfulJsonClientPutFunction} put - queries the current URL via PUT using defined data\n * @property {RestfulJsonClientPatchFunction} patch - queries the current URL via PATCH using defined data\n * @property {RestfulJsonClientDeleteFunction} delete - queries the current URL via DELETE\n */\n\n/**\n * This method creates a dedicated client for restful operations against an API via JSON payloads and responses.\n *\n * Internally this implementation uses createJsonRequest to actually request stuff, while the return value of this\n * method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as\n * standard methods for HTTP verbs and setup things like setting headers.\n *\n * @param {String} baseUrl - the base URL for all queries, based on which final request URLs will be built, adding the paths\n * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/json\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/json\"\n * @returns {RestfulJsonClient}\n *\n * @memberof Requests:createRestfulJsonClient\n * @alias createRestfulJsonClient\n * @see createJsonRequest\n * @example\n * const client = createRestfulJsonClient('https://jsonplaceholder.typicode.com', {credentials : 'include'});\n * const postJson = await client\n * .path('/posts')\n * \t .params({\n * \t ids : [1, 2],\n * \t q : 'lorem'\n * \t })\n * \t .data({\n * \t title : 'foo',\n * \t body : 'bar',\n * \t userId : 1,\n * \t })\n * \t .post()\n * ;\n */\nexport function createRestfulJsonClient(baseUrl, baseOptions=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createRestfulJsonClient',\n\t\timplementation = createJsonRequest,\n\t\tcontentTypeHeader = 'Content-Type',\n\t\tcontentType = 'application/json',\n\t\tdataValidationMessage = 'data must be plain object',\n\t\toptionsValidationMessage = 'options must be plain object'\n\t;\n\n\n\tfunction flatEntries(obj){\n\t\tconst\n\t\t\tentries = Object.entries(obj),\n\t\t\tflattenedEntries = []\n\t\t;\n\n\t\tfor(const entryIndex in entries ){\n\t\t\tconst\n\t\t\t\tentryKey = entries[entryIndex][0],\n\t\t\t\tentryVal = entries[entryIndex][1],\n\t\t\t\tentryValType = getType(entryVal)\n\t\t\t;\n\n\t\t\tif( ['array', 'set'].includes(entryValType) ){\n\t\t\t\tArray.from(entryVal).forEach(val => {\n\t\t\t\t\tflattenedEntries.push([entryKey, `${val}`]);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tflattenedEntries.push([entryKey, `${entryVal}`]);\n\t\t\t}\n\t\t}\n\n\t\treturn flattenedEntries;\n\t}\n\n\n\tfunction request(client, method){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['GET', 'DELETE'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tclient.config.options.method = method;\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t})\n\t\t;\n\t}\n\n\n\tfunction requestWithPayload(client, method, data=null){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['POST', 'PUT', 'PATCH'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tif( hasValue(data) ){\n\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | ${dataValidationMessage}`);\n\t\t}\n\n\t\tclient.config.options.method = method;\n\t\tclient.config.options.body = JSON.stringify(data ?? client.config.data);\n\t\tclient.header(contentTypeHeader, `${contentType}; charset=UTF-8`);\n\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t\tdelete client.config.options.body;\n\t\t\t\tclient.header(contentTypeHeader, null);\n\t\t\t})\n\t\t;\n\t}\n\n\n\treturn {\n\t\tconfig : {\n\t\t\turl : new URL('/', baseUrl),\n\t\t\toptions : isPlainObject(baseOptions) ? baseOptions : {},\n\t\t\tparams : new URLSearchParams(),\n\t\t\tdata : {},\n\t\t},\n\n\t\tpath(path){\n\t\t\tthis.config.url = new URL(path, baseUrl);\n\t\t\treturn this;\n\t\t},\n\n\t\toptions(options){\n\t\t\tif( hasValue(options) ){\n\t\t\t\tassert(isPlainObject(options), `${MODULE_NAME}:${__methodName__} | ${optionsValidationMessage}`);\n\t\t\t\tthis.config.options = merge(baseOptions, options);\n\t\t\t} else {\n\t\t\t\tthis.config.options = baseOptions;\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\theader(key, value){\n\t\t\tif( !hasValue(this.config.options.headers) ){\n\t\t\t\tthis.config.options.headers = {};\n\t\t\t}\n\t\t\tif( hasValue(value) ){\n\t\t\t\tthis.config.options.headers[`${key}`] = `${value}`;\n\t\t\t} else {\n\t\t\t\tdelete this.config.options.headers[`${key}`];\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tparams(params){\n\t\t\tif( hasValue(params) ){\n\t\t\t\tthis.config.params = new URLSearchParams(isPlainObject(params) ? flatEntries(params) : params);\n\t\t\t} else {\n\t\t\t\tthis.config.params = new URLSearchParams();\n\t\t\t}\n\t\t\tthis.config.url.search = this.config.params.toString();\n\t\t\treturn this;\n\t\t},\n\n\t\tdata(data){\n\t\t\tif( hasValue(data) ){\n\t\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | `);\n\t\t\t\tthis.config.data = data;\n\t\t\t} else {\n\t\t\t\tthis.config.data = {};\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tget(){\n\t\t\treturn request(this, 'GET');\n\t\t},\n\n\t\tpost(data=null){\n\t\t\treturn requestWithPayload(this, 'POST', data);\n\t\t},\n\n\t\tput(data=null){\n\t\t\treturn requestWithPayload(this, 'PUT', data);\n\t\t},\n\n\t\tpatch(data=null){\n\t\t\treturn requestWithPayload(this, 'PATCH', data);\n\t\t},\n\n\t\tdelete(){\n\t\t\treturn request(this, 'DELETE');\n\t\t},\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createJsRequest\n */\n\n/**\n * @typedef JsFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef JsFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a script with a src instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a script tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef JsFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {JsFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve JavaScript.\n *\n * Usually you'll want to retrieve JavaScript to include it into a page to execute the script on the page\n * currently open, so the default mode of this method is to resolve to a directly usable script tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw JavaScript source.\n *\n * Be aware that requesting JavaScript from an unsecure source is a very big security risk. Do not load and execute\n * source from a source you do not fully trust!\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline script, but\n * you may also choose to insert a sourced script tag, loading a script on insertion and executing in asynchronously\n * in turn. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * script, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/javascript\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/javascript\"\n * @returns {JsFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createJsRequest\n * @alias createJsRequest\n * @see createFetchRequest\n * @example\n * createJsRequest('/js/test.js')\n * .execute()\n * .then(jsElement => { document.body.appendChild(jsElement); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute(null, injectTarget, 'request-2')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.textContent}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'})\n * .then(rawJs => { alert(`has been injected: \"${rawJs}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.getAttribute('data-id')}\"`); })\n * ;\n */\nexport function createJsRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createJsRequest',\n\t\tcontentType = 'application/javascript'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, js='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? js : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? js : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tfInsertAndResolve(createNode('script', {src : url}));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for JavaScript, expecting \"application/javascript\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(js => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('script', null, js), js);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createCssRequest\n */\n\n/**\n * @typedef CssFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef CssFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a link with a href instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a style/link tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?String} [media='all'] - define the style's media attribute here to target the output device(s), could be \"screen\" or \"print\" for example\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef CssFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {CssFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve Cascading Stylesheets.\n *\n * Usually you'll want to retrieve CSS to include it into a page and thereby style something on the page\n * currently open, so the default mode of this method is to resolve to a directly usable style tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw CSS source.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline style, but\n * you may also choose to insert a sourced link tag, loading a stylesheet on insertion and adding the included styles\n * on load. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * link, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/css\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/css\"\n * @returns {CssFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createCssRequest\n * @alias createCssRequest\n * @see createFetchRequest\n * @example\n * createCssRequest('/css/test.css')\n * .execute()\n * .then(cssElement => { document.head.appendChild(cssElement); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute(null, injectTarget, 'request-2')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.textContent}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-3', 'screen')\n * .then(rawCss => { alert(`has been injected: \"${rawCss}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4', 'screen')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.getAttribute('data-id')+}\"`); })\n * ;\n */\nexport function createCssRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createCssRequest',\n\t\tcontentType = 'text/css'\n\t;\n\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, media='all', resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, css='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? css : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? css : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tconst linkAttrs = {href : url, rel : 'stylesheet'};\n\t\t\t\tif( media !== 'all' ){\n\t\t\t\t\tlinkAttrs.media = media;\n\t\t\t\t}\n\t\t\t\tfInsertAndResolve(createNode('link', linkAttrs));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for CSS, expecting \"text/css\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(css => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('style', (media !== 'all') ? {media} : null, css), css);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createHtmlRequest\n */\n\n/**\n * @typedef HtmlFetchResponse\n * @type {HTMLElement|Array|String}\n */\n\n/**\n * @typedef HtmlFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\" or \"raw\"\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as (a) node(s), otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node(s)\n * @param {?String} [selector=null] - if you'd like to preselect something from the result, you may define a regular query selector to find matching elements in the result\n * @param {?Boolean} [selectAll=false] - usually, if a selector is defined, we select a single element, if you need to select a list, set this to true\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef HtmlFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {HtmlFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve HTML content.\n *\n * Usually you'll want to retrieve HTML to include it into a page or extract information from it, so the default mode\n * of this method is to resolve to a node, you may insert into the DOM wherever you please or use stuff like a\n * querySelector on. However, you may also specify to retrieve the raw HTML source.\n *\n * Be aware, that requesting and parsing HTML from an unsecure source comes with a high risk. If you cannot fully\n * trust the source, request the HTML raw and use something like dom purify before using the result.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/html\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/html\"\n * @returns {HtmlFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createHtmlRequest\n * @alias createHtmlRequest\n * @see createFetchRequest\n * @example\n * createHtmlRequest('/html/test.html')\n * .execute()\n * .then(htmlElement => { document.body.appendChild(htmlElement); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute('raw', null, 'request-1')\n * .then(rawHtml => { alert(`document has been loaded: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute(null, injectTarget, 'request-3', 'body > main > h1')\n * .then(htmlElement => { alert(`has been injected: \"${htmlElement.outerHTML}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-1.html')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-4', 'h1 ~ p', true)\n * .then(rawHtml => { alert(`has been injected: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-2.html')\n * .execute('element', {element : injectTarget, position : 'prepend'}, 'request-5', 'p', true)\n * .then(htmlElements => { alert(`has been injected: \"${htmlElements.map(e => e.outerHTML).join('')}\"`); })\n * ;\n */\nexport function createHtmlRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createHtmlRequest',\n\t\tcontentType = 'text/html'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, selector=null, selectAll=false){\n\t\t\tconst\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, html='') => {\n\t\t\t\t\tif( hasValue(element) ){\n\t\t\t\t\t\tconst elements = [].concat(element);\n\n\t\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\t\tconst\n\t\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tif( ['before', 'beforebegin', 'prepend', 'afterbegin'].includes(position) ){\n\t\t\t\t\t\t\t\telements.reverse();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve((resolveTo === 'raw') ? html : element);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t.then(response => {\n\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t).split(';')[0].trim();\n\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for HTML, expecting \"text/html\"`;\n\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.text();\n\t\t\t\t})\n\t\t\t\t.then(html => {\n\t\t\t\t\tconst\n\t\t\t\t\t\tisWholeDocument = html.includes(' {\n\t\t\t\t\t\t\t\thtml += element.outerHTML;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfInsertAndResolve(element, html);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:visitUrl\n */\n\n/**\n * This function opens a given URL, using a dynamically created iframe, thereby opening the URL as if the user\n * him- or herself navigates to the URL using a browser window. Why should we do this you ask?\n *\n * For example: In session management, you'll sometimes have the case, that you need to trigger URLs on login or logout,\n * that construct or destruct parts of the session by creating of removing cookie or other client-storage items.\n * If that domain is part of a system running on another (sub)domain, using a usual client request for this will\n * not work, since the calling context of the request will have no access to the storage scope of that domain.\n *\n * So, to allow those domains to do their tasks, triggered from a different context, we can use this method to execute\n * those webhooks with the iframe, which natively runs in the called domains scope and therefore can do all necessary\n * domain-based storage actions.\n *\n * The big downside of this is, that we cannot really handle errors well this way. So if the URL returns a 404\n * or a 500, this will actually be treated as a resolved promise, since the iframe loaded. The only case a request\n * of this kind fails, is if the request runs into a timeout. So, for really critical actions, this way of handling\n * thing should be avoided in favour of an approach, that actually includes a postMessage implementation on the other\n * domain, to verify completion on load.\n *\n * @param {String} url - the URL to query, will be the current one if left empty\n * @param {?Number} [timeout=5000] - the timeout in ms to wait for completion of the request, before rejecting the promise\n * @param {?String} [tokenValue=null] - if the URL needs to include a token, you can provide this token here, which will replace the placeholder defined in \"tokenPlaceholder\"\n * @param {?String} [tokenPlaceholder='token'] = the placeholder in the url to replace with the tokenValue, must be surrounded with curly braces in the url (\"{token}\")\n * @returns {Deferred} resolves on load of URL (with the final URL as resolution value), rejects on timeout (with a \"timeout\" error)\n *\n * @memberof Requests:visitUrl\n * @alias visitUrl\n * @example\n * visitUrl('https://some.other.domain?token={token}', 2500, 'A38')\n * .then(() => { console.log('loaded!'); })\n * ;\n * visitUrl(\n * 'https://some.other.domain?token={session_value}',\n * 5000,\n * 'A38',\n * 'session_value'\n * )\n * .then(url => { console.log(`\"${url}\" loaded!`); })\n * .catch(error => { console.log(`${error.message} - URL did not load super fast, blimey!`); })\n * ;\n */\nexport function visitUrl(url, timeout=5000, tokenValue=null, tokenPlaceholder='token'){\n\turl = orDefault(url, '', 'str');\n\ttimeout = Math.abs(orDefault(timeout, 5000, 'int'));\n\ttokenValue = orDefault(tokenValue, null, 'str');\n\ttokenPlaceholder = orDefault(tokenPlaceholder, 'token', 'str');\n\turl = hasValue(tokenValue) ? url.replaceAll(`{${tokenPlaceholder}}`, tokenValue) : url;\n\n\tconst\n\t\tdeferred = new Deferred(),\n\t\touterNode = document.createElement('div')\n\t;\n\n\touterNode.innerHTML = `\n\t\t\n\t`.trim();\n\n\tconst\n\t\tiframe = outerNode.firstChild,\n\t\tfOnLoad = () => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\twindow.clearTimeout(loadTimeout);\n\t\t\t// we need to wait a bit after load before removing the iframe,\n\t\t\t// otherwise safari considers the request cancelled :(\n\t\t\twindow.setTimeout(() => {\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\tdeferred.resolve(url);\n\t\t\t}, 250);\n\t\t},\n\t\tloadTimeout = window.setTimeout(() => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\tdocument.body.removeChild(iframe);\n\t\t\tdeferred.reject(new Error('timeout'));\n\t\t}, timeout)\n\t;\n\n\tiframe.addEventListener('load', fOnLoad);\n\tdocument.body.appendChild(iframe);\n\n\treturn deferred;\n}\n"]} \ No newline at end of file +{"version":3,"file":"requests.js","names":["MODULE_NAME","warn","hasValue","orDefault","isPlainObject","assert","Deferred","getType","merge","createNode","insertNode","schedule","countermand","createFetchRequest","url","options","useNative","__methodName__","method","includes","toUpperCase","timeout","window","__ANNEX_USE_NATIVE_FETCH__","execute","res","request","XMLHttpRequest","headerKeys","Set","headerEntries","Map","response","ok","parseInt","status","statusText","responseURL","text","Promise","resolve","responseText","json","then","JSON","parse","blob","Blob","clone","headers","keys","entries","get","key","has","open","ontimeout","reject","Error","onload","getAllResponseHeaders","replace","m","value","add","set","onerror","withCredentials","credentials","i","hasOwnProperty","setRequestHeader","send","body","timeoutTimer","abortController","AbortController","signal","fetch","catch","error","abort","createJsonRequest","strict","contentType","resolveTo","insertTarget","dataId","responseContentType","split","trim","message","element","stringify","setAttribute","target","position","createRestfulJsonClient","baseUrl","baseOptions","location","origin","startsWith","implementation","contentTypeHeader","client","config","finally","requestWithPayload","data","header","URL","params","URLSearchParams","path","this","obj","Object","flattenedEntries","entryIndex","entryKey","entryVal","entryValType","Array","from","forEach","val","push","flatEntries","search","toString","post","put","patch","delete","createJsRequest","resolveSourcedOnInsert","sourceElementValue","fInsertAndResolve","js","src","createCssRequest","media","css","linkAttrs","href","rel","createHtmlRequest","selector","selectAll","html","isWholeDocument","isDocument","fragmentNode","DOMParser","parseFromString","documentElement","querySelectorAll","querySelector","children","length","item","concat","outerHTML","elements","reverse","visitUrl","tokenValue","tokenPlaceholder","Math","abs","replaceAll","deferred","outerNode","document","createElement","innerHTML","iframe","firstChild","fOnLoad","removeEventListener","clearTimeout","loadTimeout","setTimeout","removeChild","addEventListener","appendChild"],"sources":["requests.js"],"mappings":"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","sourcesContent":["/*!\n * Module Requests\n */\n\n/**\n * @namespace Requests\n */\n\nconst MODULE_NAME = 'Requests';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {warn} from './logging.js';\nimport {hasValue, orDefault, isPlainObject, assert, Deferred, getType} from './basic.js';\nimport {merge} from './objects.js';\nimport {createNode, insertNode} from './elements.js';\nimport {schedule, countermand} from './timers.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Requests:createFetchRequest\n */\n\n/**\n * @typedef FetchResponse\n * @type {Object}\n * @property {Boolean} ok - returns true if the request received a status in the OK range (200-299)\n * @property {Number} status - contains the status code of the response, e.g. 404 for a not found resource, 200 for a success\n * @property {String} statusText - a message related to the status attribute, e.g. OK for a status 200\n * @property {Function} clone - will return another object with the same shape and content as response\n * @property {Function} text - will return the response content as plain text\n * @property {Function} json - will return the response content as JSON\n * @property {Function} blob - will return the response content as a (binary) blob\n * @property {Object} headers - we do not implement a full spec-compliant Headers class, but emulate some of the functionality\n * @property {Function} headers.keys - returns an Iterable containing the key for every header in the response, transform to array with Array.from\n * @property {Function} headers.entries - returns an Iterable containing the [key, value] pairs for every header in the response, transform to array with Array.from\n * @property {Function} headers.get - returns the value associated with the given key\n * @property {Function} headers.has - returns a boolean asserting the existence of a value for the given key among the response headers\n */\n\n/**\n * @typedef FetchRequestExecuteFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef FetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {FetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a ponyfilled fetch request based on \"unfetch\", but basically fulfilling the signature of\n * a native fetch request.\n *\n * The reasoning for this is to provide a baseline fetch implementation for all requests of annex, as long as we\n * still support non ES6 browsers or old implementations in any way. During transpilation with core js, fetch does\n * not automatically get polyfilled, so we need to do this ourselves and to actually stay testable, we provide the\n * polyfill as long as we might target legacy contexts. As soon as we drop legacy contexts, we can immediately also\n * remove this method and its uses.\n *\n * The function signature is the same as \"unfetch\"'s and all non-implemented features are absent here as well.\n *\n * All usual responses (40X and 50X as well) resolve, only uncompletable requests, such as those being prevented by a\n * general network error, reject with the provided error.\n *\n * Set __ANNEX_USE_NATIVE_FETCH__ on window (true/false/'auto') to force useNative setting for all annex requests\n * globally.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options\n * @param {?String} [options.method='GET'] - indicates the request method to be performed on the target resource (one of \"GET\", \"POST\", \"PUT\", \"PATCH\", \"HEAD\", \"OPTIONS\" or \"DELETE\")\n * @param {?Object} [options.headers] - an object containing additional information to be sent with the request (e.g. {\"Content-Type\": \"application/json\"} to indicate a JSON-typed request body)\n * @param {?String} [options.credentials] - accepts an \"include\" string, which will allow both CORS and same origin requests to work with cookies; the method won't send or receive cookies otherwise; the \"same-origin\" value is not supported\n * @param {?Object|String} [options.body] - the content to be transmitted in request's body; common content types include FormData, JSON, Blob, ArrayBuffer or plain text\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @returns {FetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createFetchRequest\n * @alias createFetchRequest\n * @see https://github.com/developit/unfetch\n * @see https://github.com/developit/unfetch#fetchurl-string-options-object\n * @example\n * createFetchRequest('/foo').execute()\n * .then(r => r.text())\n * .then(txt => console.log(txt))\n * ;\n * createFetchRequest(\n * '/bear',\n * {\n * method : 'POST',\n * headers : {'Content-Type' : 'application/json'},\n * body : JSON.stringify({hungry : true})\n * })\n * .execute()\n * .then(r => { open(r.headers.get('location')); return r.json(); })\n * ;\n */\nexport function createFetchRequest(url, options=null, useNative=false){\n\tconst __methodName__ = 'createFetchRequest';\n\n\tassert(hasValue(url), `${MODULE_NAME}:${__methodName__} | no url given`);\n\toptions = orDefault(options, {});\n\tassert(isPlainObject(options), `${MODULE_NAME}:${__methodName__} | options must be plain object`);\n\n\toptions.method = orDefault(options.method, 'GET', 'str');\n\toptions.method = ['GET', 'POST', 'PUT', 'PATCH', 'HEAD', 'OPTIONS', 'DELETE'].includes(options.method.toUpperCase())\n\t\t? options.method.toUpperCase()\n\t\t: 'GET'\n\t;\n\n\t// 0 would be unlimited/unset\n\toptions.timeout = orDefault(options.timeout, 10000, 'int');\n\toptions.timeout = (options.timeout < 0) ? 0 : options.timeout;\n\n\tuseNative = window.__ANNEX_USE_NATIVE_FETCH__ ?? useNative;\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute : !useNative || ((useNative === 'auto') && !('fetch' in window))\n\t\t\t? function(){\n\t\t\t\tconst\n\t\t\t\t\tres = new Deferred(),\n\t\t\t\t\trequest = new XMLHttpRequest(),\n\t\t\t\t\theaderKeys = new Set(),\n\t\t\t\t\theaderEntries = new Map(),\n\t\t\t\t\tresponse = () => ({\n\t\t\t\t\t\tok : (parseInt(request.status, 10) >= 200) && (parseInt(request.status, 10) <= 299),\n\t\t\t\t\t\tstatusText : request.statusText,\n\t\t\t\t\t\tstatus : request.status,\n\t\t\t\t\t\turl : request.responseURL,\n\t\t\t\t\t\ttext : () => Promise.resolve(request.responseText),\n\t\t\t\t\t\tjson : () => Promise.resolve(request.responseText).then(JSON.parse),\n\t\t\t\t\t\tblob : () => Promise.resolve(new Blob([request.response])),\n\t\t\t\t\t\tclone : response,\n\t\t\t\t\t\theaders : {\n\t\t\t\t\t\t\tkeys(){\n\t\t\t\t\t\t\t\treturn headerKeys;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tentries(){\n\t\t\t\t\t\t\t\treturn headerEntries;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tget(key){\n\t\t\t\t\t\t\t\treturn headerEntries.get(key);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\thas(key){\n\t\t\t\t\t\t\t\treturn headerKeys.has(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t;\n\n\t\t\t\trequest.open(options.method, url, true);\n\n\t\t\t\tif( options.timeout > 0 ){\n\t\t\t\t\trequest.timeout = options.timeout;\n\t\t\t\t\trequest.ontimeout = () => { res.reject(new Error('timeout')); };\n\t\t\t\t}\n\n\t\t\t\trequest.onload = () => {\n\t\t\t\t\trequest.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm, (m, key, value) => {\n\t\t\t\t\t\tkey = `${key}`;\n\t\t\t\t\t\theaderKeys.add(key);\n\t\t\t\t\t\tif( headerEntries.has(key) ){\n\t\t\t\t\t\t\theaderEntries.set(key, `${headerEntries.get(key)},${value}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\theaderEntries.set(key, `${value}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tres.resolve(response());\n\t\t\t\t};\n\n\t\t\t\trequest.onerror = res.reject;\n\n\t\t\t\trequest.withCredentials = (options.credentials === 'include');\n\n\t\t\t\tif( hasValue(options.headers) ){\n\t\t\t\t\tfor( let i in options.headers ){\n\t\t\t\t\t\tif( options.headers.hasOwnProperty(i) ){\n\t\t\t\t\t\t\trequest.setRequestHeader(i, options.headers[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trequest.send(options.body ?? null);\n\n\t\t\t\treturn res;\n\t\t\t}\n\t\t\t: function(){\n\t\t\t\tconst\n\t\t\t\t\tres = new Deferred(),\n\t\t\t\t\ttimeout = options.timeout\n\t\t\t\t;\n\n\t\t\t\tlet timeoutTimer, abortController;\n\n\t\t\t\tif( (timeout > 0) && ('AbortController' in window) ){\n\t\t\t\t\tabortController = new AbortController();\n\t\t\t\t\toptions.signal = abortController.signal;\n\t\t\t\t}\n\n\t\t\t\twindow.fetch(url, options)\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tcountermand(timeoutTimer);\n\t\t\t\t\t\tres.resolve(response);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tcountermand(timeoutTimer);\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\n\t\t\t\tif( (timeout > 0) && ('AbortController' in window) ){\n\t\t\t\t\ttimeoutTimer = schedule(timeout, () => { abortController.abort(); });\n\t\t\t\t}\n\n\t\t\t\treturn res;\n\t\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createJsonRequest\n */\n\n/**\n * @typedef JsonFetchResponse\n * @type {Object|HTMLElement|String}\n */\n\n/**\n * @typedef JsonFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='object'] - defines what the response should resolve to, may either be \"object\", \"element\" or \"raw\"\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a script tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef JsonFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {JsonFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve JSON data.\n *\n * Usually you'll want to retrieve JSON as a PlainObject, so that's the default resolve value here.\n * However, you may also specify to retrieve the raw JSON or let the method handle the creation of a DOM element\n * for you and return that, ready to be used/inserted however you like.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. BTW: Inserting does not automatically change the resolve value, those are separate\n * concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/json\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/json\"\n * @returns {JsonFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createJsonRequest\n * @alias createJsonRequest\n * @see createFetchRequest\n * @example\n * createJsonRequest('message.json').execute()\n * .then(json => { alert(json.someProperty); })\n * ;\n * createJsonRequest('/dev/config.json')\n * .execute('element', null, 'config-json-id')\n * .then(jsonElement => { document.querySelector('main').appendChild(jsonElement); })\n * ;\n * createJsonRequest('https://foobar.com/config.json')\n * .execute('raw', {element : document.body, position : 'prepend'}, 'config-json-id')\n * .then(rawJson => { console.log(`\"${rawJson}\" has been inserted at the beginning of the document's body`); })\n * ;\n */\nexport function createJsonRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createJsonRequest',\n\t\tcontentType = 'application/json'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='object', insertTarget=null, dataId=null){\n\t\t\tconst res = new Deferred();\n\n\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t.then(response => {\n\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for JSON, expecting \"application/json\"`;\n\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.json();\n\t\t\t\t})\n\t\t\t\t.then(json => {\n\t\t\t\t\tconst element = createNode(``);\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve(\n\t\t\t\t\t\t(resolveTo === 'element')\n\t\t\t\t\t\t\t? element\n\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t(resolveTo === 'raw')\n\t\t\t\t\t\t\t\t? JSON.stringify(json)\n\t\t\t\t\t\t\t\t: json\n\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createRestfulJsonClient\n */\n\n/**\n * @typedef RestfulJsonClientPathFunction\n * @type {Function}\n * @param {String} path - the current path to request from baseUrl\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientOptionsFunction\n * @type {Function}\n * @param {?Object} options - options plain object to merge with baseOptions to define current request options (see JsonFetchRequest for details and defaults); if nullish, will reset to baseOptions\n * @throws error if given options are not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientHeaderFunction\n * @type {Function}\n * @param {String} key - the header to set for all following requests\n * @param {?String} value - the header's value; nullish value will remove the header again\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientParamsFunction\n * @type {Function}\n * @param {?*} params - query parameters to set on the current URL, this parameter takes all regular definitions for URLSearchParams constructor, as well as flat plain objects, which may also have arrays as values; if nullish, parameters are emptied\n * @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientDataFunction\n * @type {Function}\n * @param {?Object} data - data payload to send with the next POST, PUT or PATCH request, this parameter will set a permanent payload, for one-off payloads, use the verb method's parameter; if nullish, data will be emptied\n * @throws error if given data is not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientGetFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPostFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPutFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPatchFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientDeleteFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClient\n * @type {Object}\n * @property {Object} config - the current configuration state of the client\n * @property {URL} config.url=baseUrl - the current, complete URL to query (baseUrl + path)\n * @property {Object} config.options - the current request options (see JsonFetchRequest for details and defaults)\n * @property {URLSearchParams} config.params - the current searchParams of config.url, with which to query the URL\n * @property {Object} config.data={} - the current data payload object to send with POST, PUT and PATCH (this will persist between requests, set one-off data via verb methods)\n * @property {RestfulJsonClientPathFunction} path - sets the current request path, which will be concatenated after baseUrl\n * @property {RestfulJsonClientOptionsFunction} options - sets the current request options, which will be merged with baseOptions to constitute current request options\n * @property {RestfulJsonClientHeaderFunction} header - sets a header for all subsequent requests\n * @property {RestfulJsonClientParamsFunction} params - sets query parameters to be added to the request URL\n * @property {RestfulJsonClientDataFunction} data - sets data payload for POST, PUT and PATCH requests\n * @property {RestfulJsonClientGetFunction} get - queries the current URL via GET\n * @property {RestfulJsonClientPostFunction} post - queries the current URL via POST using defined data\n * @property {RestfulJsonClientPutFunction} put - queries the current URL via PUT using defined data\n * @property {RestfulJsonClientPatchFunction} patch - queries the current URL via PATCH using defined data\n * @property {RestfulJsonClientDeleteFunction} delete - queries the current URL via DELETE\n */\n\n/**\n * This method creates a dedicated client for restful operations against an API via JSON payloads and responses.\n *\n * Internally this implementation uses createJsonRequest to actually request stuff, while the return value of this\n * method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as\n * standard methods for HTTP verbs and setup things like setting headers.\n *\n * @param {?String} [baseUrl=window.location.origin] - the base URL for all queries, based on which final request URLs will be built, adding the paths, may be absolute or relative to current origin\n * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/json\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/json\"\n * @returns {RestfulJsonClient}\n *\n * @memberof Requests:createRestfulJsonClient\n * @alias createRestfulJsonClient\n * @see createJsonRequest\n * @example\n * const client = createRestfulJsonClient('https://jsonplaceholder.typicode.com', {credentials : 'include'});\n * const postJson = await client\n * .path('/posts')\n * \t .params({\n * \t ids : [1, 2],\n * \t q : 'lorem'\n * \t })\n * \t .data({\n * \t title : 'foo',\n * \t body : 'bar',\n * \t userId : 1,\n * \t })\n * \t .post()\n * ;\n */\nexport function createRestfulJsonClient(baseUrl=null, baseOptions=null, useNative=false, strict=true){\n\tbaseUrl = orDefault(baseUrl, window.location.origin, 'str');\n\tif( !baseUrl.startsWith('//') && baseUrl.startsWith('/') ){\n\t\tbaseUrl = `${window.location.origin}${baseUrl}`;\n\t}\n\n\tconst\n\t\t__methodName__ = 'createRestfulJsonClient',\n\t\timplementation = createJsonRequest,\n\t\tcontentTypeHeader = 'Content-Type',\n\t\tcontentType = 'application/json',\n\t\tdataValidationMessage = 'data must be plain object',\n\t\toptionsValidationMessage = 'options must be plain object'\n\t;\n\n\n\tfunction flatEntries(obj){\n\t\tconst\n\t\t\tentries = Object.entries(obj),\n\t\t\tflattenedEntries = []\n\t\t;\n\n\t\tfor(const entryIndex in entries ){\n\t\t\tconst\n\t\t\t\tentryKey = entries[entryIndex][0],\n\t\t\t\tentryVal = entries[entryIndex][1],\n\t\t\t\tentryValType = getType(entryVal)\n\t\t\t;\n\n\t\t\tif( ['array', 'set'].includes(entryValType) ){\n\t\t\t\tArray.from(entryVal).forEach(val => {\n\t\t\t\t\tflattenedEntries.push([entryKey, `${val}`]);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tflattenedEntries.push([entryKey, `${entryVal}`]);\n\t\t\t}\n\t\t}\n\n\t\treturn flattenedEntries;\n\t}\n\n\n\tfunction request(client, method){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['GET', 'DELETE'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tclient.config.options.method = method;\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t})\n\t\t;\n\t}\n\n\n\tfunction requestWithPayload(client, method, data=null){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['POST', 'PUT', 'PATCH'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tif( hasValue(data) ){\n\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | ${dataValidationMessage}`);\n\t\t}\n\n\t\tclient.config.options.method = method;\n\t\tclient.config.options.body = JSON.stringify(data ?? client.config.data);\n\t\tclient.header(contentTypeHeader, `${contentType}; charset=UTF-8`);\n\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t\tdelete client.config.options.body;\n\t\t\t\tclient.header(contentTypeHeader, null);\n\t\t\t})\n\t\t;\n\t}\n\n\n\treturn {\n\t\tconfig : {\n\t\t\turl : new URL('/', baseUrl),\n\t\t\toptions : isPlainObject(baseOptions) ? baseOptions : {},\n\t\t\tparams : new URLSearchParams(),\n\t\t\tdata : {},\n\t\t},\n\n\t\tpath(path){\n\t\t\tthis.config.url = new URL(path, baseUrl);\n\t\t\treturn this;\n\t\t},\n\n\t\toptions(options){\n\t\t\tif( hasValue(options) ){\n\t\t\t\tassert(isPlainObject(options), `${MODULE_NAME}:${__methodName__} | ${optionsValidationMessage}`);\n\t\t\t\tthis.config.options = merge(baseOptions, options);\n\t\t\t} else {\n\t\t\t\tthis.config.options = baseOptions;\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\theader(key, value){\n\t\t\tif( !hasValue(this.config.options.headers) ){\n\t\t\t\tthis.config.options.headers = {};\n\t\t\t}\n\t\t\tif( hasValue(value) ){\n\t\t\t\tthis.config.options.headers[`${key}`] = `${value}`;\n\t\t\t} else {\n\t\t\t\tdelete this.config.options.headers[`${key}`];\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tparams(params){\n\t\t\tif( hasValue(params) ){\n\t\t\t\tthis.config.params = new URLSearchParams(isPlainObject(params) ? flatEntries(params) : params);\n\t\t\t} else {\n\t\t\t\tthis.config.params = new URLSearchParams();\n\t\t\t}\n\t\t\tthis.config.url.search = this.config.params.toString();\n\t\t\treturn this;\n\t\t},\n\n\t\tdata(data){\n\t\t\tif( hasValue(data) ){\n\t\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | `);\n\t\t\t\tthis.config.data = data;\n\t\t\t} else {\n\t\t\t\tthis.config.data = {};\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tget(){\n\t\t\treturn request(this, 'GET');\n\t\t},\n\n\t\tpost(data=null){\n\t\t\treturn requestWithPayload(this, 'POST', data);\n\t\t},\n\n\t\tput(data=null){\n\t\t\treturn requestWithPayload(this, 'PUT', data);\n\t\t},\n\n\t\tpatch(data=null){\n\t\t\treturn requestWithPayload(this, 'PATCH', data);\n\t\t},\n\n\t\tdelete(){\n\t\t\treturn request(this, 'DELETE');\n\t\t},\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createJsRequest\n */\n\n/**\n * @typedef JsFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef JsFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a script with a src instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a script tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef JsFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {JsFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve JavaScript.\n *\n * Usually you'll want to retrieve JavaScript to include it into a page to execute the script on the page\n * currently open, so the default mode of this method is to resolve to a directly usable script tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw JavaScript source.\n *\n * Be aware that requesting JavaScript from an unsecure source is a very big security risk. Do not load and execute\n * source from a source you do not fully trust!\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline script, but\n * you may also choose to insert a sourced script tag, loading a script on insertion and executing in asynchronously\n * in turn. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * script, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/javascript\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/javascript\"\n * @returns {JsFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createJsRequest\n * @alias createJsRequest\n * @see createFetchRequest\n * @example\n * createJsRequest('/js/test.js')\n * .execute()\n * .then(jsElement => { document.body.appendChild(jsElement); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute(null, injectTarget, 'request-2')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.textContent}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'})\n * .then(rawJs => { alert(`has been injected: \"${rawJs}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.getAttribute('data-id')}\"`); })\n * ;\n */\nexport function createJsRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createJsRequest',\n\t\tcontentType = 'application/javascript'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, js='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? js : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? js : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tfInsertAndResolve(createNode('script', {src : url}));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for JavaScript, expecting \"application/javascript\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(js => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('script', null, js), js);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createCssRequest\n */\n\n/**\n * @typedef CssFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef CssFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a link with a href instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a style/link tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?String} [media='all'] - define the style's media attribute here to target the output device(s), could be \"screen\" or \"print\" for example\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef CssFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {CssFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve Cascading Stylesheets.\n *\n * Usually you'll want to retrieve CSS to include it into a page and thereby style something on the page\n * currently open, so the default mode of this method is to resolve to a directly usable style tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw CSS source.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline style, but\n * you may also choose to insert a sourced link tag, loading a stylesheet on insertion and adding the included styles\n * on load. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * link, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/css\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/css\"\n * @returns {CssFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createCssRequest\n * @alias createCssRequest\n * @see createFetchRequest\n * @example\n * createCssRequest('/css/test.css')\n * .execute()\n * .then(cssElement => { document.head.appendChild(cssElement); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute(null, injectTarget, 'request-2')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.textContent}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-3', 'screen')\n * .then(rawCss => { alert(`has been injected: \"${rawCss}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4', 'screen')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.getAttribute('data-id')+}\"`); })\n * ;\n */\nexport function createCssRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createCssRequest',\n\t\tcontentType = 'text/css'\n\t;\n\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, media='all', resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, css='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? css : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? css : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tconst linkAttrs = {href : url, rel : 'stylesheet'};\n\t\t\t\tif( media !== 'all' ){\n\t\t\t\t\tlinkAttrs.media = media;\n\t\t\t\t}\n\t\t\t\tfInsertAndResolve(createNode('link', linkAttrs));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for CSS, expecting \"text/css\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(css => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('style', (media !== 'all') ? {media} : null, css), css);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createHtmlRequest\n */\n\n/**\n * @typedef HtmlFetchResponse\n * @type {HTMLElement|Array|String}\n */\n\n/**\n * @typedef HtmlFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\" or \"raw\"\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as (a) node(s), otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node(s)\n * @param {?String} [selector=null] - if you'd like to preselect something from the result, you may define a regular query selector to find matching elements in the result\n * @param {?Boolean} [selectAll=false] - usually, if a selector is defined, we select a single element, if you need to select a list, set this to true\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef HtmlFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {HtmlFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve HTML content.\n *\n * Usually you'll want to retrieve HTML to include it into a page or extract information from it, so the default mode\n * of this method is to resolve to a node, you may insert into the DOM wherever you please or use stuff like a\n * querySelector on. However, you may also specify to retrieve the raw HTML source.\n *\n * Be aware, that requesting and parsing HTML from an unsecure source comes with a high risk. If you cannot fully\n * trust the source, request the HTML raw and use something like dom purify before using the result.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/html\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/html\"\n * @returns {HtmlFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createHtmlRequest\n * @alias createHtmlRequest\n * @see createFetchRequest\n * @example\n * createHtmlRequest('/html/test.html')\n * .execute()\n * .then(htmlElement => { document.body.appendChild(htmlElement); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute('raw', null, 'request-1')\n * .then(rawHtml => { alert(`document has been loaded: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute(null, injectTarget, 'request-3', 'body > main > h1')\n * .then(htmlElement => { alert(`has been injected: \"${htmlElement.outerHTML}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-1.html')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-4', 'h1 ~ p', true)\n * .then(rawHtml => { alert(`has been injected: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-2.html')\n * .execute('element', {element : injectTarget, position : 'prepend'}, 'request-5', 'p', true)\n * .then(htmlElements => { alert(`has been injected: \"${htmlElements.map(e => e.outerHTML).join('')}\"`); })\n * ;\n */\nexport function createHtmlRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createHtmlRequest',\n\t\tcontentType = 'text/html'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, selector=null, selectAll=false){\n\t\t\tconst\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, html='') => {\n\t\t\t\t\tif( hasValue(element) ){\n\t\t\t\t\t\tconst elements = [].concat(element);\n\n\t\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\t\tconst\n\t\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tif( ['before', 'beforebegin', 'prepend', 'afterbegin'].includes(position) ){\n\t\t\t\t\t\t\t\telements.reverse();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve((resolveTo === 'raw') ? html : element);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t.then(response => {\n\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t).split(';')[0].trim();\n\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for HTML, expecting \"text/html\"`;\n\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.text();\n\t\t\t\t})\n\t\t\t\t.then(html => {\n\t\t\t\t\tconst\n\t\t\t\t\t\tisWholeDocument = html.includes(' {\n\t\t\t\t\t\t\t\thtml += element.outerHTML;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfInsertAndResolve(element, html);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:visitUrl\n */\n\n/**\n * This function opens a given URL, using a dynamically created iframe, thereby opening the URL as if the user\n * him- or herself navigates to the URL using a browser window. Why should we do this you ask?\n *\n * For example: In session management, you'll sometimes have the case, that you need to trigger URLs on login or logout,\n * that construct or destruct parts of the session by creating of removing cookie or other client-storage items.\n * If that domain is part of a system running on another (sub)domain, using a usual client request for this will\n * not work, since the calling context of the request will have no access to the storage scope of that domain.\n *\n * So, to allow those domains to do their tasks, triggered from a different context, we can use this method to execute\n * those webhooks with the iframe, which natively runs in the called domains scope and therefore can do all necessary\n * domain-based storage actions.\n *\n * The big downside of this is, that we cannot really handle errors well this way. So if the URL returns a 404\n * or a 500, this will actually be treated as a resolved promise, since the iframe loaded. The only case a request\n * of this kind fails, is if the request runs into a timeout. So, for really critical actions, this way of handling\n * thing should be avoided in favour of an approach, that actually includes a postMessage implementation on the other\n * domain, to verify completion on load.\n *\n * @param {String} url - the URL to query, will be the current one if left empty\n * @param {?Number} [timeout=5000] - the timeout in ms to wait for completion of the request, before rejecting the promise\n * @param {?String} [tokenValue=null] - if the URL needs to include a token, you can provide this token here, which will replace the placeholder defined in \"tokenPlaceholder\"\n * @param {?String} [tokenPlaceholder='token'] = the placeholder in the url to replace with the tokenValue, must be surrounded with curly braces in the url (\"{token}\")\n * @returns {Deferred} resolves on load of URL (with the final URL as resolution value), rejects on timeout (with a \"timeout\" error)\n *\n * @memberof Requests:visitUrl\n * @alias visitUrl\n * @example\n * visitUrl('https://some.other.domain?token={token}', 2500, 'A38')\n * .then(() => { console.log('loaded!'); })\n * ;\n * visitUrl(\n * 'https://some.other.domain?token={session_value}',\n * 5000,\n * 'A38',\n * 'session_value'\n * )\n * .then(url => { console.log(`\"${url}\" loaded!`); })\n * .catch(error => { console.log(`${error.message} - URL did not load super fast, blimey!`); })\n * ;\n */\nexport function visitUrl(url, timeout=5000, tokenValue=null, tokenPlaceholder='token'){\n\turl = orDefault(url, '', 'str');\n\ttimeout = Math.abs(orDefault(timeout, 5000, 'int'));\n\ttokenValue = orDefault(tokenValue, null, 'str');\n\ttokenPlaceholder = orDefault(tokenPlaceholder, 'token', 'str');\n\turl = hasValue(tokenValue) ? url.replaceAll(`{${tokenPlaceholder}}`, tokenValue) : url;\n\n\tconst\n\t\tdeferred = new Deferred(),\n\t\touterNode = document.createElement('div')\n\t;\n\n\touterNode.innerHTML = `\n\t\t\n\t`.trim();\n\n\tconst\n\t\tiframe = outerNode.firstChild,\n\t\tfOnLoad = () => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\twindow.clearTimeout(loadTimeout);\n\t\t\t// we need to wait a bit after load before removing the iframe,\n\t\t\t// otherwise safari considers the request cancelled :(\n\t\t\twindow.setTimeout(() => {\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\tdeferred.resolve(url);\n\t\t\t}, 250);\n\t\t},\n\t\tloadTimeout = window.setTimeout(() => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\tdocument.body.removeChild(iframe);\n\t\t\tdeferred.reject(new Error('timeout'));\n\t\t}, timeout)\n\t;\n\n\tiframe.addEventListener('load', fOnLoad);\n\tdocument.body.appendChild(iframe);\n\n\treturn deferred;\n}\n"]} \ No newline at end of file diff --git a/dist/strings.js b/dist/strings.js index c6233c7f..e94e9203 100644 --- a/dist/strings.js +++ b/dist/strings.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Strings */ -const MODULE_NAME="Strings";import{isA,orDefault,isNaN,hasValue,isPlainObject}from"./basic.js";const SLUGIFY_LATINMAP={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};export function replace(t,e,r){t=`${t}`,e=[].concat(e),r=[].concat(r);let o="";return e.forEach(((e,n)=>{o=r.length>1?void 0!==r[n]?r[n]:"":r[0],t=isA(String.prototype.replaceAll,"function")?t.replaceAll(`${e}`,`${o}`):t.split(`${e}`).join(`${o}`)})),t}export function truncate(t,e=30,r="..."){if(t=`${t}`,e=orDefault(e,30,"int"),(r=orDefault(r,"...","str")).length>e)throw new Error("Strings:truncate | suffix cannot be longer than maxLength");return t.length>e&&(t=`${t.slice(0,e-r.length)}${r}`),t}export function concat(t="",...e){return t=orDefault(t,"","str"),e.length>0&&isA(e[0],"array")?e[0].join(t):e.join(t)}export function format(t,...e){let r=0,o=!1,n=!1;const a=function(t,e){const r=t[e];return isA(r,"function")?r.call(t):r},l={int(t,e){e=orDefault(e,10,"int");const r=parseInt(t,e);return isNaN(r)?"":`${r}`},float(t,e){e=orDefault(e,null,"str");let r=null;if(hasValue(e)){let o=0;try{o=e.split(".")[1].length}catch(t){throw new Error("Strings:format | float precision arg malformed")}const n=Math.pow(10,o);r=Math.round(parseFloat(t)*n)/n}else r=parseFloat(t);return isNaN(r)?"":`${r}`}};return(t=`${t}`).replace(/([{}])\1|[{](.*?)(?:!(.+?))?[}]/g,(function(t,i,u){let c=null,s="",f=function(t){return t},A=null;if(i)return i;if(u.length){const t=u.split(":");if(t.length>1){u=t[0];const e=t[1].split("("),r=e[0];e.length>1&&(A=e[1].replace(")",""));try{f=l[r]}catch(t){throw new Error("Strings:format | unknown formatter")}}if(n)throw new Error("Strings:format | cannot switch from implicit to explicit numbering");o=!0,c=function(t,e){/^(\d+)([.]|$)/.test(e)||(e=`0.${e}`);let r=/(.+?)[.](.+)/.exec(e);for(;r;)t=a(t,r[1]),e=r[2],r=/(.+?)[.](.+)/.exec(e);return a(t,e)}(e,u),s=orDefault(c,"")}else{if(o)throw new Error("Strings:format | cannot switch from explicit to implicit numbering");n=!0,c=e[r],s=orDefault(c,""),r++}return f(s,A)}))}export function slugify(t,e=null){return isPlainObject(e)||(e={}),`${t}`.toLowerCase().replace(/\s+|_+/g,"-").replace(/[^\-]/g,(t=>e[t]??SLUGIFY_LATINMAP[t]??t)).replace(/[^\w\-]+/g,"").replace(/--+/g,"-").replace(/^-+/,"").replace(/-+$/,"")}export function maskForSelector(t){return`${t}`.replace(/([#;&,.+*~':"!^$\[\]()=>|\/@])/g,"\\$&")}export function maskForRegEx(t){return`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&")}export function maskForHtml(t){const e=document.createElement("textarea");return e.textContent=`${t}`,e.innerHTML}export function unmaskFromHtml(t){const e=document.createElement("textarea");return e.innerHTML=`${t}`,e.textContent} +const MODULE_NAME="Strings";import{isFunction,isArray,orDefault,isNaN,hasValue,isPlainObject}from"./basic.js";const SLUGIFY_LATINMAP={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};export function replace(t,e,r){t=`${t}`,e=[].concat(e),r=[].concat(r);let o="";return e.forEach(((e,n)=>{o=r.length>1?void 0!==r[n]?r[n]:"":r[0],t=isFunction(String.prototype.replaceAll)?t.replaceAll(`${e}`,`${o}`):t.split(`${e}`).join(`${o}`)})),t}export function truncate(t,e=30,r="..."){if(t=`${t}`,e=orDefault(e,30,"int"),(r=orDefault(r,"...","str")).length>e)throw new Error("Strings:truncate | suffix cannot be longer than maxLength");return t.length>e&&(t=`${t.slice(0,e-r.length)}${r}`),t}export function concat(t="",...e){return t=orDefault(t,"","str"),e.length>0&&isArray(e[0])?e[0].join(t):e.join(t)}export function format(t,...e){let r=0,o=!1,n=!1;const a=function(t,e){const r=t[e];return isFunction(r)?r.call(t):r},i={int(t,e){e=orDefault(e,10,"int");const r=parseInt(t,e);return isNaN(r)?"":`${r}`},float(t,e){e=orDefault(e,null,"str");let r=null;if(hasValue(e)){let o=0;try{o=e.split(".")[1].length}catch(t){throw new Error("Strings:format | float precision arg malformed")}const n=Math.pow(10,o);r=Math.round(parseFloat(t)*n)/n}else r=parseFloat(t);return isNaN(r)?"":`${r}`}};return(t=`${t}`).replace(/([{}])\1|[{](.*?)(?:!(.+?))?[}]/g,(function(t,l,u){let c=null,s="",f=function(t){return t},O=null;if(l)return l;if(u.length){const t=u.split(":");if(t.length>1){u=t[0];const e=t[1].split("("),r=e[0];e.length>1&&(O=e[1].replace(")",""));try{f=i[r]}catch(t){throw new Error("Strings:format | unknown formatter")}}if(n)throw new Error("Strings:format | cannot switch from implicit to explicit numbering");o=!0,c=function(t,e){/^(\d+)([.]|$)/.test(e)||(e=`0.${e}`);let r=/(.+?)[.](.+)/.exec(e);for(;r;)t=a(t,r[1]),e=r[2],r=/(.+?)[.](.+)/.exec(e);return a(t,e)}(e,u),s=orDefault(c,"")}else{if(o)throw new Error("Strings:format | cannot switch from explicit to implicit numbering");n=!0,c=e[r],s=orDefault(c,""),r++}return f(s,O)}))}export function slugify(t,e=null){return isPlainObject(e)||(e={}),`${t}`.toLowerCase().replace(/\s+|_+/g,"-").replace(/[^\-]/g,(t=>e[t]??SLUGIFY_LATINMAP[t]??t)).replace(/[^\w\-]+/g,"").replace(/--+/g,"-").replace(/^-+/,"").replace(/-+$/,"")}export function maskForSelector(t){return`${t}`.replace(/([#;&,.+*~':"!^$\[\]()=>|\/@])/g,"\\$&")}export function maskForRegEx(t){return`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&")}export function maskForHtml(t){const e=document.createElement("textarea");return e.textContent=`${t}`,e.innerHTML}export function unmaskFromHtml(t){const e=document.createElement("textarea");return e.innerHTML=`${t}`,e.textContent} //# sourceMappingURL=strings.js.map diff --git a/dist/strings.js.map b/dist/strings.js.map index ac5a8523..a2b46593 100644 --- a/dist/strings.js.map +++ b/dist/strings.js.map @@ -1 +1 @@ -{"version":3,"file":"strings.js","names":["MODULE_NAME","isA","orDefault","isNaN","hasValue","isPlainObject","SLUGIFY_LATINMAP","replace","subject","search","concat","tmp","forEach","searchTerm","index","length","undefined","String","prototype","replaceAll","split","join","truncate","maxLength","suffix","Error","slice","glue","strings","format","template","replacements","idx","explicit","implicit","fResolve","object","key","value","call","formatters","int","radix","res","parseInt","float","precision","ex","power","Math","pow","round","parseFloat","match","literal","ref","formatter","formatterArg","keyParts","formatterParts","formatterName","test","exec","fLookup","slugify","text","additionalMap","toLowerCase","char","maskForSelector","str","maskForRegEx","maskForHtml","escape","document","createElement","textContent","innerHTML","unmaskFromHtml","html"],"sources":["strings.js"],"mappings":";;;AAQA,MAAMA,YAAc,iBAMZC,IAAKC,UAAWC,MAAOC,SAAUC,kBAAoB,aAM7D,MAAMC,iBAAmB,CACxB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IACrG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAC5G,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAC3G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,YA8B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","sourcesContent":["/*!\n * Module Strings\n */\n\n/**\n * @namespace Strings\n */\n\nconst MODULE_NAME = 'Strings';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {isA, orDefault, isNaN, hasValue, isPlainObject} from './basic.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst SLUGIFY_LATINMAP = {\n\t'Á':'A','Ă':'A','Ắ':'A','Ặ':'A','Ằ':'A','Ẳ':'A','Ẵ':'A','Ǎ':'A','Â':'A','Ấ':'A','Ậ':'A','Ầ':'A','Ẩ':'A','Ẫ':'A',\n\t'Ä':'A','Ǟ':'A','Ȧ':'A','Ǡ':'A','Ạ':'A','Ȁ':'A','À':'A','Ả':'A','Ȃ':'A','Ā':'A','Ą':'A','Å':'A','Ǻ':'A','Ḁ':'A',\n\t'Ⱥ':'A','Ã':'A','Ꜳ':'AA','Æ':'AE','Ǽ':'AE','Ǣ':'AE','Ꜵ':'AO','Ꜷ':'AU','Ꜹ':'AV','Ꜻ':'AV','Ꜽ':'AY','Ḃ':'B',\n\t'Ḅ':'B','Ɓ':'B','Ḇ':'B','Ƀ':'B','Ƃ':'B','Ć':'C','Č':'C','Ç':'C','Ḉ':'C','Ĉ':'C','Ċ':'C','Ƈ':'C','Ȼ':'C','Ď':'D',\n\t'Ḑ':'D','Ḓ':'D','Ḋ':'D','Ḍ':'D','Ɗ':'D','Ḏ':'D','Dz':'D','Dž':'D','Đ':'D','Ƌ':'D','DZ':'DZ','DŽ':'DZ','É':'E','Ĕ':'E',\n\t'Ě':'E','Ȩ':'E','Ḝ':'E','Ê':'E','Ế':'E','Ệ':'E','Ề':'E','Ể':'E','Ễ':'E','Ḙ':'E','Ë':'E','Ė':'E','Ẹ':'E','Ȅ':'E',\n\t'È':'E','Ẻ':'E','Ȇ':'E','Ē':'E','Ḗ':'E','Ḕ':'E','Ę':'E','Ɇ':'E','Ẽ':'E','Ḛ':'E','Ꝫ':'ET','Ḟ':'F','Ƒ':'F','Ǵ':'G',\n\t'Ğ':'G','Ǧ':'G','Ģ':'G','Ĝ':'G','Ġ':'G','Ɠ':'G','Ḡ':'G','Ǥ':'G','Ḫ':'H','Ȟ':'H','Ḩ':'H','Ĥ':'H','Ⱨ':'H','Ḧ':'H',\n\t'Ḣ':'H','Ḥ':'H','Ħ':'H','Í':'I','Ĭ':'I','Ǐ':'I','Î':'I','Ï':'I','Ḯ':'I','İ':'I','Ị':'I','Ȉ':'I','Ì':'I','Ỉ':'I',\n\t'Ȋ':'I','Ī':'I','Į':'I','Ɨ':'I','Ĩ':'I','Ḭ':'I','Ꝺ':'D','Ꝼ':'F','Ᵹ':'G','Ꞃ':'R','Ꞅ':'S','Ꞇ':'T','Ꝭ':'IS','Ĵ':'J',\n\t'Ɉ':'J','Ḱ':'K','Ǩ':'K','Ķ':'K','Ⱪ':'K','Ꝃ':'K','Ḳ':'K','Ƙ':'K','Ḵ':'K','Ꝁ':'K','Ꝅ':'K','Ĺ':'L','Ƚ':'L','Ľ':'L',\n\t'Ļ':'L','Ḽ':'L','Ḷ':'L','Ḹ':'L','Ⱡ':'L','Ꝉ':'L','Ḻ':'L','Ŀ':'L','Ɫ':'L','Lj':'L','Ł':'L','LJ':'LJ','Ḿ':'M','Ṁ':'M',\n\t'Ṃ':'M','Ɱ':'M','Ń':'N','Ň':'N','Ņ':'N','Ṋ':'N','Ṅ':'N','Ṇ':'N','Ǹ':'N','Ɲ':'N','Ṉ':'N','Ƞ':'N','Nj':'N','Ñ':'N',\n\t'NJ':'NJ','Ó':'O','Ŏ':'O','Ǒ':'O','Ô':'O','Ố':'O','Ộ':'O','Ồ':'O','Ổ':'O','Ỗ':'O','Ö':'O','Ȫ':'O','Ȯ':'O','Ȱ':'O',\n\t'Ọ':'O','Ő':'O','Ȍ':'O','Ò':'O','Ỏ':'O','Ơ':'O','Ớ':'O','Ợ':'O','Ờ':'O','Ở':'O','Ỡ':'O','Ȏ':'O','Ꝋ':'O','Ꝍ':'O',\n\t'Ō':'O','Ṓ':'O','Ṑ':'O','Ɵ':'O','Ǫ':'O','Ǭ':'O','Ø':'O','Ǿ':'O','Õ':'O','Ṍ':'O','Ṏ':'O','Ȭ':'O','Ƣ':'OI','Ꝏ':'OO',\n\t'Ɛ':'E','Ɔ':'O','Ȣ':'OU','Ṕ':'P','Ṗ':'P','Ꝓ':'P','Ƥ':'P','Ꝕ':'P','Ᵽ':'P','Ꝑ':'P','Ꝙ':'Q','Ꝗ':'Q','Ŕ':'R','Ř':'R',\n\t'Ŗ':'R','Ṙ':'R','Ṛ':'R','Ṝ':'R','Ȑ':'R','Ȓ':'R','Ṟ':'R','Ɍ':'R','Ɽ':'R','Ꜿ':'C','Ǝ':'E','Ś':'S','Ṥ':'S','Š':'S',\n\t'Ṧ':'S','Ş':'S','Ŝ':'S','Ș':'S','Ṡ':'S','Ṣ':'S','Ṩ':'S','ẞ':'SS','Ť':'T','Ţ':'T','Ṱ':'T','Ț':'T','Ⱦ':'T','Ṫ':'T',\n\t'Ṭ':'T','Ƭ':'T','Ṯ':'T','Ʈ':'T','Ŧ':'T','Ɐ':'A','Ꞁ':'L','Ɯ':'M','Ʌ':'V','Ꜩ':'TZ','Ú':'U','Ŭ':'U','Ǔ':'U','Û':'U',\n\t'Ṷ':'U','Ü':'U','Ǘ':'U','Ǚ':'U','Ǜ':'U','Ǖ':'U','Ṳ':'U','Ụ':'U','Ű':'U','Ȕ':'U','Ù':'U','Ủ':'U','Ư':'U','Ứ':'U',\n\t'Ự':'U','Ừ':'U','Ử':'U','Ữ':'U','Ȗ':'U','Ū':'U','Ṻ':'U','Ų':'U','Ů':'U','Ũ':'U','Ṹ':'U','Ṵ':'U','Ꝟ':'V','Ṿ':'V',\n\t'Ʋ':'V','Ṽ':'V','Ꝡ':'VY','Ẃ':'W','Ŵ':'W','Ẅ':'W','Ẇ':'W','Ẉ':'W','Ẁ':'W','Ⱳ':'W','Ẍ':'X','Ẋ':'X','Ý':'Y','Ŷ':'Y',\n\t'Ÿ':'Y','Ẏ':'Y','Ỵ':'Y','Ỳ':'Y','Ƴ':'Y','Ỷ':'Y','Ỿ':'Y','Ȳ':'Y','Ɏ':'Y','Ỹ':'Y','Ź':'Z','Ž':'Z','Ẑ':'Z','Ⱬ':'Z',\n\t'Ż':'Z','Ẓ':'Z','Ȥ':'Z','Ẕ':'Z','Ƶ':'Z','IJ':'IJ','Œ':'OE','ᴀ':'A','ᴁ':'AE','ʙ':'B','ᴃ':'B','ᴄ':'C','ᴅ':'D','ᴇ':'E',\n\t'ꜰ':'F','ɢ':'G','ʛ':'G','ʜ':'H','ɪ':'I','ʁ':'R','ᴊ':'J','ᴋ':'K','ʟ':'L','ᴌ':'L','ᴍ':'M','ɴ':'N','ᴏ':'O','ɶ':'OE',\n\t'ᴐ':'O','ᴕ':'OU','ᴘ':'P','ʀ':'R','ᴎ':'N','ᴙ':'R','ꜱ':'S','ᴛ':'T','ⱻ':'E','ᴚ':'R','ᴜ':'U','ᴠ':'V','ᴡ':'W','ʏ':'Y',\n\t'ᴢ':'Z','á':'a','ă':'a','ắ':'a','ặ':'a','ằ':'a','ẳ':'a','ẵ':'a','ǎ':'a','â':'a','ấ':'a','ậ':'a','ầ':'a','ẩ':'a',\n\t'ẫ':'a','ä':'a','ǟ':'a','ȧ':'a','ǡ':'a','ạ':'a','ȁ':'a','à':'a','ả':'a','ȃ':'a','ā':'a','ą':'a','ᶏ':'a','ẚ':'a',\n\t'å':'a','ǻ':'a','ḁ':'a','ⱥ':'a','ã':'a','ꜳ':'aa','æ':'ae','ǽ':'ae','ǣ':'ae','ꜵ':'ao','ꜷ':'au','ꜹ':'av','ꜻ':'av',\n\t'ꜽ':'ay','ḃ':'b','ḅ':'b','ɓ':'b','ḇ':'b','ᵬ':'b','ᶀ':'b','ƀ':'b','ƃ':'b','ɵ':'o','ć':'c','č':'c','ç':'c','ḉ':'c',\n\t'ĉ':'c','ɕ':'c','ċ':'c','ƈ':'c','ȼ':'c','ď':'d','ḑ':'d','ḓ':'d','ȡ':'d','ḋ':'d','ḍ':'d','ɗ':'d','ᶑ':'d','ḏ':'d',\n\t'ᵭ':'d','ᶁ':'d','đ':'d','ɖ':'d','ƌ':'d','ı':'i','ȷ':'j','ɟ':'j','ʄ':'j','dz':'dz','dž':'dz','é':'e','ĕ':'e','ě':'e',\n\t'ȩ':'e','ḝ':'e','ê':'e','ế':'e','ệ':'e','ề':'e','ể':'e','ễ':'e','ḙ':'e','ë':'e','ė':'e','ẹ':'e','ȅ':'e','è':'e',\n\t'ẻ':'e','ȇ':'e','ē':'e','ḗ':'e','ḕ':'e','ⱸ':'e','ę':'e','ᶒ':'e','ɇ':'e','ẽ':'e','ḛ':'e','ꝫ':'et','ḟ':'f','ƒ':'f',\n\t'ᵮ':'f','ᶂ':'f','ǵ':'g','ğ':'g','ǧ':'g','ģ':'g','ĝ':'g','ġ':'g','ɠ':'g','ḡ':'g','ᶃ':'g','ǥ':'g','ḫ':'h','ȟ':'h',\n\t'ḩ':'h','ĥ':'h','ⱨ':'h','ḧ':'h','ḣ':'h','ḥ':'h','ɦ':'h','ẖ':'h','ħ':'h','ƕ':'hv','í':'i','ĭ':'i','ǐ':'i','î':'i',\n\t'ï':'i','ḯ':'i','ị':'i','ȉ':'i','ì':'i','ỉ':'i','ȋ':'i','ī':'i','į':'i','ᶖ':'i','ɨ':'i','ĩ':'i','ḭ':'i','ꝺ':'d',\n\t'ꝼ':'f','ᵹ':'g','ꞃ':'r','ꞅ':'s','ꞇ':'t','ꝭ':'is','ǰ':'j','ĵ':'j','ʝ':'j','ɉ':'j','ḱ':'k','ǩ':'k','ķ':'k','ⱪ':'k',\n\t'ꝃ':'k','ḳ':'k','ƙ':'k','ḵ':'k','ᶄ':'k','ꝁ':'k','ꝅ':'k','ĺ':'l','ƚ':'l','ɬ':'l','ľ':'l','ļ':'l','ḽ':'l','ȴ':'l',\n\t'ḷ':'l','ḹ':'l','ⱡ':'l','ꝉ':'l','ḻ':'l','ŀ':'l','ɫ':'l','ᶅ':'l','ɭ':'l','ł':'l','lj':'lj','ſ':'s','ẜ':'s','ẛ':'s',\n\t'ẝ':'s','ḿ':'m','ṁ':'m','ṃ':'m','ɱ':'m','ᵯ':'m','ᶆ':'m','ń':'n','ň':'n','ņ':'n','ṋ':'n','ȵ':'n','ṅ':'n','ṇ':'n',\n\t'ǹ':'n','ɲ':'n','ṉ':'n','ƞ':'n','ᵰ':'n','ᶇ':'n','ɳ':'n','ñ':'n','nj':'nj','ó':'o','ŏ':'o','ǒ':'o','ô':'o','ố':'o',\n\t'ộ':'o','ồ':'o','ổ':'o','ỗ':'o','ö':'o','ȫ':'o','ȯ':'o','ȱ':'o','ọ':'o','ő':'o','ȍ':'o','ò':'o','ỏ':'o','ơ':'o',\n\t'ớ':'o','ợ':'o','ờ':'o','ở':'o','ỡ':'o','ȏ':'o','ꝋ':'o','ꝍ':'o','ⱺ':'o','ō':'o','ṓ':'o','ṑ':'o','ǫ':'o','ǭ':'o',\n\t'ø':'o','ǿ':'o','õ':'o','ṍ':'o','ṏ':'o','ȭ':'o','ƣ':'oi','ꝏ':'oo','ɛ':'e','ᶓ':'e','ɔ':'o','ᶗ':'o','ȣ':'ou','ṕ':'p',\n\t'ṗ':'p','ꝓ':'p','ƥ':'p','ᵱ':'p','ᶈ':'p','ꝕ':'p','ᵽ':'p','ꝑ':'p','ꝙ':'q','ʠ':'q','ɋ':'q','ꝗ':'q','ŕ':'r','ř':'r',\n\t'ŗ':'r','ṙ':'r','ṛ':'r','ṝ':'r','ȑ':'r','ɾ':'r','ᵳ':'r','ȓ':'r','ṟ':'r','ɼ':'r','ᵲ':'r','ᶉ':'r','ɍ':'r','ɽ':'r',\n\t'ↄ':'c','ꜿ':'c','ɘ':'e','ɿ':'r','ś':'s','ṥ':'s','š':'s','ṧ':'s','ş':'s','ŝ':'s','ș':'s','ṡ':'s','ṣ':'s','ṩ':'s',\n\t'ʂ':'s','ᵴ':'s','ᶊ':'s','ȿ':'s','ɡ':'g','ß':'ss','ᴑ':'o','ᴓ':'o','ᴝ':'u','ť':'t','ţ':'t','ṱ':'t','ț':'t','ȶ':'t',\n\t'ẗ':'t','ⱦ':'t','ṫ':'t','ṭ':'t','ƭ':'t','ṯ':'t','ᵵ':'t','ƫ':'t','ʈ':'t','ŧ':'t','ᵺ':'th','ɐ':'a','ᴂ':'ae','ǝ':'e',\n\t'ᵷ':'g','ɥ':'h','ʮ':'h','ʯ':'h','ᴉ':'i','ʞ':'k','ꞁ':'l','ɯ':'m','ɰ':'m','ᴔ':'oe','ɹ':'r','ɻ':'r','ɺ':'r','ⱹ':'r',\n\t'ʇ':'t','ʌ':'v','ʍ':'w','ʎ':'y','ꜩ':'tz','ú':'u','ŭ':'u','ǔ':'u','û':'u','ṷ':'u','ü':'u','ǘ':'u','ǚ':'u','ǜ':'u',\n\t'ǖ':'u','ṳ':'u','ụ':'u','ű':'u','ȕ':'u','ù':'u','ủ':'u','ư':'u','ứ':'u','ự':'u','ừ':'u','ử':'u','ữ':'u','ȗ':'u',\n\t'ū':'u','ṻ':'u','ų':'u','ᶙ':'u','ů':'u','ũ':'u','ṹ':'u','ṵ':'u','ᵫ':'ue','ꝸ':'um','ⱴ':'v','ꝟ':'v','ṿ':'v','ʋ':'v',\n\t'ᶌ':'v','ⱱ':'v','ṽ':'v','ꝡ':'vy','ẃ':'w','ŵ':'w','ẅ':'w','ẇ':'w','ẉ':'w','ẁ':'w','ⱳ':'w','ẘ':'w','ẍ':'x','ẋ':'x',\n\t'ᶍ':'x','ý':'y','ŷ':'y','ÿ':'y','ẏ':'y','ỵ':'y','ỳ':'y','ƴ':'y','ỷ':'y','ỿ':'y','ȳ':'y','ẙ':'y','ɏ':'y','ỹ':'y',\n\t'ź':'z','ž':'z','ẑ':'z','ʑ':'z','ⱬ':'z','ż':'z','ẓ':'z','ȥ':'z','ẕ':'z','ᵶ':'z','ᶎ':'z','ʐ':'z','ƶ':'z','ɀ':'z',\n\t'ff':'ff','ffi':'ffi','ffl':'ffl','fi':'fi','fl':'fl','ij':'ij','œ':'oe','st':'st','ₐ':'a','ₑ':'e','ᵢ':'i','ⱼ':'j','ₒ':'o',\n\t'ᵣ':'r','ᵤ':'u','ᵥ':'v','ₓ':'x'\n};\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Strings:replace\n */\n\n/**\n * Offers similar functionality to PHP's str_replace or ES2021's replaceAll and avoids RegExps for this task.\n * Replaces occurrences of search in subject with replace. search and replace may be arrays.\n * If search is an array and replace is a string, all phrases in the array will be replaced with one string.\n * If replace is an array itself, phrases and replacements are matched by index.\n * Missing replacements are treated as an empty string (for example: if your array lengths do not match).\n *\n * Uses String.prototype.replaceAll internally, if available.\n *\n * @param {String} subject - the string to replace in\n * @param {(String|String[])} search - the string(s) to replace\n * @param {String|String[]} replace - the string(s) to replace the search string(s)\n * @returns {String} the modified string\n *\n * @memberof Strings:replace\n * @alias replace\n * @example\n * const sanitizedString = replace([':', '#', '-'], '_', exampleString);\n */\nexport function replace(subject, search, replace){\n\tsubject = `${subject}`;\n\tsearch = [].concat(search);\n\treplace = [].concat(replace);\n\n\tlet tmp = '';\n\n\tsearch.forEach((searchTerm, index) => {\n\t\ttmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0];\n\n\t\tif( isA(String.prototype.replaceAll, 'function') ){\n\t\t\tsubject = subject.replaceAll(`${searchTerm}`, `${tmp}`);\n\t\t} else {\n\t\t\tsubject = subject.split(`${searchTerm}`).join(`${tmp}`);\n\t\t}\n\t});\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:truncate\n */\n\n/**\n * Truncates a given string after a certain number of characters to enforce length restrictions.\n *\n * @param {String} subject - the string to check and truncate\n * @param {?Number} [maxLength=30] - the maximum allowed character length for the string\n * @param {?String} [suffix='...'] - the trailing string to end a truncated string with\n * @throws error if suffix length is bigger than defined maxLength\n * @returns {String} the (truncated) subject\n *\n * @memberof Strings:truncate\n * @alias truncate\n * @example\n * const truncatedString = truncate(string, 10, '...');\n */\nexport function truncate(subject, maxLength=30, suffix='...'){\n\tsubject = `${subject}`;\n\tmaxLength = orDefault(maxLength, 30, 'int');\n\tsuffix = orDefault(suffix, '...', 'str');\n\n\tif( suffix.length > maxLength ){\n\t\tthrow new Error(`${MODULE_NAME}:truncate | suffix cannot be longer than maxLength`);\n\t}\n\n\tif( subject.length > maxLength ){\n\t\tsubject = `${subject.slice(0, maxLength - suffix.length)}${suffix}`;\n\t}\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:concat\n */\n\n/**\n * Simply concatenates strings with a glue part using array.join in a handy notation.\n * You can also provide arguments to glue as a prepared array as the second parameter,\n * in that case other parameters will be ignored.\n *\n * @param {?String} [glue=''] - the separator to use between single strings\n * @param {?String[]} strings - list of strings to concatenate, either comma-separated or as single array\n * @returns {String} the concatenated string\n *\n * @memberof Strings:concat\n * @alias concat\n * @example\n * const finalCountdown = concat(' ... ', 10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!');\n * const finalCountdown = concat(' ... ', [10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!']);\n */\nexport function concat(glue='', ...strings){\n\tglue = orDefault(glue, '', 'str');\n\n\tif( (strings.length > 0) && isA(strings[0], 'array') ){\n\t\treturn strings[0].join(glue);\n\t} else {\n\t\treturn strings.join(glue);\n\t}\n}\n\n\n\n/**\n * @namespace Strings:format\n */\n\n/**\n * This is a pythonesque string format implementation.\n * Apply formatted values to a string template, in which replacements are marked with curly braces.\n *\n * Display literal curly brace with {{ and }}.\n *\n * Unknown keys/indexes will be ignored.\n *\n * This solution is adapted from:\n * https://github.com/davidchambers/string-format\n *\n * @param {String} template -\n * @param {(String[]|Object)} replacements - arguments to insert into template, either as a dictionary, an array or a parameter sequence\n * @throws general exception on syntax errors\n * @returns {String} the formatted string\n *\n * @memberof Strings:format\n * @alias format\n * @example\n * format('An elephant is {times:float(0.00)} times smarter than a {animal}', {times : 5.5555, animal : 'lion'})\n * => 'An elephant is 5.56 times smarter than a lion'\n * format('{0}{0}{0} ... {{BATMAN!}}', 'Nana')\n * => 'NanaNanaNana ... {BATMAN!}'\n * format('{} {} {} starts the alphabet.', 'A', 'B', 'C')\n * => 'A B C starts the alphabet.'\n * format('{0:int}, {1:int}, {2:int}: details are for wankers', '1a', 2.222, 3)\n * => '1, 2, 3: details are for wankers'\n */\nexport function format(template, ...replacements){\n\ttemplate = `${template}`;\n\n\tlet\n\t\tidx = 0,\n\t\texplicit = false,\n\t\timplicit = false\n\t;\n\n\tconst fResolve = function(object, key){\n\t\tconst value = object[key];\n\n\t\tif( isA(value, 'function') ){\n\t\t\treturn value.call(object);\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t};\n\n\tconst fLookup = function(object, key){\n\t\tif( !/^(\\d+)([.]|$)/.test(key) ){\n\t\t\tkey = `0.${key}`;\n\t\t}\n\n\t\tlet match = /(.+?)[.](.+)/.exec(key);\n\t\twhile( match ){\n\t\t\tobject = fResolve(object, match[1]);\n\t\t\tkey = match[2];\n\t\t\tmatch = /(.+?)[.](.+)/.exec(key);\n\t\t}\n\n\t\treturn fResolve(object, key);\n\t};\n\n\tconst formatters = {\n\t\tint(value, radix){\n\t\t\tradix = orDefault(radix, 10, 'int');\n\t\t\tconst res = parseInt(value, radix);\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t},\n\t\tfloat(value, format){\n\t\t\tformat = orDefault(format, null, 'str');\n\n\t\t\tlet res = null;\n\n\t\t\tif( hasValue(format) ){\n\t\t\t\tlet precision = 0;\n\n\t\t\t\ttry {\n\t\t\t\t\tprecision = format.split('.')[1].length;\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | float precision arg malformed`);\n\t\t\t\t}\n\n\t\t\t\tconst power = Math.pow(10, precision);\n\n\t\t\t\tres = Math.round(parseFloat(value) * power) / power;\n\t\t\t} else {\n\t\t\t\tres = parseFloat(value);\n\t\t\t}\n\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t}\n\t};\n\n\treturn template.replace(/([{}])\\1|[{](.*?)(?:!(.+?))?[}]/g, function(match, literal, key){\n\t\tlet\n\t\t\tref = null,\n\t\t\tvalue = '',\n\t\t\tformatter = function(value){ return value; },\n\t\t\tformatterArg = null\n\t\t;\n\n\t\tif( literal ){\n\t\t\treturn literal;\n\t\t}\n\n\t\tif( key.length ){\n\t\t\tconst keyParts = key.split(':');\n\n\t\t\tif( keyParts.length > 1 ){\n\t\t\t\tkey = keyParts[0];\n\n\t\t\t\tconst\n\t\t\t\t\tformatterParts = keyParts[1].split('('),\n\t\t\t\t\tformatterName = formatterParts[0]\n\t\t\t\t;\n\n\t\t\t\tif( formatterParts.length > 1 ){\n\t\t\t\t\tformatterArg = formatterParts[1].replace(')', '');\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tformatter = formatters[formatterName];\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | unknown formatter`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( implicit ){\n\t\t\t\tthrow new Error(`${MODULE_NAME}:format | cannot switch from implicit to explicit numbering`);\n\t\t\t} else {\n\t\t\t\texplicit = true;\n\t\t\t}\n\n\t\t\tref = fLookup(replacements, key);\n\t\t\tvalue = orDefault(ref, '');\n\t\t} else {\n\t\t\tif( explicit ){\n\t\t\t\tthrow new Error (`${MODULE_NAME}:format | cannot switch from explicit to implicit numbering`);\n\t\t\t} else {\n\t\t\t\timplicit = true;\n\t\t\t}\n\n\t\t\tref = replacements[idx];\n\t\t\tvalue = orDefault(ref, '');\n\t\t\tidx++;\n\t\t}\n\n\t\treturn formatter(value, formatterArg);\n\t});\n}\n\n\n\n/**\n * @namespace Strings:slugify\n */\n\n/**\n * Slugifies a text for use in a URL or id/class/attribute.\n * Transforms accented characters to non-accented ones.\n * Throws out everything except basic A-Z characters and numbers after replacements have taken place.\n * Provide own replacements, supplementing or overriding the default replacement map to cover special cases\n * (will take precedence over the default map).\n *\n * @param {String} text - the text to slugify\n * @param {String?} [additionalMap=null] - optional character map to supplement/override the default map, having the form {'[search character]' : '[replacement]', ...}\n * @returns {String} the slugified string\n *\n * @memberof Strings:slugify\n * @alias slugify\n * @example\n * slugify('This is a cömplicated ßtring for URLs!')\n * => 'this-is-a-complicated-sstring-for-urls'\n */\nexport function slugify(text, additionalMap=null){\n\tif( !isPlainObject(additionalMap) ){\n\t\tadditionalMap = {};\n\t}\n\n\treturn `${text}`.toLowerCase()\n\t\t.replace(/\\s+|_+/g, '-') // replace spaces and underscores with \"-\"\n\t\t.replace(\n\t\t\t/[^\\-]/g, // replace accented chars with plain ones via map and/or apply additionalMap\n\t\t\tchar => additionalMap[char] ?? SLUGIFY_LATINMAP[char] ?? char\n\t\t)\n\t\t.replace(/[^\\w\\-]+/g, '') // remove all non-word, non-dash chars\n\t\t.replace(/--+/g, '-') // replace multiple \"-\" with single \"-\"\n\t\t.replace(/^-+/, '') // trim \"-\" from start of text\n\t\t.replace(/-+$/, '') // trim \"-\" from end of text\n\t;\n}\n\n\n\n/**\n * @namespace Strings:maskForSelector\n */\n\n/**\n * Masks all selector-special-characters, to allow selecting elements with special characters in selector using\n * querySelector and querySelectorAll (also works for jQuery and Cash).\n *\n * @param {String} str - the string to mask for use in a selector\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForSelector\n * @alias maskForSelector\n * @example\n * document.querySelector(`#element_${maskForSelector(elementName)}`).classList.remove('test');\n */\nexport function maskForSelector(str){\n\treturn `${str}`.replace(/([#;&,.+*~':\"!^$\\[\\]()=>|\\/@])/g, '\\\\$&');\n}\n\n\n\n/**\n * @namespace Strings:maskForRegEx\n */\n\n/**\n * Masks all regex special characters, to test or match a string using a regex, that contains\n * characters used in regexes themselves.\n *\n * @param {String} str - the string to mask for use in a regexp\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForRegEx\n * @alias maskForRegEx\n * @example\n * if( (new RegExp(`^${maskForRegEx(arbitraryString)}$')).test('abc') ){\n * alert('are identical!');\n * }\n */\nexport function maskForRegEx(str){\n\treturn `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n}\n\n\n\n/**\n * @namespace Strings:maskForHtml\n */\n\n/**\n * Masks a string possibly containing reserved HTML chars for HTML output as is\n * (so a < actually reads on the page).\n *\n * Only replaces critical chars like <>& with entities, but\n * keeps non-critical unicode chars like »/.\n *\n * @param {String} text - the string to mask for use in HTML\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForHtml\n * @alias maskForHtml\n * @see unmaskFromHtml\n * @example\n * maskForHtml('&;üäöÜÄÖß– »')\n * => '</>&;üäöÜÄÖß– »'\n */\nexport function maskForHtml(text){\n\tconst escape = document.createElement('textarea');\n\tescape.textContent = `${text}`;\n\treturn escape.innerHTML;\n}\n\n\n\n/**\n * @namespace Strings:unmaskFromHtml\n */\n\n/**\n * Replaces entities in a html-masked string with the vanilla characters\n * thereby returning a real HTML string, which could, for example, be used\n * to construct new elements with tag markup.\n *\n * @param {String} html - the string to unmask entities in\n * @returns {String} the unmasked string\n *\n * @memberof Strings:unmaskFromHtml\n * @alias unmaskFromHtml\n * @see maskForHtml\n * @example\n * unmaskFromHtml('</>&;üäöÜÄÖß– »')\n * => '&;üäöÜÄÖß– »'\n */\nexport function unmaskFromHtml(html){\n\tconst escape = document.createElement('textarea');\n\tescape.innerHTML = `${html}`;\n\treturn escape.textContent;\n}\n"]} \ No newline at end of file +{"version":3,"file":"strings.js","names":["MODULE_NAME","isFunction","isArray","orDefault","isNaN","hasValue","isPlainObject","SLUGIFY_LATINMAP","replace","subject","search","concat","tmp","forEach","searchTerm","index","length","undefined","String","prototype","replaceAll","split","join","truncate","maxLength","suffix","Error","slice","glue","strings","format","template","replacements","idx","explicit","implicit","fResolve","object","key","value","call","formatters","int","radix","res","parseInt","float","precision","ex","power","Math","pow","round","parseFloat","match","literal","ref","formatter","formatterArg","keyParts","formatterParts","formatterName","test","exec","fLookup","slugify","text","additionalMap","toLowerCase","char","maskForSelector","str","maskForRegEx","maskForHtml","escape","document","createElement","textContent","innerHTML","unmaskFromHtml","html"],"sources":["strings.js"],"mappings":";;;AAQA,MAAMA,YAAc,iBAMZC,WAAYC,QAASC,UAAWC,MAAOC,SAAUC,kBAAoB,aAM7E,MAAMC,iBAAmB,CACxB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IACrG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAC5G,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAC3G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAA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","sourcesContent":["/*!\n * Module Strings\n */\n\n/**\n * @namespace Strings\n */\n\nconst MODULE_NAME = 'Strings';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {isFunction, isArray, orDefault, isNaN, hasValue, isPlainObject} from './basic.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst SLUGIFY_LATINMAP = {\n\t'Á':'A','Ă':'A','Ắ':'A','Ặ':'A','Ằ':'A','Ẳ':'A','Ẵ':'A','Ǎ':'A','Â':'A','Ấ':'A','Ậ':'A','Ầ':'A','Ẩ':'A','Ẫ':'A',\n\t'Ä':'A','Ǟ':'A','Ȧ':'A','Ǡ':'A','Ạ':'A','Ȁ':'A','À':'A','Ả':'A','Ȃ':'A','Ā':'A','Ą':'A','Å':'A','Ǻ':'A','Ḁ':'A',\n\t'Ⱥ':'A','Ã':'A','Ꜳ':'AA','Æ':'AE','Ǽ':'AE','Ǣ':'AE','Ꜵ':'AO','Ꜷ':'AU','Ꜹ':'AV','Ꜻ':'AV','Ꜽ':'AY','Ḃ':'B',\n\t'Ḅ':'B','Ɓ':'B','Ḇ':'B','Ƀ':'B','Ƃ':'B','Ć':'C','Č':'C','Ç':'C','Ḉ':'C','Ĉ':'C','Ċ':'C','Ƈ':'C','Ȼ':'C','Ď':'D',\n\t'Ḑ':'D','Ḓ':'D','Ḋ':'D','Ḍ':'D','Ɗ':'D','Ḏ':'D','Dz':'D','Dž':'D','Đ':'D','Ƌ':'D','DZ':'DZ','DŽ':'DZ','É':'E','Ĕ':'E',\n\t'Ě':'E','Ȩ':'E','Ḝ':'E','Ê':'E','Ế':'E','Ệ':'E','Ề':'E','Ể':'E','Ễ':'E','Ḙ':'E','Ë':'E','Ė':'E','Ẹ':'E','Ȅ':'E',\n\t'È':'E','Ẻ':'E','Ȇ':'E','Ē':'E','Ḗ':'E','Ḕ':'E','Ę':'E','Ɇ':'E','Ẽ':'E','Ḛ':'E','Ꝫ':'ET','Ḟ':'F','Ƒ':'F','Ǵ':'G',\n\t'Ğ':'G','Ǧ':'G','Ģ':'G','Ĝ':'G','Ġ':'G','Ɠ':'G','Ḡ':'G','Ǥ':'G','Ḫ':'H','Ȟ':'H','Ḩ':'H','Ĥ':'H','Ⱨ':'H','Ḧ':'H',\n\t'Ḣ':'H','Ḥ':'H','Ħ':'H','Í':'I','Ĭ':'I','Ǐ':'I','Î':'I','Ï':'I','Ḯ':'I','İ':'I','Ị':'I','Ȉ':'I','Ì':'I','Ỉ':'I',\n\t'Ȋ':'I','Ī':'I','Į':'I','Ɨ':'I','Ĩ':'I','Ḭ':'I','Ꝺ':'D','Ꝼ':'F','Ᵹ':'G','Ꞃ':'R','Ꞅ':'S','Ꞇ':'T','Ꝭ':'IS','Ĵ':'J',\n\t'Ɉ':'J','Ḱ':'K','Ǩ':'K','Ķ':'K','Ⱪ':'K','Ꝃ':'K','Ḳ':'K','Ƙ':'K','Ḵ':'K','Ꝁ':'K','Ꝅ':'K','Ĺ':'L','Ƚ':'L','Ľ':'L',\n\t'Ļ':'L','Ḽ':'L','Ḷ':'L','Ḹ':'L','Ⱡ':'L','Ꝉ':'L','Ḻ':'L','Ŀ':'L','Ɫ':'L','Lj':'L','Ł':'L','LJ':'LJ','Ḿ':'M','Ṁ':'M',\n\t'Ṃ':'M','Ɱ':'M','Ń':'N','Ň':'N','Ņ':'N','Ṋ':'N','Ṅ':'N','Ṇ':'N','Ǹ':'N','Ɲ':'N','Ṉ':'N','Ƞ':'N','Nj':'N','Ñ':'N',\n\t'NJ':'NJ','Ó':'O','Ŏ':'O','Ǒ':'O','Ô':'O','Ố':'O','Ộ':'O','Ồ':'O','Ổ':'O','Ỗ':'O','Ö':'O','Ȫ':'O','Ȯ':'O','Ȱ':'O',\n\t'Ọ':'O','Ő':'O','Ȍ':'O','Ò':'O','Ỏ':'O','Ơ':'O','Ớ':'O','Ợ':'O','Ờ':'O','Ở':'O','Ỡ':'O','Ȏ':'O','Ꝋ':'O','Ꝍ':'O',\n\t'Ō':'O','Ṓ':'O','Ṑ':'O','Ɵ':'O','Ǫ':'O','Ǭ':'O','Ø':'O','Ǿ':'O','Õ':'O','Ṍ':'O','Ṏ':'O','Ȭ':'O','Ƣ':'OI','Ꝏ':'OO',\n\t'Ɛ':'E','Ɔ':'O','Ȣ':'OU','Ṕ':'P','Ṗ':'P','Ꝓ':'P','Ƥ':'P','Ꝕ':'P','Ᵽ':'P','Ꝑ':'P','Ꝙ':'Q','Ꝗ':'Q','Ŕ':'R','Ř':'R',\n\t'Ŗ':'R','Ṙ':'R','Ṛ':'R','Ṝ':'R','Ȑ':'R','Ȓ':'R','Ṟ':'R','Ɍ':'R','Ɽ':'R','Ꜿ':'C','Ǝ':'E','Ś':'S','Ṥ':'S','Š':'S',\n\t'Ṧ':'S','Ş':'S','Ŝ':'S','Ș':'S','Ṡ':'S','Ṣ':'S','Ṩ':'S','ẞ':'SS','Ť':'T','Ţ':'T','Ṱ':'T','Ț':'T','Ⱦ':'T','Ṫ':'T',\n\t'Ṭ':'T','Ƭ':'T','Ṯ':'T','Ʈ':'T','Ŧ':'T','Ɐ':'A','Ꞁ':'L','Ɯ':'M','Ʌ':'V','Ꜩ':'TZ','Ú':'U','Ŭ':'U','Ǔ':'U','Û':'U',\n\t'Ṷ':'U','Ü':'U','Ǘ':'U','Ǚ':'U','Ǜ':'U','Ǖ':'U','Ṳ':'U','Ụ':'U','Ű':'U','Ȕ':'U','Ù':'U','Ủ':'U','Ư':'U','Ứ':'U',\n\t'Ự':'U','Ừ':'U','Ử':'U','Ữ':'U','Ȗ':'U','Ū':'U','Ṻ':'U','Ų':'U','Ů':'U','Ũ':'U','Ṹ':'U','Ṵ':'U','Ꝟ':'V','Ṿ':'V',\n\t'Ʋ':'V','Ṽ':'V','Ꝡ':'VY','Ẃ':'W','Ŵ':'W','Ẅ':'W','Ẇ':'W','Ẉ':'W','Ẁ':'W','Ⱳ':'W','Ẍ':'X','Ẋ':'X','Ý':'Y','Ŷ':'Y',\n\t'Ÿ':'Y','Ẏ':'Y','Ỵ':'Y','Ỳ':'Y','Ƴ':'Y','Ỷ':'Y','Ỿ':'Y','Ȳ':'Y','Ɏ':'Y','Ỹ':'Y','Ź':'Z','Ž':'Z','Ẑ':'Z','Ⱬ':'Z',\n\t'Ż':'Z','Ẓ':'Z','Ȥ':'Z','Ẕ':'Z','Ƶ':'Z','IJ':'IJ','Œ':'OE','ᴀ':'A','ᴁ':'AE','ʙ':'B','ᴃ':'B','ᴄ':'C','ᴅ':'D','ᴇ':'E',\n\t'ꜰ':'F','ɢ':'G','ʛ':'G','ʜ':'H','ɪ':'I','ʁ':'R','ᴊ':'J','ᴋ':'K','ʟ':'L','ᴌ':'L','ᴍ':'M','ɴ':'N','ᴏ':'O','ɶ':'OE',\n\t'ᴐ':'O','ᴕ':'OU','ᴘ':'P','ʀ':'R','ᴎ':'N','ᴙ':'R','ꜱ':'S','ᴛ':'T','ⱻ':'E','ᴚ':'R','ᴜ':'U','ᴠ':'V','ᴡ':'W','ʏ':'Y',\n\t'ᴢ':'Z','á':'a','ă':'a','ắ':'a','ặ':'a','ằ':'a','ẳ':'a','ẵ':'a','ǎ':'a','â':'a','ấ':'a','ậ':'a','ầ':'a','ẩ':'a',\n\t'ẫ':'a','ä':'a','ǟ':'a','ȧ':'a','ǡ':'a','ạ':'a','ȁ':'a','à':'a','ả':'a','ȃ':'a','ā':'a','ą':'a','ᶏ':'a','ẚ':'a',\n\t'å':'a','ǻ':'a','ḁ':'a','ⱥ':'a','ã':'a','ꜳ':'aa','æ':'ae','ǽ':'ae','ǣ':'ae','ꜵ':'ao','ꜷ':'au','ꜹ':'av','ꜻ':'av',\n\t'ꜽ':'ay','ḃ':'b','ḅ':'b','ɓ':'b','ḇ':'b','ᵬ':'b','ᶀ':'b','ƀ':'b','ƃ':'b','ɵ':'o','ć':'c','č':'c','ç':'c','ḉ':'c',\n\t'ĉ':'c','ɕ':'c','ċ':'c','ƈ':'c','ȼ':'c','ď':'d','ḑ':'d','ḓ':'d','ȡ':'d','ḋ':'d','ḍ':'d','ɗ':'d','ᶑ':'d','ḏ':'d',\n\t'ᵭ':'d','ᶁ':'d','đ':'d','ɖ':'d','ƌ':'d','ı':'i','ȷ':'j','ɟ':'j','ʄ':'j','dz':'dz','dž':'dz','é':'e','ĕ':'e','ě':'e',\n\t'ȩ':'e','ḝ':'e','ê':'e','ế':'e','ệ':'e','ề':'e','ể':'e','ễ':'e','ḙ':'e','ë':'e','ė':'e','ẹ':'e','ȅ':'e','è':'e',\n\t'ẻ':'e','ȇ':'e','ē':'e','ḗ':'e','ḕ':'e','ⱸ':'e','ę':'e','ᶒ':'e','ɇ':'e','ẽ':'e','ḛ':'e','ꝫ':'et','ḟ':'f','ƒ':'f',\n\t'ᵮ':'f','ᶂ':'f','ǵ':'g','ğ':'g','ǧ':'g','ģ':'g','ĝ':'g','ġ':'g','ɠ':'g','ḡ':'g','ᶃ':'g','ǥ':'g','ḫ':'h','ȟ':'h',\n\t'ḩ':'h','ĥ':'h','ⱨ':'h','ḧ':'h','ḣ':'h','ḥ':'h','ɦ':'h','ẖ':'h','ħ':'h','ƕ':'hv','í':'i','ĭ':'i','ǐ':'i','î':'i',\n\t'ï':'i','ḯ':'i','ị':'i','ȉ':'i','ì':'i','ỉ':'i','ȋ':'i','ī':'i','į':'i','ᶖ':'i','ɨ':'i','ĩ':'i','ḭ':'i','ꝺ':'d',\n\t'ꝼ':'f','ᵹ':'g','ꞃ':'r','ꞅ':'s','ꞇ':'t','ꝭ':'is','ǰ':'j','ĵ':'j','ʝ':'j','ɉ':'j','ḱ':'k','ǩ':'k','ķ':'k','ⱪ':'k',\n\t'ꝃ':'k','ḳ':'k','ƙ':'k','ḵ':'k','ᶄ':'k','ꝁ':'k','ꝅ':'k','ĺ':'l','ƚ':'l','ɬ':'l','ľ':'l','ļ':'l','ḽ':'l','ȴ':'l',\n\t'ḷ':'l','ḹ':'l','ⱡ':'l','ꝉ':'l','ḻ':'l','ŀ':'l','ɫ':'l','ᶅ':'l','ɭ':'l','ł':'l','lj':'lj','ſ':'s','ẜ':'s','ẛ':'s',\n\t'ẝ':'s','ḿ':'m','ṁ':'m','ṃ':'m','ɱ':'m','ᵯ':'m','ᶆ':'m','ń':'n','ň':'n','ņ':'n','ṋ':'n','ȵ':'n','ṅ':'n','ṇ':'n',\n\t'ǹ':'n','ɲ':'n','ṉ':'n','ƞ':'n','ᵰ':'n','ᶇ':'n','ɳ':'n','ñ':'n','nj':'nj','ó':'o','ŏ':'o','ǒ':'o','ô':'o','ố':'o',\n\t'ộ':'o','ồ':'o','ổ':'o','ỗ':'o','ö':'o','ȫ':'o','ȯ':'o','ȱ':'o','ọ':'o','ő':'o','ȍ':'o','ò':'o','ỏ':'o','ơ':'o',\n\t'ớ':'o','ợ':'o','ờ':'o','ở':'o','ỡ':'o','ȏ':'o','ꝋ':'o','ꝍ':'o','ⱺ':'o','ō':'o','ṓ':'o','ṑ':'o','ǫ':'o','ǭ':'o',\n\t'ø':'o','ǿ':'o','õ':'o','ṍ':'o','ṏ':'o','ȭ':'o','ƣ':'oi','ꝏ':'oo','ɛ':'e','ᶓ':'e','ɔ':'o','ᶗ':'o','ȣ':'ou','ṕ':'p',\n\t'ṗ':'p','ꝓ':'p','ƥ':'p','ᵱ':'p','ᶈ':'p','ꝕ':'p','ᵽ':'p','ꝑ':'p','ꝙ':'q','ʠ':'q','ɋ':'q','ꝗ':'q','ŕ':'r','ř':'r',\n\t'ŗ':'r','ṙ':'r','ṛ':'r','ṝ':'r','ȑ':'r','ɾ':'r','ᵳ':'r','ȓ':'r','ṟ':'r','ɼ':'r','ᵲ':'r','ᶉ':'r','ɍ':'r','ɽ':'r',\n\t'ↄ':'c','ꜿ':'c','ɘ':'e','ɿ':'r','ś':'s','ṥ':'s','š':'s','ṧ':'s','ş':'s','ŝ':'s','ș':'s','ṡ':'s','ṣ':'s','ṩ':'s',\n\t'ʂ':'s','ᵴ':'s','ᶊ':'s','ȿ':'s','ɡ':'g','ß':'ss','ᴑ':'o','ᴓ':'o','ᴝ':'u','ť':'t','ţ':'t','ṱ':'t','ț':'t','ȶ':'t',\n\t'ẗ':'t','ⱦ':'t','ṫ':'t','ṭ':'t','ƭ':'t','ṯ':'t','ᵵ':'t','ƫ':'t','ʈ':'t','ŧ':'t','ᵺ':'th','ɐ':'a','ᴂ':'ae','ǝ':'e',\n\t'ᵷ':'g','ɥ':'h','ʮ':'h','ʯ':'h','ᴉ':'i','ʞ':'k','ꞁ':'l','ɯ':'m','ɰ':'m','ᴔ':'oe','ɹ':'r','ɻ':'r','ɺ':'r','ⱹ':'r',\n\t'ʇ':'t','ʌ':'v','ʍ':'w','ʎ':'y','ꜩ':'tz','ú':'u','ŭ':'u','ǔ':'u','û':'u','ṷ':'u','ü':'u','ǘ':'u','ǚ':'u','ǜ':'u',\n\t'ǖ':'u','ṳ':'u','ụ':'u','ű':'u','ȕ':'u','ù':'u','ủ':'u','ư':'u','ứ':'u','ự':'u','ừ':'u','ử':'u','ữ':'u','ȗ':'u',\n\t'ū':'u','ṻ':'u','ų':'u','ᶙ':'u','ů':'u','ũ':'u','ṹ':'u','ṵ':'u','ᵫ':'ue','ꝸ':'um','ⱴ':'v','ꝟ':'v','ṿ':'v','ʋ':'v',\n\t'ᶌ':'v','ⱱ':'v','ṽ':'v','ꝡ':'vy','ẃ':'w','ŵ':'w','ẅ':'w','ẇ':'w','ẉ':'w','ẁ':'w','ⱳ':'w','ẘ':'w','ẍ':'x','ẋ':'x',\n\t'ᶍ':'x','ý':'y','ŷ':'y','ÿ':'y','ẏ':'y','ỵ':'y','ỳ':'y','ƴ':'y','ỷ':'y','ỿ':'y','ȳ':'y','ẙ':'y','ɏ':'y','ỹ':'y',\n\t'ź':'z','ž':'z','ẑ':'z','ʑ':'z','ⱬ':'z','ż':'z','ẓ':'z','ȥ':'z','ẕ':'z','ᵶ':'z','ᶎ':'z','ʐ':'z','ƶ':'z','ɀ':'z',\n\t'ff':'ff','ffi':'ffi','ffl':'ffl','fi':'fi','fl':'fl','ij':'ij','œ':'oe','st':'st','ₐ':'a','ₑ':'e','ᵢ':'i','ⱼ':'j','ₒ':'o',\n\t'ᵣ':'r','ᵤ':'u','ᵥ':'v','ₓ':'x'\n};\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Strings:replace\n */\n\n/**\n * Offers similar functionality to PHP's str_replace or ES2021's replaceAll and avoids RegExps for this task.\n * Replaces occurrences of search in subject with replace. search and replace may be arrays.\n * If search is an array and replace is a string, all phrases in the array will be replaced with one string.\n * If replace is an array itself, phrases and replacements are matched by index.\n * Missing replacements are treated as an empty string (for example: if your array lengths do not match).\n *\n * Uses String.prototype.replaceAll internally, if available.\n *\n * @param {String} subject - the string to replace in\n * @param {(String|String[])} search - the string(s) to replace\n * @param {String|String[]} replace - the string(s) to replace the search string(s)\n * @returns {String} the modified string\n *\n * @memberof Strings:replace\n * @alias replace\n * @example\n * const sanitizedString = replace([':', '#', '-'], '_', exampleString);\n */\nexport function replace(subject, search, replace){\n\tsubject = `${subject}`;\n\tsearch = [].concat(search);\n\treplace = [].concat(replace);\n\n\tlet tmp = '';\n\n\tsearch.forEach((searchTerm, index) => {\n\t\ttmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0];\n\n\t\tif( isFunction(String.prototype.replaceAll) ){\n\t\t\tsubject = subject.replaceAll(`${searchTerm}`, `${tmp}`);\n\t\t} else {\n\t\t\tsubject = subject.split(`${searchTerm}`).join(`${tmp}`);\n\t\t}\n\t});\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:truncate\n */\n\n/**\n * Truncates a given string after a certain number of characters to enforce length restrictions.\n *\n * @param {String} subject - the string to check and truncate\n * @param {?Number} [maxLength=30] - the maximum allowed character length for the string\n * @param {?String} [suffix='...'] - the trailing string to end a truncated string with\n * @throws error if suffix length is bigger than defined maxLength\n * @returns {String} the (truncated) subject\n *\n * @memberof Strings:truncate\n * @alias truncate\n * @example\n * const truncatedString = truncate(string, 10, '...');\n */\nexport function truncate(subject, maxLength=30, suffix='...'){\n\tsubject = `${subject}`;\n\tmaxLength = orDefault(maxLength, 30, 'int');\n\tsuffix = orDefault(suffix, '...', 'str');\n\n\tif( suffix.length > maxLength ){\n\t\tthrow new Error(`${MODULE_NAME}:truncate | suffix cannot be longer than maxLength`);\n\t}\n\n\tif( subject.length > maxLength ){\n\t\tsubject = `${subject.slice(0, maxLength - suffix.length)}${suffix}`;\n\t}\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:concat\n */\n\n/**\n * Simply concatenates strings with a glue part using array.join in a handy notation.\n * You can also provide arguments to glue as a prepared array as the second parameter,\n * in that case other parameters will be ignored.\n *\n * @param {?String} [glue=''] - the separator to use between single strings\n * @param {?String[]} strings - list of strings to concatenate, either comma-separated or as single array\n * @returns {String} the concatenated string\n *\n * @memberof Strings:concat\n * @alias concat\n * @example\n * const finalCountdown = concat(' ... ', 10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!');\n * const finalCountdown = concat(' ... ', [10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!']);\n */\nexport function concat(glue='', ...strings){\n\tglue = orDefault(glue, '', 'str');\n\n\tif( (strings.length > 0) && isArray(strings[0]) ){\n\t\treturn strings[0].join(glue);\n\t} else {\n\t\treturn strings.join(glue);\n\t}\n}\n\n\n\n/**\n * @namespace Strings:format\n */\n\n/**\n * This is a pythonesque string format implementation.\n * Apply formatted values to a string template, in which replacements are marked with curly braces.\n *\n * Display literal curly brace with {{ and }}.\n *\n * Unknown keys/indexes will be ignored.\n *\n * This solution is adapted from:\n * https://github.com/davidchambers/string-format\n *\n * @param {String} template -\n * @param {(String[]|Object)} replacements - arguments to insert into template, either as a dictionary, an array or a parameter sequence\n * @throws general exception on syntax errors\n * @returns {String} the formatted string\n *\n * @memberof Strings:format\n * @alias format\n * @example\n * format('An elephant is {times:float(0.00)} times smarter than a {animal}', {times : 5.5555, animal : 'lion'})\n * => 'An elephant is 5.56 times smarter than a lion'\n * format('{0}{0}{0} ... {{BATMAN!}}', 'Nana')\n * => 'NanaNanaNana ... {BATMAN!}'\n * format('{} {} {} starts the alphabet.', 'A', 'B', 'C')\n * => 'A B C starts the alphabet.'\n * format('{0:int}, {1:int}, {2:int}: details are for wankers', '1a', 2.222, 3)\n * => '1, 2, 3: details are for wankers'\n */\nexport function format(template, ...replacements){\n\ttemplate = `${template}`;\n\n\tlet\n\t\tidx = 0,\n\t\texplicit = false,\n\t\timplicit = false\n\t;\n\n\tconst fResolve = function(object, key){\n\t\tconst value = object[key];\n\n\t\tif( isFunction(value) ){\n\t\t\treturn value.call(object);\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t};\n\n\tconst fLookup = function(object, key){\n\t\tif( !/^(\\d+)([.]|$)/.test(key) ){\n\t\t\tkey = `0.${key}`;\n\t\t}\n\n\t\tlet match = /(.+?)[.](.+)/.exec(key);\n\t\twhile( match ){\n\t\t\tobject = fResolve(object, match[1]);\n\t\t\tkey = match[2];\n\t\t\tmatch = /(.+?)[.](.+)/.exec(key);\n\t\t}\n\n\t\treturn fResolve(object, key);\n\t};\n\n\tconst formatters = {\n\t\tint(value, radix){\n\t\t\tradix = orDefault(radix, 10, 'int');\n\t\t\tconst res = parseInt(value, radix);\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t},\n\t\tfloat(value, format){\n\t\t\tformat = orDefault(format, null, 'str');\n\n\t\t\tlet res = null;\n\n\t\t\tif( hasValue(format) ){\n\t\t\t\tlet precision = 0;\n\n\t\t\t\ttry {\n\t\t\t\t\tprecision = format.split('.')[1].length;\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | float precision arg malformed`);\n\t\t\t\t}\n\n\t\t\t\tconst power = Math.pow(10, precision);\n\n\t\t\t\tres = Math.round(parseFloat(value) * power) / power;\n\t\t\t} else {\n\t\t\t\tres = parseFloat(value);\n\t\t\t}\n\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t}\n\t};\n\n\treturn template.replace(/([{}])\\1|[{](.*?)(?:!(.+?))?[}]/g, function(match, literal, key){\n\t\tlet\n\t\t\tref = null,\n\t\t\tvalue = '',\n\t\t\tformatter = function(value){ return value; },\n\t\t\tformatterArg = null\n\t\t;\n\n\t\tif( literal ){\n\t\t\treturn literal;\n\t\t}\n\n\t\tif( key.length ){\n\t\t\tconst keyParts = key.split(':');\n\n\t\t\tif( keyParts.length > 1 ){\n\t\t\t\tkey = keyParts[0];\n\n\t\t\t\tconst\n\t\t\t\t\tformatterParts = keyParts[1].split('('),\n\t\t\t\t\tformatterName = formatterParts[0]\n\t\t\t\t;\n\n\t\t\t\tif( formatterParts.length > 1 ){\n\t\t\t\t\tformatterArg = formatterParts[1].replace(')', '');\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tformatter = formatters[formatterName];\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | unknown formatter`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( implicit ){\n\t\t\t\tthrow new Error(`${MODULE_NAME}:format | cannot switch from implicit to explicit numbering`);\n\t\t\t} else {\n\t\t\t\texplicit = true;\n\t\t\t}\n\n\t\t\tref = fLookup(replacements, key);\n\t\t\tvalue = orDefault(ref, '');\n\t\t} else {\n\t\t\tif( explicit ){\n\t\t\t\tthrow new Error (`${MODULE_NAME}:format | cannot switch from explicit to implicit numbering`);\n\t\t\t} else {\n\t\t\t\timplicit = true;\n\t\t\t}\n\n\t\t\tref = replacements[idx];\n\t\t\tvalue = orDefault(ref, '');\n\t\t\tidx++;\n\t\t}\n\n\t\treturn formatter(value, formatterArg);\n\t});\n}\n\n\n\n/**\n * @namespace Strings:slugify\n */\n\n/**\n * Slugifies a text for use in a URL or id/class/attribute.\n * Transforms accented characters to non-accented ones.\n * Throws out everything except basic A-Z characters and numbers after replacements have taken place.\n * Provide own replacements, supplementing or overriding the default replacement map to cover special cases\n * (will take precedence over the default map).\n *\n * @param {String} text - the text to slugify\n * @param {String?} [additionalMap=null] - optional character map to supplement/override the default map, having the form {'[search character]' : '[replacement]', ...}\n * @returns {String} the slugified string\n *\n * @memberof Strings:slugify\n * @alias slugify\n * @example\n * slugify('This is a cömplicated ßtring for URLs!')\n * => 'this-is-a-complicated-sstring-for-urls'\n */\nexport function slugify(text, additionalMap=null){\n\tif( !isPlainObject(additionalMap) ){\n\t\tadditionalMap = {};\n\t}\n\n\treturn `${text}`.toLowerCase()\n\t\t.replace(/\\s+|_+/g, '-') // replace spaces and underscores with \"-\"\n\t\t.replace(\n\t\t\t/[^\\-]/g, // replace accented chars with plain ones via map and/or apply additionalMap\n\t\t\tchar => additionalMap[char] ?? SLUGIFY_LATINMAP[char] ?? char\n\t\t)\n\t\t.replace(/[^\\w\\-]+/g, '') // remove all non-word, non-dash chars\n\t\t.replace(/--+/g, '-') // replace multiple \"-\" with single \"-\"\n\t\t.replace(/^-+/, '') // trim \"-\" from start of text\n\t\t.replace(/-+$/, '') // trim \"-\" from end of text\n\t;\n}\n\n\n\n/**\n * @namespace Strings:maskForSelector\n */\n\n/**\n * Masks all selector-special-characters, to allow selecting elements with special characters in selector using\n * querySelector and querySelectorAll (also works for jQuery and Cash).\n *\n * @param {String} str - the string to mask for use in a selector\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForSelector\n * @alias maskForSelector\n * @example\n * document.querySelector(`#element_${maskForSelector(elementName)}`).classList.remove('test');\n */\nexport function maskForSelector(str){\n\treturn `${str}`.replace(/([#;&,.+*~':\"!^$\\[\\]()=>|\\/@])/g, '\\\\$&');\n}\n\n\n\n/**\n * @namespace Strings:maskForRegEx\n */\n\n/**\n * Masks all regex special characters, to test or match a string using a regex, that contains\n * characters used in regexes themselves.\n *\n * @param {String} str - the string to mask for use in a regexp\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForRegEx\n * @alias maskForRegEx\n * @example\n * if( (new RegExp(`^${maskForRegEx(arbitraryString)}$')).test('abc') ){\n * alert('are identical!');\n * }\n */\nexport function maskForRegEx(str){\n\treturn `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n}\n\n\n\n/**\n * @namespace Strings:maskForHtml\n */\n\n/**\n * Masks a string possibly containing reserved HTML chars for HTML output as is\n * (so a < actually reads on the page).\n *\n * Only replaces critical chars like <>& with entities, but\n * keeps non-critical unicode chars like »/.\n *\n * @param {String} text - the string to mask for use in HTML\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForHtml\n * @alias maskForHtml\n * @see unmaskFromHtml\n * @example\n * maskForHtml('&;üäöÜÄÖß– »')\n * => '</>&;üäöÜÄÖß– »'\n */\nexport function maskForHtml(text){\n\tconst escape = document.createElement('textarea');\n\tescape.textContent = `${text}`;\n\treturn escape.innerHTML;\n}\n\n\n\n/**\n * @namespace Strings:unmaskFromHtml\n */\n\n/**\n * Replaces entities in a html-masked string with the vanilla characters\n * thereby returning a real HTML string, which could, for example, be used\n * to construct new elements with tag markup.\n *\n * @param {String} html - the string to unmask entities in\n * @returns {String} the unmasked string\n *\n * @memberof Strings:unmaskFromHtml\n * @alias unmaskFromHtml\n * @see maskForHtml\n * @example\n * unmaskFromHtml('</>&;üäöÜÄÖß– »')\n * => '&;üäöÜÄÖß– »'\n */\nexport function unmaskFromHtml(html){\n\tconst escape = document.createElement('textarea');\n\tescape.innerHTML = `${html}`;\n\treturn escape.textContent;\n}\n"]} \ No newline at end of file diff --git a/dist/timers.js b/dist/timers.js index 60c6b521..7c5fc56d 100644 --- a/dist/timers.js +++ b/dist/timers.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Timers */ -const MODULE_NAME="Timers";import{orDefault,isA,assert,hasValue,hasMembers}from"./basic.js";export function schedule(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:schedule | ms must be positive"),assert(isA(t,"function"),"Timers:schedule | callback must be a function"),hasValue(n)&&countermand(n),{id:window.setTimeout(t,e),type:"timeout"}}export function pschedule(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:pschedule | ms must be positive"),assert(isA(t,"function"),"Timers:pschedule | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n),n.precise=!0):n={id:-1,type:"timeout",precise:!0};const i=Date.now();let o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):t()};return n.id=window.setTimeout(s,o),n}export function reschedule(e,t,n){return t=orDefault(t,1,"int"),assert(t>=0,"Timers:reschedule | ms must be positive"),assert(isA(n,"function"),"Timers:reschedule | callback must be a function"),hasValue(e)&&hasValue(e.precise)&&e.precise?pschedule(t,n,e):schedule(t,n,e)}export function loop(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:loop | ms must be positive"),assert(isA(t,"function"),"Timers:loop | callback must be a function"),hasValue(n)&&countermand(n,!0),{id:window.setInterval(t,e),type:"interval"}}export function ploop(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:ploop | ms must be positive"),assert(isA(t,"function"),"Timers:ploop | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n,!0),n.precise=!0):n={id:-1,type:"interval",precise:!0};let i=Date.now(),o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):(t(),i=Date.now(),o=e,n.id=window.setTimeout(s,o))};return n.id=window.setTimeout(s,o),n}export function countermand(e,t=!1){t=orDefault(t,!1,"bool"),hasValue(e)&&(hasMembers(e,["id","type"])?"interval"===e.type?window.clearInterval(e.id):window.clearTimeout(e.id):t?window.clearInterval(e):window.clearTimeout(e))}export function requestAnimationFrame(e){assert(isA(e,"function"),"Timers:requestAnimationFrame | callback is no function");const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame??function(e){return schedule(16,e)};return t(e)}export function cancelAnimationFrame(e){const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame;let n=window.cancelAnimationFrame??window.mozCancelAnimationFrame;return hasValue(t)||(n=countermand),n(e)}export function waitForRepaint(e){assert(isA(e,"function"),"Timers:waitForRepaint | callback is no function");const t={};return t.outer=requestAnimationFrame((function(){t.inner=requestAnimationFrame(e)})),t} +const MODULE_NAME="Timers";import{orDefault,isFunction,assert,hasValue,hasMembers}from"./basic.js";export function schedule(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:schedule | ms must be positive"),assert(isFunction(t),"Timers:schedule | callback must be a function"),hasValue(n)&&countermand(n),{id:window.setTimeout(t,e),type:"timeout"}}export function pschedule(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:pschedule | ms must be positive"),assert(isFunction(t),"Timers:pschedule | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n),n.precise=!0):n={id:-1,type:"timeout",precise:!0};const i=Date.now();let o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):t()};return n.id=window.setTimeout(s,o),n}export function reschedule(e,t,n){return t=orDefault(t,1,"int"),assert(t>=0,"Timers:reschedule | ms must be positive"),assert(isFunction(n),"Timers:reschedule | callback must be a function"),hasValue(e)&&hasValue(e.precise)&&e.precise?pschedule(t,n,e):schedule(t,n,e)}export function loop(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:loop | ms must be positive"),assert(isFunction(t),"Timers:loop | callback must be a function"),hasValue(n)&&countermand(n,!0),{id:window.setInterval(t,e),type:"interval"}}export function ploop(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:ploop | ms must be positive"),assert(isFunction(t),"Timers:ploop | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n,!0),n.precise=!0):n={id:-1,type:"interval",precise:!0};let i=Date.now(),o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):(t(),i=Date.now(),o=e,n.id=window.setTimeout(s,o))};return n.id=window.setTimeout(s,o),n}export function countermand(e,t=!1){t=orDefault(t,!1,"bool"),hasValue(e)&&(hasMembers(e,["id","type"])?"interval"===e.type?window.clearInterval(e.id):window.clearTimeout(e.id):t?window.clearInterval(e):window.clearTimeout(e))}export function requestAnimationFrame(e){assert(isFunction(e),"Timers:requestAnimationFrame | callback is no function");const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame??function(e){return schedule(16,e)};return t(e)}export function cancelAnimationFrame(e){const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame;let n=window.cancelAnimationFrame??window.mozCancelAnimationFrame;return hasValue(t)||(n=countermand),n(e)}export function waitForRepaint(e){assert(isFunction(e),"Timers:waitForRepaint | callback is no function");const t={};return t.outer=requestAnimationFrame((function(){t.inner=requestAnimationFrame(e)})),t} //# sourceMappingURL=timers.js.map diff --git a/dist/timers.js.map b/dist/timers.js.map index 8561cac8..8fdd9beb 100644 --- a/dist/timers.js.map +++ b/dist/timers.js.map @@ -1 +1 @@ -{"version":3,"file":"timers.js","names":["MODULE_NAME","orDefault","isA","assert","hasValue","hasMembers","schedule","ms","callback","oldTimer","countermand","id","window","setTimeout","type","pschedule","precise","waitStart","Date","now","waitMilliSecs","fAdjustWait","reschedule","timer","loop","oldLoop","setInterval","ploop","isInterval","clearInterval","clearTimeout","requestAnimationFrame","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cancelAnimationFrame","caf","mozCancelAnimationFrame","waitForRepaint","ids","outer","inner"],"sources":["timers.js"],"mappings":"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","sourcesContent":["/*!\n * Module Timers\n */\n\n/**\n * @namespace Timers\n */\n\nconst MODULE_NAME = 'Timers';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {orDefault, isA, assert, hasValue, hasMembers} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Timers:schedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is negative or callback is not a function\n * @returns {Object} new timer\n *\n * @memberof Timers:schedule\n * @alias schedule\n * @see pschedule\n * @see countermand\n * @example\n * const timer = schedule(1000, function(){ alert('time for tea'); });\n * const timer = schedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function schedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:schedule | callback must be a function`);\n\n\tif( hasValue(oldTimer) ){\n\t\tcountermand(oldTimer);\n\t}\n\n\treturn {id : window.setTimeout(callback, ms), type : 'timeout'};\n}\n\n\n\n/**\n * @namespace Timers:pschedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long\n * running timers. The timers of this method can also be used in countermand().\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (does not create new timer object if oldTimer given, but returns old one)\n *\n * @memberof Timers:pschedule\n * @alias pschedule\n * @see schedule\n * @see countermand\n * @example\n * const timer = pschedule(1000, function(){ alert('time for tea'); });\n * const timer = pschedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function pschedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:pschedule | callback must be a function`);\n\n\tif(\n\t\thasValue(oldTimer)\n\t\t&& hasMembers(oldTimer, ['id', 'type'])\n\t){\n\t\tcountermand(oldTimer);\n\t\toldTimer.precise = true;\n\t} else {\n\t\toldTimer = {id : -1, type : 'timeout', precise : true};\n\t}\n\n\tconst waitStart = Date.now();\n\tlet waitMilliSecs = ms;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldTimer.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t}\n\t};\n\n\toldTimer.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldTimer;\n}\n\n\n\n/**\n * @namespace Timers:reschedule\n */\n\n/**\n * Alias for schedule() with more natural param-order for rescheduling.\n *\n * @param {(Object|Number)} timer - the timer to refresh/reset\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (may be the original timer, if given timer is precise from pschedule or ploop)\n *\n * @memberof Timers:reschedule\n * @alias reschedule\n * @see schedule\n * @example\n * const timer = reschedule(timer, 3000, function(){ alert('taking even more time'); });\n */\nexport function reschedule(timer, ms, callback){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:reschedule | callback must be a function`);\n\n\tif( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){\n\t\treturn pschedule(ms, callback, timer);\n\t} else {\n\t\treturn schedule(ms, callback, timer);\n\t}\n}\n\n\n\n/**\n * @namespace Timers:loop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} new loop\n *\n * @memberof Timers:loop\n * @alias loop\n * @see ploop\n * @see countermand\n * @example\n * const loop = loop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = loop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function loop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:loop | callback must be a function`);\n\n\tif( hasValue(oldLoop) ){\n\t\tcountermand(oldLoop, true);\n\t}\n\n\treturn {id : window.setInterval(callback, ms), type : 'interval'};\n}\n\n\n\n/**\n * @namespace Timers:ploop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long running loops.\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * The loops of this method can also be used in countermand().\n * This method does not actually use intervals internally but timeouts,\n * so don't wonder if you can't find the ids in JS.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} loop (if you give an old loop into the function the same reference will be returned)\n *\n * @memberof Timers:ploop\n * @alias ploop\n * @see loop\n * @see countermand\n * @example\n * const loop = ploop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = ploop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function ploop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:ploop | callback must be a function`);\n\n\tif(\n\t\thasValue(oldLoop)\n\t\t&& hasMembers(oldLoop, ['id', 'type'])\n\t){\n\t\tcountermand(oldLoop, true);\n\t\toldLoop.precise = true;\n\t} else {\n\t\toldLoop = {id : -1, type : 'interval', precise : true};\n\t}\n\n\tlet\n\t\twaitStart = Date.now(),\n\t\twaitMilliSecs = ms\n\t;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t\twaitStart = Date.now();\n\t\t\twaitMilliSecs = ms;\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\t\t}\n\t};\n\n\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldLoop;\n}\n\n\n\n/**\n * @namespace Timers:countermand\n */\n\n/**\n * Cancel a timer or loop immediately.\n *\n * @param {(Object|Number)} timer - the timer or loop to end\n * @param {?Boolean} [isInterval=false] - defines if a timer or a loop is to be stopped, set in case timer is a GUID\n *\n * @memberof Timers:countermand\n * @alias countermand\n * @see schedule\n * @see pschedule\n * @see loop\n * @see ploop\n * @example\n * countermand(timer);\n * countermand(loop);\n */\nexport function countermand(timer, isInterval=false){\n\tisInterval = orDefault(isInterval, false, 'bool');\n\n\tif( hasValue(timer) ){\n\t\tif( hasMembers(timer, ['id', 'type']) ){\n\t\t\tif( timer.type === 'interval' ){\n\t\t\t\twindow.clearInterval(timer.id);\n\t\t\t} else {\n\t\t\t\twindow.clearTimeout(timer.id);\n\t\t\t}\n\t\t} else {\n\t\t\tif( !isInterval ){\n\t\t\t\twindow.clearTimeout(timer);\n\t\t\t} else {\n\t\t\t\twindow.clearInterval(timer);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/**\n * @namespace Timers:requestAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.requestAnimationFrame with a timeout fallback in\n * case the functionality is missing from the browser.\n *\n * @param {Function} callback - the code to execute once the browser has assigned an execution slot for it\n * @throws error if callback is not a function\n * @return {Number} either the id of the requestAnimationFrame or the internal timeout, both are cancellable via cancelAnimationFrame\n *\n * @memberof Timers:requestAnimationFrame\n * @alias requestAnimationFrame\n * @see raf\n * @see cancelAnimationFrame\n * @see caf\n * @example\n * const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; });\n */\nexport function requestAnimationFrame(callback){\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:requestAnimationFrame | callback is no function`);\n\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t\t?? function(callback){ return schedule(16, callback); }\n\t;\n\n\treturn raf(callback);\n}\n\n\n\n/**\n * @namespace Timers:cancelAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.cancelAnimationFrame.\n *\n * @param {Number} id - either the id of the requestAnimationFrame or its timeout fallback\n *\n * @memberof Timers:cancelAnimationFrame\n * @alias cancelAnimationFrame\n * @see requestAnimationFrame\n * @see raf\n * @see caf\n * @example\n * cancelAnimationFrame(requestAnimationFrame(function(){ window.body.style.opacity = 0; }));\n */\nexport function cancelAnimationFrame(id){\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t;\n\n\tlet caf = window.cancelAnimationFrame\n\t\t?? window.mozCancelAnimationFrame\n\t;\n\n\tif( !hasValue(raf) ){\n\t\tcaf = countermand;\n\t}\n\n\treturn caf(id);\n}\n\n\n\n/**\n * @namespace Timers:waitForRepaint\n */\n\n/**\n * This function has the purpose to offer a safe execution slot for code depending on an up-to-date rendering state of\n * the DOM after a change to styles for example. Let's say you add a class to an element and right in the next line\n * you'll want to read a layout attribute like width or height from it. This might fail, because there is no guarantee\n * the browser actually already applied the new styles to be read from the DOM.\n *\n * To wait safely for the new DOM state this method works with two stacked requestAnimationFrame calls.\n *\n * Since requestAnimationFrame always happens _before_ a repaint, two stacked calls ensure, that there has to be a\n * repaint between them.\n *\n * @param {Function} callback - the code to execute once the browser performed a repaint\n * @throws error if callback is not a function\n * @return {Object} dictionary of ids for the inner and outer request ids, outer gets assigned right away, while inner gets assigned after first callback => {outer : 1, inner : 2}\n *\n * @memberof Timers:waitForRepaint\n * @alias waitForRepaint\n * @see requestAnimationFrame\n * @see raf\n * @example\n * element.classList.add('special-stuff');\n * waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); });\n */\nexport function waitForRepaint(callback){\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:waitForRepaint | callback is no function`);\n\n\tconst ids = {};\n\n\tids.outer = requestAnimationFrame(function(){\n\t\tids.inner = requestAnimationFrame(callback);\n\t});\n\n\treturn ids;\n}\n"]} \ No newline at end of file +{"version":3,"file":"timers.js","names":["MODULE_NAME","orDefault","isFunction","assert","hasValue","hasMembers","schedule","ms","callback","oldTimer","countermand","id","window","setTimeout","type","pschedule","precise","waitStart","Date","now","waitMilliSecs","fAdjustWait","reschedule","timer","loop","oldLoop","setInterval","ploop","isInterval","clearInterval","clearTimeout","requestAnimationFrame","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cancelAnimationFrame","caf","mozCancelAnimationFrame","waitForRepaint","ids","outer","inner"],"sources":["timers.js"],"mappings":"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","sourcesContent":["/*!\n * Module Timers\n */\n\n/**\n * @namespace Timers\n */\n\nconst MODULE_NAME = 'Timers';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {orDefault, isFunction, assert, hasValue, hasMembers} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Timers:schedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is negative or callback is not a function\n * @returns {Object} new timer\n *\n * @memberof Timers:schedule\n * @alias schedule\n * @see pschedule\n * @see countermand\n * @example\n * const timer = schedule(1000, function(){ alert('time for tea'); });\n * const timer = schedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function schedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:schedule | callback must be a function`);\n\n\tif( hasValue(oldTimer) ){\n\t\tcountermand(oldTimer);\n\t}\n\n\treturn {id : window.setTimeout(callback, ms), type : 'timeout'};\n}\n\n\n\n/**\n * @namespace Timers:pschedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long\n * running timers. The timers of this method can also be used in countermand().\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (does not create new timer object if oldTimer given, but returns old one)\n *\n * @memberof Timers:pschedule\n * @alias pschedule\n * @see schedule\n * @see countermand\n * @example\n * const timer = pschedule(1000, function(){ alert('time for tea'); });\n * const timer = pschedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function pschedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:pschedule | callback must be a function`);\n\n\tif(\n\t\thasValue(oldTimer)\n\t\t&& hasMembers(oldTimer, ['id', 'type'])\n\t){\n\t\tcountermand(oldTimer);\n\t\toldTimer.precise = true;\n\t} else {\n\t\toldTimer = {id : -1, type : 'timeout', precise : true};\n\t}\n\n\tconst waitStart = Date.now();\n\tlet waitMilliSecs = ms;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldTimer.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t}\n\t};\n\n\toldTimer.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldTimer;\n}\n\n\n\n/**\n * @namespace Timers:reschedule\n */\n\n/**\n * Alias for schedule() with more natural param-order for rescheduling.\n *\n * @param {(Object|Number)} timer - the timer to refresh/reset\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (may be the original timer, if given timer is precise from pschedule or ploop)\n *\n * @memberof Timers:reschedule\n * @alias reschedule\n * @see schedule\n * @example\n * const timer = reschedule(timer, 3000, function(){ alert('taking even more time'); });\n */\nexport function reschedule(timer, ms, callback){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:reschedule | callback must be a function`);\n\n\tif( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){\n\t\treturn pschedule(ms, callback, timer);\n\t} else {\n\t\treturn schedule(ms, callback, timer);\n\t}\n}\n\n\n\n/**\n * @namespace Timers:loop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} new loop\n *\n * @memberof Timers:loop\n * @alias loop\n * @see ploop\n * @see countermand\n * @example\n * const loop = loop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = loop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function loop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:loop | callback must be a function`);\n\n\tif( hasValue(oldLoop) ){\n\t\tcountermand(oldLoop, true);\n\t}\n\n\treturn {id : window.setInterval(callback, ms), type : 'interval'};\n}\n\n\n\n/**\n * @namespace Timers:ploop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long running loops.\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * The loops of this method can also be used in countermand().\n * This method does not actually use intervals internally but timeouts,\n * so don't wonder if you can't find the ids in JS.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} loop (if you give an old loop into the function the same reference will be returned)\n *\n * @memberof Timers:ploop\n * @alias ploop\n * @see loop\n * @see countermand\n * @example\n * const loop = ploop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = ploop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function ploop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:ploop | callback must be a function`);\n\n\tif(\n\t\thasValue(oldLoop)\n\t\t&& hasMembers(oldLoop, ['id', 'type'])\n\t){\n\t\tcountermand(oldLoop, true);\n\t\toldLoop.precise = true;\n\t} else {\n\t\toldLoop = {id : -1, type : 'interval', precise : true};\n\t}\n\n\tlet\n\t\twaitStart = Date.now(),\n\t\twaitMilliSecs = ms\n\t;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t\twaitStart = Date.now();\n\t\t\twaitMilliSecs = ms;\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\t\t}\n\t};\n\n\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldLoop;\n}\n\n\n\n/**\n * @namespace Timers:countermand\n */\n\n/**\n * Cancel a timer or loop immediately.\n *\n * @param {(Object|Number)} timer - the timer or loop to end\n * @param {?Boolean} [isInterval=false] - defines if a timer or a loop is to be stopped, set in case timer is a GUID\n *\n * @memberof Timers:countermand\n * @alias countermand\n * @see schedule\n * @see pschedule\n * @see loop\n * @see ploop\n * @example\n * countermand(timer);\n * countermand(loop);\n */\nexport function countermand(timer, isInterval=false){\n\tisInterval = orDefault(isInterval, false, 'bool');\n\n\tif( hasValue(timer) ){\n\t\tif( hasMembers(timer, ['id', 'type']) ){\n\t\t\tif( timer.type === 'interval' ){\n\t\t\t\twindow.clearInterval(timer.id);\n\t\t\t} else {\n\t\t\t\twindow.clearTimeout(timer.id);\n\t\t\t}\n\t\t} else {\n\t\t\tif( !isInterval ){\n\t\t\t\twindow.clearTimeout(timer);\n\t\t\t} else {\n\t\t\t\twindow.clearInterval(timer);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/**\n * @namespace Timers:requestAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.requestAnimationFrame with a timeout fallback in\n * case the functionality is missing from the browser.\n *\n * @param {Function} callback - the code to execute once the browser has assigned an execution slot for it\n * @throws error if callback is not a function\n * @return {Number} either the id of the requestAnimationFrame or the internal timeout, both are cancellable via cancelAnimationFrame\n *\n * @memberof Timers:requestAnimationFrame\n * @alias requestAnimationFrame\n * @see raf\n * @see cancelAnimationFrame\n * @see caf\n * @example\n * const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; });\n */\nexport function requestAnimationFrame(callback){\n\tassert(isFunction(callback), `${MODULE_NAME}:requestAnimationFrame | callback is no function`);\n\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t\t?? function(callback){ return schedule(16, callback); }\n\t;\n\n\treturn raf(callback);\n}\n\n\n\n/**\n * @namespace Timers:cancelAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.cancelAnimationFrame.\n *\n * @param {Number} id - either the id of the requestAnimationFrame or its timeout fallback\n *\n * @memberof Timers:cancelAnimationFrame\n * @alias cancelAnimationFrame\n * @see requestAnimationFrame\n * @see raf\n * @see caf\n * @example\n * cancelAnimationFrame(requestAnimationFrame(function(){ window.body.style.opacity = 0; }));\n */\nexport function cancelAnimationFrame(id){\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t;\n\n\tlet caf = window.cancelAnimationFrame\n\t\t?? window.mozCancelAnimationFrame\n\t;\n\n\tif( !hasValue(raf) ){\n\t\tcaf = countermand;\n\t}\n\n\treturn caf(id);\n}\n\n\n\n/**\n * @namespace Timers:waitForRepaint\n */\n\n/**\n * This function has the purpose to offer a safe execution slot for code depending on an up-to-date rendering state of\n * the DOM after a change to styles for example. Let's say you add a class to an element and right in the next line\n * you'll want to read a layout attribute like width or height from it. This might fail, because there is no guarantee\n * the browser actually already applied the new styles to be read from the DOM.\n *\n * To wait safely for the new DOM state this method works with two stacked requestAnimationFrame calls.\n *\n * Since requestAnimationFrame always happens _before_ a repaint, two stacked calls ensure, that there has to be a\n * repaint between them.\n *\n * @param {Function} callback - the code to execute once the browser performed a repaint\n * @throws error if callback is not a function\n * @return {Object} dictionary of ids for the inner and outer request ids, outer gets assigned right away, while inner gets assigned after first callback => {outer : 1, inner : 2}\n *\n * @memberof Timers:waitForRepaint\n * @alias waitForRepaint\n * @see requestAnimationFrame\n * @see raf\n * @example\n * element.classList.add('special-stuff');\n * waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); });\n */\nexport function waitForRepaint(callback){\n\tassert(isFunction(callback), `${MODULE_NAME}:waitForRepaint | callback is no function`);\n\n\tconst ids = {};\n\n\tids.outer = requestAnimationFrame(function(){\n\t\tids.inner = requestAnimationFrame(callback);\n\t});\n\n\treturn ids;\n}\n"]} \ No newline at end of file diff --git a/dist/urls.js b/dist/urls.js index 8a03bff2..4907a6f5 100644 --- a/dist/urls.js +++ b/dist/urls.js @@ -1,5 +1,5 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Urls diff --git a/dist/viewport.js b/dist/viewport.js index d8e3f7eb..bf345f2a 100644 --- a/dist/viewport.js +++ b/dist/viewport.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Viewport */ -const MODULE_NAME="Viewport";import{hasValue,orDefault,isA,isElement,Deferred,assert}from"./basic.js";import{EasingFunctions}from"./animation.js";import{requestAnimationFrame}from"./timers.js";export function isInViewport(t,e=!1){let o,n;e=orDefault(e,!1,"bool");try{o=t.getBoundingClientRect()}catch(t){return!0}return n=e?{top:0,right:window.innerWidth,bottom:window.innerHeight,left:0}:{top:1-(o.bottom-o.top),right:window.innerWidth+(o.right-o.left)+1,bottom:window.innerHeight+(o.bottom-o.top)+1,left:1-(o.right-o.left)},o.top>=n.top&&o.right<=n.right&&o.left>=n.left&&o.bottom<=n.bottom}export function scrollTo(t,e=1e3,o=0,n="easeInOutCubic",i=!1,r=!1){e=orDefault(e,1e3,"int"),o=orDefault(o,0,"int"),n=orDefault(n,"easeInOutCubic","str"),i=orDefault(i,!1,"bool"),r=orDefault(r,!1,"bool"),assert(isElement(t)||isA(t,"window"),"Viewport:scrollTo | element unusable"),assert(e>0,"Viewport:scrollTo | durationMs must be > 0"),n=isA(EasingFunctions[n],"function")?EasingFunctions[n]:EasingFunctions.easeInOutCubic;const s=new Deferred,l=t.self===t;let u=!l&&isInViewport(t,!0);try{t.getBoundingClientRect()}catch(t){u=!1}if(i||!u){let i,u,a=!1;const c=window.pageYOffset;u=l?o:window.pageYOffset+t.getBoundingClientRect().top-Math.round(window.innerHeight/2)+o;const w=u-c,f=function(t){if(!a){hasValue(i)||(i=t);const o=t-i,r=n(Math.min(o/e,1));window.scrollTo(0,c+w*r),o=n.top&&o.right<=n.right&&o.left>=n.left&&o.bottom<=n.bottom}export function scrollTo(t,e=1e3,o=0,n="easeInOutCubic",i=!1,r=!1){e=orDefault(e,1e3,"int"),o=orDefault(o,0,"int"),n=orDefault(n,"easeInOutCubic","str"),i=orDefault(i,!1,"bool"),r=orDefault(r,!1,"bool"),assert(isElement(t)||isWindow(t),"Viewport:scrollTo | element unusable"),assert(e>0,"Viewport:scrollTo | durationMs must be > 0"),n=isFunction(EasingFunctions[n])?EasingFunctions[n]:EasingFunctions.easeInOutCubic;const s=new Deferred,l=t.self===t;let u=!l&&isInViewport(t,!0);try{t.getBoundingClientRect()}catch(t){u=!1}if(i||!u){let i,u,a=!1;const c=window.pageYOffset;u=l?o:window.pageYOffset+t.getBoundingClientRect().top-Math.round(window.innerHeight/2)+o;const w=u-c,f=function(t){if(!a){hasValue(i)||(i=t);const o=t-i,r=n(Math.min(o/e,1));window.scrollTo(0,c+w*r),o= viewportBounds.top &&\n\t\tbb.right <= viewportBounds.right &&\n\t\tbb.left >= viewportBounds.left &&\n\t\tbb.bottom <= viewportBounds.bottom\n\t);\n}\n\n\n\n/**\n * @namespace Viewport:scrollTo\n */\n\n/**\n * Scrolls the viewport to the element's position (first pixel at half viewport height).\n * Does not do anything if target element is already fully in viewport, unless scrollEvenIfFullyInViewport is set to\n * true. Uses getBoundingClientRect to measure viewport check, scrolls always if missing.\n *\n * If you use this function on a window, the offset is directly used as scrollTop, so this function may also be used for\n * things like back to top buttons.\n *\n * Scrolls may be cancelled by setting cancelOnUserScroll to true, but keep in mind, that this will only work\n * with mousewheels and (maybe) touchpads on modern browsers. No keyboard or scrollbar support yet.\n * The root of the problem is that a user scroll is indistinguishable from a js-triggered scroll,\n * since both trigger the scroll event and look exactly the same. So we have to use exotic\n * and specific events like mousewheel and DOMMouseScroll. So, please, use cancelOnUserScroll only\n * as a convenience option and not as a must.\n *\n *\n * @param {HTMLElement|Window} element - the element to scroll to or the window to scroll within\n * @param {?Number} [durationMs=1000] - duration of the scrolling animation\n * @param {?Number} [offset=0] - offset from the viewport center to apply to the end position\n * @param {?String} [easing='easeInOutCubic'] - easing function to use, can be any of Animation.EasingFunctions\n * @param {?Boolean} [scrollEvenIfFullyInViewport=false] - if true, forces method to always scroll no matter the element's position\n * @param {?Boolean} [cancelOnUserScroll=false] - if true, scrolling animation will immediately be canceled on manual user scroll, return value will not resolve in that case\n * @throws error if element is not usable or if durationMs is <= 0\n * @returns {Deferred} resolves when scroll complete, rejects if scroll fails or is cancelled\n *\n * @memberof Viewport:scrollTo\n * @alias scrollTo\n * @see EasingFunctions\n * @example\n * document.querySelector('a.jumpitem').addEventListener('click', function(){ scrollTo(document.querySelector('.jumptarget'), function(){ alert('scrolled!'); }, 500, -100, true); });\n * scrollTo(document.querySelector('.jumptarget'), function(){ alert('Not triggered if user uses mousewheel.'); }, 5000, -0, false, true);\n * scrollTo(window, null, 500, 0, false, true);\n */\nexport function scrollTo(element, durationMs=1000, offset=0, easing='easeInOutCubic', scrollEvenIfFullyInViewport=false, cancelOnUserScroll=false){\n\tdurationMs = orDefault(durationMs, 1000, 'int');\n\toffset = orDefault(offset, 0, 'int');\n\teasing = orDefault(easing, 'easeInOutCubic', 'str');\n\tscrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool');\n\tcancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool');\n\n\tassert(isElement(element) || isA(element, 'window'), `${MODULE_NAME}:scrollTo | element unusable`);\n\tassert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`);\n\n\tif( !isA(EasingFunctions[easing], 'function') ){\n\t\teasing = EasingFunctions.easeInOutCubic;\n\t} else {\n\t\teasing = EasingFunctions[easing];\n\t}\n\n\tconst\n\t\tres = new Deferred(),\n\t\telementIsWindow = (element.self === element)\n\t;\n\n\t// the window itself is considered not to be in viewport\n\tlet elementInViewport = elementIsWindow ? false : isInViewport(element, true);\n\n\t// in this case missing support for bounding rects should result in scrolling\n\ttry {\n\t\telement.getBoundingClientRect();\n\t} catch(err){\n\t\telementInViewport = false;\n\t}\n\n\tif( scrollEvenIfFullyInViewport || !elementInViewport ){\n\t\tlet start, targetY, cancelled = false;\n\t\tconst startY = window.pageYOffset;\n\n\t\tif( elementIsWindow ){\n\t\t\ttargetY = offset;\n\t\t} else {\n\t\t\ttargetY = window.pageYOffset + element.getBoundingClientRect().top - Math.round(window.innerHeight / 2) + offset;\n\t\t}\n\n\t\tconst\n\t\t\tdiff = targetY - startY,\n\t\t\tfScroll = function(timestamp){\n\t\t\t\tif( !cancelled ){\n\t\t\t\t\tif( !hasValue(start) ){\n\t\t\t\t\t\tstart = timestamp;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst\n\t\t\t\t\t\ttime = timestamp - start,\n\t\t\t\t\t\tprogress = easing(Math.min(time / durationMs, 1))\n\t\t\t\t\t;\n\n\t\t\t\t\twindow.scrollTo(0, startY + (diff * progress));\n\n\t\t\t\t\tif( (time < durationMs) && (progress < 1) ){\n\t\t\t\t\t\trequestAnimationFrame(fScroll)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres.resolve();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t;\n\n\t\tif( cancelOnUserScroll ){\n\t\t\tconst fCancelScroll = function(){\n\t\t\t\tcancelled = true;\n\t\t\t\tres.reject(new Error('cancelled'));\n\t\t\t\twindow.removeEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\t\twindow.removeEventListener('mousewheel', fCancelScroll);\n\t\t\t};\n\n\t\t\twindow.addEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\twindow.addEventListener('mousewheel', fCancelScroll);\n\t\t}\n\n\t\tif( diff !== 0 ){\n\t\t\trequestAnimationFrame(fScroll);\n\t\t}\n\t}\n\n\treturn res;\n}\n"]} \ No newline at end of file +{"version":3,"file":"viewport.js","names":["MODULE_NAME","hasValue","orDefault","isWindow","isFunction","isElement","Deferred","assert","EasingFunctions","requestAnimationFrame","isInViewport","element","mustBeFullyInside","bb","viewportBounds","getBoundingClientRect","err","top","right","window","innerWidth","bottom","innerHeight","left","scrollTo","durationMs","offset","easing","scrollEvenIfFullyInViewport","cancelOnUserScroll","easeInOutCubic","res","elementIsWindow","self","elementInViewport","start","targetY","cancelled","startY","pageYOffset","Math","round","diff","fScroll","timestamp","time","progress","min","resolve","fCancelScroll","reject","Error","removeEventListener","addEventListener"],"sources":["viewport.js"],"mappings":";;;AAQA,MAAMA,YAAc,kBAMZC,SAAUC,UAAWC,SAAUC,WAAYC,UAAWC,SAAUC,WAAa,oBAC7EC,oBAAsB,wBACtBC,0BAA4B,qBA0B7B,SAASC,aAAaC,EAASC,GAAkB,GAGvD,IAAIC,EAQAC,EAVJF,EAAoBV,UAAUU,GAAmB,EAAO,QAGxD,IACCC,EAAKF,EAAQI,uBAId,CAHE,MAAMC,GAEP,OAAO,CACR,CAmBA,OAfCF,EADGF,EACc,CAChBK,IAAK,EACLC,MAAQC,OAAOC,WACfC,OAASF,OAAOG,YAChBC,KAAO,GAGS,CAChBN,IAA8B,GAAtBJ,EAAGQ,OAASR,EAAGI,KACvBC,MAASC,OAAOC,YAAcP,EAAGK,MAAQL,EAAGU,MAAS,EACrDF,OAAUF,OAAOG,aAAeT,EAAGQ,OAASR,EAAGI,KAAQ,EACvDM,KAA+B,GAAtBV,EAAGK,MAAQL,EAAGU,OAKxBV,EAAGI,KAAOH,EAAeG,KACzBJ,EAAGK,OAASJ,EAAeI,OAC3BL,EAAGU,MAAQT,EAAeS,MAC1BV,EAAGQ,QAAUP,EAAeO,MAE9B,QAyCO,SAASG,SAASb,EAASc,EAAW,IAAMC,EAAO,EAAGC,EAAO,iBAAkBC,GAA4B,EAAOC,GAAmB,GAC3IJ,EAAavB,UAAUuB,EAAY,IAAM,OACzCC,EAASxB,UAAUwB,EAAQ,EAAG,OAC9BC,EAASzB,UAAUyB,EAAQ,iBAAkB,OAC7CC,EAA8B1B,UAAU0B,GAA6B,EAAO,QAC5EC,EAAqB3B,UAAU2B,GAAoB,EAAO,QAE1DtB,OAAOF,UAAUM,IAAYR,SAASQ,GAAU,wCAChDJ,OAAOkB,EAAa,EAAG,8CAKtBE,EAHIvB,WAAWI,gBAAgBmB,IAGtBnB,gBAAgBmB,GAFhBnB,gBAAgBsB,eAK1B,MACCC,EAAM,IAAIzB,SACV0B,EAAmBrB,EAAQsB,OAAStB,EAIrC,IAAIuB,GAAoBF,GAA0BtB,aAAaC,GAAS,GAGxE,IACCA,EAAQI,uBAGT,CAFE,MAAMC,GACPkB,GAAoB,CACrB,CAEA,GAAIN,IAAgCM,EAAmB,CACtD,IAAIC,EAAOC,EAASC,GAAY,EAChC,MAAMC,EAASnB,OAAOoB,YAGrBH,EADGJ,EACON,EAEAP,OAAOoB,YAAc5B,EAAQI,wBAAwBE,IAAMuB,KAAKC,MAAMtB,OAAOG,YAAc,GAAKI,EAG3G,MACCgB,EAAON,EAAUE,EACjBK,EAAU,SAASC,GAClB,IAAKP,EAAW,CACVpC,SAASkC,KACbA,EAAQS,GAGT,MACCC,EAAOD,EAAYT,EACnBW,EAAWnB,EAAOa,KAAKO,IAAIF,EAAOpB,EAAY,IAG/CN,OAAOK,SAAS,EAAGc,EAAUI,EAAOI,GAE/BD,EAAOpB,GAAgBqB,EAAW,EACtCrC,sBAAsBkC,GAEtBZ,EAAIiB,SAEN,CACD,EAGD,GAAInB,EAAoB,CACvB,MAAMoB,EAAgB,WACrBZ,GAAY,EACZN,EAAImB,OAAO,IAAIC,MAAM,cACrBhC,OAAOiC,oBAAoB,iBAAkBH,GAC7C9B,OAAOiC,oBAAoB,aAAcH,EAC1C,EAEA9B,OAAOkC,iBAAiB,iBAAkBJ,GAC1C9B,OAAOkC,iBAAiB,aAAcJ,EACvC,CAEa,IAATP,GACHjC,sBAAsBkC,EAExB,CAEA,OAAOZ,CACR","sourcesContent":["/*!\n * Module Viewport\n */\n\n/**\n * @namespace Viewport\n */\n\nconst MODULE_NAME = 'Viewport';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {hasValue, orDefault, isWindow, isFunction, isElement, Deferred, assert} from './basic.js';\nimport {EasingFunctions} from './animation.js';\nimport {requestAnimationFrame} from './timers.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Viewport:isInViewport\n */\n\n/**\n * Returns if the current element is visible in the window's viewport at the moment.\n * This method uses getBoundingClientRect(), which has to be supported by the browser, otherwise\n * the method will always return true.\n *\n * @param {HTMLElement} element - the element to check\n * @param {?Boolean} [mustBeFullyInside=false] - defines if the element has to be fully enclosed in the viewport, default is false\n * @returns {Boolean} true if in viewport\n *\n * @memberof Viewport:isInViewport\n * @alias isInViewport\n * @example\n * if( isInViewport(document.querySelector('div.moving'), true) ){\n * ...\n * }\n */\nexport function isInViewport(element, mustBeFullyInside=false){\n\tmustBeFullyInside = orDefault(mustBeFullyInside, false, 'bool');\n\n\tlet bb;\n\ttry {\n\t\tbb = element.getBoundingClientRect();\n\t} catch(err){\n\t\t// if we cannot calculate position, we must assume the element is in\n\t\treturn true;\n\t}\n\n\tlet viewportBounds;\n\tif( mustBeFullyInside ){\n\t\tviewportBounds = {\n\t\t\ttop: 0,\n\t\t\tright : window.innerWidth,\n\t\t\tbottom : window.innerHeight,\n\t\t\tleft : 0\n\t\t};\n\t} else {\n\t\tviewportBounds = {\n\t\t\ttop : -(bb.bottom - bb.top) + 1,\n\t\t\tright : (window.innerWidth + (bb.right - bb.left)) + 1,\n\t\t\tbottom : (window.innerHeight + (bb.bottom - bb.top)) + 1,\n\t\t\tleft : -(bb.right - bb.left) + 1\n\t\t};\n\t}\n\n\treturn (\n\t\tbb.top >= viewportBounds.top &&\n\t\tbb.right <= viewportBounds.right &&\n\t\tbb.left >= viewportBounds.left &&\n\t\tbb.bottom <= viewportBounds.bottom\n\t);\n}\n\n\n\n/**\n * @namespace Viewport:scrollTo\n */\n\n/**\n * Scrolls the viewport to the element's position (first pixel at half viewport height).\n * Does not do anything if target element is already fully in viewport, unless scrollEvenIfFullyInViewport is set to\n * true. Uses getBoundingClientRect to measure viewport check, scrolls always if missing.\n *\n * If you use this function on a window, the offset is directly used as scrollTop, so this function may also be used for\n * things like back to top buttons.\n *\n * Scrolls may be cancelled by setting cancelOnUserScroll to true, but keep in mind, that this will only work\n * with mousewheels and (maybe) touchpads on modern browsers. No keyboard or scrollbar support yet.\n * The root of the problem is that a user scroll is indistinguishable from a js-triggered scroll,\n * since both trigger the scroll event and look exactly the same. So we have to use exotic\n * and specific events like mousewheel and DOMMouseScroll. So, please, use cancelOnUserScroll only\n * as a convenience option and not as a must.\n *\n *\n * @param {HTMLElement|Window} element - the element to scroll to or the window to scroll within\n * @param {?Number} [durationMs=1000] - duration of the scrolling animation\n * @param {?Number} [offset=0] - offset from the viewport center to apply to the end position\n * @param {?String} [easing='easeInOutCubic'] - easing function to use, can be any of Animation.EasingFunctions\n * @param {?Boolean} [scrollEvenIfFullyInViewport=false] - if true, forces method to always scroll no matter the element's position\n * @param {?Boolean} [cancelOnUserScroll=false] - if true, scrolling animation will immediately be canceled on manual user scroll, return value will not resolve in that case\n * @throws error if element is not usable or if durationMs is <= 0\n * @returns {Deferred} resolves when scroll complete, rejects if scroll fails or is cancelled\n *\n * @memberof Viewport:scrollTo\n * @alias scrollTo\n * @see EasingFunctions\n * @example\n * document.querySelector('a.jumpitem').addEventListener('click', function(){ scrollTo(document.querySelector('.jumptarget'), function(){ alert('scrolled!'); }, 500, -100, true); });\n * scrollTo(document.querySelector('.jumptarget'), function(){ alert('Not triggered if user uses mousewheel.'); }, 5000, -0, false, true);\n * scrollTo(window, null, 500, 0, false, true);\n */\nexport function scrollTo(element, durationMs=1000, offset=0, easing='easeInOutCubic', scrollEvenIfFullyInViewport=false, cancelOnUserScroll=false){\n\tdurationMs = orDefault(durationMs, 1000, 'int');\n\toffset = orDefault(offset, 0, 'int');\n\teasing = orDefault(easing, 'easeInOutCubic', 'str');\n\tscrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool');\n\tcancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool');\n\n\tassert(isElement(element) || isWindow(element), `${MODULE_NAME}:scrollTo | element unusable`);\n\tassert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`);\n\n\tif( !isFunction(EasingFunctions[easing]) ){\n\t\teasing = EasingFunctions.easeInOutCubic;\n\t} else {\n\t\teasing = EasingFunctions[easing];\n\t}\n\n\tconst\n\t\tres = new Deferred(),\n\t\telementIsWindow = (element.self === element)\n\t;\n\n\t// the window itself is considered not to be in viewport\n\tlet elementInViewport = elementIsWindow ? false : isInViewport(element, true);\n\n\t// in this case missing support for bounding rects should result in scrolling\n\ttry {\n\t\telement.getBoundingClientRect();\n\t} catch(err){\n\t\telementInViewport = false;\n\t}\n\n\tif( scrollEvenIfFullyInViewport || !elementInViewport ){\n\t\tlet start, targetY, cancelled = false;\n\t\tconst startY = window.pageYOffset;\n\n\t\tif( elementIsWindow ){\n\t\t\ttargetY = offset;\n\t\t} else {\n\t\t\ttargetY = window.pageYOffset + element.getBoundingClientRect().top - Math.round(window.innerHeight / 2) + offset;\n\t\t}\n\n\t\tconst\n\t\t\tdiff = targetY - startY,\n\t\t\tfScroll = function(timestamp){\n\t\t\t\tif( !cancelled ){\n\t\t\t\t\tif( !hasValue(start) ){\n\t\t\t\t\t\tstart = timestamp;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst\n\t\t\t\t\t\ttime = timestamp - start,\n\t\t\t\t\t\tprogress = easing(Math.min(time / durationMs, 1))\n\t\t\t\t\t;\n\n\t\t\t\t\twindow.scrollTo(0, startY + (diff * progress));\n\n\t\t\t\t\tif( (time < durationMs) && (progress < 1) ){\n\t\t\t\t\t\trequestAnimationFrame(fScroll)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres.resolve();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t;\n\n\t\tif( cancelOnUserScroll ){\n\t\t\tconst fCancelScroll = function(){\n\t\t\t\tcancelled = true;\n\t\t\t\tres.reject(new Error('cancelled'));\n\t\t\t\twindow.removeEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\t\twindow.removeEventListener('mousewheel', fCancelScroll);\n\t\t\t};\n\n\t\t\twindow.addEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\twindow.addEventListener('mousewheel', fCancelScroll);\n\t\t}\n\n\t\tif( diff !== 0 ){\n\t\t\trequestAnimationFrame(fScroll);\n\t\t}\n\t}\n\n\treturn res;\n}\n"]} \ No newline at end of file diff --git a/docs/documentation/Animation.html b/docs/documentation/Animation.html index 8d9af35b..47f4389c 100644 --- a/docs/documentation/Animation.html +++ b/docs/documentation/Animation.html @@ -113,13 +113,13 @@

Animation


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Animation_EasingFunctions.html b/docs/documentation/Animation_EasingFunctions.html index 8c3d119a..e2b58b82 100644 --- a/docs/documentation/Animation_EasingFunctions.html +++ b/docs/documentation/Animation_EasingFunctions.html @@ -202,13 +202,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Animation_transition.html b/docs/documentation/Animation_transition.html index d47a7c23..a74b2d82 100644 --- a/docs/documentation/Animation_transition.html +++ b/docs/documentation/Animation_transition.html @@ -444,13 +444,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Arrays.html b/docs/documentation/Arrays.html index 1e8cc4ad..f9e9dbf1 100644 --- a/docs/documentation/Arrays.html +++ b/docs/documentation/Arrays.html @@ -113,13 +113,13 @@

Arrays


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Arrays_removeFrom.html b/docs/documentation/Arrays_removeFrom.html index ade2cd5f..0692518a 100644 --- a/docs/documentation/Arrays_removeFrom.html +++ b/docs/documentation/Arrays_removeFrom.html @@ -414,13 +414,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic.html b/docs/documentation/Basic.html index 8f5a890c..b900f679 100644 --- a/docs/documentation/Basic.html +++ b/docs/documentation/Basic.html @@ -113,13 +113,13 @@

Basic


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_Deferred.html b/docs/documentation/Basic_Deferred.html index c056b230..85203cab 100644 --- a/docs/documentation/Basic_Deferred.html +++ b/docs/documentation/Basic_Deferred.html @@ -70,7 +70,7 @@

Basic:Deferred

Source:
@@ -159,7 +159,7 @@

(static) Def
Source:
@@ -210,13 +210,13 @@

Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_Observable.html b/docs/documentation/Basic_Observable.html index 5fabf150..fb3acc4b 100644 --- a/docs/documentation/Basic_Observable.html +++ b/docs/documentation/Basic_Observable.html @@ -70,7 +70,7 @@

Basic:Observable

Source:
@@ -147,7 +147,7 @@

(static) O
Source:
@@ -191,13 +191,13 @@

Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_assert.html b/docs/documentation/Basic_assert.html index 9eda3df5..0d507e6e 100644 --- a/docs/documentation/Basic_assert.html +++ b/docs/documentation/Basic_assert.html @@ -326,13 +326,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_attempt.html b/docs/documentation/Basic_attempt.html index 32b43f37..c9850d79 100644 --- a/docs/documentation/Basic_attempt.html +++ b/docs/documentation/Basic_attempt.html @@ -291,13 +291,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_getType.html b/docs/documentation/Basic_getType.html index 7bb8e30e..26f56972 100644 --- a/docs/documentation/Basic_getType.html +++ b/docs/documentation/Basic_getType.html @@ -115,7 +115,7 @@

getType

Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on -useful frontend types like "htmldocument", "htmlelement" and "nodelist"

+useful frontend types like "htmldocument", "htmlelement", "htmlcollection" and "nodelist"

Types:

  • "undefined"
  • @@ -139,6 +139,7 @@

    getType"weakmap"
  • "htmldocument"
  • "htmlelement"
  • +
  • "htmlcollection"
  • "nodelist"
  • "window"
@@ -246,7 +247,7 @@
Parameters:
Source:
@@ -317,13 +318,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_hasMembers.html b/docs/documentation/Basic_hasMembers.html index c8d351b3..495c92da 100644 --- a/docs/documentation/Basic_hasMembers.html +++ b/docs/documentation/Basic_hasMembers.html @@ -369,13 +369,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_hasValue.html b/docs/documentation/Basic_hasValue.html index 895c5966..407d9045 100644 --- a/docs/documentation/Basic_hasValue.html +++ b/docs/documentation/Basic_hasValue.html @@ -293,13 +293,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isA.html b/docs/documentation/Basic_isA.html index dd6e9f93..c94d1bb9 100644 --- a/docs/documentation/Basic_isA.html +++ b/docs/documentation/Basic_isA.html @@ -70,7 +70,7 @@

Basic:isA

Source:
@@ -230,7 +230,7 @@
Parameters:
Source:
@@ -306,13 +306,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isArray.html b/docs/documentation/Basic_isArray.html new file mode 100644 index 00000000..4eb5c69f --- /dev/null +++ b/docs/documentation/Basic_isArray.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isArray + + + + + + + + + + +
+ +

Namespace: Basic:isArray

+ + + + + + +
+ +
+ +

Basic:isArray

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isArray(value) → {Boolean}

+ + + + + +
+

Returns if a value is an array.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is an array +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isArray(val) ){
+  val.push('foobar');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isBigInt.html b/docs/documentation/Basic_isBigInt.html new file mode 100644 index 00000000..54a2b547 --- /dev/null +++ b/docs/documentation/Basic_isBigInt.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isBigInt + + + + + + + + + + +
+ +

Namespace: Basic:isBigInt

+ + + + + + +
+ +
+ +

Basic:isBigInt

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isBigInt(value) → {Boolean}

+ + + + + +
+

Returns if a value is a BigInt value.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a BigInt +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isBigInt(val) ){
+  console.log('this is a really huge number!');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isBoolean.html b/docs/documentation/Basic_isBoolean.html new file mode 100644 index 00000000..76785909 --- /dev/null +++ b/docs/documentation/Basic_isBoolean.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isBoolean + + + + + + + + + + +
+ +

Namespace: Basic:isBoolean

+ + + + + + +
+ +
+ +

Basic:isBoolean

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isBoolean(value) → {Boolean}

+ + + + + +
+

Returns if a value is a boolean value.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a boolean +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isBoolean(val) ){
+  console.log('val must be either true or false');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isCollection.html b/docs/documentation/Basic_isCollection.html new file mode 100644 index 00000000..a40d459a --- /dev/null +++ b/docs/documentation/Basic_isCollection.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isCollection + + + + + + + + + + +
+ +

Namespace: Basic:isCollection

+ + + + + + +
+ +
+ +

Basic:isCollection

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isCollection(value) → {Boolean}

+ + + + + +
+

Returns if a value is a collection of html elements.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a collection of html elements +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isCollection(val) ){
+  return val.item(0);
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isDate.html b/docs/documentation/Basic_isDate.html new file mode 100644 index 00000000..5d956fe9 --- /dev/null +++ b/docs/documentation/Basic_isDate.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isDate + + + + + + + + + + +
+ +

Namespace: Basic:isDate

+ + + + + + +
+ +
+ +

Basic:isDate

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isDate(value) → {Boolean}

+ + + + + +
+

Returns if a value is a date.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a date +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isDate(val) ){
+  return val.toISOString();
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isDocument.html b/docs/documentation/Basic_isDocument.html new file mode 100644 index 00000000..96372e47 --- /dev/null +++ b/docs/documentation/Basic_isDocument.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isDocument + + + + + + + + + + +
+ +

Namespace: Basic:isDocument

+ + + + + + +
+ +
+ +

Basic:isDocument

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isDocument(value) → {Boolean}

+ + + + + +
+

Returns if a value is an HTML document.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is an HTML document +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isDocument(val) ){
+  return val.body;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isElement.html b/docs/documentation/Basic_isElement.html index 33ab0153..108e25ee 100644 --- a/docs/documentation/Basic_isElement.html +++ b/docs/documentation/Basic_isElement.html @@ -70,7 +70,7 @@

Basic:isElement

Source:
@@ -208,7 +208,7 @@
Parameters:
Source:
@@ -279,13 +279,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isEmpty.html b/docs/documentation/Basic_isEmpty.html index 6796133d..f22a65a7 100644 --- a/docs/documentation/Basic_isEmpty.html +++ b/docs/documentation/Basic_isEmpty.html @@ -296,13 +296,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isError.html b/docs/documentation/Basic_isError.html new file mode 100644 index 00000000..d3dc41bf --- /dev/null +++ b/docs/documentation/Basic_isError.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isError + + + + + + + + + + +
+ +

Namespace: Basic:isError

+ + + + + + +
+ +
+ +

Basic:isError

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isError(value) → {Boolean}

+ + + + + +
+

Returns if a value is an error.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is an error +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isError(val) ){
+  return val.message;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isEventTarget.html b/docs/documentation/Basic_isEventTarget.html index 15eaac18..da5b0eb0 100644 --- a/docs/documentation/Basic_isEventTarget.html +++ b/docs/documentation/Basic_isEventTarget.html @@ -70,7 +70,7 @@

Basic:isEventTarget

Source:
@@ -210,7 +210,7 @@
Parameters:
Source:
@@ -281,13 +281,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isFloat.html b/docs/documentation/Basic_isFloat.html index 01b2d7a8..576a3924 100644 --- a/docs/documentation/Basic_isFloat.html +++ b/docs/documentation/Basic_isFloat.html @@ -70,7 +70,7 @@

Basic:isFloat

Source:
@@ -209,7 +209,7 @@
Parameters:
Source:
@@ -280,13 +280,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isFunction.html b/docs/documentation/Basic_isFunction.html new file mode 100644 index 00000000..0e37d81c --- /dev/null +++ b/docs/documentation/Basic_isFunction.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isFunction + + + + + + + + + + +
+ +

Namespace: Basic:isFunction

+ + + + + + +
+ +
+ +

Basic:isFunction

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isFunction(value) → {Boolean}

+ + + + + +
+

Returns if a value is a function.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a function +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isFunction(val) ){
+  val();
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isGenerator.html b/docs/documentation/Basic_isGenerator.html new file mode 100644 index 00000000..5a5b8012 --- /dev/null +++ b/docs/documentation/Basic_isGenerator.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isGenerator + + + + + + + + + + +
+ +

Namespace: Basic:isGenerator

+ + + + + + +
+ +
+ +

Basic:isGenerator

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isGenerator(value) → {Boolean}

+ + + + + +
+

Returns if a value is a generator.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a generator +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isGenerator(val) ){
+  return val.return(val.next().value);
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isInt.html b/docs/documentation/Basic_isInt.html index a1e6307e..38d7168d 100644 --- a/docs/documentation/Basic_isInt.html +++ b/docs/documentation/Basic_isInt.html @@ -70,7 +70,7 @@

Basic:isInt

Source:
@@ -208,7 +208,7 @@
Parameters:
Source:
@@ -279,13 +279,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isIterator.html b/docs/documentation/Basic_isIterator.html new file mode 100644 index 00000000..cff14b7b --- /dev/null +++ b/docs/documentation/Basic_isIterator.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isIterator + + + + + + + + + + +
+ +

Namespace: Basic:isIterator

+ + + + + + +
+ +
+ +

Basic:isIterator

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isIterator(value) → {Boolean}

+ + + + + +
+

Returns if a value is an iterator.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is an iterator +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isIterator(val) ){
+  return val.next().value;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isMap.html b/docs/documentation/Basic_isMap.html new file mode 100644 index 00000000..5b33619b --- /dev/null +++ b/docs/documentation/Basic_isMap.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isMap + + + + + + + + + + +
+ +

Namespace: Basic:isMap

+ + + + + + +
+ +
+ +

Basic:isMap

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isMap(value) → {Boolean}

+ + + + + +
+

Returns if a value is a map.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a map +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isMap(val) ){
+  return val.get('foobar');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isNaN.html b/docs/documentation/Basic_isNaN.html index ba347441..e6623da0 100644 --- a/docs/documentation/Basic_isNaN.html +++ b/docs/documentation/Basic_isNaN.html @@ -70,7 +70,7 @@

Basic:isNaN

Source:
@@ -266,7 +266,7 @@
Parameters:
Source:
@@ -337,13 +337,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isNodeList.html b/docs/documentation/Basic_isNodeList.html new file mode 100644 index 00000000..6e37e09a --- /dev/null +++ b/docs/documentation/Basic_isNodeList.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isNodeList + + + + + + + + + + +
+ +

Namespace: Basic:isNodeList

+ + + + + + +
+ +
+ +

Basic:isNodeList

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isNodeList(value) → {Boolean}

+ + + + + +
+

Returns if a value is a node list.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a node list +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isNodeList(val) ){
+  return val.item(0);
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isNumber.html b/docs/documentation/Basic_isNumber.html new file mode 100644 index 00000000..b3441957 --- /dev/null +++ b/docs/documentation/Basic_isNumber.html @@ -0,0 +1,304 @@ + + + + + JSDoc: Namespace: Basic:isNumber + + + + + + + + + + +
+ +

Namespace: Basic:isNumber

+ + + + + + +
+ +
+ +

Basic:isNumber

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isNumber(value) → {Boolean}

+ + + + + +
+

Returns if a value is a number.

+

Hint: to check numbers in more detail, use isInt, isFloat and isNaN

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a number +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isNumber(val) ){
+  result = val * 5;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isObject.html b/docs/documentation/Basic_isObject.html new file mode 100644 index 00000000..8eb0a1ce --- /dev/null +++ b/docs/documentation/Basic_isObject.html @@ -0,0 +1,300 @@ + + + + + JSDoc: Namespace: Basic:isObject + + + + + + + + + + +
+ +

Namespace: Basic:isObject

+ + + + + + +
+ +
+ +

Basic:isObject

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isObject(value) → {Boolean}

+ + + + + +
+

Returns if a value is an object.

+

Hint: if you explicitly want to check for a plain object, use isPlainObject

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is an object +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isObject(val) ){
+  val.newProperty = 'foobar';
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isPlainObject.html b/docs/documentation/Basic_isPlainObject.html index e3e7b4ec..4cbfde08 100644 --- a/docs/documentation/Basic_isPlainObject.html +++ b/docs/documentation/Basic_isPlainObject.html @@ -70,7 +70,7 @@

Basic:isPlainObject

Source:
@@ -212,7 +212,7 @@
Parameters:
Source:
@@ -281,13 +281,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isPotentialId.html b/docs/documentation/Basic_isPotentialId.html index 40f4e756..5f75d1dd 100644 --- a/docs/documentation/Basic_isPotentialId.html +++ b/docs/documentation/Basic_isPotentialId.html @@ -70,7 +70,7 @@

Basic:isPotentialId

Source:
@@ -391,7 +391,7 @@
Parameters:
Source:
@@ -465,13 +465,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isRegExp.html b/docs/documentation/Basic_isRegExp.html new file mode 100644 index 00000000..dc229088 --- /dev/null +++ b/docs/documentation/Basic_isRegExp.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isRegExp + + + + + + + + + + +
+ +

Namespace: Basic:isRegExp

+ + + + + + +
+ +
+ +

Basic:isRegExp

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isRegExp(value) → {Boolean}

+ + + + + +
+

Returns if a value is a regular expression.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a regular expression +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isRegExp(val) ){
+  return val.test('foobar');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isSelector.html b/docs/documentation/Basic_isSelector.html index faa73f87..35025e9a 100644 --- a/docs/documentation/Basic_isSelector.html +++ b/docs/documentation/Basic_isSelector.html @@ -70,7 +70,7 @@

Basic:isSelector

Source:
@@ -207,7 +207,7 @@
Parameters:
Source:
@@ -278,13 +278,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_isSet.html b/docs/documentation/Basic_isSet.html new file mode 100644 index 00000000..44e72b73 --- /dev/null +++ b/docs/documentation/Basic_isSet.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isSet + + + + + + + + + + +
+ +

Namespace: Basic:isSet

+ + + + + + +
+ +
+ +

Basic:isSet

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isSet(value) → {Boolean}

+ + + + + +
+

Returns if a value is a set.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a set +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isSet(val) ){
+  return val.has('foobar');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isString.html b/docs/documentation/Basic_isString.html new file mode 100644 index 00000000..9d6d7320 --- /dev/null +++ b/docs/documentation/Basic_isString.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isString + + + + + + + + + + +
+ +

Namespace: Basic:isString

+ + + + + + +
+ +
+ +

Basic:isString

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isString(value) → {Boolean}

+ + + + + +
+

Returns if a value is a string.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a string +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isString(val) ){
+  return prefix+val;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isSymbol.html b/docs/documentation/Basic_isSymbol.html new file mode 100644 index 00000000..7454a22a --- /dev/null +++ b/docs/documentation/Basic_isSymbol.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isSymbol + + + + + + + + + + +
+ +

Namespace: Basic:isSymbol

+ + + + + + +
+ +
+ +

Basic:isSymbol

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isSymbol(value) → {Boolean}

+ + + + + +
+

Returns if a value is a symbol.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a symbol +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isSymbol(val) ){
+  return val.description;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isWeakMap.html b/docs/documentation/Basic_isWeakMap.html new file mode 100644 index 00000000..eaae7182 --- /dev/null +++ b/docs/documentation/Basic_isWeakMap.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isWeakMap + + + + + + + + + + +
+ +

Namespace: Basic:isWeakMap

+ + + + + + +
+ +
+ +

Basic:isWeakMap

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isWeakMap(value) → {Boolean}

+ + + + + +
+

Returns if a value is a weak map.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a weak map +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isWeakMap(val) ){
+  return val.get('foobar');
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isWeakSet.html b/docs/documentation/Basic_isWeakSet.html new file mode 100644 index 00000000..a1801d1e --- /dev/null +++ b/docs/documentation/Basic_isWeakSet.html @@ -0,0 +1,299 @@ + + + + + JSDoc: Namespace: Basic:isWeakSet + + + + + + + + + + +
+ +

Namespace: Basic:isWeakSet

+ + + + + + +
+ +
+ +

Basic:isWeakSet

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isWeakSet(value) → {Boolean}

+ + + + + +
+

Returns if a value is a weak set.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a weak set +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isWeakSet(val) ){
+  return val.has(someSymbol);
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_isWindow.html b/docs/documentation/Basic_isWindow.html new file mode 100644 index 00000000..44267af8 --- /dev/null +++ b/docs/documentation/Basic_isWindow.html @@ -0,0 +1,292 @@ + + + + + JSDoc: Namespace: Basic:isWindow + + + + + + + + + + +
+ +

Namespace: Basic:isWindow

+ + + + + + +
+ +
+ +

Basic:isWindow

+ + +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

isWindow(value) → {Boolean}

+ + + + + +
+

Returns if a value is a window.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +* + + + +

the value to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Returns:
+ + +
+ true if value is a window +
+ + + +
+
+ Type +
+
+ +Boolean + + +
+
+ + + + +
Example
+ +
if( isWindow(val) ){
+  return val.location.origin;
+}
+ + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time) +
+ + + + + \ No newline at end of file diff --git a/docs/documentation/Basic_minMax.html b/docs/documentation/Basic_minMax.html index c2e1bc25..b80a2a66 100644 --- a/docs/documentation/Basic_minMax.html +++ b/docs/documentation/Basic_minMax.html @@ -70,7 +70,7 @@

Basic:minMax

Source:
@@ -254,7 +254,7 @@
Parameters:
Source:
@@ -335,13 +335,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_orDefault.html b/docs/documentation/Basic_orDefault.html index 04f2b701..8d81840c 100644 --- a/docs/documentation/Basic_orDefault.html +++ b/docs/documentation/Basic_orDefault.html @@ -415,13 +415,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Basic_size.html b/docs/documentation/Basic_size.html index 8d490a30..0e155eda 100644 --- a/docs/documentation/Basic_size.html +++ b/docs/documentation/Basic_size.html @@ -378,13 +378,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/CSS.html b/docs/documentation/CSS.html index e4d21ecb..4213525e 100644 --- a/docs/documentation/CSS.html +++ b/docs/documentation/CSS.html @@ -113,13 +113,13 @@

CSS


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/CSS_applyStyles.html b/docs/documentation/CSS_applyStyles.html index b5c75d5d..34ed3de5 100644 --- a/docs/documentation/CSS_applyStyles.html +++ b/docs/documentation/CSS_applyStyles.html @@ -448,13 +448,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/CSS_cssUrlValueToUrl.html b/docs/documentation/CSS_cssUrlValueToUrl.html index 77b3b527..2a58e6af 100644 --- a/docs/documentation/CSS_cssUrlValueToUrl.html +++ b/docs/documentation/CSS_cssUrlValueToUrl.html @@ -384,13 +384,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/CSS_cssValueToNumber.html b/docs/documentation/CSS_cssValueToNumber.html index be39a6f1..7c8de91c 100644 --- a/docs/documentation/CSS_cssValueToNumber.html +++ b/docs/documentation/CSS_cssValueToNumber.html @@ -281,13 +281,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/CSS_remByPx.html b/docs/documentation/CSS_remByPx.html index 084a2d2e..ee6d32e3 100644 --- a/docs/documentation/CSS_remByPx.html +++ b/docs/documentation/CSS_remByPx.html @@ -364,13 +364,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context.html b/docs/documentation/Context.html index 884cc573..1bb4863d 100644 --- a/docs/documentation/Context.html +++ b/docs/documentation/Context.html @@ -113,13 +113,13 @@

Context


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_browserSupportsHistoryManipulation.html b/docs/documentation/Context_browserSupportsHistoryManipulation.html index 3df0589e..138dc0f4 100644 --- a/docs/documentation/Context_browserSupportsHistoryManipulation.html +++ b/docs/documentation/Context_browserSupportsHistoryManipulation.html @@ -229,13 +229,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_contextHasHighDpi.html b/docs/documentation/Context_contextHasHighDpi.html index 9c1e0bbd..479b3b6d 100644 --- a/docs/documentation/Context_contextHasHighDpi.html +++ b/docs/documentation/Context_contextHasHighDpi.html @@ -230,13 +230,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_detectAppleDevice.html b/docs/documentation/Context_detectAppleDevice.html index 46607ce0..b339c890 100644 --- a/docs/documentation/Context_detectAppleDevice.html +++ b/docs/documentation/Context_detectAppleDevice.html @@ -303,13 +303,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_detectInteractionType.html b/docs/documentation/Context_detectInteractionType.html index 8b5645f6..fa579fe3 100644 --- a/docs/documentation/Context_detectInteractionType.html +++ b/docs/documentation/Context_detectInteractionType.html @@ -313,13 +313,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_getBrowserLanguage.html b/docs/documentation/Context_getBrowserLanguage.html index dea61a29..c8248a09 100644 --- a/docs/documentation/Context_getBrowserLanguage.html +++ b/docs/documentation/Context_getBrowserLanguage.html @@ -310,13 +310,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_getBrowserLocale.html b/docs/documentation/Context_getBrowserLocale.html index ef172e29..6ff98142 100644 --- a/docs/documentation/Context_getBrowserLocale.html +++ b/docs/documentation/Context_getBrowserLocale.html @@ -320,13 +320,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_getBrowserScrollbarWidth.html b/docs/documentation/Context_getBrowserScrollbarWidth.html index f511fdc3..91285dbf 100644 --- a/docs/documentation/Context_getBrowserScrollbarWidth.html +++ b/docs/documentation/Context_getBrowserScrollbarWidth.html @@ -231,13 +231,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Context_getLocale.html b/docs/documentation/Context_getLocale.html index 042ba82e..f5cd8168 100644 --- a/docs/documentation/Context_getLocale.html +++ b/docs/documentation/Context_getLocale.html @@ -363,13 +363,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Cookies.html b/docs/documentation/Cookies.html index 8f72ef23..083bc1d5 100644 --- a/docs/documentation/Cookies.html +++ b/docs/documentation/Cookies.html @@ -113,13 +113,13 @@

Cookies


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Cookies_getCookie.html b/docs/documentation/Cookies_getCookie.html index e976fe2d..3ea8c19d 100644 --- a/docs/documentation/Cookies_getCookie.html +++ b/docs/documentation/Cookies_getCookie.html @@ -313,13 +313,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Cookies_getCookies.html b/docs/documentation/Cookies_getCookies.html index eab66f27..e68a6de3 100644 --- a/docs/documentation/Cookies_getCookies.html +++ b/docs/documentation/Cookies_getCookies.html @@ -308,13 +308,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Cookies_removeCookie.html b/docs/documentation/Cookies_removeCookie.html index 08a49099..839c1ec5 100644 --- a/docs/documentation/Cookies_removeCookie.html +++ b/docs/documentation/Cookies_removeCookie.html @@ -331,13 +331,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Cookies_setCookie.html b/docs/documentation/Cookies_setCookie.html index b8b5a661..3ffd5874 100644 --- a/docs/documentation/Cookies_setCookie.html +++ b/docs/documentation/Cookies_setCookie.html @@ -372,13 +372,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements.html b/docs/documentation/Elements.html index ca29351d..859f24d2 100644 --- a/docs/documentation/Elements.html +++ b/docs/documentation/Elements.html @@ -113,13 +113,13 @@

Elements


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_createNode.html b/docs/documentation/Elements_createNode.html index a942f4a2..a0191c8c 100644 --- a/docs/documentation/Elements_createNode.html +++ b/docs/documentation/Elements_createNode.html @@ -70,7 +70,7 @@

Elements:createNode

Source:
@@ -319,7 +319,7 @@
Parameters:
Source:
@@ -396,13 +396,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_defineNode.html b/docs/documentation/Elements_defineNode.html index 0f28fc9a..60f88dfc 100644 --- a/docs/documentation/Elements_defineNode.html +++ b/docs/documentation/Elements_defineNode.html @@ -70,7 +70,7 @@

Elements:defineNode

Source:
@@ -314,7 +314,7 @@
Parameters:
Source:
@@ -413,13 +413,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_find.html b/docs/documentation/Elements_find.html index b7d38f82..f1e82f1e 100644 --- a/docs/documentation/Elements_find.html +++ b/docs/documentation/Elements_find.html @@ -70,7 +70,7 @@

Elements:find

Source:
@@ -319,7 +319,7 @@
Parameters:
Source:
@@ -421,13 +421,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_findOne.html b/docs/documentation/Elements_findOne.html index b7c83f28..c5526520 100644 --- a/docs/documentation/Elements_findOne.html +++ b/docs/documentation/Elements_findOne.html @@ -70,7 +70,7 @@

Elements:findOne

Source:
@@ -272,7 +272,7 @@
Parameters:
Source:
@@ -367,13 +367,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_findTextNodes.html b/docs/documentation/Elements_findTextNodes.html index 2fb8ee9d..322f2649 100644 --- a/docs/documentation/Elements_findTextNodes.html +++ b/docs/documentation/Elements_findTextNodes.html @@ -70,7 +70,7 @@

Elements:findTextNodes

Source:
@@ -309,7 +309,7 @@
Parameters:
Source:
@@ -398,13 +398,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_getData.html b/docs/documentation/Elements_getData.html index 4423165c..ae7bc2f4 100644 --- a/docs/documentation/Elements_getData.html +++ b/docs/documentation/Elements_getData.html @@ -70,7 +70,7 @@

Elements:getData

Source:
@@ -276,7 +276,7 @@
Parameters:
Source:
@@ -385,13 +385,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_getTextContent.html b/docs/documentation/Elements_getTextContent.html index 69c38de8..e92628d8 100644 --- a/docs/documentation/Elements_getTextContent.html +++ b/docs/documentation/Elements_getTextContent.html @@ -70,7 +70,7 @@

Elements:getTextContent

Source:
@@ -268,7 +268,7 @@
Parameters:
Source:
@@ -349,13 +349,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_insertNode.html b/docs/documentation/Elements_insertNode.html index d08b94bd..4b92922b 100644 --- a/docs/documentation/Elements_insertNode.html +++ b/docs/documentation/Elements_insertNode.html @@ -70,7 +70,7 @@

Elements:insertNode

Source:
@@ -312,7 +312,7 @@
Parameters:
Source:
@@ -394,13 +394,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_isInDom.html b/docs/documentation/Elements_isInDom.html index ba575722..a2991c01 100644 --- a/docs/documentation/Elements_isInDom.html +++ b/docs/documentation/Elements_isInDom.html @@ -70,7 +70,7 @@

Elements:isInDom

Source:
@@ -206,7 +206,7 @@
Parameters:
Source:
@@ -289,13 +289,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_measureHiddenDimensions.html b/docs/documentation/Elements_measureHiddenDimensions.html index 9a29477c..b02c5895 100644 --- a/docs/documentation/Elements_measureHiddenDimensions.html +++ b/docs/documentation/Elements_measureHiddenDimensions.html @@ -70,7 +70,7 @@

Elements:measureHiddenDimensions

Source:
@@ -355,7 +355,7 @@
Parameters:
Source:
@@ -444,13 +444,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_prime.html b/docs/documentation/Elements_prime.html index b677e8d6..c52202ab 100644 --- a/docs/documentation/Elements_prime.html +++ b/docs/documentation/Elements_prime.html @@ -70,7 +70,7 @@

Elements:prime

Source:
@@ -358,7 +358,7 @@
Parameters:
Source:
@@ -451,13 +451,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_removeData.html b/docs/documentation/Elements_removeData.html index 946763d8..8d479e22 100644 --- a/docs/documentation/Elements_removeData.html +++ b/docs/documentation/Elements_removeData.html @@ -70,7 +70,7 @@

Elements:removeData

Source:
@@ -269,7 +269,7 @@
Parameters:
Source:
@@ -375,13 +375,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_replaceNode.html b/docs/documentation/Elements_replaceNode.html index f2362242..6037925e 100644 --- a/docs/documentation/Elements_replaceNode.html +++ b/docs/documentation/Elements_replaceNode.html @@ -70,7 +70,7 @@

Elements:replaceNode

Source:
@@ -235,7 +235,7 @@
Parameters:
Source:
@@ -317,13 +317,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Elements_setData.html b/docs/documentation/Elements_setData.html index 1821869e..1380d8ef 100644 --- a/docs/documentation/Elements_setData.html +++ b/docs/documentation/Elements_setData.html @@ -70,7 +70,7 @@

Elements:setData

Source:
@@ -314,7 +314,7 @@
Parameters:
Source:
@@ -425,13 +425,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events.html b/docs/documentation/Events.html index 2ef94a71..9492ca90 100644 --- a/docs/documentation/Events.html +++ b/docs/documentation/Events.html @@ -113,13 +113,13 @@

Events


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_emit.html b/docs/documentation/Events_emit.html index d6299644..18e64530 100644 --- a/docs/documentation/Events_emit.html +++ b/docs/documentation/Events_emit.html @@ -70,7 +70,7 @@

Events:emit

Source:
@@ -396,7 +396,7 @@
Parameters:
Source:
@@ -525,13 +525,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_emitPostMessage.html b/docs/documentation/Events_emitPostMessage.html index 180040cd..c57b25fc 100644 --- a/docs/documentation/Events_emitPostMessage.html +++ b/docs/documentation/Events_emitPostMessage.html @@ -70,7 +70,7 @@

Events:emitPostMessage

Source:
@@ -347,7 +347,7 @@
Parameters:
Source:
@@ -432,13 +432,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_fire.html b/docs/documentation/Events_fire.html index 38bf917a..a5ee4b0d 100644 --- a/docs/documentation/Events_fire.html +++ b/docs/documentation/Events_fire.html @@ -70,7 +70,7 @@

Events:fire

Source:
@@ -318,7 +318,7 @@
Parameters:
Source:
@@ -447,13 +447,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_off.html b/docs/documentation/Events_off.html index dc4dc26a..987b81d2 100644 --- a/docs/documentation/Events_off.html +++ b/docs/documentation/Events_off.html @@ -70,7 +70,7 @@

Events:off

Source:
@@ -353,7 +353,7 @@
Parameters:
Source:
@@ -491,13 +491,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_offDetachedElements.html b/docs/documentation/Events_offDetachedElements.html index 2f99db75..c7e03b1f 100644 --- a/docs/documentation/Events_offDetachedElements.html +++ b/docs/documentation/Events_offDetachedElements.html @@ -70,7 +70,7 @@

Events:offDetachedElements

Source:
@@ -247,7 +247,7 @@
Parameters:
Source:
@@ -324,13 +324,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_offPostMessage.html b/docs/documentation/Events_offPostMessage.html index 66927b68..595e065f 100644 --- a/docs/documentation/Events_offPostMessage.html +++ b/docs/documentation/Events_offPostMessage.html @@ -70,7 +70,7 @@

Events:offPostMessage

Source:
@@ -401,7 +401,7 @@
Parameters:
Source:
@@ -482,13 +482,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_offSwipe.html b/docs/documentation/Events_offSwipe.html index 9bcb3d87..b34cd883 100644 --- a/docs/documentation/Events_offSwipe.html +++ b/docs/documentation/Events_offSwipe.html @@ -70,7 +70,7 @@

Events:offSwipe

Source:
@@ -349,7 +349,7 @@
Parameters:
Source:
@@ -479,13 +479,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_on.html b/docs/documentation/Events_on.html index cebef582..335e96d3 100644 --- a/docs/documentation/Events_on.html +++ b/docs/documentation/Events_on.html @@ -70,7 +70,7 @@

Events:on

Source:
@@ -387,7 +387,7 @@
Parameters:
Source:
@@ -527,13 +527,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_onDomReady.html b/docs/documentation/Events_onDomReady.html index 6743179e..aaa62b94 100644 --- a/docs/documentation/Events_onDomReady.html +++ b/docs/documentation/Events_onDomReady.html @@ -70,7 +70,7 @@

Events:onDomReady

Source:
@@ -206,7 +206,7 @@
Parameters:
Source:
@@ -255,13 +255,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_onPostMessage.html b/docs/documentation/Events_onPostMessage.html index 6a4e1020..9b69cbeb 100644 --- a/docs/documentation/Events_onPostMessage.html +++ b/docs/documentation/Events_onPostMessage.html @@ -70,7 +70,7 @@

Events:onPostMessage

Source:
@@ -287,7 +287,7 @@
Parameters:
Source:
@@ -370,13 +370,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_onSwipe.html b/docs/documentation/Events_onSwipe.html index 6c134d7f..ad68a980 100644 --- a/docs/documentation/Events_onSwipe.html +++ b/docs/documentation/Events_onSwipe.html @@ -70,7 +70,7 @@

Events:onSwipe

Source:
@@ -422,7 +422,7 @@
Parameters:
Source:
@@ -551,13 +551,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_once.html b/docs/documentation/Events_once.html index e93738f6..28705617 100644 --- a/docs/documentation/Events_once.html +++ b/docs/documentation/Events_once.html @@ -70,7 +70,7 @@

Events:once

Source:
@@ -347,7 +347,7 @@
Parameters:
Source:
@@ -487,13 +487,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_pause.html b/docs/documentation/Events_pause.html index f752bb9a..b069a4e3 100644 --- a/docs/documentation/Events_pause.html +++ b/docs/documentation/Events_pause.html @@ -70,7 +70,7 @@

Events:pause

Source:
@@ -350,7 +350,7 @@
Parameters:
Source:
@@ -484,13 +484,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Events_resume.html b/docs/documentation/Events_resume.html index 4fd44264..b9c3e2cc 100644 --- a/docs/documentation/Events_resume.html +++ b/docs/documentation/Events_resume.html @@ -70,7 +70,7 @@

Events:resume

Source:
@@ -307,7 +307,7 @@
Parameters:
Source:
@@ -440,13 +440,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Fonts.html b/docs/documentation/Fonts.html index 55237f60..b687e4a5 100644 --- a/docs/documentation/Fonts.html +++ b/docs/documentation/Fonts.html @@ -113,13 +113,13 @@

Fonts


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Fonts_waitForWebfonts.html b/docs/documentation/Fonts_waitForWebfonts.html index 19e51b36..bb93b284 100644 --- a/docs/documentation/Fonts_waitForWebfonts.html +++ b/docs/documentation/Fonts_waitForWebfonts.html @@ -388,13 +388,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Forms.html b/docs/documentation/Forms.html index b6337ff1..db0f91ed 100644 --- a/docs/documentation/Forms.html +++ b/docs/documentation/Forms.html @@ -113,13 +113,13 @@

Forms


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Forms_formDataToObject.html b/docs/documentation/Forms_formDataToObject.html index 8ddb3c7e..c82e5d45 100644 --- a/docs/documentation/Forms_formDataToObject.html +++ b/docs/documentation/Forms_formDataToObject.html @@ -318,13 +318,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Forms_objectToFormData.html b/docs/documentation/Forms_objectToFormData.html index 046f9d97..16fc17b3 100644 --- a/docs/documentation/Forms_objectToFormData.html +++ b/docs/documentation/Forms_objectToFormData.html @@ -309,13 +309,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Functions.html b/docs/documentation/Functions.html index 3fee6f24..d6f15090 100644 --- a/docs/documentation/Functions.html +++ b/docs/documentation/Functions.html @@ -113,13 +113,13 @@

Functions


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Functions_debounce.html b/docs/documentation/Functions_debounce.html index 222138f4..d7107719 100644 --- a/docs/documentation/Functions_debounce.html +++ b/docs/documentation/Functions_debounce.html @@ -313,13 +313,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Functions_defer.html b/docs/documentation/Functions_defer.html index ced8bb67..c22a0b70 100644 --- a/docs/documentation/Functions_defer.html +++ b/docs/documentation/Functions_defer.html @@ -346,13 +346,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Functions_kwargs.html b/docs/documentation/Functions_kwargs.html index a7b829d3..8f54d18f 100644 --- a/docs/documentation/Functions_kwargs.html +++ b/docs/documentation/Functions_kwargs.html @@ -365,13 +365,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Functions_throttle.html b/docs/documentation/Functions_throttle.html index 109863be..446694be 100644 --- a/docs/documentation/Functions_throttle.html +++ b/docs/documentation/Functions_throttle.html @@ -427,13 +427,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Images.html b/docs/documentation/Images.html index bd8e32a4..bdf1ab86 100644 --- a/docs/documentation/Images.html +++ b/docs/documentation/Images.html @@ -113,13 +113,13 @@

Images


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Images_loaded.html b/docs/documentation/Images_loaded.html index b2cc83e5..73dd98d8 100644 --- a/docs/documentation/Images_loaded.html +++ b/docs/documentation/Images_loaded.html @@ -352,13 +352,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Images_preload.html b/docs/documentation/Images_preload.html index a217a458..122aac10 100644 --- a/docs/documentation/Images_preload.html +++ b/docs/documentation/Images_preload.html @@ -291,13 +291,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction.html b/docs/documentation/Interaction.html index 4b55d238..9ef1af7b 100644 --- a/docs/documentation/Interaction.html +++ b/docs/documentation/Interaction.html @@ -113,13 +113,13 @@

Interaction


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_createSelection.html b/docs/documentation/Interaction_createSelection.html index a1a46147..7d9e86b5 100644 --- a/docs/documentation/Interaction_createSelection.html +++ b/docs/documentation/Interaction_createSelection.html @@ -390,13 +390,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_disableSelection.html b/docs/documentation/Interaction_disableSelection.html index 0ae82707..58a6d713 100644 --- a/docs/documentation/Interaction_disableSelection.html +++ b/docs/documentation/Interaction_disableSelection.html @@ -282,13 +282,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_enableSelection.html b/docs/documentation/Interaction_enableSelection.html index c31c150a..4daba428 100644 --- a/docs/documentation/Interaction_enableSelection.html +++ b/docs/documentation/Interaction_enableSelection.html @@ -283,13 +283,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_obfuscatePrivateMailToLink.html b/docs/documentation/Interaction_obfuscatePrivateMailToLink.html index ab04c521..8775639d 100644 --- a/docs/documentation/Interaction_obfuscatePrivateMailToLink.html +++ b/docs/documentation/Interaction_obfuscatePrivateMailToLink.html @@ -684,13 +684,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_obfuscatePrivateTelLink.html b/docs/documentation/Interaction_obfuscatePrivateTelLink.html index 35d45c4d..03205f23 100644 --- a/docs/documentation/Interaction_obfuscatePrivateTelLink.html +++ b/docs/documentation/Interaction_obfuscatePrivateTelLink.html @@ -524,13 +524,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_removeSelections.html b/docs/documentation/Interaction_removeSelections.html index 41c24c6d..1a4cbc48 100644 --- a/docs/documentation/Interaction_removeSelections.html +++ b/docs/documentation/Interaction_removeSelections.html @@ -212,13 +212,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_setTappedState.html b/docs/documentation/Interaction_setTappedState.html index 79618a3b..841d8ae3 100644 --- a/docs/documentation/Interaction_setTappedState.html +++ b/docs/documentation/Interaction_setTappedState.html @@ -388,13 +388,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Interaction_setupAutoTappedStates.html b/docs/documentation/Interaction_setupAutoTappedStates.html index 232ab5d4..5ee537e5 100644 --- a/docs/documentation/Interaction_setupAutoTappedStates.html +++ b/docs/documentation/Interaction_setupAutoTappedStates.html @@ -467,13 +467,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Logging.html b/docs/documentation/Logging.html index 0bf1c359..04fc8c2b 100644 --- a/docs/documentation/Logging.html +++ b/docs/documentation/Logging.html @@ -113,13 +113,13 @@

Logging


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Logging_err.html b/docs/documentation/Logging_err.html index 465c4ddd..0ceaad5b 100644 --- a/docs/documentation/Logging_err.html +++ b/docs/documentation/Logging_err.html @@ -271,13 +271,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Logging_log.html b/docs/documentation/Logging_log.html index 3fa801d3..8d763ea9 100644 --- a/docs/documentation/Logging_log.html +++ b/docs/documentation/Logging_log.html @@ -301,13 +301,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Logging_warn.html b/docs/documentation/Logging_warn.html index ae40aade..a8aaf544 100644 --- a/docs/documentation/Logging_warn.html +++ b/docs/documentation/Logging_warn.html @@ -270,13 +270,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Logging_xlog.html b/docs/documentation/Logging_xlog.html index dada50f2..5a031a12 100644 --- a/docs/documentation/Logging_xlog.html +++ b/docs/documentation/Logging_xlog.html @@ -284,13 +284,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation.html b/docs/documentation/Navigation.html index b6e393b7..80305fa6 100644 --- a/docs/documentation/Navigation.html +++ b/docs/documentation/Navigation.html @@ -113,13 +113,13 @@

Navigation


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_changeCurrentUrl.html b/docs/documentation/Navigation_changeCurrentUrl.html index 55558b41..35fdd0d1 100644 --- a/docs/documentation/Navigation_changeCurrentUrl.html +++ b/docs/documentation/Navigation_changeCurrentUrl.html @@ -416,13 +416,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_offHistoryChange.html b/docs/documentation/Navigation_offHistoryChange.html index ddb83065..0b21897e 100644 --- a/docs/documentation/Navigation_offHistoryChange.html +++ b/docs/documentation/Navigation_offHistoryChange.html @@ -321,13 +321,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_onHistoryChange.html b/docs/documentation/Navigation_onHistoryChange.html index 25ccfac0..4e7de1d3 100644 --- a/docs/documentation/Navigation_onHistoryChange.html +++ b/docs/documentation/Navigation_onHistoryChange.html @@ -379,13 +379,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_openTab.html b/docs/documentation/Navigation_openTab.html index 716f538f..7a6e6f93 100644 --- a/docs/documentation/Navigation_openTab.html +++ b/docs/documentation/Navigation_openTab.html @@ -407,13 +407,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_openWindow.html b/docs/documentation/Navigation_openWindow.html index 51d63d83..d0385c45 100644 --- a/docs/documentation/Navigation_openWindow.html +++ b/docs/documentation/Navigation_openWindow.html @@ -423,13 +423,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_redirect.html b/docs/documentation/Navigation_redirect.html index db4295c2..b80b1e6a 100644 --- a/docs/documentation/Navigation_redirect.html +++ b/docs/documentation/Navigation_redirect.html @@ -450,13 +450,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Navigation_reload.html b/docs/documentation/Navigation_reload.html index 3b466393..27116a93 100644 --- a/docs/documentation/Navigation_reload.html +++ b/docs/documentation/Navigation_reload.html @@ -327,13 +327,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Objects.html b/docs/documentation/Objects.html index d88ebf83..31a7817c 100644 --- a/docs/documentation/Objects.html +++ b/docs/documentation/Objects.html @@ -113,13 +113,13 @@

Objects


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Objects_clone.html b/docs/documentation/Objects_clone.html index 99f13d28..1f065134 100644 --- a/docs/documentation/Objects_clone.html +++ b/docs/documentation/Objects_clone.html @@ -354,13 +354,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Objects_merge.html b/docs/documentation/Objects_merge.html index f9785652..2b49c88e 100644 --- a/docs/documentation/Objects_merge.html +++ b/docs/documentation/Objects_merge.html @@ -312,13 +312,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polling.html b/docs/documentation/Polling.html index 51387701..f14c3b70 100644 --- a/docs/documentation/Polling.html +++ b/docs/documentation/Polling.html @@ -113,13 +113,13 @@

Polling


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polling_poll.html b/docs/documentation/Polling_poll.html index 6a03783e..2398a5e7 100644 --- a/docs/documentation/Polling_poll.html +++ b/docs/documentation/Polling_poll.html @@ -515,13 +515,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polling_unpoll.html b/docs/documentation/Polling_unpoll.html index 5bc17d30..b6f9dad8 100644 --- a/docs/documentation/Polling_unpoll.html +++ b/docs/documentation/Polling_unpoll.html @@ -286,13 +286,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polyfills.html b/docs/documentation/Polyfills.html index 3c2ca452..f18b1822 100644 --- a/docs/documentation/Polyfills.html +++ b/docs/documentation/Polyfills.html @@ -113,13 +113,13 @@

Polyfills


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polyfills_polyfillArrayAt.html b/docs/documentation/Polyfills_polyfillArrayAt.html index 7b27bf43..40b485c0 100644 --- a/docs/documentation/Polyfills_polyfillArrayAt.html +++ b/docs/documentation/Polyfills_polyfillArrayAt.html @@ -214,13 +214,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polyfills_polyfillCustomEvent.html b/docs/documentation/Polyfills_polyfillCustomEvent.html index 41eb8ef5..8b0f1a91 100644 --- a/docs/documentation/Polyfills_polyfillCustomEvent.html +++ b/docs/documentation/Polyfills_polyfillCustomEvent.html @@ -213,13 +213,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polyfills_polyfillElementMatches.html b/docs/documentation/Polyfills_polyfillElementMatches.html index a22b4498..ade928b2 100644 --- a/docs/documentation/Polyfills_polyfillElementMatches.html +++ b/docs/documentation/Polyfills_polyfillElementMatches.html @@ -225,13 +225,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Polyfills_polyfillFetch.html b/docs/documentation/Polyfills_polyfillFetch.html index 835a85c1..82b6f3ca 100644 --- a/docs/documentation/Polyfills_polyfillFetch.html +++ b/docs/documentation/Polyfills_polyfillFetch.html @@ -287,13 +287,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Random.html b/docs/documentation/Random.html index 96d37d24..8d7cf99a 100644 --- a/docs/documentation/Random.html +++ b/docs/documentation/Random.html @@ -113,13 +113,13 @@

Random


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Random_randomNumber.html b/docs/documentation/Random_randomNumber.html index 007ed32e..a235f0a3 100644 --- a/docs/documentation/Random_randomNumber.html +++ b/docs/documentation/Random_randomNumber.html @@ -436,13 +436,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Random_randomUuid.html b/docs/documentation/Random_randomUuid.html index a44b73c9..84616f9d 100644 --- a/docs/documentation/Random_randomUuid.html +++ b/docs/documentation/Random_randomUuid.html @@ -314,13 +314,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests.html b/docs/documentation/Requests.html index a7c64cbd..e7f9438b 100644 --- a/docs/documentation/Requests.html +++ b/docs/documentation/Requests.html @@ -113,13 +113,13 @@

Requests


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_createCssRequest.html b/docs/documentation/Requests_createCssRequest.html index e61091fb..b1c4f9d3 100644 --- a/docs/documentation/Requests_createCssRequest.html +++ b/docs/documentation/Requests_createCssRequest.html @@ -70,7 +70,7 @@

Requests:createCssRequest

Source:
@@ -356,7 +356,7 @@
Parameters:
Source:
@@ -459,13 +459,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_createFetchRequest.html b/docs/documentation/Requests_createFetchRequest.html index 27e5e51c..f15d4b04 100644 --- a/docs/documentation/Requests_createFetchRequest.html +++ b/docs/documentation/Requests_createFetchRequest.html @@ -596,13 +596,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_createHtmlRequest.html b/docs/documentation/Requests_createHtmlRequest.html index 08d256bc..acfd3a74 100644 --- a/docs/documentation/Requests_createHtmlRequest.html +++ b/docs/documentation/Requests_createHtmlRequest.html @@ -70,7 +70,7 @@

Requests:createHtmlRequest

Source:
@@ -354,7 +354,7 @@
Parameters:
Source:
@@ -461,13 +461,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_createJsRequest.html b/docs/documentation/Requests_createJsRequest.html index 033ae4c8..63c1d61f 100644 --- a/docs/documentation/Requests_createJsRequest.html +++ b/docs/documentation/Requests_createJsRequest.html @@ -70,7 +70,7 @@

Requests:createJsRequest

Source:
@@ -358,7 +358,7 @@
Parameters:
Source:
@@ -461,13 +461,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_createJsonRequest.html b/docs/documentation/Requests_createJsonRequest.html index 4a3d91fa..02e5c0b0 100644 --- a/docs/documentation/Requests_createJsonRequest.html +++ b/docs/documentation/Requests_createJsonRequest.html @@ -450,13 +450,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_createRestfulJsonClient.html b/docs/documentation/Requests_createRestfulJsonClient.html index 1f336317..82760521 100644 --- a/docs/documentation/Requests_createRestfulJsonClient.html +++ b/docs/documentation/Requests_createRestfulJsonClient.html @@ -106,7 +106,7 @@

Methods

-

createRestfulJsonClient(baseUrl, baseOptionsopt, nullable, useNativeopt, strictopt, nullable) → {RestfulJsonClient}

+

createRestfulJsonClient(baseUrlopt, nullable, baseOptionsopt, nullable, useNativeopt, strictopt, nullable) → {RestfulJsonClient}

@@ -171,8 +171,12 @@
Parameters:
+ <optional>
+ + <nullable>
+ @@ -181,10 +185,12 @@
Parameters:
+ window.location.origin + -

the base URL for all queries, based on which final request URLs will be built, adding the paths

+

the base URL for all queries, based on which final request URLs will be built, adding the paths, may be absolute or relative to current origin

@@ -446,13 +452,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Requests_visitUrl.html b/docs/documentation/Requests_visitUrl.html index 7c425797..8de51fe2 100644 --- a/docs/documentation/Requests_visitUrl.html +++ b/docs/documentation/Requests_visitUrl.html @@ -70,7 +70,7 @@

Requests:visitUrl

Source:
@@ -358,7 +358,7 @@
Parameters:
Source:
@@ -438,13 +438,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings.html b/docs/documentation/Strings.html index 82bbd423..c32ad8f1 100644 --- a/docs/documentation/Strings.html +++ b/docs/documentation/Strings.html @@ -113,13 +113,13 @@

Strings


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_concat.html b/docs/documentation/Strings_concat.html index e1e6d2d2..906ae9a6 100644 --- a/docs/documentation/Strings_concat.html +++ b/docs/documentation/Strings_concat.html @@ -337,13 +337,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_format.html b/docs/documentation/Strings_format.html index f119a39f..5b4dad7c 100644 --- a/docs/documentation/Strings_format.html +++ b/docs/documentation/Strings_format.html @@ -327,13 +327,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_maskForHtml.html b/docs/documentation/Strings_maskForHtml.html index 45bbbb2b..cdd0bab8 100644 --- a/docs/documentation/Strings_maskForHtml.html +++ b/docs/documentation/Strings_maskForHtml.html @@ -286,13 +286,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_maskForRegEx.html b/docs/documentation/Strings_maskForRegEx.html index 10ee36ec..d9195bd0 100644 --- a/docs/documentation/Strings_maskForRegEx.html +++ b/docs/documentation/Strings_maskForRegEx.html @@ -278,13 +278,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_maskForSelector.html b/docs/documentation/Strings_maskForSelector.html index 4f779108..fa32423f 100644 --- a/docs/documentation/Strings_maskForSelector.html +++ b/docs/documentation/Strings_maskForSelector.html @@ -276,13 +276,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_replace.html b/docs/documentation/Strings_replace.html index 15ca15b6..89d05cb8 100644 --- a/docs/documentation/Strings_replace.html +++ b/docs/documentation/Strings_replace.html @@ -332,13 +332,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_slugify.html b/docs/documentation/Strings_slugify.html index 82ed8249..bb2a347b 100644 --- a/docs/documentation/Strings_slugify.html +++ b/docs/documentation/Strings_slugify.html @@ -337,13 +337,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_truncate.html b/docs/documentation/Strings_truncate.html index 6b44430b..2eaf28b3 100644 --- a/docs/documentation/Strings_truncate.html +++ b/docs/documentation/Strings_truncate.html @@ -385,13 +385,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Strings_unmaskFromHtml.html b/docs/documentation/Strings_unmaskFromHtml.html index 4a44356c..eef5481f 100644 --- a/docs/documentation/Strings_unmaskFromHtml.html +++ b/docs/documentation/Strings_unmaskFromHtml.html @@ -285,13 +285,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers.html b/docs/documentation/Timers.html index 05001430..5d78e4e6 100644 --- a/docs/documentation/Timers.html +++ b/docs/documentation/Timers.html @@ -113,13 +113,13 @@

Timers


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_cancelAnimationFrame.html b/docs/documentation/Timers_cancelAnimationFrame.html index 03c117bd..c5d2486d 100644 --- a/docs/documentation/Timers_cancelAnimationFrame.html +++ b/docs/documentation/Timers_cancelAnimationFrame.html @@ -264,13 +264,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_countermand.html b/docs/documentation/Timers_countermand.html index 44871843..67b598e4 100644 --- a/docs/documentation/Timers_countermand.html +++ b/docs/documentation/Timers_countermand.html @@ -327,13 +327,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_loop.html b/docs/documentation/Timers_loop.html index 2812e0c9..1c934ff8 100644 --- a/docs/documentation/Timers_loop.html +++ b/docs/documentation/Timers_loop.html @@ -393,13 +393,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_ploop.html b/docs/documentation/Timers_ploop.html index 9db2e852..64a64ec1 100644 --- a/docs/documentation/Timers_ploop.html +++ b/docs/documentation/Timers_ploop.html @@ -400,13 +400,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_pschedule.html b/docs/documentation/Timers_pschedule.html index 9c09364b..1e2a3e82 100644 --- a/docs/documentation/Timers_pschedule.html +++ b/docs/documentation/Timers_pschedule.html @@ -398,13 +398,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_requestAnimationFrame.html b/docs/documentation/Timers_requestAnimationFrame.html index b31c2a93..7e29819e 100644 --- a/docs/documentation/Timers_requestAnimationFrame.html +++ b/docs/documentation/Timers_requestAnimationFrame.html @@ -299,13 +299,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_reschedule.html b/docs/documentation/Timers_reschedule.html index c911b742..a2fc7f00 100644 --- a/docs/documentation/Timers_reschedule.html +++ b/docs/documentation/Timers_reschedule.html @@ -343,13 +343,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_schedule.html b/docs/documentation/Timers_schedule.html index 5987877c..14266ece 100644 --- a/docs/documentation/Timers_schedule.html +++ b/docs/documentation/Timers_schedule.html @@ -393,13 +393,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Timers_waitForRepaint.html b/docs/documentation/Timers_waitForRepaint.html index 8555a067..af8f8f7c 100644 --- a/docs/documentation/Timers_waitForRepaint.html +++ b/docs/documentation/Timers_waitForRepaint.html @@ -303,13 +303,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls.html b/docs/documentation/Urls.html index 75d3f68d..3944daff 100644 --- a/docs/documentation/Urls.html +++ b/docs/documentation/Urls.html @@ -113,13 +113,13 @@

Urls


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:32 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls_addCacheBuster.html b/docs/documentation/Urls_addCacheBuster.html index 26cc5d0d..2fb0b62c 100644 --- a/docs/documentation/Urls_addCacheBuster.html +++ b/docs/documentation/Urls_addCacheBuster.html @@ -342,13 +342,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls_addNextParameter.html b/docs/documentation/Urls_addNextParameter.html index b0ac445d..87df2de2 100644 --- a/docs/documentation/Urls_addNextParameter.html +++ b/docs/documentation/Urls_addNextParameter.html @@ -478,13 +478,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls_evaluateBaseDomain.html b/docs/documentation/Urls_evaluateBaseDomain.html index 16b879d0..2bffc9d1 100644 --- a/docs/documentation/Urls_evaluateBaseDomain.html +++ b/docs/documentation/Urls_evaluateBaseDomain.html @@ -339,13 +339,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls_urlAnchor.html b/docs/documentation/Urls_urlAnchor.html index cdd2679d..def4d2bc 100644 --- a/docs/documentation/Urls_urlAnchor.html +++ b/docs/documentation/Urls_urlAnchor.html @@ -342,13 +342,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls_urlParameter.html b/docs/documentation/Urls_urlParameter.html index 19899c1a..0e64a139 100644 --- a/docs/documentation/Urls_urlParameter.html +++ b/docs/documentation/Urls_urlParameter.html @@ -369,13 +369,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Urls_urlParameters.html b/docs/documentation/Urls_urlParameters.html index 564cf05d..e0d2f596 100644 --- a/docs/documentation/Urls_urlParameters.html +++ b/docs/documentation/Urls_urlParameters.html @@ -299,13 +299,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:32 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Viewport.html b/docs/documentation/Viewport.html index d82531aa..5cb12d33 100644 --- a/docs/documentation/Viewport.html +++ b/docs/documentation/Viewport.html @@ -113,13 +113,13 @@

Viewport


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:32 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Viewport_isInViewport.html b/docs/documentation/Viewport_isInViewport.html index be5c31d9..ef4150ad 100644 --- a/docs/documentation/Viewport_isInViewport.html +++ b/docs/documentation/Viewport_isInViewport.html @@ -336,13 +336,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/Viewport_scrollTo.html b/docs/documentation/Viewport_scrollTo.html index 097d11f9..bf91ccc2 100644 --- a/docs/documentation/Viewport_scrollTo.html +++ b/docs/documentation/Viewport_scrollTo.html @@ -530,13 +530,13 @@
Example

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:08 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/animation.js.html b/docs/documentation/animation.js.html index 56ee4ae5..32de98a7 100644 --- a/docs/documentation/animation.js.html +++ b/docs/documentation/animation.js.html @@ -309,13 +309,13 @@

Source: animation.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/arrays.js.html b/docs/documentation/arrays.js.html index b26b7c94..bfa85b89 100644 --- a/docs/documentation/arrays.js.html +++ b/docs/documentation/arrays.js.html @@ -40,7 +40,7 @@

Source: arrays.js

//###[ IMPORTS ]######################################################################################################## -import {assert, isA, isPlainObject, orDefault} from './basic.js'; +import {assert, isArray, isNumber, isString, isMap, isSet, isPlainObject, orDefault} from './basic.js'; @@ -103,9 +103,9 @@

Source: arrays.js

* => [1] */ export function removeFrom(target, from, to=null){ - assert(isA(target, 'array'), `${MODULE_NAME}:remove | target is no array`); + assert(isArray(target), `${MODULE_NAME}:remove | target is no array`); - if( isA(from, 'number') && (to !== true) ){ + if( isNumber(from) && (to !== true) ){ from = parseInt(from, 10); to = orDefault(to, null, 'int'); @@ -114,7 +114,7 @@

Source: arrays.js

target.length = (from < 0) ? (target.length + from) : from; return target.concat(rest); - } else if( isA(from, 'string') ){ + } else if( isString(from) ){ return target.reduce((reducedArray, item) => { if( `${item}` !== from ){ reducedArray.push(item); @@ -125,9 +125,9 @@

Source: arrays.js

let fromList; if( isPlainObject(from) ){ fromList = Object.values(from); - } else if( isA(from, 'map') ){ + } else if( isMap(from) ){ fromList = Array.from(from.values()); - } else if( isA(from, 'set') ){ + } else if( isSet(from) ){ fromList = Array.from(from.values()); } else { fromList = Array.from(from); @@ -158,13 +158,13 @@

Source: arrays.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/basic.js.html b/docs/documentation/basic.js.html index ea784793..9b2bf9dd 100644 --- a/docs/documentation/basic.js.html +++ b/docs/documentation/basic.js.html @@ -98,7 +98,7 @@

Source: basic.js

* if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); } */ export function attempt(closure){ - assert(isA(closure, 'function'), `${MODULE_NAME}:attempt | closure is no function`); + assert(isFunction(closure), `${MODULE_NAME}:attempt | closure is no function`); try { closure(); @@ -186,7 +186,7 @@

Source: basic.js

* => null */ export function size(target, countStringCharacters=true){ - if( isA(target?.values, 'function') ) return Array.from(target.values()).length; + if( isFunction(target?.values) ) return Array.from(target.values()).length; let res; switch( getType(target) ){ @@ -252,14 +252,14 @@

Source: basic.js

; Array.from(arguments).forEach(obj => { - if( isA(obj?.__additionalEmptyValues__, 'array') ){ + if( isArray(obj?.__additionalEmptyValues__) ){ emptyValues = emptyValues.concat(obj.__additionalEmptyValues__); } }); emptyValues = Array.from(new Set(emptyValues)); Array.from(arguments).forEach(obj => { - if( res && !isA(obj?.__additionalEmptyValues__, 'array') ){ + if( res && !isArray(obj?.__additionalEmptyValues__) ){ res = emptyValues.includes(obj); if( !res ){ @@ -346,7 +346,7 @@

Source: basic.js

if( hasValue(caster) ){ if( - !isA(caster, 'function') + !isFunction(caster) && ([ 'str', 'string', 'int', 'integer', @@ -368,7 +368,7 @@

Source: basic.js

} else if( ['arr', 'array'].includes(caster) ){ caster = function(value){ return [].concat(value); }; } - } else if( !isA(caster, 'function') ){ + } else if( !isFunction(caster) ){ caster = function(value){ return value; }; } } else { @@ -391,7 +391,7 @@

Source: basic.js

/** * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on - * useful frontend types like "htmldocument", "htmlelement" and "nodelist" + * useful frontend types like "htmldocument", "htmlelement", "htmlcollection" and "nodelist" * * Types: * - "undefined" @@ -415,6 +415,7 @@

Source: basic.js

* - "weakmap" * - "htmldocument" * - "htmlelement" + * - "htmlcollection" * - "nodelist" * - "window" * @@ -439,7 +440,7 @@

Source: basic.js

if( /^html.*element$/.test(deepType) ) return 'htmlelement'; if( /^.*iterator$/.test(deepType) ) return 'iterator'; - return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/) + return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/) ? deepType : ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value ; @@ -489,6 +490,7 @@

Source: basic.js

'weakmap', 'htmldocument', 'htmlelement', + 'htmlcollection', 'nodelist', 'window' ].includes(`${type}`.toLowerCase()) @@ -502,6 +504,80 @@

Source: basic.js

+/** + * @namespace Basic:isBoolean + */ + +/** + * Returns if a value is a boolean value. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a boolean + * + * @memberof Basic:isBoolean + * @alias isBoolean + * @example + * if( isBoolean(val) ){ + * console.log('val must be either true or false'); + * } + */ +export function isBoolean(value){ + return isA(value, 'boolean'); +} + + + +/** + * @namespace Basic:isNumber + */ + +/** + * Returns if a value is a number. + * + * Hint: to check numbers in more detail, use isInt, isFloat and isNaN + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a number + * + * @memberof Basic:isNumber + * @alias isNumber + * @see isInt + * @see isFloat + * @see isNaN + * @example + * if( isNumber(val) ){ + * result = val * 5; + * } + */ +export function isNumber(value){ + return isA(value, 'number'); +} + + + +/** + * @namespace Basic:isBigInt + */ + +/** + * Returns if a value is a BigInt value. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a BigInt + * + * @memberof Basic:isBigInt + * @alias isBigInt + * @example + * if( isBigInt(val) ){ + * console.log('this is a really huge number!'); + * } + */ +export function isBigInt(value){ + return isA(value, 'bigint'); +} + + + /** * @namespace Basic:isInt */ @@ -553,6 +629,137 @@

Source: basic.js

+/** + * @namespace Basic:isNaN + */ + +/** + * Returns if an expression is NaN or not. + * This method employs two different approaches: + * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something. + * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being + * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which + * inspects the expression, tries to cast or parse a number from it and returns the result. + * + * @param {*} expression - the expression to check + * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality + * @returns {Boolean} true if expression is NaN + * + * @memberof Basic:isNaN + * @alias isNaN + * @example + * if( !isNaN(suspiciousCalculatedValue) ){ + * return suspiciousCalculatedValue * 3; + * } + */ +export function isNaN(expression, checkForIdentity=true){ + checkForIdentity = orDefault(checkForIdentity, true, 'bool'); + + if( checkForIdentity ){ + return expression !== expression; + } else { + return isNaN(expression); + } +} + + + +/** + * @namespace Basic:isString + */ + +/** + * Returns if a value is a string. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a string + * + * @memberof Basic:isString + * @alias isString + * @example + * if( isString(val) ){ + * return prefix+val; + * } + */ +export function isString(value){ + return isA(value, 'string'); +} + + + +/** + * @namespace Basic:isSymbol + */ + +/** + * Returns if a value is a symbol. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a symbol + * + * @memberof Basic:isSymbol + * @alias isSymbol + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol + * @example + * if( isSymbol(val) ){ + * return val.description; + * } + */ +export function isSymbol(value){ + return isA(value, 'symbol'); +} + + + +/** + * @namespace Basic:isFunction + */ + +/** + * Returns if a value is a function. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a function + * + * @memberof Basic:isFunction + * @alias isFunction + * @example + * if( isFunction(val) ){ + * val(); + * } + */ +export function isFunction(value){ + return isA(value, 'function'); +} + + + +/** + * @namespace Basic:isObject + */ + +/** + * Returns if a value is an object. + * + * Hint: if you explicitly want to check for a plain object, use isPlainObject + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an object + * + * @memberof Basic:isObject + * @alias isObject + * @see isPlainObject + * @example + * if( isObject(val) ){ + * val.newProperty = 'foobar'; + * } + */ +export function isObject(value){ + return isA(value, 'object'); +} + + + /** * @namespace Basic:isPlainObject */ @@ -577,7 +784,7 @@

Source: basic.js

* const isParameterConfigObject = isPlainObject(param); */ export function isPlainObject(value){ - return isA(value, 'object') + return isObject(value) && hasValue(value) && (value.constructor === Object) && Object.prototype.toString.call(value) === '[object Object]' @@ -587,36 +794,260 @@

Source: basic.js

/** - * @namespace Basic:isNaN + * @namespace Basic:isArray */ /** - * Returns if an expression is NaN or not. - * This method employs two different approaches: - * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something. - * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being - * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which - * inspects the expression, tries to cast or parse a number from it and returns the result. + * Returns if a value is an array. * - * @param {*} expression - the expression to check - * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality - * @returns {Boolean} true if expression is NaN + * @param {*} value - the value to check + * @returns {Boolean} true if value is an array * - * @memberof Basic:isNaN - * @alias isNaN + * @memberof Basic:isArray + * @alias isArray * @example - * if( !isNaN(suspiciousCalculatedValue) ){ - * return suspiciousCalculatedValue * 3; + * if( isArray(val) ){ + * val.push('foobar'); * } */ -export function isNaN(expression, checkForIdentity=true){ - checkForIdentity = orDefault(checkForIdentity, true, 'bool'); +export function isArray(value){ + return isA(value, 'array'); +} - if( checkForIdentity ){ - return expression !== expression; - } else { - return isNaN(expression); - } + + +/** + * @namespace Basic:isDate + */ + +/** + * Returns if a value is a date. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a date + * + * @memberof Basic:isDate + * @alias isDate + * @example + * if( isDate(val) ){ + * return val.toISOString(); + * } + */ +export function isDate(value){ + return isA(value, 'date'); +} + + + +/** + * @namespace Basic:isError + */ + +/** + * Returns if a value is an error. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an error + * + * @memberof Basic:isError + * @alias isError + * @example + * if( isError(val) ){ + * return val.message; + * } + */ +export function isError(value){ + return isA(value, 'error'); +} + + + +/** + * @namespace Basic:isGenerator + */ + +/** + * Returns if a value is a generator. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a generator + * + * @memberof Basic:isGenerator + * @alias isGenerator + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator + * @example + * if( isGenerator(val) ){ + * return val.return(val.next().value); + * } + */ +export function isGenerator(value){ + return isA(value, 'generator'); +} + + + +/** + * @namespace Basic:isIterator + */ + +/** + * Returns if a value is an iterator. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an iterator + * + * @memberof Basic:isIterator + * @alias isIterator + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator + * @example + * if( isIterator(val) ){ + * return val.next().value; + * } + */ +export function isIterator(value){ + return isA(value, 'iterator'); +} + + + +/** + * @namespace Basic:isRegExp + */ + +/** + * Returns if a value is a regular expression. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a regular expression + * + * @memberof Basic:isRegExp + * @alias isRegExp + * @example + * if( isRegExp(val) ){ + * return val.test('foobar'); + * } + */ +export function isRegExp(value){ + return isA(value, 'regexp'); +} + + + +/** + * @namespace Basic:isSet + */ + +/** + * Returns if a value is a set. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a set + * + * @memberof Basic:isSet + * @alias isSet + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set + * @example + * if( isSet(val) ){ + * return val.has('foobar'); + * } + */ +export function isSet(value){ + return isA(value, 'set'); +} + + + +/** + * @namespace Basic:isWeakSet + */ + +/** + * Returns if a value is a weak set. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a weak set + * + * @memberof Basic:isWeakSet + * @alias isWeakSet + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet + * @example + * if( isWeakSet(val) ){ + * return val.has(someSymbol); + * } + */ +export function isWeakSet(value){ + return isA(value, 'weakset'); +} + + + +/** + * @namespace Basic:isMap + */ + +/** + * Returns if a value is a map. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a map + * + * @memberof Basic:isMap + * @alias isMap + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map + * @example + * if( isMap(val) ){ + * return val.get('foobar'); + * } + */ +export function isMap(value){ + return isA(value, 'map'); +} + + + +/** + * @namespace Basic:isWeakMap + */ + +/** + * Returns if a value is a weak map. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a weak map + * + * @memberof Basic:isWeakMap + * @alias isWeakMap + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap + * @example + * if( isWeakMap(val) ){ + * return val.get('foobar'); + * } + */ +export function isWeakMap(value){ + return isA(value, 'weakmap'); +} + + + +/** + * @namespace Basic:isDocument + */ + +/** + * Returns if a value is an HTML document. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an HTML document + * + * @memberof Basic:isDocument + * @alias isDocument + * @example + * if( isDocument(val) ){ + * return val.body; + * } + */ +export function isDocument(value){ + return isA(value, 'htmldocument'); } @@ -646,6 +1077,77 @@

Source: basic.js

+/** + * @namespace Basic:isCollection + */ + +/** + * Returns if a value is a collection of html elements. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a collection of html elements + * + * @memberof Basic:isCollection + * @alias isCollection + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection + * @example + * if( isCollection(val) ){ + * return val.item(0); + * } + */ +export function isCollection(value){ + return isA(value, 'htmlcollection'); +} + + + +/** + * @namespace Basic:isNodeList + */ + +/** + * Returns if a value is a node list. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a node list + * + * @memberof Basic:isNodeList + * @alias isNodeList + * @see https://developer.mozilla.org/en-US/docs/Web/API/NodeList + * @example + * if( isNodeList(val) ){ + * return val.item(0); + * } + */ +export function isNodeList(value){ + return isA(value, 'nodelist'); +} + + + +/** + * @namespace Basic:isWindow + */ + +/** + * Returns if a value is a window. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a window + * + * @memberof Basic:isWindow + * @alias isWindow + * @example + * if( isWindow(val) ){ + * return val.location.origin; + * } + */ +export function isWindow(value){ + return isA(value, 'window'); +} + + + /** * @namespace Basic:isEventTarget */ @@ -669,9 +1171,9 @@

Source: basic.js

*/ export function isEventTarget(value){ return hasValue(value) - && isA(value.addEventListener, 'function') - && isA(value.removeEventListener, 'function') - && isA(value.dispatchEvent, 'function') + && isFunction(value.addEventListener) + && isFunction(value.removeEventListener) + && isFunction(value.dispatchEvent) ; } @@ -937,7 +1439,7 @@

Source: basic.js

subscribe(subscription){ const __methodName__ = 'subscribe'; - assert(isA(subscription, 'function'), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`); + assert(isFunction(subscription), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`); if( this._subscriptions.indexOf(subscription) < 0 ){ this._subscriptions = [...this._subscriptions, subscription]; } @@ -962,13 +1464,13 @@

Source: basic.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/context.js.html b/docs/documentation/context.js.html index 4f396e5a..4fae02aa 100644 --- a/docs/documentation/context.js.html +++ b/docs/documentation/context.js.html @@ -40,7 +40,7 @@

Source: context.js

//###[ IMPORTS ]######################################################################################################## -import {hasValue, isA, orDefault, Observable} from './basic.js'; +import {hasValue, isFunction, isArray, orDefault, Observable} from './basic.js'; import {throttle} from './functions.js'; import {reschedule} from './timers.js'; @@ -99,8 +99,8 @@

Source: context.js

*/ export function browserSupportsHistoryManipulation(){ return hasValue(window.history) - && isA(window.history.pushState, 'function') - && isA(window.history.replaceState, 'function') + && isFunction(window.history.pushState) + && isFunction(window.history.replaceState) ; } @@ -313,7 +313,7 @@

Source: context.js

break; } - if( isA(additionalTest, 'function') ){ + if( isFunction(additionalTest) ){ deviceType = additionalTest(deviceType); } } @@ -348,7 +348,7 @@

Source: context.js

if( hasValue(window.navigator.languages) ){ const browserLanguages = Array.from(window.navigator.languages); - if( isA(browserLanguages, 'array') && (browserLanguages.length > 0) ){ + if( isArray(browserLanguages) && (browserLanguages.length > 0) ){ language = `${browserLanguages[0]}`; } } @@ -422,7 +422,7 @@

Source: context.js

isFallback : false }; - let langAttr = isA(element.getAttribute, 'function') ? element.getAttribute('lang') : null; + let langAttr = isFunction(element.getAttribute) ? element.getAttribute('lang') : null; if( !hasValue(langAttr) && hasValue(fallbackLanguage) ){ langAttr = `${fallbackLanguage}`; locale.isFallback = true; @@ -486,13 +486,13 @@

Source: context.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/cookies.js.html b/docs/documentation/cookies.js.html index 89506f56..151b3a60 100644 --- a/docs/documentation/cookies.js.html +++ b/docs/documentation/cookies.js.html @@ -40,7 +40,7 @@

Source: cookies.js

//###[ IMPORTS ]######################################################################################################## -import {assert, isA, orDefault, hasValue} from './basic.js'; +import {assert, isDate, orDefault, hasValue} from './basic.js'; import {warn} from './logging.js'; @@ -124,7 +124,7 @@

Source: cookies.js

options = normalizedOptions; if( hasValue(options.expires) ){ - if( !isA(options.expires, 'date') ){ + if( !isDate(options.expires) ){ options.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000)); } options.expires = options.expires.toUTCString(); @@ -356,13 +356,13 @@

Source: cookies.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/css.js.html b/docs/documentation/css.js.html index 4e96ece7..449f1d4d 100644 --- a/docs/documentation/css.js.html +++ b/docs/documentation/css.js.html @@ -40,7 +40,7 @@

Source: css.js

//###[ IMPORTS ]######################################################################################################## -import {assert, isA, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js'; +import {assert, isNumber, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js'; import {maskForRegEx} from './strings.js'; @@ -110,7 +110,7 @@

Source: css.js

} Object.entries({...styles}).forEach(([cssKey, cssValue]) => { - if( isA(cssValue, 'number') && (cssValue !== 0) ){ + if( isNumber(cssValue) && (cssValue !== 0) ){ styles[cssKey] = `${cssValue}px`; element.style.setProperty(cssKey, styles[cssKey]); } else if( !hasValue(cssValue) ){ @@ -271,13 +271,13 @@

Source: css.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/elements.js.html b/docs/documentation/elements.js.html index fe8526e9..f54aef31 100644 --- a/docs/documentation/elements.js.html +++ b/docs/documentation/elements.js.html @@ -40,7 +40,18 @@

Source: elements.js

//###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, isSelector, isElement, hasValue, assert, size, Deferred} from './basic.js'; +import { + orDefault, + isString, + isFunction, + isPlainObject, + isSelector, + isElement, + hasValue, + assert, + size, + Deferred +} from './basic.js'; import {randomUuid} from './random.js'; import {clone} from './objects.js'; import {onDomReady} from './events.js'; @@ -436,7 +447,7 @@

Source: elements.js

onlyFirstLevel = orDefault(onlyFirstLevel, false, 'bool'); - if( isA(target, 'string') ){ + if( isString(target) ){ target = createNode(target); } @@ -482,7 +493,7 @@

Source: elements.js

assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); - return isA(document.contains, 'function') ? document.contains(node) : document.body.contains(node); + return isFunction(document.contains) ? document.contains(node) : document.body.contains(node); } @@ -639,7 +650,7 @@

Source: elements.js

const appliedValues = {}; Object.entries(dataSet).forEach(([property, value]) => { - if( isA(value, 'function') ){ + if( isFunction(value) ){ value = value(); } @@ -885,7 +896,7 @@

Source: elements.js

export function findTextNodes(node, filter=null, onlyFirstLevel=false){ const __methodName__ = 'findTextNodes'; - filter = isA(filter, 'function') ? filter : () => true; + filter = isFunction(filter) ? filter : () => true; onlyFirstLevel = orDefault(onlyFirstLevel, false, 'bool'); assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); @@ -967,7 +978,7 @@

Source: elements.js

markerAttributesName = orDefault(markerAttributesName, 'primed', 'str'); assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); - assert(isA(init, 'function'), `${MODULE_NAME}:${__methodName__} | init is not a function`); + assert(isFunction(init), `${MODULE_NAME}:${__methodName__} | init is not a function`); const deferred = new Deferred(); @@ -979,8 +990,8 @@

Source: elements.js

if( hasValue(initResult) - && isA(initResult.then, 'function') - && isA(initResult.catch, 'function') + && isFunction(initResult.then) + && isFunction(initResult.catch) ){ initResult .then(resolution => { deferred.resolve(resolution); }) @@ -1108,13 +1119,13 @@

Source: elements.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/events.js.html b/docs/documentation/events.js.html index c1aaf482..ae3a80b7 100644 --- a/docs/documentation/events.js.html +++ b/docs/documentation/events.js.html @@ -40,7 +40,22 @@

Source: events.js

//###[ IMPORTS ]######################################################################################################## -import {assert, isA, isEventTarget, isPlainObject, isElement, orDefault, hasValue, isEmpty, isSelector} from './basic.js'; +import { + assert, + isFunction, + isString, + isArray, + isBoolean, + isObject, + isWindow, + isEventTarget, + isPlainObject, + isElement, + orDefault, + hasValue, + isEmpty, + isSelector +} from './basic.js'; import {slugify} from './strings.js'; import {removeFrom} from './arrays.js'; import {detectInteractionType} from './context.js'; @@ -113,7 +128,7 @@

Source: events.js

events = orDefault(events, [], 'arr'); assert(events.length > 0, `${MODULE_NAME}:${methodName} | no events provided`); if( !handlerIsOptional || hasValue(handler) ){ - assert(isA(handler, 'function'), `${MODULE_NAME}:${methodName} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${methodName} | handler is not a function`); } let @@ -122,7 +137,7 @@

Source: events.js

; targets.forEach((target, targetIndex) => { - if( isA(target, 'string') ){ + if( isString(target) ){ const ancestor = (targetIndex > 0) ? targets[targetIndex - 1] : null; delegatedTargetsAreSelectorsAndHaveAncestor &&= isSelector(target) && isEventTarget(ancestor); } else { @@ -329,7 +344,7 @@

Source: events.js

: ( isEventTarget(e.syntheticTarget) || ( - isA(e.syntheticTarget, 'array') + isArray(e.syntheticTarget) && isSelector(e.syntheticTarget[1]) ) ? ( @@ -574,8 +589,8 @@

Source: events.js

* @private */ function compileEventListenerOptions(options){ - if( isA(options, 'boolean') ) return options; - if( !isA(options, 'object') ) return null; + if( isBoolean(options) ) return options; + if( !isObject(options) ) return null; const supportedOptions = {}; @@ -617,7 +632,7 @@

Source: events.js

eventOptions = isPlainObject(eventOptions) ? eventOptions : {}; let e; - if( isA(EventConstructor, 'function') ){ + if( isFunction(EventConstructor) ){ if( isPlainObject(payload) ){ console.warn(`${MODULE_NAME}:${__methodName__} | can't add payload to event "${EventConstructor.name}", skipping`); } @@ -638,7 +653,7 @@

Source: events.js

e.syntheticTarget = syntheticTarget; e.syntheticTargetElements = [syntheticTarget] } else if( - isA(syntheticTarget, 'array') + isArray(syntheticTarget) && isEventTarget(syntheticTarget[0]) && isSelector(syntheticTarget[1]) ){ @@ -679,10 +694,10 @@

Source: events.js

* @private */ function resolvePostMessageTarget(target, method){ - target = isA(target, 'window') + target = isWindow(target) ? target : ( - isA(target?.contentWindow, 'window') + isWindow(target?.contentWindow) ? target.contentWindow : null ) @@ -1627,7 +1642,7 @@

Source: events.js

origin = orDefault(origin, '*', 'str'); messageType = `${messageType}`; - assert(isA(handler, 'function'), `${MODULE_NAME}:${__methodName__} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${__methodName__} | handler is not a function`); if( !hasValue(POST_MESSAGE_MAP.get(target)) ){ POST_MESSAGE_MAP.set(target, {}); @@ -1694,7 +1709,7 @@

Source: events.js

tryNativeRemoval = orDefault(tryNativeRemoval, true, 'bool'); if( hasValue(handler) ){ - assert(isA(handler, 'function'), `${MODULE_NAME}:${__methodName__} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${__methodName__} | handler is not a function`); } let removedCount = 0; @@ -1791,13 +1806,13 @@

Source: events.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/fonts.js.html b/docs/documentation/fonts.js.html index 989cb5ca..7cb245a0 100644 --- a/docs/documentation/fonts.js.html +++ b/docs/documentation/fonts.js.html @@ -161,13 +161,13 @@

Source: fonts.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/forms.js.html b/docs/documentation/forms.js.html index 19f69078..bf0dbfb3 100644 --- a/docs/documentation/forms.js.html +++ b/docs/documentation/forms.js.html @@ -40,7 +40,7 @@

Source: forms.js

//###[ IMPORTS ]######################################################################################################## -import {isA, isPlainObject, hasValue} from './basic.js'; +import {isFunction, isPlainObject, hasValue} from './basic.js'; @@ -102,9 +102,9 @@

Source: forms.js

// let's do duck-typing to allow polyfills if( - isA(formDataOrForm.append, 'function') - && isA(formDataOrForm.getAll, 'function') - && isA(formDataOrForm.entries, 'function') + isFunction(formDataOrForm.append) + && isFunction(formDataOrForm.getAll) + && isFunction(formDataOrForm.entries) ){ formData = formDataOrForm; } else { @@ -230,13 +230,13 @@

Source: forms.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/functions.js.html b/docs/documentation/functions.js.html index adc53978..bfb49714 100644 --- a/docs/documentation/functions.js.html +++ b/docs/documentation/functions.js.html @@ -40,7 +40,7 @@

Source: functions.js

//###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, assert, hasValue} from './basic.js'; +import {orDefault, isFunction, isPlainObject, assert, hasValue} from './basic.js'; import {schedule, reschedule} from './timers.js'; @@ -80,7 +80,7 @@

Source: functions.js

hasTrailingExecution = orDefault(hasTrailingExecution, false, 'bool'); assert(ms > 0, `${MODULE_NAME}:throttle | ms must be > 0`); - assert(isA(func, 'function'), `${MODULE_NAME}:throttle | no function given`); + assert(isFunction(func), `${MODULE_NAME}:throttle | no function given`); let frameHasStarted = false, @@ -142,7 +142,7 @@

Source: functions.js

ms = orDefault(ms, 0, 'int'); assert(ms > 0, `${MODULE_NAME}:debounce | ms must be > 0`); - assert(isA(func, 'function'), `${MODULE_NAME}:debounce | no function given`); + assert(isFunction(func), `${MODULE_NAME}:debounce | no function given`); let debounceTimer; @@ -175,7 +175,7 @@

Source: functions.js

export function defer(func, delay=1){ delay = orDefault(delay, 1, 'int'); - assert(isA(func, 'function'), `${MODULE_NAME}:defer | no function given`); + assert(isFunction(func), `${MODULE_NAME}:defer | no function given`); assert(delay > 0, `${MODULE_NAME}:defer | delay must be > 0`); return function(){ @@ -228,7 +228,7 @@

Source: functions.js

export function kwargs(func, defaults=null){ defaults = isPlainObject(defaults) ? defaults : {}; - assert(isA(func, 'function'), `${MODULE_NAME}:kwargs | no function given`); + assert(isFunction(func), `${MODULE_NAME}:kwargs | no function given`); const argNamesString = func.toString().match(/\(([^)]+)/)[1], @@ -278,13 +278,13 @@

Source: functions.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/global.html b/docs/documentation/global.html index 47b49ce7..fbe14e9f 100644 --- a/docs/documentation/global.html +++ b/docs/documentation/global.html @@ -790,7 +790,7 @@
Properties
Source:
@@ -1192,7 +1192,7 @@
Properties
Source:
@@ -1298,7 +1298,7 @@
Type:
Source:
@@ -1702,7 +1702,7 @@
Properties:
Source:
@@ -2940,7 +2940,7 @@
Properties
Source:
@@ -3342,7 +3342,7 @@
Properties
Source:
@@ -3451,7 +3451,7 @@
Type:
Source:
@@ -3823,7 +3823,7 @@
Properties
Source:
@@ -4184,7 +4184,7 @@
Properties
Source:
@@ -4290,7 +4290,7 @@
Type:
Source:
@@ -5280,7 +5280,7 @@
Properties:
Source:
@@ -7327,13 +7327,13 @@
Returns:

- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/images.js.html b/docs/documentation/images.js.html index 217e4960..5ec2f492 100644 --- a/docs/documentation/images.js.html +++ b/docs/documentation/images.js.html @@ -40,7 +40,7 @@

Source: images.js

//###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, assert, isEmpty, isElement, hasValue, Deferred} from './basic.js'; +import {orDefault, isArray, isPlainObject, assert, isEmpty, isElement, hasValue, Deferred} from './basic.js'; import {waitForRepaint} from './timers.js'; @@ -86,7 +86,7 @@

Source: images.js

; let newImages; - if( !isPlainObject(images) && !isA(images, 'array') ){ + if( !isPlainObject(images) && !isArray(images) ){ images = `${images}`; if( hasValue(PRELOADED_IMAGES.named[images]) ){ @@ -111,7 +111,7 @@

Source: images.js

}); PRELOADED_IMAGES.named = {...PRELOADED_IMAGES.named, ...newImages}; - } else if( isA(images, 'array') ){ + } else if( isArray(images) ){ newImages = []; images.forEach(value => { @@ -124,7 +124,7 @@

Source: images.js

PRELOADED_IMAGES.unnamed = Array.from(new Set(PRELOADED_IMAGES.unnamed.concat(newImages))); } - deferred.provision = (isA(newImages, 'array') && (newImages.length === 1)) ? newImages[0] : newImages; + deferred.provision = (isArray(newImages) && (newImages.length === 1)) ? newImages[0] : newImages; loaded(preloadedImages) .then(deferred.resolve) .catch(deferred.reject) @@ -274,13 +274,13 @@

Source: images.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/index.html b/docs/documentation/index.html index aaefdbfa..31521b18 100644 --- a/docs/documentation/index.html +++ b/docs/documentation/index.html @@ -259,13 +259,13 @@

Is This Any Good, Why Should I Use This?


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:31 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/interaction.js.html b/docs/documentation/interaction.js.html index dc9adcc7..89ab53f6 100644 --- a/docs/documentation/interaction.js.html +++ b/docs/documentation/interaction.js.html @@ -40,7 +40,7 @@

Source: interaction.js

//###[ IMPORTS ]######################################################################################################## -import {assert, isA, isElement, orDefault, hasValue, Deferred} from './basic.js'; +import {assert, isFunction, isElement, orDefault, hasValue, Deferred} from './basic.js'; import {findTextNodes} from './elements.js'; import {applyStyles} from './css.js'; @@ -102,7 +102,7 @@

Source: interaction.js

node.selectionStart = startOffset; node.selectionEnd = rangeText.length - endOffset; selectionText = rangeText.substring(node.selectionStart, node.selectionEnd); - } else if( isA(window.getSelection, 'function') ){ + } else if( isFunction(window.getSelection) ){ range = document.createRange(); range.selectNodeContents(node); @@ -164,7 +164,7 @@

Source: interaction.js

selection.removeAllRanges(); selection.addRange(range); selectionText = range.toString(); - } else if( isA(document.body.createTextRange, 'function') ){ + } else if( isFunction(document.body.createTextRange) ){ range = document.body.createTextRange(); range.moveToElementText(node); @@ -201,9 +201,9 @@

Source: interaction.js

* removeSelections(); */ export function removeSelections(){ - if( isA(window.getSelection, 'function') ){ + if( isFunction(window.getSelection) ){ window.getSelection().removeAllRanges(); - } else if( isA(document.getSelection, 'function') ){ + } else if( isFunction(document.getSelection) ){ document.getSelection().removeAllRanges(); } @@ -587,13 +587,13 @@

Source: interaction.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/logging.js.html b/docs/documentation/logging.js.html index a8ece4ce..4bf757c5 100644 --- a/docs/documentation/logging.js.html +++ b/docs/documentation/logging.js.html @@ -345,13 +345,13 @@

Source: logging.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/navigation.js.html b/docs/documentation/navigation.js.html index d6bf1bb0..d6c91309 100644 --- a/docs/documentation/navigation.js.html +++ b/docs/documentation/navigation.js.html @@ -41,7 +41,7 @@

Source: navigation.js

//###[ IMPORTS ]######################################################################################################## import {warn} from './logging.js'; -import {hasValue, orDefault, isPlainObject, isEmpty, isA, assert} from './basic.js'; +import {hasValue, orDefault, isPlainObject, isEmpty, isArray, isWindow, isFunction, assert} from './basic.js'; import {createNode} from './elements.js'; import {browserSupportsHistoryManipulation} from './context.js'; @@ -201,7 +201,7 @@

Source: navigation.js

const redirectForm = createNode('form', formAttributes); for( let paramName in postParams ){ - if( isA(postParams[paramName], 'array') ){ + if( isArray(postParams[paramName]) ){ postParams[paramName].forEach(val => { redirectForm.appendChild(createNode( 'input', @@ -311,7 +311,7 @@

Source: navigation.js

export function openWindow(url, options=null, parentWindow=null, tryAsPopup=false){ url = `${url}`; options = isPlainObject(options) ? options : null; - parentWindow = isA(parentWindow, 'window') ? parentWindow : window; + parentWindow = isWindow(parentWindow) ? parentWindow : window; tryAsPopup = orDefault(tryAsPopup, false, 'bool'); let windowName = ''; @@ -467,7 +467,7 @@

Source: navigation.js

clearOld = orDefault(clearOld, false, 'bool'); usePreviousState = orDefault(usePreviousState, false, 'bool'); - assert(isA(callback, 'function'), `${MODULE_NAME}:${__methodName__} | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:${__methodName__} | callback is no function`); if ( browserSupportsHistoryManipulation() ) { if( clearOld ){ @@ -524,7 +524,7 @@

Source: navigation.js

const __methodName__ = 'offHistoryChange'; if( hasValue(callback) ){ - assert(isA(callback, 'function'), `${MODULE_NAME}:${__methodName__} | callback is not a function`); + assert(isFunction(callback), `${MODULE_NAME}:${__methodName__} | callback is not a function`); const oldCallbackCount = HISTORY.popState.callbacks.length; HISTORY.popState.callbacks = HISTORY.popState.callbacks.reduce((cbs, cb) => { @@ -560,13 +560,13 @@

Source: navigation.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/objects.js.html b/docs/documentation/objects.js.html index f2dbc73f..c281c318 100644 --- a/docs/documentation/objects.js.html +++ b/docs/documentation/objects.js.html @@ -40,7 +40,7 @@

Source: objects.js

//###[ IMPORTS ]######################################################################################################## -import {getType, isA, orDefault} from './basic.js'; +import {getType, isFunction, isObject, orDefault} from './basic.js'; @@ -88,7 +88,7 @@

Source: objects.js

export function clone(target, deep=true){ deep = orDefault(deep, true, 'bool'); - if( isA(target?.clone, 'function') ){ + if( isFunction(target?.clone) ){ return target.clone(deep); } @@ -247,7 +247,7 @@

Source: objects.js

if( extension.hasOwnProperty(prop) ){ if( base.hasOwnProperty(prop) - && (isA(base[prop], 'object') && isA(extension[prop], 'object')) + && (isObject(base[prop]) && isObject(extension[prop])) && (Object.keys(extension[prop]).length > 0) ){ base[prop] = merge(base[prop], extension[prop]); @@ -270,13 +270,13 @@

Source: objects.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/polling.js.html b/docs/documentation/polling.js.html index 66027a3b..03e526bd 100644 --- a/docs/documentation/polling.js.html +++ b/docs/documentation/polling.js.html @@ -40,7 +40,7 @@

Source: polling.js

//###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, assert, hasValue} from './basic.js'; +import {orDefault, isFunction, isObject, assert, hasValue} from './basic.js'; import {loop, countermand} from './timers.js'; @@ -96,13 +96,13 @@

Source: polling.js

*/ export function poll(name, fCondition, fAction, fElseAction=null, newLoopMs=POLL_DEFAULT_LOOP_MS, useOwnTimer=false){ name = orDefault(name, '', 'str').trim(); - fElseAction = isA(fElseAction, 'function') ? fElseAction : () => {}; + fElseAction = isFunction(fElseAction) ? fElseAction : () => {}; newLoopMs = orDefault(newLoopMs, POLL_DEFAULT_LOOP_MS, 'int'); useOwnTimer = orDefault(useOwnTimer, false, 'bool'); assert(name !== '', `${MODULE_NAME}:poll | name is missing`); - assert(isA(fCondition, 'function'), `${MODULE_NAME}:poll | fCondition is not a function`); - assert(isA(fAction, 'function'), `${MODULE_NAME}:poll | fAction is not a function`); + assert(isFunction(fCondition), `${MODULE_NAME}:poll | fCondition is not a function`); + assert(isFunction(fAction), `${MODULE_NAME}:poll | fAction is not a function`); const newPoll = { name, @@ -196,7 +196,7 @@

Source: polling.js

* unpoll(pollBodyHeightAndStopIfHighEnough); */ export function unpoll(poll){ - const name = (isA(poll, 'object') && hasValue(poll.name)) ? `${poll.name}` : `${poll}`.trim(); + const name = (isObject(poll) && hasValue(poll.name)) ? `${poll.name}` : `${poll}`.trim(); if( name === '' ) return false; poll = POLLS.activePolls[name]; @@ -228,13 +228,13 @@

Source: polling.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/polyfills.js.html b/docs/documentation/polyfills.js.html index 86519a4f..c2619ea3 100644 --- a/docs/documentation/polyfills.js.html +++ b/docs/documentation/polyfills.js.html @@ -40,7 +40,7 @@

Source: polyfills.js

//###[ IMPORTS ]######################################################################################################## -import {assert, hasValue, isA, orDefault} from './basic.js'; +import {assert, hasValue, isFunction, orDefault} from './basic.js'; import {createFetchRequest} from './requests.js'; @@ -70,7 +70,7 @@

Source: polyfills.js

export function polyfillFetch(force=false){ force = orDefault(force, false, 'bool'); - if( force || !isA(window.fetch, 'function') ){ + if( force || !isFunction(window.fetch) ){ window.fetch = function(url, options=null){ return createFetchRequest(url, options).execute(); }; @@ -127,7 +127,7 @@

Source: polyfills.js

* => makes "window.CustomEvent" and "new CustomEvent()" available, if not already present */ export function polyfillCustomEvent(){ - if( isA(window.CustomEvent, 'function') ) return false; + if( isFunction(window.CustomEvent) ) return false; const CustomEvent = function(event, params){ params = params ?? {bubbles : false, cancelable : false, detail : undefined}; @@ -159,7 +159,7 @@

Source: polyfills.js

* => adds Array.prototype.at if not already defined */ export function polyfillArrayAt(){ - if( isA(Array.prototype.at, 'function') ) return false; + if( isFunction(Array.prototype.at) ) return false; Object.defineProperty(Array.prototype, 'at', { value : function(n){ @@ -183,13 +183,13 @@

Source: polyfills.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/random.js.html b/docs/documentation/random.js.html index 8efee30c..7373bb03 100644 --- a/docs/documentation/random.js.html +++ b/docs/documentation/random.js.html @@ -40,7 +40,7 @@

Source: random.js

//###[ IMPORTS ]######################################################################################################## -import {orDefault, assert, hasValue, isA} from './basic.js'; +import {orDefault, assert, hasValue, isFunction} from './basic.js'; @@ -133,13 +133,13 @@

Source: random.js

// explicitly from either window.crypto or window.msCrypto, since invoking it from another // context will trigger an "illegal invocation" of the method :( if( - isA(window.crypto?.getRandomValues, 'function') - || isA(window.msCrypto?.getRandomValues, 'function') + isFunction(window.crypto?.getRandomValues) + || isFunction(window.msCrypto?.getRandomValues) ){ uuid = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => ( c ^ ( - isA(window.crypto?.getRandomValues, 'function') + isFunction(window.crypto?.getRandomValues) ? window.crypto.getRandomValues(new Uint8Array(1)) : window.msCrypto?.getRandomValues(new Uint8Array(1)) )[0] @@ -178,13 +178,13 @@

Source: random.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/requests.js.html b/docs/documentation/requests.js.html index 44175cb1..92cdee0f 100644 --- a/docs/documentation/requests.js.html +++ b/docs/documentation/requests.js.html @@ -517,7 +517,7 @@

Source: requests.js

* method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as * standard methods for HTTP verbs and setup things like setting headers. * - * @param {String} baseUrl - the base URL for all queries, based on which final request URLs will be built, adding the paths + * @param {?String} [baseUrl=window.location.origin] - the base URL for all queries, based on which final request URLs will be built, adding the paths, may be absolute or relative to current origin * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details) * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, "auto" uses it only if available * @param {?Boolean} [strict=true] - if true, enforces "application/json" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning @@ -543,7 +543,12 @@

Source: requests.js

* .post() * ; */ -export function createRestfulJsonClient(baseUrl, baseOptions=null, useNative=false, strict=true){ +export function createRestfulJsonClient(baseUrl=null, baseOptions=null, useNative=false, strict=true){ + baseUrl = orDefault(baseUrl, window.location.origin, 'str'); + if( !baseUrl.startsWith('//') && baseUrl.startsWith('/') ){ + baseUrl = `${window.location.origin}${baseUrl}`; + } + const __methodName__ = 'createRestfulJsonClient', implementation = createJsonRequest, @@ -1369,13 +1374,13 @@

Source: requests.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/strings.js.html b/docs/documentation/strings.js.html index a70a6463..90ddd06a 100644 --- a/docs/documentation/strings.js.html +++ b/docs/documentation/strings.js.html @@ -40,7 +40,7 @@

Source: strings.js

//###[ IMPORTS ]######################################################################################################## -import {isA, orDefault, isNaN, hasValue, isPlainObject} from './basic.js'; +import {isFunction, isArray, orDefault, isNaN, hasValue, isPlainObject} from './basic.js'; @@ -146,7 +146,7 @@

Source: strings.js

search.forEach((searchTerm, index) => { tmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0]; - if( isA(String.prototype.replaceAll, 'function') ){ + if( isFunction(String.prototype.replaceAll) ){ subject = subject.replaceAll(`${searchTerm}`, `${tmp}`); } else { subject = subject.split(`${searchTerm}`).join(`${tmp}`); @@ -216,7 +216,7 @@

Source: strings.js

export function concat(glue='', ...strings){ glue = orDefault(glue, '', 'str'); - if( (strings.length > 0) && isA(strings[0], 'array') ){ + if( (strings.length > 0) && isArray(strings[0]) ){ return strings[0].join(glue); } else { return strings.join(glue); @@ -269,7 +269,7 @@

Source: strings.js

const fResolve = function(object, key){ const value = object[key]; - if( isA(value, 'function') ){ + if( isFunction(value) ){ return value.call(object); } else { return value; @@ -532,13 +532,13 @@

Source: strings.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/timers.js.html b/docs/documentation/timers.js.html index ddd50329..a0c49eea 100644 --- a/docs/documentation/timers.js.html +++ b/docs/documentation/timers.js.html @@ -40,7 +40,7 @@

Source: timers.js

//###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, assert, hasValue, hasMembers} from './basic.js'; +import {orDefault, isFunction, assert, hasValue, hasMembers} from './basic.js'; @@ -72,7 +72,7 @@

Source: timers.js

ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:schedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:schedule | callback must be a function`); if( hasValue(oldTimer) ){ countermand(oldTimer); @@ -115,7 +115,7 @@

Source: timers.js

ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:pschedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:pschedule | callback must be a function`); if( hasValue(oldTimer) @@ -169,7 +169,7 @@

Source: timers.js

ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:reschedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:reschedule | callback must be a function`); if( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){ return pschedule(ms, callback, timer); @@ -206,7 +206,7 @@

Source: timers.js

ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:loop | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:loop | callback must be a function`); if( hasValue(oldLoop) ){ countermand(oldLoop, true); @@ -252,7 +252,7 @@

Source: timers.js

ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:ploop | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:ploop | callback must be a function`); if( hasValue(oldLoop) @@ -351,7 +351,7 @@

Source: timers.js

* const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; }); */ export function requestAnimationFrame(callback){ - assert(isA(callback, 'function'), `${MODULE_NAME}:requestAnimationFrame | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:requestAnimationFrame | callback is no function`); const raf = window.requestAnimationFrame ?? window.webkitRequestAnimationFrame @@ -430,7 +430,7 @@

Source: timers.js

* waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); }); */ export function waitForRepaint(callback){ - assert(isA(callback, 'function'), `${MODULE_NAME}:waitForRepaint | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:waitForRepaint | callback is no function`); const ids = {}; @@ -450,13 +450,13 @@

Source: timers.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/urls.js.html b/docs/documentation/urls.js.html index 234390a6..e6a24ed6 100644 --- a/docs/documentation/urls.js.html +++ b/docs/documentation/urls.js.html @@ -392,13 +392,13 @@

Source: urls.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/documentation/viewport.js.html b/docs/documentation/viewport.js.html index f742cdba..9d567d81 100644 --- a/docs/documentation/viewport.js.html +++ b/docs/documentation/viewport.js.html @@ -40,7 +40,7 @@

Source: viewport.js

//###[ IMPORTS ]######################################################################################################## -import {hasValue, orDefault, isA, isElement, Deferred, assert} from './basic.js'; +import {hasValue, orDefault, isWindow, isFunction, isElement, Deferred, assert} from './basic.js'; import {EasingFunctions} from './animation.js'; import {requestAnimationFrame} from './timers.js'; @@ -150,10 +150,10 @@

Source: viewport.js

scrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool'); cancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool'); - assert(isElement(element) || isA(element, 'window'), `${MODULE_NAME}:scrollTo | element unusable`); + assert(isElement(element) || isWindow(element), `${MODULE_NAME}:scrollTo | element unusable`); assert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`); - if( !isA(EasingFunctions[easing], 'function') ){ + if( !isFunction(EasingFunctions[easing]) ){ easing = EasingFunctions.easeInOutCubic; } else { easing = EasingFunctions[easing]; @@ -237,13 +237,13 @@

Source: viewport.js


- Documentation generated by JSDoc 3.6.11 on Fri Sep 01 2023 18:27:30 GMT+0000 (Coordinated Universal Time) + Documentation generated by JSDoc 3.6.11 on Mon Sep 04 2023 12:09:07 GMT+0000 (Coordinated Universal Time)
diff --git a/docs/examples/lib/annex/dist/animation.js b/docs/examples/lib/annex/dist/animation.js index 4bbebdef..e9992cee 100644 --- a/docs/examples/lib/annex/dist/animation.js +++ b/docs/examples/lib/annex/dist/animation.js @@ -1,5 +1,5 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Animation diff --git a/docs/examples/lib/annex/dist/arrays.js b/docs/examples/lib/annex/dist/arrays.js index 5e0594bb..660e4bc6 100644 --- a/docs/examples/lib/annex/dist/arrays.js +++ b/docs/examples/lib/annex/dist/arrays.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Arrays */ -const MODULE_NAME="Arrays";import{assert,isA,isPlainObject,orDefault}from"./basic.js";export function removeFrom(r,e,s=null){if(assert(isA(r,"array"),"Arrays:remove | target is no array"),isA(e,"number")&&!0!==s){e=parseInt(e,10),s=orDefault(s,null,"int");const t=(r=r.slice(0)).slice((s||e)+1||r.length);return r.length=e<0?r.length+e:e,r.concat(t)}if(isA(e,"string"))return r.reduce(((r,s)=>(`${s}`!==e&&r.push(s),r)),[]);{let t;return t=isPlainObject(e)?Object.values(e):isA(e,"map")||isA(e,"set")?Array.from(e.values()):Array.from(e),t.length>0&&!0!==s?t.reduce(((r,e)=>r=removeFrom(r,e,!0)),[...r]):r.reduce(((r,s)=>(s!==e&&r.push(s),r)),[])}} +const MODULE_NAME="Arrays";import{assert,isArray,isNumber,isString,isMap,isSet,isPlainObject,orDefault}from"./basic.js";export function removeFrom(r,e,s=null){if(assert(isArray(r),"Arrays:remove | target is no array"),isNumber(e)&&!0!==s){e=parseInt(e,10),s=orDefault(s,null,"int");const t=(r=r.slice(0)).slice((s||e)+1||r.length);return r.length=e<0?r.length+e:e,r.concat(t)}if(isString(e))return r.reduce(((r,s)=>(`${s}`!==e&&r.push(s),r)),[]);{let t;return t=isPlainObject(e)?Object.values(e):isMap(e)||isSet(e)?Array.from(e.values()):Array.from(e),t.length>0&&!0!==s?t.reduce(((r,e)=>r=removeFrom(r,e,!0)),[...r]):r.reduce(((r,s)=>(s!==e&&r.push(s),r)),[])}} //# sourceMappingURL=arrays.js.map diff --git a/docs/examples/lib/annex/dist/arrays.js.map b/docs/examples/lib/annex/dist/arrays.js.map index a2b8b029..2297f371 100644 --- a/docs/examples/lib/annex/dist/arrays.js.map +++ b/docs/examples/lib/annex/dist/arrays.js.map @@ -1 +1 @@ -{"version":3,"file":"arrays.js","names":["MODULE_NAME","assert","isA","isPlainObject","orDefault","removeFrom","target","from","to","parseInt","rest","slice","length","concat","reduce","reducedArray","item","push","fromList","Object","values","Array"],"sources":["arrays.js"],"mappings":";;;AAQA,MAAMA,YAAc,gBAMZC,OAAQC,IAAKC,cAAeC,cAAgB,oBA8D7C,SAASC,WAAWC,EAAQC,EAAMC,EAAG,MAG3C,GAFAP,OAAOC,IAAII,EAAQ,SAAU,sCAEzBJ,IAAIK,EAAM,YAAqB,IAAPC,EAAc,CACzCD,EAAOE,SAASF,EAAM,IACtBC,EAAKJ,UAAUI,EAAI,KAAM,OAGzB,MAAME,GADNJ,EAASA,EAAOK,MAAM,IACFA,OAAOH,GAAMD,GAAQ,GAAKD,EAAOM,QAGrD,OAFAN,EAAOM,OAAUL,EAAO,EAAMD,EAAOM,OAASL,EAAQA,EAE/CD,EAAOO,OAAOH,EACtB,CAAO,GAAIR,IAAIK,EAAM,UACpB,OAAOD,EAAOQ,QAAO,CAACC,EAAcC,KAC/B,GAAGA,MAAWT,GACjBQ,EAAaE,KAAKD,GAEZD,IACL,IACG,CACN,IAAIG,EAWJ,OATCA,EADGf,cAAcI,GACNY,OAAOC,OAAOb,GACfL,IAAIK,EAAM,QAEVL,IAAIK,EAAM,OADTc,MAAMd,KAAKA,EAAKa,UAIhBC,MAAMd,KAAKA,GAGlBW,EAASN,OAAS,IAAc,IAAPJ,EACtBU,EAASJ,QAAO,CAACC,EAAcC,IACrCD,EAAeV,WAAWU,EAAcC,GAAM,IAE5C,IAAIV,IAEAA,EAAOQ,QAAO,CAACC,EAAcC,KAC/BA,IAAST,GACZQ,EAAaE,KAAKD,GAEZD,IACL,GAEL,CACD","sourcesContent":["/*!\n * Module Arrays\n */\n\n/**\n * @namespace Arrays\n */\n\nconst MODULE_NAME = 'Arrays';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isA, isPlainObject, orDefault} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Arrays:removeFrom\n */\n\n/**\n * Removes Elements from an Array, where to and from are inclusive.\n * If you only provide \"from\", that exact index is removed.\n *\n * Does not modify the original.\n *\n * Keep in mind, that \"from\" should normally be smaller than \"to\" to slice from left to right. This means that the elements\n * indexed by \"from\" and \"to\" should have the right order. For example: [1,2,3,4]. Here from=-1 and to=-3 are illegal since\n * \"from\" references a later element than \"to\", but there are also viable examples where \"from\" is numerically bigger. If we\n * use from=2 and to=-1, \"from\" is numerically bigger, but references an earlier element than -1 (which is the last element),\n * which is totally okay. Just make sure \"from\" comes before \"to\" in the element's order.\n *\n * If you provide a string for \"from\" everything matching that string with its string representation will be removed\n * (you can provide stringification for objects via the toString method, see:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString).\n *\n * Everything else (except collections) provided for \"from\" will determine the element(s) to remove by identity (===).\n *\n * If you want to remove several elements at once, you may provide an iterable collection as \"from\" and\n * This also makes it possible to actually remove numbers from an array by identity: define the number(s) as an array,\n * to signal, that these are no indices. If you need to remove a collection from the array by reference, either put\n * the collection in an array or set \"to\" to true, to force the collection being treated as a reference.\n *\n * Iterable collections, usable in \"from\" in the sense of this method are:\n * - PlainObject (values)\n * - Array\n * - Set\n * - Map (values)\n * To remove these by reference from target, instead of iterating them, set \"to\" to true.\n *\n * @param {Array} target - the array to remove elements from\n * @param {*} from - numerical index to start removing from (can also be negative to start counting from back), a string to identify elements to remove by their string representation or any other value identifying elements to remove by identity, if this is an iterable collection, the collection is iterated instead of being treated as a reference, enforce treatment as a reference, by setting \"to\" to true\n * @param {?Number|Boolean} [to=null] - index to end removing (can also be negative to end counting from back), if true, \"from\" defines a given iterable collection to be removed by reference, instead of removing the contained values, with this you can remove an array from an array for example\n * @throws error if target is not an array\n * @returns {Array} new array without index/range/matches\n *\n * @memberof Arrays:removeFrom\n * @alias removeFrom\n * @example\n * removeFrom([1, 2, 3, 4, 5], 0, 2);\n * => [4, 5]\n * removeFrom([1, 2, 3, 4, 5], -3, -1);\n * => [1, 2]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], 'b');\n * => [b, 1]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], b);\n * => [{a : 'b', toString(){ return 'b'; }}, 'b', 1]\n * removeFrom([true, true, false, true, true], true)\n * => [false]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1, 2], ['b', b, 2]);\n * => [1]\n */\nexport function removeFrom(target, from, to=null){\n\tassert(isA(target, 'array'), `${MODULE_NAME}:remove | target is no array`);\n\n\tif( isA(from, 'number') && (to !== true) ){\n\t\tfrom = parseInt(from, 10);\n\t\tto = orDefault(to, null, 'int');\n\n\t\ttarget = target.slice(0);\n\t\tconst rest = target.slice((to || from) + 1 || target.length);\n\t\ttarget.length = (from < 0) ? (target.length + from) : from;\n\n\t\treturn target.concat(rest);\n\t} else if( isA(from, 'string') ){\n\t\treturn target.reduce((reducedArray, item) => {\n\t\t\tif( `${item}` !== from ){\n\t\t\t\treducedArray.push(item);\n\t\t\t}\n\t\t\treturn reducedArray;\n\t\t}, []);\n\t} else {\n\t\tlet fromList;\n\t\tif( isPlainObject(from) ){\n\t\t\tfromList = Object.values(from);\n\t\t} else if( isA(from, 'map') ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else if( isA(from, 'set') ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else {\n\t\t\tfromList = Array.from(from);\n\t\t}\n\n\t\tif( (fromList.length > 0) && (to !== true) ){\n\t\t\treturn fromList.reduce((reducedArray, item) => {\n\t\t\t\treducedArray = removeFrom(reducedArray, item, true);\n\t\t\t\treturn reducedArray;\n\t\t\t}, [...target]);\n\t\t} else {\n\t\t\treturn target.reduce((reducedArray, item) => {\n\t\t\t\tif( item !== from ){\n\t\t\t\t\treducedArray.push(item);\n\t\t\t\t}\n\t\t\t\treturn reducedArray;\n\t\t\t}, []);\n\t\t}\n\t}\n}\n"]} \ No newline at end of file +{"version":3,"file":"arrays.js","names":["MODULE_NAME","assert","isArray","isNumber","isString","isMap","isSet","isPlainObject","orDefault","removeFrom","target","from","to","parseInt","rest","slice","length","concat","reduce","reducedArray","item","push","fromList","Object","values","Array"],"sources":["arrays.js"],"mappings":";;;AAQA,MAAMA,YAAc,gBAMZC,OAAQC,QAASC,SAAUC,SAAUC,MAAOC,MAAOC,cAAeC,cAAgB,oBA8DnF,SAASC,WAAWC,EAAQC,EAAMC,EAAG,MAG3C,GAFAX,OAAOC,QAAQQ,GAAS,sCAEpBP,SAASQ,KAAiB,IAAPC,EAAc,CACpCD,EAAOE,SAASF,EAAM,IACtBC,EAAKJ,UAAUI,EAAI,KAAM,OAGzB,MAAME,GADNJ,EAASA,EAAOK,MAAM,IACFA,OAAOH,GAAMD,GAAQ,GAAKD,EAAOM,QAGrD,OAFAN,EAAOM,OAAUL,EAAO,EAAMD,EAAOM,OAASL,EAAQA,EAE/CD,EAAOO,OAAOH,EACtB,CAAO,GAAIV,SAASO,GACnB,OAAOD,EAAOQ,QAAO,CAACC,EAAcC,KAC/B,GAAGA,MAAWT,GACjBQ,EAAaE,KAAKD,GAEZD,IACL,IACG,CACN,IAAIG,EAWJ,OATCA,EADGf,cAAcI,GACNY,OAAOC,OAAOb,GACfN,MAAMM,IAENL,MAAMK,GADLc,MAAMd,KAAKA,EAAKa,UAIhBC,MAAMd,KAAKA,GAGlBW,EAASN,OAAS,IAAc,IAAPJ,EACtBU,EAASJ,QAAO,CAACC,EAAcC,IACrCD,EAAeV,WAAWU,EAAcC,GAAM,IAE5C,IAAIV,IAEAA,EAAOQ,QAAO,CAACC,EAAcC,KAC/BA,IAAST,GACZQ,EAAaE,KAAKD,GAEZD,IACL,GAEL,CACD","sourcesContent":["/*!\n * Module Arrays\n */\n\n/**\n * @namespace Arrays\n */\n\nconst MODULE_NAME = 'Arrays';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isArray, isNumber, isString, isMap, isSet, isPlainObject, orDefault} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Arrays:removeFrom\n */\n\n/**\n * Removes Elements from an Array, where to and from are inclusive.\n * If you only provide \"from\", that exact index is removed.\n *\n * Does not modify the original.\n *\n * Keep in mind, that \"from\" should normally be smaller than \"to\" to slice from left to right. This means that the elements\n * indexed by \"from\" and \"to\" should have the right order. For example: [1,2,3,4]. Here from=-1 and to=-3 are illegal since\n * \"from\" references a later element than \"to\", but there are also viable examples where \"from\" is numerically bigger. If we\n * use from=2 and to=-1, \"from\" is numerically bigger, but references an earlier element than -1 (which is the last element),\n * which is totally okay. Just make sure \"from\" comes before \"to\" in the element's order.\n *\n * If you provide a string for \"from\" everything matching that string with its string representation will be removed\n * (you can provide stringification for objects via the toString method, see:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString).\n *\n * Everything else (except collections) provided for \"from\" will determine the element(s) to remove by identity (===).\n *\n * If you want to remove several elements at once, you may provide an iterable collection as \"from\" and\n * This also makes it possible to actually remove numbers from an array by identity: define the number(s) as an array,\n * to signal, that these are no indices. If you need to remove a collection from the array by reference, either put\n * the collection in an array or set \"to\" to true, to force the collection being treated as a reference.\n *\n * Iterable collections, usable in \"from\" in the sense of this method are:\n * - PlainObject (values)\n * - Array\n * - Set\n * - Map (values)\n * To remove these by reference from target, instead of iterating them, set \"to\" to true.\n *\n * @param {Array} target - the array to remove elements from\n * @param {*} from - numerical index to start removing from (can also be negative to start counting from back), a string to identify elements to remove by their string representation or any other value identifying elements to remove by identity, if this is an iterable collection, the collection is iterated instead of being treated as a reference, enforce treatment as a reference, by setting \"to\" to true\n * @param {?Number|Boolean} [to=null] - index to end removing (can also be negative to end counting from back), if true, \"from\" defines a given iterable collection to be removed by reference, instead of removing the contained values, with this you can remove an array from an array for example\n * @throws error if target is not an array\n * @returns {Array} new array without index/range/matches\n *\n * @memberof Arrays:removeFrom\n * @alias removeFrom\n * @example\n * removeFrom([1, 2, 3, 4, 5], 0, 2);\n * => [4, 5]\n * removeFrom([1, 2, 3, 4, 5], -3, -1);\n * => [1, 2]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], 'b');\n * => [b, 1]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1], b);\n * => [{a : 'b', toString(){ return 'b'; }}, 'b', 1]\n * removeFrom([true, true, false, true, true], true)\n * => [false]\n * removeFrom([{a : 'b', toString(){ return 'b'; }}, 'b', b, 1, 2], ['b', b, 2]);\n * => [1]\n */\nexport function removeFrom(target, from, to=null){\n\tassert(isArray(target), `${MODULE_NAME}:remove | target is no array`);\n\n\tif( isNumber(from) && (to !== true) ){\n\t\tfrom = parseInt(from, 10);\n\t\tto = orDefault(to, null, 'int');\n\n\t\ttarget = target.slice(0);\n\t\tconst rest = target.slice((to || from) + 1 || target.length);\n\t\ttarget.length = (from < 0) ? (target.length + from) : from;\n\n\t\treturn target.concat(rest);\n\t} else if( isString(from) ){\n\t\treturn target.reduce((reducedArray, item) => {\n\t\t\tif( `${item}` !== from ){\n\t\t\t\treducedArray.push(item);\n\t\t\t}\n\t\t\treturn reducedArray;\n\t\t}, []);\n\t} else {\n\t\tlet fromList;\n\t\tif( isPlainObject(from) ){\n\t\t\tfromList = Object.values(from);\n\t\t} else if( isMap(from) ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else if( isSet(from) ){\n\t\t\tfromList = Array.from(from.values());\n\t\t} else {\n\t\t\tfromList = Array.from(from);\n\t\t}\n\n\t\tif( (fromList.length > 0) && (to !== true) ){\n\t\t\treturn fromList.reduce((reducedArray, item) => {\n\t\t\t\treducedArray = removeFrom(reducedArray, item, true);\n\t\t\t\treturn reducedArray;\n\t\t\t}, [...target]);\n\t\t} else {\n\t\t\treturn target.reduce((reducedArray, item) => {\n\t\t\t\tif( item !== from ){\n\t\t\t\t\treducedArray.push(item);\n\t\t\t\t}\n\t\t\t\treturn reducedArray;\n\t\t\t}, []);\n\t\t}\n\t}\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/basic.js b/docs/examples/lib/annex/dist/basic.js index b50dcfdd..b3be1143 100644 --- a/docs/examples/lib/annex/dist/basic.js +++ b/docs/examples/lib/annex/dist/basic.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Basic */ -const MODULE_NAME="Basic";import{log,warn}from"./logging.js";export function assert(t,e){if(!t)throw e=orDefault(e,"assert exception: assertion failed","str"),new Error(e)}export function attempt(t){assert(isA(t,"function"),"Basic:attempt | closure is no function");try{t()}catch(t){return!1}return!0}export function hasValue(){let t=!0;return Array.from(arguments).forEach((e=>{t&&=null!=e})),t}export function size(t,e=!0){if(isA(t?.values,"function"))return Array.from(t.values()).length;let r;switch(getType(t)){case"array":r=t.length;break;case"set":case"map":r=t.size;break;case"iterator":r=Array.from(t).length;break;case"string":r=e?[...t].length:t.length;break;case"object":r=Object.values(t).length;break;default:r=null}return r}export function isEmpty(){let t=!0,e=[void 0,null,"",0];return Array.from(arguments).forEach((t=>{isA(t?.__additionalEmptyValues__,"array")&&(e=e.concat(t.__additionalEmptyValues__))})),e=Array.from(new Set(e)),Array.from(arguments).forEach((r=>{t&&!isA(r?.__additionalEmptyValues__,"array")&&(t=e.includes(r),t||(t=0===size(r)))})),t}export function hasMembers(t,e,r=!1){e=orDefault(e,[],"arr"),r=orDefault(r,!1,"bool");let n=!0;return e.forEach((e=>{hasValue(t[`${e}`])||(r&&log().info(`Basic:hasMembers | missing member ${e}`),n=!1)})),n}export function orDefault(t,e,r=null,n=null){return n=hasValue(n)?[].concat(n):[],hasValue(r)?!isA(r,"function")&&["str","string","int","integer","bool","boolean","float","arr","array"].includes(`${r.toLowerCase()}`)?(r=`${r}`.toLowerCase(),["str","string"].includes(r)?r=function(t){return`${t}`}:["int","integer"].includes(r)?r=function(t){return parseInt(t,10)}:["bool","boolean"].includes(r)?r=function(t){return!!t}:"float"===r?r=function(t){return parseFloat(t)}:["arr","array"].includes(r)&&(r=function(t){return[].concat(t)})):isA(r,"function")||(r=function(t){return t}):r=function(t){return t},!hasValue(t)||n.includes(t)?e:r(t)}export function getType(t){if(!hasValue(t))return`${t}`.toLowerCase();const e=Object.prototype.toString.call(t).slice(8,-1).toLowerCase();return"generatorfunction"===e?"function":"document"===e?"htmldocument":"element"===e||/^html.*element$/.test(e)?"htmlelement":/^.*iterator$/.test(e)?"iterator":e.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/)?e:"object"==typeof t||"function"==typeof t?"object":typeof t}export function isA(t,e){return["undefined","null","boolean","number","bigint","string","symbol","function","object","array","date","error","generator","iterator","regexp","set","weakset","map","weakmap","htmldocument","htmlelement","nodelist","window"].includes(`${e}`.toLowerCase())?getType(t)===`${e}`.toLowerCase():(warn(`Basic:isA | "${e}" is not a recognized type`),!1)}export function isInt(t){return parseInt(t,10)===t}export function isFloat(t){return parseFloat(t)===t}export function isPlainObject(t){return isA(t,"object")&&hasValue(t)&&t.constructor===Object&&"[object Object]"===Object.prototype.toString.call(t)}export function isNaN(t,e=!0){return(e=orDefault(e,!0,"bool"))?t!=t:isNaN(t)}export function isElement(t){return isA(t,"htmlelement")}export function isEventTarget(t){return hasValue(t)&&isA(t.addEventListener,"function")&&isA(t.removeEventListener,"function")&&isA(t.dispatchEvent,"function")}export function isSelector(t){t=orDefault(t,0,"str");const e=document.createDocumentFragment();try{e.querySelector(t)}catch(t){return!1}return!0}export function isPotentialId(t,e="",r="[1-9][0-9]*",n="",s=!0){t=`${t}`,e=orDefault(e,"","str"),r=orDefault(r,"[1-9][0-9]*","str"),n=orDefault(n,"","str");const o=t=>`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&");let i;i=(s=orDefault(s,!0,"bool"))?new RegExp(`^${o(e)}(${r})${o(n)}$`):new RegExp(`^${e}(${r})${n}$`);const a=i.exec(t);return!!hasValue(a)&&a[1]}export function minMax(t,e,r){return assert(t<=r,"Basic:minMax | min can not be larger than max"),er?r:e}export class Deferred{constructor(){const t="fulfilled",e="rejected";this.resolve=null,this.reject=null,this.provision=null,this.status="pending",this.isSettled=()=>[t,e].includes(this.status),this.promise=new Promise(((r,n)=>{this.resolve=e=>{this.status=t,r(e)},this.reject=t=>{this.status=e,n(t)}}))}then(t){return this.promise.then(t)}catch(t){return this.promise.catch(t)}finally(t){return this.promise.finally(t)}}export class Observable{constructor(t){this.__className__="Observable",this._value=t,this._subscriptions=[]}getValue(){return this._value}setValue(t,e=!1){const r=this._value,n=r!==t;this._value=t,(n||e)&&this._subscriptions.forEach((e=>e(t,r)))}subscribe(t){return assert(isA(t,"function"),`Basic:${this.__className__}.subscribe | subscription must be function`),this._subscriptions.indexOf(t)<0&&(this._subscriptions=[...this._subscriptions,t]),t}unsubscribe(t){this._subscriptions=this._subscriptions.filter((e=>e!==t))}toString(){return`${this._value}`}} +const MODULE_NAME="Basic";import{log,warn}from"./logging.js";export function assert(t,e){if(!t)throw e=orDefault(e,"assert exception: assertion failed","str"),new Error(e)}export function attempt(t){assert(isFunction(t),"Basic:attempt | closure is no function");try{t()}catch(t){return!1}return!0}export function hasValue(){let t=!0;return Array.from(arguments).forEach((e=>{t&&=null!=e})),t}export function size(t,e=!0){if(isFunction(t?.values))return Array.from(t.values()).length;let r;switch(getType(t)){case"array":r=t.length;break;case"set":case"map":r=t.size;break;case"iterator":r=Array.from(t).length;break;case"string":r=e?[...t].length:t.length;break;case"object":r=Object.values(t).length;break;default:r=null}return r}export function isEmpty(){let t=!0,e=[void 0,null,"",0];return Array.from(arguments).forEach((t=>{isArray(t?.__additionalEmptyValues__)&&(e=e.concat(t.__additionalEmptyValues__))})),e=Array.from(new Set(e)),Array.from(arguments).forEach((r=>{t&&!isArray(r?.__additionalEmptyValues__)&&(t=e.includes(r),t||(t=0===size(r)))})),t}export function hasMembers(t,e,r=!1){e=orDefault(e,[],"arr"),r=orDefault(r,!1,"bool");let n=!0;return e.forEach((e=>{hasValue(t[`${e}`])||(r&&log().info(`Basic:hasMembers | missing member ${e}`),n=!1)})),n}export function orDefault(t,e,r=null,n=null){return n=hasValue(n)?[].concat(n):[],hasValue(r)?!isFunction(r)&&["str","string","int","integer","bool","boolean","float","arr","array"].includes(`${r.toLowerCase()}`)?(r=`${r}`.toLowerCase(),["str","string"].includes(r)?r=function(t){return`${t}`}:["int","integer"].includes(r)?r=function(t){return parseInt(t,10)}:["bool","boolean"].includes(r)?r=function(t){return!!t}:"float"===r?r=function(t){return parseFloat(t)}:["arr","array"].includes(r)&&(r=function(t){return[].concat(t)})):isFunction(r)||(r=function(t){return t}):r=function(t){return t},!hasValue(t)||n.includes(t)?e:r(t)}export function getType(t){if(!hasValue(t))return`${t}`.toLowerCase();const e=Object.prototype.toString.call(t).slice(8,-1).toLowerCase();return"generatorfunction"===e?"function":"document"===e?"htmldocument":"element"===e||/^html.*element$/.test(e)?"htmlelement":/^.*iterator$/.test(e)?"iterator":e.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/)?e:"object"==typeof t||"function"==typeof t?"object":typeof t}export function isA(t,e){return["undefined","null","boolean","number","bigint","string","symbol","function","object","array","date","error","generator","iterator","regexp","set","weakset","map","weakmap","htmldocument","htmlelement","htmlcollection","nodelist","window"].includes(`${e}`.toLowerCase())?getType(t)===`${e}`.toLowerCase():(warn(`Basic:isA | "${e}" is not a recognized type`),!1)}export function isBoolean(t){return isA(t,"boolean")}export function isNumber(t){return isA(t,"number")}export function isBigInt(t){return isA(t,"bigint")}export function isInt(t){return parseInt(t,10)===t}export function isFloat(t){return parseFloat(t)===t}export function isNaN(t,e=!0){return(e=orDefault(e,!0,"bool"))?t!=t:isNaN(t)}export function isString(t){return isA(t,"string")}export function isSymbol(t){return isA(t,"symbol")}export function isFunction(t){return isA(t,"function")}export function isObject(t){return isA(t,"object")}export function isPlainObject(t){return isObject(t)&&hasValue(t)&&t.constructor===Object&&"[object Object]"===Object.prototype.toString.call(t)}export function isArray(t){return isA(t,"array")}export function isDate(t){return isA(t,"date")}export function isError(t){return isA(t,"error")}export function isGenerator(t){return isA(t,"generator")}export function isIterator(t){return isA(t,"iterator")}export function isRegExp(t){return isA(t,"regexp")}export function isSet(t){return isA(t,"set")}export function isWeakSet(t){return isA(t,"weakset")}export function isMap(t){return isA(t,"map")}export function isWeakMap(t){return isA(t,"weakmap")}export function isDocument(t){return isA(t,"htmldocument")}export function isElement(t){return isA(t,"htmlelement")}export function isCollection(t){return isA(t,"htmlcollection")}export function isNodeList(t){return isA(t,"nodelist")}export function isWindow(t){return isA(t,"window")}export function isEventTarget(t){return hasValue(t)&&isFunction(t.addEventListener)&&isFunction(t.removeEventListener)&&isFunction(t.dispatchEvent)}export function isSelector(t){t=orDefault(t,0,"str");const e=document.createDocumentFragment();try{e.querySelector(t)}catch(t){return!1}return!0}export function isPotentialId(t,e="",r="[1-9][0-9]*",n="",i=!0){t=`${t}`,e=orDefault(e,"","str"),r=orDefault(r,"[1-9][0-9]*","str"),n=orDefault(n,"","str");const o=t=>`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&");let s;s=(i=orDefault(i,!0,"bool"))?new RegExp(`^${o(e)}(${r})${o(n)}$`):new RegExp(`^${e}(${r})${n}$`);const u=s.exec(t);return!!hasValue(u)&&u[1]}export function minMax(t,e,r){return assert(t<=r,"Basic:minMax | min can not be larger than max"),er?r:e}export class Deferred{constructor(){const t="fulfilled",e="rejected";this.resolve=null,this.reject=null,this.provision=null,this.status="pending",this.isSettled=()=>[t,e].includes(this.status),this.promise=new Promise(((r,n)=>{this.resolve=e=>{this.status=t,r(e)},this.reject=t=>{this.status=e,n(t)}}))}then(t){return this.promise.then(t)}catch(t){return this.promise.catch(t)}finally(t){return this.promise.finally(t)}}export class Observable{constructor(t){this.__className__="Observable",this._value=t,this._subscriptions=[]}getValue(){return this._value}setValue(t,e=!1){const r=this._value,n=r!==t;this._value=t,(n||e)&&this._subscriptions.forEach((e=>e(t,r)))}subscribe(t){return assert(isFunction(t),`Basic:${this.__className__}.subscribe | subscription must be function`),this._subscriptions.indexOf(t)<0&&(this._subscriptions=[...this._subscriptions,t]),t}unsubscribe(t){this._subscriptions=this._subscriptions.filter((e=>e!==t))}toString(){return`${this._value}`}} //# sourceMappingURL=basic.js.map diff --git a/docs/examples/lib/annex/dist/basic.js.map b/docs/examples/lib/annex/dist/basic.js.map index 5c4ebcd4..7d1c94a7 100644 --- a/docs/examples/lib/annex/dist/basic.js.map +++ b/docs/examples/lib/annex/dist/basic.js.map @@ -1 +1 @@ -{"version":3,"file":"basic.js","names":["MODULE_NAME","log","warn","assert","condition","message","orDefault","Error","attempt","closure","isA","ex","hasValue","res","Array","from","arguments","forEach","value","size","target","countStringCharacters","values","length","getType","Object","isEmpty","emptyValues","undefined","obj","__additionalEmptyValues__","concat","Set","includes","hasMembers","memberNames","verbose","memberName","info","expression","defaultValue","caster","additionalEmptyValues","toLowerCase","parseInt","parseFloat","deepType","prototype","toString","call","slice","test","match","type","isInt","intVal","isFloat","floatVal","isPlainObject","constructor","isNaN","checkForIdentity","isElement","isEventTarget","addEventListener","removeEventListener","dispatchEvent","isSelector","fragment","document","createDocumentFragment","querySelector","isPotentialId","prefix","idRex","postfix","maskFixes","mask","str","replace","rex","RegExp","matches","exec","minMax","min","max","Deferred","STATUS_FULFILLED","STATUS_REJECTED","this","resolve","reject","provision","status","isSettled","promise","Promise","resolution","rejection","then","f","catch","finally","Observable","initialValue","__className__","_value","_subscriptions","getValue","setValue","newValue","force","oldValue","isNewValue","s","subscribe","subscription","indexOf","unsubscribe","filter"],"sources":["basic.js"],"mappings":"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","sourcesContent":["/*!\n * Module Basic\n */\n\n/**\n * @namespace Basic\n */\n\nconst MODULE_NAME = 'Basic';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {log, warn} from './logging.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Basic:assert\n */\n\n/**\n * Classical assert method. If condition is falsy, throw assert exception.\n *\n * @param {Boolean} condition - defines if an assertion is successful\n * @param {?String} [message='assert exception: assertion failed'] - to display if assertion fails\n * @throws assert exception\n *\n * @memberof Basic:assert\n * @alias assert\n * @example\n * function set(name, value){\n * assert(name.length > 0);\n * assert(isPlainObject(value), 'error: value must be plain object');\n * ...\n * }\n */\nexport function assert(condition, message){\n\tif( !condition ){\n\t\tmessage = orDefault(message, 'assert exception: assertion failed', 'str');\n\t\tthrow new Error(message);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:attempt\n */\n\n/**\n * Attempt to compute contents of closure and catch all occurring exceptions.\n * The boolean result tells you if the operation was successful or not.\n *\n * This is most helpful, when used to test value conversions or other atomic/singluar operations, where it\n * just is important if something isolated works or not.\n *\n * Do not encapsulate complex code in the closure and mind recursively occurring exceptions!\n *\n * @param {Function} closure - the code to test\n * @throws error if closure is not a function\n * @returns {Boolean} true if no exception occurred\n *\n * @memberof Basic:attempt\n * @alias attempt\n * @example\n * if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); }\n */\nexport function attempt(closure){\n\tassert(isA(closure, 'function'), `${MODULE_NAME}:attempt | closure is no function`);\n\n\ttry {\n\t\tclosure();\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:hasValue\n */\n\n/**\n * Check if variable(s) is set, by being neither undefined nor null.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are set\n *\n * @memberof Basic:hasValue\n * @alias hasValue\n * @example\n * function set(name, value){\n * if( hasValue(name, value) ){\n * ...\n * }\n * }\n */\nexport function hasValue(){\n\tlet res = true;\n\n\tArray.from(arguments).forEach(value => {\n\t\tres &&= ((value !== undefined) && (value !== null));\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:size\n */\n\n/**\n * Determine the (value) size of a collection.\n *\n * A collection is an object with countable values:\n * - Arrays return their length\n * - Sets and Maps return their size\n * - Strings return their (character) length\n * - Iterators return the length of their value list\n * - Objects return the length of their value list\n * - any object implementing .values() returns the length of the returned value list\n *\n * @param {Object|Array|Set|Map|String|Iterable} target - a collection to determine the (value) size of\n * @param {?Boolean} [countStringCharacters=true] - if we want to determine the length of a string, we'd normally like to count actual characters, but length normally returns the technical length counting more than one for unicode chars, set this to \"false\" to use technical length instead of characters\n * @returns {Number|null} the size of the collection or null if no size could be determined\n *\n * @memberof Basic:size\n * @alias size\n * @example\n * size('日本国💩👻');\n * => 5\n * size('日本国💩👻', false);\n * => 7\n * size({a : 1, b : new Date(), c : [1, 2, 3]});\n * => 3\n * size(['test', 'test', 'test']);\n * => 3\n * size(new Set(['test1', 'test2', 'test3']));\n * => 3\n * size(new Set(['test1', 'test2', 'test3']).values());\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]));\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]).values());\n * => 3\n * size(null);\n * => null\n * size(undefined);\n * => null\n */\nexport function size(target, countStringCharacters=true){\n\tif( isA(target?.values, 'function') ) return Array.from(target.values()).length;\n\n\tlet res;\n\tswitch( getType(target) ){\n\t\tcase 'array':\n\t\t\tres = target.length;\n\t\tbreak;\n\n\t\tcase 'set':\n\t\tcase 'map':\n\t\t\tres = target.size;\n\t\tbreak;\n\n\t\tcase 'iterator':\n\t\t\tres = Array.from(target).length;\n\t\tbreak;\n\n\t\tcase 'string':\n\t\t\t// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#description\n\t\t\tres = countStringCharacters ? [...target].length : target.length;\n\t\tbreak;\n\n\t\tcase 'object':\n\t\t\tres = Object.values(target).length;\n\t\tbreak;\n\n\t\tdefault:\n\t\t\tres = null;\n\t\tbreak;\n\t}\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:isEmpty\n */\n\n/**\n * Check if variable(s) contain non-empty value\n * (not undefined, null, '', 0, [], {} or an empty Set/Map).\n *\n * You can supply additional non-empty values by providing an object having the key \"__additionalEmptyValues__\" as\n * any single parameter. Multiple occurrences will be merged.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are empty\n *\n * @memberof Basic:isEmpty\n * @alias isEmpty\n * @example\n * function set(name, value){\n * if( isEmpty(fooBar) || isEmpty({'__additionalEmptyValues__' : [false, '0']}, someArray, someSet, someString, value) ){\n * ...\n * }\n * }\n */\nexport function isEmpty(){\n\tlet\n\t\tres = true,\n\t\temptyValues = [undefined, null, '', 0]\n\t;\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( isA(obj?.__additionalEmptyValues__, 'array') ){\n\t\t\temptyValues = emptyValues.concat(obj.__additionalEmptyValues__);\n\t\t}\n\t});\n\temptyValues = Array.from(new Set(emptyValues));\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( res && !isA(obj?.__additionalEmptyValues__, 'array') ){\n\t\t\tres = emptyValues.includes(obj);\n\n\t\t\tif( !res ){\n\t\t\t\tres = (size(obj) === 0);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:hasMembers\n */\n\n/**\n * \"Validates\" an object in a very basic way by checking if all given members are present and are not nullish.\n *\n * @param {Object} obj - the object to check\n * @param {String[]} memberNames - the names of the members to check\n * @param {Boolean} [verbose=false] - defines if method should output missing members to console\n * @returns {Boolean} all memberNames present and not nullish\n *\n * @memberof Basic:hasMembers\n * @alias hasMembers\n * @example\n * function pat(kitten){\n * if( hasMembers(kitten, ['fluff', 'meow', 'scratch']) ){\n * ...\n * }\n * }\n */\nexport function hasMembers(obj, memberNames, verbose=false){\n\tmemberNames = orDefault(memberNames, [], 'arr');\n\tverbose = orDefault(verbose, false, 'bool');\n\n\tlet res = true;\n\n\tmemberNames.forEach(memberName => {\n\t\tif( !hasValue(obj[`${memberName}`]) ){\n\t\t\tif( verbose ){\n\t\t\t\tlog().info(`${MODULE_NAME}:hasMembers | missing member ${memberName}`);\n\t\t\t}\n\n\t\t\tres = false;\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:orDefault\n */\n\n/**\n * If an expression returns a non-value (undefined or null), use the default value instead.\n * Define a caster name, to force expression result/value into certain data type.\n *\n * @param {*} expression - the expression to evaluate\n * @param {*} defaultValue - the default value to use if the expression is considered empty\n * @param {?(String|Function)} [caster=null] - either a default caster by name ('str', 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'arr', 'array') or a function getting the value and returning the transformed value\n * @param {?Array} [additionalEmptyValues=null] - if set, provides a list of additional values to be considered empty, apart from undefined and null\n * @returns {*} expression of defaultValue\n *\n * @memberof Basic:orDefault\n * @alias orDefault\n * @example\n * function set(name, value){\n * name = orDefault(name, 'kittens!', 'string', ['', 'none']);\n * value = orDefault(value, 42, 'int');\n * }\n */\nexport function orDefault(expression, defaultValue, caster=null, additionalEmptyValues=null){\n\tif( hasValue(additionalEmptyValues) ){\n\t\tadditionalEmptyValues = [].concat(additionalEmptyValues);\n\t} else {\n\t\tadditionalEmptyValues = [];\n\t}\n\n\tif( hasValue(caster) ){\n\t\tif(\n\t\t\t!isA(caster, 'function')\n\t\t\t&& ([\n\t\t\t\t'str', 'string',\n\t\t\t\t'int', 'integer',\n\t\t\t\t'bool', 'boolean',\n\t\t\t\t'float',\n\t\t\t\t'arr', 'array'\n\t\t\t].includes(`${caster.toLowerCase()}`))\n\t\t){\n\t\t\tcaster = `${caster}`.toLowerCase();\n\n\t\t\tif( ['str', 'string'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return `${value}`; };\n\t\t\t} else if( ['int', 'integer'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return parseInt(value, 10); };\n\t\t\t} else if( ['bool', 'boolean'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return !!value; };\n\t\t\t} else if( caster === 'float' ){\n\t\t\t\tcaster = function(value){ return parseFloat(value); };\n\t\t\t} else if( ['arr', 'array'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return [].concat(value); };\n\t\t\t}\n\t\t} else if( !isA(caster, 'function') ){\n\t\t\tcaster = function(value){ return value; };\n\t\t}\n\t} else {\n\t\tcaster = function(value){ return value; };\n\t}\n\n\tif( !hasValue(expression) || (additionalEmptyValues.includes(expression)) ){\n\t\treturn defaultValue;\n\t} else {\n\t\treturn caster(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:getType\n */\n\n/**\n * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on\n * useful frontend types like \"htmldocument\", \"htmlelement\" and \"nodelist\"\n *\n * Types:\n * - \"undefined\"\n * - \"null\"\n * - \"boolean\"\n * - \"number\"\n * - \"bigint\"\n * - \"string\"\n * - \"symbol\"\n * - \"function\"\n * - \"object\"\n * - \"array\"\n * - \"date\"\n * - \"error\"\n * - \"generator\"\n * - \"iterator\"\n * - \"regexp\"\n * - \"set\"\n * - \"weakset\"\n * - \"map\"\n * - \"weakmap\"\n * - \"htmldocument\"\n * - \"htmlelement\"\n * - \"nodelist\"\n * - \"window\"\n *\n * @param {*} [value] - variable to check the type of\n * @returns {String} the value type in lower case\n *\n * @memberof Basic:getType\n * @alias getType\n * @example\n * if( getType(cb) === 'function' ){\n * ...\n * }\n */\nexport function getType(value) {\n\tif( !hasValue(value) ) return `${value}`.toLowerCase();\n\n\tconst deepType = Object.prototype.toString.call(value).slice(8,-1).toLowerCase();\n\n\tif( deepType === 'generatorfunction' ) return 'function';\n\tif( deepType === 'document' ) return 'htmldocument';\n\tif( deepType === 'element' ) return 'htmlelement';\n\tif( /^html.*element$/.test(deepType) ) return 'htmlelement';\n\tif( /^.*iterator$/.test(deepType) ) return 'iterator';\n\n\treturn deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/)\n\t\t? deepType\n\t\t: ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isA\n */\n\n/**\n * Short form of \"getType\"-method with a more compact syntax.\n * Can identify all types listed in getType.\n *\n * @param {*} value - variable to check the type of\n * @param {String} type - the name of the type to check for, has to be a standard JS-type, is case insensitive\n * @returns {Boolean} target has type\n *\n * @memberof Basic:isA\n * @alias isA\n * @see getType\n * @example\n * let stringBool = (isA(test, 'boolean') && test) ? 'true' : 'false';\n */\nexport function isA(value, type){\n\tif(\n\t\t[\n\t\t\t'undefined',\n\t\t\t'null',\n\t\t\t'boolean',\n\t\t\t'number',\n\t\t\t'bigint',\n\t\t\t'string',\n\t\t\t'symbol',\n\t\t\t'function',\n\t\t\t'object',\n\t\t\t'array',\n\t\t\t'date',\n\t\t\t'error',\n\t\t\t'generator',\n\t\t\t'iterator',\n\t\t\t'regexp',\n\t\t\t'set',\n\t\t\t'weakset',\n\t\t\t'map',\n\t\t\t'weakmap',\n\t\t\t'htmldocument',\n\t\t\t'htmlelement',\n\t\t\t'nodelist',\n\t\t\t'window'\n\t\t].includes(`${type}`.toLowerCase())\n\t){\n\t\treturn getType(value) === `${type}`.toLowerCase();\n\t} else {\n\t\twarn(`${MODULE_NAME}:isA | \"${type}\" is not a recognized type`);\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isInt\n */\n\n/**\n * Returns if a value is truly a real integer value and not just an int-parsable value for example.\n * Since JS only knows the data type \"number\" all numbers are usable as floats by default, but not the\n * other way round.\n *\n * @param {*} intVal - the value the check\n * @returns {Boolean} true if intVal is a true integer value\n *\n * @memberof Basic:isInt\n * @alias isInt\n * @example\n * if( !isInt(val) ){\n * val = parseInt(val, 10);\n * }\n */\nexport function isInt(intVal){\n\treturn parseInt(intVal, 10) === intVal;\n}\n\n\n\n/**\n * @namespace Basic:isFloat\n */\n\n/**\n * Returns if a value is a numeric value, usable as a float number in any calculation.\n * Any number that fulfills isInt, is also considered a valid float, which lies in JS's\n * nature of not differentiating ints and floats by putting them both into a \"number\"-type.\n * So ints are always floats, but not necessarily the other way round.\n *\n * @param {*} floatVal - the value to check\n * @returns {Boolean} true if floatVal is usable in a float context\n *\n * @memberof Basic:isFloat\n * @alias isFloat\n * @example\n * if( !isFloat(val) ){\n * alert('val can not be calculated with!');\n * }\n */\nexport function isFloat(floatVal){\n\treturn parseFloat(floatVal) === floatVal;\n}\n\n\n\n/**\n * @namespace Basic:isPlainObject\n */\n\n/**\n * Returns if a value is an object literal, so so-called \"plain object.\n * A plain object is something like \"{hello : 'world'}\".\n *\n * This might especially be helpful when dealing with JSON configs, so quickly check if\n * something might even be parsed JSON (which in most cases is a plain object in js).\n *\n * Be aware that this function cannot differentiate between constructor-based simple objects and\n * plain objects declared inline. So, if someone took on the work to instantiate a base object and assign\n * properties either in a function or a constructor, we accept that as a plain object.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value seems to be a plain object\n *\n * @memberof Basic:isPlainObject\n * @alias isPlainObject\n * @example\n * const isParameterConfigObject = isPlainObject(param);\n */\nexport function isPlainObject(value){\n\treturn isA(value, 'object')\n\t\t&& hasValue(value)\n\t\t&& (value.constructor === Object)\n\t\t&& Object.prototype.toString.call(value) === '[object Object]'\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isNaN\n */\n\n/**\n * Returns if an expression is NaN or not.\n * This method employs two different approaches:\n * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something.\n * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being\n * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which\n * inspects the expression, tries to cast or parse a number from it and returns the result.\n *\n * @param {*} expression - the expression to check\n * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality\n * @returns {Boolean} true if expression is NaN\n *\n * @memberof Basic:isNaN\n * @alias isNaN\n * @example\n * if( !isNaN(suspiciousCalculatedValue) ){\n * return suspiciousCalculatedValue * 3;\n * }\n */\nexport function isNaN(expression, checkForIdentity=true){\n\tcheckForIdentity = orDefault(checkForIdentity, true, 'bool');\n\n\tif( checkForIdentity ){\n\t\treturn expression !== expression;\n\t} else {\n\t\treturn isNaN(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isElement\n */\n\n/**\n * Returns if a value is an HTML element.\n * Be aware, that this explicitly means an element, not necessarily any node.\n * So text nodes, comments and such do not qualify.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an HTML element\n *\n * @memberof Basic:isElement\n * @alias isElement\n * @example\n * if( isElement(target) ){\n * target.classList.add('foo');\n * }\n */\nexport function isElement(value){\n\treturn isA(value, 'htmlelement');\n}\n\n\n\n/**\n * @namespace Basic:isEventTarget\n */\n\n/**\n * Returns if a value is an EventTarget, which means that it is able to dispatch and receive events.\n * This is determined via duck-typing and not via class inheritance check, since this method is not\n * about type-safety, but the question if we can use the target for events, which is simply determined\n * by three essential object methods: addEventListener, removeEventListener and dispatchEvent. All\n * objects supporting these are fine with us.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value supports event methods\n *\n * @memberof Basic:isEventTarget\n * @alias isEventTarget\n * @example\n * if( isEventTarget(target) ){\n * target.dispatchEvent(new CustomEvent('foobar'));\n * }\n */\nexport function isEventTarget(value){\n\treturn hasValue(value)\n\t\t&& isA(value.addEventListener, 'function')\n\t\t&& isA(value.removeEventListener, 'function')\n\t\t&& isA(value.dispatchEvent, 'function')\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isSelector\n */\n\n/**\n * Returns if a value is a valid selector, usable in methods such as querySelector\n * and querySelectorAll.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a valid selector\n *\n * @memberof Basic:isSelector\n * @alias isSelector\n * @example\n * if( isSelector(selector) ){\n * document.querySelector(selector)?.style.setProperty('color', 'red');\n * }\n */\nexport function isSelector(value){\n\t// almost all values like \"null\", \"undefined\" and \"NaN\" are accepted querySelectors, numbers are not\n\tvalue = orDefault(value, 0, 'str');\n\n\tconst fragment = document.createDocumentFragment();\n\n\ttry {\n\t\tfragment.querySelector(value);\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:isPotentialId\n */\n\n/**\n * Determines if a given value is potentially a valid id for something, because it matches a format of given\n * prefix, postfix and id regex. \"Potential\", because we can only assume by the format, we do not actually know\n * if the id really matches anything like a database entry for example.\n *\n * @param {(String|Number)} value - the value to test, will be stringified\n * @param {?String} [prefix=''] - a prefix for the id\n * @param {?String} [idRex='[1-9][0-9]*'] - the regex string to use to identify the id part of the value\n * @param {?String} [postfix=''] - a postfix for the id\n * @param {?Boolean} [maskFixes=true] - usually, prefixes are not treated as regexes and are automatically masked, if you'd like to define complex pre- and postfixes using regexes, set this to false\n * @returns {String|Boolean} if value is potential id according to format, the id is returned as a string (still usable as a truthy value), otherwise the return value is false\n *\n * @memberof Basic:isPotentialId\n * @alias isPotentialId\n * @example\n * if( isPotentialId(id, 'test_(', '[0-9]+', ')') ){\n * createJsonRequest(`/backend/${id}`).then(() => { alert('done'); });\n * }\n */\nexport function isPotentialId(value, prefix='', idRex='[1-9][0-9]*', postfix='', maskFixes=true){\n\tvalue = `${value}`;\n\tprefix = orDefault(prefix, '', 'str');\n\tidRex = orDefault(idRex, '[1-9][0-9]*', 'str');\n\tpostfix = orDefault(postfix, '', 'str');\n\tmaskFixes = orDefault(maskFixes, true, 'bool');\n\n\tconst mask = str => `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n\n\tlet rex;\n\tif( maskFixes ){\n\t\trex = new RegExp(`^${mask(prefix)}(${idRex})${mask(postfix)}$`);\n\t} else {\n\t\trex = new RegExp(`^${prefix}(${idRex})${postfix}$`);\n\t}\n\n\tconst matches = rex.exec(value);\n\treturn hasValue(matches) ? matches[1] : false;\n}\n\n\n\n/**\n * @namespace Basic:minMax\n */\n\n/**\n * Checks if a value is within bounds of a minimum and maximum and returns\n * the value or the upper or lower bound respectively.\n *\n * Accepts all values comparable with > and <.\n *\n * @param {*} min - the lower bound\n * @param {*} value - the value to check\n * @param {*} max - the upper bound\n * @throws error if min is not smaller than max\n * @returns {*} value, min or max\n *\n * @memberof Basic:minMax\n * @alias minMax\n * @example\n * let croppedVal = minMax(-100, value, 100);\n */\nexport function minMax(min, value, max){\n\tassert(min <= max, `${MODULE_NAME}:minMax | min can not be larger than max`);\n\n\treturn (value < min)\n\t\t? min\n\t\t: (\n\t\t\t(value > max)\n\t\t\t\t? max\n\t\t\t\t: value\n\t\t)\n\t;\n}\n\n\n\n/**\n * @namespace Basic:Deferred\n */\n\n/**\n * @typedef Deferred\n * @type {Object}\n * @property {Promise} promise - the wrapped promise\n * @property {Function} resolve - resolves the wrapped promise with given value\n * @property {Function} reject - rejects the wrapped promise with given error\n * @property {Function} then - defines a success handler for the wrapped promise and returns its result\n * @property {Function} catch - defines an error handler for the wrapped promise and returns its result\n * @property {Function} finally - defines a \"settled\" handler for the wrapped promise and returns its result\n * @property {String} status - holds the current resolution status, can either be \"pending\", \"fulfilled\" or \"rejected\"\n * @property {Function} isSettled - returns true, if the Deferred is either \"fulfilled\" or \"rejected\"\n * @property {?*} [provision=null] - may contain (a) provisional value(s) to use for a newly instantiated Deferred, before it has resolved to the actual value(s)\n */\n\n/**\n * Class that wraps a Promise, to allow resolving and rejecting outside the\n * Promise's function scope. This allows for decoupled handling of states and\n * handling promises as references in a distributed context, like a class, where\n * a Deferred might then represent an async state.\n *\n * Deferreds also provide accessible status information, normal Promises do not have.\n * Accessing the \"status\" property returns the current status, being either \"pending\",\n * \"fulfilled\" or \"rejected\". You may also check if the Deferred has been settled via\n * \"isSettled()\". If you want to provide a preliminary result, available before the\n * promise has settled, you may set this result as a payload using the \"provision\" property.\n *\n * This follows ideas by jQuery and Q Promises:\n * - https://api.jquery.com/jQuery.Deferred/\n * - https://github.com/kriskowal/q/wiki/Coming-from-jQuery#deferreds-promises-resolvers\n *\n * Keep in mind, that Promises might need a polyfill such as core-js.\n *\n * @memberof Basic:Deferred\n * @name Deferred\n * @example\n * const doStuff = new Deferred();\n * doStuff.provision = 'provisional value';\n * doStuff\n * .then(value => { alert(`yeah, ready with \"${value}\"!`); })\n * .catch(error => { console.error(error); })\n * .finally(() => { console.info('has been settled); })\n * ;\n * if( foobar === 42 ){\n * doStuff.resolve(42);\n * } else {\n * doStuff.reject(new Error('not 42!'));\n * }\n * console.info(doStuff.status);\n */\nexport class Deferred {\n\tconstructor(){\n\t\tconst\n\t\t\tSTATUS_PENDING = 'pending',\n\t\t\tSTATUS_FULFILLED = 'fulfilled',\n\t\t\tSTATUS_REJECTED = 'rejected'\n\t\t;\n\t\tthis.resolve = null;\n\t\tthis.reject = null;\n\t\tthis.provision = null;\n\t\tthis.status = STATUS_PENDING;\n\t\tthis.isSettled = () => [STATUS_FULFILLED, STATUS_REJECTED].includes(this.status);\n\t\tthis.promise = new Promise((resolve, reject) => {\n\t\t\tthis.resolve = resolution => {\n\t\t\t\tthis.status = STATUS_FULFILLED;\n\t\t\t\tresolve(resolution);\n\t\t\t};\n\t\t\tthis.reject = rejection => {\n\t\t\t\tthis.status = STATUS_REJECTED;\n\t\t\t\treject(rejection);\n\t\t\t};\n\t\t});\n\t}\n\n\tthen(f){\n\t\treturn this.promise.then(f);\n\t}\n\n\tcatch(f){\n\t\treturn this.promise.catch(f);\n\t}\n\n\tfinally(f){\n\t\treturn this.promise.finally(f);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:Observable\n */\n\n/**\n * @typedef Observable\n * @type {Object}\n * @property {Function} getValue - returns the current value\n * @property {Function} setValue - sets a new value, which will subsequently trigger all subscriptions\n * @property {Function} subscribe - register a given function to be executed on any value change, the subscription receives the new and the old value on each execution, returns the subscription value, which can later be used to unsubscribe again\n * @property {Function} unsubscribe - removes a given subscription again, use subscription value returned by subscribe here\n */\n\n/**\n * A class offering the bare minimum feature set to observe a value and subscribe to future value changes.\n * No automatic magic going on here, this simply follows a basic subscription pattern, where each subscription is\n * a function, being called with a newly set value. This closely resembles the kind of observables knockout is using.\n *\n * @memberof Basic:Observable\n * @name Observable\n * @example\n * const status = new Observable('ok');\n * const subscription = status.subscribe(s => {\n * console.log(`status changed to: ${s}`);\n * });\n * status.setValue('oh noez');\n * status.unsubscribe(subscription);\n */\nexport class Observable {\n\tconstructor(initialValue){\n\t\tthis.__className__ = 'Observable';\n\t\tthis._value = initialValue;\n\t\tthis._subscriptions = [];\n\t}\n\n\tgetValue(){\n\t\treturn this._value;\n\t}\n\n\tsetValue(newValue, force=false){\n\t\tconst\n\t\t\toldValue = this._value,\n\t\t\tisNewValue = oldValue !== newValue\n\t\t;\n\t\tthis._value = newValue;\n\t\tif( isNewValue || force ){\n\t\t\tthis._subscriptions.forEach(s => s(newValue, oldValue));\n\t\t}\n\t}\n\n\tsubscribe(subscription){\n\t\tconst __methodName__ = 'subscribe';\n\t\tassert(isA(subscription, 'function'), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`);\n\t\tif( this._subscriptions.indexOf(subscription) < 0 ){\n\t\t\tthis._subscriptions = [...this._subscriptions, subscription];\n\t\t}\n\t\treturn subscription;\n\t}\n\n\tunsubscribe(subscription){\n\t\tthis._subscriptions = this._subscriptions.filter(s => s !== subscription);\n\t}\n\n\ttoString(){\n\t\treturn `${this._value}`;\n\t}\n}\n"]} \ No newline at end of file +{"version":3,"file":"basic.js","names":["MODULE_NAME","log","warn","assert","condition","message","orDefault","Error","attempt","closure","isFunction","ex","hasValue","res","Array","from","arguments","forEach","value","size","target","countStringCharacters","values","length","getType","Object","isEmpty","emptyValues","undefined","obj","isArray","__additionalEmptyValues__","concat","Set","includes","hasMembers","memberNames","verbose","memberName","info","expression","defaultValue","caster","additionalEmptyValues","toLowerCase","parseInt","parseFloat","deepType","prototype","toString","call","slice","test","match","isA","type","isBoolean","isNumber","isBigInt","isInt","intVal","isFloat","floatVal","isNaN","checkForIdentity","isString","isSymbol","isObject","isPlainObject","constructor","isDate","isError","isGenerator","isIterator","isRegExp","isSet","isWeakSet","isMap","isWeakMap","isDocument","isElement","isCollection","isNodeList","isWindow","isEventTarget","addEventListener","removeEventListener","dispatchEvent","isSelector","fragment","document","createDocumentFragment","querySelector","isPotentialId","prefix","idRex","postfix","maskFixes","mask","str","replace","rex","RegExp","matches","exec","minMax","min","max","Deferred","STATUS_FULFILLED","STATUS_REJECTED","this","resolve","reject","provision","status","isSettled","promise","Promise","resolution","rejection","then","f","catch","finally","Observable","initialValue","__className__","_value","_subscriptions","getValue","setValue","newValue","force","oldValue","isNewValue","s","subscribe","subscription","indexOf","unsubscribe","filter"],"sources":["basic.js"],"mappings":"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","sourcesContent":["/*!\n * Module Basic\n */\n\n/**\n * @namespace Basic\n */\n\nconst MODULE_NAME = 'Basic';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {log, warn} from './logging.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Basic:assert\n */\n\n/**\n * Classical assert method. If condition is falsy, throw assert exception.\n *\n * @param {Boolean} condition - defines if an assertion is successful\n * @param {?String} [message='assert exception: assertion failed'] - to display if assertion fails\n * @throws assert exception\n *\n * @memberof Basic:assert\n * @alias assert\n * @example\n * function set(name, value){\n * assert(name.length > 0);\n * assert(isPlainObject(value), 'error: value must be plain object');\n * ...\n * }\n */\nexport function assert(condition, message){\n\tif( !condition ){\n\t\tmessage = orDefault(message, 'assert exception: assertion failed', 'str');\n\t\tthrow new Error(message);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:attempt\n */\n\n/**\n * Attempt to compute contents of closure and catch all occurring exceptions.\n * The boolean result tells you if the operation was successful or not.\n *\n * This is most helpful, when used to test value conversions or other atomic/singluar operations, where it\n * just is important if something isolated works or not.\n *\n * Do not encapsulate complex code in the closure and mind recursively occurring exceptions!\n *\n * @param {Function} closure - the code to test\n * @throws error if closure is not a function\n * @returns {Boolean} true if no exception occurred\n *\n * @memberof Basic:attempt\n * @alias attempt\n * @example\n * if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); }\n */\nexport function attempt(closure){\n\tassert(isFunction(closure), `${MODULE_NAME}:attempt | closure is no function`);\n\n\ttry {\n\t\tclosure();\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:hasValue\n */\n\n/**\n * Check if variable(s) is set, by being neither undefined nor null.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are set\n *\n * @memberof Basic:hasValue\n * @alias hasValue\n * @example\n * function set(name, value){\n * if( hasValue(name, value) ){\n * ...\n * }\n * }\n */\nexport function hasValue(){\n\tlet res = true;\n\n\tArray.from(arguments).forEach(value => {\n\t\tres &&= ((value !== undefined) && (value !== null));\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:size\n */\n\n/**\n * Determine the (value) size of a collection.\n *\n * A collection is an object with countable values:\n * - Arrays return their length\n * - Sets and Maps return their size\n * - Strings return their (character) length\n * - Iterators return the length of their value list\n * - Objects return the length of their value list\n * - any object implementing .values() returns the length of the returned value list\n *\n * @param {Object|Array|Set|Map|String|Iterable} target - a collection to determine the (value) size of\n * @param {?Boolean} [countStringCharacters=true] - if we want to determine the length of a string, we'd normally like to count actual characters, but length normally returns the technical length counting more than one for unicode chars, set this to \"false\" to use technical length instead of characters\n * @returns {Number|null} the size of the collection or null if no size could be determined\n *\n * @memberof Basic:size\n * @alias size\n * @example\n * size('日本国💩👻');\n * => 5\n * size('日本国💩👻', false);\n * => 7\n * size({a : 1, b : new Date(), c : [1, 2, 3]});\n * => 3\n * size(['test', 'test', 'test']);\n * => 3\n * size(new Set(['test1', 'test2', 'test3']));\n * => 3\n * size(new Set(['test1', 'test2', 'test3']).values());\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]));\n * => 3\n * size(new Map([[1, 1], [new Date(), new Date()], ['foo', 'bar']]).values());\n * => 3\n * size(null);\n * => null\n * size(undefined);\n * => null\n */\nexport function size(target, countStringCharacters=true){\n\tif( isFunction(target?.values) ) return Array.from(target.values()).length;\n\n\tlet res;\n\tswitch( getType(target) ){\n\t\tcase 'array':\n\t\t\tres = target.length;\n\t\tbreak;\n\n\t\tcase 'set':\n\t\tcase 'map':\n\t\t\tres = target.size;\n\t\tbreak;\n\n\t\tcase 'iterator':\n\t\t\tres = Array.from(target).length;\n\t\tbreak;\n\n\t\tcase 'string':\n\t\t\t// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#description\n\t\t\tres = countStringCharacters ? [...target].length : target.length;\n\t\tbreak;\n\n\t\tcase 'object':\n\t\t\tres = Object.values(target).length;\n\t\tbreak;\n\n\t\tdefault:\n\t\t\tres = null;\n\t\tbreak;\n\t}\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:isEmpty\n */\n\n/**\n * Check if variable(s) contain non-empty value\n * (not undefined, null, '', 0, [], {} or an empty Set/Map).\n *\n * You can supply additional non-empty values by providing an object having the key \"__additionalEmptyValues__\" as\n * any single parameter. Multiple occurrences will be merged.\n *\n * @param {...*} [...] - add any number of variables you wish to check\n * @returns {Boolean} variable(s) is/are empty\n *\n * @memberof Basic:isEmpty\n * @alias isEmpty\n * @example\n * function set(name, value){\n * if( isEmpty(fooBar) || isEmpty({'__additionalEmptyValues__' : [false, '0']}, someArray, someSet, someString, value) ){\n * ...\n * }\n * }\n */\nexport function isEmpty(){\n\tlet\n\t\tres = true,\n\t\temptyValues = [undefined, null, '', 0]\n\t;\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( isArray(obj?.__additionalEmptyValues__) ){\n\t\t\temptyValues = emptyValues.concat(obj.__additionalEmptyValues__);\n\t\t}\n\t});\n\temptyValues = Array.from(new Set(emptyValues));\n\n\tArray.from(arguments).forEach(obj => {\n\t\tif( res && !isArray(obj?.__additionalEmptyValues__) ){\n\t\t\tres = emptyValues.includes(obj);\n\n\t\t\tif( !res ){\n\t\t\t\tres = (size(obj) === 0);\n\t\t\t}\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:hasMembers\n */\n\n/**\n * \"Validates\" an object in a very basic way by checking if all given members are present and are not nullish.\n *\n * @param {Object} obj - the object to check\n * @param {String[]} memberNames - the names of the members to check\n * @param {Boolean} [verbose=false] - defines if method should output missing members to console\n * @returns {Boolean} all memberNames present and not nullish\n *\n * @memberof Basic:hasMembers\n * @alias hasMembers\n * @example\n * function pat(kitten){\n * if( hasMembers(kitten, ['fluff', 'meow', 'scratch']) ){\n * ...\n * }\n * }\n */\nexport function hasMembers(obj, memberNames, verbose=false){\n\tmemberNames = orDefault(memberNames, [], 'arr');\n\tverbose = orDefault(verbose, false, 'bool');\n\n\tlet res = true;\n\n\tmemberNames.forEach(memberName => {\n\t\tif( !hasValue(obj[`${memberName}`]) ){\n\t\t\tif( verbose ){\n\t\t\t\tlog().info(`${MODULE_NAME}:hasMembers | missing member ${memberName}`);\n\t\t\t}\n\n\t\t\tres = false;\n\t\t}\n\t});\n\n\treturn res;\n}\n\n\n\n/**\n * @namespace Basic:orDefault\n */\n\n/**\n * If an expression returns a non-value (undefined or null), use the default value instead.\n * Define a caster name, to force expression result/value into certain data type.\n *\n * @param {*} expression - the expression to evaluate\n * @param {*} defaultValue - the default value to use if the expression is considered empty\n * @param {?(String|Function)} [caster=null] - either a default caster by name ('str', 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'arr', 'array') or a function getting the value and returning the transformed value\n * @param {?Array} [additionalEmptyValues=null] - if set, provides a list of additional values to be considered empty, apart from undefined and null\n * @returns {*} expression of defaultValue\n *\n * @memberof Basic:orDefault\n * @alias orDefault\n * @example\n * function set(name, value){\n * name = orDefault(name, 'kittens!', 'string', ['', 'none']);\n * value = orDefault(value, 42, 'int');\n * }\n */\nexport function orDefault(expression, defaultValue, caster=null, additionalEmptyValues=null){\n\tif( hasValue(additionalEmptyValues) ){\n\t\tadditionalEmptyValues = [].concat(additionalEmptyValues);\n\t} else {\n\t\tadditionalEmptyValues = [];\n\t}\n\n\tif( hasValue(caster) ){\n\t\tif(\n\t\t\t!isFunction(caster)\n\t\t\t&& ([\n\t\t\t\t'str', 'string',\n\t\t\t\t'int', 'integer',\n\t\t\t\t'bool', 'boolean',\n\t\t\t\t'float',\n\t\t\t\t'arr', 'array'\n\t\t\t].includes(`${caster.toLowerCase()}`))\n\t\t){\n\t\t\tcaster = `${caster}`.toLowerCase();\n\n\t\t\tif( ['str', 'string'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return `${value}`; };\n\t\t\t} else if( ['int', 'integer'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return parseInt(value, 10); };\n\t\t\t} else if( ['bool', 'boolean'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return !!value; };\n\t\t\t} else if( caster === 'float' ){\n\t\t\t\tcaster = function(value){ return parseFloat(value); };\n\t\t\t} else if( ['arr', 'array'].includes(caster) ){\n\t\t\t\tcaster = function(value){ return [].concat(value); };\n\t\t\t}\n\t\t} else if( !isFunction(caster) ){\n\t\t\tcaster = function(value){ return value; };\n\t\t}\n\t} else {\n\t\tcaster = function(value){ return value; };\n\t}\n\n\tif( !hasValue(expression) || (additionalEmptyValues.includes(expression)) ){\n\t\treturn defaultValue;\n\t} else {\n\t\treturn caster(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:getType\n */\n\n/**\n * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on\n * useful frontend types like \"htmldocument\", \"htmlelement\", \"htmlcollection\" and \"nodelist\"\n *\n * Types:\n * - \"undefined\"\n * - \"null\"\n * - \"boolean\"\n * - \"number\"\n * - \"bigint\"\n * - \"string\"\n * - \"symbol\"\n * - \"function\"\n * - \"object\"\n * - \"array\"\n * - \"date\"\n * - \"error\"\n * - \"generator\"\n * - \"iterator\"\n * - \"regexp\"\n * - \"set\"\n * - \"weakset\"\n * - \"map\"\n * - \"weakmap\"\n * - \"htmldocument\"\n * - \"htmlelement\"\n * - \"htmlcollection\"\n * - \"nodelist\"\n * - \"window\"\n *\n * @param {*} [value] - variable to check the type of\n * @returns {String} the value type in lower case\n *\n * @memberof Basic:getType\n * @alias getType\n * @example\n * if( getType(cb) === 'function' ){\n * ...\n * }\n */\nexport function getType(value) {\n\tif( !hasValue(value) ) return `${value}`.toLowerCase();\n\n\tconst deepType = Object.prototype.toString.call(value).slice(8,-1).toLowerCase();\n\n\tif( deepType === 'generatorfunction' ) return 'function';\n\tif( deepType === 'document' ) return 'htmldocument';\n\tif( deepType === 'element' ) return 'htmlelement';\n\tif( /^html.*element$/.test(deepType) ) return 'htmlelement';\n\tif( /^.*iterator$/.test(deepType) ) return 'iterator';\n\n\treturn deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/)\n\t\t? deepType\n\t\t: ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isA\n */\n\n/**\n * Short form of \"getType\"-method with a more compact syntax.\n * Can identify all types listed in getType.\n *\n * @param {*} value - variable to check the type of\n * @param {String} type - the name of the type to check for, has to be a standard JS-type, is case insensitive\n * @returns {Boolean} target has type\n *\n * @memberof Basic:isA\n * @alias isA\n * @see getType\n * @example\n * let stringBool = (isA(test, 'boolean') && test) ? 'true' : 'false';\n */\nexport function isA(value, type){\n\tif(\n\t\t[\n\t\t\t'undefined',\n\t\t\t'null',\n\t\t\t'boolean',\n\t\t\t'number',\n\t\t\t'bigint',\n\t\t\t'string',\n\t\t\t'symbol',\n\t\t\t'function',\n\t\t\t'object',\n\t\t\t'array',\n\t\t\t'date',\n\t\t\t'error',\n\t\t\t'generator',\n\t\t\t'iterator',\n\t\t\t'regexp',\n\t\t\t'set',\n\t\t\t'weakset',\n\t\t\t'map',\n\t\t\t'weakmap',\n\t\t\t'htmldocument',\n\t\t\t'htmlelement',\n\t\t\t'htmlcollection',\n\t\t\t'nodelist',\n\t\t\t'window'\n\t\t].includes(`${type}`.toLowerCase())\n\t){\n\t\treturn getType(value) === `${type}`.toLowerCase();\n\t} else {\n\t\twarn(`${MODULE_NAME}:isA | \"${type}\" is not a recognized type`);\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isBoolean\n */\n\n/**\n * Returns if a value is a boolean value.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a boolean\n *\n * @memberof Basic:isBoolean\n * @alias isBoolean\n * @example\n * if( isBoolean(val) ){\n * console.log('val must be either true or false');\n * }\n */\nexport function isBoolean(value){\n\treturn isA(value, 'boolean');\n}\n\n\n\n/**\n * @namespace Basic:isNumber\n */\n\n/**\n * Returns if a value is a number.\n *\n * Hint: to check numbers in more detail, use isInt, isFloat and isNaN\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a number\n *\n * @memberof Basic:isNumber\n * @alias isNumber\n * @see isInt\n * @see isFloat\n * @see isNaN\n * @example\n * if( isNumber(val) ){\n * result = val * 5;\n * }\n */\nexport function isNumber(value){\n\treturn isA(value, 'number');\n}\n\n\n\n/**\n * @namespace Basic:isBigInt\n */\n\n/**\n * Returns if a value is a BigInt value.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a BigInt\n *\n * @memberof Basic:isBigInt\n * @alias isBigInt\n * @example\n * if( isBigInt(val) ){\n * console.log('this is a really huge number!');\n * }\n */\nexport function isBigInt(value){\n\treturn isA(value, 'bigint');\n}\n\n\n\n/**\n * @namespace Basic:isInt\n */\n\n/**\n * Returns if a value is truly a real integer value and not just an int-parsable value for example.\n * Since JS only knows the data type \"number\" all numbers are usable as floats by default, but not the\n * other way round.\n *\n * @param {*} intVal - the value the check\n * @returns {Boolean} true if intVal is a true integer value\n *\n * @memberof Basic:isInt\n * @alias isInt\n * @example\n * if( !isInt(val) ){\n * val = parseInt(val, 10);\n * }\n */\nexport function isInt(intVal){\n\treturn parseInt(intVal, 10) === intVal;\n}\n\n\n\n/**\n * @namespace Basic:isFloat\n */\n\n/**\n * Returns if a value is a numeric value, usable as a float number in any calculation.\n * Any number that fulfills isInt, is also considered a valid float, which lies in JS's\n * nature of not differentiating ints and floats by putting them both into a \"number\"-type.\n * So ints are always floats, but not necessarily the other way round.\n *\n * @param {*} floatVal - the value to check\n * @returns {Boolean} true if floatVal is usable in a float context\n *\n * @memberof Basic:isFloat\n * @alias isFloat\n * @example\n * if( !isFloat(val) ){\n * alert('val can not be calculated with!');\n * }\n */\nexport function isFloat(floatVal){\n\treturn parseFloat(floatVal) === floatVal;\n}\n\n\n\n/**\n * @namespace Basic:isNaN\n */\n\n/**\n * Returns if an expression is NaN or not.\n * This method employs two different approaches:\n * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something.\n * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being\n * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which\n * inspects the expression, tries to cast or parse a number from it and returns the result.\n *\n * @param {*} expression - the expression to check\n * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality\n * @returns {Boolean} true if expression is NaN\n *\n * @memberof Basic:isNaN\n * @alias isNaN\n * @example\n * if( !isNaN(suspiciousCalculatedValue) ){\n * return suspiciousCalculatedValue * 3;\n * }\n */\nexport function isNaN(expression, checkForIdentity=true){\n\tcheckForIdentity = orDefault(checkForIdentity, true, 'bool');\n\n\tif( checkForIdentity ){\n\t\treturn expression !== expression;\n\t} else {\n\t\treturn isNaN(expression);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:isString\n */\n\n/**\n * Returns if a value is a string.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a string\n *\n * @memberof Basic:isString\n * @alias isString\n * @example\n * if( isString(val) ){\n * return prefix+val;\n * }\n */\nexport function isString(value){\n\treturn isA(value, 'string');\n}\n\n\n\n/**\n * @namespace Basic:isSymbol\n */\n\n/**\n * Returns if a value is a symbol.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a symbol\n *\n * @memberof Basic:isSymbol\n * @alias isSymbol\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol\n * @example\n * if( isSymbol(val) ){\n * return val.description;\n * }\n */\nexport function isSymbol(value){\n\treturn isA(value, 'symbol');\n}\n\n\n\n/**\n * @namespace Basic:isFunction\n */\n\n/**\n * Returns if a value is a function.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a function\n *\n * @memberof Basic:isFunction\n * @alias isFunction\n * @example\n * if( isFunction(val) ){\n * val();\n * }\n */\nexport function isFunction(value){\n\treturn isA(value, 'function');\n}\n\n\n\n/**\n * @namespace Basic:isObject\n */\n\n/**\n * Returns if a value is an object.\n *\n * Hint: if you explicitly want to check for a plain object, use isPlainObject\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an object\n *\n * @memberof Basic:isObject\n * @alias isObject\n * @see isPlainObject\n * @example\n * if( isObject(val) ){\n * val.newProperty = 'foobar';\n * }\n */\nexport function isObject(value){\n\treturn isA(value, 'object');\n}\n\n\n\n/**\n * @namespace Basic:isPlainObject\n */\n\n/**\n * Returns if a value is an object literal, so so-called \"plain object.\n * A plain object is something like \"{hello : 'world'}\".\n *\n * This might especially be helpful when dealing with JSON configs, so quickly check if\n * something might even be parsed JSON (which in most cases is a plain object in js).\n *\n * Be aware that this function cannot differentiate between constructor-based simple objects and\n * plain objects declared inline. So, if someone took on the work to instantiate a base object and assign\n * properties either in a function or a constructor, we accept that as a plain object.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value seems to be a plain object\n *\n * @memberof Basic:isPlainObject\n * @alias isPlainObject\n * @example\n * const isParameterConfigObject = isPlainObject(param);\n */\nexport function isPlainObject(value){\n\treturn isObject(value)\n\t\t&& hasValue(value)\n\t\t&& (value.constructor === Object)\n\t\t&& Object.prototype.toString.call(value) === '[object Object]'\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isArray\n */\n\n/**\n * Returns if a value is an array.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an array\n *\n * @memberof Basic:isArray\n * @alias isArray\n * @example\n * if( isArray(val) ){\n * val.push('foobar');\n * }\n */\nexport function isArray(value){\n\treturn isA(value, 'array');\n}\n\n\n\n/**\n * @namespace Basic:isDate\n */\n\n/**\n * Returns if a value is a date.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a date\n *\n * @memberof Basic:isDate\n * @alias isDate\n * @example\n * if( isDate(val) ){\n * return val.toISOString();\n * }\n */\nexport function isDate(value){\n\treturn isA(value, 'date');\n}\n\n\n\n/**\n * @namespace Basic:isError\n */\n\n/**\n * Returns if a value is an error.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an error\n *\n * @memberof Basic:isError\n * @alias isError\n * @example\n * if( isError(val) ){\n * return val.message;\n * }\n */\nexport function isError(value){\n\treturn isA(value, 'error');\n}\n\n\n\n/**\n * @namespace Basic:isGenerator\n */\n\n/**\n * Returns if a value is a generator.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a generator\n *\n * @memberof Basic:isGenerator\n * @alias isGenerator\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator\n * @example\n * if( isGenerator(val) ){\n * return val.return(val.next().value);\n * }\n */\nexport function isGenerator(value){\n\treturn isA(value, 'generator');\n}\n\n\n\n/**\n * @namespace Basic:isIterator\n */\n\n/**\n * Returns if a value is an iterator.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an iterator\n *\n * @memberof Basic:isIterator\n * @alias isIterator\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator\n * @example\n * if( isIterator(val) ){\n * return val.next().value;\n * }\n */\nexport function isIterator(value){\n\treturn isA(value, 'iterator');\n}\n\n\n\n/**\n * @namespace Basic:isRegExp\n */\n\n/**\n * Returns if a value is a regular expression.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a regular expression\n *\n * @memberof Basic:isRegExp\n * @alias isRegExp\n * @example\n * if( isRegExp(val) ){\n * return val.test('foobar');\n * }\n */\nexport function isRegExp(value){\n\treturn isA(value, 'regexp');\n}\n\n\n\n/**\n * @namespace Basic:isSet\n */\n\n/**\n * Returns if a value is a set.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a set\n *\n * @memberof Basic:isSet\n * @alias isSet\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set\n * @example\n * if( isSet(val) ){\n * return val.has('foobar');\n * }\n */\nexport function isSet(value){\n\treturn isA(value, 'set');\n}\n\n\n\n/**\n * @namespace Basic:isWeakSet\n */\n\n/**\n * Returns if a value is a weak set.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a weak set\n *\n * @memberof Basic:isWeakSet\n * @alias isWeakSet\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet\n * @example\n * if( isWeakSet(val) ){\n * return val.has(someSymbol);\n * }\n */\nexport function isWeakSet(value){\n\treturn isA(value, 'weakset');\n}\n\n\n\n/**\n * @namespace Basic:isMap\n */\n\n/**\n * Returns if a value is a map.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a map\n *\n * @memberof Basic:isMap\n * @alias isMap\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map\n * @example\n * if( isMap(val) ){\n * return val.get('foobar');\n * }\n */\nexport function isMap(value){\n\treturn isA(value, 'map');\n}\n\n\n\n/**\n * @namespace Basic:isWeakMap\n */\n\n/**\n * Returns if a value is a weak map.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a weak map\n *\n * @memberof Basic:isWeakMap\n * @alias isWeakMap\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap\n * @example\n * if( isWeakMap(val) ){\n * return val.get('foobar');\n * }\n */\nexport function isWeakMap(value){\n\treturn isA(value, 'weakmap');\n}\n\n\n\n/**\n * @namespace Basic:isDocument\n */\n\n/**\n * Returns if a value is an HTML document.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an HTML document\n *\n * @memberof Basic:isDocument\n * @alias isDocument\n * @example\n * if( isDocument(val) ){\n * return val.body;\n * }\n */\nexport function isDocument(value){\n\treturn isA(value, 'htmldocument');\n}\n\n\n\n/**\n * @namespace Basic:isElement\n */\n\n/**\n * Returns if a value is an HTML element.\n * Be aware, that this explicitly means an element, not necessarily any node.\n * So text nodes, comments and such do not qualify.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is an HTML element\n *\n * @memberof Basic:isElement\n * @alias isElement\n * @example\n * if( isElement(target) ){\n * target.classList.add('foo');\n * }\n */\nexport function isElement(value){\n\treturn isA(value, 'htmlelement');\n}\n\n\n\n/**\n * @namespace Basic:isCollection\n */\n\n/**\n * Returns if a value is a collection of html elements.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a collection of html elements\n *\n * @memberof Basic:isCollection\n * @alias isCollection\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection\n * @example\n * if( isCollection(val) ){\n * return val.item(0);\n * }\n */\nexport function isCollection(value){\n\treturn isA(value, 'htmlcollection');\n}\n\n\n\n/**\n * @namespace Basic:isNodeList\n */\n\n/**\n * Returns if a value is a node list.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a node list\n *\n * @memberof Basic:isNodeList\n * @alias isNodeList\n * @see https://developer.mozilla.org/en-US/docs/Web/API/NodeList\n * @example\n * if( isNodeList(val) ){\n * return val.item(0);\n * }\n */\nexport function isNodeList(value){\n\treturn isA(value, 'nodelist');\n}\n\n\n\n/**\n * @namespace Basic:isWindow\n */\n\n/**\n * Returns if a value is a window.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a window\n *\n * @memberof Basic:isWindow\n * @alias isWindow\n * @example\n * if( isWindow(val) ){\n * return val.location.origin;\n * }\n */\nexport function isWindow(value){\n\treturn isA(value, 'window');\n}\n\n\n\n/**\n * @namespace Basic:isEventTarget\n */\n\n/**\n * Returns if a value is an EventTarget, which means that it is able to dispatch and receive events.\n * This is determined via duck-typing and not via class inheritance check, since this method is not\n * about type-safety, but the question if we can use the target for events, which is simply determined\n * by three essential object methods: addEventListener, removeEventListener and dispatchEvent. All\n * objects supporting these are fine with us.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value supports event methods\n *\n * @memberof Basic:isEventTarget\n * @alias isEventTarget\n * @example\n * if( isEventTarget(target) ){\n * target.dispatchEvent(new CustomEvent('foobar'));\n * }\n */\nexport function isEventTarget(value){\n\treturn hasValue(value)\n\t\t&& isFunction(value.addEventListener)\n\t\t&& isFunction(value.removeEventListener)\n\t\t&& isFunction(value.dispatchEvent)\n\t;\n}\n\n\n\n/**\n * @namespace Basic:isSelector\n */\n\n/**\n * Returns if a value is a valid selector, usable in methods such as querySelector\n * and querySelectorAll.\n *\n * @param {*} value - the value to check\n * @returns {Boolean} true if value is a valid selector\n *\n * @memberof Basic:isSelector\n * @alias isSelector\n * @example\n * if( isSelector(selector) ){\n * document.querySelector(selector)?.style.setProperty('color', 'red');\n * }\n */\nexport function isSelector(value){\n\t// almost all values like \"null\", \"undefined\" and \"NaN\" are accepted querySelectors, numbers are not\n\tvalue = orDefault(value, 0, 'str');\n\n\tconst fragment = document.createDocumentFragment();\n\n\ttry {\n\t\tfragment.querySelector(value);\n\t} catch(ex){\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n\n\n/**\n * @namespace Basic:isPotentialId\n */\n\n/**\n * Determines if a given value is potentially a valid id for something, because it matches a format of given\n * prefix, postfix and id regex. \"Potential\", because we can only assume by the format, we do not actually know\n * if the id really matches anything like a database entry for example.\n *\n * @param {(String|Number)} value - the value to test, will be stringified\n * @param {?String} [prefix=''] - a prefix for the id\n * @param {?String} [idRex='[1-9][0-9]*'] - the regex string to use to identify the id part of the value\n * @param {?String} [postfix=''] - a postfix for the id\n * @param {?Boolean} [maskFixes=true] - usually, prefixes are not treated as regexes and are automatically masked, if you'd like to define complex pre- and postfixes using regexes, set this to false\n * @returns {String|Boolean} if value is potential id according to format, the id is returned as a string (still usable as a truthy value), otherwise the return value is false\n *\n * @memberof Basic:isPotentialId\n * @alias isPotentialId\n * @example\n * if( isPotentialId(id, 'test_(', '[0-9]+', ')') ){\n * createJsonRequest(`/backend/${id}`).then(() => { alert('done'); });\n * }\n */\nexport function isPotentialId(value, prefix='', idRex='[1-9][0-9]*', postfix='', maskFixes=true){\n\tvalue = `${value}`;\n\tprefix = orDefault(prefix, '', 'str');\n\tidRex = orDefault(idRex, '[1-9][0-9]*', 'str');\n\tpostfix = orDefault(postfix, '', 'str');\n\tmaskFixes = orDefault(maskFixes, true, 'bool');\n\n\tconst mask = str => `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n\n\tlet rex;\n\tif( maskFixes ){\n\t\trex = new RegExp(`^${mask(prefix)}(${idRex})${mask(postfix)}$`);\n\t} else {\n\t\trex = new RegExp(`^${prefix}(${idRex})${postfix}$`);\n\t}\n\n\tconst matches = rex.exec(value);\n\treturn hasValue(matches) ? matches[1] : false;\n}\n\n\n\n/**\n * @namespace Basic:minMax\n */\n\n/**\n * Checks if a value is within bounds of a minimum and maximum and returns\n * the value or the upper or lower bound respectively.\n *\n * Accepts all values comparable with > and <.\n *\n * @param {*} min - the lower bound\n * @param {*} value - the value to check\n * @param {*} max - the upper bound\n * @throws error if min is not smaller than max\n * @returns {*} value, min or max\n *\n * @memberof Basic:minMax\n * @alias minMax\n * @example\n * let croppedVal = minMax(-100, value, 100);\n */\nexport function minMax(min, value, max){\n\tassert(min <= max, `${MODULE_NAME}:minMax | min can not be larger than max`);\n\n\treturn (value < min)\n\t\t? min\n\t\t: (\n\t\t\t(value > max)\n\t\t\t\t? max\n\t\t\t\t: value\n\t\t)\n\t;\n}\n\n\n\n/**\n * @namespace Basic:Deferred\n */\n\n/**\n * @typedef Deferred\n * @type {Object}\n * @property {Promise} promise - the wrapped promise\n * @property {Function} resolve - resolves the wrapped promise with given value\n * @property {Function} reject - rejects the wrapped promise with given error\n * @property {Function} then - defines a success handler for the wrapped promise and returns its result\n * @property {Function} catch - defines an error handler for the wrapped promise and returns its result\n * @property {Function} finally - defines a \"settled\" handler for the wrapped promise and returns its result\n * @property {String} status - holds the current resolution status, can either be \"pending\", \"fulfilled\" or \"rejected\"\n * @property {Function} isSettled - returns true, if the Deferred is either \"fulfilled\" or \"rejected\"\n * @property {?*} [provision=null] - may contain (a) provisional value(s) to use for a newly instantiated Deferred, before it has resolved to the actual value(s)\n */\n\n/**\n * Class that wraps a Promise, to allow resolving and rejecting outside the\n * Promise's function scope. This allows for decoupled handling of states and\n * handling promises as references in a distributed context, like a class, where\n * a Deferred might then represent an async state.\n *\n * Deferreds also provide accessible status information, normal Promises do not have.\n * Accessing the \"status\" property returns the current status, being either \"pending\",\n * \"fulfilled\" or \"rejected\". You may also check if the Deferred has been settled via\n * \"isSettled()\". If you want to provide a preliminary result, available before the\n * promise has settled, you may set this result as a payload using the \"provision\" property.\n *\n * This follows ideas by jQuery and Q Promises:\n * - https://api.jquery.com/jQuery.Deferred/\n * - https://github.com/kriskowal/q/wiki/Coming-from-jQuery#deferreds-promises-resolvers\n *\n * Keep in mind, that Promises might need a polyfill such as core-js.\n *\n * @memberof Basic:Deferred\n * @name Deferred\n * @example\n * const doStuff = new Deferred();\n * doStuff.provision = 'provisional value';\n * doStuff\n * .then(value => { alert(`yeah, ready with \"${value}\"!`); })\n * .catch(error => { console.error(error); })\n * .finally(() => { console.info('has been settled); })\n * ;\n * if( foobar === 42 ){\n * doStuff.resolve(42);\n * } else {\n * doStuff.reject(new Error('not 42!'));\n * }\n * console.info(doStuff.status);\n */\nexport class Deferred {\n\tconstructor(){\n\t\tconst\n\t\t\tSTATUS_PENDING = 'pending',\n\t\t\tSTATUS_FULFILLED = 'fulfilled',\n\t\t\tSTATUS_REJECTED = 'rejected'\n\t\t;\n\t\tthis.resolve = null;\n\t\tthis.reject = null;\n\t\tthis.provision = null;\n\t\tthis.status = STATUS_PENDING;\n\t\tthis.isSettled = () => [STATUS_FULFILLED, STATUS_REJECTED].includes(this.status);\n\t\tthis.promise = new Promise((resolve, reject) => {\n\t\t\tthis.resolve = resolution => {\n\t\t\t\tthis.status = STATUS_FULFILLED;\n\t\t\t\tresolve(resolution);\n\t\t\t};\n\t\t\tthis.reject = rejection => {\n\t\t\t\tthis.status = STATUS_REJECTED;\n\t\t\t\treject(rejection);\n\t\t\t};\n\t\t});\n\t}\n\n\tthen(f){\n\t\treturn this.promise.then(f);\n\t}\n\n\tcatch(f){\n\t\treturn this.promise.catch(f);\n\t}\n\n\tfinally(f){\n\t\treturn this.promise.finally(f);\n\t}\n}\n\n\n\n/**\n * @namespace Basic:Observable\n */\n\n/**\n * @typedef Observable\n * @type {Object}\n * @property {Function} getValue - returns the current value\n * @property {Function} setValue - sets a new value, which will subsequently trigger all subscriptions\n * @property {Function} subscribe - register a given function to be executed on any value change, the subscription receives the new and the old value on each execution, returns the subscription value, which can later be used to unsubscribe again\n * @property {Function} unsubscribe - removes a given subscription again, use subscription value returned by subscribe here\n */\n\n/**\n * A class offering the bare minimum feature set to observe a value and subscribe to future value changes.\n * No automatic magic going on here, this simply follows a basic subscription pattern, where each subscription is\n * a function, being called with a newly set value. This closely resembles the kind of observables knockout is using.\n *\n * @memberof Basic:Observable\n * @name Observable\n * @example\n * const status = new Observable('ok');\n * const subscription = status.subscribe(s => {\n * console.log(`status changed to: ${s}`);\n * });\n * status.setValue('oh noez');\n * status.unsubscribe(subscription);\n */\nexport class Observable {\n\tconstructor(initialValue){\n\t\tthis.__className__ = 'Observable';\n\t\tthis._value = initialValue;\n\t\tthis._subscriptions = [];\n\t}\n\n\tgetValue(){\n\t\treturn this._value;\n\t}\n\n\tsetValue(newValue, force=false){\n\t\tconst\n\t\t\toldValue = this._value,\n\t\t\tisNewValue = oldValue !== newValue\n\t\t;\n\t\tthis._value = newValue;\n\t\tif( isNewValue || force ){\n\t\t\tthis._subscriptions.forEach(s => s(newValue, oldValue));\n\t\t}\n\t}\n\n\tsubscribe(subscription){\n\t\tconst __methodName__ = 'subscribe';\n\t\tassert(isFunction(subscription), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`);\n\t\tif( this._subscriptions.indexOf(subscription) < 0 ){\n\t\t\tthis._subscriptions = [...this._subscriptions, subscription];\n\t\t}\n\t\treturn subscription;\n\t}\n\n\tunsubscribe(subscription){\n\t\tthis._subscriptions = this._subscriptions.filter(s => s !== subscription);\n\t}\n\n\ttoString(){\n\t\treturn `${this._value}`;\n\t}\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/context.js b/docs/examples/lib/annex/dist/context.js index de852cc8..091bc847 100644 --- a/docs/examples/lib/annex/dist/context.js +++ b/docs/examples/lib/annex/dist/context.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Context */ -const MODULE_NAME="Context";import{hasValue,isA,orDefault,Observable}from"./basic.js";import{throttle}from"./functions.js";import{reschedule}from"./timers.js";const INTERACTION_TYPE_DETECTION={touchHappening:!1,touchEndingTimer:null,touchStartHandler(){INTERACTION_TYPE_DETECTION.touchHappening=!0,"touch"!==CURRENT_INTERACTION_TYPE.getValue()&&CURRENT_INTERACTION_TYPE.setValue("touch")},touchEndHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},blurHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},mouseMoveHandler:throttle(1e3,(function(){CURRENT_INTERACTION_TYPE.getValue("pointer")&&!INTERACTION_TYPE_DETECTION.touchHappening&&CURRENT_INTERACTION_TYPE.setValue("pointer")}))};export let CURRENT_INTERACTION_TYPE;export function browserSupportsHistoryManipulation(){return hasValue(window.history)&&isA(window.history.pushState,"function")&&isA(window.history.replaceState,"function")}export function contextHasHighDpi(){return!!window.matchMedia&&window.matchMedia("only screen and (-webkit-min-device-pixel-ratio: 1.5),only screen and (-o-min-device-pixel-ratio: 3/2),only screen and (min--moz-device-pixel-ratio: 1.5),only screen and (min-device-pixel-ratio: 1.5),only screen and (min-resolution: 144dpi),only screen and (min-resolution: 1.5dppx)").matches}export function getBrowserScrollbarWidth(){const e=document.createElement("div");e.style.visibility="hidden",e.style.opacity="0",e.style.pointerEvents="none",e.style.overflow="scroll",e.style.position="fixed",e.style.top="0",e.style.right="0",e.style.left="0",e.style.height="50px";const t=document.createElement("div");t.style.width="100%",t.style.height="100px",e.appendChild(t),document.body.appendChild(e);const n=e.offsetWidth-t.offsetWidth;return document.body.removeChild(e),n}export function detectInteractionType(e=!1){return e=orDefault(e,!1,"bool"),hasValue(CURRENT_INTERACTION_TYPE)||(CURRENT_INTERACTION_TYPE=new Observable(""),"ontouchstart"in document&&"ontouchend"in document&&window.navigator.maxTouchPoints>0?CURRENT_INTERACTION_TYPE.setValue("touch"):CURRENT_INTERACTION_TYPE.setValue("pointer"),document.addEventListener("touchstart",INTERACTION_TYPE_DETECTION.touchStartHandler),document.addEventListener("touchend",INTERACTION_TYPE_DETECTION.touchEndHandler),window.addEventListener("blur",INTERACTION_TYPE_DETECTION.blurHandler),document.addEventListener("mousemove",INTERACTION_TYPE_DETECTION.mouseMoveHandler)),e?CURRENT_INTERACTION_TYPE:CURRENT_INTERACTION_TYPE.getValue()}export function detectAppleDevice(e=null){let t=/iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),n=null;if(Array.isArray(t)&&t.length>0?t=t[0]:(t=/^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform),Array.isArray(t)&&t.length>0?(t=t[0],"Mac"===t&&(t="Macintosh")):t=null),hasValue(t)){switch("Macintosh"===t&&window.navigator.maxTouchPoints>1&&(t="iPad"),t){case"iPad":n="ipad";break;case"iPhone":n="iphone";break;case"iPod":n="ipod";break;case"Macintosh":n="mac"}isA(e,"function")&&(n=e(n))}return n}export function getBrowserLanguage(e=null){let t=null;if(hasValue(window.navigator.languages)){const e=Array.from(window.navigator.languages);isA(e,"array")&&e.length>0&&(t=`${e[0]}`)}hasValue(t)||["language","browserLanguage","userLanguage","systemLanguage"].forEach((e=>{if(!hasValue(t)){const n=window.navigator[e];t=hasValue(n)?`${n}`:null}})),!hasValue(t)&&hasValue(e)&&(t=`${e}`);const n=t.split("-");t=n[0].toLowerCase().trim();const o=n?.[1]?.toUpperCase()?.trim();return t=hasValue(o)?`${t}-${o}`:t,t}export function getLocale(e=null,t=null){e=orDefault(e,document.documentElement);const n={code:null,country:null,language:null,isFallback:!1};let o=isA(e.getAttribute,"function")?e.getAttribute("lang"):null;if(!hasValue(o)&&hasValue(t)&&(o=`${t}`,n.isFallback=!0),hasValue(o)){const e=`${o}`.split("-");n.country=e?.[1]?.toLowerCase()?.trim(),n.language=e[0].toLowerCase().trim(),n.code=hasValue(n.country)?`${n.language}-${n.country.toUpperCase()}`:n.language}return n}export function getBrowserLocale(e=null){return getLocale({getAttribute:()=>getBrowserLanguage(e)},e)} +const MODULE_NAME="Context";import{hasValue,isFunction,isArray,orDefault,Observable}from"./basic.js";import{throttle}from"./functions.js";import{reschedule}from"./timers.js";const INTERACTION_TYPE_DETECTION={touchHappening:!1,touchEndingTimer:null,touchStartHandler(){INTERACTION_TYPE_DETECTION.touchHappening=!0,"touch"!==CURRENT_INTERACTION_TYPE.getValue()&&CURRENT_INTERACTION_TYPE.setValue("touch")},touchEndHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},blurHandler(){INTERACTION_TYPE_DETECTION.touchEndingTimer=reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer,1032,(()=>{INTERACTION_TYPE_DETECTION.touchHappening=!1}))},mouseMoveHandler:throttle(1e3,(function(){CURRENT_INTERACTION_TYPE.getValue("pointer")&&!INTERACTION_TYPE_DETECTION.touchHappening&&CURRENT_INTERACTION_TYPE.setValue("pointer")}))};export let CURRENT_INTERACTION_TYPE;export function browserSupportsHistoryManipulation(){return hasValue(window.history)&&isFunction(window.history.pushState)&&isFunction(window.history.replaceState)}export function contextHasHighDpi(){return!!window.matchMedia&&window.matchMedia("only screen and (-webkit-min-device-pixel-ratio: 1.5),only screen and (-o-min-device-pixel-ratio: 3/2),only screen and (min--moz-device-pixel-ratio: 1.5),only screen and (min-device-pixel-ratio: 1.5),only screen and (min-resolution: 144dpi),only screen and (min-resolution: 1.5dppx)").matches}export function getBrowserScrollbarWidth(){const e=document.createElement("div");e.style.visibility="hidden",e.style.opacity="0",e.style.pointerEvents="none",e.style.overflow="scroll",e.style.position="fixed",e.style.top="0",e.style.right="0",e.style.left="0",e.style.height="50px";const t=document.createElement("div");t.style.width="100%",t.style.height="100px",e.appendChild(t),document.body.appendChild(e);const n=e.offsetWidth-t.offsetWidth;return document.body.removeChild(e),n}export function detectInteractionType(e=!1){return e=orDefault(e,!1,"bool"),hasValue(CURRENT_INTERACTION_TYPE)||(CURRENT_INTERACTION_TYPE=new Observable(""),"ontouchstart"in document&&"ontouchend"in document&&window.navigator.maxTouchPoints>0?CURRENT_INTERACTION_TYPE.setValue("touch"):CURRENT_INTERACTION_TYPE.setValue("pointer"),document.addEventListener("touchstart",INTERACTION_TYPE_DETECTION.touchStartHandler),document.addEventListener("touchend",INTERACTION_TYPE_DETECTION.touchEndHandler),window.addEventListener("blur",INTERACTION_TYPE_DETECTION.blurHandler),document.addEventListener("mousemove",INTERACTION_TYPE_DETECTION.mouseMoveHandler)),e?CURRENT_INTERACTION_TYPE:CURRENT_INTERACTION_TYPE.getValue()}export function detectAppleDevice(e=null){let t=/iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),n=null;if(Array.isArray(t)&&t.length>0?t=t[0]:(t=/^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform),Array.isArray(t)&&t.length>0?(t=t[0],"Mac"===t&&(t="Macintosh")):t=null),hasValue(t)){switch("Macintosh"===t&&window.navigator.maxTouchPoints>1&&(t="iPad"),t){case"iPad":n="ipad";break;case"iPhone":n="iphone";break;case"iPod":n="ipod";break;case"Macintosh":n="mac"}isFunction(e)&&(n=e(n))}return n}export function getBrowserLanguage(e=null){let t=null;if(hasValue(window.navigator.languages)){const e=Array.from(window.navigator.languages);isArray(e)&&e.length>0&&(t=`${e[0]}`)}hasValue(t)||["language","browserLanguage","userLanguage","systemLanguage"].forEach((e=>{if(!hasValue(t)){const n=window.navigator[e];t=hasValue(n)?`${n}`:null}})),!hasValue(t)&&hasValue(e)&&(t=`${e}`);const n=t.split("-");t=n[0].toLowerCase().trim();const o=n?.[1]?.toUpperCase()?.trim();return t=hasValue(o)?`${t}-${o}`:t,t}export function getLocale(e=null,t=null){e=orDefault(e,document.documentElement);const n={code:null,country:null,language:null,isFallback:!1};let o=isFunction(e.getAttribute)?e.getAttribute("lang"):null;if(!hasValue(o)&&hasValue(t)&&(o=`${t}`,n.isFallback=!0),hasValue(o)){const e=`${o}`.split("-");n.country=e?.[1]?.toLowerCase()?.trim(),n.language=e[0].toLowerCase().trim(),n.code=hasValue(n.country)?`${n.language}-${n.country.toUpperCase()}`:n.language}return n}export function getBrowserLocale(e=null){return getLocale({getAttribute:()=>getBrowserLanguage(e)},e)} //# sourceMappingURL=context.js.map diff --git a/docs/examples/lib/annex/dist/context.js.map b/docs/examples/lib/annex/dist/context.js.map index 3297b540..22880d00 100644 --- a/docs/examples/lib/annex/dist/context.js.map +++ b/docs/examples/lib/annex/dist/context.js.map @@ -1 +1 @@ -{"version":3,"file":"context.js","names":["MODULE_NAME","hasValue","isA","orDefault","Observable","throttle","reschedule","INTERACTION_TYPE_DETECTION","touchHappening","touchEndingTimer","touchStartHandler","CURRENT_INTERACTION_TYPE","getValue","setValue","touchEndHandler","blurHandler","mouseMoveHandler","browserSupportsHistoryManipulation","window","history","pushState","replaceState","contextHasHighDpi","matchMedia","matches","getBrowserScrollbarWidth","sandbox","document","createElement","style","visibility","opacity","pointerEvents","overflow","position","top","right","left","height","scrollbarEnforcer","width","appendChild","body","scrollbarWidth","offsetWidth","removeChild","detectInteractionType","returnObservable","navigator","maxTouchPoints","addEventListener","detectAppleDevice","additionalTest","family","exec","userAgent","deviceType","Array","isArray","length","platform","getBrowserLanguage","fallbackLanguage","language","languages","browserLanguages","from","forEach","browserLanguagePropertyKey","browserLanguage","languageParts","split","toLowerCase","trim","country","toUpperCase","getLocale","element","documentElement","locale","code","isFallback","langAttr","getAttribute","localeParts","getBrowserLocale"],"sources":["context.js"],"mappings":"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","sourcesContent":["/*!\n * Module Context\n */\n\n/**\n * @namespace Context\n */\n\nconst MODULE_NAME = 'Context';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {hasValue, isA, orDefault, Observable} from './basic.js';\nimport {throttle} from './functions.js';\nimport {reschedule} from './timers.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst INTERACTION_TYPE_DETECTION = {\n\ttouchHappening : false,\n\ttouchEndingTimer : null,\n\ttouchStartHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchHappening = true;\n\t\tif( CURRENT_INTERACTION_TYPE.getValue() !== 'touch' ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t}\n\t},\n\ttouchEndHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tblurHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tmouseMoveHandler : throttle(1000, function(){\n\t\tif( (CURRENT_INTERACTION_TYPE.getValue('pointer')) && !INTERACTION_TYPE_DETECTION.touchHappening ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\t})\n};\n\nexport let CURRENT_INTERACTION_TYPE;\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Context:browserSupportsHistoryManipulation\n */\n\n/**\n * Detects if the browser supports history manipulation, by checking the most common\n * methods for presence in the history-object.\n *\n * @returns {Boolean} true if browser seems to support history manipulation\n *\n * @memberof Context:browserSupportsHistoryManipulation\n * @alias browserSupportsHistoryManipulation\n * @example\n * if( browserSupportsHistoryManipulation() ){\n * window.history.replaceState(null, 'test', '/test');\n * }\n */\nexport function browserSupportsHistoryManipulation(){\n\treturn hasValue(window.history)\n\t\t&& isA(window.history.pushState, 'function')\n\t\t&& isA(window.history.replaceState, 'function')\n\t;\n}\n\n\n\n/**\n * @namespace Context:contextHasHighDpi\n */\n\n/**\n * Checks if the context would benefit from high DPI graphics.\n *\n * @returns {Boolean} true if device has high DPI, false if not or browser does not support media queries\n *\n * @memberof Context:contextHasHighDpi\n * @alias contextHasHighDpi\n * @example\n * if( contextHasHighDpi() ){\n * document.querySelectorAll('img').forEach(img => {\n * img.setAttribute('src', img.getAttribute('src').replace('.jpg', '@2x.jpg'));\n * });\n * }\n */\nexport function contextHasHighDpi(){\n\tif( window.matchMedia ){\n\t\treturn window.matchMedia(\n\t\t\t'only screen and (-webkit-min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (-o-min-device-pixel-ratio: 3/2),'\n\t\t\t+'only screen and (min--moz-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-resolution: 144dpi),'\n\t\t\t+'only screen and (min-resolution: 1.5dppx)'\n\t\t).matches;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Context:getBrowserScrollbarWidth\n */\n\n/**\n * Returns the current context's scrollbar width. Returns 0 if scrollbar is over content.\n * There are edge cases in which we might want to calculate positions in respect to the\n * actual width of the scrollbar. For example when working with elements with a 100vw width.\n *\n * This method temporarily inserts three elements into the body while forcing the body to\n * actually show scrollbars, measuring the difference between 100vw and 100% on the body and\n * returns the result.\n *\n * @returns {Number} the width of the body scrollbar in pixels\n *\n * @memberof Context:getBrowserScrollbarWidth\n * @alias getBrowserScrollbarWidth\n * @example\n * foobarElement.style.width = `calc(100vw - ${getBrowserScrollbarWidth()}px)`;\n */\nexport function getBrowserScrollbarWidth(){\n\tconst sandbox = document.createElement('div');\n\tsandbox.style.visibility = 'hidden';\n\tsandbox.style.opacity = '0';\n\tsandbox.style.pointerEvents = 'none';\n\tsandbox.style.overflow = 'scroll';\n\tsandbox.style.position = 'fixed';\n\tsandbox.style.top = '0';\n\tsandbox.style.right = '0';\n\tsandbox.style.left = '0';\n\t// firefox needs container to be at least 30px high to display scrollbar\n\tsandbox.style.height = '50px';\n\n\tconst scrollbarEnforcer = document.createElement('div');\n\tscrollbarEnforcer.style.width = '100%';\n\tscrollbarEnforcer.style.height = '100px';\n\n\tsandbox.appendChild(scrollbarEnforcer);\n\tdocument.body.appendChild(sandbox);\n\n\tconst scrollbarWidth = sandbox.offsetWidth - scrollbarEnforcer.offsetWidth;\n\n\tdocument.body.removeChild(sandbox);\n\n\treturn scrollbarWidth;\n}\n\n\n\n/**\n * @namespace Context:detectInteractionType\n */\n\n/**\n * Try to figure out the current type of interaction between the user and the document.\n * This is determined by the input device and is currently limited to either \"pointer\" or \"touch\".\n *\n * On call the function returns an educated guess about the fact what interaction type might be more\n * probable based on browser features and sets up event listeners to update Context module's CURRENT_INTERACTION_TYPE\n * observable (to which you may subscribe to be informed about updates), when interaction type should change while\n * the page is being interacted with. In case a touch occurs we determine touch interaction and\n * on mousemove we determine pointer interaction. If you use this observable to set up a class on your document for\n * example you can even relatively safely handle dual devices like a surface book.\n *\n * Hint: because touch devices also emit a single mousemove after touchend with a single touch we have to block\n * mousemove detection for 1s after the last touchend. Therefore, it takes up to 1s after the last touch event until\n * we are able to detect the change to a pointer device.\n *\n * @param {?Boolean} [returnObservable=false] - if set to true, the call returns Context module's CURRENT_INTERACTION_TYPE observable\n * @returns {String|Observable} interaction type string \"pointer\" or \"touch\", or the CURRENT_INTERACTION_TYPE observable\n *\n * @memberof Context:detectInteractionType\n * @alias detectInteractionType\n * @example\n * let interactionTypeGuess = detectInteractionType();\n * detectInteractionType(true).subscribe(function(type){\n * document.body.classList.toggle('touch', type === 'touch');\n * });\n */\n\nexport function detectInteractionType(returnObservable=false){\n\treturnObservable = orDefault(returnObservable, false, 'bool');\n\n\tif( !hasValue(CURRENT_INTERACTION_TYPE) ){\n\t\tCURRENT_INTERACTION_TYPE = new Observable('');\n\t\tif( ('ontouchstart' in document) && ('ontouchend' in document) && (window.navigator.maxTouchPoints > 0) ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t} else {\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\n\t\tdocument.addEventListener('touchstart', INTERACTION_TYPE_DETECTION.touchStartHandler);\n\t\tdocument.addEventListener('touchend', INTERACTION_TYPE_DETECTION.touchEndHandler);\n\t\twindow.addEventListener('blur', INTERACTION_TYPE_DETECTION.blurHandler);\n\t\tdocument.addEventListener('mousemove', INTERACTION_TYPE_DETECTION.mouseMoveHandler);\n\t}\n\n\treturn returnObservable ? CURRENT_INTERACTION_TYPE : CURRENT_INTERACTION_TYPE.getValue();\n}\n\n\n\n/**\n * @namespace Context:detectAppleDevice\n */\n\n/**\n * Try to determine if the execution context is an Apple device and if so: which type.\n *\n * We use an escalating test starting with the user agent and then, as a fallback, checking the platform value\n * to determine the general device class (iPhone, iPad ,iPod ,Macintosh). If we get a Macintosh, we double check\n * if the device might be a falsely reporting iPad with iPadOS13+.\n *\n * You can hook up additional tests by providing an \"additionalTest\" function as a function parameter,\n * that function takes the evaluated device type at the end of the function and expects a new device type to be\n * returned. Using this, you can tap into the process and handle edge cases yourself.\n *\n * @param {?Function} [additionalTest=null] - if set, is executed after determining the device type, takes the current device type as parameter and is expected to return a new one; use this to add edge case tests to overwrite the result in certain conditions\n * @returns {String} \"ipad\", \"iphone\", \"ipod\" or \"mac\"\n *\n * @memberof Context:detectAppleDevice\n * @alias detectAppleDevice\n * @example\n * const IS_IOS_DEVICE = ['iphone', 'ipod', 'ipad'].includes(detectAppleDevice());\n */\nexport function detectAppleDevice(additionalTest=null){\n\tlet\n\t\tfamily = /iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),\n\t\tdeviceType = null\n\t;\n\n\tif( Array.isArray(family) && (family.length > 0) ){\n\t\tfamily = family[0];\n\t} else {\n\t\tfamily = /^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform);\n\n\t\tif( Array.isArray(family) && (family.length > 0) ){\n\t\t\tfamily = family[0];\n\n\t\t\tif( family === 'Mac' ){\n\t\t\t\tfamily = 'Macintosh';\n\t\t\t}\n\t\t} else {\n\t\t\tfamily = null;\n\t\t}\n\t}\n\n\tif( hasValue(family) ){\n\t\t// If User-Agent reports Macintosh double check this against touch points, since the device might\n\t\t// be a disguised iPad with i(Pad)Os13+\n\t\tif(\n\t\t\t(family === 'Macintosh')\n\t\t\t&& (window.navigator.maxTouchPoints > 1)\n\t\t){\n\t\t\tfamily = 'iPad';\n\t\t}\n\n\t\tswitch( family ) {\n\t\t\tcase 'iPad':\n\t\t\t\tdeviceType = 'ipad';\n\t\t\tbreak;\n\t\t\tcase 'iPhone':\n\t\t\t\tdeviceType = 'iphone';\n\t\t\tbreak;\n\t\t\tcase 'iPod':\n\t\t\t\tdeviceType = 'ipod';\n\t\t\tbreak;\n\t\t\tcase 'Macintosh':\n\t\t\t\tdeviceType = 'mac';\n\t\t\tbreak;\n\t\t}\n\n\t\tif( isA(additionalTest, 'function') ){\n\t\t\tdeviceType = additionalTest(deviceType);\n\t\t}\n\t}\n\n\treturn deviceType;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLanguage\n */\n\n/**\n * Evaluates all available browser languages and tries to return the preferred one.\n *\n * Since browsers could not agree on a uniform way to return language values yet, the returned language\n * will always be \"lowercaselanguage-UPPERCASECOUNTRY\" or just \"lowercaselanguage\", if we have no country.\n *\n * @param {?String} [fallbackLanguage=null] - fallback value to return if no language could be evaluated\n * @returns {String|null} the preferred browser language if available, null if no language can be detected and no fallback has been defined\n *\n * @memberof Context:getBrowserLanguage\n * @alias getBrowserLanguage\n * @see getBrowserLocale\n * @example\n * getBrowserLanguage()\n * => \"en\"\n */\nexport function getBrowserLanguage(fallbackLanguage=null){\n\tlet language = null;\n\n\tif( hasValue(window.navigator.languages) ){\n\t\tconst browserLanguages = Array.from(window.navigator.languages);\n\t\tif( isA(browserLanguages, 'array') && (browserLanguages.length > 0) ){\n\t\t\tlanguage = `${browserLanguages[0]}`;\n\t\t}\n\t}\n\n\tif( !hasValue(language) ){\n\t\t['language', 'browserLanguage', 'userLanguage', 'systemLanguage'].forEach(browserLanguagePropertyKey => {\n\t\t\tif( !hasValue(language) ){\n\t\t\t\tconst browserLanguage = window.navigator[browserLanguagePropertyKey];\n\t\t\t\tlanguage = hasValue(browserLanguage) ? `${browserLanguage}` : null;\n\t\t\t}\n\t\t});\n\t}\n\n\tif( !hasValue(language) && hasValue(fallbackLanguage) ){\n\t\tlanguage = `${fallbackLanguage}`;\n\t}\n\n\tconst languageParts = language.split('-');\n\tlanguage = languageParts[0].toLowerCase().trim();\n\tconst country = languageParts?.[1]?.toUpperCase()?.trim();\n\tlanguage = hasValue(country) ? `${language}-${country}` : language;\n\n\treturn language;\n}\n\n\n\n/**\n * @namespace Context:getLocale\n */\n\n/**\n * Evaluates the document's locale by having a look at the HTML element's lang-attribute.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?HTMLElement} [element=document.documentElement] - the element holding the lang-attribute to evaluate\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if element holds no lang information\n * @returns {Object} the locale as an object, having the lang value as \"code\", the split-up parts in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getLocale\n * @alias getLocale\n * @see getBrowserLocale\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang\n * @example\n * getLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getLocale(document.querySelector('p'), 'en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getLocale(element=null, fallbackLanguage=null){\n\t// document.documentElement not as function default to prevent errors in document-less context on import\n\telement = orDefault(element, document.documentElement);\n\n\tconst locale = {\n\t\tcode : null,\n\t\tcountry : null,\n\t\tlanguage : null,\n\t\tisFallback : false\n\t};\n\n\tlet langAttr = isA(element.getAttribute, 'function') ? element.getAttribute('lang') : null;\n\tif( !hasValue(langAttr) && hasValue(fallbackLanguage) ){\n\t\tlangAttr = `${fallbackLanguage}`;\n\t\tlocale.isFallback = true;\n\t}\n\n\tif( hasValue(langAttr) ){\n\t\tconst localeParts = `${langAttr}`.split('-');\n\t\tlocale.country = localeParts?.[1]?.toLowerCase()?.trim();\n\t\tlocale.language = localeParts[0].toLowerCase().trim();\n\t\tlocale.code = hasValue(locale.country) ? `${locale.language}-${locale.country.toUpperCase()}` : locale.language;\n\t}\n\n\treturn locale;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLocale\n */\n\n/**\n * Evaluates the browser's locale by having a look at the preferred browser language, as reported by `getBrowserLanguage`.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if browser reports no preferred language\n * @returns {Object} the locale as an object, having the in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getBrowserLocale\n * @alias getBrowserLocale\n * @see getBrowserLanguage\n * @example\n * getBrowserLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getBrowserLocale('en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getBrowserLocale(fallbackLanguage=null){\n\treturn getLocale({getAttribute(){ return getBrowserLanguage(fallbackLanguage); }}, fallbackLanguage);\n}\n"]} \ No newline at end of file +{"version":3,"file":"context.js","names":["MODULE_NAME","hasValue","isFunction","isArray","orDefault","Observable","throttle","reschedule","INTERACTION_TYPE_DETECTION","touchHappening","touchEndingTimer","touchStartHandler","CURRENT_INTERACTION_TYPE","getValue","setValue","touchEndHandler","blurHandler","mouseMoveHandler","browserSupportsHistoryManipulation","window","history","pushState","replaceState","contextHasHighDpi","matchMedia","matches","getBrowserScrollbarWidth","sandbox","document","createElement","style","visibility","opacity","pointerEvents","overflow","position","top","right","left","height","scrollbarEnforcer","width","appendChild","body","scrollbarWidth","offsetWidth","removeChild","detectInteractionType","returnObservable","navigator","maxTouchPoints","addEventListener","detectAppleDevice","additionalTest","family","exec","userAgent","deviceType","Array","length","platform","getBrowserLanguage","fallbackLanguage","language","languages","browserLanguages","from","forEach","browserLanguagePropertyKey","browserLanguage","languageParts","split","toLowerCase","trim","country","toUpperCase","getLocale","element","documentElement","locale","code","isFallback","langAttr","getAttribute","localeParts","getBrowserLocale"],"sources":["context.js"],"mappings":"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","sourcesContent":["/*!\n * Module Context\n */\n\n/**\n * @namespace Context\n */\n\nconst MODULE_NAME = 'Context';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {hasValue, isFunction, isArray, orDefault, Observable} from './basic.js';\nimport {throttle} from './functions.js';\nimport {reschedule} from './timers.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst INTERACTION_TYPE_DETECTION = {\n\ttouchHappening : false,\n\ttouchEndingTimer : null,\n\ttouchStartHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchHappening = true;\n\t\tif( CURRENT_INTERACTION_TYPE.getValue() !== 'touch' ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t}\n\t},\n\ttouchEndHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tblurHandler(){\n\t\tINTERACTION_TYPE_DETECTION.touchEndingTimer = reschedule(INTERACTION_TYPE_DETECTION.touchEndingTimer, 1032, () => {\n\t\t\tINTERACTION_TYPE_DETECTION.touchHappening = false;\n\t\t});\n\t},\n\tmouseMoveHandler : throttle(1000, function(){\n\t\tif( (CURRENT_INTERACTION_TYPE.getValue('pointer')) && !INTERACTION_TYPE_DETECTION.touchHappening ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\t})\n};\n\nexport let CURRENT_INTERACTION_TYPE;\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Context:browserSupportsHistoryManipulation\n */\n\n/**\n * Detects if the browser supports history manipulation, by checking the most common\n * methods for presence in the history-object.\n *\n * @returns {Boolean} true if browser seems to support history manipulation\n *\n * @memberof Context:browserSupportsHistoryManipulation\n * @alias browserSupportsHistoryManipulation\n * @example\n * if( browserSupportsHistoryManipulation() ){\n * window.history.replaceState(null, 'test', '/test');\n * }\n */\nexport function browserSupportsHistoryManipulation(){\n\treturn hasValue(window.history)\n\t\t&& isFunction(window.history.pushState)\n\t\t&& isFunction(window.history.replaceState)\n\t;\n}\n\n\n\n/**\n * @namespace Context:contextHasHighDpi\n */\n\n/**\n * Checks if the context would benefit from high DPI graphics.\n *\n * @returns {Boolean} true if device has high DPI, false if not or browser does not support media queries\n *\n * @memberof Context:contextHasHighDpi\n * @alias contextHasHighDpi\n * @example\n * if( contextHasHighDpi() ){\n * document.querySelectorAll('img').forEach(img => {\n * img.setAttribute('src', img.getAttribute('src').replace('.jpg', '@2x.jpg'));\n * });\n * }\n */\nexport function contextHasHighDpi(){\n\tif( window.matchMedia ){\n\t\treturn window.matchMedia(\n\t\t\t'only screen and (-webkit-min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (-o-min-device-pixel-ratio: 3/2),'\n\t\t\t+'only screen and (min--moz-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-device-pixel-ratio: 1.5),'\n\t\t\t+'only screen and (min-resolution: 144dpi),'\n\t\t\t+'only screen and (min-resolution: 1.5dppx)'\n\t\t).matches;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n\n\n/**\n * @namespace Context:getBrowserScrollbarWidth\n */\n\n/**\n * Returns the current context's scrollbar width. Returns 0 if scrollbar is over content.\n * There are edge cases in which we might want to calculate positions in respect to the\n * actual width of the scrollbar. For example when working with elements with a 100vw width.\n *\n * This method temporarily inserts three elements into the body while forcing the body to\n * actually show scrollbars, measuring the difference between 100vw and 100% on the body and\n * returns the result.\n *\n * @returns {Number} the width of the body scrollbar in pixels\n *\n * @memberof Context:getBrowserScrollbarWidth\n * @alias getBrowserScrollbarWidth\n * @example\n * foobarElement.style.width = `calc(100vw - ${getBrowserScrollbarWidth()}px)`;\n */\nexport function getBrowserScrollbarWidth(){\n\tconst sandbox = document.createElement('div');\n\tsandbox.style.visibility = 'hidden';\n\tsandbox.style.opacity = '0';\n\tsandbox.style.pointerEvents = 'none';\n\tsandbox.style.overflow = 'scroll';\n\tsandbox.style.position = 'fixed';\n\tsandbox.style.top = '0';\n\tsandbox.style.right = '0';\n\tsandbox.style.left = '0';\n\t// firefox needs container to be at least 30px high to display scrollbar\n\tsandbox.style.height = '50px';\n\n\tconst scrollbarEnforcer = document.createElement('div');\n\tscrollbarEnforcer.style.width = '100%';\n\tscrollbarEnforcer.style.height = '100px';\n\n\tsandbox.appendChild(scrollbarEnforcer);\n\tdocument.body.appendChild(sandbox);\n\n\tconst scrollbarWidth = sandbox.offsetWidth - scrollbarEnforcer.offsetWidth;\n\n\tdocument.body.removeChild(sandbox);\n\n\treturn scrollbarWidth;\n}\n\n\n\n/**\n * @namespace Context:detectInteractionType\n */\n\n/**\n * Try to figure out the current type of interaction between the user and the document.\n * This is determined by the input device and is currently limited to either \"pointer\" or \"touch\".\n *\n * On call the function returns an educated guess about the fact what interaction type might be more\n * probable based on browser features and sets up event listeners to update Context module's CURRENT_INTERACTION_TYPE\n * observable (to which you may subscribe to be informed about updates), when interaction type should change while\n * the page is being interacted with. In case a touch occurs we determine touch interaction and\n * on mousemove we determine pointer interaction. If you use this observable to set up a class on your document for\n * example you can even relatively safely handle dual devices like a surface book.\n *\n * Hint: because touch devices also emit a single mousemove after touchend with a single touch we have to block\n * mousemove detection for 1s after the last touchend. Therefore, it takes up to 1s after the last touch event until\n * we are able to detect the change to a pointer device.\n *\n * @param {?Boolean} [returnObservable=false] - if set to true, the call returns Context module's CURRENT_INTERACTION_TYPE observable\n * @returns {String|Observable} interaction type string \"pointer\" or \"touch\", or the CURRENT_INTERACTION_TYPE observable\n *\n * @memberof Context:detectInteractionType\n * @alias detectInteractionType\n * @example\n * let interactionTypeGuess = detectInteractionType();\n * detectInteractionType(true).subscribe(function(type){\n * document.body.classList.toggle('touch', type === 'touch');\n * });\n */\n\nexport function detectInteractionType(returnObservable=false){\n\treturnObservable = orDefault(returnObservable, false, 'bool');\n\n\tif( !hasValue(CURRENT_INTERACTION_TYPE) ){\n\t\tCURRENT_INTERACTION_TYPE = new Observable('');\n\t\tif( ('ontouchstart' in document) && ('ontouchend' in document) && (window.navigator.maxTouchPoints > 0) ){\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('touch');\n\t\t} else {\n\t\t\tCURRENT_INTERACTION_TYPE.setValue('pointer');\n\t\t}\n\n\t\tdocument.addEventListener('touchstart', INTERACTION_TYPE_DETECTION.touchStartHandler);\n\t\tdocument.addEventListener('touchend', INTERACTION_TYPE_DETECTION.touchEndHandler);\n\t\twindow.addEventListener('blur', INTERACTION_TYPE_DETECTION.blurHandler);\n\t\tdocument.addEventListener('mousemove', INTERACTION_TYPE_DETECTION.mouseMoveHandler);\n\t}\n\n\treturn returnObservable ? CURRENT_INTERACTION_TYPE : CURRENT_INTERACTION_TYPE.getValue();\n}\n\n\n\n/**\n * @namespace Context:detectAppleDevice\n */\n\n/**\n * Try to determine if the execution context is an Apple device and if so: which type.\n *\n * We use an escalating test starting with the user agent and then, as a fallback, checking the platform value\n * to determine the general device class (iPhone, iPad ,iPod ,Macintosh). If we get a Macintosh, we double check\n * if the device might be a falsely reporting iPad with iPadOS13+.\n *\n * You can hook up additional tests by providing an \"additionalTest\" function as a function parameter,\n * that function takes the evaluated device type at the end of the function and expects a new device type to be\n * returned. Using this, you can tap into the process and handle edge cases yourself.\n *\n * @param {?Function} [additionalTest=null] - if set, is executed after determining the device type, takes the current device type as parameter and is expected to return a new one; use this to add edge case tests to overwrite the result in certain conditions\n * @returns {String} \"ipad\", \"iphone\", \"ipod\" or \"mac\"\n *\n * @memberof Context:detectAppleDevice\n * @alias detectAppleDevice\n * @example\n * const IS_IOS_DEVICE = ['iphone', 'ipod', 'ipad'].includes(detectAppleDevice());\n */\nexport function detectAppleDevice(additionalTest=null){\n\tlet\n\t\tfamily = /iPhone|iPad|iPod|Macintosh/.exec(window.navigator.userAgent),\n\t\tdeviceType = null\n\t;\n\n\tif( Array.isArray(family) && (family.length > 0) ){\n\t\tfamily = family[0];\n\t} else {\n\t\tfamily = /^(iPhone|iPad|iPod|Mac)/.exec(window.navigator.platform);\n\n\t\tif( Array.isArray(family) && (family.length > 0) ){\n\t\t\tfamily = family[0];\n\n\t\t\tif( family === 'Mac' ){\n\t\t\t\tfamily = 'Macintosh';\n\t\t\t}\n\t\t} else {\n\t\t\tfamily = null;\n\t\t}\n\t}\n\n\tif( hasValue(family) ){\n\t\t// If User-Agent reports Macintosh double check this against touch points, since the device might\n\t\t// be a disguised iPad with i(Pad)Os13+\n\t\tif(\n\t\t\t(family === 'Macintosh')\n\t\t\t&& (window.navigator.maxTouchPoints > 1)\n\t\t){\n\t\t\tfamily = 'iPad';\n\t\t}\n\n\t\tswitch( family ) {\n\t\t\tcase 'iPad':\n\t\t\t\tdeviceType = 'ipad';\n\t\t\tbreak;\n\t\t\tcase 'iPhone':\n\t\t\t\tdeviceType = 'iphone';\n\t\t\tbreak;\n\t\t\tcase 'iPod':\n\t\t\t\tdeviceType = 'ipod';\n\t\t\tbreak;\n\t\t\tcase 'Macintosh':\n\t\t\t\tdeviceType = 'mac';\n\t\t\tbreak;\n\t\t}\n\n\t\tif( isFunction(additionalTest) ){\n\t\t\tdeviceType = additionalTest(deviceType);\n\t\t}\n\t}\n\n\treturn deviceType;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLanguage\n */\n\n/**\n * Evaluates all available browser languages and tries to return the preferred one.\n *\n * Since browsers could not agree on a uniform way to return language values yet, the returned language\n * will always be \"lowercaselanguage-UPPERCASECOUNTRY\" or just \"lowercaselanguage\", if we have no country.\n *\n * @param {?String} [fallbackLanguage=null] - fallback value to return if no language could be evaluated\n * @returns {String|null} the preferred browser language if available, null if no language can be detected and no fallback has been defined\n *\n * @memberof Context:getBrowserLanguage\n * @alias getBrowserLanguage\n * @see getBrowserLocale\n * @example\n * getBrowserLanguage()\n * => \"en\"\n */\nexport function getBrowserLanguage(fallbackLanguage=null){\n\tlet language = null;\n\n\tif( hasValue(window.navigator.languages) ){\n\t\tconst browserLanguages = Array.from(window.navigator.languages);\n\t\tif( isArray(browserLanguages) && (browserLanguages.length > 0) ){\n\t\t\tlanguage = `${browserLanguages[0]}`;\n\t\t}\n\t}\n\n\tif( !hasValue(language) ){\n\t\t['language', 'browserLanguage', 'userLanguage', 'systemLanguage'].forEach(browserLanguagePropertyKey => {\n\t\t\tif( !hasValue(language) ){\n\t\t\t\tconst browserLanguage = window.navigator[browserLanguagePropertyKey];\n\t\t\t\tlanguage = hasValue(browserLanguage) ? `${browserLanguage}` : null;\n\t\t\t}\n\t\t});\n\t}\n\n\tif( !hasValue(language) && hasValue(fallbackLanguage) ){\n\t\tlanguage = `${fallbackLanguage}`;\n\t}\n\n\tconst languageParts = language.split('-');\n\tlanguage = languageParts[0].toLowerCase().trim();\n\tconst country = languageParts?.[1]?.toUpperCase()?.trim();\n\tlanguage = hasValue(country) ? `${language}-${country}` : language;\n\n\treturn language;\n}\n\n\n\n/**\n * @namespace Context:getLocale\n */\n\n/**\n * Evaluates the document's locale by having a look at the HTML element's lang-attribute.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?HTMLElement} [element=document.documentElement] - the element holding the lang-attribute to evaluate\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if element holds no lang information\n * @returns {Object} the locale as an object, having the lang value as \"code\", the split-up parts in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getLocale\n * @alias getLocale\n * @see getBrowserLocale\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang\n * @example\n * getLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getLocale(document.querySelector('p'), 'en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getLocale(element=null, fallbackLanguage=null){\n\t// document.documentElement not as function default to prevent errors in document-less context on import\n\telement = orDefault(element, document.documentElement);\n\n\tconst locale = {\n\t\tcode : null,\n\t\tcountry : null,\n\t\tlanguage : null,\n\t\tisFallback : false\n\t};\n\n\tlet langAttr = isFunction(element.getAttribute) ? element.getAttribute('lang') : null;\n\tif( !hasValue(langAttr) && hasValue(fallbackLanguage) ){\n\t\tlangAttr = `${fallbackLanguage}`;\n\t\tlocale.isFallback = true;\n\t}\n\n\tif( hasValue(langAttr) ){\n\t\tconst localeParts = `${langAttr}`.split('-');\n\t\tlocale.country = localeParts?.[1]?.toLowerCase()?.trim();\n\t\tlocale.language = localeParts[0].toLowerCase().trim();\n\t\tlocale.code = hasValue(locale.country) ? `${locale.language}-${locale.country.toUpperCase()}` : locale.language;\n\t}\n\n\treturn locale;\n}\n\n\n\n/**\n * @namespace Context:getBrowserLocale\n */\n\n/**\n * Evaluates the browser's locale by having a look at the preferred browser language, as reported by `getBrowserLanguage`.\n *\n * Since browsers could not agree on a uniform way to return locale values yet, the returned \"code\" will always be\n * \"lowercaselanguage-UPPERCASECOUNTRY\" (or just \"lowercaselanguage\", if we have no country), regardless of how the\n * browser returns the value, while \"country\" and \"language\" will always be lower case.\n *\n * @param {?String} [fallbackLanguage=null] - if defined, a fallback lang value if browser reports no preferred language\n * @returns {Object} the locale as an object, having the in \"country\" and \"language\" (if available) and \"isFallback\" to tell us if the fallback had to be used\n *\n * @memberof Context:getBrowserLocale\n * @alias getBrowserLocale\n * @see getBrowserLanguage\n * @example\n * getBrowserLocale()\n * => {\n * code : 'en-GB',\n * country : 'gb',\n * language : 'en',\n * isFallback : false\n * }\n * getBrowserLocale('en-US')\n * => {\n * code : 'en-US',\n * country : 'us',\n * language : 'en',\n * isFallback : true\n * }\n */\nexport function getBrowserLocale(fallbackLanguage=null){\n\treturn getLocale({getAttribute(){ return getBrowserLanguage(fallbackLanguage); }}, fallbackLanguage);\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/cookies.js b/docs/examples/lib/annex/dist/cookies.js index db9aa856..b5939730 100644 --- a/docs/examples/lib/annex/dist/cookies.js +++ b/docs/examples/lib/annex/dist/cookies.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Cookies */ -const MODULE_NAME="Cookies";import{assert,isA,orDefault,hasValue}from"./basic.js";import{warn}from"./logging.js";function encodeCookieValue(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}function decodeCookieValue(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)}function encodeCookieName(e){return encodeURIComponent(`${e}`).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape)}function decodeCookieName(e){return decodeURIComponent(e)}function normalizeCookieOptions(e){e=orDefault(e,{});const o={};for(let t in e)o[t.toLowerCase()]=e[t];return hasValue((e=o).expires)?(isA(e.expires,"date")||(e.expires=new Date(Date.now()+24*Math.round(parseFloat(e.expires))*60*60*1e3)),e.expires=e.expires.toUTCString()):e.expires=null,e["max-age"]=orDefault(e["max-age"],null,"int"),e.path=orDefault(e.path,"/","str"),"auto"===e.path&&(e.path=""),e.domain=orDefault(e.domain,null,"str"),e.httponly=orDefault(e.httponly,!1,"bool"),e.samesite=orDefault(e.samesite,"lax","str").toLowerCase(),["strict","lax","none"].includes(e.samesite)||console.warn(`Cookies:setCookie | unknown samesite mode "${e.samesite}"`),e.secure=orDefault(e.secure,"none"===e.samesite,"bool"),e}export function getCookie(e){const o=hasValue(e)?new Set([].concat(e).map((e=>e.trim()))):new Set,t=new Set;let n=0===o.size?{}:null;if(!hasValue(document.cookie))return n;const i=document.cookie.split(";");for(let e in i)try{const a=i[e].trim().split("="),r=decodeCookieName(a[0]).trim(),s=decodeCookieValue(a.slice(1).join("="));if(""!==r&&(o.has(r)||0===o.size)&&(null===n&&(n={}),n[r]=s,t.add(r),t.size===o.size&&0!==o.size))break}catch(o){warn(`Cookies:getCookie | decoding cookie "${i[e]}" failed with "${o}"`)}return 1===o.size?n?.[e]??null:n}export function getCookies(e){return e=[],Array.from(arguments).forEach((o=>{e=e.concat(o)})),getCookie(e)}export function setCookie(e,o,t){assert(hasValue(e)&&""!==e,"Cookies:setCookie | no usable name"),e=`${e}`.trim(),o=hasValue(o)?encodeCookieValue(orDefault(o,"","str")):null,t=normalizeCookieOptions(t);let n="";for(let e in t){const o=t[e];hasValue(o)&&!1!==o&&(n+=`; ${e}`,!0!==o&&(n+=`=${o.split(";")[0]}`))}return hasValue(o)?document.cookie=`${encodeCookieName(e)}=${o}${n}`:removeCookie(e,t),getCookie(e)}export function removeCookie(e,o){return assert(hasValue(e)&&""!==e,"Cookies:removeCookie | no usable name"),(o=normalizeCookieOptions(o)).expires=-1,null===setCookie(e,"",o)} +const MODULE_NAME="Cookies";import{assert,isDate,orDefault,hasValue}from"./basic.js";import{warn}from"./logging.js";function encodeCookieValue(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}function decodeCookieValue(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)}function encodeCookieName(e){return encodeURIComponent(`${e}`).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape)}function decodeCookieName(e){return decodeURIComponent(e)}function normalizeCookieOptions(e){e=orDefault(e,{});const o={};for(let t in e)o[t.toLowerCase()]=e[t];return hasValue((e=o).expires)?(isDate(e.expires)||(e.expires=new Date(Date.now()+24*Math.round(parseFloat(e.expires))*60*60*1e3)),e.expires=e.expires.toUTCString()):e.expires=null,e["max-age"]=orDefault(e["max-age"],null,"int"),e.path=orDefault(e.path,"/","str"),"auto"===e.path&&(e.path=""),e.domain=orDefault(e.domain,null,"str"),e.httponly=orDefault(e.httponly,!1,"bool"),e.samesite=orDefault(e.samesite,"lax","str").toLowerCase(),["strict","lax","none"].includes(e.samesite)||console.warn(`Cookies:setCookie | unknown samesite mode "${e.samesite}"`),e.secure=orDefault(e.secure,"none"===e.samesite,"bool"),e}export function getCookie(e){const o=hasValue(e)?new Set([].concat(e).map((e=>e.trim()))):new Set,t=new Set;let n=0===o.size?{}:null;if(!hasValue(document.cookie))return n;const i=document.cookie.split(";");for(let e in i)try{const a=i[e].trim().split("="),r=decodeCookieName(a[0]).trim(),s=decodeCookieValue(a.slice(1).join("="));if(""!==r&&(o.has(r)||0===o.size)&&(null===n&&(n={}),n[r]=s,t.add(r),t.size===o.size&&0!==o.size))break}catch(o){warn(`Cookies:getCookie | decoding cookie "${i[e]}" failed with "${o}"`)}return 1===o.size?n?.[e]??null:n}export function getCookies(e){return e=[],Array.from(arguments).forEach((o=>{e=e.concat(o)})),getCookie(e)}export function setCookie(e,o,t){assert(hasValue(e)&&""!==e,"Cookies:setCookie | no usable name"),e=`${e}`.trim(),o=hasValue(o)?encodeCookieValue(orDefault(o,"","str")):null,t=normalizeCookieOptions(t);let n="";for(let e in t){const o=t[e];hasValue(o)&&!1!==o&&(n+=`; ${e}`,!0!==o&&(n+=`=${o.split(";")[0]}`))}return hasValue(o)?document.cookie=`${encodeCookieName(e)}=${o}${n}`:removeCookie(e,t),getCookie(e)}export function removeCookie(e,o){return assert(hasValue(e)&&""!==e,"Cookies:removeCookie | no usable name"),(o=normalizeCookieOptions(o)).expires=-1,null===setCookie(e,"",o)} //# sourceMappingURL=cookies.js.map diff --git a/docs/examples/lib/annex/dist/cookies.js.map b/docs/examples/lib/annex/dist/cookies.js.map index 1210d9ce..5663c8f1 100644 --- a/docs/examples/lib/annex/dist/cookies.js.map +++ b/docs/examples/lib/annex/dist/cookies.js.map @@ -1 +1 @@ -{"version":3,"file":"cookies.js","names":["MODULE_NAME","assert","isA","orDefault","hasValue","warn","encodeCookieValue","value","encodeURIComponent","replace","decodeURIComponent","decodeCookieValue","slice","encodeCookieName","name","escape","decodeCookieName","normalizeCookieOptions","options","normalizedOptions","optionsProp","toLowerCase","expires","Date","now","Math","round","parseFloat","toUTCString","path","domain","httponly","samesite","includes","console","secure","getCookie","names","Set","concat","map","n","trim","foundNames","res","size","document","cookie","cookies","split","i","cookieParts","cookieName","cookieValue","join","has","add","ex","getCookies","Array","from","arguments","forEach","argument","setCookie","cookieOptions","option","removeCookie"],"sources":["cookies.js"],"mappings":"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","sourcesContent":["/*!\n * Module Cookies\n */\n\n/**\n * @namespace Cookies\n */\n\nconst MODULE_NAME = 'Cookies';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isA, orDefault, hasValue} from './basic.js';\nimport {warn} from './logging.js';\n\n\n\n//###[ HELPERS ]########################################################################################################\n\n/*\n * Encodes a string to be stored in a cookie.\n *\n * @private\n */\nfunction encodeCookieValue(value){\n\treturn encodeURIComponent(value).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g, decodeURIComponent);\n}\n\n\n\n/*\n * Decodes a cookie value to be used as a string in JavaScript.\n *\n * @private\n */\nfunction decodeCookieValue(value){\n\tif( value[0] === '\"' ){\n\t\tvalue = value.slice(1, -1);\n\t}\n\treturn value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent);\n}\n\n\n\n/*\n * Makes sure a cookie name conforms to the cookie name rules and translates special chars to % representations.\n *\n * @private\n */\nfunction encodeCookieName(name){\n\treturn encodeURIComponent(`${name}`)\n\t\t.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n\t\t// using escape, because encodeURIComponent, indeed, does _not_ encode brackets\n\t\t.replace(/[()]/g, escape)\n\t;\n}\n\n\n\n/*\n * Decodes a cookie name, set prior with encodeCookieName to a standard JavaScript string again.\n *\n * @private\n */\nfunction decodeCookieName(name){\n\treturn decodeURIComponent(name);\n}\n\n\n\n/**\n * @typedef CookieOptions\n * @type {Object}\n * @property {?Date|Number} [expires=null] - expiry time of the cookie, either a Date object or time in days\n * @property {?Number} [max-age=null] - max age of the cookie in seconds\n * @property {?String} [path='/'] - the cookie path, setting this to \"auto\" or an empty string defines auto-mode, which targets the current site path, which usually is the default, but we use '/' to set a cookie for while site, this being the common use-case\n * @property {?Boolean} [secure=false] - define if the cookie should only be transmitted via https (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?Boolean} [httponly=false] - define this, if cookie should only be sent to servers and not be accessible to javascript (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?String} [samesite=null] - define if this cookie should be included in cross-site requests, may be either \"strict\" (will only ever transmit same-site), \"lax\" (usual browser default, transmits same-site and top-level GET) or \"none\" (no restrictions, will always be sent)\n */\n\n/*\n * Makes sure, that supplied cookie options are in a usable form for setting a cookie.\n *\n * @private\n */\nfunction normalizeCookieOptions(options){\n\toptions = orDefault(options, {});\n\n\tconst normalizedOptions = {};\n\tfor( let optionsProp in options ){\n\t\tnormalizedOptions[optionsProp.toLowerCase()] = options[optionsProp];\n\t}\n\toptions = normalizedOptions;\n\n\tif( hasValue(options.expires) ){\n\t\tif( !isA(options.expires, 'date') ){\n\t\t\toptions.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000));\n\t\t}\n\t\toptions.expires = options.expires.toUTCString();\n\t} else {\n\t\toptions.expires = null;\n\t}\n\n\toptions['max-age'] = orDefault(options['max-age'], null, 'int');\n\n\toptions.path = orDefault(options.path, '/', 'str');\n\tif( options.path === 'auto' ){\n\t\toptions.path = '';\n\t}\n\n\toptions.domain = orDefault(options.domain, null, 'str');\n\n\toptions.httponly = orDefault(options.httponly, false, 'bool');\n\n\toptions.samesite = orDefault(options.samesite, 'lax', 'str').toLowerCase();\n\tif( !['strict', 'lax', 'none'].includes(options.samesite) ){\n\t\tconsole.warn(`${MODULE_NAME}:setCookie | unknown samesite mode \"${options.samesite}\"`);\n\t}\n\n\toptions.secure = orDefault(options.secure, options.samesite === 'none', 'bool');\n\n\treturn options;\n}\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Cookies:getCookie\n */\n\n/**\n * Retrieves a decoded cookie value by name. Automatically decodes the value (assumes, that, if encoded, url/percent\n * encoding has been used).\n *\n * @param {?String|Array} [name] - the name of the cookie (or several names), if empty, all available cookies are returned\n * @returns {String|Object|null} decoded value of the cookie, null, if no such cookie available or a dictionary of found cookies if all or a list are being returned (if a list is requested and non are found, an empty object is returned)\n *\n * @memberof Cookies:getCookie\n * @alias getCookie\n * @see getCookies\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookie('foobar')\n * => 'value'\n * getCookie(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookie(name){\n\tconst\n\t\tnames = hasValue(name) ? new Set([].concat(name).map(n => n.trim())) : new Set(),\n\t\tfoundNames = new Set()\n\t;\n\n\tlet res = (names.size === 0) ? {} : null;\n\tif( !hasValue(document.cookie) ) return res;\n\n\tconst cookies = document.cookie.split(';');\n\tfor( let i in cookies ){\n\t\ttry {\n\t\t\tconst\n\t\t\t\tcookie = cookies[i].trim(),\n\t\t\t\tcookieParts = cookie.split('='),\n\t\t\t\tcookieName = decodeCookieName(cookieParts[0]).trim(),\n\t\t\t\tcookieValue = decodeCookieValue(cookieParts.slice(1).join('='))\n\t\t\t;\n\n\t\t\tif( (cookieName !== '') && (names.has(cookieName) || (names.size === 0)) ){\n\t\t\t\tif( res === null ){\n\t\t\t\t\tres = {};\n\t\t\t\t}\n\n\t\t\t\tres[cookieName] = cookieValue;\n\t\t\t\tfoundNames.add(cookieName);\n\n\t\t\t\tif( (foundNames.size === names.size) && (names.size !== 0) ){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(ex){\n\t\t\twarn(`${MODULE_NAME}:getCookie | decoding cookie \"${cookies[i]}\" failed with \"${ex}\"`)\n\t\t}\n\t}\n\n\tif( names.size === 1 ){\n\t\treturn res?.[name] ?? null;\n\t} else {\n\t\treturn res;\n\t}\n}\n\n\n\n/**\n * @namespace Cookies:getCookies\n */\n\n/**\n * Retrieve decoded cookie values by name. If no name is provided, all available cookie are being returned.\n * Automatically decodes the values (assumes, that, if encoded, url/percent encoding has been used).\n *\n * You can provide names as an array or as comma-separated parameters.\n *\n * @param {?String|Array} [names] - the names of the cookies, if empty or not set, all available cookies are returned\n * @returns {Object} dictionary of named decoded values of the cookies, will be empty if none of the cookies were available\n *\n * @memberof Cookies:getCookies\n * @alias getCookies\n * @see getCookie\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookies(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookies('foobar', 'boofar')\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookies(names){\n\tnames = [];\n\tArray.from(arguments).forEach(argument => {\n\t\tnames = names.concat(argument);\n\t});\n\n\treturn getCookie(names);\n}\n\n\n\n/**\n * @namespace Cookies:setCookie\n */\n\n/**\n * Set a cookie value (if possible) by name. Value will automatically be encoded.\n *\n * If you set a cookie to a nullish value, the method will try to remove the cookie with the given options.\n *\n * @param {String} name - the name of the cookie to set\n * @param {?String} [value] - the value of the cookie to set\n * @param {?CookieOptions} [options] - the cookie options to apply\n * @returns {String|null} returns the set cookie value if available after setting or null if cookie not available (which would also mean, that setting the cookie did not work, or, in case of removal, that the removal worked)\n *\n * @memberof Cookies:setCookie\n * @alias setCookie\n * @see getCookie\n * @see getCookies\n * @see removeCookie\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie\n * @example\n * setCookie('mykittencookie', 'meow meow', {expires : 7, path : '/kittens', secure : true, samesite : 'strict'});\n */\nexport function setCookie(name, value, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:setCookie | no usable name`);\n\n\tname = `${name}`.trim();\n\tvalue = hasValue(value) ? encodeCookieValue(orDefault(value, '', 'str')) : null;\n\toptions = normalizeCookieOptions(options);\n\n\tlet cookieOptions = '';\n\tfor( let optionsProp in options ){\n\t\tconst option = options[optionsProp];\n\n\t\tif( !hasValue(option) || (option === false) ) continue;\n\n\t\tcookieOptions += `; ${optionsProp}`;\n\n\t\tif( option === true ) continue;\n\n\t\t// if the value itself contains a semicolon, according to RFC 6265 section 5.2,\n\t\t// we use everything that comes before the semicolon as the value and drop the rest\n\t\tcookieOptions += `=${option.split(';')[0]}`;\n\t}\n\n\tif( hasValue(value) ){\n\t\tdocument.cookie = `${encodeCookieName(name)}=${value}${cookieOptions}`;\n\t} else {\n\t\tremoveCookie(name, options);\n\t}\n\n\treturn getCookie(name);\n}\n\n\n\n/**\n * @namespace Cookies:removeCookie\n */\n\n/**\n * Removes a cookie (if possible) by name.\n *\n * @param {String} name - the name of the cookie to remove\n * @param {?CookieOptions} [options] - the cookie options to apply (needed for different paths/domains for example)\n * @returns {Boolean} true if cookie is not available anymore after removal, if this is false, cookie removal failed or another cookie of the same name is still available\n *\n * @memberof Cookies:removeCookie\n * @alias removeCookie\n * @see getCookie\n * @see getCookies\n * @see setCookie\n * @example\n * removeCookie('mykittencookie', {path : '/kittens'});\n */\nexport function removeCookie(name, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:removeCookie | no usable name`);\n\n\toptions = normalizeCookieOptions(options);\n\toptions.expires = -1;\n\n\treturn (setCookie(name, '', options) === null);\n}\n"]} \ No newline at end of file +{"version":3,"file":"cookies.js","names":["MODULE_NAME","assert","isDate","orDefault","hasValue","warn","encodeCookieValue","value","encodeURIComponent","replace","decodeURIComponent","decodeCookieValue","slice","encodeCookieName","name","escape","decodeCookieName","normalizeCookieOptions","options","normalizedOptions","optionsProp","toLowerCase","expires","Date","now","Math","round","parseFloat","toUTCString","path","domain","httponly","samesite","includes","console","secure","getCookie","names","Set","concat","map","n","trim","foundNames","res","size","document","cookie","cookies","split","i","cookieParts","cookieName","cookieValue","join","has","add","ex","getCookies","Array","from","arguments","forEach","argument","setCookie","cookieOptions","option","removeCookie"],"sources":["cookies.js"],"mappings":"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","sourcesContent":["/*!\n * Module Cookies\n */\n\n/**\n * @namespace Cookies\n */\n\nconst MODULE_NAME = 'Cookies';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isDate, orDefault, hasValue} from './basic.js';\nimport {warn} from './logging.js';\n\n\n\n//###[ HELPERS ]########################################################################################################\n\n/*\n * Encodes a string to be stored in a cookie.\n *\n * @private\n */\nfunction encodeCookieValue(value){\n\treturn encodeURIComponent(value).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g, decodeURIComponent);\n}\n\n\n\n/*\n * Decodes a cookie value to be used as a string in JavaScript.\n *\n * @private\n */\nfunction decodeCookieValue(value){\n\tif( value[0] === '\"' ){\n\t\tvalue = value.slice(1, -1);\n\t}\n\treturn value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent);\n}\n\n\n\n/*\n * Makes sure a cookie name conforms to the cookie name rules and translates special chars to % representations.\n *\n * @private\n */\nfunction encodeCookieName(name){\n\treturn encodeURIComponent(`${name}`)\n\t\t.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n\t\t// using escape, because encodeURIComponent, indeed, does _not_ encode brackets\n\t\t.replace(/[()]/g, escape)\n\t;\n}\n\n\n\n/*\n * Decodes a cookie name, set prior with encodeCookieName to a standard JavaScript string again.\n *\n * @private\n */\nfunction decodeCookieName(name){\n\treturn decodeURIComponent(name);\n}\n\n\n\n/**\n * @typedef CookieOptions\n * @type {Object}\n * @property {?Date|Number} [expires=null] - expiry time of the cookie, either a Date object or time in days\n * @property {?Number} [max-age=null] - max age of the cookie in seconds\n * @property {?String} [path='/'] - the cookie path, setting this to \"auto\" or an empty string defines auto-mode, which targets the current site path, which usually is the default, but we use '/' to set a cookie for while site, this being the common use-case\n * @property {?Boolean} [secure=false] - define if the cookie should only be transmitted via https (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?Boolean} [httponly=false] - define this, if cookie should only be sent to servers and not be accessible to javascript (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)\n * @property {?String} [samesite=null] - define if this cookie should be included in cross-site requests, may be either \"strict\" (will only ever transmit same-site), \"lax\" (usual browser default, transmits same-site and top-level GET) or \"none\" (no restrictions, will always be sent)\n */\n\n/*\n * Makes sure, that supplied cookie options are in a usable form for setting a cookie.\n *\n * @private\n */\nfunction normalizeCookieOptions(options){\n\toptions = orDefault(options, {});\n\n\tconst normalizedOptions = {};\n\tfor( let optionsProp in options ){\n\t\tnormalizedOptions[optionsProp.toLowerCase()] = options[optionsProp];\n\t}\n\toptions = normalizedOptions;\n\n\tif( hasValue(options.expires) ){\n\t\tif( !isDate(options.expires) ){\n\t\t\toptions.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000));\n\t\t}\n\t\toptions.expires = options.expires.toUTCString();\n\t} else {\n\t\toptions.expires = null;\n\t}\n\n\toptions['max-age'] = orDefault(options['max-age'], null, 'int');\n\n\toptions.path = orDefault(options.path, '/', 'str');\n\tif( options.path === 'auto' ){\n\t\toptions.path = '';\n\t}\n\n\toptions.domain = orDefault(options.domain, null, 'str');\n\n\toptions.httponly = orDefault(options.httponly, false, 'bool');\n\n\toptions.samesite = orDefault(options.samesite, 'lax', 'str').toLowerCase();\n\tif( !['strict', 'lax', 'none'].includes(options.samesite) ){\n\t\tconsole.warn(`${MODULE_NAME}:setCookie | unknown samesite mode \"${options.samesite}\"`);\n\t}\n\n\toptions.secure = orDefault(options.secure, options.samesite === 'none', 'bool');\n\n\treturn options;\n}\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Cookies:getCookie\n */\n\n/**\n * Retrieves a decoded cookie value by name. Automatically decodes the value (assumes, that, if encoded, url/percent\n * encoding has been used).\n *\n * @param {?String|Array} [name] - the name of the cookie (or several names), if empty, all available cookies are returned\n * @returns {String|Object|null} decoded value of the cookie, null, if no such cookie available or a dictionary of found cookies if all or a list are being returned (if a list is requested and non are found, an empty object is returned)\n *\n * @memberof Cookies:getCookie\n * @alias getCookie\n * @see getCookies\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookie('foobar')\n * => 'value'\n * getCookie(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookie(name){\n\tconst\n\t\tnames = hasValue(name) ? new Set([].concat(name).map(n => n.trim())) : new Set(),\n\t\tfoundNames = new Set()\n\t;\n\n\tlet res = (names.size === 0) ? {} : null;\n\tif( !hasValue(document.cookie) ) return res;\n\n\tconst cookies = document.cookie.split(';');\n\tfor( let i in cookies ){\n\t\ttry {\n\t\t\tconst\n\t\t\t\tcookie = cookies[i].trim(),\n\t\t\t\tcookieParts = cookie.split('='),\n\t\t\t\tcookieName = decodeCookieName(cookieParts[0]).trim(),\n\t\t\t\tcookieValue = decodeCookieValue(cookieParts.slice(1).join('='))\n\t\t\t;\n\n\t\t\tif( (cookieName !== '') && (names.has(cookieName) || (names.size === 0)) ){\n\t\t\t\tif( res === null ){\n\t\t\t\t\tres = {};\n\t\t\t\t}\n\n\t\t\t\tres[cookieName] = cookieValue;\n\t\t\t\tfoundNames.add(cookieName);\n\n\t\t\t\tif( (foundNames.size === names.size) && (names.size !== 0) ){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(ex){\n\t\t\twarn(`${MODULE_NAME}:getCookie | decoding cookie \"${cookies[i]}\" failed with \"${ex}\"`)\n\t\t}\n\t}\n\n\tif( names.size === 1 ){\n\t\treturn res?.[name] ?? null;\n\t} else {\n\t\treturn res;\n\t}\n}\n\n\n\n/**\n * @namespace Cookies:getCookies\n */\n\n/**\n * Retrieve decoded cookie values by name. If no name is provided, all available cookie are being returned.\n * Automatically decodes the values (assumes, that, if encoded, url/percent encoding has been used).\n *\n * You can provide names as an array or as comma-separated parameters.\n *\n * @param {?String|Array} [names] - the names of the cookies, if empty or not set, all available cookies are returned\n * @returns {Object} dictionary of named decoded values of the cookies, will be empty if none of the cookies were available\n *\n * @memberof Cookies:getCookies\n * @alias getCookies\n * @see getCookie\n * @see setCookie\n * @see removeCookie\n * @example\n * getCookies(['foobar', 'boofar'])\n * => {foobar : 'value', boofar : 'value'}\n * getCookies('foobar', 'boofar')\n * => {foobar : 'value', boofar : 'value'}\n * getCookie()\n * => all available cookies\n */\nexport function getCookies(names){\n\tnames = [];\n\tArray.from(arguments).forEach(argument => {\n\t\tnames = names.concat(argument);\n\t});\n\n\treturn getCookie(names);\n}\n\n\n\n/**\n * @namespace Cookies:setCookie\n */\n\n/**\n * Set a cookie value (if possible) by name. Value will automatically be encoded.\n *\n * If you set a cookie to a nullish value, the method will try to remove the cookie with the given options.\n *\n * @param {String} name - the name of the cookie to set\n * @param {?String} [value] - the value of the cookie to set\n * @param {?CookieOptions} [options] - the cookie options to apply\n * @returns {String|null} returns the set cookie value if available after setting or null if cookie not available (which would also mean, that setting the cookie did not work, or, in case of removal, that the removal worked)\n *\n * @memberof Cookies:setCookie\n * @alias setCookie\n * @see getCookie\n * @see getCookies\n * @see removeCookie\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie\n * @example\n * setCookie('mykittencookie', 'meow meow', {expires : 7, path : '/kittens', secure : true, samesite : 'strict'});\n */\nexport function setCookie(name, value, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:setCookie | no usable name`);\n\n\tname = `${name}`.trim();\n\tvalue = hasValue(value) ? encodeCookieValue(orDefault(value, '', 'str')) : null;\n\toptions = normalizeCookieOptions(options);\n\n\tlet cookieOptions = '';\n\tfor( let optionsProp in options ){\n\t\tconst option = options[optionsProp];\n\n\t\tif( !hasValue(option) || (option === false) ) continue;\n\n\t\tcookieOptions += `; ${optionsProp}`;\n\n\t\tif( option === true ) continue;\n\n\t\t// if the value itself contains a semicolon, according to RFC 6265 section 5.2,\n\t\t// we use everything that comes before the semicolon as the value and drop the rest\n\t\tcookieOptions += `=${option.split(';')[0]}`;\n\t}\n\n\tif( hasValue(value) ){\n\t\tdocument.cookie = `${encodeCookieName(name)}=${value}${cookieOptions}`;\n\t} else {\n\t\tremoveCookie(name, options);\n\t}\n\n\treturn getCookie(name);\n}\n\n\n\n/**\n * @namespace Cookies:removeCookie\n */\n\n/**\n * Removes a cookie (if possible) by name.\n *\n * @param {String} name - the name of the cookie to remove\n * @param {?CookieOptions} [options] - the cookie options to apply (needed for different paths/domains for example)\n * @returns {Boolean} true if cookie is not available anymore after removal, if this is false, cookie removal failed or another cookie of the same name is still available\n *\n * @memberof Cookies:removeCookie\n * @alias removeCookie\n * @see getCookie\n * @see getCookies\n * @see setCookie\n * @example\n * removeCookie('mykittencookie', {path : '/kittens'});\n */\nexport function removeCookie(name, options){\n\tassert(hasValue(name) && (name !== ''), `${MODULE_NAME}:removeCookie | no usable name`);\n\n\toptions = normalizeCookieOptions(options);\n\toptions.expires = -1;\n\n\treturn (setCookie(name, '', options) === null);\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/css.js b/docs/examples/lib/annex/dist/css.js index fb757f48..7adf56db 100644 --- a/docs/examples/lib/annex/dist/css.js +++ b/docs/examples/lib/annex/dist/css.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module CSS */ -const MODULE_NAME="CSS";import{assert,isA,orDefault,isPlainObject,isElement,hasValue,isNaN}from"./basic.js";import{maskForRegEx}from"./strings.js";export function applyStyles(e,t,r=!1,s=!1){const l="applyStyles";r=orDefault(r,!1,"bool"),s=orDefault(s,!1,"bool"),assert(isElement(e),`CSS:${l} | element is not an html element`),assert(isPlainObject(t),`CSS:${l} | styles must be a plain object`);const o=["-webkit-","-moz-","-ms-","-o-","-khtml-"];return r&&Object.entries({...t}).forEach((([e,r])=>{o.forEach((s=>{t[s+e]="transition"===e?r.replace("transform",`${s}transform`):r}))})),Object.entries({...t}).forEach((([r,s])=>{isA(s,"number")&&0!==s?(t[r]=`${s}px`,e.style.setProperty(r,t[r])):hasValue(s)?(t[r]=`${s}`,e.style.setProperty(r,t[r])):(o.forEach((s=>{delete t[s+r],e.style.removeProperty(s+r)})),delete t[r],e.style.removeProperty(r))})),s?e.style:t}export function cssValueToNumber(e){return parseFloat(orDefault(e,"","str"))}export function cssUrlValueToUrl(e,t=null,r=null){e=orDefault(e,"","str"),t=orDefault(t,null,"str"),r=orDefault(r,null,"str");const s=new RegExp("(?:^|\\s|,)url\\((?:'|\")?([^'\"\\n\\r\\t]+)(?:'|\")?\\)","gmi"),l=[];let o;for(;null!==(o=s.exec(e));)o=o[1],hasValue(t,r)&&(o=o.replace(new RegExp(`^${maskForRegEx(t)}`),r)),l.push(o);return 1===l.length?l[0]:l.length>1?l:null}export function remByPx(e,t="html"){if(e=cssValueToNumber(e),t=orDefault(t,"html"),isElement(t))t=cssValueToNumber(t.style.getPropertyValue("font-size"));else{const e=cssValueToNumber(t);if(isNaN(e)){const e=document.querySelector(t);assert(hasValue(e),"CSS:remByPx | selector does not return element"),t=cssValueToNumber(e.style.getPropertyValue("font-size"))}else t=e}const r=e/t;return 0===t||isNaN(r)?null:`${r}rem`} +const MODULE_NAME="CSS";import{assert,isNumber,orDefault,isPlainObject,isElement,hasValue,isNaN}from"./basic.js";import{maskForRegEx}from"./strings.js";export function applyStyles(e,t,r=!1,s=!1){const l="applyStyles";r=orDefault(r,!1,"bool"),s=orDefault(s,!1,"bool"),assert(isElement(e),`CSS:${l} | element is not an html element`),assert(isPlainObject(t),`CSS:${l} | styles must be a plain object`);const o=["-webkit-","-moz-","-ms-","-o-","-khtml-"];return r&&Object.entries({...t}).forEach((([e,r])=>{o.forEach((s=>{t[s+e]="transition"===e?r.replace("transform",`${s}transform`):r}))})),Object.entries({...t}).forEach((([r,s])=>{isNumber(s)&&0!==s?(t[r]=`${s}px`,e.style.setProperty(r,t[r])):hasValue(s)?(t[r]=`${s}`,e.style.setProperty(r,t[r])):(o.forEach((s=>{delete t[s+r],e.style.removeProperty(s+r)})),delete t[r],e.style.removeProperty(r))})),s?e.style:t}export function cssValueToNumber(e){return parseFloat(orDefault(e,"","str"))}export function cssUrlValueToUrl(e,t=null,r=null){e=orDefault(e,"","str"),t=orDefault(t,null,"str"),r=orDefault(r,null,"str");const s=new RegExp("(?:^|\\s|,)url\\((?:'|\")?([^'\"\\n\\r\\t]+)(?:'|\")?\\)","gmi"),l=[];let o;for(;null!==(o=s.exec(e));)o=o[1],hasValue(t,r)&&(o=o.replace(new RegExp(`^${maskForRegEx(t)}`),r)),l.push(o);return 1===l.length?l[0]:l.length>1?l:null}export function remByPx(e,t="html"){if(e=cssValueToNumber(e),t=orDefault(t,"html"),isElement(t))t=cssValueToNumber(t.style.getPropertyValue("font-size"));else{const e=cssValueToNumber(t);if(isNaN(e)){const e=document.querySelector(t);assert(hasValue(e),"CSS:remByPx | selector does not return element"),t=cssValueToNumber(e.style.getPropertyValue("font-size"))}else t=e}const r=e/t;return 0===t||isNaN(r)?null:`${r}rem`} //# sourceMappingURL=css.js.map diff --git a/docs/examples/lib/annex/dist/css.js.map b/docs/examples/lib/annex/dist/css.js.map index 3e835c9a..d30e1dcc 100644 --- a/docs/examples/lib/annex/dist/css.js.map +++ b/docs/examples/lib/annex/dist/css.js.map @@ -1 +1 @@ -{"version":3,"file":"css.js","names":["MODULE_NAME","assert","isA","orDefault","isPlainObject","isElement","hasValue","isNaN","maskForRegEx","applyStyles","element","styles","crossBrowser","returnCssStyleDeclaration","__methodName__","vendorPrefixes","Object","entries","forEach","cssKey","cssValue","vendorPrefix","replace","style","setProperty","removeProperty","cssValueToNumber","value","parseFloat","cssUrlValueToUrl","urlValue","baseUrl","baseUrlSubstitution","urlValueRex","RegExp","matches","match","exec","push","length","remByPx","px","initial","getPropertyValue","document","querySelector","remVal"],"sources":["css.js"],"mappings":";;;AAQA,MAAMA,YAAc,aAMZC,OAAQC,IAAKC,UAAWC,cAAeC,UAAWC,SAAUC,UAAY,oBACxEC,iBAAmB,sBA6CpB,SAASC,YAAYC,EAASC,EAAQC,GAAa,EAAOC,GAA0B,GAC1F,MAAMC,EAAiB,cAEvBF,EAAeT,UAAUS,GAAc,EAAO,QAC9CC,EAA4BV,UAAUU,GAA2B,EAAO,QAExEZ,OAAOI,UAAUK,GAAU,OAAkBI,sCAC7Cb,OAAOG,cAAcO,GAAS,OAAkBG,qCAEhD,MAAMC,EAAiB,CAAC,WAAY,QAAS,OAAQ,MAAO,WA+B5D,OA7BIH,GACHI,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MAC7CL,EAAeG,SAAQG,IAErBV,EAAOU,EAAaF,GADP,eAAXA,EAC4BC,EAASE,QAAQ,YAAa,GAAGD,cAEjCD,CAC/B,GACC,IAIJJ,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MACzClB,IAAIkB,EAAU,WAA2B,IAAbA,GAC/BT,EAAOQ,GAAU,GAAGC,MACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,KAC9Bb,SAASc,IAQpBT,EAAOQ,GAAU,GAAGC,IACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,MARzCJ,EAAeG,SAAQG,WACfV,EAAOU,EAAaF,GAC3BT,EAAQa,MAAME,eAAeJ,EAAaF,EAAO,WAE3CR,EAAOQ,GACdT,EAAQa,MAAME,eAAeN,GAI9B,IAGMN,EAA4BH,EAAQa,MAAQZ,CACpD,QAsBO,SAASe,iBAAiBC,GAChC,OAAOC,WAAWzB,UAAUwB,EAAO,GAAI,OACxC,QA0BO,SAASE,iBAAiBC,EAAUC,EAAQ,KAAMC,EAAoB,MAC5EF,EAAW3B,UAAU2B,EAAU,GAAI,OACnCC,EAAU5B,UAAU4B,EAAS,KAAM,OACnCC,EAAsB7B,UAAU6B,EAAqB,KAAM,OAE3D,MACCC,EAAc,IAAIC,OAAO,2DAA4D,OACrFC,EAAU,GAGX,IAAIC,EACJ,KAAgD,QAAxCA,EAAQH,EAAYI,KAAKP,KAChCM,EAAQA,EAAM,GACV9B,SAASyB,EAASC,KACrBI,EAAQA,EAAMd,QAAQ,IAAIY,OAAO,IAAI1B,aAAauB,MAAaC,IAEhEG,EAAQG,KAAKF,GAGd,OAAuB,IAAnBD,EAAQI,OACJJ,EAAQ,GACLA,EAAQI,OAAS,EACpBJ,EAEA,IAET,QAiCO,SAASK,QAAQC,EAAIC,EAAQ,QAInC,GAHAD,EAAKf,iBAAiBe,GACtBC,EAAUvC,UAAUuC,EAAS,QAEzBrC,UAAUqC,GACbA,EAAUhB,iBAAiBgB,EAAQnB,MAAMoB,iBAAiB,kBACpD,CACN,MAAMhB,EAAQD,iBAAiBgB,GAC/B,GAAInC,MAAMoB,GAAQ,CACjB,MAAMjB,EAAUkC,SAASC,cAAcH,GACvCzC,OAAOK,SAASI,GAAU,kDAC1BgC,EAAUhB,iBAAiBhB,EAAQa,MAAMoB,iBAAiB,aAC3D,MACCD,EAAUf,CAEZ,CAEA,MAAMmB,EAASL,EAAKC,EAEpB,OAAiB,IAAZA,GAAmBnC,MAAMuC,GAGtB,KAFA,GAAGA,MAIZ","sourcesContent":["/*!\n * Module CSS\n */\n\n/**\n * @namespace CSS\n */\n\nconst MODULE_NAME = 'CSS';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isA, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js';\nimport {maskForRegEx} from './strings.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace CSS:applyStyles\n */\n\n/**\n * Applies CSS definitions to an HTMLElement, by providing a plain object of property-value-pairs.\n * Properties may be written as default CSS kebab-case properties such as \"margin-left\" or as JS\n * camel-cased versions such as \"marginLeft\".\n *\n * Providing a real JS number without a unit will be treated as a pixel value, so defining \"'line-height' : 0\" will\n * actually result in a 1px line-height. To actually set a unit-less value, just set the value as a string:\n * \"'line-height' : '0'\".\n *\n * Generally all CSS values are usually strings (this is also the way JS handles this),\n * treating plain numbers as pixels is just a convenience feature, since pixels are most likely to be\n * calculated values, where it is bothersome and error-prone to add the \"px\" all the time.\n *\n * To remove a property, just set the value to a nullish value. Deleting a property also tries to remove all\n * vendor prefixed variants.\n *\n * This function uses CSSStyleDeclaration.setProperty instead of direct style assignments. This means, that the\n * browser itself decides which value to apply, based on the support of the property. This means, the style object\n * will not be polluted with vendor stuff the browser does not support, but this also means, that all non-standard\n * properties might be refused. If you really need to set something out of spec, use direct style assignment instead.\n *\n * @param {HTMLElement} element - the element to apply the styles to, use null or undefined as value to remove a prop\n * @param {Object} styles - the styles to apply, provided as a plain object, defining property-value-pairs\n * @param {?Boolean} [crossBrowser=false] - set this to true, to automatically generate vendor-prefixed versions of all provided properties\n * @param {?Boolean} [returnCssStyleDeclaration=false] - set this to true, return the CSSStyleDeclaration of the element after the style application, rather than the plain object\n * @throws error if element is not an HTMLElement\n * @throws error if styles is not a plain object\n * @returns {Object|CSSStyleDeclaration} the applied/active styles\n *\n * @memberof CSS:applyStyles\n * @alias applyStyles\n * @example\n * applyStyles(document.body, {backgroundColor : red, transition : 'all 200ms'}, true);\n * applyStyles(document.querySelector('main'), {'font-family' : 'serif'}, false, true);\n */\nexport function applyStyles(element, styles, crossBrowser=false, returnCssStyleDeclaration=false){\n\tconst __methodName__ = 'applyStyles';\n\n\tcrossBrowser = orDefault(crossBrowser, false, 'bool');\n\treturnCssStyleDeclaration = orDefault(returnCssStyleDeclaration, false, 'bool');\n\n\tassert(isElement(element), `${MODULE_NAME}:${__methodName__} | element is not an html element`);\n\tassert(isPlainObject(styles), `${MODULE_NAME}:${__methodName__} | styles must be a plain object`);\n\n\tconst vendorPrefixes = ['-webkit-', '-moz-', '-ms-', '-o-', '-khtml-'];\n\n\tif( crossBrowser ){\n\t\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tif(cssKey === 'transition'){\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue.replace('transform', `${vendorPrefix}transform`);\n\t\t\t\t} else {\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\tif( isA(cssValue, 'number') && (cssValue !== 0) ){\n\t\t\tstyles[cssKey] = `${cssValue}px`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t} else if( !hasValue(cssValue) ){\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tdelete styles[vendorPrefix+cssKey];\n\t\t\t\telement.style.removeProperty(vendorPrefix+cssKey);\n\t\t\t});\n\t\t\tdelete styles[cssKey];\n\t\t\telement.style.removeProperty(cssKey);\n\t\t} else {\n\t\t\tstyles[cssKey] = `${cssValue}`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t}\n\t});\n\n\treturn returnCssStyleDeclaration ? element.style : styles;\n}\n\n\n\n/**\n * @namespace CSS:cssValueToNumber\n */\n\n/**\n * Converts a CSS-value to a number without unit. If the base number is an integer the result will also\n * be an integer, float values will also be converted correctly.\n *\n * @param {String} value - the css-value to convert\n * @returns {Number|NaN} true number representation of the given value or NaN if the value is not parsable\n *\n * @memberof CSS:cssValueToNumber\n * @alias cssValueToNumber\n * @example\n * document.querySelector('main').style.setProperty('width', '99vh');\n * cssValueToNumber(document.querySelector('main').style.getPropertyValue('width'));\n * => 99\n */\nexport function cssValueToNumber(value){\n\treturn parseFloat(orDefault(value, '', 'str'));\n}\n\n\n\n/**\n * @namespace CSS:cssUrlValueToUrl\n */\n\n/**\n * Converts a CSS-URL-value (\"url('/foo/bar/baz.jpg')\") to a plain URL usable in requests or src-attributes.\n *\n * @param {String} urlValue - the URL-value from CSS\n * @param {?String} [baseUrl=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace here\n * @param {?String} [baseUrlSubstitution=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace the baseUrl with here\n * @returns {String|Array|null} the extracted URL (or list of URLs if value contained several) with substitutions (if defined) or null if no URL-values were found\n *\n * @memberof CSS:cssUrlValueToUrl\n * @alias cssUrlValueToUrl\n * @example\n * cssUrlValueToUrl('url(\"https://foobar.com/test.jpg\")', 'https://foobar.com', '..');\n * => '../test.jpg'\n * cssUrlValueToUrl(`url(/foo/bar),\n * url('https://google.de') url(\"test.jpg\"),url(omg.svg)\n * url(http://lol.com)`)\n * => ['/foo/bar', 'https://google.com', 'test.jpg', 'omg.svg', 'http://lol.com']\n */\nexport function cssUrlValueToUrl(urlValue, baseUrl=null, baseUrlSubstitution=null){\n\turlValue = orDefault(urlValue, '', 'str');\n\tbaseUrl = orDefault(baseUrl, null, 'str');\n\tbaseUrlSubstitution = orDefault(baseUrlSubstitution, null, 'str');\n\n\tconst\n\t\turlValueRex = new RegExp('(?:^|\\\\s|,)url\\\\((?:\\'|\")?([^\\'\"\\\\n\\\\r\\\\t]+)(?:\\'|\")?\\\\)', 'gmi'),\n\t\tmatches = []\n\t;\n\n\tlet match;\n\twhile( (match = urlValueRex.exec(urlValue)) !== null ){\n\t\tmatch = match[1];\n\t\tif( hasValue(baseUrl, baseUrlSubstitution) ){\n\t\t\tmatch = match.replace(new RegExp(`^${maskForRegEx(baseUrl)}`), baseUrlSubstitution);\n\t\t}\n\t\tmatches.push(match);\n\t}\n\n\tif( matches.length === 1 ){\n\t\treturn matches[0];\n\t} else if( matches.length > 1 ){\n\t\treturn matches;\n\t} else {\n\t\treturn null;\n\t}\n}\n\n\n\n/**\n * @namespace CSS:remByPx\n */\n\n/**\n * Calculates a rem value based on a given px value.\n * As a default this method takes the font-size (supposedly being in px) of the html-container.\n * You can overwrite this behaviour by setting initial to a number to use as a base px value or\n * to a string, which then defines a new selector for an element to get the initial font-size from.\n * You can also provide an HTMLElement directly, but keep in mind that the element's font size definition\n * has to be in pixels, to make this work.\n *\n * In most cases you will have to define the initial value via a constant or a selector to a container\n * with non-changing font-size, since you can never be sure which relative font-size applies atm, even on first\n * call, after dom ready, since responsive definitions might already be active, returning a viewport-specific\n * size.\n *\n * @param {Number} px - the pixel value to convert to rem\n * @param {?(Number|String|HTMLElement)} [initial='html'] - either a pixel value to use as a conversion base, a selector for an element to get the initial font-size from or the element itself; keep in mind, that the element's font-size definition has to be in px\n * @throws error if given selector in initial does not return an element\n * @returns {String|null} the rem value string to use in a css definition or null if the value could not be calculated\n *\n * @memberof CSS:remByPx\n * @alias remByPx\n * @example\n * remByPx(20, 16);\n * => '1.25rem'\n * remByPx('100px', 'p.has-base-fontsize');\n */\nexport function remByPx(px, initial='html'){\n\tpx = cssValueToNumber(px);\n\tinitial = orDefault(initial, 'html');\n\n\tif( isElement(initial) ){\n\t\tinitial = cssValueToNumber(initial.style.getPropertyValue('font-size'));\n\t} else {\n\t\tconst value = cssValueToNumber(initial);\n\t\tif( isNaN(value) ){\n\t\t\tconst element = document.querySelector(initial);\n\t\t\tassert(hasValue(element), `${MODULE_NAME}:remByPx | selector does not return element`);\n\t\t\tinitial = cssValueToNumber(element.style.getPropertyValue('font-size'));\n\t\t} else {\n\t\t\tinitial = value;\n\t\t}\n\t}\n\n\tconst remVal = px / initial;\n\n\tif( (initial !== 0) && !isNaN(remVal) ){\n\t\treturn `${remVal}rem`;\n\t} else {\n\t\treturn null;\n\t}\n}\n"]} \ No newline at end of file +{"version":3,"file":"css.js","names":["MODULE_NAME","assert","isNumber","orDefault","isPlainObject","isElement","hasValue","isNaN","maskForRegEx","applyStyles","element","styles","crossBrowser","returnCssStyleDeclaration","__methodName__","vendorPrefixes","Object","entries","forEach","cssKey","cssValue","vendorPrefix","replace","style","setProperty","removeProperty","cssValueToNumber","value","parseFloat","cssUrlValueToUrl","urlValue","baseUrl","baseUrlSubstitution","urlValueRex","RegExp","matches","match","exec","push","length","remByPx","px","initial","getPropertyValue","document","querySelector","remVal"],"sources":["css.js"],"mappings":";;;AAQA,MAAMA,YAAc,aAMZC,OAAQC,SAAUC,UAAWC,cAAeC,UAAWC,SAAUC,UAAY,oBAC7EC,iBAAmB,sBA6CpB,SAASC,YAAYC,EAASC,EAAQC,GAAa,EAAOC,GAA0B,GAC1F,MAAMC,EAAiB,cAEvBF,EAAeT,UAAUS,GAAc,EAAO,QAC9CC,EAA4BV,UAAUU,GAA2B,EAAO,QAExEZ,OAAOI,UAAUK,GAAU,OAAkBI,sCAC7Cb,OAAOG,cAAcO,GAAS,OAAkBG,qCAEhD,MAAMC,EAAiB,CAAC,WAAY,QAAS,OAAQ,MAAO,WA+B5D,OA7BIH,GACHI,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MAC7CL,EAAeG,SAAQG,IAErBV,EAAOU,EAAaF,GADP,eAAXA,EAC4BC,EAASE,QAAQ,YAAa,GAAGD,cAEjCD,CAC/B,GACC,IAIJJ,OAAOC,QAAQ,IAAIN,IAASO,SAAQ,EAAEC,EAAQC,MACzClB,SAASkB,IAA2B,IAAbA,GAC1BT,EAAOQ,GAAU,GAAGC,MACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,KAC9Bb,SAASc,IAQpBT,EAAOQ,GAAU,GAAGC,IACpBV,EAAQa,MAAMC,YAAYL,EAAQR,EAAOQ,MARzCJ,EAAeG,SAAQG,WACfV,EAAOU,EAAaF,GAC3BT,EAAQa,MAAME,eAAeJ,EAAaF,EAAO,WAE3CR,EAAOQ,GACdT,EAAQa,MAAME,eAAeN,GAI9B,IAGMN,EAA4BH,EAAQa,MAAQZ,CACpD,QAsBO,SAASe,iBAAiBC,GAChC,OAAOC,WAAWzB,UAAUwB,EAAO,GAAI,OACxC,QA0BO,SAASE,iBAAiBC,EAAUC,EAAQ,KAAMC,EAAoB,MAC5EF,EAAW3B,UAAU2B,EAAU,GAAI,OACnCC,EAAU5B,UAAU4B,EAAS,KAAM,OACnCC,EAAsB7B,UAAU6B,EAAqB,KAAM,OAE3D,MACCC,EAAc,IAAIC,OAAO,2DAA4D,OACrFC,EAAU,GAGX,IAAIC,EACJ,KAAgD,QAAxCA,EAAQH,EAAYI,KAAKP,KAChCM,EAAQA,EAAM,GACV9B,SAASyB,EAASC,KACrBI,EAAQA,EAAMd,QAAQ,IAAIY,OAAO,IAAI1B,aAAauB,MAAaC,IAEhEG,EAAQG,KAAKF,GAGd,OAAuB,IAAnBD,EAAQI,OACJJ,EAAQ,GACLA,EAAQI,OAAS,EACpBJ,EAEA,IAET,QAiCO,SAASK,QAAQC,EAAIC,EAAQ,QAInC,GAHAD,EAAKf,iBAAiBe,GACtBC,EAAUvC,UAAUuC,EAAS,QAEzBrC,UAAUqC,GACbA,EAAUhB,iBAAiBgB,EAAQnB,MAAMoB,iBAAiB,kBACpD,CACN,MAAMhB,EAAQD,iBAAiBgB,GAC/B,GAAInC,MAAMoB,GAAQ,CACjB,MAAMjB,EAAUkC,SAASC,cAAcH,GACvCzC,OAAOK,SAASI,GAAU,kDAC1BgC,EAAUhB,iBAAiBhB,EAAQa,MAAMoB,iBAAiB,aAC3D,MACCD,EAAUf,CAEZ,CAEA,MAAMmB,EAASL,EAAKC,EAEpB,OAAiB,IAAZA,GAAmBnC,MAAMuC,GAGtB,KAFA,GAAGA,MAIZ","sourcesContent":["/*!\n * Module CSS\n */\n\n/**\n * @namespace CSS\n */\n\nconst MODULE_NAME = 'CSS';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {assert, isNumber, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js';\nimport {maskForRegEx} from './strings.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace CSS:applyStyles\n */\n\n/**\n * Applies CSS definitions to an HTMLElement, by providing a plain object of property-value-pairs.\n * Properties may be written as default CSS kebab-case properties such as \"margin-left\" or as JS\n * camel-cased versions such as \"marginLeft\".\n *\n * Providing a real JS number without a unit will be treated as a pixel value, so defining \"'line-height' : 0\" will\n * actually result in a 1px line-height. To actually set a unit-less value, just set the value as a string:\n * \"'line-height' : '0'\".\n *\n * Generally all CSS values are usually strings (this is also the way JS handles this),\n * treating plain numbers as pixels is just a convenience feature, since pixels are most likely to be\n * calculated values, where it is bothersome and error-prone to add the \"px\" all the time.\n *\n * To remove a property, just set the value to a nullish value. Deleting a property also tries to remove all\n * vendor prefixed variants.\n *\n * This function uses CSSStyleDeclaration.setProperty instead of direct style assignments. This means, that the\n * browser itself decides which value to apply, based on the support of the property. This means, the style object\n * will not be polluted with vendor stuff the browser does not support, but this also means, that all non-standard\n * properties might be refused. If you really need to set something out of spec, use direct style assignment instead.\n *\n * @param {HTMLElement} element - the element to apply the styles to, use null or undefined as value to remove a prop\n * @param {Object} styles - the styles to apply, provided as a plain object, defining property-value-pairs\n * @param {?Boolean} [crossBrowser=false] - set this to true, to automatically generate vendor-prefixed versions of all provided properties\n * @param {?Boolean} [returnCssStyleDeclaration=false] - set this to true, return the CSSStyleDeclaration of the element after the style application, rather than the plain object\n * @throws error if element is not an HTMLElement\n * @throws error if styles is not a plain object\n * @returns {Object|CSSStyleDeclaration} the applied/active styles\n *\n * @memberof CSS:applyStyles\n * @alias applyStyles\n * @example\n * applyStyles(document.body, {backgroundColor : red, transition : 'all 200ms'}, true);\n * applyStyles(document.querySelector('main'), {'font-family' : 'serif'}, false, true);\n */\nexport function applyStyles(element, styles, crossBrowser=false, returnCssStyleDeclaration=false){\n\tconst __methodName__ = 'applyStyles';\n\n\tcrossBrowser = orDefault(crossBrowser, false, 'bool');\n\treturnCssStyleDeclaration = orDefault(returnCssStyleDeclaration, false, 'bool');\n\n\tassert(isElement(element), `${MODULE_NAME}:${__methodName__} | element is not an html element`);\n\tassert(isPlainObject(styles), `${MODULE_NAME}:${__methodName__} | styles must be a plain object`);\n\n\tconst vendorPrefixes = ['-webkit-', '-moz-', '-ms-', '-o-', '-khtml-'];\n\n\tif( crossBrowser ){\n\t\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tif(cssKey === 'transition'){\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue.replace('transform', `${vendorPrefix}transform`);\n\t\t\t\t} else {\n\t\t\t\t\tstyles[vendorPrefix+cssKey] = cssValue;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tObject.entries({...styles}).forEach(([cssKey, cssValue]) => {\n\t\tif( isNumber(cssValue) && (cssValue !== 0) ){\n\t\t\tstyles[cssKey] = `${cssValue}px`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t} else if( !hasValue(cssValue) ){\n\t\t\tvendorPrefixes.forEach(vendorPrefix => {\n\t\t\t\tdelete styles[vendorPrefix+cssKey];\n\t\t\t\telement.style.removeProperty(vendorPrefix+cssKey);\n\t\t\t});\n\t\t\tdelete styles[cssKey];\n\t\t\telement.style.removeProperty(cssKey);\n\t\t} else {\n\t\t\tstyles[cssKey] = `${cssValue}`;\n\t\t\telement.style.setProperty(cssKey, styles[cssKey]);\n\t\t}\n\t});\n\n\treturn returnCssStyleDeclaration ? element.style : styles;\n}\n\n\n\n/**\n * @namespace CSS:cssValueToNumber\n */\n\n/**\n * Converts a CSS-value to a number without unit. If the base number is an integer the result will also\n * be an integer, float values will also be converted correctly.\n *\n * @param {String} value - the css-value to convert\n * @returns {Number|NaN} true number representation of the given value or NaN if the value is not parsable\n *\n * @memberof CSS:cssValueToNumber\n * @alias cssValueToNumber\n * @example\n * document.querySelector('main').style.setProperty('width', '99vh');\n * cssValueToNumber(document.querySelector('main').style.getPropertyValue('width'));\n * => 99\n */\nexport function cssValueToNumber(value){\n\treturn parseFloat(orDefault(value, '', 'str'));\n}\n\n\n\n/**\n * @namespace CSS:cssUrlValueToUrl\n */\n\n/**\n * Converts a CSS-URL-value (\"url('/foo/bar/baz.jpg')\") to a plain URL usable in requests or src-attributes.\n *\n * @param {String} urlValue - the URL-value from CSS\n * @param {?String} [baseUrl=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace here\n * @param {?String} [baseUrlSubstitution=null] - if you want to transform the URL by substituting the start of the path or URL with something fitting for your context, define what to replace the baseUrl with here\n * @returns {String|Array|null} the extracted URL (or list of URLs if value contained several) with substitutions (if defined) or null if no URL-values were found\n *\n * @memberof CSS:cssUrlValueToUrl\n * @alias cssUrlValueToUrl\n * @example\n * cssUrlValueToUrl('url(\"https://foobar.com/test.jpg\")', 'https://foobar.com', '..');\n * => '../test.jpg'\n * cssUrlValueToUrl(`url(/foo/bar),\n * url('https://google.de') url(\"test.jpg\"),url(omg.svg)\n * url(http://lol.com)`)\n * => ['/foo/bar', 'https://google.com', 'test.jpg', 'omg.svg', 'http://lol.com']\n */\nexport function cssUrlValueToUrl(urlValue, baseUrl=null, baseUrlSubstitution=null){\n\turlValue = orDefault(urlValue, '', 'str');\n\tbaseUrl = orDefault(baseUrl, null, 'str');\n\tbaseUrlSubstitution = orDefault(baseUrlSubstitution, null, 'str');\n\n\tconst\n\t\turlValueRex = new RegExp('(?:^|\\\\s|,)url\\\\((?:\\'|\")?([^\\'\"\\\\n\\\\r\\\\t]+)(?:\\'|\")?\\\\)', 'gmi'),\n\t\tmatches = []\n\t;\n\n\tlet match;\n\twhile( (match = urlValueRex.exec(urlValue)) !== null ){\n\t\tmatch = match[1];\n\t\tif( hasValue(baseUrl, baseUrlSubstitution) ){\n\t\t\tmatch = match.replace(new RegExp(`^${maskForRegEx(baseUrl)}`), baseUrlSubstitution);\n\t\t}\n\t\tmatches.push(match);\n\t}\n\n\tif( matches.length === 1 ){\n\t\treturn matches[0];\n\t} else if( matches.length > 1 ){\n\t\treturn matches;\n\t} else {\n\t\treturn null;\n\t}\n}\n\n\n\n/**\n * @namespace CSS:remByPx\n */\n\n/**\n * Calculates a rem value based on a given px value.\n * As a default this method takes the font-size (supposedly being in px) of the html-container.\n * You can overwrite this behaviour by setting initial to a number to use as a base px value or\n * to a string, which then defines a new selector for an element to get the initial font-size from.\n * You can also provide an HTMLElement directly, but keep in mind that the element's font size definition\n * has to be in pixels, to make this work.\n *\n * In most cases you will have to define the initial value via a constant or a selector to a container\n * with non-changing font-size, since you can never be sure which relative font-size applies atm, even on first\n * call, after dom ready, since responsive definitions might already be active, returning a viewport-specific\n * size.\n *\n * @param {Number} px - the pixel value to convert to rem\n * @param {?(Number|String|HTMLElement)} [initial='html'] - either a pixel value to use as a conversion base, a selector for an element to get the initial font-size from or the element itself; keep in mind, that the element's font-size definition has to be in px\n * @throws error if given selector in initial does not return an element\n * @returns {String|null} the rem value string to use in a css definition or null if the value could not be calculated\n *\n * @memberof CSS:remByPx\n * @alias remByPx\n * @example\n * remByPx(20, 16);\n * => '1.25rem'\n * remByPx('100px', 'p.has-base-fontsize');\n */\nexport function remByPx(px, initial='html'){\n\tpx = cssValueToNumber(px);\n\tinitial = orDefault(initial, 'html');\n\n\tif( isElement(initial) ){\n\t\tinitial = cssValueToNumber(initial.style.getPropertyValue('font-size'));\n\t} else {\n\t\tconst value = cssValueToNumber(initial);\n\t\tif( isNaN(value) ){\n\t\t\tconst element = document.querySelector(initial);\n\t\t\tassert(hasValue(element), `${MODULE_NAME}:remByPx | selector does not return element`);\n\t\t\tinitial = cssValueToNumber(element.style.getPropertyValue('font-size'));\n\t\t} else {\n\t\t\tinitial = value;\n\t\t}\n\t}\n\n\tconst remVal = px / initial;\n\n\tif( (initial !== 0) && !isNaN(remVal) ){\n\t\treturn `${remVal}rem`;\n\t} else {\n\t\treturn null;\n\t}\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/elements.js b/docs/examples/lib/annex/dist/elements.js index 82345eea..3a735825 100644 --- a/docs/examples/lib/annex/dist/elements.js +++ b/docs/examples/lib/annex/dist/elements.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Elements */ -const MODULE_NAME="Elements";import{orDefault,isA,isPlainObject,isSelector,isElement,hasValue,assert,size,Deferred}from"./basic.js";import{randomUuid}from"./random.js";import{clone}from"./objects.js";import{onDomReady}from"./events.js";import{applyStyles}from"./css.js";const NOT_AN_HTMLELEMENT_ERROR="given node/target is not an HTMLElement";let BROWSER_HAS_CSS_SCOPE_SUPPORT;try{document.querySelector(":scope *")}catch(e){BROWSER_HAS_CSS_SCOPE_SUPPORT=!1}export function createNode(e,t=null,n=null){e=orDefault(e,"span","str").trim(),t=isPlainObject(t)?t:null,n=orDefault(n,null,"str");const s=document.createElement("div");/^<[^\/][^<>]*>/.test(e)&&/<\/[^<>\/]+>$/.test(e)?s.innerHTML=e:s.appendChild(document.createElement(e));const r=s.firstChild;if(s.removeChild(r),hasValue(t))for(let e in t)r.setAttribute(e,`${t[e]}`);return hasValue(n)&&(r.textContent=n),r}export function insertNode(e,t,n="beforeend"){switch(assert(isElement(e),`Elements.insertNode | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),n){case"beforebegin":case"before":n="beforebegin";break;case"afterend":case"after":n="afterend";break;case"afterbegin":case"prepend":n="afterbegin";break;default:n="beforeend"}return e.insertAdjacentElement(n,t),t}export function replaceNode(e,t){const n="replaceNode";return assert(isElement(e),`Elements.${n} | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),assert(isElement(e.parentNode),`Elements.${n} | given target does not have a parent)`),insertNode(e,t,"after"),e.parentNode.removeChild(e),t}export function defineNode(e,t,n=null){const s="defineNode";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isPlainObject(t),`Elements:${s} | definitions is not a plain object`);const r="<-";return isElement(n)&&Array.from(n.attributes).forEach((e=>{(t[e.name]===r||!hasValue(t[e.name])&&(t["data*"]===r&&e.name.startsWith("data-")||t["on*"]===r&&e.name.startsWith("on")))&&(t[e.name]=e.value),(t[`+${e.name}`]===r||!hasValue(t[`+${e.name}`])&&(t["+data*"]===r&&e.name.startsWith("data-")||t["+on*"]===r&&e.name.startsWith("on")))&&(hasValue(t[`+${e.name}`])&&t[`+${e.name}`]!==r||(t[`+${e.name}`]=""),t[`+${e.name}`]+=e.value)})),delete t["data*"],delete t["+data*"],delete t["on*"],delete t["+on*"],Object.keys(t).forEach((e=>{t[e]===r&&delete t[e]})),Object.keys(t).sort().reverse().forEach((n=>{const s=t[n],r=n.startsWith("+");r&&(n=n.slice(1)),n.endsWith("*")&&(n=n.slice(0,-1)),"class"===n?(r||e.setAttribute("class",""),[].concat(s).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(`${t.trim()}`)}))}))):"style"===n?(r||e.setAttribute("style",""),[].concat(s).forEach((t=>{if(!isPlainObject(t)){const e=`${t}`.split(";"),n={};e.forEach((e=>{let[t,s]=e.split(":");t=t.trim(),hasValue(s)&&(s=s.trim(),s=s.endsWith(";")?s.slice(0,-1):s,n[t]=s)})),t=n}hasValue(t)&&applyStyles(e,t)}))):r?e.setAttribute(n,`${e.getAttribute(n)??""}${s}`):e.setAttribute(n,`${s}`)})),e}export function getTextContent(e,t=!1){if(t=orDefault(t,!1,"bool"),isA(e,"string")&&(e=createNode(e)),assert(isElement(e),"Elements:getTextContent | target is neither node nor markup"),t){let t="";return e.childNodes.forEach((e=>{3===e.nodeType&&(t+=e.textContent)})),t}return e.textContent}export function isInDom(e){return assert(isElement(e),`Elements:isInDom | ${NOT_AN_HTMLELEMENT_ERROR}`),isA(document.contains,"function")?document.contains(e):document.body.contains(e)}export function getData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:getData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n={};return hasValue(t)?t.forEach((t=>{let s=e.getAttribute(`data-${t}`);if(hasValue(s))try{n[t]=JSON.parse(s)}catch(e){n[t]=s}})):Array.from(e.attributes).forEach((e=>{if(e.name.startsWith("data-")){const t=e.name.replace(/^data-/,"");try{n[t]=JSON.parse(e.value)}catch(s){n[t]=e.value}}})),0===size(n)?n=null:1===t?.length&&(n=n[t[0]]??null),n}export function setData(e,t,n=null){const s="setData";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`);let r=null;hasValue(n)&&(r=`${t}`,t={[r]:n}),assert(isPlainObject(t),`Elements:${s} | dataSet is not a plain object`);const a={};return Object.entries(t).forEach((([t,n])=>{if(isA(n,"function")&&(n=n()),void 0!==n){let s,r;try{s=JSON.stringify(n),r=JSON.parse(s)}catch(e){s=`${n}`,r=s}s=s.replace(/^['"]/,"").replace(/['"]$/,"").trim(),""!==s?(a[t]=r,e.setAttribute(`data-${t}`,s)):e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))}else e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))})),hasValue(r)?r in a?a[r]:null:size(a)>0?a:null}export function removeData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:removeData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n=getData(e,t);return hasValue(n)?setData(e,1===t?.length?{[t[0]]:void 0}:Object.keys(n).reduce(((e,t)=>(e[t]=void 0,e)),{})):n=null,n}export function find(e,t="*",n=!1){const s=/:scope(?![\w-])/gi;if(assert(isElement(e),`Elements:find | ${NOT_AN_HTMLELEMENT_ERROR}`),t=orDefault(t,"*","str").trim(),s.test(t)||(t=`:scope ${t}`),n=orDefault(n,!1,"bool"),BROWSER_HAS_CSS_SCOPE_SUPPORT)return n?e.querySelector(t):Array.from(e.querySelectorAll(t));{const r=`find-scope-${randomUuid()}`;t=t.replace(s,`[${r}]`),e.setAttribute(r,"");const a=n?e.querySelector(t):Array.from(e.querySelectorAll(t));return e.removeAttribute(r),a}}export function findOne(e,t="*"){return find(e,t,!0)}export function findTextNodes(e,t=null,n=!1){t=isA(t,"function")?t:()=>!0,n=orDefault(n,!1,"bool"),assert(isElement(e),`Elements:findTextNodes | ${NOT_AN_HTMLELEMENT_ERROR}`);const s=e=>3===e.nodeType&&""!==e.textContent.trim()&&!!t(e),r=e=>s(e)?[].concat(e):Array.from(e.childNodes).reduce(((e,t)=>s(t)?e.concat(t):n?e:e.concat(r(t))),[]);return r(e)}export function prime(e,t,n=null,s="primed"){const r="prime";n=orDefault(n,{}),s=orDefault(s,"primed","str"),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isA(t,"function"),`Elements:${r} | init is not a function`);const a=new Deferred;return!0!==getData(e,s)?(setData(e,s,!0),onDomReady((()=>{const n=t(e);hasValue(n)&&isA(n.then,"function")&&isA(n.catch,"function")?n.then((e=>{a.resolve(e)})).catch((e=>{a.reject(e)})):a.resolve(n),setData(e,`${s}-ready`,!0)}))):a.resolve(void 0),a.then((()=>{hasValue(n.remove)&&[].concat(n.remove).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.remove(t.trim())}))})),hasValue(n.add)&&[].concat(n.add).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(t.trim())}))})),setData(e,`${s}-resolved`,!0)})),a}export function measureHiddenDimensions(e,t="outer",n=null,s=null){const r="measureHidden",a={offset:{width:"offsetWidth",height:"offsetHeight"},outer:{width:"offsetWidth",height:"offsetHeight"},client:{width:"clientWidth",height:"clientHeight"},inner:{width:"clientWidth",height:"clientHeight"},scroll:{width:"scrollWidth",height:"scrollHeight"}};t=a[orDefault(t,"outer","str")]??a.outer,s=orDefault(s,document.body),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isElement(s),`Elements:${r} | context is no an htmlelement`);const o=createNode("div",{id:`sandbox-${randomUuid()}`,class:"sandbox",style:"display:block; opacity:0; visibility:hidden; pointer-events:none; position:absolute; top:-10000px; left:-10000px;"}),i=clone(e);s.appendChild(o),o.appendChild(i);const l=isSelector(n)?i.querySelector(n):i,c=l?.[t.width]??0,d=l?.[t.height]??0,u={width:c,height:d,toString:()=>`${c}x${d}`};return s.removeChild(o),u} +const MODULE_NAME="Elements";import{orDefault,isString,isFunction,isPlainObject,isSelector,isElement,hasValue,assert,size,Deferred}from"./basic.js";import{randomUuid}from"./random.js";import{clone}from"./objects.js";import{onDomReady}from"./events.js";import{applyStyles}from"./css.js";const NOT_AN_HTMLELEMENT_ERROR="given node/target is not an HTMLElement";let BROWSER_HAS_CSS_SCOPE_SUPPORT;try{document.querySelector(":scope *")}catch(e){BROWSER_HAS_CSS_SCOPE_SUPPORT=!1}export function createNode(e,t=null,n=null){e=orDefault(e,"span","str").trim(),t=isPlainObject(t)?t:null,n=orDefault(n,null,"str");const s=document.createElement("div");/^<[^\/][^<>]*>/.test(e)&&/<\/[^<>\/]+>$/.test(e)?s.innerHTML=e:s.appendChild(document.createElement(e));const r=s.firstChild;if(s.removeChild(r),hasValue(t))for(let e in t)r.setAttribute(e,`${t[e]}`);return hasValue(n)&&(r.textContent=n),r}export function insertNode(e,t,n="beforeend"){switch(assert(isElement(e),`Elements.insertNode | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),n){case"beforebegin":case"before":n="beforebegin";break;case"afterend":case"after":n="afterend";break;case"afterbegin":case"prepend":n="afterbegin";break;default:n="beforeend"}return e.insertAdjacentElement(n,t),t}export function replaceNode(e,t){const n="replaceNode";return assert(isElement(e),`Elements.${n} | ${NOT_AN_HTMLELEMENT_ERROR}`),isElement(t)||(t=createNode(`${t}`)),assert(isElement(e.parentNode),`Elements.${n} | given target does not have a parent)`),insertNode(e,t,"after"),e.parentNode.removeChild(e),t}export function defineNode(e,t,n=null){const s="defineNode";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isPlainObject(t),`Elements:${s} | definitions is not a plain object`);const r="<-";return isElement(n)&&Array.from(n.attributes).forEach((e=>{(t[e.name]===r||!hasValue(t[e.name])&&(t["data*"]===r&&e.name.startsWith("data-")||t["on*"]===r&&e.name.startsWith("on")))&&(t[e.name]=e.value),(t[`+${e.name}`]===r||!hasValue(t[`+${e.name}`])&&(t["+data*"]===r&&e.name.startsWith("data-")||t["+on*"]===r&&e.name.startsWith("on")))&&(hasValue(t[`+${e.name}`])&&t[`+${e.name}`]!==r||(t[`+${e.name}`]=""),t[`+${e.name}`]+=e.value)})),delete t["data*"],delete t["+data*"],delete t["on*"],delete t["+on*"],Object.keys(t).forEach((e=>{t[e]===r&&delete t[e]})),Object.keys(t).sort().reverse().forEach((n=>{const s=t[n],r=n.startsWith("+");r&&(n=n.slice(1)),n.endsWith("*")&&(n=n.slice(0,-1)),"class"===n?(r||e.setAttribute("class",""),[].concat(s).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(`${t.trim()}`)}))}))):"style"===n?(r||e.setAttribute("style",""),[].concat(s).forEach((t=>{if(!isPlainObject(t)){const e=`${t}`.split(";"),n={};e.forEach((e=>{let[t,s]=e.split(":");t=t.trim(),hasValue(s)&&(s=s.trim(),s=s.endsWith(";")?s.slice(0,-1):s,n[t]=s)})),t=n}hasValue(t)&&applyStyles(e,t)}))):r?e.setAttribute(n,`${e.getAttribute(n)??""}${s}`):e.setAttribute(n,`${s}`)})),e}export function getTextContent(e,t=!1){if(t=orDefault(t,!1,"bool"),isString(e)&&(e=createNode(e)),assert(isElement(e),"Elements:getTextContent | target is neither node nor markup"),t){let t="";return e.childNodes.forEach((e=>{3===e.nodeType&&(t+=e.textContent)})),t}return e.textContent}export function isInDom(e){return assert(isElement(e),`Elements:isInDom | ${NOT_AN_HTMLELEMENT_ERROR}`),isFunction(document.contains)?document.contains(e):document.body.contains(e)}export function getData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:getData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n={};return hasValue(t)?t.forEach((t=>{let s=e.getAttribute(`data-${t}`);if(hasValue(s))try{n[t]=JSON.parse(s)}catch(e){n[t]=s}})):Array.from(e.attributes).forEach((e=>{if(e.name.startsWith("data-")){const t=e.name.replace(/^data-/,"");try{n[t]=JSON.parse(e.value)}catch(s){n[t]=e.value}}})),0===size(n)?n=null:1===t?.length&&(n=n[t[0]]??null),n}export function setData(e,t,n=null){const s="setData";assert(isElement(e),`Elements:${s} | ${NOT_AN_HTMLELEMENT_ERROR}`);let r=null;hasValue(n)&&(r=`${t}`,t={[r]:n}),assert(isPlainObject(t),`Elements:${s} | dataSet is not a plain object`);const a={};return Object.entries(t).forEach((([t,n])=>{if(isFunction(n)&&(n=n()),void 0!==n){let s,r;try{s=JSON.stringify(n),r=JSON.parse(s)}catch(e){s=`${n}`,r=s}s=s.replace(/^['"]/,"").replace(/['"]$/,"").trim(),""!==s?(a[t]=r,e.setAttribute(`data-${t}`,s)):e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))}else e.hasAttribute(`data-${t}`)&&(a[t]=void 0,e.removeAttribute(`data-${t}`))})),hasValue(r)?r in a?a[r]:null:size(a)>0?a:null}export function removeData(e,t=null){t=orDefault(t,null,"arr"),assert(isElement(e),`Elements:removeData | ${NOT_AN_HTMLELEMENT_ERROR}`);let n=getData(e,t);return hasValue(n)?setData(e,1===t?.length?{[t[0]]:void 0}:Object.keys(n).reduce(((e,t)=>(e[t]=void 0,e)),{})):n=null,n}export function find(e,t="*",n=!1){const s=/:scope(?![\w-])/gi;if(assert(isElement(e),`Elements:find | ${NOT_AN_HTMLELEMENT_ERROR}`),t=orDefault(t,"*","str").trim(),s.test(t)||(t=`:scope ${t}`),n=orDefault(n,!1,"bool"),BROWSER_HAS_CSS_SCOPE_SUPPORT)return n?e.querySelector(t):Array.from(e.querySelectorAll(t));{const r=`find-scope-${randomUuid()}`;t=t.replace(s,`[${r}]`),e.setAttribute(r,"");const a=n?e.querySelector(t):Array.from(e.querySelectorAll(t));return e.removeAttribute(r),a}}export function findOne(e,t="*"){return find(e,t,!0)}export function findTextNodes(e,t=null,n=!1){t=isFunction(t)?t:()=>!0,n=orDefault(n,!1,"bool"),assert(isElement(e),`Elements:findTextNodes | ${NOT_AN_HTMLELEMENT_ERROR}`);const s=e=>3===e.nodeType&&""!==e.textContent.trim()&&!!t(e),r=e=>s(e)?[].concat(e):Array.from(e.childNodes).reduce(((e,t)=>s(t)?e.concat(t):n?e:e.concat(r(t))),[]);return r(e)}export function prime(e,t,n=null,s="primed"){const r="prime";n=orDefault(n,{}),s=orDefault(s,"primed","str"),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isFunction(t),`Elements:${r} | init is not a function`);const a=new Deferred;return!0!==getData(e,s)?(setData(e,s,!0),onDomReady((()=>{const n=t(e);hasValue(n)&&isFunction(n.then)&&isFunction(n.catch)?n.then((e=>{a.resolve(e)})).catch((e=>{a.reject(e)})):a.resolve(n),setData(e,`${s}-ready`,!0)}))):a.resolve(void 0),a.then((()=>{hasValue(n.remove)&&[].concat(n.remove).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.remove(t.trim())}))})),hasValue(n.add)&&[].concat(n.add).forEach((t=>{`${t}`.split(" ").forEach((t=>{e.classList.add(t.trim())}))})),setData(e,`${s}-resolved`,!0)})),a}export function measureHiddenDimensions(e,t="outer",n=null,s=null){const r="measureHidden",a={offset:{width:"offsetWidth",height:"offsetHeight"},outer:{width:"offsetWidth",height:"offsetHeight"},client:{width:"clientWidth",height:"clientHeight"},inner:{width:"clientWidth",height:"clientHeight"},scroll:{width:"scrollWidth",height:"scrollHeight"}};t=a[orDefault(t,"outer","str")]??a.outer,s=orDefault(s,document.body),assert(isElement(e),`Elements:${r} | ${NOT_AN_HTMLELEMENT_ERROR}`),assert(isElement(s),`Elements:${r} | context is no an htmlelement`);const o=createNode("div",{id:`sandbox-${randomUuid()}`,class:"sandbox",style:"display:block; opacity:0; visibility:hidden; pointer-events:none; position:absolute; top:-10000px; left:-10000px;"}),i=clone(e);s.appendChild(o),o.appendChild(i);const l=isSelector(n)?i.querySelector(n):i,c=l?.[t.width]??0,d=l?.[t.height]??0,u={width:c,height:d,toString:()=>`${c}x${d}`};return s.removeChild(o),u} //# sourceMappingURL=elements.js.map diff --git a/docs/examples/lib/annex/dist/elements.js.map b/docs/examples/lib/annex/dist/elements.js.map index fa897e6e..dd6302da 100644 --- a/docs/examples/lib/annex/dist/elements.js.map +++ b/docs/examples/lib/annex/dist/elements.js.map @@ -1 +1 @@ -{"version":3,"file":"elements.js","names":["MODULE_NAME","orDefault","isA","isPlainObject","isSelector","isElement","hasValue","assert","size","Deferred","randomUuid","clone","onDomReady","applyStyles","NOT_AN_HTMLELEMENT_ERROR","BROWSER_HAS_CSS_SCOPE_SUPPORT","document","querySelector","ex","createNode","tag","attributes","content","trim","outerNode","createElement","test","innerHTML","appendChild","node","firstChild","removeChild","attribute","setAttribute","textContent","insertNode","target","position","insertAdjacentElement","replaceNode","__methodName__","parentNode","defineNode","definition","boilerplateNode","inheritValue","Array","from","forEach","name","startsWith","value","Object","keys","sort","reverse","addValue","slice","endsWith","concat","split","classList","add","rules","valueObj","rule","key","prop","getAttribute","getTextContent","onlyFirstLevel","childNodes","nodeType","isInDom","contains","body","getData","properties","data","property","attributeValue","JSON","parse","replace","length","setData","dataSet","singleValue","singleKey","appliedValues","entries","undefined","stringifiedValue","getValue","stringify","hasAttribute","removeAttribute","removeData","reduce","removalDataSet","find","selector","onlyOne","scopeRex","querySelectorAll","fallbackScopeAttribute","found","findOne","findTextNodes","filter","isValidTextNode","extractTextNodes","textNodes","childNode","prime","init","classChanges","markerAttributesName","deferred","initResult","then","catch","resolution","resolve","error","reject","remove","removeClass","addClass","measureHiddenDimensions","method","context","methods","offset","width","height","outer","client","inner","scroll","sandbox","id","class","style","measureClone","dimensions","toString"],"sources":["elements.js"],"mappings":"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","sourcesContent":["/*!\n * Module Elements\n */\n\n/**\n * @namespace Elements\n */\n\nconst MODULE_NAME = 'Elements';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {orDefault, isA, isPlainObject, isSelector, isElement, hasValue, assert, size, Deferred} from './basic.js';\nimport {randomUuid} from './random.js';\nimport {clone} from './objects.js';\nimport {onDomReady} from './events.js';\nimport {applyStyles} from './css.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst NOT_AN_HTMLELEMENT_ERROR = 'given node/target is not an HTMLElement';\nlet BROWSER_HAS_CSS_SCOPE_SUPPORT;\ntry {\n\tdocument.querySelector(':scope *');\n} catch(ex){\n\tBROWSER_HAS_CSS_SCOPE_SUPPORT = false;\n}\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Elements:createNode\n */\n\n/**\n * Creates an element on the fly programmatically, based on provided name, attributes and content or markup,\n * without inserting it into the DOM.\n *\n * If you provide markup as \"tag\", make sure that there is one single root element, this method returns exactly one\n * element, not a NodeList. Also be sure to _not_ just pass HTML source from an unsecure source, since this\n * method does not deal with potential security risks.\n *\n * One thing about dynamically creating script tags with this: if you want the script is javascript and you want to\n * actually execute the script upon adding it to the dom, you cannot provide the complete tag as a source string,\n * since scripts created with innerHTML will not execute.\n * (see: https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#security_considerations)\n * Instead, just provide the tag name and define attributes and source via the parameters instead.\n *\n * @param {?String} [tag='span'] - tag of the element to create or markup for root element\n * @param {?Object} [attributes=null] - tag attributes as key/value-pairs, will also be added to provided markup\n * @param {?String} [content=null] - content to insert into the element as textContent, be aware, that this will replace other content in provided markup\n * @returns {HTMLElement} the created DOM-node\n *\n * @memberof Elements:createNode\n * @alias createNode\n * @example\n * document.body.appendChild(\n * createNode('div', {id : 'content', style : 'display:none;'}, 'loading...')\n * );\n * document.body.appendChild(\n * createNode('
loading...
')\n * );\n * document.body.appendChild(\n * createNode('script', {type : 'text/javascript'}, 'alert(\"Hello World\");');\n * );\n */\nexport function createNode(tag, attributes=null, content=null){\n\ttag = orDefault(tag, 'span', 'str').trim();\n\tattributes = isPlainObject(attributes) ? attributes : null;\n\tcontent = orDefault(content, null, 'str');\n\n\t// using anything more generic like template results in non-standard nodes like\n\t// `);\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve(\n\t\t\t\t\t\t(resolveTo === 'element')\n\t\t\t\t\t\t\t? element\n\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t(resolveTo === 'raw')\n\t\t\t\t\t\t\t\t? JSON.stringify(json)\n\t\t\t\t\t\t\t\t: json\n\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createRestfulJsonClient\n */\n\n/**\n * @typedef RestfulJsonClientPathFunction\n * @type {Function}\n * @param {String} path - the current path to request from baseUrl\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientOptionsFunction\n * @type {Function}\n * @param {?Object} options - options plain object to merge with baseOptions to define current request options (see JsonFetchRequest for details and defaults); if nullish, will reset to baseOptions\n * @throws error if given options are not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientHeaderFunction\n * @type {Function}\n * @param {String} key - the header to set for all following requests\n * @param {?String} value - the header's value; nullish value will remove the header again\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientParamsFunction\n * @type {Function}\n * @param {?*} params - query parameters to set on the current URL, this parameter takes all regular definitions for URLSearchParams constructor, as well as flat plain objects, which may also have arrays as values; if nullish, parameters are emptied\n * @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientDataFunction\n * @type {Function}\n * @param {?Object} data - data payload to send with the next POST, PUT or PATCH request, this parameter will set a permanent payload, for one-off payloads, use the verb method's parameter; if nullish, data will be emptied\n * @throws error if given data is not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientGetFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPostFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPutFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPatchFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientDeleteFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClient\n * @type {Object}\n * @property {Object} config - the current configuration state of the client\n * @property {URL} config.url=baseUrl - the current, complete URL to query (baseUrl + path)\n * @property {Object} config.options - the current request options (see JsonFetchRequest for details and defaults)\n * @property {URLSearchParams} config.params - the current searchParams of config.url, with which to query the URL\n * @property {Object} config.data={} - the current data payload object to send with POST, PUT and PATCH (this will persist between requests, set one-off data via verb methods)\n * @property {RestfulJsonClientPathFunction} path - sets the current request path, which will be concatenated after baseUrl\n * @property {RestfulJsonClientOptionsFunction} options - sets the current request options, which will be merged with baseOptions to constitute current request options\n * @property {RestfulJsonClientHeaderFunction} header - sets a header for all subsequent requests\n * @property {RestfulJsonClientParamsFunction} params - sets query parameters to be added to the request URL\n * @property {RestfulJsonClientDataFunction} data - sets data payload for POST, PUT and PATCH requests\n * @property {RestfulJsonClientGetFunction} get - queries the current URL via GET\n * @property {RestfulJsonClientPostFunction} post - queries the current URL via POST using defined data\n * @property {RestfulJsonClientPutFunction} put - queries the current URL via PUT using defined data\n * @property {RestfulJsonClientPatchFunction} patch - queries the current URL via PATCH using defined data\n * @property {RestfulJsonClientDeleteFunction} delete - queries the current URL via DELETE\n */\n\n/**\n * This method creates a dedicated client for restful operations against an API via JSON payloads and responses.\n *\n * Internally this implementation uses createJsonRequest to actually request stuff, while the return value of this\n * method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as\n * standard methods for HTTP verbs and setup things like setting headers.\n *\n * @param {String} baseUrl - the base URL for all queries, based on which final request URLs will be built, adding the paths\n * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/json\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/json\"\n * @returns {RestfulJsonClient}\n *\n * @memberof Requests:createRestfulJsonClient\n * @alias createRestfulJsonClient\n * @see createJsonRequest\n * @example\n * const client = createRestfulJsonClient('https://jsonplaceholder.typicode.com', {credentials : 'include'});\n * const postJson = await client\n * .path('/posts')\n * \t .params({\n * \t ids : [1, 2],\n * \t q : 'lorem'\n * \t })\n * \t .data({\n * \t title : 'foo',\n * \t body : 'bar',\n * \t userId : 1,\n * \t })\n * \t .post()\n * ;\n */\nexport function createRestfulJsonClient(baseUrl, baseOptions=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createRestfulJsonClient',\n\t\timplementation = createJsonRequest,\n\t\tcontentTypeHeader = 'Content-Type',\n\t\tcontentType = 'application/json',\n\t\tdataValidationMessage = 'data must be plain object',\n\t\toptionsValidationMessage = 'options must be plain object'\n\t;\n\n\n\tfunction flatEntries(obj){\n\t\tconst\n\t\t\tentries = Object.entries(obj),\n\t\t\tflattenedEntries = []\n\t\t;\n\n\t\tfor(const entryIndex in entries ){\n\t\t\tconst\n\t\t\t\tentryKey = entries[entryIndex][0],\n\t\t\t\tentryVal = entries[entryIndex][1],\n\t\t\t\tentryValType = getType(entryVal)\n\t\t\t;\n\n\t\t\tif( ['array', 'set'].includes(entryValType) ){\n\t\t\t\tArray.from(entryVal).forEach(val => {\n\t\t\t\t\tflattenedEntries.push([entryKey, `${val}`]);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tflattenedEntries.push([entryKey, `${entryVal}`]);\n\t\t\t}\n\t\t}\n\n\t\treturn flattenedEntries;\n\t}\n\n\n\tfunction request(client, method){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['GET', 'DELETE'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tclient.config.options.method = method;\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t})\n\t\t;\n\t}\n\n\n\tfunction requestWithPayload(client, method, data=null){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['POST', 'PUT', 'PATCH'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tif( hasValue(data) ){\n\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | ${dataValidationMessage}`);\n\t\t}\n\n\t\tclient.config.options.method = method;\n\t\tclient.config.options.body = JSON.stringify(data ?? client.config.data);\n\t\tclient.header(contentTypeHeader, `${contentType}; charset=UTF-8`);\n\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t\tdelete client.config.options.body;\n\t\t\t\tclient.header(contentTypeHeader, null);\n\t\t\t})\n\t\t;\n\t}\n\n\n\treturn {\n\t\tconfig : {\n\t\t\turl : new URL('/', baseUrl),\n\t\t\toptions : isPlainObject(baseOptions) ? baseOptions : {},\n\t\t\tparams : new URLSearchParams(),\n\t\t\tdata : {},\n\t\t},\n\n\t\tpath(path){\n\t\t\tthis.config.url = new URL(path, baseUrl);\n\t\t\treturn this;\n\t\t},\n\n\t\toptions(options){\n\t\t\tif( hasValue(options) ){\n\t\t\t\tassert(isPlainObject(options), `${MODULE_NAME}:${__methodName__} | ${optionsValidationMessage}`);\n\t\t\t\tthis.config.options = merge(baseOptions, options);\n\t\t\t} else {\n\t\t\t\tthis.config.options = baseOptions;\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\theader(key, value){\n\t\t\tif( !hasValue(this.config.options.headers) ){\n\t\t\t\tthis.config.options.headers = {};\n\t\t\t}\n\t\t\tif( hasValue(value) ){\n\t\t\t\tthis.config.options.headers[`${key}`] = `${value}`;\n\t\t\t} else {\n\t\t\t\tdelete this.config.options.headers[`${key}`];\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tparams(params){\n\t\t\tif( hasValue(params) ){\n\t\t\t\tthis.config.params = new URLSearchParams(isPlainObject(params) ? flatEntries(params) : params);\n\t\t\t} else {\n\t\t\t\tthis.config.params = new URLSearchParams();\n\t\t\t}\n\t\t\tthis.config.url.search = this.config.params.toString();\n\t\t\treturn this;\n\t\t},\n\n\t\tdata(data){\n\t\t\tif( hasValue(data) ){\n\t\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | `);\n\t\t\t\tthis.config.data = data;\n\t\t\t} else {\n\t\t\t\tthis.config.data = {};\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tget(){\n\t\t\treturn request(this, 'GET');\n\t\t},\n\n\t\tpost(data=null){\n\t\t\treturn requestWithPayload(this, 'POST', data);\n\t\t},\n\n\t\tput(data=null){\n\t\t\treturn requestWithPayload(this, 'PUT', data);\n\t\t},\n\n\t\tpatch(data=null){\n\t\t\treturn requestWithPayload(this, 'PATCH', data);\n\t\t},\n\n\t\tdelete(){\n\t\t\treturn request(this, 'DELETE');\n\t\t},\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createJsRequest\n */\n\n/**\n * @typedef JsFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef JsFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a script with a src instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a script tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef JsFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {JsFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve JavaScript.\n *\n * Usually you'll want to retrieve JavaScript to include it into a page to execute the script on the page\n * currently open, so the default mode of this method is to resolve to a directly usable script tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw JavaScript source.\n *\n * Be aware that requesting JavaScript from an unsecure source is a very big security risk. Do not load and execute\n * source from a source you do not fully trust!\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline script, but\n * you may also choose to insert a sourced script tag, loading a script on insertion and executing in asynchronously\n * in turn. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * script, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/javascript\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/javascript\"\n * @returns {JsFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createJsRequest\n * @alias createJsRequest\n * @see createFetchRequest\n * @example\n * createJsRequest('/js/test.js')\n * .execute()\n * .then(jsElement => { document.body.appendChild(jsElement); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute(null, injectTarget, 'request-2')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.textContent}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'})\n * .then(rawJs => { alert(`has been injected: \"${rawJs}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.getAttribute('data-id')}\"`); })\n * ;\n */\nexport function createJsRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createJsRequest',\n\t\tcontentType = 'application/javascript'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, js='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? js : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? js : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tfInsertAndResolve(createNode('script', {src : url}));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for JavaScript, expecting \"application/javascript\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(js => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('script', null, js), js);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createCssRequest\n */\n\n/**\n * @typedef CssFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef CssFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a link with a href instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a style/link tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?String} [media='all'] - define the style's media attribute here to target the output device(s), could be \"screen\" or \"print\" for example\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef CssFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {CssFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve Cascading Stylesheets.\n *\n * Usually you'll want to retrieve CSS to include it into a page and thereby style something on the page\n * currently open, so the default mode of this method is to resolve to a directly usable style tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw CSS source.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline style, but\n * you may also choose to insert a sourced link tag, loading a stylesheet on insertion and adding the included styles\n * on load. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * link, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/css\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/css\"\n * @returns {CssFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createCssRequest\n * @alias createCssRequest\n * @see createFetchRequest\n * @example\n * createCssRequest('/css/test.css')\n * .execute()\n * .then(cssElement => { document.head.appendChild(cssElement); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute(null, injectTarget, 'request-2')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.textContent}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-3', 'screen')\n * .then(rawCss => { alert(`has been injected: \"${rawCss}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4', 'screen')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.getAttribute('data-id')+}\"`); })\n * ;\n */\nexport function createCssRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createCssRequest',\n\t\tcontentType = 'text/css'\n\t;\n\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, media='all', resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, css='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? css : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? css : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tconst linkAttrs = {href : url, rel : 'stylesheet'};\n\t\t\t\tif( media !== 'all' ){\n\t\t\t\t\tlinkAttrs.media = media;\n\t\t\t\t}\n\t\t\t\tfInsertAndResolve(createNode('link', linkAttrs));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for CSS, expecting \"text/css\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(css => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('style', (media !== 'all') ? {media} : null, css), css);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createHtmlRequest\n */\n\n/**\n * @typedef HtmlFetchResponse\n * @type {HTMLElement|Array|String}\n */\n\n/**\n * @typedef HtmlFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\" or \"raw\"\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as (a) node(s), otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node(s)\n * @param {?String} [selector=null] - if you'd like to preselect something from the result, you may define a regular query selector to find matching elements in the result\n * @param {?Boolean} [selectAll=false] - usually, if a selector is defined, we select a single element, if you need to select a list, set this to true\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef HtmlFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {HtmlFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve HTML content.\n *\n * Usually you'll want to retrieve HTML to include it into a page or extract information from it, so the default mode\n * of this method is to resolve to a node, you may insert into the DOM wherever you please or use stuff like a\n * querySelector on. However, you may also specify to retrieve the raw HTML source.\n *\n * Be aware, that requesting and parsing HTML from an unsecure source comes with a high risk. If you cannot fully\n * trust the source, request the HTML raw and use something like dom purify before using the result.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/html\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/html\"\n * @returns {HtmlFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createHtmlRequest\n * @alias createHtmlRequest\n * @see createFetchRequest\n * @example\n * createHtmlRequest('/html/test.html')\n * .execute()\n * .then(htmlElement => { document.body.appendChild(htmlElement); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute('raw', null, 'request-1')\n * .then(rawHtml => { alert(`document has been loaded: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute(null, injectTarget, 'request-3', 'body > main > h1')\n * .then(htmlElement => { alert(`has been injected: \"${htmlElement.outerHTML}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-1.html')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-4', 'h1 ~ p', true)\n * .then(rawHtml => { alert(`has been injected: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-2.html')\n * .execute('element', {element : injectTarget, position : 'prepend'}, 'request-5', 'p', true)\n * .then(htmlElements => { alert(`has been injected: \"${htmlElements.map(e => e.outerHTML).join('')}\"`); })\n * ;\n */\nexport function createHtmlRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createHtmlRequest',\n\t\tcontentType = 'text/html'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, selector=null, selectAll=false){\n\t\t\tconst\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, html='') => {\n\t\t\t\t\tif( hasValue(element) ){\n\t\t\t\t\t\tconst elements = [].concat(element);\n\n\t\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\t\tconst\n\t\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tif( ['before', 'beforebegin', 'prepend', 'afterbegin'].includes(position) ){\n\t\t\t\t\t\t\t\telements.reverse();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve((resolveTo === 'raw') ? html : element);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t.then(response => {\n\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t).split(';')[0].trim();\n\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for HTML, expecting \"text/html\"`;\n\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.text();\n\t\t\t\t})\n\t\t\t\t.then(html => {\n\t\t\t\t\tconst\n\t\t\t\t\t\tisWholeDocument = html.includes(' {\n\t\t\t\t\t\t\t\thtml += element.outerHTML;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfInsertAndResolve(element, html);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:visitUrl\n */\n\n/**\n * This function opens a given URL, using a dynamically created iframe, thereby opening the URL as if the user\n * him- or herself navigates to the URL using a browser window. Why should we do this you ask?\n *\n * For example: In session management, you'll sometimes have the case, that you need to trigger URLs on login or logout,\n * that construct or destruct parts of the session by creating of removing cookie or other client-storage items.\n * If that domain is part of a system running on another (sub)domain, using a usual client request for this will\n * not work, since the calling context of the request will have no access to the storage scope of that domain.\n *\n * So, to allow those domains to do their tasks, triggered from a different context, we can use this method to execute\n * those webhooks with the iframe, which natively runs in the called domains scope and therefore can do all necessary\n * domain-based storage actions.\n *\n * The big downside of this is, that we cannot really handle errors well this way. So if the URL returns a 404\n * or a 500, this will actually be treated as a resolved promise, since the iframe loaded. The only case a request\n * of this kind fails, is if the request runs into a timeout. So, for really critical actions, this way of handling\n * thing should be avoided in favour of an approach, that actually includes a postMessage implementation on the other\n * domain, to verify completion on load.\n *\n * @param {String} url - the URL to query, will be the current one if left empty\n * @param {?Number} [timeout=5000] - the timeout in ms to wait for completion of the request, before rejecting the promise\n * @param {?String} [tokenValue=null] - if the URL needs to include a token, you can provide this token here, which will replace the placeholder defined in \"tokenPlaceholder\"\n * @param {?String} [tokenPlaceholder='token'] = the placeholder in the url to replace with the tokenValue, must be surrounded with curly braces in the url (\"{token}\")\n * @returns {Deferred} resolves on load of URL (with the final URL as resolution value), rejects on timeout (with a \"timeout\" error)\n *\n * @memberof Requests:visitUrl\n * @alias visitUrl\n * @example\n * visitUrl('https://some.other.domain?token={token}', 2500, 'A38')\n * .then(() => { console.log('loaded!'); })\n * ;\n * visitUrl(\n * 'https://some.other.domain?token={session_value}',\n * 5000,\n * 'A38',\n * 'session_value'\n * )\n * .then(url => { console.log(`\"${url}\" loaded!`); })\n * .catch(error => { console.log(`${error.message} - URL did not load super fast, blimey!`); })\n * ;\n */\nexport function visitUrl(url, timeout=5000, tokenValue=null, tokenPlaceholder='token'){\n\turl = orDefault(url, '', 'str');\n\ttimeout = Math.abs(orDefault(timeout, 5000, 'int'));\n\ttokenValue = orDefault(tokenValue, null, 'str');\n\ttokenPlaceholder = orDefault(tokenPlaceholder, 'token', 'str');\n\turl = hasValue(tokenValue) ? url.replaceAll(`{${tokenPlaceholder}}`, tokenValue) : url;\n\n\tconst\n\t\tdeferred = new Deferred(),\n\t\touterNode = document.createElement('div')\n\t;\n\n\touterNode.innerHTML = `\n\t\t\n\t`.trim();\n\n\tconst\n\t\tiframe = outerNode.firstChild,\n\t\tfOnLoad = () => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\twindow.clearTimeout(loadTimeout);\n\t\t\t// we need to wait a bit after load before removing the iframe,\n\t\t\t// otherwise safari considers the request cancelled :(\n\t\t\twindow.setTimeout(() => {\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\tdeferred.resolve(url);\n\t\t\t}, 250);\n\t\t},\n\t\tloadTimeout = window.setTimeout(() => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\tdocument.body.removeChild(iframe);\n\t\t\tdeferred.reject(new Error('timeout'));\n\t\t}, timeout)\n\t;\n\n\tiframe.addEventListener('load', fOnLoad);\n\tdocument.body.appendChild(iframe);\n\n\treturn deferred;\n}\n"]} \ No newline at end of file +{"version":3,"file":"requests.js","names":["MODULE_NAME","warn","hasValue","orDefault","isPlainObject","assert","Deferred","getType","merge","createNode","insertNode","schedule","countermand","createFetchRequest","url","options","useNative","__methodName__","method","includes","toUpperCase","timeout","window","__ANNEX_USE_NATIVE_FETCH__","execute","res","request","XMLHttpRequest","headerKeys","Set","headerEntries","Map","response","ok","parseInt","status","statusText","responseURL","text","Promise","resolve","responseText","json","then","JSON","parse","blob","Blob","clone","headers","keys","entries","get","key","has","open","ontimeout","reject","Error","onload","getAllResponseHeaders","replace","m","value","add","set","onerror","withCredentials","credentials","i","hasOwnProperty","setRequestHeader","send","body","timeoutTimer","abortController","AbortController","signal","fetch","catch","error","abort","createJsonRequest","strict","contentType","resolveTo","insertTarget","dataId","responseContentType","split","trim","message","element","stringify","setAttribute","target","position","createRestfulJsonClient","baseUrl","baseOptions","location","origin","startsWith","implementation","contentTypeHeader","client","config","finally","requestWithPayload","data","header","URL","params","URLSearchParams","path","this","obj","Object","flattenedEntries","entryIndex","entryKey","entryVal","entryValType","Array","from","forEach","val","push","flatEntries","search","toString","post","put","patch","delete","createJsRequest","resolveSourcedOnInsert","sourceElementValue","fInsertAndResolve","js","src","createCssRequest","media","css","linkAttrs","href","rel","createHtmlRequest","selector","selectAll","html","isWholeDocument","isDocument","fragmentNode","DOMParser","parseFromString","documentElement","querySelectorAll","querySelector","children","length","item","concat","outerHTML","elements","reverse","visitUrl","tokenValue","tokenPlaceholder","Math","abs","replaceAll","deferred","outerNode","document","createElement","innerHTML","iframe","firstChild","fOnLoad","removeEventListener","clearTimeout","loadTimeout","setTimeout","removeChild","addEventListener","appendChild"],"sources":["requests.js"],"mappings":"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","sourcesContent":["/*!\n * Module Requests\n */\n\n/**\n * @namespace Requests\n */\n\nconst MODULE_NAME = 'Requests';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {warn} from './logging.js';\nimport {hasValue, orDefault, isPlainObject, assert, Deferred, getType} from './basic.js';\nimport {merge} from './objects.js';\nimport {createNode, insertNode} from './elements.js';\nimport {schedule, countermand} from './timers.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Requests:createFetchRequest\n */\n\n/**\n * @typedef FetchResponse\n * @type {Object}\n * @property {Boolean} ok - returns true if the request received a status in the OK range (200-299)\n * @property {Number} status - contains the status code of the response, e.g. 404 for a not found resource, 200 for a success\n * @property {String} statusText - a message related to the status attribute, e.g. OK for a status 200\n * @property {Function} clone - will return another object with the same shape and content as response\n * @property {Function} text - will return the response content as plain text\n * @property {Function} json - will return the response content as JSON\n * @property {Function} blob - will return the response content as a (binary) blob\n * @property {Object} headers - we do not implement a full spec-compliant Headers class, but emulate some of the functionality\n * @property {Function} headers.keys - returns an Iterable containing the key for every header in the response, transform to array with Array.from\n * @property {Function} headers.entries - returns an Iterable containing the [key, value] pairs for every header in the response, transform to array with Array.from\n * @property {Function} headers.get - returns the value associated with the given key\n * @property {Function} headers.has - returns a boolean asserting the existence of a value for the given key among the response headers\n */\n\n/**\n * @typedef FetchRequestExecuteFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef FetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {FetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a ponyfilled fetch request based on \"unfetch\", but basically fulfilling the signature of\n * a native fetch request.\n *\n * The reasoning for this is to provide a baseline fetch implementation for all requests of annex, as long as we\n * still support non ES6 browsers or old implementations in any way. During transpilation with core js, fetch does\n * not automatically get polyfilled, so we need to do this ourselves and to actually stay testable, we provide the\n * polyfill as long as we might target legacy contexts. As soon as we drop legacy contexts, we can immediately also\n * remove this method and its uses.\n *\n * The function signature is the same as \"unfetch\"'s and all non-implemented features are absent here as well.\n *\n * All usual responses (40X and 50X as well) resolve, only uncompletable requests, such as those being prevented by a\n * general network error, reject with the provided error.\n *\n * Set __ANNEX_USE_NATIVE_FETCH__ on window (true/false/'auto') to force useNative setting for all annex requests\n * globally.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options\n * @param {?String} [options.method='GET'] - indicates the request method to be performed on the target resource (one of \"GET\", \"POST\", \"PUT\", \"PATCH\", \"HEAD\", \"OPTIONS\" or \"DELETE\")\n * @param {?Object} [options.headers] - an object containing additional information to be sent with the request (e.g. {\"Content-Type\": \"application/json\"} to indicate a JSON-typed request body)\n * @param {?String} [options.credentials] - accepts an \"include\" string, which will allow both CORS and same origin requests to work with cookies; the method won't send or receive cookies otherwise; the \"same-origin\" value is not supported\n * @param {?Object|String} [options.body] - the content to be transmitted in request's body; common content types include FormData, JSON, Blob, ArrayBuffer or plain text\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @returns {FetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createFetchRequest\n * @alias createFetchRequest\n * @see https://github.com/developit/unfetch\n * @see https://github.com/developit/unfetch#fetchurl-string-options-object\n * @example\n * createFetchRequest('/foo').execute()\n * .then(r => r.text())\n * .then(txt => console.log(txt))\n * ;\n * createFetchRequest(\n * '/bear',\n * {\n * method : 'POST',\n * headers : {'Content-Type' : 'application/json'},\n * body : JSON.stringify({hungry : true})\n * })\n * .execute()\n * .then(r => { open(r.headers.get('location')); return r.json(); })\n * ;\n */\nexport function createFetchRequest(url, options=null, useNative=false){\n\tconst __methodName__ = 'createFetchRequest';\n\n\tassert(hasValue(url), `${MODULE_NAME}:${__methodName__} | no url given`);\n\toptions = orDefault(options, {});\n\tassert(isPlainObject(options), `${MODULE_NAME}:${__methodName__} | options must be plain object`);\n\n\toptions.method = orDefault(options.method, 'GET', 'str');\n\toptions.method = ['GET', 'POST', 'PUT', 'PATCH', 'HEAD', 'OPTIONS', 'DELETE'].includes(options.method.toUpperCase())\n\t\t? options.method.toUpperCase()\n\t\t: 'GET'\n\t;\n\n\t// 0 would be unlimited/unset\n\toptions.timeout = orDefault(options.timeout, 10000, 'int');\n\toptions.timeout = (options.timeout < 0) ? 0 : options.timeout;\n\n\tuseNative = window.__ANNEX_USE_NATIVE_FETCH__ ?? useNative;\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute : !useNative || ((useNative === 'auto') && !('fetch' in window))\n\t\t\t? function(){\n\t\t\t\tconst\n\t\t\t\t\tres = new Deferred(),\n\t\t\t\t\trequest = new XMLHttpRequest(),\n\t\t\t\t\theaderKeys = new Set(),\n\t\t\t\t\theaderEntries = new Map(),\n\t\t\t\t\tresponse = () => ({\n\t\t\t\t\t\tok : (parseInt(request.status, 10) >= 200) && (parseInt(request.status, 10) <= 299),\n\t\t\t\t\t\tstatusText : request.statusText,\n\t\t\t\t\t\tstatus : request.status,\n\t\t\t\t\t\turl : request.responseURL,\n\t\t\t\t\t\ttext : () => Promise.resolve(request.responseText),\n\t\t\t\t\t\tjson : () => Promise.resolve(request.responseText).then(JSON.parse),\n\t\t\t\t\t\tblob : () => Promise.resolve(new Blob([request.response])),\n\t\t\t\t\t\tclone : response,\n\t\t\t\t\t\theaders : {\n\t\t\t\t\t\t\tkeys(){\n\t\t\t\t\t\t\t\treturn headerKeys;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tentries(){\n\t\t\t\t\t\t\t\treturn headerEntries;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tget(key){\n\t\t\t\t\t\t\t\treturn headerEntries.get(key);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\thas(key){\n\t\t\t\t\t\t\t\treturn headerKeys.has(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t;\n\n\t\t\t\trequest.open(options.method, url, true);\n\n\t\t\t\tif( options.timeout > 0 ){\n\t\t\t\t\trequest.timeout = options.timeout;\n\t\t\t\t\trequest.ontimeout = () => { res.reject(new Error('timeout')); };\n\t\t\t\t}\n\n\t\t\t\trequest.onload = () => {\n\t\t\t\t\trequest.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm, (m, key, value) => {\n\t\t\t\t\t\tkey = `${key}`;\n\t\t\t\t\t\theaderKeys.add(key);\n\t\t\t\t\t\tif( headerEntries.has(key) ){\n\t\t\t\t\t\t\theaderEntries.set(key, `${headerEntries.get(key)},${value}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\theaderEntries.set(key, `${value}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tres.resolve(response());\n\t\t\t\t};\n\n\t\t\t\trequest.onerror = res.reject;\n\n\t\t\t\trequest.withCredentials = (options.credentials === 'include');\n\n\t\t\t\tif( hasValue(options.headers) ){\n\t\t\t\t\tfor( let i in options.headers ){\n\t\t\t\t\t\tif( options.headers.hasOwnProperty(i) ){\n\t\t\t\t\t\t\trequest.setRequestHeader(i, options.headers[i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trequest.send(options.body ?? null);\n\n\t\t\t\treturn res;\n\t\t\t}\n\t\t\t: function(){\n\t\t\t\tconst\n\t\t\t\t\tres = new Deferred(),\n\t\t\t\t\ttimeout = options.timeout\n\t\t\t\t;\n\n\t\t\t\tlet timeoutTimer, abortController;\n\n\t\t\t\tif( (timeout > 0) && ('AbortController' in window) ){\n\t\t\t\t\tabortController = new AbortController();\n\t\t\t\t\toptions.signal = abortController.signal;\n\t\t\t\t}\n\n\t\t\t\twindow.fetch(url, options)\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tcountermand(timeoutTimer);\n\t\t\t\t\t\tres.resolve(response);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tcountermand(timeoutTimer);\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\n\t\t\t\tif( (timeout > 0) && ('AbortController' in window) ){\n\t\t\t\t\ttimeoutTimer = schedule(timeout, () => { abortController.abort(); });\n\t\t\t\t}\n\n\t\t\t\treturn res;\n\t\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createJsonRequest\n */\n\n/**\n * @typedef JsonFetchResponse\n * @type {Object|HTMLElement|String}\n */\n\n/**\n * @typedef JsonFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='object'] - defines what the response should resolve to, may either be \"object\", \"element\" or \"raw\"\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a script tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef JsonFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {JsonFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve JSON data.\n *\n * Usually you'll want to retrieve JSON as a PlainObject, so that's the default resolve value here.\n * However, you may also specify to retrieve the raw JSON or let the method handle the creation of a DOM element\n * for you and return that, ready to be used/inserted however you like.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. BTW: Inserting does not automatically change the resolve value, those are separate\n * concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/json\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/json\"\n * @returns {JsonFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createJsonRequest\n * @alias createJsonRequest\n * @see createFetchRequest\n * @example\n * createJsonRequest('message.json').execute()\n * .then(json => { alert(json.someProperty); })\n * ;\n * createJsonRequest('/dev/config.json')\n * .execute('element', null, 'config-json-id')\n * .then(jsonElement => { document.querySelector('main').appendChild(jsonElement); })\n * ;\n * createJsonRequest('https://foobar.com/config.json')\n * .execute('raw', {element : document.body, position : 'prepend'}, 'config-json-id')\n * .then(rawJson => { console.log(`\"${rawJson}\" has been inserted at the beginning of the document's body`); })\n * ;\n */\nexport function createJsonRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createJsonRequest',\n\t\tcontentType = 'application/json'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='object', insertTarget=null, dataId=null){\n\t\t\tconst res = new Deferred();\n\n\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t.then(response => {\n\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for JSON, expecting \"application/json\"`;\n\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.json();\n\t\t\t\t})\n\t\t\t\t.then(json => {\n\t\t\t\t\tconst element = createNode(``);\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve(\n\t\t\t\t\t\t(resolveTo === 'element')\n\t\t\t\t\t\t\t? element\n\t\t\t\t\t\t\t: (\n\t\t\t\t\t\t\t\t(resolveTo === 'raw')\n\t\t\t\t\t\t\t\t? JSON.stringify(json)\n\t\t\t\t\t\t\t\t: json\n\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createRestfulJsonClient\n */\n\n/**\n * @typedef RestfulJsonClientPathFunction\n * @type {Function}\n * @param {String} path - the current path to request from baseUrl\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientOptionsFunction\n * @type {Function}\n * @param {?Object} options - options plain object to merge with baseOptions to define current request options (see JsonFetchRequest for details and defaults); if nullish, will reset to baseOptions\n * @throws error if given options are not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientHeaderFunction\n * @type {Function}\n * @param {String} key - the header to set for all following requests\n * @param {?String} value - the header's value; nullish value will remove the header again\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientParamsFunction\n * @type {Function}\n * @param {?*} params - query parameters to set on the current URL, this parameter takes all regular definitions for URLSearchParams constructor, as well as flat plain objects, which may also have arrays as values; if nullish, parameters are emptied\n * @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientDataFunction\n * @type {Function}\n * @param {?Object} data - data payload to send with the next POST, PUT or PATCH request, this parameter will set a permanent payload, for one-off payloads, use the verb method's parameter; if nullish, data will be emptied\n * @throws error if given data is not a plain object\n * @returns {RestfulJsonClient}\n */\n\n/**\n * @typedef RestfulJsonClientGetFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPostFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPutFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientPatchFunction\n * @type {Function}\n * @param {?Object} [data=null] - one-off data to use in this request, will replace any central data defined before and will only be valid for this request\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClientDeleteFunction\n * @type {Function}\n * @returns {Deferred}\n */\n\n/**\n * @typedef RestfulJsonClient\n * @type {Object}\n * @property {Object} config - the current configuration state of the client\n * @property {URL} config.url=baseUrl - the current, complete URL to query (baseUrl + path)\n * @property {Object} config.options - the current request options (see JsonFetchRequest for details and defaults)\n * @property {URLSearchParams} config.params - the current searchParams of config.url, with which to query the URL\n * @property {Object} config.data={} - the current data payload object to send with POST, PUT and PATCH (this will persist between requests, set one-off data via verb methods)\n * @property {RestfulJsonClientPathFunction} path - sets the current request path, which will be concatenated after baseUrl\n * @property {RestfulJsonClientOptionsFunction} options - sets the current request options, which will be merged with baseOptions to constitute current request options\n * @property {RestfulJsonClientHeaderFunction} header - sets a header for all subsequent requests\n * @property {RestfulJsonClientParamsFunction} params - sets query parameters to be added to the request URL\n * @property {RestfulJsonClientDataFunction} data - sets data payload for POST, PUT and PATCH requests\n * @property {RestfulJsonClientGetFunction} get - queries the current URL via GET\n * @property {RestfulJsonClientPostFunction} post - queries the current URL via POST using defined data\n * @property {RestfulJsonClientPutFunction} put - queries the current URL via PUT using defined data\n * @property {RestfulJsonClientPatchFunction} patch - queries the current URL via PATCH using defined data\n * @property {RestfulJsonClientDeleteFunction} delete - queries the current URL via DELETE\n */\n\n/**\n * This method creates a dedicated client for restful operations against an API via JSON payloads and responses.\n *\n * Internally this implementation uses createJsonRequest to actually request stuff, while the return value of this\n * method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as\n * standard methods for HTTP verbs and setup things like setting headers.\n *\n * @param {?String} [baseUrl=window.location.origin] - the base URL for all queries, based on which final request URLs will be built, adding the paths, may be absolute or relative to current origin\n * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/json\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/json\"\n * @returns {RestfulJsonClient}\n *\n * @memberof Requests:createRestfulJsonClient\n * @alias createRestfulJsonClient\n * @see createJsonRequest\n * @example\n * const client = createRestfulJsonClient('https://jsonplaceholder.typicode.com', {credentials : 'include'});\n * const postJson = await client\n * .path('/posts')\n * \t .params({\n * \t ids : [1, 2],\n * \t q : 'lorem'\n * \t })\n * \t .data({\n * \t title : 'foo',\n * \t body : 'bar',\n * \t userId : 1,\n * \t })\n * \t .post()\n * ;\n */\nexport function createRestfulJsonClient(baseUrl=null, baseOptions=null, useNative=false, strict=true){\n\tbaseUrl = orDefault(baseUrl, window.location.origin, 'str');\n\tif( !baseUrl.startsWith('//') && baseUrl.startsWith('/') ){\n\t\tbaseUrl = `${window.location.origin}${baseUrl}`;\n\t}\n\n\tconst\n\t\t__methodName__ = 'createRestfulJsonClient',\n\t\timplementation = createJsonRequest,\n\t\tcontentTypeHeader = 'Content-Type',\n\t\tcontentType = 'application/json',\n\t\tdataValidationMessage = 'data must be plain object',\n\t\toptionsValidationMessage = 'options must be plain object'\n\t;\n\n\n\tfunction flatEntries(obj){\n\t\tconst\n\t\t\tentries = Object.entries(obj),\n\t\t\tflattenedEntries = []\n\t\t;\n\n\t\tfor(const entryIndex in entries ){\n\t\t\tconst\n\t\t\t\tentryKey = entries[entryIndex][0],\n\t\t\t\tentryVal = entries[entryIndex][1],\n\t\t\t\tentryValType = getType(entryVal)\n\t\t\t;\n\n\t\t\tif( ['array', 'set'].includes(entryValType) ){\n\t\t\t\tArray.from(entryVal).forEach(val => {\n\t\t\t\t\tflattenedEntries.push([entryKey, `${val}`]);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tflattenedEntries.push([entryKey, `${entryVal}`]);\n\t\t\t}\n\t\t}\n\n\t\treturn flattenedEntries;\n\t}\n\n\n\tfunction request(client, method){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['GET', 'DELETE'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tclient.config.options.method = method;\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t})\n\t\t;\n\t}\n\n\n\tfunction requestWithPayload(client, method, data=null){\n\t\tmethod = method.toUpperCase();\n\t\tassert(['POST', 'PUT', 'PATCH'].includes(method), `${MODULE_NAME}:${__methodName__} | invalid request method \"${method}\"`);\n\n\t\tif( hasValue(data) ){\n\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | ${dataValidationMessage}`);\n\t\t}\n\n\t\tclient.config.options.method = method;\n\t\tclient.config.options.body = JSON.stringify(data ?? client.config.data);\n\t\tclient.header(contentTypeHeader, `${contentType}; charset=UTF-8`);\n\n\t\treturn implementation(client.config.url, client.config.options, useNative, strict)\n\t\t\t.execute()\n\t\t\t.finally(() => {\n\t\t\t\tdelete client.config.options.method;\n\t\t\t\tdelete client.config.options.body;\n\t\t\t\tclient.header(contentTypeHeader, null);\n\t\t\t})\n\t\t;\n\t}\n\n\n\treturn {\n\t\tconfig : {\n\t\t\turl : new URL('/', baseUrl),\n\t\t\toptions : isPlainObject(baseOptions) ? baseOptions : {},\n\t\t\tparams : new URLSearchParams(),\n\t\t\tdata : {},\n\t\t},\n\n\t\tpath(path){\n\t\t\tthis.config.url = new URL(path, baseUrl);\n\t\t\treturn this;\n\t\t},\n\n\t\toptions(options){\n\t\t\tif( hasValue(options) ){\n\t\t\t\tassert(isPlainObject(options), `${MODULE_NAME}:${__methodName__} | ${optionsValidationMessage}`);\n\t\t\t\tthis.config.options = merge(baseOptions, options);\n\t\t\t} else {\n\t\t\t\tthis.config.options = baseOptions;\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\theader(key, value){\n\t\t\tif( !hasValue(this.config.options.headers) ){\n\t\t\t\tthis.config.options.headers = {};\n\t\t\t}\n\t\t\tif( hasValue(value) ){\n\t\t\t\tthis.config.options.headers[`${key}`] = `${value}`;\n\t\t\t} else {\n\t\t\t\tdelete this.config.options.headers[`${key}`];\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tparams(params){\n\t\t\tif( hasValue(params) ){\n\t\t\t\tthis.config.params = new URLSearchParams(isPlainObject(params) ? flatEntries(params) : params);\n\t\t\t} else {\n\t\t\t\tthis.config.params = new URLSearchParams();\n\t\t\t}\n\t\t\tthis.config.url.search = this.config.params.toString();\n\t\t\treturn this;\n\t\t},\n\n\t\tdata(data){\n\t\t\tif( hasValue(data) ){\n\t\t\t\tassert(isPlainObject(data), `${MODULE_NAME}:${__methodName__} | `);\n\t\t\t\tthis.config.data = data;\n\t\t\t} else {\n\t\t\t\tthis.config.data = {};\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tget(){\n\t\t\treturn request(this, 'GET');\n\t\t},\n\n\t\tpost(data=null){\n\t\t\treturn requestWithPayload(this, 'POST', data);\n\t\t},\n\n\t\tput(data=null){\n\t\t\treturn requestWithPayload(this, 'PUT', data);\n\t\t},\n\n\t\tpatch(data=null){\n\t\t\treturn requestWithPayload(this, 'PATCH', data);\n\t\t},\n\n\t\tdelete(){\n\t\t\treturn request(this, 'DELETE');\n\t\t},\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createJsRequest\n */\n\n/**\n * @typedef JsFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef JsFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a script with a src instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a script tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef JsFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {JsFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve JavaScript.\n *\n * Usually you'll want to retrieve JavaScript to include it into a page to execute the script on the page\n * currently open, so the default mode of this method is to resolve to a directly usable script tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw JavaScript source.\n *\n * Be aware that requesting JavaScript from an unsecure source is a very big security risk. Do not load and execute\n * source from a source you do not fully trust!\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline script, but\n * you may also choose to insert a sourced script tag, loading a script on insertion and executing in asynchronously\n * in turn. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * script, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"application/javascript\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"application/javascript\"\n * @returns {JsFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createJsRequest\n * @alias createJsRequest\n * @see createFetchRequest\n * @example\n * createJsRequest('/js/test.js')\n * .execute()\n * .then(jsElement => { document.body.appendChild(jsElement); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute(null, injectTarget, 'request-2')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.textContent}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'})\n * .then(rawJs => { alert(`has been injected: \"${rawJs}\"`); })\n * ;\n * createJsRequest('/js/test.js')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4')\n * .then(jsElement => { alert(`has been injected: \"${jsElement.getAttribute('data-id')}\"`); })\n * ;\n */\nexport function createJsRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createJsRequest',\n\t\tcontentType = 'application/javascript'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, js='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? js : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? js : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tfInsertAndResolve(createNode('script', {src : url}));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for JavaScript, expecting \"application/javascript\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(js => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('script', null, js), js);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createCssRequest\n */\n\n/**\n * @typedef CssFetchResponse\n * @type {HTMLElement|String}\n */\n\n/**\n * @typedef CssFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\", \"raw\" or \"sourced-element\" (which is the special case to insert a link with a href instead of doing a real request)\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as a style/link tag, otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node\n * @param {?String} [media='all'] - define the style's media attribute here to target the output device(s), could be \"screen\" or \"print\" for example\n * @param {?Boolean} [resolveSourcedOnInsert=false] - normally sourced elements resolve on load to work with the request as far as possible, but if you want to ignore the request after insertion, you may set this parameter to \"true\", resulting in immediate resolution after insertion\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef CssFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {CssFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve Cascading Stylesheets.\n *\n * Usually you'll want to retrieve CSS to include it into a page and thereby style something on the page\n * currently open, so the default mode of this method is to resolve to a directly usable style tag, you may\n * insert into the DOM wherever you please. However, you may also specify to retrieve the raw CSS source.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target. In case you decide to insert the result directly, the default is an inline style, but\n * you may also choose to insert a sourced link tag, loading a stylesheet on insertion and adding the included styles\n * on load. This is not strictly a programmatic \"request\" anymore, but very handy. If you are inserting a sourced\n * link, the Deferred resolves on load by default (and rejects on error), thereby keeping the general idea of\n * working with a request. But you may also define a parameter on execute to force resolve immediately on insert.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/css\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/css\"\n * @returns {CssFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createCssRequest\n * @alias createCssRequest\n * @see createFetchRequest\n * @example\n * createCssRequest('/css/test.css')\n * .execute()\n * .then(cssElement => { document.head.appendChild(cssElement); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute(null, injectTarget, 'request-2')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.textContent}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-3', 'screen')\n * .then(rawCss => { alert(`has been injected: \"${rawCss}\"`); })\n * ;\n * createCssRequest('/css/test.css')\n * .execute('sourced-element', {element : injectTarget, position : 'prepend'}, 'request-4', 'screen')\n * .then(cssElement => { alert(`has been injected: \"${cssElement.getAttribute('data-id')+}\"`); })\n * ;\n */\nexport function createCssRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createCssRequest',\n\t\tcontentType = 'text/css'\n\t;\n\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, media='all', resolveSourcedOnInsert=false){\n\t\t\tconst\n\t\t\t\tsourceElementValue = 'sourced-element',\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, css='') => {\n\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\tconst\n\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t;\n\n\t\t\t\t\t\tif( !resolveSourcedOnInsert ){\n\t\t\t\t\t\t\telement.onload = () => { res.resolve((resolveTo === 'raw') ? css : element); };\n\t\t\t\t\t\t\telement.onerror = error => { res.reject(error); };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(\n\t\t\t\t\t\t(resolveTo !== sourceElementValue)\n\t\t\t\t\t\t|| ((resolveTo === sourceElementValue) && resolveSourcedOnInsert)\n\t\t\t\t\t){\n\t\t\t\t\t\tres.resolve((resolveTo === 'raw') ? css : element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tif( resolveTo === sourceElementValue ){\n\t\t\t\tconst linkAttrs = {href : url, rel : 'stylesheet'};\n\t\t\t\tif( media !== 'all' ){\n\t\t\t\t\tlinkAttrs.media = media;\n\t\t\t\t}\n\t\t\t\tfInsertAndResolve(createNode('link', linkAttrs));\n\t\t\t} else {\n\t\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t\t.then(response => {\n\t\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t\t).split(';')[0].trim();\n\n\t\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for CSS, expecting \"text/css\"`;\n\t\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn response.text();\n\t\t\t\t\t})\n\t\t\t\t\t.then(css => {\n\t\t\t\t\t\tfInsertAndResolve(createNode('style', (media !== 'all') ? {media} : null, css), css);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\tres.reject(error);\n\t\t\t\t\t})\n\t\t\t\t;\n\t\t\t}\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:createHtmlRequest\n */\n\n/**\n * @typedef HtmlFetchResponse\n * @type {HTMLElement|Array|String}\n */\n\n/**\n * @typedef HtmlFetchRequestExecuteFunction\n * @type {Function}\n * @param {?String} [resolveTo='element'] - defines what the response should resolve to, may either be \"element\" or \"raw\"\n * @param {?HTMLElement|Object} [insertTarget=null] - defines if the retrieved value should be inserted as a dom element and if so where; if this is an element, the value gets appended into that as (a) node(s), otherwise the properties below apply\n * @param {?HTMLElement} [insertTarget.element] - target element in relation to which the resolved value should be inserted into the dom\n * @param {?String} [insertTarget.position] - defines where, in relation to the target element, the resolved value will be inserted, see insertNode for more details\n * @param {?String} [dataId=null] - if you need an identifier, to find inserted elements again after they are inserted into dom, you can define an id here, which will be set as the \"data-id\" attribute on the created node(s)\n * @param {?String} [selector=null] - if you'd like to preselect something from the result, you may define a regular query selector to find matching elements in the result\n * @param {?Boolean} [selectAll=false] - usually, if a selector is defined, we select a single element, if you need to select a list, set this to true\n * @see insertNode\n * @returns {Deferred}\n */\n\n/**\n * @typedef HtmlFetchRequest\n * @type {Object}\n * @property {String} url - the request URL\n * @property {Object} options - the options with which the request has been created\n * @property {String} options.method - the request method\n * @property {?Object} options.headers - the set headers for the request\n * @property {?String} options.credentials - the credentials setting for the request\n * @property {?String} options.body - the provided request body of the request\n * @property {?Number} [options.timeout=10000] - milliseconds until the request fails due to a timeout\n * @property {HtmlFetchRequestExecuteFunction} execute - call this to execute the request\n */\n\n/**\n * This method creates a special version of a FetchRequest specifically designed to retrieve HTML content.\n *\n * Usually you'll want to retrieve HTML to include it into a page or extract information from it, so the default mode\n * of this method is to resolve to a node, you may insert into the DOM wherever you please or use stuff like a\n * querySelector on. However, you may also specify to retrieve the raw HTML source.\n *\n * Be aware, that requesting and parsing HTML from an unsecure source comes with a high risk. If you cannot fully\n * trust the source, request the HTML raw and use something like dom purify before using the result.\n *\n * If you plan on inserting the result into DOM anyway you'll like the fact that this is also directly possible, by\n * defining an insert target.\n *\n * BTW: Inserting does not automatically change the resolve value, those are separate concerns.\n *\n * @param {String} url - the complete URL to query\n * @param {?Object} [options=null] - the request options (see: createFetchRequests for details)\n * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, \"auto\" uses it only if available\n * @param {?Boolean} [strict=true] - if true, enforces \"text/html\" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning\n * @throws error in strict mode if response content type is not \"text/html\"\n * @returns {HtmlFetchRequest} use this via the \"execute\" method, which resolves to a FetchResponse or rejects with error in case of a technical request error (request is not completable)\n *\n * @memberof Requests:createHtmlRequest\n * @alias createHtmlRequest\n * @see createFetchRequest\n * @example\n * createHtmlRequest('/html/test.html')\n * .execute()\n * .then(htmlElement => { document.body.appendChild(htmlElement); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute('raw', null, 'request-1')\n * .then(rawHtml => { alert(`document has been loaded: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/html/test.html')\n * .execute(null, injectTarget, 'request-3', 'body > main > h1')\n * .then(htmlElement => { alert(`has been injected: \"${htmlElement.outerHTML}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-1.html')\n * .execute('raw', {element : injectTarget, position : 'beforebegin'}, 'request-4', 'h1 ~ p', true)\n * .then(rawHtml => { alert(`has been injected: \"${rawHtml}\"`); })\n * ;\n * createHtmlRequest('/files/html/requests-test-2.html')\n * .execute('element', {element : injectTarget, position : 'prepend'}, 'request-5', 'p', true)\n * .then(htmlElements => { alert(`has been injected: \"${htmlElements.map(e => e.outerHTML).join('')}\"`); })\n * ;\n */\nexport function createHtmlRequest(url, options=null, useNative=false, strict=true){\n\tconst\n\t\t__methodName__ = 'createHtmlRequest',\n\t\tcontentType = 'text/html'\n\t;\n\n\tif( strict ){\n\t\tif( !hasValue(options) ){\n\t\t\toptions = {};\n\t\t}\n\n\t\tif( !hasValue(options.headers) ){\n\t\t\toptions.headers = {};\n\t\t}\n\n\t\toptions.headers['Accept'] = contentType;\n\t}\n\n\treturn {\n\t\turl,\n\t\toptions,\n\t\texecute(resolveTo='element', insertTarget=null, dataId=null, selector=null, selectAll=false){\n\t\t\tconst\n\t\t\t\tres = new Deferred(),\n\t\t\t\tfInsertAndResolve = (element, html='') => {\n\t\t\t\t\tif( hasValue(element) ){\n\t\t\t\t\t\tconst elements = [].concat(element);\n\n\t\t\t\t\t\tif( dataId !== null ){\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\telement.setAttribute('data-id', `${dataId}`);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( hasValue(insertTarget) ){\n\t\t\t\t\t\t\tconst\n\t\t\t\t\t\t\t\ttarget = insertTarget.element ?? insertTarget,\n\t\t\t\t\t\t\t\tposition = insertTarget.position ?? null\n\t\t\t\t\t\t\t;\n\n\t\t\t\t\t\t\tif( ['before', 'beforebegin', 'prepend', 'afterbegin'].includes(position) ){\n\t\t\t\t\t\t\t\telements.reverse();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\telements.forEach(element => {\n\t\t\t\t\t\t\t\tif( position === null ){\n\t\t\t\t\t\t\t\t\tinsertNode(target, element);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tinsertNode(target, element, position);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tres.resolve((resolveTo === 'raw') ? html : element);\n\t\t\t\t}\n\t\t\t;\n\n\t\t\tcreateFetchRequest(url, options, useNative).execute()\n\t\t\t\t.then(response => {\n\t\t\t\t\tconst responseContentType = (\n\t\t\t\t\t\tresponse.headers.get('content-type') ?? response.headers.get('Content-Type') ?? ''\n\t\t\t\t\t).split(';')[0].trim();\n\t\t\t\t\tif( responseContentType !== contentType ){\n\t\t\t\t\t\tconst message = `${MODULE_NAME}:${__methodName__} | content-type \"${responseContentType}\" is not valid for HTML, expecting \"text/html\"`;\n\t\t\t\t\t\tif( strict ){\n\t\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twarn(message);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn response.text();\n\t\t\t\t})\n\t\t\t\t.then(html => {\n\t\t\t\t\tconst\n\t\t\t\t\t\tisWholeDocument = html.includes(' {\n\t\t\t\t\t\t\t\thtml += element.outerHTML;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfInsertAndResolve(element, html);\n\t\t\t\t})\n\t\t\t\t.catch(error => {\n\t\t\t\t\tres.reject(error);\n\t\t\t\t})\n\t\t\t;\n\n\t\t\treturn res;\n\t\t}\n\t};\n}\n\n\n\n/**\n * @namespace Requests:visitUrl\n */\n\n/**\n * This function opens a given URL, using a dynamically created iframe, thereby opening the URL as if the user\n * him- or herself navigates to the URL using a browser window. Why should we do this you ask?\n *\n * For example: In session management, you'll sometimes have the case, that you need to trigger URLs on login or logout,\n * that construct or destruct parts of the session by creating of removing cookie or other client-storage items.\n * If that domain is part of a system running on another (sub)domain, using a usual client request for this will\n * not work, since the calling context of the request will have no access to the storage scope of that domain.\n *\n * So, to allow those domains to do their tasks, triggered from a different context, we can use this method to execute\n * those webhooks with the iframe, which natively runs in the called domains scope and therefore can do all necessary\n * domain-based storage actions.\n *\n * The big downside of this is, that we cannot really handle errors well this way. So if the URL returns a 404\n * or a 500, this will actually be treated as a resolved promise, since the iframe loaded. The only case a request\n * of this kind fails, is if the request runs into a timeout. So, for really critical actions, this way of handling\n * thing should be avoided in favour of an approach, that actually includes a postMessage implementation on the other\n * domain, to verify completion on load.\n *\n * @param {String} url - the URL to query, will be the current one if left empty\n * @param {?Number} [timeout=5000] - the timeout in ms to wait for completion of the request, before rejecting the promise\n * @param {?String} [tokenValue=null] - if the URL needs to include a token, you can provide this token here, which will replace the placeholder defined in \"tokenPlaceholder\"\n * @param {?String} [tokenPlaceholder='token'] = the placeholder in the url to replace with the tokenValue, must be surrounded with curly braces in the url (\"{token}\")\n * @returns {Deferred} resolves on load of URL (with the final URL as resolution value), rejects on timeout (with a \"timeout\" error)\n *\n * @memberof Requests:visitUrl\n * @alias visitUrl\n * @example\n * visitUrl('https://some.other.domain?token={token}', 2500, 'A38')\n * .then(() => { console.log('loaded!'); })\n * ;\n * visitUrl(\n * 'https://some.other.domain?token={session_value}',\n * 5000,\n * 'A38',\n * 'session_value'\n * )\n * .then(url => { console.log(`\"${url}\" loaded!`); })\n * .catch(error => { console.log(`${error.message} - URL did not load super fast, blimey!`); })\n * ;\n */\nexport function visitUrl(url, timeout=5000, tokenValue=null, tokenPlaceholder='token'){\n\turl = orDefault(url, '', 'str');\n\ttimeout = Math.abs(orDefault(timeout, 5000, 'int'));\n\ttokenValue = orDefault(tokenValue, null, 'str');\n\ttokenPlaceholder = orDefault(tokenPlaceholder, 'token', 'str');\n\turl = hasValue(tokenValue) ? url.replaceAll(`{${tokenPlaceholder}}`, tokenValue) : url;\n\n\tconst\n\t\tdeferred = new Deferred(),\n\t\touterNode = document.createElement('div')\n\t;\n\n\touterNode.innerHTML = `\n\t\t\n\t`.trim();\n\n\tconst\n\t\tiframe = outerNode.firstChild,\n\t\tfOnLoad = () => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\twindow.clearTimeout(loadTimeout);\n\t\t\t// we need to wait a bit after load before removing the iframe,\n\t\t\t// otherwise safari considers the request cancelled :(\n\t\t\twindow.setTimeout(() => {\n\t\t\t\tdocument.body.removeChild(iframe);\n\t\t\t\tdeferred.resolve(url);\n\t\t\t}, 250);\n\t\t},\n\t\tloadTimeout = window.setTimeout(() => {\n\t\t\tiframe.removeEventListener('load', fOnLoad);\n\t\t\tdocument.body.removeChild(iframe);\n\t\t\tdeferred.reject(new Error('timeout'));\n\t\t}, timeout)\n\t;\n\n\tiframe.addEventListener('load', fOnLoad);\n\tdocument.body.appendChild(iframe);\n\n\treturn deferred;\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/strings.js b/docs/examples/lib/annex/dist/strings.js index c6233c7f..e94e9203 100644 --- a/docs/examples/lib/annex/dist/strings.js +++ b/docs/examples/lib/annex/dist/strings.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Strings */ -const MODULE_NAME="Strings";import{isA,orDefault,isNaN,hasValue,isPlainObject}from"./basic.js";const SLUGIFY_LATINMAP={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};export function replace(t,e,r){t=`${t}`,e=[].concat(e),r=[].concat(r);let o="";return e.forEach(((e,n)=>{o=r.length>1?void 0!==r[n]?r[n]:"":r[0],t=isA(String.prototype.replaceAll,"function")?t.replaceAll(`${e}`,`${o}`):t.split(`${e}`).join(`${o}`)})),t}export function truncate(t,e=30,r="..."){if(t=`${t}`,e=orDefault(e,30,"int"),(r=orDefault(r,"...","str")).length>e)throw new Error("Strings:truncate | suffix cannot be longer than maxLength");return t.length>e&&(t=`${t.slice(0,e-r.length)}${r}`),t}export function concat(t="",...e){return t=orDefault(t,"","str"),e.length>0&&isA(e[0],"array")?e[0].join(t):e.join(t)}export function format(t,...e){let r=0,o=!1,n=!1;const a=function(t,e){const r=t[e];return isA(r,"function")?r.call(t):r},l={int(t,e){e=orDefault(e,10,"int");const r=parseInt(t,e);return isNaN(r)?"":`${r}`},float(t,e){e=orDefault(e,null,"str");let r=null;if(hasValue(e)){let o=0;try{o=e.split(".")[1].length}catch(t){throw new Error("Strings:format | float precision arg malformed")}const n=Math.pow(10,o);r=Math.round(parseFloat(t)*n)/n}else r=parseFloat(t);return isNaN(r)?"":`${r}`}};return(t=`${t}`).replace(/([{}])\1|[{](.*?)(?:!(.+?))?[}]/g,(function(t,i,u){let c=null,s="",f=function(t){return t},A=null;if(i)return i;if(u.length){const t=u.split(":");if(t.length>1){u=t[0];const e=t[1].split("("),r=e[0];e.length>1&&(A=e[1].replace(")",""));try{f=l[r]}catch(t){throw new Error("Strings:format | unknown formatter")}}if(n)throw new Error("Strings:format | cannot switch from implicit to explicit numbering");o=!0,c=function(t,e){/^(\d+)([.]|$)/.test(e)||(e=`0.${e}`);let r=/(.+?)[.](.+)/.exec(e);for(;r;)t=a(t,r[1]),e=r[2],r=/(.+?)[.](.+)/.exec(e);return a(t,e)}(e,u),s=orDefault(c,"")}else{if(o)throw new Error("Strings:format | cannot switch from explicit to implicit numbering");n=!0,c=e[r],s=orDefault(c,""),r++}return f(s,A)}))}export function slugify(t,e=null){return isPlainObject(e)||(e={}),`${t}`.toLowerCase().replace(/\s+|_+/g,"-").replace(/[^\-]/g,(t=>e[t]??SLUGIFY_LATINMAP[t]??t)).replace(/[^\w\-]+/g,"").replace(/--+/g,"-").replace(/^-+/,"").replace(/-+$/,"")}export function maskForSelector(t){return`${t}`.replace(/([#;&,.+*~':"!^$\[\]()=>|\/@])/g,"\\$&")}export function maskForRegEx(t){return`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&")}export function maskForHtml(t){const e=document.createElement("textarea");return e.textContent=`${t}`,e.innerHTML}export function unmaskFromHtml(t){const e=document.createElement("textarea");return e.innerHTML=`${t}`,e.textContent} +const MODULE_NAME="Strings";import{isFunction,isArray,orDefault,isNaN,hasValue,isPlainObject}from"./basic.js";const SLUGIFY_LATINMAP={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};export function replace(t,e,r){t=`${t}`,e=[].concat(e),r=[].concat(r);let o="";return e.forEach(((e,n)=>{o=r.length>1?void 0!==r[n]?r[n]:"":r[0],t=isFunction(String.prototype.replaceAll)?t.replaceAll(`${e}`,`${o}`):t.split(`${e}`).join(`${o}`)})),t}export function truncate(t,e=30,r="..."){if(t=`${t}`,e=orDefault(e,30,"int"),(r=orDefault(r,"...","str")).length>e)throw new Error("Strings:truncate | suffix cannot be longer than maxLength");return t.length>e&&(t=`${t.slice(0,e-r.length)}${r}`),t}export function concat(t="",...e){return t=orDefault(t,"","str"),e.length>0&&isArray(e[0])?e[0].join(t):e.join(t)}export function format(t,...e){let r=0,o=!1,n=!1;const a=function(t,e){const r=t[e];return isFunction(r)?r.call(t):r},i={int(t,e){e=orDefault(e,10,"int");const r=parseInt(t,e);return isNaN(r)?"":`${r}`},float(t,e){e=orDefault(e,null,"str");let r=null;if(hasValue(e)){let o=0;try{o=e.split(".")[1].length}catch(t){throw new Error("Strings:format | float precision arg malformed")}const n=Math.pow(10,o);r=Math.round(parseFloat(t)*n)/n}else r=parseFloat(t);return isNaN(r)?"":`${r}`}};return(t=`${t}`).replace(/([{}])\1|[{](.*?)(?:!(.+?))?[}]/g,(function(t,l,u){let c=null,s="",f=function(t){return t},O=null;if(l)return l;if(u.length){const t=u.split(":");if(t.length>1){u=t[0];const e=t[1].split("("),r=e[0];e.length>1&&(O=e[1].replace(")",""));try{f=i[r]}catch(t){throw new Error("Strings:format | unknown formatter")}}if(n)throw new Error("Strings:format | cannot switch from implicit to explicit numbering");o=!0,c=function(t,e){/^(\d+)([.]|$)/.test(e)||(e=`0.${e}`);let r=/(.+?)[.](.+)/.exec(e);for(;r;)t=a(t,r[1]),e=r[2],r=/(.+?)[.](.+)/.exec(e);return a(t,e)}(e,u),s=orDefault(c,"")}else{if(o)throw new Error("Strings:format | cannot switch from explicit to implicit numbering");n=!0,c=e[r],s=orDefault(c,""),r++}return f(s,O)}))}export function slugify(t,e=null){return isPlainObject(e)||(e={}),`${t}`.toLowerCase().replace(/\s+|_+/g,"-").replace(/[^\-]/g,(t=>e[t]??SLUGIFY_LATINMAP[t]??t)).replace(/[^\w\-]+/g,"").replace(/--+/g,"-").replace(/^-+/,"").replace(/-+$/,"")}export function maskForSelector(t){return`${t}`.replace(/([#;&,.+*~':"!^$\[\]()=>|\/@])/g,"\\$&")}export function maskForRegEx(t){return`${t}`.replace(/([\-\[\]\/{}()*+?.\\^$|])/g,"\\$&")}export function maskForHtml(t){const e=document.createElement("textarea");return e.textContent=`${t}`,e.innerHTML}export function unmaskFromHtml(t){const e=document.createElement("textarea");return e.innerHTML=`${t}`,e.textContent} //# sourceMappingURL=strings.js.map diff --git a/docs/examples/lib/annex/dist/strings.js.map b/docs/examples/lib/annex/dist/strings.js.map index ac5a8523..a2b46593 100644 --- a/docs/examples/lib/annex/dist/strings.js.map +++ b/docs/examples/lib/annex/dist/strings.js.map @@ -1 +1 @@ -{"version":3,"file":"strings.js","names":["MODULE_NAME","isA","orDefault","isNaN","hasValue","isPlainObject","SLUGIFY_LATINMAP","replace","subject","search","concat","tmp","forEach","searchTerm","index","length","undefined","String","prototype","replaceAll","split","join","truncate","maxLength","suffix","Error","slice","glue","strings","format","template","replacements","idx","explicit","implicit","fResolve","object","key","value","call","formatters","int","radix","res","parseInt","float","precision","ex","power","Math","pow","round","parseFloat","match","literal","ref","formatter","formatterArg","keyParts","formatterParts","formatterName","test","exec","fLookup","slugify","text","additionalMap","toLowerCase","char","maskForSelector","str","maskForRegEx","maskForHtml","escape","document","createElement","textContent","innerHTML","unmaskFromHtml","html"],"sources":["strings.js"],"mappings":";;;AAQA,MAAMA,YAAc,iBAMZC,IAAKC,UAAWC,MAAOC,SAAUC,kBAAoB,aAM7D,MAAMC,iBAAmB,CACxB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IACrG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAC5G,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAC3G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,YA8B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","sourcesContent":["/*!\n * Module Strings\n */\n\n/**\n * @namespace Strings\n */\n\nconst MODULE_NAME = 'Strings';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {isA, orDefault, isNaN, hasValue, isPlainObject} from './basic.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst SLUGIFY_LATINMAP = {\n\t'Á':'A','Ă':'A','Ắ':'A','Ặ':'A','Ằ':'A','Ẳ':'A','Ẵ':'A','Ǎ':'A','Â':'A','Ấ':'A','Ậ':'A','Ầ':'A','Ẩ':'A','Ẫ':'A',\n\t'Ä':'A','Ǟ':'A','Ȧ':'A','Ǡ':'A','Ạ':'A','Ȁ':'A','À':'A','Ả':'A','Ȃ':'A','Ā':'A','Ą':'A','Å':'A','Ǻ':'A','Ḁ':'A',\n\t'Ⱥ':'A','Ã':'A','Ꜳ':'AA','Æ':'AE','Ǽ':'AE','Ǣ':'AE','Ꜵ':'AO','Ꜷ':'AU','Ꜹ':'AV','Ꜻ':'AV','Ꜽ':'AY','Ḃ':'B',\n\t'Ḅ':'B','Ɓ':'B','Ḇ':'B','Ƀ':'B','Ƃ':'B','Ć':'C','Č':'C','Ç':'C','Ḉ':'C','Ĉ':'C','Ċ':'C','Ƈ':'C','Ȼ':'C','Ď':'D',\n\t'Ḑ':'D','Ḓ':'D','Ḋ':'D','Ḍ':'D','Ɗ':'D','Ḏ':'D','Dz':'D','Dž':'D','Đ':'D','Ƌ':'D','DZ':'DZ','DŽ':'DZ','É':'E','Ĕ':'E',\n\t'Ě':'E','Ȩ':'E','Ḝ':'E','Ê':'E','Ế':'E','Ệ':'E','Ề':'E','Ể':'E','Ễ':'E','Ḙ':'E','Ë':'E','Ė':'E','Ẹ':'E','Ȅ':'E',\n\t'È':'E','Ẻ':'E','Ȇ':'E','Ē':'E','Ḗ':'E','Ḕ':'E','Ę':'E','Ɇ':'E','Ẽ':'E','Ḛ':'E','Ꝫ':'ET','Ḟ':'F','Ƒ':'F','Ǵ':'G',\n\t'Ğ':'G','Ǧ':'G','Ģ':'G','Ĝ':'G','Ġ':'G','Ɠ':'G','Ḡ':'G','Ǥ':'G','Ḫ':'H','Ȟ':'H','Ḩ':'H','Ĥ':'H','Ⱨ':'H','Ḧ':'H',\n\t'Ḣ':'H','Ḥ':'H','Ħ':'H','Í':'I','Ĭ':'I','Ǐ':'I','Î':'I','Ï':'I','Ḯ':'I','İ':'I','Ị':'I','Ȉ':'I','Ì':'I','Ỉ':'I',\n\t'Ȋ':'I','Ī':'I','Į':'I','Ɨ':'I','Ĩ':'I','Ḭ':'I','Ꝺ':'D','Ꝼ':'F','Ᵹ':'G','Ꞃ':'R','Ꞅ':'S','Ꞇ':'T','Ꝭ':'IS','Ĵ':'J',\n\t'Ɉ':'J','Ḱ':'K','Ǩ':'K','Ķ':'K','Ⱪ':'K','Ꝃ':'K','Ḳ':'K','Ƙ':'K','Ḵ':'K','Ꝁ':'K','Ꝅ':'K','Ĺ':'L','Ƚ':'L','Ľ':'L',\n\t'Ļ':'L','Ḽ':'L','Ḷ':'L','Ḹ':'L','Ⱡ':'L','Ꝉ':'L','Ḻ':'L','Ŀ':'L','Ɫ':'L','Lj':'L','Ł':'L','LJ':'LJ','Ḿ':'M','Ṁ':'M',\n\t'Ṃ':'M','Ɱ':'M','Ń':'N','Ň':'N','Ņ':'N','Ṋ':'N','Ṅ':'N','Ṇ':'N','Ǹ':'N','Ɲ':'N','Ṉ':'N','Ƞ':'N','Nj':'N','Ñ':'N',\n\t'NJ':'NJ','Ó':'O','Ŏ':'O','Ǒ':'O','Ô':'O','Ố':'O','Ộ':'O','Ồ':'O','Ổ':'O','Ỗ':'O','Ö':'O','Ȫ':'O','Ȯ':'O','Ȱ':'O',\n\t'Ọ':'O','Ő':'O','Ȍ':'O','Ò':'O','Ỏ':'O','Ơ':'O','Ớ':'O','Ợ':'O','Ờ':'O','Ở':'O','Ỡ':'O','Ȏ':'O','Ꝋ':'O','Ꝍ':'O',\n\t'Ō':'O','Ṓ':'O','Ṑ':'O','Ɵ':'O','Ǫ':'O','Ǭ':'O','Ø':'O','Ǿ':'O','Õ':'O','Ṍ':'O','Ṏ':'O','Ȭ':'O','Ƣ':'OI','Ꝏ':'OO',\n\t'Ɛ':'E','Ɔ':'O','Ȣ':'OU','Ṕ':'P','Ṗ':'P','Ꝓ':'P','Ƥ':'P','Ꝕ':'P','Ᵽ':'P','Ꝑ':'P','Ꝙ':'Q','Ꝗ':'Q','Ŕ':'R','Ř':'R',\n\t'Ŗ':'R','Ṙ':'R','Ṛ':'R','Ṝ':'R','Ȑ':'R','Ȓ':'R','Ṟ':'R','Ɍ':'R','Ɽ':'R','Ꜿ':'C','Ǝ':'E','Ś':'S','Ṥ':'S','Š':'S',\n\t'Ṧ':'S','Ş':'S','Ŝ':'S','Ș':'S','Ṡ':'S','Ṣ':'S','Ṩ':'S','ẞ':'SS','Ť':'T','Ţ':'T','Ṱ':'T','Ț':'T','Ⱦ':'T','Ṫ':'T',\n\t'Ṭ':'T','Ƭ':'T','Ṯ':'T','Ʈ':'T','Ŧ':'T','Ɐ':'A','Ꞁ':'L','Ɯ':'M','Ʌ':'V','Ꜩ':'TZ','Ú':'U','Ŭ':'U','Ǔ':'U','Û':'U',\n\t'Ṷ':'U','Ü':'U','Ǘ':'U','Ǚ':'U','Ǜ':'U','Ǖ':'U','Ṳ':'U','Ụ':'U','Ű':'U','Ȕ':'U','Ù':'U','Ủ':'U','Ư':'U','Ứ':'U',\n\t'Ự':'U','Ừ':'U','Ử':'U','Ữ':'U','Ȗ':'U','Ū':'U','Ṻ':'U','Ų':'U','Ů':'U','Ũ':'U','Ṹ':'U','Ṵ':'U','Ꝟ':'V','Ṿ':'V',\n\t'Ʋ':'V','Ṽ':'V','Ꝡ':'VY','Ẃ':'W','Ŵ':'W','Ẅ':'W','Ẇ':'W','Ẉ':'W','Ẁ':'W','Ⱳ':'W','Ẍ':'X','Ẋ':'X','Ý':'Y','Ŷ':'Y',\n\t'Ÿ':'Y','Ẏ':'Y','Ỵ':'Y','Ỳ':'Y','Ƴ':'Y','Ỷ':'Y','Ỿ':'Y','Ȳ':'Y','Ɏ':'Y','Ỹ':'Y','Ź':'Z','Ž':'Z','Ẑ':'Z','Ⱬ':'Z',\n\t'Ż':'Z','Ẓ':'Z','Ȥ':'Z','Ẕ':'Z','Ƶ':'Z','IJ':'IJ','Œ':'OE','ᴀ':'A','ᴁ':'AE','ʙ':'B','ᴃ':'B','ᴄ':'C','ᴅ':'D','ᴇ':'E',\n\t'ꜰ':'F','ɢ':'G','ʛ':'G','ʜ':'H','ɪ':'I','ʁ':'R','ᴊ':'J','ᴋ':'K','ʟ':'L','ᴌ':'L','ᴍ':'M','ɴ':'N','ᴏ':'O','ɶ':'OE',\n\t'ᴐ':'O','ᴕ':'OU','ᴘ':'P','ʀ':'R','ᴎ':'N','ᴙ':'R','ꜱ':'S','ᴛ':'T','ⱻ':'E','ᴚ':'R','ᴜ':'U','ᴠ':'V','ᴡ':'W','ʏ':'Y',\n\t'ᴢ':'Z','á':'a','ă':'a','ắ':'a','ặ':'a','ằ':'a','ẳ':'a','ẵ':'a','ǎ':'a','â':'a','ấ':'a','ậ':'a','ầ':'a','ẩ':'a',\n\t'ẫ':'a','ä':'a','ǟ':'a','ȧ':'a','ǡ':'a','ạ':'a','ȁ':'a','à':'a','ả':'a','ȃ':'a','ā':'a','ą':'a','ᶏ':'a','ẚ':'a',\n\t'å':'a','ǻ':'a','ḁ':'a','ⱥ':'a','ã':'a','ꜳ':'aa','æ':'ae','ǽ':'ae','ǣ':'ae','ꜵ':'ao','ꜷ':'au','ꜹ':'av','ꜻ':'av',\n\t'ꜽ':'ay','ḃ':'b','ḅ':'b','ɓ':'b','ḇ':'b','ᵬ':'b','ᶀ':'b','ƀ':'b','ƃ':'b','ɵ':'o','ć':'c','č':'c','ç':'c','ḉ':'c',\n\t'ĉ':'c','ɕ':'c','ċ':'c','ƈ':'c','ȼ':'c','ď':'d','ḑ':'d','ḓ':'d','ȡ':'d','ḋ':'d','ḍ':'d','ɗ':'d','ᶑ':'d','ḏ':'d',\n\t'ᵭ':'d','ᶁ':'d','đ':'d','ɖ':'d','ƌ':'d','ı':'i','ȷ':'j','ɟ':'j','ʄ':'j','dz':'dz','dž':'dz','é':'e','ĕ':'e','ě':'e',\n\t'ȩ':'e','ḝ':'e','ê':'e','ế':'e','ệ':'e','ề':'e','ể':'e','ễ':'e','ḙ':'e','ë':'e','ė':'e','ẹ':'e','ȅ':'e','è':'e',\n\t'ẻ':'e','ȇ':'e','ē':'e','ḗ':'e','ḕ':'e','ⱸ':'e','ę':'e','ᶒ':'e','ɇ':'e','ẽ':'e','ḛ':'e','ꝫ':'et','ḟ':'f','ƒ':'f',\n\t'ᵮ':'f','ᶂ':'f','ǵ':'g','ğ':'g','ǧ':'g','ģ':'g','ĝ':'g','ġ':'g','ɠ':'g','ḡ':'g','ᶃ':'g','ǥ':'g','ḫ':'h','ȟ':'h',\n\t'ḩ':'h','ĥ':'h','ⱨ':'h','ḧ':'h','ḣ':'h','ḥ':'h','ɦ':'h','ẖ':'h','ħ':'h','ƕ':'hv','í':'i','ĭ':'i','ǐ':'i','î':'i',\n\t'ï':'i','ḯ':'i','ị':'i','ȉ':'i','ì':'i','ỉ':'i','ȋ':'i','ī':'i','į':'i','ᶖ':'i','ɨ':'i','ĩ':'i','ḭ':'i','ꝺ':'d',\n\t'ꝼ':'f','ᵹ':'g','ꞃ':'r','ꞅ':'s','ꞇ':'t','ꝭ':'is','ǰ':'j','ĵ':'j','ʝ':'j','ɉ':'j','ḱ':'k','ǩ':'k','ķ':'k','ⱪ':'k',\n\t'ꝃ':'k','ḳ':'k','ƙ':'k','ḵ':'k','ᶄ':'k','ꝁ':'k','ꝅ':'k','ĺ':'l','ƚ':'l','ɬ':'l','ľ':'l','ļ':'l','ḽ':'l','ȴ':'l',\n\t'ḷ':'l','ḹ':'l','ⱡ':'l','ꝉ':'l','ḻ':'l','ŀ':'l','ɫ':'l','ᶅ':'l','ɭ':'l','ł':'l','lj':'lj','ſ':'s','ẜ':'s','ẛ':'s',\n\t'ẝ':'s','ḿ':'m','ṁ':'m','ṃ':'m','ɱ':'m','ᵯ':'m','ᶆ':'m','ń':'n','ň':'n','ņ':'n','ṋ':'n','ȵ':'n','ṅ':'n','ṇ':'n',\n\t'ǹ':'n','ɲ':'n','ṉ':'n','ƞ':'n','ᵰ':'n','ᶇ':'n','ɳ':'n','ñ':'n','nj':'nj','ó':'o','ŏ':'o','ǒ':'o','ô':'o','ố':'o',\n\t'ộ':'o','ồ':'o','ổ':'o','ỗ':'o','ö':'o','ȫ':'o','ȯ':'o','ȱ':'o','ọ':'o','ő':'o','ȍ':'o','ò':'o','ỏ':'o','ơ':'o',\n\t'ớ':'o','ợ':'o','ờ':'o','ở':'o','ỡ':'o','ȏ':'o','ꝋ':'o','ꝍ':'o','ⱺ':'o','ō':'o','ṓ':'o','ṑ':'o','ǫ':'o','ǭ':'o',\n\t'ø':'o','ǿ':'o','õ':'o','ṍ':'o','ṏ':'o','ȭ':'o','ƣ':'oi','ꝏ':'oo','ɛ':'e','ᶓ':'e','ɔ':'o','ᶗ':'o','ȣ':'ou','ṕ':'p',\n\t'ṗ':'p','ꝓ':'p','ƥ':'p','ᵱ':'p','ᶈ':'p','ꝕ':'p','ᵽ':'p','ꝑ':'p','ꝙ':'q','ʠ':'q','ɋ':'q','ꝗ':'q','ŕ':'r','ř':'r',\n\t'ŗ':'r','ṙ':'r','ṛ':'r','ṝ':'r','ȑ':'r','ɾ':'r','ᵳ':'r','ȓ':'r','ṟ':'r','ɼ':'r','ᵲ':'r','ᶉ':'r','ɍ':'r','ɽ':'r',\n\t'ↄ':'c','ꜿ':'c','ɘ':'e','ɿ':'r','ś':'s','ṥ':'s','š':'s','ṧ':'s','ş':'s','ŝ':'s','ș':'s','ṡ':'s','ṣ':'s','ṩ':'s',\n\t'ʂ':'s','ᵴ':'s','ᶊ':'s','ȿ':'s','ɡ':'g','ß':'ss','ᴑ':'o','ᴓ':'o','ᴝ':'u','ť':'t','ţ':'t','ṱ':'t','ț':'t','ȶ':'t',\n\t'ẗ':'t','ⱦ':'t','ṫ':'t','ṭ':'t','ƭ':'t','ṯ':'t','ᵵ':'t','ƫ':'t','ʈ':'t','ŧ':'t','ᵺ':'th','ɐ':'a','ᴂ':'ae','ǝ':'e',\n\t'ᵷ':'g','ɥ':'h','ʮ':'h','ʯ':'h','ᴉ':'i','ʞ':'k','ꞁ':'l','ɯ':'m','ɰ':'m','ᴔ':'oe','ɹ':'r','ɻ':'r','ɺ':'r','ⱹ':'r',\n\t'ʇ':'t','ʌ':'v','ʍ':'w','ʎ':'y','ꜩ':'tz','ú':'u','ŭ':'u','ǔ':'u','û':'u','ṷ':'u','ü':'u','ǘ':'u','ǚ':'u','ǜ':'u',\n\t'ǖ':'u','ṳ':'u','ụ':'u','ű':'u','ȕ':'u','ù':'u','ủ':'u','ư':'u','ứ':'u','ự':'u','ừ':'u','ử':'u','ữ':'u','ȗ':'u',\n\t'ū':'u','ṻ':'u','ų':'u','ᶙ':'u','ů':'u','ũ':'u','ṹ':'u','ṵ':'u','ᵫ':'ue','ꝸ':'um','ⱴ':'v','ꝟ':'v','ṿ':'v','ʋ':'v',\n\t'ᶌ':'v','ⱱ':'v','ṽ':'v','ꝡ':'vy','ẃ':'w','ŵ':'w','ẅ':'w','ẇ':'w','ẉ':'w','ẁ':'w','ⱳ':'w','ẘ':'w','ẍ':'x','ẋ':'x',\n\t'ᶍ':'x','ý':'y','ŷ':'y','ÿ':'y','ẏ':'y','ỵ':'y','ỳ':'y','ƴ':'y','ỷ':'y','ỿ':'y','ȳ':'y','ẙ':'y','ɏ':'y','ỹ':'y',\n\t'ź':'z','ž':'z','ẑ':'z','ʑ':'z','ⱬ':'z','ż':'z','ẓ':'z','ȥ':'z','ẕ':'z','ᵶ':'z','ᶎ':'z','ʐ':'z','ƶ':'z','ɀ':'z',\n\t'ff':'ff','ffi':'ffi','ffl':'ffl','fi':'fi','fl':'fl','ij':'ij','œ':'oe','st':'st','ₐ':'a','ₑ':'e','ᵢ':'i','ⱼ':'j','ₒ':'o',\n\t'ᵣ':'r','ᵤ':'u','ᵥ':'v','ₓ':'x'\n};\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Strings:replace\n */\n\n/**\n * Offers similar functionality to PHP's str_replace or ES2021's replaceAll and avoids RegExps for this task.\n * Replaces occurrences of search in subject with replace. search and replace may be arrays.\n * If search is an array and replace is a string, all phrases in the array will be replaced with one string.\n * If replace is an array itself, phrases and replacements are matched by index.\n * Missing replacements are treated as an empty string (for example: if your array lengths do not match).\n *\n * Uses String.prototype.replaceAll internally, if available.\n *\n * @param {String} subject - the string to replace in\n * @param {(String|String[])} search - the string(s) to replace\n * @param {String|String[]} replace - the string(s) to replace the search string(s)\n * @returns {String} the modified string\n *\n * @memberof Strings:replace\n * @alias replace\n * @example\n * const sanitizedString = replace([':', '#', '-'], '_', exampleString);\n */\nexport function replace(subject, search, replace){\n\tsubject = `${subject}`;\n\tsearch = [].concat(search);\n\treplace = [].concat(replace);\n\n\tlet tmp = '';\n\n\tsearch.forEach((searchTerm, index) => {\n\t\ttmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0];\n\n\t\tif( isA(String.prototype.replaceAll, 'function') ){\n\t\t\tsubject = subject.replaceAll(`${searchTerm}`, `${tmp}`);\n\t\t} else {\n\t\t\tsubject = subject.split(`${searchTerm}`).join(`${tmp}`);\n\t\t}\n\t});\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:truncate\n */\n\n/**\n * Truncates a given string after a certain number of characters to enforce length restrictions.\n *\n * @param {String} subject - the string to check and truncate\n * @param {?Number} [maxLength=30] - the maximum allowed character length for the string\n * @param {?String} [suffix='...'] - the trailing string to end a truncated string with\n * @throws error if suffix length is bigger than defined maxLength\n * @returns {String} the (truncated) subject\n *\n * @memberof Strings:truncate\n * @alias truncate\n * @example\n * const truncatedString = truncate(string, 10, '...');\n */\nexport function truncate(subject, maxLength=30, suffix='...'){\n\tsubject = `${subject}`;\n\tmaxLength = orDefault(maxLength, 30, 'int');\n\tsuffix = orDefault(suffix, '...', 'str');\n\n\tif( suffix.length > maxLength ){\n\t\tthrow new Error(`${MODULE_NAME}:truncate | suffix cannot be longer than maxLength`);\n\t}\n\n\tif( subject.length > maxLength ){\n\t\tsubject = `${subject.slice(0, maxLength - suffix.length)}${suffix}`;\n\t}\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:concat\n */\n\n/**\n * Simply concatenates strings with a glue part using array.join in a handy notation.\n * You can also provide arguments to glue as a prepared array as the second parameter,\n * in that case other parameters will be ignored.\n *\n * @param {?String} [glue=''] - the separator to use between single strings\n * @param {?String[]} strings - list of strings to concatenate, either comma-separated or as single array\n * @returns {String} the concatenated string\n *\n * @memberof Strings:concat\n * @alias concat\n * @example\n * const finalCountdown = concat(' ... ', 10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!');\n * const finalCountdown = concat(' ... ', [10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!']);\n */\nexport function concat(glue='', ...strings){\n\tglue = orDefault(glue, '', 'str');\n\n\tif( (strings.length > 0) && isA(strings[0], 'array') ){\n\t\treturn strings[0].join(glue);\n\t} else {\n\t\treturn strings.join(glue);\n\t}\n}\n\n\n\n/**\n * @namespace Strings:format\n */\n\n/**\n * This is a pythonesque string format implementation.\n * Apply formatted values to a string template, in which replacements are marked with curly braces.\n *\n * Display literal curly brace with {{ and }}.\n *\n * Unknown keys/indexes will be ignored.\n *\n * This solution is adapted from:\n * https://github.com/davidchambers/string-format\n *\n * @param {String} template -\n * @param {(String[]|Object)} replacements - arguments to insert into template, either as a dictionary, an array or a parameter sequence\n * @throws general exception on syntax errors\n * @returns {String} the formatted string\n *\n * @memberof Strings:format\n * @alias format\n * @example\n * format('An elephant is {times:float(0.00)} times smarter than a {animal}', {times : 5.5555, animal : 'lion'})\n * => 'An elephant is 5.56 times smarter than a lion'\n * format('{0}{0}{0} ... {{BATMAN!}}', 'Nana')\n * => 'NanaNanaNana ... {BATMAN!}'\n * format('{} {} {} starts the alphabet.', 'A', 'B', 'C')\n * => 'A B C starts the alphabet.'\n * format('{0:int}, {1:int}, {2:int}: details are for wankers', '1a', 2.222, 3)\n * => '1, 2, 3: details are for wankers'\n */\nexport function format(template, ...replacements){\n\ttemplate = `${template}`;\n\n\tlet\n\t\tidx = 0,\n\t\texplicit = false,\n\t\timplicit = false\n\t;\n\n\tconst fResolve = function(object, key){\n\t\tconst value = object[key];\n\n\t\tif( isA(value, 'function') ){\n\t\t\treturn value.call(object);\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t};\n\n\tconst fLookup = function(object, key){\n\t\tif( !/^(\\d+)([.]|$)/.test(key) ){\n\t\t\tkey = `0.${key}`;\n\t\t}\n\n\t\tlet match = /(.+?)[.](.+)/.exec(key);\n\t\twhile( match ){\n\t\t\tobject = fResolve(object, match[1]);\n\t\t\tkey = match[2];\n\t\t\tmatch = /(.+?)[.](.+)/.exec(key);\n\t\t}\n\n\t\treturn fResolve(object, key);\n\t};\n\n\tconst formatters = {\n\t\tint(value, radix){\n\t\t\tradix = orDefault(radix, 10, 'int');\n\t\t\tconst res = parseInt(value, radix);\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t},\n\t\tfloat(value, format){\n\t\t\tformat = orDefault(format, null, 'str');\n\n\t\t\tlet res = null;\n\n\t\t\tif( hasValue(format) ){\n\t\t\t\tlet precision = 0;\n\n\t\t\t\ttry {\n\t\t\t\t\tprecision = format.split('.')[1].length;\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | float precision arg malformed`);\n\t\t\t\t}\n\n\t\t\t\tconst power = Math.pow(10, precision);\n\n\t\t\t\tres = Math.round(parseFloat(value) * power) / power;\n\t\t\t} else {\n\t\t\t\tres = parseFloat(value);\n\t\t\t}\n\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t}\n\t};\n\n\treturn template.replace(/([{}])\\1|[{](.*?)(?:!(.+?))?[}]/g, function(match, literal, key){\n\t\tlet\n\t\t\tref = null,\n\t\t\tvalue = '',\n\t\t\tformatter = function(value){ return value; },\n\t\t\tformatterArg = null\n\t\t;\n\n\t\tif( literal ){\n\t\t\treturn literal;\n\t\t}\n\n\t\tif( key.length ){\n\t\t\tconst keyParts = key.split(':');\n\n\t\t\tif( keyParts.length > 1 ){\n\t\t\t\tkey = keyParts[0];\n\n\t\t\t\tconst\n\t\t\t\t\tformatterParts = keyParts[1].split('('),\n\t\t\t\t\tformatterName = formatterParts[0]\n\t\t\t\t;\n\n\t\t\t\tif( formatterParts.length > 1 ){\n\t\t\t\t\tformatterArg = formatterParts[1].replace(')', '');\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tformatter = formatters[formatterName];\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | unknown formatter`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( implicit ){\n\t\t\t\tthrow new Error(`${MODULE_NAME}:format | cannot switch from implicit to explicit numbering`);\n\t\t\t} else {\n\t\t\t\texplicit = true;\n\t\t\t}\n\n\t\t\tref = fLookup(replacements, key);\n\t\t\tvalue = orDefault(ref, '');\n\t\t} else {\n\t\t\tif( explicit ){\n\t\t\t\tthrow new Error (`${MODULE_NAME}:format | cannot switch from explicit to implicit numbering`);\n\t\t\t} else {\n\t\t\t\timplicit = true;\n\t\t\t}\n\n\t\t\tref = replacements[idx];\n\t\t\tvalue = orDefault(ref, '');\n\t\t\tidx++;\n\t\t}\n\n\t\treturn formatter(value, formatterArg);\n\t});\n}\n\n\n\n/**\n * @namespace Strings:slugify\n */\n\n/**\n * Slugifies a text for use in a URL or id/class/attribute.\n * Transforms accented characters to non-accented ones.\n * Throws out everything except basic A-Z characters and numbers after replacements have taken place.\n * Provide own replacements, supplementing or overriding the default replacement map to cover special cases\n * (will take precedence over the default map).\n *\n * @param {String} text - the text to slugify\n * @param {String?} [additionalMap=null] - optional character map to supplement/override the default map, having the form {'[search character]' : '[replacement]', ...}\n * @returns {String} the slugified string\n *\n * @memberof Strings:slugify\n * @alias slugify\n * @example\n * slugify('This is a cömplicated ßtring for URLs!')\n * => 'this-is-a-complicated-sstring-for-urls'\n */\nexport function slugify(text, additionalMap=null){\n\tif( !isPlainObject(additionalMap) ){\n\t\tadditionalMap = {};\n\t}\n\n\treturn `${text}`.toLowerCase()\n\t\t.replace(/\\s+|_+/g, '-') // replace spaces and underscores with \"-\"\n\t\t.replace(\n\t\t\t/[^\\-]/g, // replace accented chars with plain ones via map and/or apply additionalMap\n\t\t\tchar => additionalMap[char] ?? SLUGIFY_LATINMAP[char] ?? char\n\t\t)\n\t\t.replace(/[^\\w\\-]+/g, '') // remove all non-word, non-dash chars\n\t\t.replace(/--+/g, '-') // replace multiple \"-\" with single \"-\"\n\t\t.replace(/^-+/, '') // trim \"-\" from start of text\n\t\t.replace(/-+$/, '') // trim \"-\" from end of text\n\t;\n}\n\n\n\n/**\n * @namespace Strings:maskForSelector\n */\n\n/**\n * Masks all selector-special-characters, to allow selecting elements with special characters in selector using\n * querySelector and querySelectorAll (also works for jQuery and Cash).\n *\n * @param {String} str - the string to mask for use in a selector\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForSelector\n * @alias maskForSelector\n * @example\n * document.querySelector(`#element_${maskForSelector(elementName)}`).classList.remove('test');\n */\nexport function maskForSelector(str){\n\treturn `${str}`.replace(/([#;&,.+*~':\"!^$\\[\\]()=>|\\/@])/g, '\\\\$&');\n}\n\n\n\n/**\n * @namespace Strings:maskForRegEx\n */\n\n/**\n * Masks all regex special characters, to test or match a string using a regex, that contains\n * characters used in regexes themselves.\n *\n * @param {String} str - the string to mask for use in a regexp\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForRegEx\n * @alias maskForRegEx\n * @example\n * if( (new RegExp(`^${maskForRegEx(arbitraryString)}$')).test('abc') ){\n * alert('are identical!');\n * }\n */\nexport function maskForRegEx(str){\n\treturn `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n}\n\n\n\n/**\n * @namespace Strings:maskForHtml\n */\n\n/**\n * Masks a string possibly containing reserved HTML chars for HTML output as is\n * (so a < actually reads on the page).\n *\n * Only replaces critical chars like <>& with entities, but\n * keeps non-critical unicode chars like »/.\n *\n * @param {String} text - the string to mask for use in HTML\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForHtml\n * @alias maskForHtml\n * @see unmaskFromHtml\n * @example\n * maskForHtml('&;üäöÜÄÖß– »')\n * => '</>&;üäöÜÄÖß– »'\n */\nexport function maskForHtml(text){\n\tconst escape = document.createElement('textarea');\n\tescape.textContent = `${text}`;\n\treturn escape.innerHTML;\n}\n\n\n\n/**\n * @namespace Strings:unmaskFromHtml\n */\n\n/**\n * Replaces entities in a html-masked string with the vanilla characters\n * thereby returning a real HTML string, which could, for example, be used\n * to construct new elements with tag markup.\n *\n * @param {String} html - the string to unmask entities in\n * @returns {String} the unmasked string\n *\n * @memberof Strings:unmaskFromHtml\n * @alias unmaskFromHtml\n * @see maskForHtml\n * @example\n * unmaskFromHtml('</>&;üäöÜÄÖß– »')\n * => '&;üäöÜÄÖß– »'\n */\nexport function unmaskFromHtml(html){\n\tconst escape = document.createElement('textarea');\n\tescape.innerHTML = `${html}`;\n\treturn escape.textContent;\n}\n"]} \ No newline at end of file +{"version":3,"file":"strings.js","names":["MODULE_NAME","isFunction","isArray","orDefault","isNaN","hasValue","isPlainObject","SLUGIFY_LATINMAP","replace","subject","search","concat","tmp","forEach","searchTerm","index","length","undefined","String","prototype","replaceAll","split","join","truncate","maxLength","suffix","Error","slice","glue","strings","format","template","replacements","idx","explicit","implicit","fResolve","object","key","value","call","formatters","int","radix","res","parseInt","float","precision","ex","power","Math","pow","round","parseFloat","match","literal","ref","formatter","formatterArg","keyParts","formatterParts","formatterName","test","exec","fLookup","slugify","text","additionalMap","toLowerCase","char","maskForSelector","str","maskForRegEx","maskForHtml","escape","document","createElement","textContent","innerHTML","unmaskFromHtml","html"],"sources":["strings.js"],"mappings":";;;AAQA,MAAMA,YAAc,iBAMZC,WAAYC,QAASC,UAAWC,MAAOC,SAAUC,kBAAoB,aAM7E,MAAMC,iBAAmB,CACxB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IACrG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAC5G,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAC3G,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAC/G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC7G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC5G,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAC9G,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAA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","sourcesContent":["/*!\n * Module Strings\n */\n\n/**\n * @namespace Strings\n */\n\nconst MODULE_NAME = 'Strings';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {isFunction, isArray, orDefault, isNaN, hasValue, isPlainObject} from './basic.js';\n\n\n\n//###[ DATA ]###########################################################################################################\n\nconst SLUGIFY_LATINMAP = {\n\t'Á':'A','Ă':'A','Ắ':'A','Ặ':'A','Ằ':'A','Ẳ':'A','Ẵ':'A','Ǎ':'A','Â':'A','Ấ':'A','Ậ':'A','Ầ':'A','Ẩ':'A','Ẫ':'A',\n\t'Ä':'A','Ǟ':'A','Ȧ':'A','Ǡ':'A','Ạ':'A','Ȁ':'A','À':'A','Ả':'A','Ȃ':'A','Ā':'A','Ą':'A','Å':'A','Ǻ':'A','Ḁ':'A',\n\t'Ⱥ':'A','Ã':'A','Ꜳ':'AA','Æ':'AE','Ǽ':'AE','Ǣ':'AE','Ꜵ':'AO','Ꜷ':'AU','Ꜹ':'AV','Ꜻ':'AV','Ꜽ':'AY','Ḃ':'B',\n\t'Ḅ':'B','Ɓ':'B','Ḇ':'B','Ƀ':'B','Ƃ':'B','Ć':'C','Č':'C','Ç':'C','Ḉ':'C','Ĉ':'C','Ċ':'C','Ƈ':'C','Ȼ':'C','Ď':'D',\n\t'Ḑ':'D','Ḓ':'D','Ḋ':'D','Ḍ':'D','Ɗ':'D','Ḏ':'D','Dz':'D','Dž':'D','Đ':'D','Ƌ':'D','DZ':'DZ','DŽ':'DZ','É':'E','Ĕ':'E',\n\t'Ě':'E','Ȩ':'E','Ḝ':'E','Ê':'E','Ế':'E','Ệ':'E','Ề':'E','Ể':'E','Ễ':'E','Ḙ':'E','Ë':'E','Ė':'E','Ẹ':'E','Ȅ':'E',\n\t'È':'E','Ẻ':'E','Ȇ':'E','Ē':'E','Ḗ':'E','Ḕ':'E','Ę':'E','Ɇ':'E','Ẽ':'E','Ḛ':'E','Ꝫ':'ET','Ḟ':'F','Ƒ':'F','Ǵ':'G',\n\t'Ğ':'G','Ǧ':'G','Ģ':'G','Ĝ':'G','Ġ':'G','Ɠ':'G','Ḡ':'G','Ǥ':'G','Ḫ':'H','Ȟ':'H','Ḩ':'H','Ĥ':'H','Ⱨ':'H','Ḧ':'H',\n\t'Ḣ':'H','Ḥ':'H','Ħ':'H','Í':'I','Ĭ':'I','Ǐ':'I','Î':'I','Ï':'I','Ḯ':'I','İ':'I','Ị':'I','Ȉ':'I','Ì':'I','Ỉ':'I',\n\t'Ȋ':'I','Ī':'I','Į':'I','Ɨ':'I','Ĩ':'I','Ḭ':'I','Ꝺ':'D','Ꝼ':'F','Ᵹ':'G','Ꞃ':'R','Ꞅ':'S','Ꞇ':'T','Ꝭ':'IS','Ĵ':'J',\n\t'Ɉ':'J','Ḱ':'K','Ǩ':'K','Ķ':'K','Ⱪ':'K','Ꝃ':'K','Ḳ':'K','Ƙ':'K','Ḵ':'K','Ꝁ':'K','Ꝅ':'K','Ĺ':'L','Ƚ':'L','Ľ':'L',\n\t'Ļ':'L','Ḽ':'L','Ḷ':'L','Ḹ':'L','Ⱡ':'L','Ꝉ':'L','Ḻ':'L','Ŀ':'L','Ɫ':'L','Lj':'L','Ł':'L','LJ':'LJ','Ḿ':'M','Ṁ':'M',\n\t'Ṃ':'M','Ɱ':'M','Ń':'N','Ň':'N','Ņ':'N','Ṋ':'N','Ṅ':'N','Ṇ':'N','Ǹ':'N','Ɲ':'N','Ṉ':'N','Ƞ':'N','Nj':'N','Ñ':'N',\n\t'NJ':'NJ','Ó':'O','Ŏ':'O','Ǒ':'O','Ô':'O','Ố':'O','Ộ':'O','Ồ':'O','Ổ':'O','Ỗ':'O','Ö':'O','Ȫ':'O','Ȯ':'O','Ȱ':'O',\n\t'Ọ':'O','Ő':'O','Ȍ':'O','Ò':'O','Ỏ':'O','Ơ':'O','Ớ':'O','Ợ':'O','Ờ':'O','Ở':'O','Ỡ':'O','Ȏ':'O','Ꝋ':'O','Ꝍ':'O',\n\t'Ō':'O','Ṓ':'O','Ṑ':'O','Ɵ':'O','Ǫ':'O','Ǭ':'O','Ø':'O','Ǿ':'O','Õ':'O','Ṍ':'O','Ṏ':'O','Ȭ':'O','Ƣ':'OI','Ꝏ':'OO',\n\t'Ɛ':'E','Ɔ':'O','Ȣ':'OU','Ṕ':'P','Ṗ':'P','Ꝓ':'P','Ƥ':'P','Ꝕ':'P','Ᵽ':'P','Ꝑ':'P','Ꝙ':'Q','Ꝗ':'Q','Ŕ':'R','Ř':'R',\n\t'Ŗ':'R','Ṙ':'R','Ṛ':'R','Ṝ':'R','Ȑ':'R','Ȓ':'R','Ṟ':'R','Ɍ':'R','Ɽ':'R','Ꜿ':'C','Ǝ':'E','Ś':'S','Ṥ':'S','Š':'S',\n\t'Ṧ':'S','Ş':'S','Ŝ':'S','Ș':'S','Ṡ':'S','Ṣ':'S','Ṩ':'S','ẞ':'SS','Ť':'T','Ţ':'T','Ṱ':'T','Ț':'T','Ⱦ':'T','Ṫ':'T',\n\t'Ṭ':'T','Ƭ':'T','Ṯ':'T','Ʈ':'T','Ŧ':'T','Ɐ':'A','Ꞁ':'L','Ɯ':'M','Ʌ':'V','Ꜩ':'TZ','Ú':'U','Ŭ':'U','Ǔ':'U','Û':'U',\n\t'Ṷ':'U','Ü':'U','Ǘ':'U','Ǚ':'U','Ǜ':'U','Ǖ':'U','Ṳ':'U','Ụ':'U','Ű':'U','Ȕ':'U','Ù':'U','Ủ':'U','Ư':'U','Ứ':'U',\n\t'Ự':'U','Ừ':'U','Ử':'U','Ữ':'U','Ȗ':'U','Ū':'U','Ṻ':'U','Ų':'U','Ů':'U','Ũ':'U','Ṹ':'U','Ṵ':'U','Ꝟ':'V','Ṿ':'V',\n\t'Ʋ':'V','Ṽ':'V','Ꝡ':'VY','Ẃ':'W','Ŵ':'W','Ẅ':'W','Ẇ':'W','Ẉ':'W','Ẁ':'W','Ⱳ':'W','Ẍ':'X','Ẋ':'X','Ý':'Y','Ŷ':'Y',\n\t'Ÿ':'Y','Ẏ':'Y','Ỵ':'Y','Ỳ':'Y','Ƴ':'Y','Ỷ':'Y','Ỿ':'Y','Ȳ':'Y','Ɏ':'Y','Ỹ':'Y','Ź':'Z','Ž':'Z','Ẑ':'Z','Ⱬ':'Z',\n\t'Ż':'Z','Ẓ':'Z','Ȥ':'Z','Ẕ':'Z','Ƶ':'Z','IJ':'IJ','Œ':'OE','ᴀ':'A','ᴁ':'AE','ʙ':'B','ᴃ':'B','ᴄ':'C','ᴅ':'D','ᴇ':'E',\n\t'ꜰ':'F','ɢ':'G','ʛ':'G','ʜ':'H','ɪ':'I','ʁ':'R','ᴊ':'J','ᴋ':'K','ʟ':'L','ᴌ':'L','ᴍ':'M','ɴ':'N','ᴏ':'O','ɶ':'OE',\n\t'ᴐ':'O','ᴕ':'OU','ᴘ':'P','ʀ':'R','ᴎ':'N','ᴙ':'R','ꜱ':'S','ᴛ':'T','ⱻ':'E','ᴚ':'R','ᴜ':'U','ᴠ':'V','ᴡ':'W','ʏ':'Y',\n\t'ᴢ':'Z','á':'a','ă':'a','ắ':'a','ặ':'a','ằ':'a','ẳ':'a','ẵ':'a','ǎ':'a','â':'a','ấ':'a','ậ':'a','ầ':'a','ẩ':'a',\n\t'ẫ':'a','ä':'a','ǟ':'a','ȧ':'a','ǡ':'a','ạ':'a','ȁ':'a','à':'a','ả':'a','ȃ':'a','ā':'a','ą':'a','ᶏ':'a','ẚ':'a',\n\t'å':'a','ǻ':'a','ḁ':'a','ⱥ':'a','ã':'a','ꜳ':'aa','æ':'ae','ǽ':'ae','ǣ':'ae','ꜵ':'ao','ꜷ':'au','ꜹ':'av','ꜻ':'av',\n\t'ꜽ':'ay','ḃ':'b','ḅ':'b','ɓ':'b','ḇ':'b','ᵬ':'b','ᶀ':'b','ƀ':'b','ƃ':'b','ɵ':'o','ć':'c','č':'c','ç':'c','ḉ':'c',\n\t'ĉ':'c','ɕ':'c','ċ':'c','ƈ':'c','ȼ':'c','ď':'d','ḑ':'d','ḓ':'d','ȡ':'d','ḋ':'d','ḍ':'d','ɗ':'d','ᶑ':'d','ḏ':'d',\n\t'ᵭ':'d','ᶁ':'d','đ':'d','ɖ':'d','ƌ':'d','ı':'i','ȷ':'j','ɟ':'j','ʄ':'j','dz':'dz','dž':'dz','é':'e','ĕ':'e','ě':'e',\n\t'ȩ':'e','ḝ':'e','ê':'e','ế':'e','ệ':'e','ề':'e','ể':'e','ễ':'e','ḙ':'e','ë':'e','ė':'e','ẹ':'e','ȅ':'e','è':'e',\n\t'ẻ':'e','ȇ':'e','ē':'e','ḗ':'e','ḕ':'e','ⱸ':'e','ę':'e','ᶒ':'e','ɇ':'e','ẽ':'e','ḛ':'e','ꝫ':'et','ḟ':'f','ƒ':'f',\n\t'ᵮ':'f','ᶂ':'f','ǵ':'g','ğ':'g','ǧ':'g','ģ':'g','ĝ':'g','ġ':'g','ɠ':'g','ḡ':'g','ᶃ':'g','ǥ':'g','ḫ':'h','ȟ':'h',\n\t'ḩ':'h','ĥ':'h','ⱨ':'h','ḧ':'h','ḣ':'h','ḥ':'h','ɦ':'h','ẖ':'h','ħ':'h','ƕ':'hv','í':'i','ĭ':'i','ǐ':'i','î':'i',\n\t'ï':'i','ḯ':'i','ị':'i','ȉ':'i','ì':'i','ỉ':'i','ȋ':'i','ī':'i','į':'i','ᶖ':'i','ɨ':'i','ĩ':'i','ḭ':'i','ꝺ':'d',\n\t'ꝼ':'f','ᵹ':'g','ꞃ':'r','ꞅ':'s','ꞇ':'t','ꝭ':'is','ǰ':'j','ĵ':'j','ʝ':'j','ɉ':'j','ḱ':'k','ǩ':'k','ķ':'k','ⱪ':'k',\n\t'ꝃ':'k','ḳ':'k','ƙ':'k','ḵ':'k','ᶄ':'k','ꝁ':'k','ꝅ':'k','ĺ':'l','ƚ':'l','ɬ':'l','ľ':'l','ļ':'l','ḽ':'l','ȴ':'l',\n\t'ḷ':'l','ḹ':'l','ⱡ':'l','ꝉ':'l','ḻ':'l','ŀ':'l','ɫ':'l','ᶅ':'l','ɭ':'l','ł':'l','lj':'lj','ſ':'s','ẜ':'s','ẛ':'s',\n\t'ẝ':'s','ḿ':'m','ṁ':'m','ṃ':'m','ɱ':'m','ᵯ':'m','ᶆ':'m','ń':'n','ň':'n','ņ':'n','ṋ':'n','ȵ':'n','ṅ':'n','ṇ':'n',\n\t'ǹ':'n','ɲ':'n','ṉ':'n','ƞ':'n','ᵰ':'n','ᶇ':'n','ɳ':'n','ñ':'n','nj':'nj','ó':'o','ŏ':'o','ǒ':'o','ô':'o','ố':'o',\n\t'ộ':'o','ồ':'o','ổ':'o','ỗ':'o','ö':'o','ȫ':'o','ȯ':'o','ȱ':'o','ọ':'o','ő':'o','ȍ':'o','ò':'o','ỏ':'o','ơ':'o',\n\t'ớ':'o','ợ':'o','ờ':'o','ở':'o','ỡ':'o','ȏ':'o','ꝋ':'o','ꝍ':'o','ⱺ':'o','ō':'o','ṓ':'o','ṑ':'o','ǫ':'o','ǭ':'o',\n\t'ø':'o','ǿ':'o','õ':'o','ṍ':'o','ṏ':'o','ȭ':'o','ƣ':'oi','ꝏ':'oo','ɛ':'e','ᶓ':'e','ɔ':'o','ᶗ':'o','ȣ':'ou','ṕ':'p',\n\t'ṗ':'p','ꝓ':'p','ƥ':'p','ᵱ':'p','ᶈ':'p','ꝕ':'p','ᵽ':'p','ꝑ':'p','ꝙ':'q','ʠ':'q','ɋ':'q','ꝗ':'q','ŕ':'r','ř':'r',\n\t'ŗ':'r','ṙ':'r','ṛ':'r','ṝ':'r','ȑ':'r','ɾ':'r','ᵳ':'r','ȓ':'r','ṟ':'r','ɼ':'r','ᵲ':'r','ᶉ':'r','ɍ':'r','ɽ':'r',\n\t'ↄ':'c','ꜿ':'c','ɘ':'e','ɿ':'r','ś':'s','ṥ':'s','š':'s','ṧ':'s','ş':'s','ŝ':'s','ș':'s','ṡ':'s','ṣ':'s','ṩ':'s',\n\t'ʂ':'s','ᵴ':'s','ᶊ':'s','ȿ':'s','ɡ':'g','ß':'ss','ᴑ':'o','ᴓ':'o','ᴝ':'u','ť':'t','ţ':'t','ṱ':'t','ț':'t','ȶ':'t',\n\t'ẗ':'t','ⱦ':'t','ṫ':'t','ṭ':'t','ƭ':'t','ṯ':'t','ᵵ':'t','ƫ':'t','ʈ':'t','ŧ':'t','ᵺ':'th','ɐ':'a','ᴂ':'ae','ǝ':'e',\n\t'ᵷ':'g','ɥ':'h','ʮ':'h','ʯ':'h','ᴉ':'i','ʞ':'k','ꞁ':'l','ɯ':'m','ɰ':'m','ᴔ':'oe','ɹ':'r','ɻ':'r','ɺ':'r','ⱹ':'r',\n\t'ʇ':'t','ʌ':'v','ʍ':'w','ʎ':'y','ꜩ':'tz','ú':'u','ŭ':'u','ǔ':'u','û':'u','ṷ':'u','ü':'u','ǘ':'u','ǚ':'u','ǜ':'u',\n\t'ǖ':'u','ṳ':'u','ụ':'u','ű':'u','ȕ':'u','ù':'u','ủ':'u','ư':'u','ứ':'u','ự':'u','ừ':'u','ử':'u','ữ':'u','ȗ':'u',\n\t'ū':'u','ṻ':'u','ų':'u','ᶙ':'u','ů':'u','ũ':'u','ṹ':'u','ṵ':'u','ᵫ':'ue','ꝸ':'um','ⱴ':'v','ꝟ':'v','ṿ':'v','ʋ':'v',\n\t'ᶌ':'v','ⱱ':'v','ṽ':'v','ꝡ':'vy','ẃ':'w','ŵ':'w','ẅ':'w','ẇ':'w','ẉ':'w','ẁ':'w','ⱳ':'w','ẘ':'w','ẍ':'x','ẋ':'x',\n\t'ᶍ':'x','ý':'y','ŷ':'y','ÿ':'y','ẏ':'y','ỵ':'y','ỳ':'y','ƴ':'y','ỷ':'y','ỿ':'y','ȳ':'y','ẙ':'y','ɏ':'y','ỹ':'y',\n\t'ź':'z','ž':'z','ẑ':'z','ʑ':'z','ⱬ':'z','ż':'z','ẓ':'z','ȥ':'z','ẕ':'z','ᵶ':'z','ᶎ':'z','ʐ':'z','ƶ':'z','ɀ':'z',\n\t'ff':'ff','ffi':'ffi','ffl':'ffl','fi':'fi','fl':'fl','ij':'ij','œ':'oe','st':'st','ₐ':'a','ₑ':'e','ᵢ':'i','ⱼ':'j','ₒ':'o',\n\t'ᵣ':'r','ᵤ':'u','ᵥ':'v','ₓ':'x'\n};\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Strings:replace\n */\n\n/**\n * Offers similar functionality to PHP's str_replace or ES2021's replaceAll and avoids RegExps for this task.\n * Replaces occurrences of search in subject with replace. search and replace may be arrays.\n * If search is an array and replace is a string, all phrases in the array will be replaced with one string.\n * If replace is an array itself, phrases and replacements are matched by index.\n * Missing replacements are treated as an empty string (for example: if your array lengths do not match).\n *\n * Uses String.prototype.replaceAll internally, if available.\n *\n * @param {String} subject - the string to replace in\n * @param {(String|String[])} search - the string(s) to replace\n * @param {String|String[]} replace - the string(s) to replace the search string(s)\n * @returns {String} the modified string\n *\n * @memberof Strings:replace\n * @alias replace\n * @example\n * const sanitizedString = replace([':', '#', '-'], '_', exampleString);\n */\nexport function replace(subject, search, replace){\n\tsubject = `${subject}`;\n\tsearch = [].concat(search);\n\treplace = [].concat(replace);\n\n\tlet tmp = '';\n\n\tsearch.forEach((searchTerm, index) => {\n\t\ttmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0];\n\n\t\tif( isFunction(String.prototype.replaceAll) ){\n\t\t\tsubject = subject.replaceAll(`${searchTerm}`, `${tmp}`);\n\t\t} else {\n\t\t\tsubject = subject.split(`${searchTerm}`).join(`${tmp}`);\n\t\t}\n\t});\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:truncate\n */\n\n/**\n * Truncates a given string after a certain number of characters to enforce length restrictions.\n *\n * @param {String} subject - the string to check and truncate\n * @param {?Number} [maxLength=30] - the maximum allowed character length for the string\n * @param {?String} [suffix='...'] - the trailing string to end a truncated string with\n * @throws error if suffix length is bigger than defined maxLength\n * @returns {String} the (truncated) subject\n *\n * @memberof Strings:truncate\n * @alias truncate\n * @example\n * const truncatedString = truncate(string, 10, '...');\n */\nexport function truncate(subject, maxLength=30, suffix='...'){\n\tsubject = `${subject}`;\n\tmaxLength = orDefault(maxLength, 30, 'int');\n\tsuffix = orDefault(suffix, '...', 'str');\n\n\tif( suffix.length > maxLength ){\n\t\tthrow new Error(`${MODULE_NAME}:truncate | suffix cannot be longer than maxLength`);\n\t}\n\n\tif( subject.length > maxLength ){\n\t\tsubject = `${subject.slice(0, maxLength - suffix.length)}${suffix}`;\n\t}\n\n\treturn subject;\n}\n\n\n\n/**\n * @namespace Strings:concat\n */\n\n/**\n * Simply concatenates strings with a glue part using array.join in a handy notation.\n * You can also provide arguments to glue as a prepared array as the second parameter,\n * in that case other parameters will be ignored.\n *\n * @param {?String} [glue=''] - the separator to use between single strings\n * @param {?String[]} strings - list of strings to concatenate, either comma-separated or as single array\n * @returns {String} the concatenated string\n *\n * @memberof Strings:concat\n * @alias concat\n * @example\n * const finalCountdown = concat(' ... ', 10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!');\n * const finalCountdown = concat(' ... ', [10, 9, 8, 7, 6, '5', '4', '3', '2', '1', 'ZERO!']);\n */\nexport function concat(glue='', ...strings){\n\tglue = orDefault(glue, '', 'str');\n\n\tif( (strings.length > 0) && isArray(strings[0]) ){\n\t\treturn strings[0].join(glue);\n\t} else {\n\t\treturn strings.join(glue);\n\t}\n}\n\n\n\n/**\n * @namespace Strings:format\n */\n\n/**\n * This is a pythonesque string format implementation.\n * Apply formatted values to a string template, in which replacements are marked with curly braces.\n *\n * Display literal curly brace with {{ and }}.\n *\n * Unknown keys/indexes will be ignored.\n *\n * This solution is adapted from:\n * https://github.com/davidchambers/string-format\n *\n * @param {String} template -\n * @param {(String[]|Object)} replacements - arguments to insert into template, either as a dictionary, an array or a parameter sequence\n * @throws general exception on syntax errors\n * @returns {String} the formatted string\n *\n * @memberof Strings:format\n * @alias format\n * @example\n * format('An elephant is {times:float(0.00)} times smarter than a {animal}', {times : 5.5555, animal : 'lion'})\n * => 'An elephant is 5.56 times smarter than a lion'\n * format('{0}{0}{0} ... {{BATMAN!}}', 'Nana')\n * => 'NanaNanaNana ... {BATMAN!}'\n * format('{} {} {} starts the alphabet.', 'A', 'B', 'C')\n * => 'A B C starts the alphabet.'\n * format('{0:int}, {1:int}, {2:int}: details are for wankers', '1a', 2.222, 3)\n * => '1, 2, 3: details are for wankers'\n */\nexport function format(template, ...replacements){\n\ttemplate = `${template}`;\n\n\tlet\n\t\tidx = 0,\n\t\texplicit = false,\n\t\timplicit = false\n\t;\n\n\tconst fResolve = function(object, key){\n\t\tconst value = object[key];\n\n\t\tif( isFunction(value) ){\n\t\t\treturn value.call(object);\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t};\n\n\tconst fLookup = function(object, key){\n\t\tif( !/^(\\d+)([.]|$)/.test(key) ){\n\t\t\tkey = `0.${key}`;\n\t\t}\n\n\t\tlet match = /(.+?)[.](.+)/.exec(key);\n\t\twhile( match ){\n\t\t\tobject = fResolve(object, match[1]);\n\t\t\tkey = match[2];\n\t\t\tmatch = /(.+?)[.](.+)/.exec(key);\n\t\t}\n\n\t\treturn fResolve(object, key);\n\t};\n\n\tconst formatters = {\n\t\tint(value, radix){\n\t\t\tradix = orDefault(radix, 10, 'int');\n\t\t\tconst res = parseInt(value, radix);\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t},\n\t\tfloat(value, format){\n\t\t\tformat = orDefault(format, null, 'str');\n\n\t\t\tlet res = null;\n\n\t\t\tif( hasValue(format) ){\n\t\t\t\tlet precision = 0;\n\n\t\t\t\ttry {\n\t\t\t\t\tprecision = format.split('.')[1].length;\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | float precision arg malformed`);\n\t\t\t\t}\n\n\t\t\t\tconst power = Math.pow(10, precision);\n\n\t\t\t\tres = Math.round(parseFloat(value) * power) / power;\n\t\t\t} else {\n\t\t\t\tres = parseFloat(value);\n\t\t\t}\n\n\t\t\treturn !isNaN(res) ? `${res}` : '';\n\t\t}\n\t};\n\n\treturn template.replace(/([{}])\\1|[{](.*?)(?:!(.+?))?[}]/g, function(match, literal, key){\n\t\tlet\n\t\t\tref = null,\n\t\t\tvalue = '',\n\t\t\tformatter = function(value){ return value; },\n\t\t\tformatterArg = null\n\t\t;\n\n\t\tif( literal ){\n\t\t\treturn literal;\n\t\t}\n\n\t\tif( key.length ){\n\t\t\tconst keyParts = key.split(':');\n\n\t\t\tif( keyParts.length > 1 ){\n\t\t\t\tkey = keyParts[0];\n\n\t\t\t\tconst\n\t\t\t\t\tformatterParts = keyParts[1].split('('),\n\t\t\t\t\tformatterName = formatterParts[0]\n\t\t\t\t;\n\n\t\t\t\tif( formatterParts.length > 1 ){\n\t\t\t\t\tformatterArg = formatterParts[1].replace(')', '');\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tformatter = formatters[formatterName];\n\t\t\t\t} catch(ex) {\n\t\t\t\t\tthrow new Error(`${MODULE_NAME}:format | unknown formatter`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( implicit ){\n\t\t\t\tthrow new Error(`${MODULE_NAME}:format | cannot switch from implicit to explicit numbering`);\n\t\t\t} else {\n\t\t\t\texplicit = true;\n\t\t\t}\n\n\t\t\tref = fLookup(replacements, key);\n\t\t\tvalue = orDefault(ref, '');\n\t\t} else {\n\t\t\tif( explicit ){\n\t\t\t\tthrow new Error (`${MODULE_NAME}:format | cannot switch from explicit to implicit numbering`);\n\t\t\t} else {\n\t\t\t\timplicit = true;\n\t\t\t}\n\n\t\t\tref = replacements[idx];\n\t\t\tvalue = orDefault(ref, '');\n\t\t\tidx++;\n\t\t}\n\n\t\treturn formatter(value, formatterArg);\n\t});\n}\n\n\n\n/**\n * @namespace Strings:slugify\n */\n\n/**\n * Slugifies a text for use in a URL or id/class/attribute.\n * Transforms accented characters to non-accented ones.\n * Throws out everything except basic A-Z characters and numbers after replacements have taken place.\n * Provide own replacements, supplementing or overriding the default replacement map to cover special cases\n * (will take precedence over the default map).\n *\n * @param {String} text - the text to slugify\n * @param {String?} [additionalMap=null] - optional character map to supplement/override the default map, having the form {'[search character]' : '[replacement]', ...}\n * @returns {String} the slugified string\n *\n * @memberof Strings:slugify\n * @alias slugify\n * @example\n * slugify('This is a cömplicated ßtring for URLs!')\n * => 'this-is-a-complicated-sstring-for-urls'\n */\nexport function slugify(text, additionalMap=null){\n\tif( !isPlainObject(additionalMap) ){\n\t\tadditionalMap = {};\n\t}\n\n\treturn `${text}`.toLowerCase()\n\t\t.replace(/\\s+|_+/g, '-') // replace spaces and underscores with \"-\"\n\t\t.replace(\n\t\t\t/[^\\-]/g, // replace accented chars with plain ones via map and/or apply additionalMap\n\t\t\tchar => additionalMap[char] ?? SLUGIFY_LATINMAP[char] ?? char\n\t\t)\n\t\t.replace(/[^\\w\\-]+/g, '') // remove all non-word, non-dash chars\n\t\t.replace(/--+/g, '-') // replace multiple \"-\" with single \"-\"\n\t\t.replace(/^-+/, '') // trim \"-\" from start of text\n\t\t.replace(/-+$/, '') // trim \"-\" from end of text\n\t;\n}\n\n\n\n/**\n * @namespace Strings:maskForSelector\n */\n\n/**\n * Masks all selector-special-characters, to allow selecting elements with special characters in selector using\n * querySelector and querySelectorAll (also works for jQuery and Cash).\n *\n * @param {String} str - the string to mask for use in a selector\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForSelector\n * @alias maskForSelector\n * @example\n * document.querySelector(`#element_${maskForSelector(elementName)}`).classList.remove('test');\n */\nexport function maskForSelector(str){\n\treturn `${str}`.replace(/([#;&,.+*~':\"!^$\\[\\]()=>|\\/@])/g, '\\\\$&');\n}\n\n\n\n/**\n * @namespace Strings:maskForRegEx\n */\n\n/**\n * Masks all regex special characters, to test or match a string using a regex, that contains\n * characters used in regexes themselves.\n *\n * @param {String} str - the string to mask for use in a regexp\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForRegEx\n * @alias maskForRegEx\n * @example\n * if( (new RegExp(`^${maskForRegEx(arbitraryString)}$')).test('abc') ){\n * alert('are identical!');\n * }\n */\nexport function maskForRegEx(str){\n\treturn `${str}`.replace(/([\\-\\[\\]\\/{}()*+?.\\\\^$|])/g, \"\\\\$&\");\n}\n\n\n\n/**\n * @namespace Strings:maskForHtml\n */\n\n/**\n * Masks a string possibly containing reserved HTML chars for HTML output as is\n * (so a < actually reads on the page).\n *\n * Only replaces critical chars like <>& with entities, but\n * keeps non-critical unicode chars like »/.\n *\n * @param {String} text - the string to mask for use in HTML\n * @returns {String} the masked string\n *\n * @memberof Strings:maskForHtml\n * @alias maskForHtml\n * @see unmaskFromHtml\n * @example\n * maskForHtml('&;üäöÜÄÖß– »')\n * => '</>&;üäöÜÄÖß– »'\n */\nexport function maskForHtml(text){\n\tconst escape = document.createElement('textarea');\n\tescape.textContent = `${text}`;\n\treturn escape.innerHTML;\n}\n\n\n\n/**\n * @namespace Strings:unmaskFromHtml\n */\n\n/**\n * Replaces entities in a html-masked string with the vanilla characters\n * thereby returning a real HTML string, which could, for example, be used\n * to construct new elements with tag markup.\n *\n * @param {String} html - the string to unmask entities in\n * @returns {String} the unmasked string\n *\n * @memberof Strings:unmaskFromHtml\n * @alias unmaskFromHtml\n * @see maskForHtml\n * @example\n * unmaskFromHtml('</>&;üäöÜÄÖß– »')\n * => '&;üäöÜÄÖß– »'\n */\nexport function unmaskFromHtml(html){\n\tconst escape = document.createElement('textarea');\n\tescape.innerHTML = `${html}`;\n\treturn escape.textContent;\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/timers.js b/docs/examples/lib/annex/dist/timers.js index 60c6b521..7c5fc56d 100644 --- a/docs/examples/lib/annex/dist/timers.js +++ b/docs/examples/lib/annex/dist/timers.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Timers */ -const MODULE_NAME="Timers";import{orDefault,isA,assert,hasValue,hasMembers}from"./basic.js";export function schedule(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:schedule | ms must be positive"),assert(isA(t,"function"),"Timers:schedule | callback must be a function"),hasValue(n)&&countermand(n),{id:window.setTimeout(t,e),type:"timeout"}}export function pschedule(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:pschedule | ms must be positive"),assert(isA(t,"function"),"Timers:pschedule | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n),n.precise=!0):n={id:-1,type:"timeout",precise:!0};const i=Date.now();let o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):t()};return n.id=window.setTimeout(s,o),n}export function reschedule(e,t,n){return t=orDefault(t,1,"int"),assert(t>=0,"Timers:reschedule | ms must be positive"),assert(isA(n,"function"),"Timers:reschedule | callback must be a function"),hasValue(e)&&hasValue(e.precise)&&e.precise?pschedule(t,n,e):schedule(t,n,e)}export function loop(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:loop | ms must be positive"),assert(isA(t,"function"),"Timers:loop | callback must be a function"),hasValue(n)&&countermand(n,!0),{id:window.setInterval(t,e),type:"interval"}}export function ploop(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:ploop | ms must be positive"),assert(isA(t,"function"),"Timers:ploop | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n,!0),n.precise=!0):n={id:-1,type:"interval",precise:!0};let i=Date.now(),o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):(t(),i=Date.now(),o=e,n.id=window.setTimeout(s,o))};return n.id=window.setTimeout(s,o),n}export function countermand(e,t=!1){t=orDefault(t,!1,"bool"),hasValue(e)&&(hasMembers(e,["id","type"])?"interval"===e.type?window.clearInterval(e.id):window.clearTimeout(e.id):t?window.clearInterval(e):window.clearTimeout(e))}export function requestAnimationFrame(e){assert(isA(e,"function"),"Timers:requestAnimationFrame | callback is no function");const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame??function(e){return schedule(16,e)};return t(e)}export function cancelAnimationFrame(e){const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame;let n=window.cancelAnimationFrame??window.mozCancelAnimationFrame;return hasValue(t)||(n=countermand),n(e)}export function waitForRepaint(e){assert(isA(e,"function"),"Timers:waitForRepaint | callback is no function");const t={};return t.outer=requestAnimationFrame((function(){t.inner=requestAnimationFrame(e)})),t} +const MODULE_NAME="Timers";import{orDefault,isFunction,assert,hasValue,hasMembers}from"./basic.js";export function schedule(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:schedule | ms must be positive"),assert(isFunction(t),"Timers:schedule | callback must be a function"),hasValue(n)&&countermand(n),{id:window.setTimeout(t,e),type:"timeout"}}export function pschedule(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:pschedule | ms must be positive"),assert(isFunction(t),"Timers:pschedule | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n),n.precise=!0):n={id:-1,type:"timeout",precise:!0};const i=Date.now();let o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):t()};return n.id=window.setTimeout(s,o),n}export function reschedule(e,t,n){return t=orDefault(t,1,"int"),assert(t>=0,"Timers:reschedule | ms must be positive"),assert(isFunction(n),"Timers:reschedule | callback must be a function"),hasValue(e)&&hasValue(e.precise)&&e.precise?pschedule(t,n,e):schedule(t,n,e)}export function loop(e,t,n=null){return e=orDefault(e,1,"int"),assert(e>=0,"Timers:loop | ms must be positive"),assert(isFunction(t),"Timers:loop | callback must be a function"),hasValue(n)&&countermand(n,!0),{id:window.setInterval(t,e),type:"interval"}}export function ploop(e,t,n=null){e=orDefault(e,1,"int"),assert(e>=0,"Timers:ploop | ms must be positive"),assert(isFunction(t),"Timers:ploop | callback must be a function"),hasValue(n)&&hasMembers(n,["id","type"])?(countermand(n,!0),n.precise=!0):n={id:-1,type:"interval",precise:!0};let i=Date.now(),o=e;const s=function(){o>0?(o-=Date.now()-i,n.id=window.setTimeout(s,o>10?o:10)):(t(),i=Date.now(),o=e,n.id=window.setTimeout(s,o))};return n.id=window.setTimeout(s,o),n}export function countermand(e,t=!1){t=orDefault(t,!1,"bool"),hasValue(e)&&(hasMembers(e,["id","type"])?"interval"===e.type?window.clearInterval(e.id):window.clearTimeout(e.id):t?window.clearInterval(e):window.clearTimeout(e))}export function requestAnimationFrame(e){assert(isFunction(e),"Timers:requestAnimationFrame | callback is no function");const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame??function(e){return schedule(16,e)};return t(e)}export function cancelAnimationFrame(e){const t=window.requestAnimationFrame??window.webkitRequestAnimationFrame??window.mozRequestAnimationFrame??window.msRequestAnimationFrame;let n=window.cancelAnimationFrame??window.mozCancelAnimationFrame;return hasValue(t)||(n=countermand),n(e)}export function waitForRepaint(e){assert(isFunction(e),"Timers:waitForRepaint | callback is no function");const t={};return t.outer=requestAnimationFrame((function(){t.inner=requestAnimationFrame(e)})),t} //# sourceMappingURL=timers.js.map diff --git a/docs/examples/lib/annex/dist/timers.js.map b/docs/examples/lib/annex/dist/timers.js.map index 8561cac8..8fdd9beb 100644 --- a/docs/examples/lib/annex/dist/timers.js.map +++ b/docs/examples/lib/annex/dist/timers.js.map @@ -1 +1 @@ -{"version":3,"file":"timers.js","names":["MODULE_NAME","orDefault","isA","assert","hasValue","hasMembers","schedule","ms","callback","oldTimer","countermand","id","window","setTimeout","type","pschedule","precise","waitStart","Date","now","waitMilliSecs","fAdjustWait","reschedule","timer","loop","oldLoop","setInterval","ploop","isInterval","clearInterval","clearTimeout","requestAnimationFrame","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cancelAnimationFrame","caf","mozCancelAnimationFrame","waitForRepaint","ids","outer","inner"],"sources":["timers.js"],"mappings":"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","sourcesContent":["/*!\n * Module Timers\n */\n\n/**\n * @namespace Timers\n */\n\nconst MODULE_NAME = 'Timers';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {orDefault, isA, assert, hasValue, hasMembers} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Timers:schedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is negative or callback is not a function\n * @returns {Object} new timer\n *\n * @memberof Timers:schedule\n * @alias schedule\n * @see pschedule\n * @see countermand\n * @example\n * const timer = schedule(1000, function(){ alert('time for tea'); });\n * const timer = schedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function schedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:schedule | callback must be a function`);\n\n\tif( hasValue(oldTimer) ){\n\t\tcountermand(oldTimer);\n\t}\n\n\treturn {id : window.setTimeout(callback, ms), type : 'timeout'};\n}\n\n\n\n/**\n * @namespace Timers:pschedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long\n * running timers. The timers of this method can also be used in countermand().\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (does not create new timer object if oldTimer given, but returns old one)\n *\n * @memberof Timers:pschedule\n * @alias pschedule\n * @see schedule\n * @see countermand\n * @example\n * const timer = pschedule(1000, function(){ alert('time for tea'); });\n * const timer = pschedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function pschedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:pschedule | callback must be a function`);\n\n\tif(\n\t\thasValue(oldTimer)\n\t\t&& hasMembers(oldTimer, ['id', 'type'])\n\t){\n\t\tcountermand(oldTimer);\n\t\toldTimer.precise = true;\n\t} else {\n\t\toldTimer = {id : -1, type : 'timeout', precise : true};\n\t}\n\n\tconst waitStart = Date.now();\n\tlet waitMilliSecs = ms;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldTimer.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t}\n\t};\n\n\toldTimer.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldTimer;\n}\n\n\n\n/**\n * @namespace Timers:reschedule\n */\n\n/**\n * Alias for schedule() with more natural param-order for rescheduling.\n *\n * @param {(Object|Number)} timer - the timer to refresh/reset\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (may be the original timer, if given timer is precise from pschedule or ploop)\n *\n * @memberof Timers:reschedule\n * @alias reschedule\n * @see schedule\n * @example\n * const timer = reschedule(timer, 3000, function(){ alert('taking even more time'); });\n */\nexport function reschedule(timer, ms, callback){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:reschedule | callback must be a function`);\n\n\tif( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){\n\t\treturn pschedule(ms, callback, timer);\n\t} else {\n\t\treturn schedule(ms, callback, timer);\n\t}\n}\n\n\n\n/**\n * @namespace Timers:loop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} new loop\n *\n * @memberof Timers:loop\n * @alias loop\n * @see ploop\n * @see countermand\n * @example\n * const loop = loop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = loop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function loop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:loop | callback must be a function`);\n\n\tif( hasValue(oldLoop) ){\n\t\tcountermand(oldLoop, true);\n\t}\n\n\treturn {id : window.setInterval(callback, ms), type : 'interval'};\n}\n\n\n\n/**\n * @namespace Timers:ploop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long running loops.\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * The loops of this method can also be used in countermand().\n * This method does not actually use intervals internally but timeouts,\n * so don't wonder if you can't find the ids in JS.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} loop (if you give an old loop into the function the same reference will be returned)\n *\n * @memberof Timers:ploop\n * @alias ploop\n * @see loop\n * @see countermand\n * @example\n * const loop = ploop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = ploop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function ploop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`);\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:ploop | callback must be a function`);\n\n\tif(\n\t\thasValue(oldLoop)\n\t\t&& hasMembers(oldLoop, ['id', 'type'])\n\t){\n\t\tcountermand(oldLoop, true);\n\t\toldLoop.precise = true;\n\t} else {\n\t\toldLoop = {id : -1, type : 'interval', precise : true};\n\t}\n\n\tlet\n\t\twaitStart = Date.now(),\n\t\twaitMilliSecs = ms\n\t;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t\twaitStart = Date.now();\n\t\t\twaitMilliSecs = ms;\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\t\t}\n\t};\n\n\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldLoop;\n}\n\n\n\n/**\n * @namespace Timers:countermand\n */\n\n/**\n * Cancel a timer or loop immediately.\n *\n * @param {(Object|Number)} timer - the timer or loop to end\n * @param {?Boolean} [isInterval=false] - defines if a timer or a loop is to be stopped, set in case timer is a GUID\n *\n * @memberof Timers:countermand\n * @alias countermand\n * @see schedule\n * @see pschedule\n * @see loop\n * @see ploop\n * @example\n * countermand(timer);\n * countermand(loop);\n */\nexport function countermand(timer, isInterval=false){\n\tisInterval = orDefault(isInterval, false, 'bool');\n\n\tif( hasValue(timer) ){\n\t\tif( hasMembers(timer, ['id', 'type']) ){\n\t\t\tif( timer.type === 'interval' ){\n\t\t\t\twindow.clearInterval(timer.id);\n\t\t\t} else {\n\t\t\t\twindow.clearTimeout(timer.id);\n\t\t\t}\n\t\t} else {\n\t\t\tif( !isInterval ){\n\t\t\t\twindow.clearTimeout(timer);\n\t\t\t} else {\n\t\t\t\twindow.clearInterval(timer);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/**\n * @namespace Timers:requestAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.requestAnimationFrame with a timeout fallback in\n * case the functionality is missing from the browser.\n *\n * @param {Function} callback - the code to execute once the browser has assigned an execution slot for it\n * @throws error if callback is not a function\n * @return {Number} either the id of the requestAnimationFrame or the internal timeout, both are cancellable via cancelAnimationFrame\n *\n * @memberof Timers:requestAnimationFrame\n * @alias requestAnimationFrame\n * @see raf\n * @see cancelAnimationFrame\n * @see caf\n * @example\n * const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; });\n */\nexport function requestAnimationFrame(callback){\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:requestAnimationFrame | callback is no function`);\n\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t\t?? function(callback){ return schedule(16, callback); }\n\t;\n\n\treturn raf(callback);\n}\n\n\n\n/**\n * @namespace Timers:cancelAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.cancelAnimationFrame.\n *\n * @param {Number} id - either the id of the requestAnimationFrame or its timeout fallback\n *\n * @memberof Timers:cancelAnimationFrame\n * @alias cancelAnimationFrame\n * @see requestAnimationFrame\n * @see raf\n * @see caf\n * @example\n * cancelAnimationFrame(requestAnimationFrame(function(){ window.body.style.opacity = 0; }));\n */\nexport function cancelAnimationFrame(id){\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t;\n\n\tlet caf = window.cancelAnimationFrame\n\t\t?? window.mozCancelAnimationFrame\n\t;\n\n\tif( !hasValue(raf) ){\n\t\tcaf = countermand;\n\t}\n\n\treturn caf(id);\n}\n\n\n\n/**\n * @namespace Timers:waitForRepaint\n */\n\n/**\n * This function has the purpose to offer a safe execution slot for code depending on an up-to-date rendering state of\n * the DOM after a change to styles for example. Let's say you add a class to an element and right in the next line\n * you'll want to read a layout attribute like width or height from it. This might fail, because there is no guarantee\n * the browser actually already applied the new styles to be read from the DOM.\n *\n * To wait safely for the new DOM state this method works with two stacked requestAnimationFrame calls.\n *\n * Since requestAnimationFrame always happens _before_ a repaint, two stacked calls ensure, that there has to be a\n * repaint between them.\n *\n * @param {Function} callback - the code to execute once the browser performed a repaint\n * @throws error if callback is not a function\n * @return {Object} dictionary of ids for the inner and outer request ids, outer gets assigned right away, while inner gets assigned after first callback => {outer : 1, inner : 2}\n *\n * @memberof Timers:waitForRepaint\n * @alias waitForRepaint\n * @see requestAnimationFrame\n * @see raf\n * @example\n * element.classList.add('special-stuff');\n * waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); });\n */\nexport function waitForRepaint(callback){\n\tassert(isA(callback, 'function'), `${MODULE_NAME}:waitForRepaint | callback is no function`);\n\n\tconst ids = {};\n\n\tids.outer = requestAnimationFrame(function(){\n\t\tids.inner = requestAnimationFrame(callback);\n\t});\n\n\treturn ids;\n}\n"]} \ No newline at end of file +{"version":3,"file":"timers.js","names":["MODULE_NAME","orDefault","isFunction","assert","hasValue","hasMembers","schedule","ms","callback","oldTimer","countermand","id","window","setTimeout","type","pschedule","precise","waitStart","Date","now","waitMilliSecs","fAdjustWait","reschedule","timer","loop","oldLoop","setInterval","ploop","isInterval","clearInterval","clearTimeout","requestAnimationFrame","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cancelAnimationFrame","caf","mozCancelAnimationFrame","waitForRepaint","ids","outer","inner"],"sources":["timers.js"],"mappings":"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","sourcesContent":["/*!\n * Module Timers\n */\n\n/**\n * @namespace Timers\n */\n\nconst MODULE_NAME = 'Timers';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {orDefault, isFunction, assert, hasValue, hasMembers} from './basic.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Timers:schedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is negative or callback is not a function\n * @returns {Object} new timer\n *\n * @memberof Timers:schedule\n * @alias schedule\n * @see pschedule\n * @see countermand\n * @example\n * const timer = schedule(1000, function(){ alert('time for tea'); });\n * const timer = schedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function schedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:schedule | callback must be a function`);\n\n\tif( hasValue(oldTimer) ){\n\t\tcountermand(oldTimer);\n\t}\n\n\treturn {id : window.setTimeout(callback, ms), type : 'timeout'};\n}\n\n\n\n/**\n * @namespace Timers:pschedule\n */\n\n/**\n * Setup a timer for one-time execution of a callback, kills old timer if given\n * to prevent overlapping timers.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long\n * running timers. The timers of this method can also be used in countermand().\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldTimer=null] - if set, kills the timer before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (does not create new timer object if oldTimer given, but returns old one)\n *\n * @memberof Timers:pschedule\n * @alias pschedule\n * @see schedule\n * @see countermand\n * @example\n * const timer = pschedule(1000, function(){ alert('time for tea'); });\n * const timer = pschedule(2000, function(){ alert('traffic jam, tea has to wait'); }, timer);\n */\nexport function pschedule(ms, callback, oldTimer=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:pschedule | callback must be a function`);\n\n\tif(\n\t\thasValue(oldTimer)\n\t\t&& hasMembers(oldTimer, ['id', 'type'])\n\t){\n\t\tcountermand(oldTimer);\n\t\toldTimer.precise = true;\n\t} else {\n\t\toldTimer = {id : -1, type : 'timeout', precise : true};\n\t}\n\n\tconst waitStart = Date.now();\n\tlet waitMilliSecs = ms;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldTimer.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t}\n\t};\n\n\toldTimer.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldTimer;\n}\n\n\n\n/**\n * @namespace Timers:reschedule\n */\n\n/**\n * Alias for schedule() with more natural param-order for rescheduling.\n *\n * @param {(Object|Number)} timer - the timer to refresh/reset\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} timer (may be the original timer, if given timer is precise from pschedule or ploop)\n *\n * @memberof Timers:reschedule\n * @alias reschedule\n * @see schedule\n * @example\n * const timer = reschedule(timer, 3000, function(){ alert('taking even more time'); });\n */\nexport function reschedule(timer, ms, callback){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:reschedule | callback must be a function`);\n\n\tif( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){\n\t\treturn pschedule(ms, callback, timer);\n\t} else {\n\t\treturn schedule(ms, callback, timer);\n\t}\n}\n\n\n\n/**\n * @namespace Timers:loop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} new loop\n *\n * @memberof Timers:loop\n * @alias loop\n * @see ploop\n * @see countermand\n * @example\n * const loop = loop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = loop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function loop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:loop | callback must be a function`);\n\n\tif( hasValue(oldLoop) ){\n\t\tcountermand(oldLoop, true);\n\t}\n\n\treturn {id : window.setInterval(callback, ms), type : 'interval'};\n}\n\n\n\n/**\n * @namespace Timers:ploop\n */\n\n/**\n * Setup a loop for repeated execution of a callback, kills old loop if wished\n * to prevent overlapping loops.\n * This implementation uses Date.now()/Date.getTime() to improve on timer precision for long running loops.\n *\n * Warning: these timers are more precise than normal timer for _long_ time spans and less precise for short ones,\n * if you are dealing with times at least above 30s (or minutes and hours) this the right choice, if you look to\n * use precise timers in the second and millisecond range, definitely use schedule/loop instead!\n *\n * The loops of this method can also be used in countermand().\n * This method does not actually use intervals internally but timeouts,\n * so don't wonder if you can't find the ids in JS.\n *\n * @param {Number} ms - time in milliseconds until execution\n * @param {Function} callback - callback function to execute after ms\n * @param {?(Object|Number)} [oldLoop=null] - if set, kills the loop before setting up new one\n * @throws error if ms is not positive or if callback is not a function\n * @returns {Object} loop (if you give an old loop into the function the same reference will be returned)\n *\n * @memberof Timers:ploop\n * @alias ploop\n * @see loop\n * @see countermand\n * @example\n * const loop = ploop(250, function(){ document.body.classList.add('brightred'); });\n * const loop = ploop(100, function(){ document.body.classList.add('brightgreen'); }, loop);\n */\nexport function ploop(ms, callback, oldLoop=null){\n\tms = orDefault(ms, 1, 'int');\n\n\tassert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`);\n\tassert(isFunction(callback), `${MODULE_NAME}:ploop | callback must be a function`);\n\n\tif(\n\t\thasValue(oldLoop)\n\t\t&& hasMembers(oldLoop, ['id', 'type'])\n\t){\n\t\tcountermand(oldLoop, true);\n\t\toldLoop.precise = true;\n\t} else {\n\t\toldLoop = {id : -1, type : 'interval', precise : true};\n\t}\n\n\tlet\n\t\twaitStart = Date.now(),\n\t\twaitMilliSecs = ms\n\t;\n\n\tconst fAdjustWait = function(){\n\t\tif( waitMilliSecs > 0 ){\n\t\t\twaitMilliSecs -= (Date.now() - waitStart);\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, (waitMilliSecs > 10) ? waitMilliSecs : 10);\n\t\t} else {\n\t\t\tcallback();\n\t\t\twaitStart = Date.now();\n\t\t\twaitMilliSecs = ms;\n\t\t\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\t\t}\n\t};\n\n\toldLoop.id = window.setTimeout(fAdjustWait, waitMilliSecs);\n\n\treturn oldLoop;\n}\n\n\n\n/**\n * @namespace Timers:countermand\n */\n\n/**\n * Cancel a timer or loop immediately.\n *\n * @param {(Object|Number)} timer - the timer or loop to end\n * @param {?Boolean} [isInterval=false] - defines if a timer or a loop is to be stopped, set in case timer is a GUID\n *\n * @memberof Timers:countermand\n * @alias countermand\n * @see schedule\n * @see pschedule\n * @see loop\n * @see ploop\n * @example\n * countermand(timer);\n * countermand(loop);\n */\nexport function countermand(timer, isInterval=false){\n\tisInterval = orDefault(isInterval, false, 'bool');\n\n\tif( hasValue(timer) ){\n\t\tif( hasMembers(timer, ['id', 'type']) ){\n\t\t\tif( timer.type === 'interval' ){\n\t\t\t\twindow.clearInterval(timer.id);\n\t\t\t} else {\n\t\t\t\twindow.clearTimeout(timer.id);\n\t\t\t}\n\t\t} else {\n\t\t\tif( !isInterval ){\n\t\t\t\twindow.clearTimeout(timer);\n\t\t\t} else {\n\t\t\t\twindow.clearInterval(timer);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n/**\n * @namespace Timers:requestAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.requestAnimationFrame with a timeout fallback in\n * case the functionality is missing from the browser.\n *\n * @param {Function} callback - the code to execute once the browser has assigned an execution slot for it\n * @throws error if callback is not a function\n * @return {Number} either the id of the requestAnimationFrame or the internal timeout, both are cancellable via cancelAnimationFrame\n *\n * @memberof Timers:requestAnimationFrame\n * @alias requestAnimationFrame\n * @see raf\n * @see cancelAnimationFrame\n * @see caf\n * @example\n * const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; });\n */\nexport function requestAnimationFrame(callback){\n\tassert(isFunction(callback), `${MODULE_NAME}:requestAnimationFrame | callback is no function`);\n\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t\t?? function(callback){ return schedule(16, callback); }\n\t;\n\n\treturn raf(callback);\n}\n\n\n\n/**\n * @namespace Timers:cancelAnimationFrame\n */\n\n/**\n * This is a simple streamlined, vendor-cascading version of window.cancelAnimationFrame.\n *\n * @param {Number} id - either the id of the requestAnimationFrame or its timeout fallback\n *\n * @memberof Timers:cancelAnimationFrame\n * @alias cancelAnimationFrame\n * @see requestAnimationFrame\n * @see raf\n * @see caf\n * @example\n * cancelAnimationFrame(requestAnimationFrame(function(){ window.body.style.opacity = 0; }));\n */\nexport function cancelAnimationFrame(id){\n\tconst raf = window.requestAnimationFrame\n\t\t?? window.webkitRequestAnimationFrame\n\t\t?? window.mozRequestAnimationFrame\n\t\t?? window.msRequestAnimationFrame\n\t;\n\n\tlet caf = window.cancelAnimationFrame\n\t\t?? window.mozCancelAnimationFrame\n\t;\n\n\tif( !hasValue(raf) ){\n\t\tcaf = countermand;\n\t}\n\n\treturn caf(id);\n}\n\n\n\n/**\n * @namespace Timers:waitForRepaint\n */\n\n/**\n * This function has the purpose to offer a safe execution slot for code depending on an up-to-date rendering state of\n * the DOM after a change to styles for example. Let's say you add a class to an element and right in the next line\n * you'll want to read a layout attribute like width or height from it. This might fail, because there is no guarantee\n * the browser actually already applied the new styles to be read from the DOM.\n *\n * To wait safely for the new DOM state this method works with two stacked requestAnimationFrame calls.\n *\n * Since requestAnimationFrame always happens _before_ a repaint, two stacked calls ensure, that there has to be a\n * repaint between them.\n *\n * @param {Function} callback - the code to execute once the browser performed a repaint\n * @throws error if callback is not a function\n * @return {Object} dictionary of ids for the inner and outer request ids, outer gets assigned right away, while inner gets assigned after first callback => {outer : 1, inner : 2}\n *\n * @memberof Timers:waitForRepaint\n * @alias waitForRepaint\n * @see requestAnimationFrame\n * @see raf\n * @example\n * element.classList.add('special-stuff');\n * waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); });\n */\nexport function waitForRepaint(callback){\n\tassert(isFunction(callback), `${MODULE_NAME}:waitForRepaint | callback is no function`);\n\n\tconst ids = {};\n\n\tids.outer = requestAnimationFrame(function(){\n\t\tids.inner = requestAnimationFrame(callback);\n\t});\n\n\treturn ids;\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/dist/urls.js b/docs/examples/lib/annex/dist/urls.js index 8a03bff2..4907a6f5 100644 --- a/docs/examples/lib/annex/dist/urls.js +++ b/docs/examples/lib/annex/dist/urls.js @@ -1,5 +1,5 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Urls diff --git a/docs/examples/lib/annex/dist/viewport.js b/docs/examples/lib/annex/dist/viewport.js index d8e3f7eb..bf345f2a 100644 --- a/docs/examples/lib/annex/dist/viewport.js +++ b/docs/examples/lib/annex/dist/viewport.js @@ -1,8 +1,8 @@ /*! - * @oktarintentakel/annex v0.1.5-beta + * @oktarintentakel/annex v0.1.6-beta */ /*! * Module Viewport */ -const MODULE_NAME="Viewport";import{hasValue,orDefault,isA,isElement,Deferred,assert}from"./basic.js";import{EasingFunctions}from"./animation.js";import{requestAnimationFrame}from"./timers.js";export function isInViewport(t,e=!1){let o,n;e=orDefault(e,!1,"bool");try{o=t.getBoundingClientRect()}catch(t){return!0}return n=e?{top:0,right:window.innerWidth,bottom:window.innerHeight,left:0}:{top:1-(o.bottom-o.top),right:window.innerWidth+(o.right-o.left)+1,bottom:window.innerHeight+(o.bottom-o.top)+1,left:1-(o.right-o.left)},o.top>=n.top&&o.right<=n.right&&o.left>=n.left&&o.bottom<=n.bottom}export function scrollTo(t,e=1e3,o=0,n="easeInOutCubic",i=!1,r=!1){e=orDefault(e,1e3,"int"),o=orDefault(o,0,"int"),n=orDefault(n,"easeInOutCubic","str"),i=orDefault(i,!1,"bool"),r=orDefault(r,!1,"bool"),assert(isElement(t)||isA(t,"window"),"Viewport:scrollTo | element unusable"),assert(e>0,"Viewport:scrollTo | durationMs must be > 0"),n=isA(EasingFunctions[n],"function")?EasingFunctions[n]:EasingFunctions.easeInOutCubic;const s=new Deferred,l=t.self===t;let u=!l&&isInViewport(t,!0);try{t.getBoundingClientRect()}catch(t){u=!1}if(i||!u){let i,u,a=!1;const c=window.pageYOffset;u=l?o:window.pageYOffset+t.getBoundingClientRect().top-Math.round(window.innerHeight/2)+o;const w=u-c,f=function(t){if(!a){hasValue(i)||(i=t);const o=t-i,r=n(Math.min(o/e,1));window.scrollTo(0,c+w*r),o=n.top&&o.right<=n.right&&o.left>=n.left&&o.bottom<=n.bottom}export function scrollTo(t,e=1e3,o=0,n="easeInOutCubic",i=!1,r=!1){e=orDefault(e,1e3,"int"),o=orDefault(o,0,"int"),n=orDefault(n,"easeInOutCubic","str"),i=orDefault(i,!1,"bool"),r=orDefault(r,!1,"bool"),assert(isElement(t)||isWindow(t),"Viewport:scrollTo | element unusable"),assert(e>0,"Viewport:scrollTo | durationMs must be > 0"),n=isFunction(EasingFunctions[n])?EasingFunctions[n]:EasingFunctions.easeInOutCubic;const s=new Deferred,l=t.self===t;let u=!l&&isInViewport(t,!0);try{t.getBoundingClientRect()}catch(t){u=!1}if(i||!u){let i,u,a=!1;const c=window.pageYOffset;u=l?o:window.pageYOffset+t.getBoundingClientRect().top-Math.round(window.innerHeight/2)+o;const w=u-c,f=function(t){if(!a){hasValue(i)||(i=t);const o=t-i,r=n(Math.min(o/e,1));window.scrollTo(0,c+w*r),o= viewportBounds.top &&\n\t\tbb.right <= viewportBounds.right &&\n\t\tbb.left >= viewportBounds.left &&\n\t\tbb.bottom <= viewportBounds.bottom\n\t);\n}\n\n\n\n/**\n * @namespace Viewport:scrollTo\n */\n\n/**\n * Scrolls the viewport to the element's position (first pixel at half viewport height).\n * Does not do anything if target element is already fully in viewport, unless scrollEvenIfFullyInViewport is set to\n * true. Uses getBoundingClientRect to measure viewport check, scrolls always if missing.\n *\n * If you use this function on a window, the offset is directly used as scrollTop, so this function may also be used for\n * things like back to top buttons.\n *\n * Scrolls may be cancelled by setting cancelOnUserScroll to true, but keep in mind, that this will only work\n * with mousewheels and (maybe) touchpads on modern browsers. No keyboard or scrollbar support yet.\n * The root of the problem is that a user scroll is indistinguishable from a js-triggered scroll,\n * since both trigger the scroll event and look exactly the same. So we have to use exotic\n * and specific events like mousewheel and DOMMouseScroll. So, please, use cancelOnUserScroll only\n * as a convenience option and not as a must.\n *\n *\n * @param {HTMLElement|Window} element - the element to scroll to or the window to scroll within\n * @param {?Number} [durationMs=1000] - duration of the scrolling animation\n * @param {?Number} [offset=0] - offset from the viewport center to apply to the end position\n * @param {?String} [easing='easeInOutCubic'] - easing function to use, can be any of Animation.EasingFunctions\n * @param {?Boolean} [scrollEvenIfFullyInViewport=false] - if true, forces method to always scroll no matter the element's position\n * @param {?Boolean} [cancelOnUserScroll=false] - if true, scrolling animation will immediately be canceled on manual user scroll, return value will not resolve in that case\n * @throws error if element is not usable or if durationMs is <= 0\n * @returns {Deferred} resolves when scroll complete, rejects if scroll fails or is cancelled\n *\n * @memberof Viewport:scrollTo\n * @alias scrollTo\n * @see EasingFunctions\n * @example\n * document.querySelector('a.jumpitem').addEventListener('click', function(){ scrollTo(document.querySelector('.jumptarget'), function(){ alert('scrolled!'); }, 500, -100, true); });\n * scrollTo(document.querySelector('.jumptarget'), function(){ alert('Not triggered if user uses mousewheel.'); }, 5000, -0, false, true);\n * scrollTo(window, null, 500, 0, false, true);\n */\nexport function scrollTo(element, durationMs=1000, offset=0, easing='easeInOutCubic', scrollEvenIfFullyInViewport=false, cancelOnUserScroll=false){\n\tdurationMs = orDefault(durationMs, 1000, 'int');\n\toffset = orDefault(offset, 0, 'int');\n\teasing = orDefault(easing, 'easeInOutCubic', 'str');\n\tscrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool');\n\tcancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool');\n\n\tassert(isElement(element) || isA(element, 'window'), `${MODULE_NAME}:scrollTo | element unusable`);\n\tassert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`);\n\n\tif( !isA(EasingFunctions[easing], 'function') ){\n\t\teasing = EasingFunctions.easeInOutCubic;\n\t} else {\n\t\teasing = EasingFunctions[easing];\n\t}\n\n\tconst\n\t\tres = new Deferred(),\n\t\telementIsWindow = (element.self === element)\n\t;\n\n\t// the window itself is considered not to be in viewport\n\tlet elementInViewport = elementIsWindow ? false : isInViewport(element, true);\n\n\t// in this case missing support for bounding rects should result in scrolling\n\ttry {\n\t\telement.getBoundingClientRect();\n\t} catch(err){\n\t\telementInViewport = false;\n\t}\n\n\tif( scrollEvenIfFullyInViewport || !elementInViewport ){\n\t\tlet start, targetY, cancelled = false;\n\t\tconst startY = window.pageYOffset;\n\n\t\tif( elementIsWindow ){\n\t\t\ttargetY = offset;\n\t\t} else {\n\t\t\ttargetY = window.pageYOffset + element.getBoundingClientRect().top - Math.round(window.innerHeight / 2) + offset;\n\t\t}\n\n\t\tconst\n\t\t\tdiff = targetY - startY,\n\t\t\tfScroll = function(timestamp){\n\t\t\t\tif( !cancelled ){\n\t\t\t\t\tif( !hasValue(start) ){\n\t\t\t\t\t\tstart = timestamp;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst\n\t\t\t\t\t\ttime = timestamp - start,\n\t\t\t\t\t\tprogress = easing(Math.min(time / durationMs, 1))\n\t\t\t\t\t;\n\n\t\t\t\t\twindow.scrollTo(0, startY + (diff * progress));\n\n\t\t\t\t\tif( (time < durationMs) && (progress < 1) ){\n\t\t\t\t\t\trequestAnimationFrame(fScroll)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres.resolve();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t;\n\n\t\tif( cancelOnUserScroll ){\n\t\t\tconst fCancelScroll = function(){\n\t\t\t\tcancelled = true;\n\t\t\t\tres.reject(new Error('cancelled'));\n\t\t\t\twindow.removeEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\t\twindow.removeEventListener('mousewheel', fCancelScroll);\n\t\t\t};\n\n\t\t\twindow.addEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\twindow.addEventListener('mousewheel', fCancelScroll);\n\t\t}\n\n\t\tif( diff !== 0 ){\n\t\t\trequestAnimationFrame(fScroll);\n\t\t}\n\t}\n\n\treturn res;\n}\n"]} \ No newline at end of file +{"version":3,"file":"viewport.js","names":["MODULE_NAME","hasValue","orDefault","isWindow","isFunction","isElement","Deferred","assert","EasingFunctions","requestAnimationFrame","isInViewport","element","mustBeFullyInside","bb","viewportBounds","getBoundingClientRect","err","top","right","window","innerWidth","bottom","innerHeight","left","scrollTo","durationMs","offset","easing","scrollEvenIfFullyInViewport","cancelOnUserScroll","easeInOutCubic","res","elementIsWindow","self","elementInViewport","start","targetY","cancelled","startY","pageYOffset","Math","round","diff","fScroll","timestamp","time","progress","min","resolve","fCancelScroll","reject","Error","removeEventListener","addEventListener"],"sources":["viewport.js"],"mappings":";;;AAQA,MAAMA,YAAc,kBAMZC,SAAUC,UAAWC,SAAUC,WAAYC,UAAWC,SAAUC,WAAa,oBAC7EC,oBAAsB,wBACtBC,0BAA4B,qBA0B7B,SAASC,aAAaC,EAASC,GAAkB,GAGvD,IAAIC,EAQAC,EAVJF,EAAoBV,UAAUU,GAAmB,EAAO,QAGxD,IACCC,EAAKF,EAAQI,uBAId,CAHE,MAAMC,GAEP,OAAO,CACR,CAmBA,OAfCF,EADGF,EACc,CAChBK,IAAK,EACLC,MAAQC,OAAOC,WACfC,OAASF,OAAOG,YAChBC,KAAO,GAGS,CAChBN,IAA8B,GAAtBJ,EAAGQ,OAASR,EAAGI,KACvBC,MAASC,OAAOC,YAAcP,EAAGK,MAAQL,EAAGU,MAAS,EACrDF,OAAUF,OAAOG,aAAeT,EAAGQ,OAASR,EAAGI,KAAQ,EACvDM,KAA+B,GAAtBV,EAAGK,MAAQL,EAAGU,OAKxBV,EAAGI,KAAOH,EAAeG,KACzBJ,EAAGK,OAASJ,EAAeI,OAC3BL,EAAGU,MAAQT,EAAeS,MAC1BV,EAAGQ,QAAUP,EAAeO,MAE9B,QAyCO,SAASG,SAASb,EAASc,EAAW,IAAMC,EAAO,EAAGC,EAAO,iBAAkBC,GAA4B,EAAOC,GAAmB,GAC3IJ,EAAavB,UAAUuB,EAAY,IAAM,OACzCC,EAASxB,UAAUwB,EAAQ,EAAG,OAC9BC,EAASzB,UAAUyB,EAAQ,iBAAkB,OAC7CC,EAA8B1B,UAAU0B,GAA6B,EAAO,QAC5EC,EAAqB3B,UAAU2B,GAAoB,EAAO,QAE1DtB,OAAOF,UAAUM,IAAYR,SAASQ,GAAU,wCAChDJ,OAAOkB,EAAa,EAAG,8CAKtBE,EAHIvB,WAAWI,gBAAgBmB,IAGtBnB,gBAAgBmB,GAFhBnB,gBAAgBsB,eAK1B,MACCC,EAAM,IAAIzB,SACV0B,EAAmBrB,EAAQsB,OAAStB,EAIrC,IAAIuB,GAAoBF,GAA0BtB,aAAaC,GAAS,GAGxE,IACCA,EAAQI,uBAGT,CAFE,MAAMC,GACPkB,GAAoB,CACrB,CAEA,GAAIN,IAAgCM,EAAmB,CACtD,IAAIC,EAAOC,EAASC,GAAY,EAChC,MAAMC,EAASnB,OAAOoB,YAGrBH,EADGJ,EACON,EAEAP,OAAOoB,YAAc5B,EAAQI,wBAAwBE,IAAMuB,KAAKC,MAAMtB,OAAOG,YAAc,GAAKI,EAG3G,MACCgB,EAAON,EAAUE,EACjBK,EAAU,SAASC,GAClB,IAAKP,EAAW,CACVpC,SAASkC,KACbA,EAAQS,GAGT,MACCC,EAAOD,EAAYT,EACnBW,EAAWnB,EAAOa,KAAKO,IAAIF,EAAOpB,EAAY,IAG/CN,OAAOK,SAAS,EAAGc,EAAUI,EAAOI,GAE/BD,EAAOpB,GAAgBqB,EAAW,EACtCrC,sBAAsBkC,GAEtBZ,EAAIiB,SAEN,CACD,EAGD,GAAInB,EAAoB,CACvB,MAAMoB,EAAgB,WACrBZ,GAAY,EACZN,EAAImB,OAAO,IAAIC,MAAM,cACrBhC,OAAOiC,oBAAoB,iBAAkBH,GAC7C9B,OAAOiC,oBAAoB,aAAcH,EAC1C,EAEA9B,OAAOkC,iBAAiB,iBAAkBJ,GAC1C9B,OAAOkC,iBAAiB,aAAcJ,EACvC,CAEa,IAATP,GACHjC,sBAAsBkC,EAExB,CAEA,OAAOZ,CACR","sourcesContent":["/*!\n * Module Viewport\n */\n\n/**\n * @namespace Viewport\n */\n\nconst MODULE_NAME = 'Viewport';\n\n\n\n//###[ IMPORTS ]########################################################################################################\n\nimport {hasValue, orDefault, isWindow, isFunction, isElement, Deferred, assert} from './basic.js';\nimport {EasingFunctions} from './animation.js';\nimport {requestAnimationFrame} from './timers.js';\n\n\n\n//###[ EXPORTS ]########################################################################################################\n\n/**\n * @namespace Viewport:isInViewport\n */\n\n/**\n * Returns if the current element is visible in the window's viewport at the moment.\n * This method uses getBoundingClientRect(), which has to be supported by the browser, otherwise\n * the method will always return true.\n *\n * @param {HTMLElement} element - the element to check\n * @param {?Boolean} [mustBeFullyInside=false] - defines if the element has to be fully enclosed in the viewport, default is false\n * @returns {Boolean} true if in viewport\n *\n * @memberof Viewport:isInViewport\n * @alias isInViewport\n * @example\n * if( isInViewport(document.querySelector('div.moving'), true) ){\n * ...\n * }\n */\nexport function isInViewport(element, mustBeFullyInside=false){\n\tmustBeFullyInside = orDefault(mustBeFullyInside, false, 'bool');\n\n\tlet bb;\n\ttry {\n\t\tbb = element.getBoundingClientRect();\n\t} catch(err){\n\t\t// if we cannot calculate position, we must assume the element is in\n\t\treturn true;\n\t}\n\n\tlet viewportBounds;\n\tif( mustBeFullyInside ){\n\t\tviewportBounds = {\n\t\t\ttop: 0,\n\t\t\tright : window.innerWidth,\n\t\t\tbottom : window.innerHeight,\n\t\t\tleft : 0\n\t\t};\n\t} else {\n\t\tviewportBounds = {\n\t\t\ttop : -(bb.bottom - bb.top) + 1,\n\t\t\tright : (window.innerWidth + (bb.right - bb.left)) + 1,\n\t\t\tbottom : (window.innerHeight + (bb.bottom - bb.top)) + 1,\n\t\t\tleft : -(bb.right - bb.left) + 1\n\t\t};\n\t}\n\n\treturn (\n\t\tbb.top >= viewportBounds.top &&\n\t\tbb.right <= viewportBounds.right &&\n\t\tbb.left >= viewportBounds.left &&\n\t\tbb.bottom <= viewportBounds.bottom\n\t);\n}\n\n\n\n/**\n * @namespace Viewport:scrollTo\n */\n\n/**\n * Scrolls the viewport to the element's position (first pixel at half viewport height).\n * Does not do anything if target element is already fully in viewport, unless scrollEvenIfFullyInViewport is set to\n * true. Uses getBoundingClientRect to measure viewport check, scrolls always if missing.\n *\n * If you use this function on a window, the offset is directly used as scrollTop, so this function may also be used for\n * things like back to top buttons.\n *\n * Scrolls may be cancelled by setting cancelOnUserScroll to true, but keep in mind, that this will only work\n * with mousewheels and (maybe) touchpads on modern browsers. No keyboard or scrollbar support yet.\n * The root of the problem is that a user scroll is indistinguishable from a js-triggered scroll,\n * since both trigger the scroll event and look exactly the same. So we have to use exotic\n * and specific events like mousewheel and DOMMouseScroll. So, please, use cancelOnUserScroll only\n * as a convenience option and not as a must.\n *\n *\n * @param {HTMLElement|Window} element - the element to scroll to or the window to scroll within\n * @param {?Number} [durationMs=1000] - duration of the scrolling animation\n * @param {?Number} [offset=0] - offset from the viewport center to apply to the end position\n * @param {?String} [easing='easeInOutCubic'] - easing function to use, can be any of Animation.EasingFunctions\n * @param {?Boolean} [scrollEvenIfFullyInViewport=false] - if true, forces method to always scroll no matter the element's position\n * @param {?Boolean} [cancelOnUserScroll=false] - if true, scrolling animation will immediately be canceled on manual user scroll, return value will not resolve in that case\n * @throws error if element is not usable or if durationMs is <= 0\n * @returns {Deferred} resolves when scroll complete, rejects if scroll fails or is cancelled\n *\n * @memberof Viewport:scrollTo\n * @alias scrollTo\n * @see EasingFunctions\n * @example\n * document.querySelector('a.jumpitem').addEventListener('click', function(){ scrollTo(document.querySelector('.jumptarget'), function(){ alert('scrolled!'); }, 500, -100, true); });\n * scrollTo(document.querySelector('.jumptarget'), function(){ alert('Not triggered if user uses mousewheel.'); }, 5000, -0, false, true);\n * scrollTo(window, null, 500, 0, false, true);\n */\nexport function scrollTo(element, durationMs=1000, offset=0, easing='easeInOutCubic', scrollEvenIfFullyInViewport=false, cancelOnUserScroll=false){\n\tdurationMs = orDefault(durationMs, 1000, 'int');\n\toffset = orDefault(offset, 0, 'int');\n\teasing = orDefault(easing, 'easeInOutCubic', 'str');\n\tscrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool');\n\tcancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool');\n\n\tassert(isElement(element) || isWindow(element), `${MODULE_NAME}:scrollTo | element unusable`);\n\tassert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`);\n\n\tif( !isFunction(EasingFunctions[easing]) ){\n\t\teasing = EasingFunctions.easeInOutCubic;\n\t} else {\n\t\teasing = EasingFunctions[easing];\n\t}\n\n\tconst\n\t\tres = new Deferred(),\n\t\telementIsWindow = (element.self === element)\n\t;\n\n\t// the window itself is considered not to be in viewport\n\tlet elementInViewport = elementIsWindow ? false : isInViewport(element, true);\n\n\t// in this case missing support for bounding rects should result in scrolling\n\ttry {\n\t\telement.getBoundingClientRect();\n\t} catch(err){\n\t\telementInViewport = false;\n\t}\n\n\tif( scrollEvenIfFullyInViewport || !elementInViewport ){\n\t\tlet start, targetY, cancelled = false;\n\t\tconst startY = window.pageYOffset;\n\n\t\tif( elementIsWindow ){\n\t\t\ttargetY = offset;\n\t\t} else {\n\t\t\ttargetY = window.pageYOffset + element.getBoundingClientRect().top - Math.round(window.innerHeight / 2) + offset;\n\t\t}\n\n\t\tconst\n\t\t\tdiff = targetY - startY,\n\t\t\tfScroll = function(timestamp){\n\t\t\t\tif( !cancelled ){\n\t\t\t\t\tif( !hasValue(start) ){\n\t\t\t\t\t\tstart = timestamp;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst\n\t\t\t\t\t\ttime = timestamp - start,\n\t\t\t\t\t\tprogress = easing(Math.min(time / durationMs, 1))\n\t\t\t\t\t;\n\n\t\t\t\t\twindow.scrollTo(0, startY + (diff * progress));\n\n\t\t\t\t\tif( (time < durationMs) && (progress < 1) ){\n\t\t\t\t\t\trequestAnimationFrame(fScroll)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres.resolve();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t;\n\n\t\tif( cancelOnUserScroll ){\n\t\t\tconst fCancelScroll = function(){\n\t\t\t\tcancelled = true;\n\t\t\t\tres.reject(new Error('cancelled'));\n\t\t\t\twindow.removeEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\t\twindow.removeEventListener('mousewheel', fCancelScroll);\n\t\t\t};\n\n\t\t\twindow.addEventListener('DOMMouseScroll', fCancelScroll);\n\t\t\twindow.addEventListener('mousewheel', fCancelScroll);\n\t\t}\n\n\t\tif( diff !== 0 ){\n\t\t\trequestAnimationFrame(fScroll);\n\t\t}\n\t}\n\n\treturn res;\n}\n"]} \ No newline at end of file diff --git a/docs/examples/lib/annex/source/arrays.js b/docs/examples/lib/annex/source/arrays.js index 4c7d6da7..01638d11 100644 --- a/docs/examples/lib/annex/source/arrays.js +++ b/docs/examples/lib/annex/source/arrays.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Arrays'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, isPlainObject, orDefault} from './basic.js'; +import {assert, isArray, isNumber, isString, isMap, isSet, isPlainObject, orDefault} from './basic.js'; @@ -75,9 +75,9 @@ import {assert, isA, isPlainObject, orDefault} from './basic.js'; * => [1] */ export function removeFrom(target, from, to=null){ - assert(isA(target, 'array'), `${MODULE_NAME}:remove | target is no array`); + assert(isArray(target), `${MODULE_NAME}:remove | target is no array`); - if( isA(from, 'number') && (to !== true) ){ + if( isNumber(from) && (to !== true) ){ from = parseInt(from, 10); to = orDefault(to, null, 'int'); @@ -86,7 +86,7 @@ export function removeFrom(target, from, to=null){ target.length = (from < 0) ? (target.length + from) : from; return target.concat(rest); - } else if( isA(from, 'string') ){ + } else if( isString(from) ){ return target.reduce((reducedArray, item) => { if( `${item}` !== from ){ reducedArray.push(item); @@ -97,9 +97,9 @@ export function removeFrom(target, from, to=null){ let fromList; if( isPlainObject(from) ){ fromList = Object.values(from); - } else if( isA(from, 'map') ){ + } else if( isMap(from) ){ fromList = Array.from(from.values()); - } else if( isA(from, 'set') ){ + } else if( isSet(from) ){ fromList = Array.from(from.values()); } else { fromList = Array.from(from); diff --git a/docs/examples/lib/annex/source/basic.js b/docs/examples/lib/annex/source/basic.js index 0deb5bed..f4ddcf9d 100644 --- a/docs/examples/lib/annex/source/basic.js +++ b/docs/examples/lib/annex/source/basic.js @@ -70,7 +70,7 @@ export function assert(condition, message){ * if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); } */ export function attempt(closure){ - assert(isA(closure, 'function'), `${MODULE_NAME}:attempt | closure is no function`); + assert(isFunction(closure), `${MODULE_NAME}:attempt | closure is no function`); try { closure(); @@ -158,7 +158,7 @@ export function hasValue(){ * => null */ export function size(target, countStringCharacters=true){ - if( isA(target?.values, 'function') ) return Array.from(target.values()).length; + if( isFunction(target?.values) ) return Array.from(target.values()).length; let res; switch( getType(target) ){ @@ -224,14 +224,14 @@ export function isEmpty(){ ; Array.from(arguments).forEach(obj => { - if( isA(obj?.__additionalEmptyValues__, 'array') ){ + if( isArray(obj?.__additionalEmptyValues__) ){ emptyValues = emptyValues.concat(obj.__additionalEmptyValues__); } }); emptyValues = Array.from(new Set(emptyValues)); Array.from(arguments).forEach(obj => { - if( res && !isA(obj?.__additionalEmptyValues__, 'array') ){ + if( res && !isArray(obj?.__additionalEmptyValues__) ){ res = emptyValues.includes(obj); if( !res ){ @@ -318,7 +318,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty if( hasValue(caster) ){ if( - !isA(caster, 'function') + !isFunction(caster) && ([ 'str', 'string', 'int', 'integer', @@ -340,7 +340,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty } else if( ['arr', 'array'].includes(caster) ){ caster = function(value){ return [].concat(value); }; } - } else if( !isA(caster, 'function') ){ + } else if( !isFunction(caster) ){ caster = function(value){ return value; }; } } else { @@ -363,7 +363,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty /** * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on - * useful frontend types like "htmldocument", "htmlelement" and "nodelist" + * useful frontend types like "htmldocument", "htmlelement", "htmlcollection" and "nodelist" * * Types: * - "undefined" @@ -387,6 +387,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty * - "weakmap" * - "htmldocument" * - "htmlelement" + * - "htmlcollection" * - "nodelist" * - "window" * @@ -411,7 +412,7 @@ export function getType(value) { if( /^html.*element$/.test(deepType) ) return 'htmlelement'; if( /^.*iterator$/.test(deepType) ) return 'iterator'; - return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/) + return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/) ? deepType : ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value ; @@ -461,6 +462,7 @@ export function isA(value, type){ 'weakmap', 'htmldocument', 'htmlelement', + 'htmlcollection', 'nodelist', 'window' ].includes(`${type}`.toLowerCase()) @@ -474,6 +476,80 @@ export function isA(value, type){ +/** + * @namespace Basic:isBoolean + */ + +/** + * Returns if a value is a boolean value. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a boolean + * + * @memberof Basic:isBoolean + * @alias isBoolean + * @example + * if( isBoolean(val) ){ + * console.log('val must be either true or false'); + * } + */ +export function isBoolean(value){ + return isA(value, 'boolean'); +} + + + +/** + * @namespace Basic:isNumber + */ + +/** + * Returns if a value is a number. + * + * Hint: to check numbers in more detail, use isInt, isFloat and isNaN + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a number + * + * @memberof Basic:isNumber + * @alias isNumber + * @see isInt + * @see isFloat + * @see isNaN + * @example + * if( isNumber(val) ){ + * result = val * 5; + * } + */ +export function isNumber(value){ + return isA(value, 'number'); +} + + + +/** + * @namespace Basic:isBigInt + */ + +/** + * Returns if a value is a BigInt value. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a BigInt + * + * @memberof Basic:isBigInt + * @alias isBigInt + * @example + * if( isBigInt(val) ){ + * console.log('this is a really huge number!'); + * } + */ +export function isBigInt(value){ + return isA(value, 'bigint'); +} + + + /** * @namespace Basic:isInt */ @@ -525,6 +601,137 @@ export function isFloat(floatVal){ +/** + * @namespace Basic:isNaN + */ + +/** + * Returns if an expression is NaN or not. + * This method employs two different approaches: + * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something. + * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being + * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which + * inspects the expression, tries to cast or parse a number from it and returns the result. + * + * @param {*} expression - the expression to check + * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality + * @returns {Boolean} true if expression is NaN + * + * @memberof Basic:isNaN + * @alias isNaN + * @example + * if( !isNaN(suspiciousCalculatedValue) ){ + * return suspiciousCalculatedValue * 3; + * } + */ +export function isNaN(expression, checkForIdentity=true){ + checkForIdentity = orDefault(checkForIdentity, true, 'bool'); + + if( checkForIdentity ){ + return expression !== expression; + } else { + return isNaN(expression); + } +} + + + +/** + * @namespace Basic:isString + */ + +/** + * Returns if a value is a string. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a string + * + * @memberof Basic:isString + * @alias isString + * @example + * if( isString(val) ){ + * return prefix+val; + * } + */ +export function isString(value){ + return isA(value, 'string'); +} + + + +/** + * @namespace Basic:isSymbol + */ + +/** + * Returns if a value is a symbol. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a symbol + * + * @memberof Basic:isSymbol + * @alias isSymbol + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol + * @example + * if( isSymbol(val) ){ + * return val.description; + * } + */ +export function isSymbol(value){ + return isA(value, 'symbol'); +} + + + +/** + * @namespace Basic:isFunction + */ + +/** + * Returns if a value is a function. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a function + * + * @memberof Basic:isFunction + * @alias isFunction + * @example + * if( isFunction(val) ){ + * val(); + * } + */ +export function isFunction(value){ + return isA(value, 'function'); +} + + + +/** + * @namespace Basic:isObject + */ + +/** + * Returns if a value is an object. + * + * Hint: if you explicitly want to check for a plain object, use isPlainObject + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an object + * + * @memberof Basic:isObject + * @alias isObject + * @see isPlainObject + * @example + * if( isObject(val) ){ + * val.newProperty = 'foobar'; + * } + */ +export function isObject(value){ + return isA(value, 'object'); +} + + + /** * @namespace Basic:isPlainObject */ @@ -549,7 +756,7 @@ export function isFloat(floatVal){ * const isParameterConfigObject = isPlainObject(param); */ export function isPlainObject(value){ - return isA(value, 'object') + return isObject(value) && hasValue(value) && (value.constructor === Object) && Object.prototype.toString.call(value) === '[object Object]' @@ -559,36 +766,260 @@ export function isPlainObject(value){ /** - * @namespace Basic:isNaN + * @namespace Basic:isArray */ /** - * Returns if an expression is NaN or not. - * This method employs two different approaches: - * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something. - * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being - * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which - * inspects the expression, tries to cast or parse a number from it and returns the result. + * Returns if a value is an array. * - * @param {*} expression - the expression to check - * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality - * @returns {Boolean} true if expression is NaN + * @param {*} value - the value to check + * @returns {Boolean} true if value is an array * - * @memberof Basic:isNaN - * @alias isNaN + * @memberof Basic:isArray + * @alias isArray * @example - * if( !isNaN(suspiciousCalculatedValue) ){ - * return suspiciousCalculatedValue * 3; + * if( isArray(val) ){ + * val.push('foobar'); * } */ -export function isNaN(expression, checkForIdentity=true){ - checkForIdentity = orDefault(checkForIdentity, true, 'bool'); +export function isArray(value){ + return isA(value, 'array'); +} - if( checkForIdentity ){ - return expression !== expression; - } else { - return isNaN(expression); - } + + +/** + * @namespace Basic:isDate + */ + +/** + * Returns if a value is a date. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a date + * + * @memberof Basic:isDate + * @alias isDate + * @example + * if( isDate(val) ){ + * return val.toISOString(); + * } + */ +export function isDate(value){ + return isA(value, 'date'); +} + + + +/** + * @namespace Basic:isError + */ + +/** + * Returns if a value is an error. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an error + * + * @memberof Basic:isError + * @alias isError + * @example + * if( isError(val) ){ + * return val.message; + * } + */ +export function isError(value){ + return isA(value, 'error'); +} + + + +/** + * @namespace Basic:isGenerator + */ + +/** + * Returns if a value is a generator. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a generator + * + * @memberof Basic:isGenerator + * @alias isGenerator + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator + * @example + * if( isGenerator(val) ){ + * return val.return(val.next().value); + * } + */ +export function isGenerator(value){ + return isA(value, 'generator'); +} + + + +/** + * @namespace Basic:isIterator + */ + +/** + * Returns if a value is an iterator. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an iterator + * + * @memberof Basic:isIterator + * @alias isIterator + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator + * @example + * if( isIterator(val) ){ + * return val.next().value; + * } + */ +export function isIterator(value){ + return isA(value, 'iterator'); +} + + + +/** + * @namespace Basic:isRegExp + */ + +/** + * Returns if a value is a regular expression. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a regular expression + * + * @memberof Basic:isRegExp + * @alias isRegExp + * @example + * if( isRegExp(val) ){ + * return val.test('foobar'); + * } + */ +export function isRegExp(value){ + return isA(value, 'regexp'); +} + + + +/** + * @namespace Basic:isSet + */ + +/** + * Returns if a value is a set. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a set + * + * @memberof Basic:isSet + * @alias isSet + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set + * @example + * if( isSet(val) ){ + * return val.has('foobar'); + * } + */ +export function isSet(value){ + return isA(value, 'set'); +} + + + +/** + * @namespace Basic:isWeakSet + */ + +/** + * Returns if a value is a weak set. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a weak set + * + * @memberof Basic:isWeakSet + * @alias isWeakSet + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet + * @example + * if( isWeakSet(val) ){ + * return val.has(someSymbol); + * } + */ +export function isWeakSet(value){ + return isA(value, 'weakset'); +} + + + +/** + * @namespace Basic:isMap + */ + +/** + * Returns if a value is a map. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a map + * + * @memberof Basic:isMap + * @alias isMap + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map + * @example + * if( isMap(val) ){ + * return val.get('foobar'); + * } + */ +export function isMap(value){ + return isA(value, 'map'); +} + + + +/** + * @namespace Basic:isWeakMap + */ + +/** + * Returns if a value is a weak map. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a weak map + * + * @memberof Basic:isWeakMap + * @alias isWeakMap + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap + * @example + * if( isWeakMap(val) ){ + * return val.get('foobar'); + * } + */ +export function isWeakMap(value){ + return isA(value, 'weakmap'); +} + + + +/** + * @namespace Basic:isDocument + */ + +/** + * Returns if a value is an HTML document. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an HTML document + * + * @memberof Basic:isDocument + * @alias isDocument + * @example + * if( isDocument(val) ){ + * return val.body; + * } + */ +export function isDocument(value){ + return isA(value, 'htmldocument'); } @@ -618,6 +1049,77 @@ export function isElement(value){ +/** + * @namespace Basic:isCollection + */ + +/** + * Returns if a value is a collection of html elements. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a collection of html elements + * + * @memberof Basic:isCollection + * @alias isCollection + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection + * @example + * if( isCollection(val) ){ + * return val.item(0); + * } + */ +export function isCollection(value){ + return isA(value, 'htmlcollection'); +} + + + +/** + * @namespace Basic:isNodeList + */ + +/** + * Returns if a value is a node list. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a node list + * + * @memberof Basic:isNodeList + * @alias isNodeList + * @see https://developer.mozilla.org/en-US/docs/Web/API/NodeList + * @example + * if( isNodeList(val) ){ + * return val.item(0); + * } + */ +export function isNodeList(value){ + return isA(value, 'nodelist'); +} + + + +/** + * @namespace Basic:isWindow + */ + +/** + * Returns if a value is a window. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a window + * + * @memberof Basic:isWindow + * @alias isWindow + * @example + * if( isWindow(val) ){ + * return val.location.origin; + * } + */ +export function isWindow(value){ + return isA(value, 'window'); +} + + + /** * @namespace Basic:isEventTarget */ @@ -641,9 +1143,9 @@ export function isElement(value){ */ export function isEventTarget(value){ return hasValue(value) - && isA(value.addEventListener, 'function') - && isA(value.removeEventListener, 'function') - && isA(value.dispatchEvent, 'function') + && isFunction(value.addEventListener) + && isFunction(value.removeEventListener) + && isFunction(value.dispatchEvent) ; } @@ -909,7 +1411,7 @@ export class Observable { subscribe(subscription){ const __methodName__ = 'subscribe'; - assert(isA(subscription, 'function'), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`); + assert(isFunction(subscription), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`); if( this._subscriptions.indexOf(subscription) < 0 ){ this._subscriptions = [...this._subscriptions, subscription]; } diff --git a/docs/examples/lib/annex/source/context.js b/docs/examples/lib/annex/source/context.js index 1603c786..404f7787 100644 --- a/docs/examples/lib/annex/source/context.js +++ b/docs/examples/lib/annex/source/context.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Context'; //###[ IMPORTS ]######################################################################################################## -import {hasValue, isA, orDefault, Observable} from './basic.js'; +import {hasValue, isFunction, isArray, orDefault, Observable} from './basic.js'; import {throttle} from './functions.js'; import {reschedule} from './timers.js'; @@ -71,8 +71,8 @@ export let CURRENT_INTERACTION_TYPE; */ export function browserSupportsHistoryManipulation(){ return hasValue(window.history) - && isA(window.history.pushState, 'function') - && isA(window.history.replaceState, 'function') + && isFunction(window.history.pushState) + && isFunction(window.history.replaceState) ; } @@ -285,7 +285,7 @@ export function detectAppleDevice(additionalTest=null){ break; } - if( isA(additionalTest, 'function') ){ + if( isFunction(additionalTest) ){ deviceType = additionalTest(deviceType); } } @@ -320,7 +320,7 @@ export function getBrowserLanguage(fallbackLanguage=null){ if( hasValue(window.navigator.languages) ){ const browserLanguages = Array.from(window.navigator.languages); - if( isA(browserLanguages, 'array') && (browserLanguages.length > 0) ){ + if( isArray(browserLanguages) && (browserLanguages.length > 0) ){ language = `${browserLanguages[0]}`; } } @@ -394,7 +394,7 @@ export function getLocale(element=null, fallbackLanguage=null){ isFallback : false }; - let langAttr = isA(element.getAttribute, 'function') ? element.getAttribute('lang') : null; + let langAttr = isFunction(element.getAttribute) ? element.getAttribute('lang') : null; if( !hasValue(langAttr) && hasValue(fallbackLanguage) ){ langAttr = `${fallbackLanguage}`; locale.isFallback = true; diff --git a/docs/examples/lib/annex/source/cookies.js b/docs/examples/lib/annex/source/cookies.js index 5dd1894f..7b8385a1 100644 --- a/docs/examples/lib/annex/source/cookies.js +++ b/docs/examples/lib/annex/source/cookies.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Cookies'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, orDefault, hasValue} from './basic.js'; +import {assert, isDate, orDefault, hasValue} from './basic.js'; import {warn} from './logging.js'; @@ -96,7 +96,7 @@ function normalizeCookieOptions(options){ options = normalizedOptions; if( hasValue(options.expires) ){ - if( !isA(options.expires, 'date') ){ + if( !isDate(options.expires) ){ options.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000)); } options.expires = options.expires.toUTCString(); diff --git a/docs/examples/lib/annex/source/css.js b/docs/examples/lib/annex/source/css.js index b32edd29..a33a8188 100644 --- a/docs/examples/lib/annex/source/css.js +++ b/docs/examples/lib/annex/source/css.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'CSS'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js'; +import {assert, isNumber, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js'; import {maskForRegEx} from './strings.js'; @@ -82,7 +82,7 @@ export function applyStyles(element, styles, crossBrowser=false, returnCssStyleD } Object.entries({...styles}).forEach(([cssKey, cssValue]) => { - if( isA(cssValue, 'number') && (cssValue !== 0) ){ + if( isNumber(cssValue) && (cssValue !== 0) ){ styles[cssKey] = `${cssValue}px`; element.style.setProperty(cssKey, styles[cssKey]); } else if( !hasValue(cssValue) ){ diff --git a/docs/examples/lib/annex/source/elements.js b/docs/examples/lib/annex/source/elements.js index 9b144561..49e0457c 100644 --- a/docs/examples/lib/annex/source/elements.js +++ b/docs/examples/lib/annex/source/elements.js @@ -12,7 +12,18 @@ const MODULE_NAME = 'Elements'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, isSelector, isElement, hasValue, assert, size, Deferred} from './basic.js'; +import { + orDefault, + isString, + isFunction, + isPlainObject, + isSelector, + isElement, + hasValue, + assert, + size, + Deferred +} from './basic.js'; import {randomUuid} from './random.js'; import {clone} from './objects.js'; import {onDomReady} from './events.js'; @@ -408,7 +419,7 @@ export function getTextContent(target, onlyFirstLevel=false){ onlyFirstLevel = orDefault(onlyFirstLevel, false, 'bool'); - if( isA(target, 'string') ){ + if( isString(target) ){ target = createNode(target); } @@ -454,7 +465,7 @@ export function isInDom(node){ assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); - return isA(document.contains, 'function') ? document.contains(node) : document.body.contains(node); + return isFunction(document.contains) ? document.contains(node) : document.body.contains(node); } @@ -611,7 +622,7 @@ export function setData(node, dataSet, singleValue=null){ const appliedValues = {}; Object.entries(dataSet).forEach(([property, value]) => { - if( isA(value, 'function') ){ + if( isFunction(value) ){ value = value(); } @@ -857,7 +868,7 @@ export function findOne(node, selector='*'){ export function findTextNodes(node, filter=null, onlyFirstLevel=false){ const __methodName__ = 'findTextNodes'; - filter = isA(filter, 'function') ? filter : () => true; + filter = isFunction(filter) ? filter : () => true; onlyFirstLevel = orDefault(onlyFirstLevel, false, 'bool'); assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); @@ -939,7 +950,7 @@ export function prime(node, init, classChanges=null, markerAttributesName='prime markerAttributesName = orDefault(markerAttributesName, 'primed', 'str'); assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); - assert(isA(init, 'function'), `${MODULE_NAME}:${__methodName__} | init is not a function`); + assert(isFunction(init), `${MODULE_NAME}:${__methodName__} | init is not a function`); const deferred = new Deferred(); @@ -951,8 +962,8 @@ export function prime(node, init, classChanges=null, markerAttributesName='prime if( hasValue(initResult) - && isA(initResult.then, 'function') - && isA(initResult.catch, 'function') + && isFunction(initResult.then) + && isFunction(initResult.catch) ){ initResult .then(resolution => { deferred.resolve(resolution); }) diff --git a/docs/examples/lib/annex/source/events.js b/docs/examples/lib/annex/source/events.js index 6d6cb933..b3730b41 100644 --- a/docs/examples/lib/annex/source/events.js +++ b/docs/examples/lib/annex/source/events.js @@ -12,7 +12,22 @@ const MODULE_NAME = 'Events'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, isEventTarget, isPlainObject, isElement, orDefault, hasValue, isEmpty, isSelector} from './basic.js'; +import { + assert, + isFunction, + isString, + isArray, + isBoolean, + isObject, + isWindow, + isEventTarget, + isPlainObject, + isElement, + orDefault, + hasValue, + isEmpty, + isSelector +} from './basic.js'; import {slugify} from './strings.js'; import {removeFrom} from './arrays.js'; import {detectInteractionType} from './context.js'; @@ -85,7 +100,7 @@ function prepareEventMethodBaseParams(methodName, targets, events, handler, hand events = orDefault(events, [], 'arr'); assert(events.length > 0, `${MODULE_NAME}:${methodName} | no events provided`); if( !handlerIsOptional || hasValue(handler) ){ - assert(isA(handler, 'function'), `${MODULE_NAME}:${methodName} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${methodName} | handler is not a function`); } let @@ -94,7 +109,7 @@ function prepareEventMethodBaseParams(methodName, targets, events, handler, hand ; targets.forEach((target, targetIndex) => { - if( isA(target, 'string') ){ + if( isString(target) ){ const ancestor = (targetIndex > 0) ? targets[targetIndex - 1] : null; delegatedTargetsAreSelectorsAndHaveAncestor &&= isSelector(target) && isEventTarget(ancestor); } else { @@ -301,7 +316,7 @@ function createDelegatedHandler(delegation, handler){ : ( isEventTarget(e.syntheticTarget) || ( - isA(e.syntheticTarget, 'array') + isArray(e.syntheticTarget) && isSelector(e.syntheticTarget[1]) ) ? ( @@ -546,8 +561,8 @@ function createPauseAwareAction(managedHandler, nonPauseAwareAction){ * @private */ function compileEventListenerOptions(options){ - if( isA(options, 'boolean') ) return options; - if( !isA(options, 'object') ) return null; + if( isBoolean(options) ) return options; + if( !isObject(options) ) return null; const supportedOptions = {}; @@ -589,7 +604,7 @@ function createSyntheticEvent( eventOptions = isPlainObject(eventOptions) ? eventOptions : {}; let e; - if( isA(EventConstructor, 'function') ){ + if( isFunction(EventConstructor) ){ if( isPlainObject(payload) ){ console.warn(`${MODULE_NAME}:${__methodName__} | can't add payload to event "${EventConstructor.name}", skipping`); } @@ -610,7 +625,7 @@ function createSyntheticEvent( e.syntheticTarget = syntheticTarget; e.syntheticTargetElements = [syntheticTarget] } else if( - isA(syntheticTarget, 'array') + isArray(syntheticTarget) && isEventTarget(syntheticTarget[0]) && isSelector(syntheticTarget[1]) ){ @@ -651,10 +666,10 @@ function updateSwipeTouch(e){ * @private */ function resolvePostMessageTarget(target, method){ - target = isA(target, 'window') + target = isWindow(target) ? target : ( - isA(target?.contentWindow, 'window') + isWindow(target?.contentWindow) ? target.contentWindow : null ) @@ -1599,7 +1614,7 @@ export function onPostMessage(target, origin, messageType, handler){ origin = orDefault(origin, '*', 'str'); messageType = `${messageType}`; - assert(isA(handler, 'function'), `${MODULE_NAME}:${__methodName__} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${__methodName__} | handler is not a function`); if( !hasValue(POST_MESSAGE_MAP.get(target)) ){ POST_MESSAGE_MAP.set(target, {}); @@ -1666,7 +1681,7 @@ export function offPostMessage(target, origin=null, messageType=null, handler=nu tryNativeRemoval = orDefault(tryNativeRemoval, true, 'bool'); if( hasValue(handler) ){ - assert(isA(handler, 'function'), `${MODULE_NAME}:${__methodName__} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${__methodName__} | handler is not a function`); } let removedCount = 0; diff --git a/docs/examples/lib/annex/source/forms.js b/docs/examples/lib/annex/source/forms.js index 4d7ad120..e6475021 100644 --- a/docs/examples/lib/annex/source/forms.js +++ b/docs/examples/lib/annex/source/forms.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Forms'; //###[ IMPORTS ]######################################################################################################## -import {isA, isPlainObject, hasValue} from './basic.js'; +import {isFunction, isPlainObject, hasValue} from './basic.js'; @@ -74,9 +74,9 @@ export function formDataToObject(formDataOrForm){ // let's do duck-typing to allow polyfills if( - isA(formDataOrForm.append, 'function') - && isA(formDataOrForm.getAll, 'function') - && isA(formDataOrForm.entries, 'function') + isFunction(formDataOrForm.append) + && isFunction(formDataOrForm.getAll) + && isFunction(formDataOrForm.entries) ){ formData = formDataOrForm; } else { diff --git a/docs/examples/lib/annex/source/functions.js b/docs/examples/lib/annex/source/functions.js index cb9c9ee5..caf3ca1a 100644 --- a/docs/examples/lib/annex/source/functions.js +++ b/docs/examples/lib/annex/source/functions.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Functions'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, assert, hasValue} from './basic.js'; +import {orDefault, isFunction, isPlainObject, assert, hasValue} from './basic.js'; import {schedule, reschedule} from './timers.js'; @@ -52,7 +52,7 @@ export function throttle(ms, func, hasLeadingExecution=false, hasTrailingExecuti hasTrailingExecution = orDefault(hasTrailingExecution, false, 'bool'); assert(ms > 0, `${MODULE_NAME}:throttle | ms must be > 0`); - assert(isA(func, 'function'), `${MODULE_NAME}:throttle | no function given`); + assert(isFunction(func), `${MODULE_NAME}:throttle | no function given`); let frameHasStarted = false, @@ -114,7 +114,7 @@ export function debounce(ms, func){ ms = orDefault(ms, 0, 'int'); assert(ms > 0, `${MODULE_NAME}:debounce | ms must be > 0`); - assert(isA(func, 'function'), `${MODULE_NAME}:debounce | no function given`); + assert(isFunction(func), `${MODULE_NAME}:debounce | no function given`); let debounceTimer; @@ -147,7 +147,7 @@ export function debounce(ms, func){ export function defer(func, delay=1){ delay = orDefault(delay, 1, 'int'); - assert(isA(func, 'function'), `${MODULE_NAME}:defer | no function given`); + assert(isFunction(func), `${MODULE_NAME}:defer | no function given`); assert(delay > 0, `${MODULE_NAME}:defer | delay must be > 0`); return function(){ @@ -200,7 +200,7 @@ export function defer(func, delay=1){ export function kwargs(func, defaults=null){ defaults = isPlainObject(defaults) ? defaults : {}; - assert(isA(func, 'function'), `${MODULE_NAME}:kwargs | no function given`); + assert(isFunction(func), `${MODULE_NAME}:kwargs | no function given`); const argNamesString = func.toString().match(/\(([^)]+)/)[1], diff --git a/docs/examples/lib/annex/source/images.js b/docs/examples/lib/annex/source/images.js index 36213ed4..720172c5 100644 --- a/docs/examples/lib/annex/source/images.js +++ b/docs/examples/lib/annex/source/images.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Images'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, assert, isEmpty, isElement, hasValue, Deferred} from './basic.js'; +import {orDefault, isArray, isPlainObject, assert, isEmpty, isElement, hasValue, Deferred} from './basic.js'; import {waitForRepaint} from './timers.js'; @@ -58,7 +58,7 @@ export function preload(images){ ; let newImages; - if( !isPlainObject(images) && !isA(images, 'array') ){ + if( !isPlainObject(images) && !isArray(images) ){ images = `${images}`; if( hasValue(PRELOADED_IMAGES.named[images]) ){ @@ -83,7 +83,7 @@ export function preload(images){ }); PRELOADED_IMAGES.named = {...PRELOADED_IMAGES.named, ...newImages}; - } else if( isA(images, 'array') ){ + } else if( isArray(images) ){ newImages = []; images.forEach(value => { @@ -96,7 +96,7 @@ export function preload(images){ PRELOADED_IMAGES.unnamed = Array.from(new Set(PRELOADED_IMAGES.unnamed.concat(newImages))); } - deferred.provision = (isA(newImages, 'array') && (newImages.length === 1)) ? newImages[0] : newImages; + deferred.provision = (isArray(newImages) && (newImages.length === 1)) ? newImages[0] : newImages; loaded(preloadedImages) .then(deferred.resolve) .catch(deferred.reject) diff --git a/docs/examples/lib/annex/source/interaction.js b/docs/examples/lib/annex/source/interaction.js index 72e19989..86aabc86 100644 --- a/docs/examples/lib/annex/source/interaction.js +++ b/docs/examples/lib/annex/source/interaction.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Interaction'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, isElement, orDefault, hasValue, Deferred} from './basic.js'; +import {assert, isFunction, isElement, orDefault, hasValue, Deferred} from './basic.js'; import {findTextNodes} from './elements.js'; import {applyStyles} from './css.js'; @@ -74,7 +74,7 @@ export function createSelection(node, startOffset=0, endOffset=0){ node.selectionStart = startOffset; node.selectionEnd = rangeText.length - endOffset; selectionText = rangeText.substring(node.selectionStart, node.selectionEnd); - } else if( isA(window.getSelection, 'function') ){ + } else if( isFunction(window.getSelection) ){ range = document.createRange(); range.selectNodeContents(node); @@ -136,7 +136,7 @@ export function createSelection(node, startOffset=0, endOffset=0){ selection.removeAllRanges(); selection.addRange(range); selectionText = range.toString(); - } else if( isA(document.body.createTextRange, 'function') ){ + } else if( isFunction(document.body.createTextRange) ){ range = document.body.createTextRange(); range.moveToElementText(node); @@ -173,9 +173,9 @@ export function createSelection(node, startOffset=0, endOffset=0){ * removeSelections(); */ export function removeSelections(){ - if( isA(window.getSelection, 'function') ){ + if( isFunction(window.getSelection) ){ window.getSelection().removeAllRanges(); - } else if( isA(document.getSelection, 'function') ){ + } else if( isFunction(document.getSelection) ){ document.getSelection().removeAllRanges(); } diff --git a/docs/examples/lib/annex/source/navigation.js b/docs/examples/lib/annex/source/navigation.js index 463e7218..da4f98d5 100644 --- a/docs/examples/lib/annex/source/navigation.js +++ b/docs/examples/lib/annex/source/navigation.js @@ -13,7 +13,7 @@ const MODULE_NAME = 'Navigation'; //###[ IMPORTS ]######################################################################################################## import {warn} from './logging.js'; -import {hasValue, orDefault, isPlainObject, isEmpty, isA, assert} from './basic.js'; +import {hasValue, orDefault, isPlainObject, isEmpty, isArray, isWindow, isFunction, assert} from './basic.js'; import {createNode} from './elements.js'; import {browserSupportsHistoryManipulation} from './context.js'; @@ -173,7 +173,7 @@ export function redirect(url, params=null, anchor=null, target=null, postParams= const redirectForm = createNode('form', formAttributes); for( let paramName in postParams ){ - if( isA(postParams[paramName], 'array') ){ + if( isArray(postParams[paramName]) ){ postParams[paramName].forEach(val => { redirectForm.appendChild(createNode( 'input', @@ -283,7 +283,7 @@ export function openTab(url, params=null, anchor=null, postParams=null){ export function openWindow(url, options=null, parentWindow=null, tryAsPopup=false){ url = `${url}`; options = isPlainObject(options) ? options : null; - parentWindow = isA(parentWindow, 'window') ? parentWindow : window; + parentWindow = isWindow(parentWindow) ? parentWindow : window; tryAsPopup = orDefault(tryAsPopup, false, 'bool'); let windowName = ''; @@ -439,7 +439,7 @@ export function onHistoryChange(callback, clearOld=false, usePreviousState=false clearOld = orDefault(clearOld, false, 'bool'); usePreviousState = orDefault(usePreviousState, false, 'bool'); - assert(isA(callback, 'function'), `${MODULE_NAME}:${__methodName__} | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:${__methodName__} | callback is no function`); if ( browserSupportsHistoryManipulation() ) { if( clearOld ){ @@ -496,7 +496,7 @@ export function offHistoryChange(callback=null){ const __methodName__ = 'offHistoryChange'; if( hasValue(callback) ){ - assert(isA(callback, 'function'), `${MODULE_NAME}:${__methodName__} | callback is not a function`); + assert(isFunction(callback), `${MODULE_NAME}:${__methodName__} | callback is not a function`); const oldCallbackCount = HISTORY.popState.callbacks.length; HISTORY.popState.callbacks = HISTORY.popState.callbacks.reduce((cbs, cb) => { diff --git a/docs/examples/lib/annex/source/objects.js b/docs/examples/lib/annex/source/objects.js index 3183a46c..40deeb8c 100644 --- a/docs/examples/lib/annex/source/objects.js +++ b/docs/examples/lib/annex/source/objects.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Objects'; //###[ IMPORTS ]######################################################################################################## -import {getType, isA, orDefault} from './basic.js'; +import {getType, isFunction, isObject, orDefault} from './basic.js'; @@ -60,7 +60,7 @@ import {getType, isA, orDefault} from './basic.js'; export function clone(target, deep=true){ deep = orDefault(deep, true, 'bool'); - if( isA(target?.clone, 'function') ){ + if( isFunction(target?.clone) ){ return target.clone(deep); } @@ -219,7 +219,7 @@ export function merge(base, ...extensions){ if( extension.hasOwnProperty(prop) ){ if( base.hasOwnProperty(prop) - && (isA(base[prop], 'object') && isA(extension[prop], 'object')) + && (isObject(base[prop]) && isObject(extension[prop])) && (Object.keys(extension[prop]).length > 0) ){ base[prop] = merge(base[prop], extension[prop]); diff --git a/docs/examples/lib/annex/source/polling.js b/docs/examples/lib/annex/source/polling.js index f3ebcac2..e05a229c 100644 --- a/docs/examples/lib/annex/source/polling.js +++ b/docs/examples/lib/annex/source/polling.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Polling'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, assert, hasValue} from './basic.js'; +import {orDefault, isFunction, isObject, assert, hasValue} from './basic.js'; import {loop, countermand} from './timers.js'; @@ -68,13 +68,13 @@ const POLL_DEFAULT_LOOP_MS = 250; */ export function poll(name, fCondition, fAction, fElseAction=null, newLoopMs=POLL_DEFAULT_LOOP_MS, useOwnTimer=false){ name = orDefault(name, '', 'str').trim(); - fElseAction = isA(fElseAction, 'function') ? fElseAction : () => {}; + fElseAction = isFunction(fElseAction) ? fElseAction : () => {}; newLoopMs = orDefault(newLoopMs, POLL_DEFAULT_LOOP_MS, 'int'); useOwnTimer = orDefault(useOwnTimer, false, 'bool'); assert(name !== '', `${MODULE_NAME}:poll | name is missing`); - assert(isA(fCondition, 'function'), `${MODULE_NAME}:poll | fCondition is not a function`); - assert(isA(fAction, 'function'), `${MODULE_NAME}:poll | fAction is not a function`); + assert(isFunction(fCondition), `${MODULE_NAME}:poll | fCondition is not a function`); + assert(isFunction(fAction), `${MODULE_NAME}:poll | fAction is not a function`); const newPoll = { name, @@ -168,7 +168,7 @@ export function poll(name, fCondition, fAction, fElseAction=null, newLoopMs=POLL * unpoll(pollBodyHeightAndStopIfHighEnough); */ export function unpoll(poll){ - const name = (isA(poll, 'object') && hasValue(poll.name)) ? `${poll.name}` : `${poll}`.trim(); + const name = (isObject(poll) && hasValue(poll.name)) ? `${poll.name}` : `${poll}`.trim(); if( name === '' ) return false; poll = POLLS.activePolls[name]; diff --git a/docs/examples/lib/annex/source/polyfills.js b/docs/examples/lib/annex/source/polyfills.js index 372e6ee7..9231c02c 100644 --- a/docs/examples/lib/annex/source/polyfills.js +++ b/docs/examples/lib/annex/source/polyfills.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Polyfills'; //###[ IMPORTS ]######################################################################################################## -import {assert, hasValue, isA, orDefault} from './basic.js'; +import {assert, hasValue, isFunction, orDefault} from './basic.js'; import {createFetchRequest} from './requests.js'; @@ -42,7 +42,7 @@ import {createFetchRequest} from './requests.js'; export function polyfillFetch(force=false){ force = orDefault(force, false, 'bool'); - if( force || !isA(window.fetch, 'function') ){ + if( force || !isFunction(window.fetch) ){ window.fetch = function(url, options=null){ return createFetchRequest(url, options).execute(); }; @@ -99,7 +99,7 @@ export function polyfillElementMatches(){ * => makes "window.CustomEvent" and "new CustomEvent()" available, if not already present */ export function polyfillCustomEvent(){ - if( isA(window.CustomEvent, 'function') ) return false; + if( isFunction(window.CustomEvent) ) return false; const CustomEvent = function(event, params){ params = params ?? {bubbles : false, cancelable : false, detail : undefined}; @@ -131,7 +131,7 @@ export function polyfillCustomEvent(){ * => adds Array.prototype.at if not already defined */ export function polyfillArrayAt(){ - if( isA(Array.prototype.at, 'function') ) return false; + if( isFunction(Array.prototype.at) ) return false; Object.defineProperty(Array.prototype, 'at', { value : function(n){ diff --git a/docs/examples/lib/annex/source/random.js b/docs/examples/lib/annex/source/random.js index 35e02cb5..dac528c2 100644 --- a/docs/examples/lib/annex/source/random.js +++ b/docs/examples/lib/annex/source/random.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Random'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, assert, hasValue, isA} from './basic.js'; +import {orDefault, assert, hasValue, isFunction} from './basic.js'; @@ -105,13 +105,13 @@ export function randomUuid(withDashes=true){ // explicitly from either window.crypto or window.msCrypto, since invoking it from another // context will trigger an "illegal invocation" of the method :( if( - isA(window.crypto?.getRandomValues, 'function') - || isA(window.msCrypto?.getRandomValues, 'function') + isFunction(window.crypto?.getRandomValues) + || isFunction(window.msCrypto?.getRandomValues) ){ uuid = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => ( c ^ ( - isA(window.crypto?.getRandomValues, 'function') + isFunction(window.crypto?.getRandomValues) ? window.crypto.getRandomValues(new Uint8Array(1)) : window.msCrypto?.getRandomValues(new Uint8Array(1)) )[0] diff --git a/docs/examples/lib/annex/source/requests.js b/docs/examples/lib/annex/source/requests.js index 3e2c339c..d4e69cad 100644 --- a/docs/examples/lib/annex/source/requests.js +++ b/docs/examples/lib/annex/source/requests.js @@ -489,7 +489,7 @@ export function createJsonRequest(url, options=null, useNative=false, strict=tru * method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as * standard methods for HTTP verbs and setup things like setting headers. * - * @param {String} baseUrl - the base URL for all queries, based on which final request URLs will be built, adding the paths + * @param {?String} [baseUrl=window.location.origin] - the base URL for all queries, based on which final request URLs will be built, adding the paths, may be absolute or relative to current origin * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details) * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, "auto" uses it only if available * @param {?Boolean} [strict=true] - if true, enforces "application/json" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning @@ -515,7 +515,12 @@ export function createJsonRequest(url, options=null, useNative=false, strict=tru * .post() * ; */ -export function createRestfulJsonClient(baseUrl, baseOptions=null, useNative=false, strict=true){ +export function createRestfulJsonClient(baseUrl=null, baseOptions=null, useNative=false, strict=true){ + baseUrl = orDefault(baseUrl, window.location.origin, 'str'); + if( !baseUrl.startsWith('//') && baseUrl.startsWith('/') ){ + baseUrl = `${window.location.origin}${baseUrl}`; + } + const __methodName__ = 'createRestfulJsonClient', implementation = createJsonRequest, diff --git a/docs/examples/lib/annex/source/strings.js b/docs/examples/lib/annex/source/strings.js index 6575b875..3d0353f1 100644 --- a/docs/examples/lib/annex/source/strings.js +++ b/docs/examples/lib/annex/source/strings.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Strings'; //###[ IMPORTS ]######################################################################################################## -import {isA, orDefault, isNaN, hasValue, isPlainObject} from './basic.js'; +import {isFunction, isArray, orDefault, isNaN, hasValue, isPlainObject} from './basic.js'; @@ -118,7 +118,7 @@ export function replace(subject, search, replace){ search.forEach((searchTerm, index) => { tmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0]; - if( isA(String.prototype.replaceAll, 'function') ){ + if( isFunction(String.prototype.replaceAll) ){ subject = subject.replaceAll(`${searchTerm}`, `${tmp}`); } else { subject = subject.split(`${searchTerm}`).join(`${tmp}`); @@ -188,7 +188,7 @@ export function truncate(subject, maxLength=30, suffix='...'){ export function concat(glue='', ...strings){ glue = orDefault(glue, '', 'str'); - if( (strings.length > 0) && isA(strings[0], 'array') ){ + if( (strings.length > 0) && isArray(strings[0]) ){ return strings[0].join(glue); } else { return strings.join(glue); @@ -241,7 +241,7 @@ export function format(template, ...replacements){ const fResolve = function(object, key){ const value = object[key]; - if( isA(value, 'function') ){ + if( isFunction(value) ){ return value.call(object); } else { return value; diff --git a/docs/examples/lib/annex/source/timers.js b/docs/examples/lib/annex/source/timers.js index 5cb8fc63..7e06826f 100644 --- a/docs/examples/lib/annex/source/timers.js +++ b/docs/examples/lib/annex/source/timers.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Timers'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, assert, hasValue, hasMembers} from './basic.js'; +import {orDefault, isFunction, assert, hasValue, hasMembers} from './basic.js'; @@ -44,7 +44,7 @@ export function schedule(ms, callback, oldTimer=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:schedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:schedule | callback must be a function`); if( hasValue(oldTimer) ){ countermand(oldTimer); @@ -87,7 +87,7 @@ export function pschedule(ms, callback, oldTimer=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:pschedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:pschedule | callback must be a function`); if( hasValue(oldTimer) @@ -141,7 +141,7 @@ export function reschedule(timer, ms, callback){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:reschedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:reschedule | callback must be a function`); if( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){ return pschedule(ms, callback, timer); @@ -178,7 +178,7 @@ export function loop(ms, callback, oldLoop=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:loop | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:loop | callback must be a function`); if( hasValue(oldLoop) ){ countermand(oldLoop, true); @@ -224,7 +224,7 @@ export function ploop(ms, callback, oldLoop=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:ploop | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:ploop | callback must be a function`); if( hasValue(oldLoop) @@ -323,7 +323,7 @@ export function countermand(timer, isInterval=false){ * const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; }); */ export function requestAnimationFrame(callback){ - assert(isA(callback, 'function'), `${MODULE_NAME}:requestAnimationFrame | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:requestAnimationFrame | callback is no function`); const raf = window.requestAnimationFrame ?? window.webkitRequestAnimationFrame @@ -402,7 +402,7 @@ export function cancelAnimationFrame(id){ * waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); }); */ export function waitForRepaint(callback){ - assert(isA(callback, 'function'), `${MODULE_NAME}:waitForRepaint | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:waitForRepaint | callback is no function`); const ids = {}; diff --git a/docs/examples/lib/annex/source/viewport.js b/docs/examples/lib/annex/source/viewport.js index 33b7f87a..91504a3a 100644 --- a/docs/examples/lib/annex/source/viewport.js +++ b/docs/examples/lib/annex/source/viewport.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Viewport'; //###[ IMPORTS ]######################################################################################################## -import {hasValue, orDefault, isA, isElement, Deferred, assert} from './basic.js'; +import {hasValue, orDefault, isWindow, isFunction, isElement, Deferred, assert} from './basic.js'; import {EasingFunctions} from './animation.js'; import {requestAnimationFrame} from './timers.js'; @@ -122,10 +122,10 @@ export function scrollTo(element, durationMs=1000, offset=0, easing='easeInOutCu scrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool'); cancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool'); - assert(isElement(element) || isA(element, 'window'), `${MODULE_NAME}:scrollTo | element unusable`); + assert(isElement(element) || isWindow(element), `${MODULE_NAME}:scrollTo | element unusable`); assert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`); - if( !isA(EasingFunctions[easing], 'function') ){ + if( !isFunction(EasingFunctions[easing]) ){ easing = EasingFunctions.easeInOutCubic; } else { easing = EasingFunctions[easing]; diff --git a/package.json b/package.json index 46ead7fd..716d51ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name" : "@oktarintentakel/annex", - "version" : "0.1.5-beta", + "version" : "0.1.6-beta", "author" : "Sebastian Schlapkohl", "description" : "Unit-tested and semantically packaged standard solutions for everyday frontend tasks and syntax streamlining for those ugly darks corners of JS.", "license" : "MIT", diff --git a/source/arrays.js b/source/arrays.js index 4c7d6da7..01638d11 100644 --- a/source/arrays.js +++ b/source/arrays.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Arrays'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, isPlainObject, orDefault} from './basic.js'; +import {assert, isArray, isNumber, isString, isMap, isSet, isPlainObject, orDefault} from './basic.js'; @@ -75,9 +75,9 @@ import {assert, isA, isPlainObject, orDefault} from './basic.js'; * => [1] */ export function removeFrom(target, from, to=null){ - assert(isA(target, 'array'), `${MODULE_NAME}:remove | target is no array`); + assert(isArray(target), `${MODULE_NAME}:remove | target is no array`); - if( isA(from, 'number') && (to !== true) ){ + if( isNumber(from) && (to !== true) ){ from = parseInt(from, 10); to = orDefault(to, null, 'int'); @@ -86,7 +86,7 @@ export function removeFrom(target, from, to=null){ target.length = (from < 0) ? (target.length + from) : from; return target.concat(rest); - } else if( isA(from, 'string') ){ + } else if( isString(from) ){ return target.reduce((reducedArray, item) => { if( `${item}` !== from ){ reducedArray.push(item); @@ -97,9 +97,9 @@ export function removeFrom(target, from, to=null){ let fromList; if( isPlainObject(from) ){ fromList = Object.values(from); - } else if( isA(from, 'map') ){ + } else if( isMap(from) ){ fromList = Array.from(from.values()); - } else if( isA(from, 'set') ){ + } else if( isSet(from) ){ fromList = Array.from(from.values()); } else { fromList = Array.from(from); diff --git a/source/basic.js b/source/basic.js index 0deb5bed..f4ddcf9d 100644 --- a/source/basic.js +++ b/source/basic.js @@ -70,7 +70,7 @@ export function assert(condition, message){ * if( !attempt(function(){ foobar(); }) ){ console.log('foobar cannot be executed!'); } */ export function attempt(closure){ - assert(isA(closure, 'function'), `${MODULE_NAME}:attempt | closure is no function`); + assert(isFunction(closure), `${MODULE_NAME}:attempt | closure is no function`); try { closure(); @@ -158,7 +158,7 @@ export function hasValue(){ * => null */ export function size(target, countStringCharacters=true){ - if( isA(target?.values, 'function') ) return Array.from(target.values()).length; + if( isFunction(target?.values) ) return Array.from(target.values()).length; let res; switch( getType(target) ){ @@ -224,14 +224,14 @@ export function isEmpty(){ ; Array.from(arguments).forEach(obj => { - if( isA(obj?.__additionalEmptyValues__, 'array') ){ + if( isArray(obj?.__additionalEmptyValues__) ){ emptyValues = emptyValues.concat(obj.__additionalEmptyValues__); } }); emptyValues = Array.from(new Set(emptyValues)); Array.from(arguments).forEach(obj => { - if( res && !isA(obj?.__additionalEmptyValues__, 'array') ){ + if( res && !isArray(obj?.__additionalEmptyValues__) ){ res = emptyValues.includes(obj); if( !res ){ @@ -318,7 +318,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty if( hasValue(caster) ){ if( - !isA(caster, 'function') + !isFunction(caster) && ([ 'str', 'string', 'int', 'integer', @@ -340,7 +340,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty } else if( ['arr', 'array'].includes(caster) ){ caster = function(value){ return [].concat(value); }; } - } else if( !isA(caster, 'function') ){ + } else if( !isFunction(caster) ){ caster = function(value){ return value; }; } } else { @@ -363,7 +363,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty /** * Prod-ready type detection for values, expanding on flawed typeof functionality, roughly following * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof, but expanding on - * useful frontend types like "htmldocument", "htmlelement" and "nodelist" + * useful frontend types like "htmldocument", "htmlelement", "htmlcollection" and "nodelist" * * Types: * - "undefined" @@ -387,6 +387,7 @@ export function orDefault(expression, defaultValue, caster=null, additionalEmpty * - "weakmap" * - "htmldocument" * - "htmlelement" + * - "htmlcollection" * - "nodelist" * - "window" * @@ -411,7 +412,7 @@ export function getType(value) { if( /^html.*element$/.test(deepType) ) return 'htmlelement'; if( /^.*iterator$/.test(deepType) ) return 'iterator'; - return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|nodelist|window)$/) + return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol|set|weakset|map|weakmap|htmldocument|htmlcollection|nodelist|window)$/) ? deepType : ((typeof value === 'object') || (typeof value === 'function')) ? 'object' : typeof value ; @@ -461,6 +462,7 @@ export function isA(value, type){ 'weakmap', 'htmldocument', 'htmlelement', + 'htmlcollection', 'nodelist', 'window' ].includes(`${type}`.toLowerCase()) @@ -474,6 +476,80 @@ export function isA(value, type){ +/** + * @namespace Basic:isBoolean + */ + +/** + * Returns if a value is a boolean value. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a boolean + * + * @memberof Basic:isBoolean + * @alias isBoolean + * @example + * if( isBoolean(val) ){ + * console.log('val must be either true or false'); + * } + */ +export function isBoolean(value){ + return isA(value, 'boolean'); +} + + + +/** + * @namespace Basic:isNumber + */ + +/** + * Returns if a value is a number. + * + * Hint: to check numbers in more detail, use isInt, isFloat and isNaN + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a number + * + * @memberof Basic:isNumber + * @alias isNumber + * @see isInt + * @see isFloat + * @see isNaN + * @example + * if( isNumber(val) ){ + * result = val * 5; + * } + */ +export function isNumber(value){ + return isA(value, 'number'); +} + + + +/** + * @namespace Basic:isBigInt + */ + +/** + * Returns if a value is a BigInt value. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a BigInt + * + * @memberof Basic:isBigInt + * @alias isBigInt + * @example + * if( isBigInt(val) ){ + * console.log('this is a really huge number!'); + * } + */ +export function isBigInt(value){ + return isA(value, 'bigint'); +} + + + /** * @namespace Basic:isInt */ @@ -525,6 +601,137 @@ export function isFloat(floatVal){ +/** + * @namespace Basic:isNaN + */ + +/** + * Returns if an expression is NaN or not. + * This method employs two different approaches: + * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something. + * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being + * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which + * inspects the expression, tries to cast or parse a number from it and returns the result. + * + * @param {*} expression - the expression to check + * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality + * @returns {Boolean} true if expression is NaN + * + * @memberof Basic:isNaN + * @alias isNaN + * @example + * if( !isNaN(suspiciousCalculatedValue) ){ + * return suspiciousCalculatedValue * 3; + * } + */ +export function isNaN(expression, checkForIdentity=true){ + checkForIdentity = orDefault(checkForIdentity, true, 'bool'); + + if( checkForIdentity ){ + return expression !== expression; + } else { + return isNaN(expression); + } +} + + + +/** + * @namespace Basic:isString + */ + +/** + * Returns if a value is a string. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a string + * + * @memberof Basic:isString + * @alias isString + * @example + * if( isString(val) ){ + * return prefix+val; + * } + */ +export function isString(value){ + return isA(value, 'string'); +} + + + +/** + * @namespace Basic:isSymbol + */ + +/** + * Returns if a value is a symbol. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a symbol + * + * @memberof Basic:isSymbol + * @alias isSymbol + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol + * @example + * if( isSymbol(val) ){ + * return val.description; + * } + */ +export function isSymbol(value){ + return isA(value, 'symbol'); +} + + + +/** + * @namespace Basic:isFunction + */ + +/** + * Returns if a value is a function. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a function + * + * @memberof Basic:isFunction + * @alias isFunction + * @example + * if( isFunction(val) ){ + * val(); + * } + */ +export function isFunction(value){ + return isA(value, 'function'); +} + + + +/** + * @namespace Basic:isObject + */ + +/** + * Returns if a value is an object. + * + * Hint: if you explicitly want to check for a plain object, use isPlainObject + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an object + * + * @memberof Basic:isObject + * @alias isObject + * @see isPlainObject + * @example + * if( isObject(val) ){ + * val.newProperty = 'foobar'; + * } + */ +export function isObject(value){ + return isA(value, 'object'); +} + + + /** * @namespace Basic:isPlainObject */ @@ -549,7 +756,7 @@ export function isFloat(floatVal){ * const isParameterConfigObject = isPlainObject(param); */ export function isPlainObject(value){ - return isA(value, 'object') + return isObject(value) && hasValue(value) && (value.constructor === Object) && Object.prototype.toString.call(value) === '[object Object]' @@ -559,36 +766,260 @@ export function isPlainObject(value){ /** - * @namespace Basic:isNaN + * @namespace Basic:isArray */ /** - * Returns if an expression is NaN or not. - * This method employs two different approaches: - * By default it really checks if the expression is the _value_ NaN or not, this being a valid JS-value for something. - * In JS this gets checked by comparing an expression with itself on identity, since NaN is the only value not being - * identical to itself. If you set checkForIdentity to false, this method will use the standard JS-isNaN, which - * inspects the expression, tries to cast or parse a number from it and returns the result. + * Returns if a value is an array. * - * @param {*} expression - the expression to check - * @param {Boolean} [checkForIdentity=true] - set to false if you want to use default JS-functionality - * @returns {Boolean} true if expression is NaN + * @param {*} value - the value to check + * @returns {Boolean} true if value is an array * - * @memberof Basic:isNaN - * @alias isNaN + * @memberof Basic:isArray + * @alias isArray * @example - * if( !isNaN(suspiciousCalculatedValue) ){ - * return suspiciousCalculatedValue * 3; + * if( isArray(val) ){ + * val.push('foobar'); * } */ -export function isNaN(expression, checkForIdentity=true){ - checkForIdentity = orDefault(checkForIdentity, true, 'bool'); +export function isArray(value){ + return isA(value, 'array'); +} - if( checkForIdentity ){ - return expression !== expression; - } else { - return isNaN(expression); - } + + +/** + * @namespace Basic:isDate + */ + +/** + * Returns if a value is a date. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a date + * + * @memberof Basic:isDate + * @alias isDate + * @example + * if( isDate(val) ){ + * return val.toISOString(); + * } + */ +export function isDate(value){ + return isA(value, 'date'); +} + + + +/** + * @namespace Basic:isError + */ + +/** + * Returns if a value is an error. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an error + * + * @memberof Basic:isError + * @alias isError + * @example + * if( isError(val) ){ + * return val.message; + * } + */ +export function isError(value){ + return isA(value, 'error'); +} + + + +/** + * @namespace Basic:isGenerator + */ + +/** + * Returns if a value is a generator. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a generator + * + * @memberof Basic:isGenerator + * @alias isGenerator + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator + * @example + * if( isGenerator(val) ){ + * return val.return(val.next().value); + * } + */ +export function isGenerator(value){ + return isA(value, 'generator'); +} + + + +/** + * @namespace Basic:isIterator + */ + +/** + * Returns if a value is an iterator. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an iterator + * + * @memberof Basic:isIterator + * @alias isIterator + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator + * @example + * if( isIterator(val) ){ + * return val.next().value; + * } + */ +export function isIterator(value){ + return isA(value, 'iterator'); +} + + + +/** + * @namespace Basic:isRegExp + */ + +/** + * Returns if a value is a regular expression. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a regular expression + * + * @memberof Basic:isRegExp + * @alias isRegExp + * @example + * if( isRegExp(val) ){ + * return val.test('foobar'); + * } + */ +export function isRegExp(value){ + return isA(value, 'regexp'); +} + + + +/** + * @namespace Basic:isSet + */ + +/** + * Returns if a value is a set. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a set + * + * @memberof Basic:isSet + * @alias isSet + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set + * @example + * if( isSet(val) ){ + * return val.has('foobar'); + * } + */ +export function isSet(value){ + return isA(value, 'set'); +} + + + +/** + * @namespace Basic:isWeakSet + */ + +/** + * Returns if a value is a weak set. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a weak set + * + * @memberof Basic:isWeakSet + * @alias isWeakSet + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet + * @example + * if( isWeakSet(val) ){ + * return val.has(someSymbol); + * } + */ +export function isWeakSet(value){ + return isA(value, 'weakset'); +} + + + +/** + * @namespace Basic:isMap + */ + +/** + * Returns if a value is a map. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a map + * + * @memberof Basic:isMap + * @alias isMap + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map + * @example + * if( isMap(val) ){ + * return val.get('foobar'); + * } + */ +export function isMap(value){ + return isA(value, 'map'); +} + + + +/** + * @namespace Basic:isWeakMap + */ + +/** + * Returns if a value is a weak map. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a weak map + * + * @memberof Basic:isWeakMap + * @alias isWeakMap + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap + * @example + * if( isWeakMap(val) ){ + * return val.get('foobar'); + * } + */ +export function isWeakMap(value){ + return isA(value, 'weakmap'); +} + + + +/** + * @namespace Basic:isDocument + */ + +/** + * Returns if a value is an HTML document. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is an HTML document + * + * @memberof Basic:isDocument + * @alias isDocument + * @example + * if( isDocument(val) ){ + * return val.body; + * } + */ +export function isDocument(value){ + return isA(value, 'htmldocument'); } @@ -618,6 +1049,77 @@ export function isElement(value){ +/** + * @namespace Basic:isCollection + */ + +/** + * Returns if a value is a collection of html elements. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a collection of html elements + * + * @memberof Basic:isCollection + * @alias isCollection + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection + * @example + * if( isCollection(val) ){ + * return val.item(0); + * } + */ +export function isCollection(value){ + return isA(value, 'htmlcollection'); +} + + + +/** + * @namespace Basic:isNodeList + */ + +/** + * Returns if a value is a node list. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a node list + * + * @memberof Basic:isNodeList + * @alias isNodeList + * @see https://developer.mozilla.org/en-US/docs/Web/API/NodeList + * @example + * if( isNodeList(val) ){ + * return val.item(0); + * } + */ +export function isNodeList(value){ + return isA(value, 'nodelist'); +} + + + +/** + * @namespace Basic:isWindow + */ + +/** + * Returns if a value is a window. + * + * @param {*} value - the value to check + * @returns {Boolean} true if value is a window + * + * @memberof Basic:isWindow + * @alias isWindow + * @example + * if( isWindow(val) ){ + * return val.location.origin; + * } + */ +export function isWindow(value){ + return isA(value, 'window'); +} + + + /** * @namespace Basic:isEventTarget */ @@ -641,9 +1143,9 @@ export function isElement(value){ */ export function isEventTarget(value){ return hasValue(value) - && isA(value.addEventListener, 'function') - && isA(value.removeEventListener, 'function') - && isA(value.dispatchEvent, 'function') + && isFunction(value.addEventListener) + && isFunction(value.removeEventListener) + && isFunction(value.dispatchEvent) ; } @@ -909,7 +1411,7 @@ export class Observable { subscribe(subscription){ const __methodName__ = 'subscribe'; - assert(isA(subscription, 'function'), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`); + assert(isFunction(subscription), `${MODULE_NAME}:${this.__className__}.${__methodName__} | subscription must be function`); if( this._subscriptions.indexOf(subscription) < 0 ){ this._subscriptions = [...this._subscriptions, subscription]; } diff --git a/source/context.js b/source/context.js index 1603c786..404f7787 100644 --- a/source/context.js +++ b/source/context.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Context'; //###[ IMPORTS ]######################################################################################################## -import {hasValue, isA, orDefault, Observable} from './basic.js'; +import {hasValue, isFunction, isArray, orDefault, Observable} from './basic.js'; import {throttle} from './functions.js'; import {reschedule} from './timers.js'; @@ -71,8 +71,8 @@ export let CURRENT_INTERACTION_TYPE; */ export function browserSupportsHistoryManipulation(){ return hasValue(window.history) - && isA(window.history.pushState, 'function') - && isA(window.history.replaceState, 'function') + && isFunction(window.history.pushState) + && isFunction(window.history.replaceState) ; } @@ -285,7 +285,7 @@ export function detectAppleDevice(additionalTest=null){ break; } - if( isA(additionalTest, 'function') ){ + if( isFunction(additionalTest) ){ deviceType = additionalTest(deviceType); } } @@ -320,7 +320,7 @@ export function getBrowserLanguage(fallbackLanguage=null){ if( hasValue(window.navigator.languages) ){ const browserLanguages = Array.from(window.navigator.languages); - if( isA(browserLanguages, 'array') && (browserLanguages.length > 0) ){ + if( isArray(browserLanguages) && (browserLanguages.length > 0) ){ language = `${browserLanguages[0]}`; } } @@ -394,7 +394,7 @@ export function getLocale(element=null, fallbackLanguage=null){ isFallback : false }; - let langAttr = isA(element.getAttribute, 'function') ? element.getAttribute('lang') : null; + let langAttr = isFunction(element.getAttribute) ? element.getAttribute('lang') : null; if( !hasValue(langAttr) && hasValue(fallbackLanguage) ){ langAttr = `${fallbackLanguage}`; locale.isFallback = true; diff --git a/source/cookies.js b/source/cookies.js index 5dd1894f..7b8385a1 100644 --- a/source/cookies.js +++ b/source/cookies.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Cookies'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, orDefault, hasValue} from './basic.js'; +import {assert, isDate, orDefault, hasValue} from './basic.js'; import {warn} from './logging.js'; @@ -96,7 +96,7 @@ function normalizeCookieOptions(options){ options = normalizedOptions; if( hasValue(options.expires) ){ - if( !isA(options.expires, 'date') ){ + if( !isDate(options.expires) ){ options.expires = new Date(Date.now() + (Math.round(parseFloat(options.expires)) * 24 * 60 * 60 * 1000)); } options.expires = options.expires.toUTCString(); diff --git a/source/css.js b/source/css.js index b32edd29..a33a8188 100644 --- a/source/css.js +++ b/source/css.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'CSS'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js'; +import {assert, isNumber, orDefault, isPlainObject, isElement, hasValue, isNaN} from './basic.js'; import {maskForRegEx} from './strings.js'; @@ -82,7 +82,7 @@ export function applyStyles(element, styles, crossBrowser=false, returnCssStyleD } Object.entries({...styles}).forEach(([cssKey, cssValue]) => { - if( isA(cssValue, 'number') && (cssValue !== 0) ){ + if( isNumber(cssValue) && (cssValue !== 0) ){ styles[cssKey] = `${cssValue}px`; element.style.setProperty(cssKey, styles[cssKey]); } else if( !hasValue(cssValue) ){ diff --git a/source/elements.js b/source/elements.js index 9b144561..49e0457c 100644 --- a/source/elements.js +++ b/source/elements.js @@ -12,7 +12,18 @@ const MODULE_NAME = 'Elements'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, isSelector, isElement, hasValue, assert, size, Deferred} from './basic.js'; +import { + orDefault, + isString, + isFunction, + isPlainObject, + isSelector, + isElement, + hasValue, + assert, + size, + Deferred +} from './basic.js'; import {randomUuid} from './random.js'; import {clone} from './objects.js'; import {onDomReady} from './events.js'; @@ -408,7 +419,7 @@ export function getTextContent(target, onlyFirstLevel=false){ onlyFirstLevel = orDefault(onlyFirstLevel, false, 'bool'); - if( isA(target, 'string') ){ + if( isString(target) ){ target = createNode(target); } @@ -454,7 +465,7 @@ export function isInDom(node){ assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); - return isA(document.contains, 'function') ? document.contains(node) : document.body.contains(node); + return isFunction(document.contains) ? document.contains(node) : document.body.contains(node); } @@ -611,7 +622,7 @@ export function setData(node, dataSet, singleValue=null){ const appliedValues = {}; Object.entries(dataSet).forEach(([property, value]) => { - if( isA(value, 'function') ){ + if( isFunction(value) ){ value = value(); } @@ -857,7 +868,7 @@ export function findOne(node, selector='*'){ export function findTextNodes(node, filter=null, onlyFirstLevel=false){ const __methodName__ = 'findTextNodes'; - filter = isA(filter, 'function') ? filter : () => true; + filter = isFunction(filter) ? filter : () => true; onlyFirstLevel = orDefault(onlyFirstLevel, false, 'bool'); assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); @@ -939,7 +950,7 @@ export function prime(node, init, classChanges=null, markerAttributesName='prime markerAttributesName = orDefault(markerAttributesName, 'primed', 'str'); assert(isElement(node), `${MODULE_NAME}:${__methodName__} | ${NOT_AN_HTMLELEMENT_ERROR}`); - assert(isA(init, 'function'), `${MODULE_NAME}:${__methodName__} | init is not a function`); + assert(isFunction(init), `${MODULE_NAME}:${__methodName__} | init is not a function`); const deferred = new Deferred(); @@ -951,8 +962,8 @@ export function prime(node, init, classChanges=null, markerAttributesName='prime if( hasValue(initResult) - && isA(initResult.then, 'function') - && isA(initResult.catch, 'function') + && isFunction(initResult.then) + && isFunction(initResult.catch) ){ initResult .then(resolution => { deferred.resolve(resolution); }) diff --git a/source/events.js b/source/events.js index 6d6cb933..b3730b41 100644 --- a/source/events.js +++ b/source/events.js @@ -12,7 +12,22 @@ const MODULE_NAME = 'Events'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, isEventTarget, isPlainObject, isElement, orDefault, hasValue, isEmpty, isSelector} from './basic.js'; +import { + assert, + isFunction, + isString, + isArray, + isBoolean, + isObject, + isWindow, + isEventTarget, + isPlainObject, + isElement, + orDefault, + hasValue, + isEmpty, + isSelector +} from './basic.js'; import {slugify} from './strings.js'; import {removeFrom} from './arrays.js'; import {detectInteractionType} from './context.js'; @@ -85,7 +100,7 @@ function prepareEventMethodBaseParams(methodName, targets, events, handler, hand events = orDefault(events, [], 'arr'); assert(events.length > 0, `${MODULE_NAME}:${methodName} | no events provided`); if( !handlerIsOptional || hasValue(handler) ){ - assert(isA(handler, 'function'), `${MODULE_NAME}:${methodName} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${methodName} | handler is not a function`); } let @@ -94,7 +109,7 @@ function prepareEventMethodBaseParams(methodName, targets, events, handler, hand ; targets.forEach((target, targetIndex) => { - if( isA(target, 'string') ){ + if( isString(target) ){ const ancestor = (targetIndex > 0) ? targets[targetIndex - 1] : null; delegatedTargetsAreSelectorsAndHaveAncestor &&= isSelector(target) && isEventTarget(ancestor); } else { @@ -301,7 +316,7 @@ function createDelegatedHandler(delegation, handler){ : ( isEventTarget(e.syntheticTarget) || ( - isA(e.syntheticTarget, 'array') + isArray(e.syntheticTarget) && isSelector(e.syntheticTarget[1]) ) ? ( @@ -546,8 +561,8 @@ function createPauseAwareAction(managedHandler, nonPauseAwareAction){ * @private */ function compileEventListenerOptions(options){ - if( isA(options, 'boolean') ) return options; - if( !isA(options, 'object') ) return null; + if( isBoolean(options) ) return options; + if( !isObject(options) ) return null; const supportedOptions = {}; @@ -589,7 +604,7 @@ function createSyntheticEvent( eventOptions = isPlainObject(eventOptions) ? eventOptions : {}; let e; - if( isA(EventConstructor, 'function') ){ + if( isFunction(EventConstructor) ){ if( isPlainObject(payload) ){ console.warn(`${MODULE_NAME}:${__methodName__} | can't add payload to event "${EventConstructor.name}", skipping`); } @@ -610,7 +625,7 @@ function createSyntheticEvent( e.syntheticTarget = syntheticTarget; e.syntheticTargetElements = [syntheticTarget] } else if( - isA(syntheticTarget, 'array') + isArray(syntheticTarget) && isEventTarget(syntheticTarget[0]) && isSelector(syntheticTarget[1]) ){ @@ -651,10 +666,10 @@ function updateSwipeTouch(e){ * @private */ function resolvePostMessageTarget(target, method){ - target = isA(target, 'window') + target = isWindow(target) ? target : ( - isA(target?.contentWindow, 'window') + isWindow(target?.contentWindow) ? target.contentWindow : null ) @@ -1599,7 +1614,7 @@ export function onPostMessage(target, origin, messageType, handler){ origin = orDefault(origin, '*', 'str'); messageType = `${messageType}`; - assert(isA(handler, 'function'), `${MODULE_NAME}:${__methodName__} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${__methodName__} | handler is not a function`); if( !hasValue(POST_MESSAGE_MAP.get(target)) ){ POST_MESSAGE_MAP.set(target, {}); @@ -1666,7 +1681,7 @@ export function offPostMessage(target, origin=null, messageType=null, handler=nu tryNativeRemoval = orDefault(tryNativeRemoval, true, 'bool'); if( hasValue(handler) ){ - assert(isA(handler, 'function'), `${MODULE_NAME}:${__methodName__} | handler is not a function`); + assert(isFunction(handler), `${MODULE_NAME}:${__methodName__} | handler is not a function`); } let removedCount = 0; diff --git a/source/forms.js b/source/forms.js index 4d7ad120..e6475021 100644 --- a/source/forms.js +++ b/source/forms.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Forms'; //###[ IMPORTS ]######################################################################################################## -import {isA, isPlainObject, hasValue} from './basic.js'; +import {isFunction, isPlainObject, hasValue} from './basic.js'; @@ -74,9 +74,9 @@ export function formDataToObject(formDataOrForm){ // let's do duck-typing to allow polyfills if( - isA(formDataOrForm.append, 'function') - && isA(formDataOrForm.getAll, 'function') - && isA(formDataOrForm.entries, 'function') + isFunction(formDataOrForm.append) + && isFunction(formDataOrForm.getAll) + && isFunction(formDataOrForm.entries) ){ formData = formDataOrForm; } else { diff --git a/source/functions.js b/source/functions.js index cb9c9ee5..caf3ca1a 100644 --- a/source/functions.js +++ b/source/functions.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Functions'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, assert, hasValue} from './basic.js'; +import {orDefault, isFunction, isPlainObject, assert, hasValue} from './basic.js'; import {schedule, reschedule} from './timers.js'; @@ -52,7 +52,7 @@ export function throttle(ms, func, hasLeadingExecution=false, hasTrailingExecuti hasTrailingExecution = orDefault(hasTrailingExecution, false, 'bool'); assert(ms > 0, `${MODULE_NAME}:throttle | ms must be > 0`); - assert(isA(func, 'function'), `${MODULE_NAME}:throttle | no function given`); + assert(isFunction(func), `${MODULE_NAME}:throttle | no function given`); let frameHasStarted = false, @@ -114,7 +114,7 @@ export function debounce(ms, func){ ms = orDefault(ms, 0, 'int'); assert(ms > 0, `${MODULE_NAME}:debounce | ms must be > 0`); - assert(isA(func, 'function'), `${MODULE_NAME}:debounce | no function given`); + assert(isFunction(func), `${MODULE_NAME}:debounce | no function given`); let debounceTimer; @@ -147,7 +147,7 @@ export function debounce(ms, func){ export function defer(func, delay=1){ delay = orDefault(delay, 1, 'int'); - assert(isA(func, 'function'), `${MODULE_NAME}:defer | no function given`); + assert(isFunction(func), `${MODULE_NAME}:defer | no function given`); assert(delay > 0, `${MODULE_NAME}:defer | delay must be > 0`); return function(){ @@ -200,7 +200,7 @@ export function defer(func, delay=1){ export function kwargs(func, defaults=null){ defaults = isPlainObject(defaults) ? defaults : {}; - assert(isA(func, 'function'), `${MODULE_NAME}:kwargs | no function given`); + assert(isFunction(func), `${MODULE_NAME}:kwargs | no function given`); const argNamesString = func.toString().match(/\(([^)]+)/)[1], diff --git a/source/images.js b/source/images.js index 36213ed4..720172c5 100644 --- a/source/images.js +++ b/source/images.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Images'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, isPlainObject, assert, isEmpty, isElement, hasValue, Deferred} from './basic.js'; +import {orDefault, isArray, isPlainObject, assert, isEmpty, isElement, hasValue, Deferred} from './basic.js'; import {waitForRepaint} from './timers.js'; @@ -58,7 +58,7 @@ export function preload(images){ ; let newImages; - if( !isPlainObject(images) && !isA(images, 'array') ){ + if( !isPlainObject(images) && !isArray(images) ){ images = `${images}`; if( hasValue(PRELOADED_IMAGES.named[images]) ){ @@ -83,7 +83,7 @@ export function preload(images){ }); PRELOADED_IMAGES.named = {...PRELOADED_IMAGES.named, ...newImages}; - } else if( isA(images, 'array') ){ + } else if( isArray(images) ){ newImages = []; images.forEach(value => { @@ -96,7 +96,7 @@ export function preload(images){ PRELOADED_IMAGES.unnamed = Array.from(new Set(PRELOADED_IMAGES.unnamed.concat(newImages))); } - deferred.provision = (isA(newImages, 'array') && (newImages.length === 1)) ? newImages[0] : newImages; + deferred.provision = (isArray(newImages) && (newImages.length === 1)) ? newImages[0] : newImages; loaded(preloadedImages) .then(deferred.resolve) .catch(deferred.reject) diff --git a/source/interaction.js b/source/interaction.js index 72e19989..86aabc86 100644 --- a/source/interaction.js +++ b/source/interaction.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Interaction'; //###[ IMPORTS ]######################################################################################################## -import {assert, isA, isElement, orDefault, hasValue, Deferred} from './basic.js'; +import {assert, isFunction, isElement, orDefault, hasValue, Deferred} from './basic.js'; import {findTextNodes} from './elements.js'; import {applyStyles} from './css.js'; @@ -74,7 +74,7 @@ export function createSelection(node, startOffset=0, endOffset=0){ node.selectionStart = startOffset; node.selectionEnd = rangeText.length - endOffset; selectionText = rangeText.substring(node.selectionStart, node.selectionEnd); - } else if( isA(window.getSelection, 'function') ){ + } else if( isFunction(window.getSelection) ){ range = document.createRange(); range.selectNodeContents(node); @@ -136,7 +136,7 @@ export function createSelection(node, startOffset=0, endOffset=0){ selection.removeAllRanges(); selection.addRange(range); selectionText = range.toString(); - } else if( isA(document.body.createTextRange, 'function') ){ + } else if( isFunction(document.body.createTextRange) ){ range = document.body.createTextRange(); range.moveToElementText(node); @@ -173,9 +173,9 @@ export function createSelection(node, startOffset=0, endOffset=0){ * removeSelections(); */ export function removeSelections(){ - if( isA(window.getSelection, 'function') ){ + if( isFunction(window.getSelection) ){ window.getSelection().removeAllRanges(); - } else if( isA(document.getSelection, 'function') ){ + } else if( isFunction(document.getSelection) ){ document.getSelection().removeAllRanges(); } diff --git a/source/navigation.js b/source/navigation.js index 463e7218..da4f98d5 100644 --- a/source/navigation.js +++ b/source/navigation.js @@ -13,7 +13,7 @@ const MODULE_NAME = 'Navigation'; //###[ IMPORTS ]######################################################################################################## import {warn} from './logging.js'; -import {hasValue, orDefault, isPlainObject, isEmpty, isA, assert} from './basic.js'; +import {hasValue, orDefault, isPlainObject, isEmpty, isArray, isWindow, isFunction, assert} from './basic.js'; import {createNode} from './elements.js'; import {browserSupportsHistoryManipulation} from './context.js'; @@ -173,7 +173,7 @@ export function redirect(url, params=null, anchor=null, target=null, postParams= const redirectForm = createNode('form', formAttributes); for( let paramName in postParams ){ - if( isA(postParams[paramName], 'array') ){ + if( isArray(postParams[paramName]) ){ postParams[paramName].forEach(val => { redirectForm.appendChild(createNode( 'input', @@ -283,7 +283,7 @@ export function openTab(url, params=null, anchor=null, postParams=null){ export function openWindow(url, options=null, parentWindow=null, tryAsPopup=false){ url = `${url}`; options = isPlainObject(options) ? options : null; - parentWindow = isA(parentWindow, 'window') ? parentWindow : window; + parentWindow = isWindow(parentWindow) ? parentWindow : window; tryAsPopup = orDefault(tryAsPopup, false, 'bool'); let windowName = ''; @@ -439,7 +439,7 @@ export function onHistoryChange(callback, clearOld=false, usePreviousState=false clearOld = orDefault(clearOld, false, 'bool'); usePreviousState = orDefault(usePreviousState, false, 'bool'); - assert(isA(callback, 'function'), `${MODULE_NAME}:${__methodName__} | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:${__methodName__} | callback is no function`); if ( browserSupportsHistoryManipulation() ) { if( clearOld ){ @@ -496,7 +496,7 @@ export function offHistoryChange(callback=null){ const __methodName__ = 'offHistoryChange'; if( hasValue(callback) ){ - assert(isA(callback, 'function'), `${MODULE_NAME}:${__methodName__} | callback is not a function`); + assert(isFunction(callback), `${MODULE_NAME}:${__methodName__} | callback is not a function`); const oldCallbackCount = HISTORY.popState.callbacks.length; HISTORY.popState.callbacks = HISTORY.popState.callbacks.reduce((cbs, cb) => { diff --git a/source/objects.js b/source/objects.js index 3183a46c..40deeb8c 100644 --- a/source/objects.js +++ b/source/objects.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Objects'; //###[ IMPORTS ]######################################################################################################## -import {getType, isA, orDefault} from './basic.js'; +import {getType, isFunction, isObject, orDefault} from './basic.js'; @@ -60,7 +60,7 @@ import {getType, isA, orDefault} from './basic.js'; export function clone(target, deep=true){ deep = orDefault(deep, true, 'bool'); - if( isA(target?.clone, 'function') ){ + if( isFunction(target?.clone) ){ return target.clone(deep); } @@ -219,7 +219,7 @@ export function merge(base, ...extensions){ if( extension.hasOwnProperty(prop) ){ if( base.hasOwnProperty(prop) - && (isA(base[prop], 'object') && isA(extension[prop], 'object')) + && (isObject(base[prop]) && isObject(extension[prop])) && (Object.keys(extension[prop]).length > 0) ){ base[prop] = merge(base[prop], extension[prop]); diff --git a/source/polling.js b/source/polling.js index f3ebcac2..e05a229c 100644 --- a/source/polling.js +++ b/source/polling.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Polling'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, assert, hasValue} from './basic.js'; +import {orDefault, isFunction, isObject, assert, hasValue} from './basic.js'; import {loop, countermand} from './timers.js'; @@ -68,13 +68,13 @@ const POLL_DEFAULT_LOOP_MS = 250; */ export function poll(name, fCondition, fAction, fElseAction=null, newLoopMs=POLL_DEFAULT_LOOP_MS, useOwnTimer=false){ name = orDefault(name, '', 'str').trim(); - fElseAction = isA(fElseAction, 'function') ? fElseAction : () => {}; + fElseAction = isFunction(fElseAction) ? fElseAction : () => {}; newLoopMs = orDefault(newLoopMs, POLL_DEFAULT_LOOP_MS, 'int'); useOwnTimer = orDefault(useOwnTimer, false, 'bool'); assert(name !== '', `${MODULE_NAME}:poll | name is missing`); - assert(isA(fCondition, 'function'), `${MODULE_NAME}:poll | fCondition is not a function`); - assert(isA(fAction, 'function'), `${MODULE_NAME}:poll | fAction is not a function`); + assert(isFunction(fCondition), `${MODULE_NAME}:poll | fCondition is not a function`); + assert(isFunction(fAction), `${MODULE_NAME}:poll | fAction is not a function`); const newPoll = { name, @@ -168,7 +168,7 @@ export function poll(name, fCondition, fAction, fElseAction=null, newLoopMs=POLL * unpoll(pollBodyHeightAndStopIfHighEnough); */ export function unpoll(poll){ - const name = (isA(poll, 'object') && hasValue(poll.name)) ? `${poll.name}` : `${poll}`.trim(); + const name = (isObject(poll) && hasValue(poll.name)) ? `${poll.name}` : `${poll}`.trim(); if( name === '' ) return false; poll = POLLS.activePolls[name]; diff --git a/source/polyfills.js b/source/polyfills.js index 372e6ee7..9231c02c 100644 --- a/source/polyfills.js +++ b/source/polyfills.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Polyfills'; //###[ IMPORTS ]######################################################################################################## -import {assert, hasValue, isA, orDefault} from './basic.js'; +import {assert, hasValue, isFunction, orDefault} from './basic.js'; import {createFetchRequest} from './requests.js'; @@ -42,7 +42,7 @@ import {createFetchRequest} from './requests.js'; export function polyfillFetch(force=false){ force = orDefault(force, false, 'bool'); - if( force || !isA(window.fetch, 'function') ){ + if( force || !isFunction(window.fetch) ){ window.fetch = function(url, options=null){ return createFetchRequest(url, options).execute(); }; @@ -99,7 +99,7 @@ export function polyfillElementMatches(){ * => makes "window.CustomEvent" and "new CustomEvent()" available, if not already present */ export function polyfillCustomEvent(){ - if( isA(window.CustomEvent, 'function') ) return false; + if( isFunction(window.CustomEvent) ) return false; const CustomEvent = function(event, params){ params = params ?? {bubbles : false, cancelable : false, detail : undefined}; @@ -131,7 +131,7 @@ export function polyfillCustomEvent(){ * => adds Array.prototype.at if not already defined */ export function polyfillArrayAt(){ - if( isA(Array.prototype.at, 'function') ) return false; + if( isFunction(Array.prototype.at) ) return false; Object.defineProperty(Array.prototype, 'at', { value : function(n){ diff --git a/source/random.js b/source/random.js index 35e02cb5..dac528c2 100644 --- a/source/random.js +++ b/source/random.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Random'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, assert, hasValue, isA} from './basic.js'; +import {orDefault, assert, hasValue, isFunction} from './basic.js'; @@ -105,13 +105,13 @@ export function randomUuid(withDashes=true){ // explicitly from either window.crypto or window.msCrypto, since invoking it from another // context will trigger an "illegal invocation" of the method :( if( - isA(window.crypto?.getRandomValues, 'function') - || isA(window.msCrypto?.getRandomValues, 'function') + isFunction(window.crypto?.getRandomValues) + || isFunction(window.msCrypto?.getRandomValues) ){ uuid = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => ( c ^ ( - isA(window.crypto?.getRandomValues, 'function') + isFunction(window.crypto?.getRandomValues) ? window.crypto.getRandomValues(new Uint8Array(1)) : window.msCrypto?.getRandomValues(new Uint8Array(1)) )[0] diff --git a/source/requests.js b/source/requests.js index 3e2c339c..d4e69cad 100644 --- a/source/requests.js +++ b/source/requests.js @@ -489,7 +489,7 @@ export function createJsonRequest(url, options=null, useNative=false, strict=tru * method is a wrapper, providing central configuration, such as a base URL and options like credentials, as well as * standard methods for HTTP verbs and setup things like setting headers. * - * @param {String} baseUrl - the base URL for all queries, based on which final request URLs will be built, adding the paths + * @param {?String} [baseUrl=window.location.origin] - the base URL for all queries, based on which final request URLs will be built, adding the paths, may be absolute or relative to current origin * @param {?Object} [baseOptions=null] - the base request options, can be expanded later via options() (see: createFetchRequests for details) * @param {?Boolean|String} [useNative=false] - determines if the native Fetch implementation of the browser should be used, true forces usage, "auto" uses it only if available * @param {?Boolean} [strict=true] - if true, enforces "application/json" as accept header as well as response mime type, if false, accept header is not set and different mime type only results in warning @@ -515,7 +515,12 @@ export function createJsonRequest(url, options=null, useNative=false, strict=tru * .post() * ; */ -export function createRestfulJsonClient(baseUrl, baseOptions=null, useNative=false, strict=true){ +export function createRestfulJsonClient(baseUrl=null, baseOptions=null, useNative=false, strict=true){ + baseUrl = orDefault(baseUrl, window.location.origin, 'str'); + if( !baseUrl.startsWith('//') && baseUrl.startsWith('/') ){ + baseUrl = `${window.location.origin}${baseUrl}`; + } + const __methodName__ = 'createRestfulJsonClient', implementation = createJsonRequest, diff --git a/source/strings.js b/source/strings.js index 6575b875..3d0353f1 100644 --- a/source/strings.js +++ b/source/strings.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Strings'; //###[ IMPORTS ]######################################################################################################## -import {isA, orDefault, isNaN, hasValue, isPlainObject} from './basic.js'; +import {isFunction, isArray, orDefault, isNaN, hasValue, isPlainObject} from './basic.js'; @@ -118,7 +118,7 @@ export function replace(subject, search, replace){ search.forEach((searchTerm, index) => { tmp = (replace.length > 1) ? ((replace[index] !== undefined) ? replace[index] : '') : replace[0]; - if( isA(String.prototype.replaceAll, 'function') ){ + if( isFunction(String.prototype.replaceAll) ){ subject = subject.replaceAll(`${searchTerm}`, `${tmp}`); } else { subject = subject.split(`${searchTerm}`).join(`${tmp}`); @@ -188,7 +188,7 @@ export function truncate(subject, maxLength=30, suffix='...'){ export function concat(glue='', ...strings){ glue = orDefault(glue, '', 'str'); - if( (strings.length > 0) && isA(strings[0], 'array') ){ + if( (strings.length > 0) && isArray(strings[0]) ){ return strings[0].join(glue); } else { return strings.join(glue); @@ -241,7 +241,7 @@ export function format(template, ...replacements){ const fResolve = function(object, key){ const value = object[key]; - if( isA(value, 'function') ){ + if( isFunction(value) ){ return value.call(object); } else { return value; diff --git a/source/timers.js b/source/timers.js index 5cb8fc63..7e06826f 100644 --- a/source/timers.js +++ b/source/timers.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Timers'; //###[ IMPORTS ]######################################################################################################## -import {orDefault, isA, assert, hasValue, hasMembers} from './basic.js'; +import {orDefault, isFunction, assert, hasValue, hasMembers} from './basic.js'; @@ -44,7 +44,7 @@ export function schedule(ms, callback, oldTimer=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:schedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:schedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:schedule | callback must be a function`); if( hasValue(oldTimer) ){ countermand(oldTimer); @@ -87,7 +87,7 @@ export function pschedule(ms, callback, oldTimer=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:pschedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:pschedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:pschedule | callback must be a function`); if( hasValue(oldTimer) @@ -141,7 +141,7 @@ export function reschedule(timer, ms, callback){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:reschedule | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:reschedule | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:reschedule | callback must be a function`); if( hasValue(timer) && hasValue(timer.precise) && !!timer.precise ){ return pschedule(ms, callback, timer); @@ -178,7 +178,7 @@ export function loop(ms, callback, oldLoop=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:loop | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:loop | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:loop | callback must be a function`); if( hasValue(oldLoop) ){ countermand(oldLoop, true); @@ -224,7 +224,7 @@ export function ploop(ms, callback, oldLoop=null){ ms = orDefault(ms, 1, 'int'); assert(ms >= 0, `${MODULE_NAME}:ploop | ms must be positive`); - assert(isA(callback, 'function'), `${MODULE_NAME}:ploop | callback must be a function`); + assert(isFunction(callback), `${MODULE_NAME}:ploop | callback must be a function`); if( hasValue(oldLoop) @@ -323,7 +323,7 @@ export function countermand(timer, isInterval=false){ * const requestId = requestAnimationFrame(function(){ window.body.style.opacity = 0; }); */ export function requestAnimationFrame(callback){ - assert(isA(callback, 'function'), `${MODULE_NAME}:requestAnimationFrame | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:requestAnimationFrame | callback is no function`); const raf = window.requestAnimationFrame ?? window.webkitRequestAnimationFrame @@ -402,7 +402,7 @@ export function cancelAnimationFrame(id){ * waitForRepaint(function(){ alert(`the new dimensions after class change are: ${element.offsetWidth}x${element.offsetHeight}`); }); */ export function waitForRepaint(callback){ - assert(isA(callback, 'function'), `${MODULE_NAME}:waitForRepaint | callback is no function`); + assert(isFunction(callback), `${MODULE_NAME}:waitForRepaint | callback is no function`); const ids = {}; diff --git a/source/viewport.js b/source/viewport.js index 33b7f87a..91504a3a 100644 --- a/source/viewport.js +++ b/source/viewport.js @@ -12,7 +12,7 @@ const MODULE_NAME = 'Viewport'; //###[ IMPORTS ]######################################################################################################## -import {hasValue, orDefault, isA, isElement, Deferred, assert} from './basic.js'; +import {hasValue, orDefault, isWindow, isFunction, isElement, Deferred, assert} from './basic.js'; import {EasingFunctions} from './animation.js'; import {requestAnimationFrame} from './timers.js'; @@ -122,10 +122,10 @@ export function scrollTo(element, durationMs=1000, offset=0, easing='easeInOutCu scrollEvenIfFullyInViewport = orDefault(scrollEvenIfFullyInViewport, false, 'bool'); cancelOnUserScroll = orDefault(cancelOnUserScroll, false, 'bool'); - assert(isElement(element) || isA(element, 'window'), `${MODULE_NAME}:scrollTo | element unusable`); + assert(isElement(element) || isWindow(element), `${MODULE_NAME}:scrollTo | element unusable`); assert(durationMs > 0, `${MODULE_NAME}:scrollTo | durationMs must be > 0`); - if( !isA(EasingFunctions[easing], 'function') ){ + if( !isFunction(EasingFunctions[easing]) ){ easing = EasingFunctions.easeInOutCubic; } else { easing = EasingFunctions[easing]; diff --git a/test/annex/basic.js b/test/annex/basic.js index c9c69571..0b1078cd 100644 --- a/test/annex/basic.js +++ b/test/annex/basic.js @@ -19,11 +19,32 @@ const { orDefault, getType, isA, + isBoolean, + isNumber, + isBigInt, isInt, isFloat, - isPlainObject, isNaN, + isString, + isSymbol, + isFunction, + isObject, + isPlainObject, + isArray, + isDate, + isError, + isGenerator, + isIterator, + isRegExp, + isSet, + isWeakSet, + isMap, + isWeakMap, + isDocument, isElement, + isCollection, + isNodeList, + isWindow, isEventTarget, isSelector, isPotentialId, @@ -287,16 +308,66 @@ test('isA', assert => { +test('isBoolean', assert => { + const + foo = true, + bar = false, + foobar = 'true', + boofar = 5 + ; + + assert.true(isBoolean(foo)); + assert.true(isBoolean(bar)); + assert.false(isBoolean(foobar)); + assert.false(isBoolean(boofar)); +}); + + + +test('isNumber', assert => { + const + foo = 42, + bar = 42.42, + foobar = '13', + boofar = true + ; + + assert.true(isNumber(foo)); + assert.true(isNumber(bar)); + assert.false(isNumber(foobar)); + assert.false(isNumber(boofar)); +}); + + + +test('isBigInt', assert => { + const + foo = BigInt('9007199254740991'), + bar = BigInt('0x1fffffffffffff'), + foobar = 9007199254740991, + boofar = 0 + ; + + assert.true(isBigInt(foo)); + assert.true(isBigInt(bar)); + assert.false(isBigInt(foobar)); + assert.false(isBigInt(boofar)); +}); + + + test('isInt', assert => { const foo = 42, bar = 42.42, - foobar = '42' + foobar = '42', + boofar = true ; assert.true(isInt(foo)); assert.false(isInt(bar)); assert.false(isInt(foobar)); + assert.false(isInt(boofar)); }); @@ -305,12 +376,101 @@ test('isFloat', assert => { const foo = 42.42, bar = 42, - foobar = '42.42' + foobar = '42.42', + boofar = true ; assert.true(isFloat(foo)); assert.true(isFloat(bar)); assert.false(isFloat(foobar)); + assert.false(isFloat(boofar)); +}); + + + +test('isNaN', assert => { + const + foo = NaN, + bar = parseInt('abc', 10), + foobar = 'abc', + boo = '42', + far = new Date(), + boofar = /abc/g + ; + + assert.true(isNaN(foo)); + assert.true(isNaN(bar)); + assert.false(isNaN(foobar)); + assert.false(isNaN(boo)); + assert.false(isNaN(far)); + assert.false(isNaN(boofar)); +}); + + + +test('isString', assert => { + const + foo = 'foo', + bar = Symbol('bar').toString(), + foobar = Symbol('foobar'), + boofar = 0 + ; + + assert.true(isString(foo)); + assert.true(isString(bar)); + assert.false(isString(foobar)); + assert.false(isString(boofar)); +}); + + + +test('isSymbol', assert => { + const + foo = Symbol('foo'), + bar = Symbol(42), + foobar = Symbol('foobar').description, + boofar = 0 + ; + + assert.true(isSymbol(foo)); + assert.true(isSymbol(bar)); + assert.false(isSymbol(foobar)); + assert.false(isSymbol(boofar)); +}); + + + +test('isFunction', assert => { + function foo(){ + return true; + } + + const + bar = () => false, + foobar = Symbol().toString, + boofar = 'function(){}' + ; + + assert.true(isFunction(foo)); + assert.true(isFunction(bar)); + assert.true(isFunction(foobar)); + assert.false(isFunction(boofar)); +}); + + + +test('isObject', assert => { + const + foo = {}, + bar = new Object(42), + foobar = new Date(), + boofar = 42 + ; + + assert.true(isObject(foo)); + assert.true(isObject(bar)); + assert.false(isObject(foobar)); + assert.false(isObject(boofar)); }); @@ -332,22 +492,223 @@ test('isPlainObject', assert => { -test('isNaN', assert => { +test('isArray', assert => { const - foo = NaN, - bar = parseInt('abc', 10), - foobar = 'abc', - boo = '42', - far = new Date(), - boofar = /abc/g + foo = [1, 2, {}, []], + bar = Array.from(new Set([1, 2, 3, {}, []])), + foobar = new Set([1, 2, 3, {}, []]), + boofar = new Set([1, 2, 3, {}, []]).values() ; - assert.true(isNaN(foo)); - assert.true(isNaN(bar)); - assert.false(isNaN(foobar)); - assert.false(isNaN(boo)); - assert.false(isNaN(far)); - assert.false(isNaN(boofar)); + assert.true(isArray(foo)); + assert.true(isArray(bar)); + assert.false(isArray(foobar)); + assert.false(isArray(boofar)); +}); + + + +test('isDate', assert => { + const + foo = new Date(), + bar = new Date('1983-03-16'), + foobar = Date.now(), + boofar = '1983-03-16' + ; + + assert.true(isDate(foo)); + assert.true(isDate(bar)); + assert.false(isDate(foobar)); + assert.false(isDate(boofar)); +}); + + + +test('isError', assert => { + class FooError extends Error { + constructor(props){ + super(props); + + } + } + + let foobar; + try { + throw 'foobar'; + } catch(ex){ + foobar = ex; + } + + const + foo = new Error(), + bar = new FooError('foo'), + boofar = 'error' + ; + + assert.true(isError(foo)); + assert.true(isError(bar)); + assert.false(isError(foobar)); + assert.false(isError(boofar)); +}); + + + +test('isGenerator', assert => { + function* finiteGen(){ + yield 1; + yield 2; + yield 3; + } + + const infiniteGen = function*(){ + let i = 0; + + while(true){ + yield i++; + } + } + + const + foo = finiteGen(), + bar = infiniteGen(), + foobar = finiteGen().return(finiteGen().next().value), + boofar = infiniteGen().next() + ; + + assert.true(isGenerator(foo)); + assert.true(isGenerator(bar)); + assert.false(isGenerator(foobar)); + assert.false(isGenerator(boofar)); +}); + + + +test('isIterator', assert => { + function* finiteGen(){ + yield 1; + yield 2; + yield 3; + } + + const + foo = Array.from(finiteGen()).values(), + bar = 'bar'.matchAll(/bar/g), + foobar = new Set([1, 2, 3, {}, []]), + boofar = 'boofar' + ; + + assert.true(isIterator(foo)); + assert.true(isIterator(bar)); + assert.false(isIterator(foobar)); + assert.false(isIterator(boofar)); +}); + + + +test('isRegExp', assert => { + const + foo = /^foo$/, + bar = new RegExp('^bar$'), + foobar = '^foobar$', + boofar = 42 + ; + + assert.true(isRegExp(foo)); + assert.true(isRegExp(bar)); + assert.false(isRegExp(foobar)); + assert.false(isRegExp(boofar)); +}); + + + +test('isSet', assert => { + const + foo = new Set([1, 2, 3, {}, []]), + bar = new Set(Array.from(new Set([1, 2, 3, {}, []]))), + foobar = [1, 2, 3, {}, []], + boofar = new WeakSet() + ; + + boofar.add(new Date()) + + assert.true(isSet(foo)); + assert.true(isSet(bar)); + assert.false(isSet(foobar)); + assert.false(isSet(boofar)); +}); + + + +test('isWeakSet', assert => { + const + foo = new WeakSet([{}, [], new Date()]), + bar = new WeakSet(Array.from(new Set([{}, [], new Date()]))), + foobar = [1, 2, 3, {}, []], + boofar = new Set([1, 2, 3, {}, []]) + ; + + assert.true(isWeakSet(foo)); + assert.true(isWeakSet(bar)); + assert.false(isWeakSet(foobar)); + assert.false(isWeakSet(boofar)); +}); + + + +test('isMap', assert => { + const + foo = new Map(Object.entries({a : 'a', b : 'b', c : 'c'})), + bar = new Map(), + foobar = {a : 'a', b : 'b', c : 'c'}, + boofar = new WeakMap() + ; + + boofar.set({}, 'boofar'); + + bar.set(Symbol('bar'), 'bar'); + + assert.true(isMap(foo)); + assert.true(isMap(bar)); + assert.false(isMap(foobar)); + assert.false(isMap(boofar)); +}); + + + +test('isWeakMap', assert => { + const + foo = new WeakMap(), + bar = new WeakMap(), + foobar = {a : 'a', b : 'b', c : 'c'}, + boofar = new Map(Object.entries({a : 'a', b : 'b', c : 'c'})) + ; + + foo.set({}, 'a'); + foo.set([], 'b'); + foo.set(new Date(), 'c'); + + bar.set({}, 'bar'); + + assert.true(isWeakMap(foo)); + assert.true(isWeakMap(bar)); + assert.false(isWeakMap(foobar)); + assert.false(isWeakMap(boofar)); +}); + + + +test('isDocument', assert => { + const + foo = window.document, + bar = window.parent.document, + foobar = window, + boofar = document.body + ; + + assert.true(isDocument(foo)); + assert.true(isDocument(bar)); + assert.false(isDocument(foobar)); + assert.false(isDocument(boofar)); }); @@ -372,6 +733,54 @@ test('isElement', assert => { +test('isCollection', assert => { + const + foo = document.body.children, + bar = document.body.appendChild(document.createElement('div')).parentNode.children, + foobar = document.body.childNodes, + boofar = [document.body] + ; + + assert.true(isCollection(foo)); + assert.true(isCollection(bar)); + assert.false(isCollection(foobar)); + assert.false(isCollection(boofar)); +}); + + + +test('isNodeList', assert => { + const + foo = document.body.childNodes, + bar = document.body.appendChild(document.createElement('div')).parentNode.childNodes, + foobar = document.body.children, + boofar = [document.body] + ; + + assert.true(isNodeList(foo)); + assert.true(isNodeList(bar)); + assert.false(isNodeList(foobar)); + assert.false(isNodeList(boofar)); +}); + + + +test('isWindow', assert => { + const + foo = window, + bar = window.parent, + foobar = document, + boofar = document.body + ; + + assert.true(isWindow(foo)); + assert.true(isWindow(bar)); + assert.false(isWindow(foobar)); + assert.false(isWindow(boofar)); +}); + + + test('isEventTarget', assert => { const foo = document,