From 9d67120755fac6e3aae65ae5ce33fadaba9e3ab8 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Fri, 4 Apr 2025 17:20:56 +0200 Subject: [PATCH 01/16] UI: Add AsyncAutocomplete To Tag --- components/ILIAS/UI/UI.php | 2 - .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/rollup.config.js | 1 + .../resources/js/Input/Field/src/Tag/tag.js | 133 ++++++++++++++++++ .../js/Input/Field/src/input.factory.js | 4 + .../UI/resources/js/Input/Field/tagInput.js | 96 ------------- .../UI/src/Component/Input/Field/Tag.php | 14 ++ .../Component/Input/Field/Renderer.php | 2 +- .../Component/Input/Field/Tag.php | 21 +++ .../Field/Tag/with_autocomplete_endpoint.php | 96 +++++++++++++ 10 files changed, 271 insertions(+), 100 deletions(-) create mode 100644 components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js delete mode 100755 components/ILIAS/UI/resources/js/Input/Field/tagInput.js create mode 100755 components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php diff --git a/components/ILIAS/UI/UI.php b/components/ILIAS/UI/UI.php index 375f5aa61145..395619bf91c2 100644 --- a/components/ILIAS/UI/UI.php +++ b/components/ILIAS/UI/UI.php @@ -584,8 +584,6 @@ public function init( new Component\Resource\ComponentJS($this, "js/Input/Field/file.js"); $contribute[Component\Resource\PublicAsset::class] = fn() => new Component\Resource\ComponentJS($this, "js/Input/Field/input.js"); - $contribute[Component\Resource\PublicAsset::class] = fn() => - new Component\Resource\ComponentJS($this, "js/Input/Field/tagInput.js"); $contribute[Component\Resource\PublicAsset::class] = fn() => new Component\Resource\ComponentJS($this, "js/Item/dist/notification.js"); $contribute[Component\Resource\PublicAsset::class] = fn() => diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index dc2dc3f768fa..91f676a31f25 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n){"use strict";class r{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return o(this.textarea.value).slice(0,i(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=o(this.textarea.value);return e.slice(i(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=o(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function i(e){return(e.match(/\n/g)??[]).length}function o(e){return e.split(/\n/)}class s{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new r(e)}get(e){return this.instances[e]??null}}class l{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const a="textarea",c="preview";class d extends r{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(a,e.querySelector("textarea")),t.set(c,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&S(n)?this.applyTransformationToSelection(u):void 0!==n&&p(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(u);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(h):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{g(e,"hidden")})),this.view_controls.forEach((e=>{g(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&g(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=h(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!p(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(c).innerHTML=e})))}getBulletPointTransformation(){return u}getEnumerationTransformation(){return h}}function u(e){const t=[],n=!S(e[0]??"");for(const r of e)t.push(n?`- ${r}`:m(r));return t}function h(e,t=1){const n=[],r=!p(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:m(i));return n}function g(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function m(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function S(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function p(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class w{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new d(new l(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const y="data-node-id",b="data-node-name",v="data-render-url",x="data-ddindex",A="c-input-node",C="c-input-tree_select",L=`${A}__async`,B=`${A}__leaf`,T=`${A}--selected`,N="hidden",q="disabled",k=".glyph",$=`.${A}`,_=`.${C}`,M=`.${C}__selection`,H='[data-action="remove"]',I='[data-action="select"]',D=`.${A}__select`,R=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(v)?e.getAttribute(v):null}function O(e){return!e.classList.contains(B)&&e.classList.contains(A)}function U(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(y);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${b}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${D}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${x}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(x)}(t),function(e){if(!O(e))return null;const t=e.querySelector(`${R}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!O(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function F(e,t){for(let n=0;n{this.#m()})),this.#f.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(y);if(null===t)throw new Error(`Could not find '${y}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#E(e)})),this.#g.addEventListener("click",(()=>{this.#y()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);P(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);P(t.element,!0),this.#L(t.selectButton,t.name),this.#B(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(k).classList.toggle(q,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(k).classList.toggle(q,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#T(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=U((r=e.listElement,Array.from(r.querySelectorAll($))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,F(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#N(e){F(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(y);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${y}' of node element.`);const n=this.#e.get(t);this.#q(n)}))}#q(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(x,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#m(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#k(){F(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#E(e){if("0"===e)return void this.#k();const t=this.#f.querySelector(`ul[${x}="${e}"]`)?.closest($)?.getAttribute(y);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#k(),this.#N(this.#e.get(t))}#$(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#T(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#_(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#B(e){if(null!==this.#d.querySelector(`li[${y}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(y,e.id),n.querySelector(`[${b}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${y}="${e}"]`)?.remove()}#b(e){this.#_(e.selectButton,e),null!==e.drilldownButton&&this.#$(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(I)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(I)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#f.close()}#y(){this.#f.showModal()}}class z extends K{#H;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#H=g}selectNode(e){if(!this.#H){const t=Array.from(this.getSelection().add(e));this.#I(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#H)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(k).classList.remove(q)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(D).forEach((e=>{e.disabled=!0,e.querySelector(k).classList.add(q)}))}))}#I(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class W{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),V(t,n,"aria-describedby"),V(t,n,"aria-labelledby"),V(t,n,"aria-controls"),V(t,n,"aria-owns"),Q(this.#D,t.children)}}class G{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#j(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#j(e);e.replaceWith(t)})),t.children}}function J(e){return Array.from(e.querySelectorAll($))}class X{#O=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#O.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(U(J(a)),this.#U,new W(this.#D),new G(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#O.set(e,u),u}initTreeSelect(e){if(this.#O.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new K(U(J(l)),this.#U,new W(this.#D),new G(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#O.set(e,d),d}getInstance(e){return this.#O.has(e)?this.#O.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(_),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(M),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Y{#z;constructor(e){this.#z=e}on(e,t,n){this.#z(e).on(t,n)}off(e,t,n){this.#z(e).off(t,n)}}var Z;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(Z=t.UI.Input).textarea=new s,Z.markdown=new w,Z.treeSelect=new X(new Y(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n)}($,il,document); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,_=`${C}--selected`,N="hidden",$="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle($,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle($,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#_(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#$(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#$();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#$(),this.#_(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove($)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add($)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=200;function te(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{tag:e=>`\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));if(i.addTags(r),null!==n.autocompleteEndpoint){const e={controller:new AbortController,timeout:void 0};i.on("input",(t=>{!function(e,t,n,r){t.controller.abort(),t.controller=new AbortController,e.whitelist=null,"number"==typeof t.timeout&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(t.timeout),t.timeout=void 0),t.timeout=e.DOM.scope.ownerDocument.defaultView.setTimeout((()=>{const i=r.detail.value;n.searchParams.append("term",i),e.loading(!0),fetch(n.toString(),{signal:t.timeout.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(i)}))}),ee)}(i,e,new URL(n.autocompleteEndpoint),t)}))}}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tag=ne.tag||{},ne.tag.init=(e,t,n)=>te(r,e,t,n)}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js b/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js index c9db74217bb2..6c4743119f0b 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js +++ b/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js @@ -33,6 +33,7 @@ export default { jquery: '$', ilias: 'il', document: 'document', + Tagify: 'Tagify', }, plugins: [ terser({ diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js new file mode 100644 index 000000000000..6053116c24e4 --- /dev/null +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -0,0 +1,133 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + */ + +const tagAutocompleteTriggerTimeout = 200; + +/** + * @param {HTMLInput} input + * @param {Object} config + * @returns {Object} + */ +function buildSettings(inputId, config) { + return { + id: inputId, + whitelist: config.options, + enforceWhitelist: !config.userInput, + duplicates: config.allowDuplicates, + maxTags: config.maxItems, + delimiters: null, + originalInputValueFormat: (valuesArr) => valuesArr.map((item) => item.value), + dropdown: { + enabled: config.dropdownSuggestionsStartAfter, + maxItems: config.dropdownMaxItems, + closeOnSelect: config.dropdownCloseOnSelect, + highlightFirst: config.highlight, + }, + transformTag(tagData) { + if (!tagData.display) { + tagData.display = tagData.value; + tagData.value = encodeURI(tagData.value); + } + tagData.display = tagData.display + .replace(//g, '>'); + }, + templates: { + tag(tagData) { + return ` + +
+ ${tagData.display} +
+
`; + }, + dropdownItem(tagData) { + return `
+ ${tagData.display} +
`; + }, + }, + }; +} + +/** + * @param {Tagify} instance + * @param {Object} context + * @param {URL} autocompleteEndpoint + * @param {InputEvent} event + */ +function retrieveAutocomplete( + instance, + context, + autocompleteEndpoint, + event, +) { + context.controller.abort(); + context.controller = new AbortController(); + + instance.whitelist = null; + + if (typeof context.timeout === 'number') { + instance.DOM.scope.ownerDocument.defaultView.clearTimeout(context.timeout); + context.timeout = undefined; + } + + context.timeout = instance.DOM.scope.ownerDocument.defaultView.setTimeout( + () => { + const searchTerm = event.detail.value; + autocompleteEndpoint.searchParams.append('term', searchTerm); + instance.loading(true); + fetch(autocompleteEndpoint.toString(), { signal: context.timeout.signal }) + .then((answer) => answer.json()) + .catch(() => {}) + .then((options) => { + instance.whitelist = options; + instance.loading(false).dropdown.show(searchTerm); + }); + }, + tagAutocompleteTriggerTimeout, + ); +} + +/** + * @param {Tagify} Tagify + * @param {HTMLInput} input + * @param {Object} config + * @param {array} value + */ +export default function init(Tagify, input, config, value) { + const instance = new Tagify( + input, + buildSettings(input.id, config), + ); + instance.addTags(value); + if (config.autocompleteEndpoint !== null) { + const context = { + controller: new AbortController(), + timeout : undefined, + }; + instance.on('input', (event) => { + retrieveAutocomplete( + instance, + context, + new URL(config.autocompleteEndpoint), + event, + ); + }); + } +} diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js index 497552fb8985..f7f452dfc31f 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js @@ -31,6 +31,8 @@ import TextareaFactory from './Textarea/textarea.factory.js'; import MarkdownFactory from './Markdown/markdown.factory.js'; import TreeSelectFactory from './TreeSelect/TreeSelectFactory.js'; import JQueryEventListener from '../../../Core/src/JQueryEventListener.js'; +import Tagify from 'Tagify'; +import tag from './Tag/tag.js'; il.UI = il.UI || {}; il.UI.Input = il.UI.Input || {}; @@ -45,4 +47,6 @@ il.UI.Input = il.UI.Input || {}; {txt: (s) => il.Language.txt(s)}, document, ); + Input.tag = Input.tag || {}; + Input.tag.init = (input, config, value) => tag(Tagify, input, config, value); }(il.UI.Input)); diff --git a/components/ILIAS/UI/resources/js/Input/Field/tagInput.js b/components/ILIAS/UI/resources/js/Input/Field/tagInput.js deleted file mode 100755 index e5d76e140ab8..000000000000 --- a/components/ILIAS/UI/resources/js/Input/Field/tagInput.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * This file is part of ILIAS, a powerful learning management system - * published by ILIAS open source e-Learning e.V. - * - * ILIAS is licensed with the GPL-3.0, - * see https://www.gnu.org/licenses/gpl-3.0.en.html - * You should have received a copy of said license along with the - * source code, too. - * - * If this is not the case or you just want to try ILIAS, you'll find - * us at: - * https://www.ilias.de - * https://github.com/ILIAS-eLearning - */ - -/** - * Wraps the TagsInput - * - * @author Fabian Schmid - * @author Nils Haagen - */ -var il = il || {}; -il.UI = il.UI || {}; -il.UI.Input = il.UI.Input || {}; -(function ($) { - il.UI.Input.tagInput = (function ($) { - const instances = []; - const init = function (raw_id, config, value) { - let _CONFIG = {}; - const _getSettings = function () { - return { - whitelist: _CONFIG.options, - enforceWhitelist: !_CONFIG.userInput, - duplicates: _CONFIG.allowDuplicates, - maxTags: _CONFIG.maxItems, - originalInputValueFormat: (valuesArr) => valuesArr.map((item) => item.value), - dropdown: { - enabled: _CONFIG.dropdownSuggestionsStartAfter, - maxItems: _CONFIG.dropdownMaxItems, - closeOnSelect: _CONFIG.dropdownCloseOnSelect, - highlightFirst: _CONFIG.highlight, - }, - transformTag(tagData) { - if (!tagData.display) { - tagData.display = tagData.value; - tagData.value = encodeURI(tagData.value); - } - tagData.display = tagData.display - .replace(//g, '>'); - }, - }; - }; - - // Initialize ID and Configuration - _CONFIG = $.extend(_CONFIG, config); - _CONFIG.id = document.querySelector(`#${raw_id} .c-input__field .c-field-tag__wrapper input`)?.id; - - const settings = _getSettings(); - settings.delimiters = null; - settings.templates = {}; - settings.templates.tag = function (tagData) { - return ` - -
- ${tagData.display} -
-
`; - }; - settings.templates.dropdownItem = function (tagData) { - return `
- ${tagData.display} -
`; - }; - - const input = document.getElementById(_CONFIG.id); - const tagify = new Tagify(input, settings); - - tagify.addTags(value); - - instances[raw_id] = tagify; - }; - - const getTagifyInstance = function (raw_id) { - return instances[raw_id]; - }; - - return { - init, - getTagifyInstance, - }; - }($)); -}($, il.UI.Input)); diff --git a/components/ILIAS/UI/src/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Component/Input/Field/Tag.php index a196be809189..46604bd88e25 100755 --- a/components/ILIAS/UI/src/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Component/Input/Field/Tag.php @@ -23,6 +23,7 @@ use ILIAS\UI\Component\Input\Container\Form\FormInput; use ILIAS\UI\Component\Signal; use InvalidArgumentException; +use ILIAS\Data\URI; /** * Interface Tag @@ -86,6 +87,19 @@ public function withMaxTags(int $max_tags): Tag; */ public function getMaxTags(): int; + /** + * Get an input like this, but add an endpoint to get a list of possible options. + * The endpoint MUST answer to a query with the provided text as parameter "term". + * It MUST answer with a json array containing the options in the form of objects + * containing three properties "value", "display", and "searchBy". The property + * "value" MUST be save to transmit as url-parameter. + */ + public function withAsyncAutocomplete(URI $autocomplete_endpoint): Tag; + + /** + * @see withAsyncAutocomplete + */ + public function getAsyncAutocomplete(): ?URI; // Events diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php index cd8ceaf18e3d..e8d02a665ed2 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php @@ -412,7 +412,7 @@ function ($v) { function ($id) use ($configuration, $value) { $encoded = json_encode($configuration); $value = json_encode($value); - return "il.UI.Input.tagInput.init('{$id}', {$encoded}, {$value});"; + return "il.UI.Input.tag.init(document.querySelector('#{$id} .c-field-tag'), {$encoded}, {$value});"; } ); diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php index 4131aa5b3e03..2d0519136f97 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php @@ -22,6 +22,7 @@ use ILIAS\Data\Factory as DataFactory; use ILIAS\Data\Result\Ok; +use ILIAS\Data\URI; use ILIAS\UI\Component as C; use ILIAS\UI\Component\Signal; use ILIAS\UI\Component\Input\InputData; @@ -54,6 +55,7 @@ class Tag extends FormInput implements C\Input\Field\Tag protected bool $extendable = true; protected int $suggestion_starts_with = 1; protected array $tags = []; + protected ?Uri $async_autocomplete = null; public function __construct( DataFactory $data_factory, @@ -102,6 +104,7 @@ public function getConfiguration(): stdClass $configuration->userInput = $this->areUserCreatedTagsAllowed(); $configuration->dropdownSuggestionsStartAfter = $this->getSuggestionsStartAfter(); $configuration->suggestionStarts = $this->getSuggestionsStartAfter(); + $configuration->autocompleteEndpoint = $this->getAsyncAutocomplete()?->__toString(); $configuration->maxChars = 2000; $configuration->suggestionLimit = 50; $configuration->debug = false; @@ -265,6 +268,24 @@ public function getMaxTags(): int return $this->max_tags; } + /** + * @inheritDoc + */ + public function withAsyncAutocomplete(URI $autocomplete_endpoint): Tag + { + $clone = clone $this; + $clone->async_autocomplete = $autocomplete_endpoint; + return $clone; + } + + /** + * @inheritDoc + */ + public function getAsyncAutocomplete(): ?URI + { + return $this->async_autocomplete; + } + /** * @inheritDoc */ diff --git a/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php b/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php new file mode 100755 index 000000000000..eda841493094 --- /dev/null +++ b/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php @@ -0,0 +1,96 @@ + + * The example shows how to create and render a basic tag input field and attach it to a + * form. This example does not contain any data processing. + * + * expected output: > + * ILIAS shows an input field titled "Basic TagInput". The Tag "Interesting" is already displayed and can get removed + * through clicking the "X". A completion of the tags will be displayed by ILIAS if an A, B, I or R is typed into the field. + * It is also possible to insert tags of your own and confirm those through hitting the Enter button on your keyboard. + * Afterwards the tags will be highlighted with color. An "X" is displayed directly next to each tag. Clicking the "X" + * will remove the tag. + * Clicking "Save" will reload the page and will set the Tag in the input field back to "Interesting". + * --- + */ +function with_autocomplete_endpoint() +{ + /** @var \ILIAS\DI\Container $DIC */ + global $DIC; + $ui = $DIC->ui()->factory(); + $renderer = $DIC->ui()->renderer(); + $refinery = $DIC->refinery(); + $http = $DIC->http(); + + $df = new \ILIAS\Data\Factory(); + + $search_term = $http->wrapper()->query()->retrieve( + 'term', + $refinery->byTrying([ + $refinery->kindlyTo()->string(), + $refinery->always('') + ]) + ); + + if ($search_term !== '') { + $response = json_encode( + array_reduce( + ['Interesting', 'Boring', 'Animating', 'Repetitious'], + static function (array $c, string $v) use ($refinery, $search_term): array { + if (stristr($v, $search_term)) { + $c[] = [ + 'value' => urlencode($refinery->encode()->htmlSpecialCharsAsEntities()->transform($v)), + 'display' => $v, + 'searchBy' => $v + ]; + } + return $c; + }, + [] + ) + ); + $http->saveResponse( + $http->response()->withBody( + Streams::ofString($response) + ) + ); + $http->sendResponse(); + $http->close(); + } + + $tag_input = $ui->input()->field()->tag( + "Tag Input with Autocomplete", + [] + )->withAsyncAutocomplete( + $df->uri($http->request()->getUri()->__toString()) + )->withUserCreatedTagsAllowed(false); + + return $renderer->render( + $ui->input()->container()->form()->standard("#", [$tag_input]) + ); +} From 49e1ce0ca65a306fc986fc61f4a3f08edb105725 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Thu, 7 Aug 2025 10:11:37 +0200 Subject: [PATCH 02/16] UI: Fix Issues in Tag from Review --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 5 ++ .../UI/src/Component/Input/Field/Tag.php | 47 +++---------------- .../src/examples/Input/Field/Tag/disabled.php | 2 +- .../Field/Tag/with_autocomplete_endpoint.php | 10 ++-- 5 files changed, 19 insertions(+), 47 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 91f676a31f25..e059d8fe3388 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,_=`${C}--selected`,N="hidden",$="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle($,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle($,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#_(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#$(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#$();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#$(),this.#_(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove($)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add($)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=200;function te(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{tag:e=>`\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));if(i.addTags(r),null!==n.autocompleteEndpoint){const e={controller:new AbortController,timeout:void 0};i.on("input",(t=>{!function(e,t,n,r){t.controller.abort(),t.controller=new AbortController,e.whitelist=null,"number"==typeof t.timeout&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(t.timeout),t.timeout=void 0),t.timeout=e.DOM.scope.ownerDocument.defaultView.setTimeout((()=>{const i=r.detail.value;n.searchParams.append("term",i),e.loading(!0),fetch(n.toString(),{signal:t.timeout.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(i)}))}),ee)}(i,e,new URL(n.autocompleteEndpoint),t)}))}}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tag=ne.tag||{},ne.tag.init=(e,t,n)=>te(r,e,t,n)}($,il,document,Tagify); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,_=`${C}--selected`,N="hidden",$="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle($,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle($,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#_(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#$(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#$();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#$(),this.#_(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove($)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add($)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=200;function te(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{tag:e=>`\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));if(i.addTags(r),null!==n.autocompleteEndpoint){const e={controller:new AbortController,timeout:void 0,suggestionsStartAfter:n.suggestionStarts};i.on("input",(t=>{!function(e,t,n,r){t.controller.abort(),t.controller=new AbortController,e.whitelist=null,"number"==typeof t.timeout&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(t.timeout),t.timeout=void 0),r.detail.value.length{const i=r.detail.value;n.searchParams.append("term",i),e.loading(!0),fetch(n.toString(),{signal:t.timeout.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(i)}))}),ee))}(i,e,new URL(n.autocompleteEndpoint),t)}))}}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tag=ne.tag||{},ne.tag.init=(e,t,n)=>te(r,e,t,n)}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index 6053116c24e4..6d81983a3bf3 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -87,6 +87,10 @@ function retrieveAutocomplete( context.timeout = undefined; } + if (event.detail.value.length < context.suggestionsStartAfter) { + return; + } + context.timeout = instance.DOM.scope.ownerDocument.defaultView.setTimeout( () => { const searchTerm = event.detail.value; @@ -120,6 +124,7 @@ export default function init(Tagify, input, config, value) { const context = { controller: new AbortController(), timeout : undefined, + suggestionsStartAfter: config.suggestionStarts, }; instance.on('input', (event) => { retrieveAutocomplete( diff --git a/components/ILIAS/UI/src/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Component/Input/Field/Tag.php index 46604bd88e25..16bfe2421f60 100755 --- a/components/ILIAS/UI/src/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Component/Input/Field/Tag.php @@ -34,23 +34,11 @@ */ interface Tag extends FormInput { - /** - * @return string[] of tags such as [ 'Interesting', 'Boring', 'Animating', 'Repetitious' ] - */ - public function getTags(): array; - /** * Get an input like this, but decide whether the user can provide own * tags or not. (Default: Allowed) */ - public function withUserCreatedTagsAllowed(bool $extendable): Tag; - - /** - * @see withUserCreatedTagsAllowed - * @return bool Whether the user is allowed to input more - * options than the given. - */ - public function areUserCreatedTagsAllowed(): bool; + public function withUserCreatedTagsAllowed(bool $extendable): self; /** * Get an input like this, but change the amount of characters the @@ -59,33 +47,17 @@ public function areUserCreatedTagsAllowed(): bool; * @param int $characters defaults to 1 * @throws InvalidArgumentException */ - public function withSuggestionsStartAfter(int $characters): Tag; - - /** - * @see withSuggestionsStartAfter - */ - public function getSuggestionsStartAfter(): int; + public function withSuggestionsStartAfter(int $characters): self; /** * Get an input like this, but limit the amount of characters one tag can be. (Default: unlimited) */ - public function withTagMaxLength(int $max_length): Tag; - - /** - * @see withTagMaxLength - */ - public function getTagMaxLength(): int; + public function withTagMaxLength(int $max_length): self; /** * Get an input like this, but limit the amount of tags a user can select or provide. (Default: unlimited) */ - public function withMaxTags(int $max_tags): Tag; - - - /** - * @see withMaxTags - */ - public function getMaxTags(): int; + public function withMaxTags(int $max_tags): self; /** * Get an input like this, but add an endpoint to get a list of possible options. @@ -94,16 +66,11 @@ public function getMaxTags(): int; * containing three properties "value", "display", and "searchBy". The property * "value" MUST be save to transmit as url-parameter. */ - public function withAsyncAutocomplete(URI $autocomplete_endpoint): Tag; - - /** - * @see withAsyncAutocomplete - */ - public function getAsyncAutocomplete(): ?URI; + public function withAsyncAutocomplete(URI $autocomplete_endpoint): self; // Events - public function withAdditionalOnTagAdded(Signal $signal): Tag; + public function withAdditionalOnTagAdded(Signal $signal): self; - public function withAdditionalOnTagRemoved(Signal $signal): Tag; + public function withAdditionalOnTagRemoved(Signal $signal): self; } diff --git a/components/ILIAS/UI/src/examples/Input/Field/Tag/disabled.php b/components/ILIAS/UI/src/examples/Input/Field/Tag/disabled.php index 8dc6a400d827..a2e58419c0ae 100755 --- a/components/ILIAS/UI/src/examples/Input/Field/Tag/disabled.php +++ b/components/ILIAS/UI/src/examples/Input/Field/Tag/disabled.php @@ -42,7 +42,7 @@ function disabled() $tag_input = $ui->input() ->field() ->tag( - "Basic Tag", + "Basic TagInput", ['Interesting', 'Boring', 'Animating', 'Repetitious'], "Just some tags" )->withDisabled(true)->withValue(["Boring", "Animating"]); diff --git a/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php b/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php index eda841493094..eeedd52ce962 100755 --- a/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php +++ b/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php @@ -30,11 +30,11 @@ * form. This example does not contain any data processing. * * expected output: > - * ILIAS shows an input field titled "Basic TagInput". The Tag "Interesting" is already displayed and can get removed - * through clicking the "X". A completion of the tags will be displayed by ILIAS if an A, B, I or R is typed into the field. - * It is also possible to insert tags of your own and confirm those through hitting the Enter button on your keyboard. - * Afterwards the tags will be highlighted with color. An "X" is displayed directly next to each tag. Clicking the "X" - * will remove the tag. + * ILIAS shows an input field titled "Tag Input with Autocomplete". A completion of + * the tags will be displayed by ILIAS if an A, B, I or R is typed into the field. + * It is also possible to insert tags of your own and confirm those through hitting + * the Enter button on your keyboard. Afterwards the tags will be highlighted with color. + * An "X" is displayed directly next to each tag. Clicking the "X" will remove the tag. * Clicking "Save" will reload the page and will set the Tag in the input field back to "Interesting". * --- */ From 801570eaaf16565a72988f9fe3092c537bc9a419 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Tue, 23 Sep 2025 14:42:15 +0200 Subject: [PATCH 03/16] UI: Move Tags to DIVs --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../UI/resources/js/Input/Field/src/Tag/tag.js | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index e059d8fe3388..4473728ad2bb 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,_=`${C}--selected`,N="hidden",$="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle($,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle($,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#_(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#$(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#$();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#$(),this.#_(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove($)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add($)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=200;function te(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{tag:e=>`\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));if(i.addTags(r),null!==n.autocompleteEndpoint){const e={controller:new AbortController,timeout:void 0,suggestionsStartAfter:n.suggestionStarts};i.on("input",(t=>{!function(e,t,n,r){t.controller.abort(),t.controller=new AbortController,e.whitelist=null,"number"==typeof t.timeout&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(t.timeout),t.timeout=void 0),r.detail.value.length{const i=r.detail.value;n.searchParams.append("term",i),e.loading(!0),fetch(n.toString(),{signal:t.timeout.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(i)}))}),ee))}(i,e,new URL(n.autocompleteEndpoint),t)}))}}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tag=ne.tag||{},ne.tag.init=(e,t,n)=>te(r,e,t,n)}($,il,document,Tagify); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=200;function te(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));if(i.addTags(r),null!==n.autocompleteEndpoint){const e={controller:new AbortController,timeout:void 0,suggestionsStartAfter:n.suggestionStarts};i.on("input",(t=>{!function(e,t,n,r){t.controller.abort(),t.controller=new AbortController,e.whitelist=null,"number"==typeof t.timeout&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(t.timeout),t.timeout=void 0),r.detail.value.length{const i=r.detail.value;n.searchParams.append("term",i),e.loading(!0),fetch(n.toString(),{signal:t.timeout.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(i)}))}),ee))}(i,e,new URL(n.autocompleteEndpoint),t)}))}}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tag=ne.tag||{},ne.tag.init=(e,t,n)=>te(r,e,t,n)}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index 6d81983a3bf3..54a636c8356c 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -45,16 +45,27 @@ function buildSettings(inputId, config) { .replace(/>/g, '>'); }, templates: { + wrapper(input, _s) { + return `
+ ${this.settings.templates.input.call(this)} + \u200B +
` + }, tag(tagData) { - return ` - +
${tagData.display}
-
`; + `; }, dropdownItem(tagData) { return `
From dc8ff49089a7bbee412fc6f15f45ad759bc985b4 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Tue, 23 Sep 2025 15:00:19 +0200 Subject: [PATCH 04/16] UI: Do Not Bundel Parameters --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 39 ++++++++++--------- .../Component/Input/Field/Tag.php | 5 +++ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 4473728ad2bb..7d13fd685388 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=200;function te(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));if(i.addTags(r),null!==n.autocompleteEndpoint){const e={controller:new AbortController,timeout:void 0,suggestionsStartAfter:n.suggestionStarts};i.on("input",(t=>{!function(e,t,n,r){t.controller.abort(),t.controller=new AbortController,e.whitelist=null,"number"==typeof t.timeout&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(t.timeout),t.timeout=void 0),r.detail.value.length{const i=r.detail.value;n.searchParams.append("term",i),e.loading(!0),fetch(n.toString(),{signal:t.timeout.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(i)}))}),ee))}(i,e,new URL(n.autocompleteEndpoint),t)}))}}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tag=ne.tag||{},ne.tag.init=(e,t,n)=>te(r,e,t,n)}($,il,document,Tagify); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}function ee(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));i.addTags(r),null!==n.autocompleteEndpoint&&i.on("input",(e=>{!function(e,t,n,r,i,o,s){t.abort(),t=new AbortController,e.whitelist=null,"number"==typeof n&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(n),n=void 0),o.detail.value.length{const n=o.detail.value;i.searchParams.append("term",n),e.loading(!0),fetch(i.toString(),{signal:t.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(n)}))}),s))}(i,new AbortController,void 0,n.suggestionStarts,new URL(n.autocompleteEndpoint),e,n.autocompleteTriggerTimeout)}))}var te;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(te=t.UI.Input).textarea=new l,te.markdown=new y,te.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),te.tag=te.tag||{},te.tag.init=(e,t,n)=>ee(r,e,t,n)}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index 54a636c8356c..557e0a2ee62c 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -13,8 +13,6 @@ * https://github.com/ILIAS-eLearning */ -const tagAutocompleteTriggerTimeout = 200; - /** * @param {HTMLInput} input * @param {Object} config @@ -78,36 +76,43 @@ function buildSettings(inputId, config) { /** * @param {Tagify} instance - * @param {Object} context + * @param {AbortController} controller + * @param {number} timeout + * @param {number} suggestionsStartAfter * @param {URL} autocompleteEndpoint * @param {InputEvent} event + * @param {number} tagAutocompleteTriggerTimeout + * @returns {void} */ function retrieveAutocomplete( instance, - context, + controller, + timeout, + suggestionsStartAfter, autocompleteEndpoint, event, + tagAutocompleteTriggerTimeout, ) { - context.controller.abort(); - context.controller = new AbortController(); + controller.abort(); + controller = new AbortController(); instance.whitelist = null; - if (typeof context.timeout === 'number') { - instance.DOM.scope.ownerDocument.defaultView.clearTimeout(context.timeout); - context.timeout = undefined; + if (typeof timeout === 'number') { + instance.DOM.scope.ownerDocument.defaultView.clearTimeout(timeout); + timeout = undefined; } - if (event.detail.value.length < context.suggestionsStartAfter) { + if (event.detail.value.length < suggestionsStartAfter) { return; } - context.timeout = instance.DOM.scope.ownerDocument.defaultView.setTimeout( + timeout = instance.DOM.scope.ownerDocument.defaultView.setTimeout( () => { const searchTerm = event.detail.value; autocompleteEndpoint.searchParams.append('term', searchTerm); instance.loading(true); - fetch(autocompleteEndpoint.toString(), { signal: context.timeout.signal }) + fetch(autocompleteEndpoint.toString(), { signal: controller.signal }) .then((answer) => answer.json()) .catch(() => {}) .then((options) => { @@ -132,17 +137,15 @@ export default function init(Tagify, input, config, value) { ); instance.addTags(value); if (config.autocompleteEndpoint !== null) { - const context = { - controller: new AbortController(), - timeout : undefined, - suggestionsStartAfter: config.suggestionStarts, - }; instance.on('input', (event) => { retrieveAutocomplete( instance, - context, + new AbortController(), + undefined, + config.suggestionStarts, new URL(config.autocompleteEndpoint), event, + config.autocompleteTriggerTimeout, ); }); } diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php index 2d0519136f97..9703681765ae 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php @@ -105,6 +105,11 @@ public function getConfiguration(): stdClass $configuration->dropdownSuggestionsStartAfter = $this->getSuggestionsStartAfter(); $configuration->suggestionStarts = $this->getSuggestionsStartAfter(); $configuration->autocompleteEndpoint = $this->getAsyncAutocomplete()?->__toString(); +<<<<<<< HEAD +======= + $configuration->autocompleteTriggerTimeout = 200; + $configuration->orderable = $this->isOrderable(); +>>>>>>> 4f6837565c8 (UI: Do Not Bundel Parameters) $configuration->maxChars = 2000; $configuration->suggestionLimit = 50; $configuration->debug = false; From 72321364b64481c950f102cf473d140866af7d03 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Tue, 23 Sep 2025 15:12:17 +0200 Subject: [PATCH 05/16] UI: Do not Alter Special Chars See: https://mantis.ilias.de/view.php?id=45566 --- .../resources/js/Input/Field/src/Tag/tag.js | 2 +- .../Component/Input/Field/Renderer.php | 2 +- .../Component/Input/Field/Tag.php | 4 +-- .../Component/Input/Field/TagInputTest.php | 34 +++++++++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index 557e0a2ee62c..3cc24cb562a8 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -36,7 +36,7 @@ function buildSettings(inputId, config) { transformTag(tagData) { if (!tagData.display) { tagData.display = tagData.value; - tagData.value = encodeURI(tagData.value); + tagData.value = encodeURIComponent(tagData.value); } tagData.display = tagData.display .replace(/ urlencode($v), 'display' => $v]; + return ['value' => rawurlencode($v), 'display' => $v]; }, $value ); diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php index 9703681765ae..bac66b215e51 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php @@ -77,7 +77,7 @@ protected function addAdditionalTransformations(): void if (count($v) == 1 && $v[0] === '') { return []; } - $array = array_map("urldecode", $v); + $array = array_map('rawurldecode', $v); return array_map('strip_tags', $array); })); } @@ -86,7 +86,7 @@ public function getConfiguration(): stdClass { $options = array_map( fn($tag) => [ - 'value' => urlencode(trim($tag)), + 'value' => rawurlencode(trim($tag)), 'display' => $tag, 'searchBy' => $tag ], diff --git a/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php b/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php index 9d04a9bf9cbe..f4b2dc476897 100755 --- a/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php +++ b/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php @@ -231,4 +231,38 @@ public function testMaxTaglengthTagsNotOk(): void ) ); } + + public static function getUITagSpecialCharValues(): array + { + return [ + ['1', '2', '3'], + ['++1#*', '[-2]', '{?3}'], + ['some\'thing "else"', '&/\\'], + ['fünf, sechs', 'sieben, acht'], + ]; + } + + /** @dataProvider getUITagSpecialCharValues */ + public function testUITagInputSpecialChars(string ...$tags): void + { + $f = $this->getFieldFactory(); + $name = "name_0"; + $tag = $f->tag('', $tags)->withNameFrom($this->name_source); + + $encoded_tags = array_map('rawurlencode', $tags); + + $this->assertEquals( + $encoded_tags, + array_map( + fn($o) => $o['value'], + $tag->getConfiguration(fn(string $txt) => $txt)->options + ) + ); + + $raw_value = implode(',', $encoded_tags); + $tag_with_input = $tag->withInput(new DefInputData([$name => $raw_value])); + $content = $tag_with_input->getContent(); + $this->assertTrue($content->isOk()); + $this->assertEquals($tags, $content->value()); + } } From 631600be96bac5e874e1c71ad7ef534c49afd28c Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Tue, 23 Sep 2025 15:33:22 +0200 Subject: [PATCH 06/16] UI: Expose Instances of TagInput --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 26 +++++++++++++++---- .../js/Input/Field/src/input.factory.js | 7 ++--- .../Component/Input/Field/Renderer.php | 2 +- .../Component/Input/Field/Tag.php | 4 --- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 7d13fd685388..9978dc4a4e13 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",L="c-input-tree_select",T=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${L}`,I=`.${L}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(T)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#L(t.selectButton,t.name),this.#T(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#T(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#L(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}function ee(e,t,n,r){const i=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURI(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n));i.addTags(r),null!==n.autocompleteEndpoint&&i.on("input",(e=>{!function(e,t,n,r,i,o,s){t.abort(),t=new AbortController,e.whitelist=null,"number"==typeof n&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(n),n=void 0),o.detail.value.length{const n=o.detail.value;i.searchParams.append("term",n),e.loading(!0),fetch(i.toString(),{signal:t.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(n)}))}),s))}(i,new AbortController,void 0,n.suggestionStarts,new URL(n.autocompleteEndpoint),e,n.autocompleteTriggerTimeout)}))}var te;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(te=t.UI.Input).textarea=new l,te.markdown=new y,te.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),te.tag=te.tag||{},te.tag.init=(e,t,n)=>ee(r,e,t,n)}($,il,document,Tagify); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",T="c-input-tree_select",L=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,_="hidden",N="disabled",q=".glyph",k=`.${C}`,M=`.${T}`,I=`.${T}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#T(t.selectButton,t.name),this.#L(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(N,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(N,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#_(n)}))}#_(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#N(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#N();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#N(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#L(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(_),e.querySelector(D)?.classList.remove(_),e.setAttribute("aria-label",this.#M("select_node",t))}#T(e,t){e.querySelector(D)?.classList.add(_),e.querySelector(H)?.classList.remove(_),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(N)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(N)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee={};function te(e,t,n,r){t.id,ee.instance_id=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURIComponent(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n)),ee.instance_id.addTags(r),null!==n.autocompleteEndpoint&&ee.instance_id.on("input",(e=>{!function(e,t,n,r,i,o,s){t.abort(),t=new AbortController,e.whitelist=null,"number"==typeof n&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(n),n=void 0),o.detail.value.length{const n=o.detail.value;i.searchParams.append("term",n),e.loading(!0),fetch(i.toString(),{signal:t.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(n)}))}),s))}(ee.instance_id,new AbortController,void 0,n.suggestionStarts,new URL(n.autocompleteEndpoint),e,n.autocompleteTriggerTimeout)}))}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tagInput=ne.tag||{},ne.tagInput.init=(e,t,n)=>te(r,e,t,n),ne.tagInput.getTagifyInstance=e=>ee.instance_id}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index 3cc24cb562a8..ad01cad2dcc3 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -14,6 +14,12 @@ */ /** + * + * @type {Object} + */ +const instances = {}; + +/* * @param {HTMLInput} input * @param {Object} config * @returns {Object} @@ -124,22 +130,32 @@ function retrieveAutocomplete( ); } +/** + * + * @param {string} instance_id + * @returns {Tagify} + */ +export function getTagifyInstance(instance_id) { + return instances.instance_id; +} + /** * @param {Tagify} Tagify * @param {HTMLInput} input * @param {Object} config * @param {array} value */ -export default function init(Tagify, input, config, value) { - const instance = new Tagify( +export function init(Tagify, input, config, value) { + const instance_id = input.id; + instances.instance_id = new Tagify( input, buildSettings(input.id, config), ); - instance.addTags(value); + instances.instance_id.addTags(value); if (config.autocompleteEndpoint !== null) { - instance.on('input', (event) => { + instances.instance_id.on('input', (event) => { retrieveAutocomplete( - instance, + instances.instance_id, new AbortController(), undefined, config.suggestionStarts, diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js index f7f452dfc31f..40eadac8975e 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js @@ -32,7 +32,7 @@ import MarkdownFactory from './Markdown/markdown.factory.js'; import TreeSelectFactory from './TreeSelect/TreeSelectFactory.js'; import JQueryEventListener from '../../../Core/src/JQueryEventListener.js'; import Tagify from 'Tagify'; -import tag from './Tag/tag.js'; +import * as tag from './Tag/tag.js'; il.UI = il.UI || {}; il.UI.Input = il.UI.Input || {}; @@ -47,6 +47,7 @@ il.UI.Input = il.UI.Input || {}; {txt: (s) => il.Language.txt(s)}, document, ); - Input.tag = Input.tag || {}; - Input.tag.init = (input, config, value) => tag(Tagify, input, config, value); + Input.tagInput = Input.tag || {}; + Input.tagInput.init = (input, config, value) => tag.init(Tagify, input, config, value); + Input.tagInput.getTagifyInstance = (input_id) => tag.getTagifyInstance(input_id); }(il.UI.Input)); diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php index e7265b1547ab..06a2158550ed 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php @@ -412,7 +412,7 @@ function ($v) { function ($id) use ($configuration, $value) { $encoded = json_encode($configuration); $value = json_encode($value); - return "il.UI.Input.tag.init(document.querySelector('#{$id} .c-field-tag'), {$encoded}, {$value});"; + return "il.UI.Input.tagInput.init(document.querySelector('#{$id} .c-field-tag'), {$encoded}, {$value});"; } ); diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php index bac66b215e51..4a8cb280815d 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php @@ -105,11 +105,7 @@ public function getConfiguration(): stdClass $configuration->dropdownSuggestionsStartAfter = $this->getSuggestionsStartAfter(); $configuration->suggestionStarts = $this->getSuggestionsStartAfter(); $configuration->autocompleteEndpoint = $this->getAsyncAutocomplete()?->__toString(); -<<<<<<< HEAD -======= $configuration->autocompleteTriggerTimeout = 200; - $configuration->orderable = $this->isOrderable(); ->>>>>>> 4f6837565c8 (UI: Do Not Bundel Parameters) $configuration->maxChars = 2000; $configuration->suggestionLimit = 50; $configuration->debug = false; From b78eecd6ba442028bfebdd9fa8434472526259a7 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Tue, 23 Sep 2025 16:47:34 +0200 Subject: [PATCH 07/16] UI: Scoped Variable for Timeout & AbortController --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 49 +++++++++++-------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 9978dc4a4e13..0af3b15c88bb 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",T="c-input-tree_select",L=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,_="hidden",N="disabled",q=".glyph",k=`.${C}`,M=`.${T}`,I=`.${T}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#T(t.selectButton,t.name),this.#L(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(N,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(N,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#_(n)}))}#_(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#N(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#N();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#N(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#L(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(_),e.querySelector(D)?.classList.remove(_),e.setAttribute("aria-label",this.#M("select_node",t))}#T(e,t){e.querySelector(D)?.classList.add(_),e.querySelector(H)?.classList.remove(_),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(N)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(N)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee={};function te(e,t,n,r){t.id,ee.instance_id=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURIComponent(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n)),ee.instance_id.addTags(r),null!==n.autocompleteEndpoint&&ee.instance_id.on("input",(e=>{!function(e,t,n,r,i,o,s){t.abort(),t=new AbortController,e.whitelist=null,"number"==typeof n&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(n),n=void 0),o.detail.value.length{const n=o.detail.value;i.searchParams.append("term",n),e.loading(!0),fetch(i.toString(),{signal:t.signal}).then((e=>e.json())).catch((()=>{})).then((t=>{e.whitelist=t,e.loading(!1).dropdown.show(n)}))}),s))}(ee.instance_id,new AbortController,void 0,n.suggestionStarts,new URL(n.autocompleteEndpoint),e,n.autocompleteTriggerTimeout)}))}var ne;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ne=t.UI.Input).textarea=new l,ne.markdown=new y,ne.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ne.tagInput=ne.tag||{},ne.tagInput.init=(e,t,n)=>te(r,e,t,n),ne.tagInput.getTagifyInstance=e=>ee.instance_id}($,il,document,Tagify); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",T="c-input-tree_select",L=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${T}`,I=`.${T}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#T(t.selectButton,t.name),this.#L(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#L(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#T(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=[];let te,ne;function re(e,t,n,r){ee[t.id]=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURIComponent(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n)),ee[t.id].addTags(r),null!==n.autocompleteEndpoint&&ee[t.id].on("input",(e=>{!function(e,t,n,r,i){void 0!==te&&te.abort(),te=new AbortController,e.whitelist=null,"number"==typeof ne&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(ne),ne=void 0),r.detail.value.length{const t=r.detail.value;n.searchParams.append("term",t),e.loading(!0),fetch(n.toString(),{signal:te.signal}).then((e=>e.json())).catch((()=>{})).then((n=>{e.whitelist=n,e.loading(!1).dropdown.show(t)}))}),i))}(ee[t.id],n.suggestionStarts,new URL(n.autocompleteEndpoint),e,n.autocompleteTriggerTimeout)}))}var ie;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ie=t.UI.Input).textarea=new l,ie.markdown=new y,ie.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ie.tagInput=ie.tag||{},ie.tagInput.init=(e,t,n)=>re(r,e,t,n),ie.tagInput.getTagifyInstance=e=>ee[e]}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index ad01cad2dcc3..e594c42af02f 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -15,9 +15,21 @@ /** * - * @type {Object} + * @type {Array} */ -const instances = {}; +const instances = []; + +/** + * + * @type {AbortController} + */ +let abortController; + +/** + * + * @type {number} + */ +let timeout; /* * @param {HTMLInput} input @@ -50,7 +62,7 @@ function buildSettings(inputId, config) { }, templates: { wrapper(input, _s) { - return `
${this.settings.templates.input.call(this)} \u200B -
` +
`; }, tag(tagData) { return `
answer.json()) .catch(() => {}) .then((options) => { @@ -132,11 +142,11 @@ function retrieveAutocomplete( /** * - * @param {string} instance_id + * @param {string} instanceId * @returns {Tagify} */ -export function getTagifyInstance(instance_id) { - return instances.instance_id; +export function getTagifyInstance(instanceId) { + return instances[instanceId]; } /** @@ -146,18 +156,15 @@ export function getTagifyInstance(instance_id) { * @param {array} value */ export function init(Tagify, input, config, value) { - const instance_id = input.id; - instances.instance_id = new Tagify( + instances[input.id] = new Tagify( input, buildSettings(input.id, config), ); - instances.instance_id.addTags(value); + instances[input.id].addTags(value); if (config.autocompleteEndpoint !== null) { - instances.instance_id.on('input', (event) => { + instances[input.id].on('input', (event) => { retrieveAutocomplete( - instances.instance_id, - new AbortController(), - undefined, + instances[input.id], config.suggestionStarts, new URL(config.autocompleteEndpoint), event, From a7133220487682f77a74decc2cab259fd9dc6bbc Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Tue, 23 Sep 2025 18:06:20 +0200 Subject: [PATCH 08/16] UI: Move Tags to URLBuilder & Token --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 17 +++++++----- .../js/Input/Field/src/input.factory.js | 3 ++- .../UI/src/Component/Input/Field/Tag.php | 8 +++--- .../Component/Input/Field/Renderer.php | 16 +++++++++-- .../Component/Input/Field/Tag.php | 27 ++++++++++++++----- .../Field/Tag/with_autocomplete_endpoint.php | 8 ++++-- 7 files changed, 59 insertions(+), 22 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 0af3b15c88bb..4f8958f73a51 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,4 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",T="c-input-tree_select",L=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${T}`,I=`.${T}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#T(t.selectButton,t.name),this.#L(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#L(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#T(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=[];let te,ne;function re(e,t,n,r){ee[t.id]=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURIComponent(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n)),ee[t.id].addTags(r),null!==n.autocompleteEndpoint&&ee[t.id].on("input",(e=>{!function(e,t,n,r,i){void 0!==te&&te.abort(),te=new AbortController,e.whitelist=null,"number"==typeof ne&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(ne),ne=void 0),r.detail.value.length{const t=r.detail.value;n.searchParams.append("term",t),e.loading(!0),fetch(n.toString(),{signal:te.signal}).then((e=>e.json())).catch((()=>{})).then((n=>{e.whitelist=n,e.loading(!1).dropdown.show(t)}))}),i))}(ee[t.id],n.suggestionStarts,new URL(n.autocompleteEndpoint),e,n.autocompleteTriggerTimeout)}))}var ie;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ie=t.UI.Input).textarea=new l,ie.markdown=new y,ie.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ie.tagInput=ie.tag||{},ie.tagInput.init=(e,t,n)=>re(r,e,t,n),ie.tagInput.getTagifyInstance=e=>ee[e]}($,il,document,Tagify); +!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",T="c-input-tree_select",L=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${T}`,I=`.${T}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#T(t.selectButton,t.name),this.#L(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#L(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#T(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=[];let te,ne;function re(e,t,n,r,i,o){ee[t.id]=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURIComponent(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n)),ee[t.id].addTags(r),void 0!==i&&ee[t.id].on("input",(e=>{!function(e,t,n,r,i,o){void 0!==te&&te.abort(),te=new AbortController,e.whitelist=null,"number"==typeof ne&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(ne),ne=void 0),i.detail.value.length{const t=i.detail.value;n.writeParameter(r,t),e.loading(!0),fetch(n.getUrl().toString(),{signal:te.signal}).then((e=>e.json())).catch((()=>{})).then((n=>{e.whitelist=n,e.loading(!1).dropdown.show(t)}))}),o))}(ee[t.id],n.suggestionStarts,i,o,e,n.autocompleteTriggerTimeout)}))}var ie;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ie=t.UI.Input).textarea=new l,ie.markdown=new y,ie.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ie.tagInput=ie.tag||{},ie.tagInput.init=(e,t,n,i,o)=>re(r,e,t,n,i,o),ie.tagInput.getTagifyInstance=e=>ee[e]}($,il,document,Tagify); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index e594c42af02f..8d6486834bf5 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -95,7 +95,8 @@ function buildSettings(inputId, config) { /** * @param {Tagify} instance * @param {number} suggestionsStartAfter - * @param {URL} autocompleteEndpoint + * @param {URLBuilder} autocompleteEndpoint + * @param {URLBuilderToken} autocompleteToken * @param {InputEvent} event * @param {number} tagAutocompleteTriggerTimeout * @returns {void} @@ -104,6 +105,7 @@ function retrieveAutocomplete( instance, suggestionsStartAfter, autocompleteEndpoint, + autocompleteToken, event, tagAutocompleteTriggerTimeout, ) { @@ -126,9 +128,9 @@ function retrieveAutocomplete( timeout = instance.DOM.scope.ownerDocument.defaultView.setTimeout( () => { const searchTerm = event.detail.value; - autocompleteEndpoint.searchParams.append('term', searchTerm); + autocompleteEndpoint.writeParameter(autocompleteToken, searchTerm); instance.loading(true); - fetch(autocompleteEndpoint.toString(), { signal: abortController.signal }) + fetch(autocompleteEndpoint.getUrl().toString(), { signal: abortController.signal }) .then((answer) => answer.json()) .catch(() => {}) .then((options) => { @@ -154,19 +156,22 @@ export function getTagifyInstance(instanceId) { * @param {HTMLInput} input * @param {Object} config * @param {array} value + * @param {URLBuilder} autocompleteEndpoint + * @param {URLBuilderToken} autocompleteToken */ -export function init(Tagify, input, config, value) { +export function init(Tagify, input, config, value, autocompleteEndpoint, autocompleteToken) { instances[input.id] = new Tagify( input, buildSettings(input.id, config), ); instances[input.id].addTags(value); - if (config.autocompleteEndpoint !== null) { + if (typeof autocompleteEndpoint !== 'undefined') { instances[input.id].on('input', (event) => { retrieveAutocomplete( instances[input.id], config.suggestionStarts, - new URL(config.autocompleteEndpoint), + autocompleteEndpoint, + autocompleteToken, event, config.autocompleteTriggerTimeout, ); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js index 40eadac8975e..8456592b4b20 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js @@ -48,6 +48,7 @@ il.UI.Input = il.UI.Input || {}; document, ); Input.tagInput = Input.tag || {}; - Input.tagInput.init = (input, config, value) => tag.init(Tagify, input, config, value); + Input.tagInput.init = (input, config, value, autocompleteEndpoint, autocompleteToken) => tag.init( + Tagify, input, config, value, autocompleteEndpoint, autocompleteToken); Input.tagInput.getTagifyInstance = (input_id) => tag.getTagifyInstance(input_id); }(il.UI.Input)); diff --git a/components/ILIAS/UI/src/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Component/Input/Field/Tag.php index 16bfe2421f60..ddf276ae2689 100755 --- a/components/ILIAS/UI/src/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Component/Input/Field/Tag.php @@ -23,7 +23,8 @@ use ILIAS\UI\Component\Input\Container\Form\FormInput; use ILIAS\UI\Component\Signal; use InvalidArgumentException; -use ILIAS\Data\URI; +use ILIAS\UI\URLBuilder; +use ILIAS\UI\URLBuilderToken; /** * Interface Tag @@ -61,12 +62,13 @@ public function withMaxTags(int $max_tags): self; /** * Get an input like this, but add an endpoint to get a list of possible options. - * The endpoint MUST answer to a query with the provided text as parameter "term". + * The $autocomplete_endpoint MUST answer to a query with the provided text + * handed over in the parameter defined in $term_token. * It MUST answer with a json array containing the options in the form of objects * containing three properties "value", "display", and "searchBy". The property * "value" MUST be save to transmit as url-parameter. */ - public function withAsyncAutocomplete(URI $autocomplete_endpoint): self; + public function withAsyncAutocomplete(URLBuilder $autocomplete_endpoint, URLBuilderToken $term_token): self; // Events diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php index 06a2158550ed..49cc9f19be3c 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php @@ -408,11 +408,23 @@ function ($v) { ); } + $autocomplete_endpoint = 'undefined'; + $autocomplete_token = 'undefined'; + if ($component->getAsyncAutocompleteEndpoint() !== null) { + $autocomplete_endpoint = $component->getAsyncAutocompleteEndpoint() + ->renderObject([$component->getAsyncAutocompleteToken()]); + $autocomplete_token = $component->getAsyncAutocompleteToken()->render(); + } + $component = $component->withAdditionalOnLoadCode( - function ($id) use ($configuration, $value) { + function ($id) use ($configuration, $value, $autocomplete_endpoint, $autocomplete_token) { $encoded = json_encode($configuration); $value = json_encode($value); - return "il.UI.Input.tagInput.init(document.querySelector('#{$id} .c-field-tag'), {$encoded}, {$value});"; + return 'il.UI.Input.tagInput.init(document.querySelector(' + . "'#{$id} .c-field-tag'), {$encoded}, {$value}," + . " {$autocomplete_endpoint}, " + . " {$autocomplete_token}" + . ");"; } ); diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php index 4a8cb280815d..6c843ad8b0d4 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php @@ -33,6 +33,8 @@ use LogicException; use ILIAS\UI\Implementation\Component\JavaScriptBindable; use ILIAS\UI\Implementation\Component\Triggerer; +use ILIAS\UI\URLBuilder; +use ILIAS\UI\URLBuilderToken; /** * Class TagInput @@ -55,7 +57,8 @@ class Tag extends FormInput implements C\Input\Field\Tag protected bool $extendable = true; protected int $suggestion_starts_with = 1; protected array $tags = []; - protected ?Uri $async_autocomplete = null; + protected ?URLBuilder $async_autocomplete_endpoint = null; + protected ?URLBuilderToken $async_autocomplete_token = null; public function __construct( DataFactory $data_factory, @@ -104,7 +107,6 @@ public function getConfiguration(): stdClass $configuration->userInput = $this->areUserCreatedTagsAllowed(); $configuration->dropdownSuggestionsStartAfter = $this->getSuggestionsStartAfter(); $configuration->suggestionStarts = $this->getSuggestionsStartAfter(); - $configuration->autocompleteEndpoint = $this->getAsyncAutocomplete()?->__toString(); $configuration->autocompleteTriggerTimeout = 200; $configuration->maxChars = 2000; $configuration->suggestionLimit = 50; @@ -272,19 +274,30 @@ public function getMaxTags(): int /** * @inheritDoc */ - public function withAsyncAutocomplete(URI $autocomplete_endpoint): Tag - { + public function withAsyncAutocomplete( + URLBuilder $autocomplete_endpoint, + URLBuilderToken $term_token + ): Tag { $clone = clone $this; - $clone->async_autocomplete = $autocomplete_endpoint; + $clone->async_autocomplete_endpoint = $autocomplete_endpoint; + $clone->async_autocomplete_token = $term_token; return $clone; } /** * @inheritDoc */ - public function getAsyncAutocomplete(): ?URI + public function getAsyncAutocompleteEndpoint(): ?URLBuilder + { + return $this->async_autocomplete_endpoint; + } + + /** + * @inheritDoc + */ + public function getAsyncAutocompleteToken(): ?URLBuilderToken { - return $this->async_autocomplete; + return $this->async_autocomplete_token; } /** diff --git a/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php b/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php index eeedd52ce962..c5d253c76032 100755 --- a/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php +++ b/components/ILIAS/UI/src/examples/Input/Field/Tag/with_autocomplete_endpoint.php @@ -49,8 +49,11 @@ function with_autocomplete_endpoint() $df = new \ILIAS\Data\Factory(); + [$url_builder, $term_token] = (new URLBuilder($df->uri($http->request()->getUri()->__toString()))) + ->acquireParameter(['examples'], 'term'); + $search_term = $http->wrapper()->query()->retrieve( - 'term', + $term_token->getName(), $refinery->byTrying([ $refinery->kindlyTo()->string(), $refinery->always('') @@ -87,7 +90,8 @@ static function (array $c, string $v) use ($refinery, $search_term): array { "Tag Input with Autocomplete", [] )->withAsyncAutocomplete( - $df->uri($http->request()->getUri()->__toString()) + $url_builder, + $term_token )->withUserCreatedTagsAllowed(false); return $renderer->render( From 193bdbf71b32ca59a4e2a8330bb5b84381c2f521 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Wed, 24 Sep 2025 16:33:35 +0200 Subject: [PATCH 09/16] UI: Add Tests to Tag --- .../Component/Input/Field/TagInputTest.php | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php b/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php index f4b2dc476897..5b9bb9811916 100755 --- a/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php +++ b/components/ILIAS/UI/tests/Component/Input/Field/TagInputTest.php @@ -24,9 +24,9 @@ require_once(__DIR__ . "/CommonFieldRendering.php"); use ILIAS\UI\Implementation\Component as I; -use ILIAS\UI\Implementation\Component\SignalGenerator; use ILIAS\Data; -use ILIAS\Refinery\Factory as Refinery; +use ILIAS\UI\URLBuilder; +use ILIAS\UI\URLBuilderToken; /** * Class TagInputTest @@ -265,4 +265,42 @@ public function testUITagInputSpecialChars(string ...$tags): void $this->assertTrue($content->isOk()); $this->assertEquals($tags, $content->value()); } + + public function testTagWithAutocompleteEndpoint(): void + { + $url_builder = new URLBuilder(new Data\URI('http://wwww.ilias.de?ref_id=1')); + $token = new URLBuilderToken(['t'], 't'); + $f = $this->getFieldFactory(); + $tag = $f->tag('my_tag', []); + + $this->assertEquals(null, $tag->getAsyncAutocompleteEndpoint()); + $this->assertEquals(null, $tag->getAsyncAutocompleteToken()); + + $tag = $tag->withAsyncAutocomplete( + $url_builder, + $token + ); + $this->assertEquals($url_builder, $tag->getAsyncAutocompleteEndpoint()); + $this->assertEquals($token, $tag->getAsyncAutocompleteToken()); + } + + public function testTagWithAutocompleteEndpointJSAdded(): void + { + $token = $this->createMock(URLBuilderToken::class); + $token->expects($this->once()) + ->method('render'); + $url_builder = $this->createMock(URLBuilder::class); + $url_builder->expects($this->once()) + ->method('renderObject') + ->with([$token]); + + $f = $this->getFieldFactory(); + $tag = $f->tag('my_tag', [])->withAsyncAutocomplete( + $url_builder, + $token + ); + + $renderer = $this->getDefaultRenderer(); + $renderer->render($tag); + } } From 44c38bf11054ad812a7d1d61d19ad6904f6f447c Mon Sep 17 00:00:00 2001 From: Thibeau Fuhrer Date: Wed, 8 Oct 2025 21:39:10 +0200 Subject: [PATCH 10/16] [FEATURE] UI: add JS unit test example for Tagify instance. --- .../ILIAS/UI/tests/Client/Input/Field/Tag.js | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 components/ILIAS/UI/tests/Client/Input/Field/Tag.js diff --git a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js new file mode 100644 index 000000000000..5be6ce83dc7d --- /dev/null +++ b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js @@ -0,0 +1,103 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + * @author Thibeau Fuhrer + */ + +import { describe, it, mock } from 'node:test'; +import { strict } from 'node:assert/strict'; +import { init } from '../../../../resources/js/Input/Field/src/Tag/tag.js'; + +describe('Tag Input Field', () => { + const pseudoConfig = { + options: [], + userInput: false, + allowDuplicates: false, + maxItems: 5, + dropdownSuggestionsStartAfter: 1, + suggestionStarts: 1, + autocompleteTriggerTimeout: 100, + dropdownMaxItems: 5, + dropdownCloseOnSelect: true, + highlight: true, + }; + it('should call the provided async endpoint.', () => { + const inputMock = { + id: 'test-id', + }; + const tagifyWindowMock = { + setTimeout: mock.fn(() => {}), + clearTimeout: () => { + }, + }; + const tagifyInstanceMock = { + DOM: { scope: { ownerDocument: { defaultView: tagifyWindowMock } } }, + on: mock.fn(() => { + }), + loading: () => { + }, + addTags: () => { + }, + }; + const tagifyMock = class { + constructor() { + // eslint-disable-next-line no-constructor-return + return tagifyInstanceMock; + } + }; + const urlBuilderMock = { + writeParameter: () => { + }, + getUrl() { + return { + toString() { + return ''; + }, + }; + }, + }; + const urlBuilderTokenMock = {}; + + init(tagifyMock, inputMock, pseudoConfig, [], urlBuilderMock, urlBuilderTokenMock); + + strict.equal(tagifyInstanceMock.on.mock.callCount(), 1); + strict.equal(tagifyInstanceMock.on.mock.calls[0].arguments[0], 'input'); + const inputEventHandler = tagifyInstanceMock.on.mock.calls[0].arguments[1]; + strict.notEqual(inputEventHandler, undefined); + strict.notEqual(inputEventHandler, null); + + const eventMock = { + detail: { value: { length: pseudoConfig.suggestionStarts + 1 } }, + }; + mock.method(global, 'AbortController', { signal: '' }); + const fetchMock = mock.fn(() => new Promise(() => {})); + mock.method(global, 'fetch', fetchMock); + + inputEventHandler(eventMock); + + strict.equal(tagifyWindowMock.setTimeout.mock.callCount(), 1); + strict.equal( + tagifyWindowMock.setTimeout.mock.calls[0].arguments[1], + pseudoConfig.autocompleteTriggerTimeout, + ); + const timoutHandler = tagifyWindowMock.setTimeout.mock.calls[0].arguments[0]; + strict.notEqual(timoutHandler, undefined); + strict.notEqual(timoutHandler, null); + + timoutHandler(); + strict.equal(fetchMock.mock.callCount(), 1); + + mock.reset(); + }); +}); From dc0c7916c8497729b4f37a70813a1c4dd2a80071 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Thu, 9 Oct 2025 18:04:52 +0200 Subject: [PATCH 11/16] UI: Add More JS-Tests to Tag --- .../ILIAS/UI/tests/Client/Input/Field/Tag.js | 206 ++++++++++++++---- 1 file changed, 159 insertions(+), 47 deletions(-) diff --git a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js index 5be6ce83dc7d..ecfd8ed66ada 100644 --- a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js +++ b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js @@ -16,12 +16,12 @@ */ import { describe, it, mock } from 'node:test'; -import { strict } from 'node:assert/strict'; +import * as assert from 'node:assert'; import { init } from '../../../../resources/js/Input/Field/src/Tag/tag.js'; describe('Tag Input Field', () => { const pseudoConfig = { - options: [], + options: ['123', 'Yay'], userInput: false, allowDuplicates: false, maxItems: 5, @@ -32,50 +32,52 @@ describe('Tag Input Field', () => { dropdownCloseOnSelect: true, highlight: true, }; - it('should call the provided async endpoint.', () => { - const inputMock = { - id: 'test-id', - }; - const tagifyWindowMock = { - setTimeout: mock.fn(() => {}), - clearTimeout: () => { - }, - }; - const tagifyInstanceMock = { - DOM: { scope: { ownerDocument: { defaultView: tagifyWindowMock } } }, - on: mock.fn(() => { - }), - loading: () => { - }, - addTags: () => { - }, - }; - const tagifyMock = class { - constructor() { - // eslint-disable-next-line no-constructor-return - return tagifyInstanceMock; - } - }; - const urlBuilderMock = { - writeParameter: () => { - }, - getUrl() { - return { - toString() { - return ''; - }, - }; - }, - }; - const urlBuilderTokenMock = {}; + const inputMock = { + id: 'test-id', + }; + const tagifyWindowMock = { + setTimeout: mock.fn(() => {}), + clearTimeout: () => { + }, + }; + const tagifyInstanceMock = { + DOM: { scope: { ownerDocument: { defaultView: tagifyWindowMock } } }, + on: mock.fn(() => { + }), + loading: () => { + }, + addTags: () => { + }, + settings: null, + }; + const tagifyMock = class { + constructor(inputMock, settings) { + tagifyInstanceMock.settings = settings; + // eslint-disable-next-line no-constructor-return + return tagifyInstanceMock; + } + }; + const urlBuilderMock = { + writeParameter: () => { + }, + getUrl() { + return { + toString() { + return ''; + }, + }; + }, + }; + const urlBuilderTokenMock = {}; + it('should call the provided async endpoint.', () => { init(tagifyMock, inputMock, pseudoConfig, [], urlBuilderMock, urlBuilderTokenMock); - strict.equal(tagifyInstanceMock.on.mock.callCount(), 1); - strict.equal(tagifyInstanceMock.on.mock.calls[0].arguments[0], 'input'); + assert.strict.equal(tagifyInstanceMock.on.mock.callCount(), 1); + assert.strict.equal(tagifyInstanceMock.on.mock.calls[0].arguments[0], 'input'); const inputEventHandler = tagifyInstanceMock.on.mock.calls[0].arguments[1]; - strict.notEqual(inputEventHandler, undefined); - strict.notEqual(inputEventHandler, null); + assert.strict.notEqual(inputEventHandler, undefined); + assert.strict.notEqual(inputEventHandler, null); const eventMock = { detail: { value: { length: pseudoConfig.suggestionStarts + 1 } }, @@ -86,17 +88,127 @@ describe('Tag Input Field', () => { inputEventHandler(eventMock); - strict.equal(tagifyWindowMock.setTimeout.mock.callCount(), 1); - strict.equal( + assert.strict.equal(tagifyWindowMock.setTimeout.mock.callCount(), 1); + assert.strict.equal( tagifyWindowMock.setTimeout.mock.calls[0].arguments[1], pseudoConfig.autocompleteTriggerTimeout, ); const timoutHandler = tagifyWindowMock.setTimeout.mock.calls[0].arguments[0]; - strict.notEqual(timoutHandler, undefined); - strict.notEqual(timoutHandler, null); + assert.strict.notEqual(timoutHandler, undefined); + assert.strict.notEqual(timoutHandler, null); timoutHandler(); - strict.equal(fetchMock.mock.callCount(), 1); + assert.strict.equal(fetchMock.mock.callCount(), 1); + + mock.reset(); + }); + + it('should build correct settings.', () => { + init(tagifyMock, inputMock, pseudoConfig, [], urlBuilderMock, urlBuilderTokenMock); + + assert.strict.equal(tagifyInstanceMock.settings.whitelist, pseudoConfig.options); + assert.strict.equal(tagifyInstanceMock.settings.enforceWhitelist, !pseudoConfig.userInput); + assert.strict.equal(tagifyInstanceMock.settings.duplicates, pseudoConfig.allowDuplicates); + assert.strict.equal(tagifyInstanceMock.settings.maxTags, pseudoConfig.maxItems); + assert.strict.equal(tagifyInstanceMock.settings.dropdown.enabled, pseudoConfig.dropdownSuggestionsStartAfter); + assert.strict.equal(tagifyInstanceMock.settings.dropdown.maxItems, pseudoConfig.dropdownMaxItems); + assert.strict.equal(tagifyInstanceMock.settings.dropdown.closeOnSelect, pseudoConfig.dropdownCloseOnSelect); + assert.strict.equal(tagifyInstanceMock.settings.dropdown.highlightFirst, pseudoConfig.highlight); + + mock.reset(); + }); + + it('should urldecode user input.', () => { + const userInput = [ + {value: '++1#*'}, + {value: '[-2]'}, + {value: '{?3}'}, + {value: 'some\'thing "else"'}, + {value: '&/\\'}, + {value: 'fünf, sechs'}, + {value: 'sieben, acht'}, + {value: ''}, + {value: ''}, + ]; + init(tagifyMock, inputMock, pseudoConfig, userInput, urlBuilderMock, urlBuilderTokenMock); + + userInput.forEach((v) => { + const display = v.value; + tagifyInstanceMock.settings.transformTag(v); + assert.deepEqual(v, {value: encodeURIComponent(display), display: display.replace(//g, '>')}); + }); + + mock.reset(); + }); + + it('should wrapp in div with attributes.', () => { + const tagData = {value: 'test', display: 'test', tagifySuggestionIdx: 'test'}; + init(tagifyMock, inputMock, pseudoConfig, tagData, urlBuilderMock, urlBuilderTokenMock); + + const input = {className: 'test'}; + + const config = [ + {classNames: {namespace: 'all_false'}, readonly: false, disabled: false, required: false, mode: ''}, + {classNames: {namespace: 'all_true', strictMode: 'strict_mode'}, readonly: true, disabled: true, required: true, mode: 'strict'}, + ]; + + const result = [ + `
\u200B
`.replace(/ /g, ''), + `
\u200B
`.replace(/ /g, ''), + ]; + + config.forEach( + (v, i) => { + const test_obj = new class { + settings = {templates: {input: {call: () => ''}}}; + + test(wrapper_function, v, result) { + const wf = wrapper_function.bind(this); + console.log(this.settings.templates.input.call); + assert.strict.equal( + wf(input, v).replace(/[ \n]/g, ''), + result, + ); + } + }; + + test_obj.test(tagifyInstanceMock.settings.templates.wrapper, v, result[i]); + } + ); + + mock.reset(); + }); + + it('should build correct tags as divs.', () => { + const tagData = {value: 'test', display: 'test', tagifySuggestionIdx: 'test'}; + init(tagifyMock, inputMock, pseudoConfig, tagData, urlBuilderMock, urlBuilderTokenMock); + + assert.strict.equal( + tagifyInstanceMock.settings.templates.tag(tagData), + `
+ +
+ ${tagData.display} +
+
` + ); + + mock.reset(); + }); + + it('should build correct dropdowns as divs.', () => { + const tagData = {value: 'test', display: 'test', tagifySuggestionIdx: 'test'}; + init(tagifyMock, inputMock, pseudoConfig, tagData, urlBuilderMock, urlBuilderTokenMock); + + assert.strict.equal( + tagifyInstanceMock.settings.templates.dropdownItem(tagData), + `
+ ${tagData.display} +
` + ); mock.reset(); }); From dab5dfc1d649651904c19e472472f28f29d3dbeb Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Thu, 9 Oct 2025 18:16:28 +0200 Subject: [PATCH 12/16] UI: Import Tagify from Node-Module --- .../js/Input/Field/dist/input.factory.min.js | 28 ++++++++++++++++++- .../resources/js/Input/Field/rollup.config.js | 5 +++- .../js/Input/Field/src/input.factory.js | 2 +- .../Component/Input/Field/Renderer.php | 1 - 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 4f8958f73a51..0fddc449ba72 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -12,4 +12,30 @@ * https://www.ilias.de * https://github.com/ILIAS-eLearning */ -!function(e,t,n,r){"use strict";class i{textarea;remainder=null;constructor(e){if(this.textarea=document.getElementById(e),null===this.textarea)throw new Error(`Could not find textarea for input-id '${e}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${e}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(e,t=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(e))return this.updateRemainderCountHook(),void this.textarea.focus();t=t??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=e,tthis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return s(this.textarea.value).slice(0,o(this.getTextBeforeSelection()))}getLinesAfterSelection(){const e=s(this.textarea.value);return e.slice(o(this.getTextBeforeSelection()+this.getTextOfSelection())+1,e.length)}getLinesOfSelection(){const e=s(this.textarea.value);return e.slice(this.getLinesBeforeSelection().length,e.length-this.getLinesAfterSelection().length)}isContentTooLarge(e){const t=this.getMaxLength();return!(t<0)&&t0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function o(e){return(e.match(/\n/g)??[]).length}function s(e){return e.split(/\n/)}class l{instances=[];init(e){if(void 0!==this.instances[e])throw new Error(`Textarea with input-id '${e}' has already been initialized.`);this.instances[e]=new i(e)}get(e){return this.instances[e]??null}}class a{preview_parameter;preview_url;constructor(e,t){this.preview_parameter=e,this.preview_url=t}async getPreviewHtmlOf(e){if(0===e.length)return"";let t=new FormData;return t.append(this.preview_parameter,e),(await fetch(this.preview_url,{method:"POST",body:t})).text()}}const c="textarea",d="preview";class u extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(e,t){super(t);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${t}'.`);this.preview_renderer=e,this.content_wrappers=function(e){const t=new Map;return t.set(c,e.querySelector("textarea")),t.set(d,e.querySelector(".c-field-markdown__preview")),t.forEach((e=>{if(null===e)throw new Error("Could not find all content-wrappers for markdown-input.")})),t}(n),this.view_controls=function(e){const t=e.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!t instanceof HTMLCollection||2!==t.length)throw new Error("Could not find exactly two view-controls.");return[...t]}(n),this.actions=function(e){const t=e.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(t instanceof HTMLCollection)return[...t];return[]}(n);let r=!0;this.textarea.addEventListener("keydown",(e=>{r=this.handleEnterKeyBeforeInsertionHook(e)})),this.textarea.addEventListener("keyup",(e=>{this.handleEnterKeyAfterInsertionHook(e,r)})),this.actions.forEach((e=>{e.addEventListener("click",(e=>{this.performMarkdownActionHook(e)}))})),this.view_controls.forEach((e=>{e.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(e,t){if(!t||!f(e))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&p(n)?this.applyTransformationToSelection(h):void 0!==n&&w(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(e){if(!f(e))return!1;const t=this.getLinesOfSelection().shift();if(void 0===t||!((t.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),r=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),r.length>0&&(r=`\n${r}`),this.updateTextareaContent(n+r,this.getAbsoluteSelectionStart()-t.length,this.getAbsoluteSelectionEnd()-t.length),e.preventDefault(),!1}performMarkdownActionHook(e){const t=function(e){const t=e.closest("span[data-action]");if(!t instanceof HTMLSpanElement)return null;if(!t.hasAttribute("data-action"))return null;return t.dataset.action}(e.target);switch(t){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(h);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(g):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${t}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((e=>{m(e,"hidden")})),this.view_controls.forEach((e=>{m(e,"engaged")})),this.isDisabled()||this.actions.forEach((e=>{e.disabled=!e.disabled;const t=e.querySelector(".glyph");null!==t&&m(t,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const e=this.getLinesOfSelection();if(1!==e.length)return void this.textarea.focus();const t=this.getLinesBeforeSelection(),n=t.length-1;let r=n>=0?function(e){const t=e.match(/([0-9]+)/);if(null!==t)return parseInt(t[0]);return null}(t[n])??0:0;const i=g(e,++r),o=function(e,t=0){if(e.length<1)return[];const n=[];for(const r of e){if(!w(r))break;n.push(r.replace(/([0-9]+)/,(++t).toString()))}n.length>0&&(e=n.concat(e.slice(n.length)));return e}(this.getLinesAfterSelection(),r);let s=t.join("\n");const l=o.join("\n");let a=i.join("\n");s.length>0&&a.length>0&&(s+="\n"),a.length>0&&l.length>0&&(a+="\n");const c=s+a+l,d=c.length-this.textarea.value.length;this.updateTextareaContent(c,this.getAbsoluteSelectionStart()+d,this.getAbsoluteSelectionEnd()+d)}applyTransformationToSelection(e){if(!e instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof e} given.`);const t=e(this.getLinesOfSelection());if(!t instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof t} returned.`);const n=t.length>1;let r=this.getLinesBeforeSelection().join("\n");const i=this.getLinesAfterSelection().join("\n");let o=t.join("\n");r.length>0&&o.length>0&&(r+="\n"),o.length>0&&i.length>0&&(o+="\n");const s=r+o+i,l=s.length-this.textarea.value.length,a=n?r.length:this.getAbsoluteSelectionStart()+l,c=n?a+o.length-1:this.getAbsoluteSelectionEnd()+l;this.updateTextareaContent(s,a,c)}insertCharactersAroundSelection(e,t){const n=this.getTextBeforeSelection()+e+this.getTextOfSelection()+t+this.getTextAfterSelection(),r=this.getAbsoluteSelectionStart()+e.length,i=this.getAbsoluteSelectionEnd()+e.length;this.updateTextareaContent(n,r,i)}maybeUpdatePreviewContent(){const e=this.preview_history[this.preview_history.length-1]??"",t=this.textarea.value;t!==e&&(this.preview_history.push(t),this.preview_renderer.getPreviewHtmlOf(t).then((e=>{this.content_wrappers.get(d).innerHTML=e})))}getBulletPointTransformation(){return h}getEnumerationTransformation(){return g}}function h(e){const t=[],n=!p(e[0]??"");for(const r of e)t.push(n?`- ${r}`:S(r));return t}function g(e,t=1){const n=[],r=!w(e[0]??"");for(const i of e)n.push(r?`${t++}. ${i}`:S(i));return n}function m(e,t){e.classList.contains(t)?e.classList.remove(t):e.classList.add(t)}function f(e){return e instanceof KeyboardEvent&&"Enter"===e.code}function S(e){return e.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function p(e){return(e.match(/^(\s*[-])/g)??[]).length>0}function w(e){return(e.match(/^(\s*\d+\.)/g)??[]).length>0}class y{instances=[];init(e,t,n){if(void 0!==this.instances[e])throw new Error(`Markdown with input-id '${e}' has already been initialized.`);this.instances[e]=new u(new a(n,t),e)}get(e){return this.instances[e]??null}}class E{constructor(e,t,n,r,i,o=null,s=null,l=null){this.id=e,this.name=t,this.element=n,this.selectButton=r,this.drilldownParentLevel=i,this.drilldownButton=o,this.listElement=s,this.renderUrl=l}}const b="data-node-id",v="data-node-name",x="data-render-url",A="data-ddindex",C="c-input-node",T="c-input-tree_select",L=`${C}__async`,B=`${C}__leaf`,$=`${C}--selected`,N="hidden",_="disabled",q=".glyph",k=`.${C}`,M=`.${T}`,I=`.${T}__selection`,H='[data-action="remove"]',D='[data-action="select"]',R=`.${C}__select`,O=".c-drilldown__menulevel--trigger";function j(e){return function(e){return e.classList.contains(L)}(e)&&e.hasAttribute(x)?e.getAttribute(x):null}function U(e){return!e.classList.contains(B)&&e.classList.contains(C)}function F(e,t=null){return e.reduce(((e,t)=>{const n=function(e){const t=e.getAttribute(b);if(null===t)throw new Error("Could not find data-node-id attribute.");return t}(t);if(e.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return e.set(n,new E(n,function(e){const t=e.querySelector(`[${v}]`);if(null===t)throw new Error("Could not find element with data-node-name attribute.");return t.textContent}(t),t,function(e){const t=e.querySelector(`:scope > ${R}`);if(null===t)throw new Error("Could not find node select button.");return t}(t),function(e){const t=e.closest(`ul[${A}]`);if(null===t)throw new Error("Could not find drilldown menu of node.");return t.getAttribute(A)}(t),function(e){if(!U(e))return null;const t=e.querySelector(`${O}`);if(null===t)throw new Error("Could not find drilldown menu button of branch node.");return t}(t),function(e){if(!U(e))return null;const t=e.querySelector("ul");if(null===t)throw new Error("Could not find list element of branch node.");return t}(t),j(t)))}),new Map(t??[]))}function P(e,t){for(let n=0;n{this.#f()})),this.#m.querySelectorAll('[data-action="close"]').forEach((e=>{e.addEventListener("click",(()=>{this.#S()}))})),this.#d.querySelectorAll("li").forEach((e=>{const t=function(e){const t=e.getAttribute(b);if(null===t)throw new Error(`Could not find '${b}' attribbute of element.`);return t}(e);this.#p(e,t),this.#w(t)})),this.#l.addEngageListener((e=>{this.#y(e)})),this.#g.addEventListener("click",(()=>{this.#E()})),this.#e.forEach((e=>{this.#b(e)})),this.#v()}unselectNode(e){if(this.#x(e),this.#v(),this.#A(e),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!1),this.#C(t.selectButton,t.name),this.updateNodeSelectButtonStates()}}selectNode(e){if(this.#w(e),this.#v(),this.#e.has(e)){const t=this.#e.get(e);K(t.element,!0),this.#T(t.selectButton,t.name),this.#L(t),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#e.forEach(((e,t)=>{this.#t.size>0?(e.selectButton.disabled=!this.#t.has(t),e.selectButton.querySelector(q).classList.toggle(_,!this.#t.has(t))):(e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.toggle(_,!1))}))}getSelection(){return new Set(this.#t)}getNodes(){return new Map(this.#e)}async#B(e){var t,n,r;if(!this.#n.has(e.id)&&!this.#r.has(e.id))try{this.#r.add(e.id);const i=await this.#o.loadContent(e.renderUrl);e.listElement.append(...i.children),this.#l.parseLevels();const o=F((r=e.listElement,Array.from(r.querySelectorAll(k))),this.#e),s=(t=o,n=this.#e,Array.from(t.entries()).filter((([e])=>!n.has(e))).map((([,e])=>e)));this.#e=o,P(s,(e=>{this.#t.has(e.id)?this.selectNode(e.id):this.unselectNode(e.id),this.#b(e)})),this.#n.add(e.id)}catch(e){throw new Error(`Could not render async node children: ${e.message}`)}finally{this.#r.delete(e.id)}}#$(e){P(function(e,t,n=255){const r=[];let i=e;for(let e=0;e{const t=e.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find '${b}' of node element.`);const n=this.#e.get(t);this.#N(n)}))}#N(e){const t=this.#i.createContent(this.#c).querySelector(".crumb");t.setAttribute(A,e.drilldownParentLevel),t.firstElementChild.textContent=e.name,t.addEventListener("click",(()=>{this.#l.engageLevel(e.drilldownParentLevel),e.drilldownButton.click()})),this.#a.append(t)}#f(){const e=this.#a.querySelectorAll(".crumb");e.item(e.length-1)?.remove()}#_(){P(this.#a.querySelectorAll(".crumb"),(e=>{e.remove()}))}#y(e){if("0"===e)return void this.#_();const t=this.#m.querySelector(`ul[${A}="${e}"]`)?.closest(k)?.getAttribute(b);if(null===t||!this.#e.has(t))throw new Error(`Could not find node for drilldown-level '${e}'.`);this.#_(),this.#$(this.#e.get(t))}#q(e,t){e.addEventListener("click",(()=>{null!==t.renderUrl&&this.#B(t)}))}#p(e,t){e.querySelector(H)?.addEventListener("click",(()=>{this.unselectNode(t),e.remove()}))}#k(e,t){e.addEventListener("click",(()=>{this.#t.has(t.id)?this.unselectNode(t.id):this.selectNode(t.id)}))}#L(e){if(null!==this.#d.querySelector(`li[${b}="${e.id}"]`))return;const t=this.#i.createContent(this.#u),n=t.querySelector("[data-node-id]");n.setAttribute(b,e.id),n.querySelector(`[${v}]`).textContent=e.name,n.querySelector("input").value=e.id,this.#p(n,e.id),this.#d.append(...t.children)}#A(e){this.#d.querySelector(`li[${b}="${e}"]`)?.remove()}#b(e){this.#k(e.selectButton,e),null!==e.drilldownButton&&this.#q(e.drilldownButton,e)}#C(e,t){e.querySelector(H)?.classList.add(N),e.querySelector(D)?.classList.remove(N),e.setAttribute("aria-label",this.#M("select_node",t))}#T(e,t){e.querySelector(D)?.classList.add(N),e.querySelector(H)?.classList.remove(N),e.setAttribute("aria-label",this.#M("unselect_node",t))}#v(){this.#h.disabled=this.#t.size<=0}#x(e){this.#t.has(e)&&this.#t.delete(e)}#w(e){this.#t.has(e)||this.#t.add(e)}#M(e,...t){return function(e,...t){const n=[...t];return e.replace(/%s/g,(()=>n.shift()??""))}(this.#s.txt(e),t)}#S(){this.#m.close()}#E(){this.#m.showModal()}}class z extends V{#I;constructor(e,t,n,r,i,o,s,l,a,c,d,u,h,g){super(e,t,n,r,i,o,s,l,a,c,d,u,h),this.#I=g}selectNode(e){if(!this.#I){const t=Array.from(this.getSelection().add(e));this.#H(t,this.getNodes())}super.selectNode(e)}updateNodeSelectButtonStates(){if(this.#I)return;const e=this.getNodes();e.forEach((e=>{e.selectButton.disabled=!1,e.selectButton.querySelector(q).classList.remove(_)})),this.getSelection().forEach((t=>{const n=e.get(t);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(R).forEach((e=>{e.disabled=!0,e.querySelector(q).classList.add(_)}))}))}#H(e,t){for(let r=0;r{const r=e.getAttribute(n);if(!t.has(r))throw new Error(`Element references '${r}' which does not exist.`);e.setAttribute(n,t.get(r))}))}class G{#D;constructor(e){this.#D=e}createContent(e){const t=e.content.cloneNode(!0),n=new Map;return t.querySelectorAll("[id]").forEach((e=>{const t=function(e=""){return`${e}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(e.id,t),e.id=t})),t.querySelectorAll("[for]").forEach((e=>{e.htmlFor=n.get(e.htmlFor)})),W(t,n,"aria-describedby"),W(t,n,"aria-labelledby"),W(t,n,"aria-controls"),W(t,n,"aria-owns"),Q(this.#D,t.children)}}class J{#D;constructor(e){this.#D=e}loadContent(e){return fetch(e.toString()).then((e=>e.text())).then((e=>this.#R(e))).then((e=>Q(this.#D,e))).catch((t=>{throw new Error(`Could not render element(s) from '${e}': ${t.message}`)}))}#O(e){const t=this.#D.createElement("script");return e.hasAttribute("type")&&t.setAttribute("type",e.getAttribute("type")),e.hasAttribute("src")&&t.setAttribute("src",e.getAttribute("src")),e.textContent.length>0&&(t.textContent=e.textContent),t}#R(e){const t=this.#D.createElement("div");return t.innerHTML=e.trim(),t.querySelectorAll("script").forEach((e=>{const t=this.#O(e);e.replaceWith(t)})),t.children}}function X(e){return Array.from(e.querySelectorAll(k))}class Y{#j=new Map;#U;#F;#s;#D;constructor(e,t,n,r){this.#U=e,this.#F=t,this.#s=n,this.#D=r}initTreeMultiSelect(e,t){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[n,r,i,o,s,l,a,c]=this.#P(e),d=this.#K(r),u=new z(F(X(a)),this.#U,new G(this.#D),new J(this.#D),this.#s,d,i,o,s,l,c,n,a,t);return this.#j.set(e,u),u}initTreeSelect(e){if(this.#j.has(e))throw new Error(`TreeSelect '${e}' already exists.`);const[t,n,r,i,o,s,l,a]=this.#P(e),c=this.#K(n),d=new V(F(X(l)),this.#U,new G(this.#D),new J(this.#D),this.#s,c,r,i,o,s,a,t,l);return this.#j.set(e,d),d}getInstance(e){return this.#j.has(e)?this.#j.get(e):null}#P(e){const t=this.#D.getElementById(e),n=t?.closest(M),r=n?.querySelector(".breadcrumb"),i=n?.querySelector(".modal-body > template"),o=n?.querySelector(I),s=o?.querySelector(":scope > template"),l=n?.querySelector("dialog"),a=l?.querySelector(".btn-primary");if(null===r||null===i||null===o||null===s||null===a||null===t||null===l)throw new Error(`Could not find some element(s) for Tree Select Input '${e}'.`);return[t,n,r,i,o,s,l,a]}#K(e){const t=e.querySelector(".c-drilldown");if(null===t||!t.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(t.id);if(null===t)throw new Error("Could not find drilldown instance.");return n}}class Z{#V;constructor(e){this.#V=e}on(e,t,n){this.#V(e).on(t,n)}off(e,t,n){this.#V(e).off(t,n)}}const ee=[];let te,ne;function re(e,t,n,r,i,o){ee[t.id]=new e(t,function(e,t){return{id:e,whitelist:t.options,enforceWhitelist:!t.userInput,duplicates:t.allowDuplicates,maxTags:t.maxItems,delimiters:null,originalInputValueFormat:e=>e.map((e=>e.value)),dropdown:{enabled:t.dropdownSuggestionsStartAfter,maxItems:t.dropdownMaxItems,closeOnSelect:t.dropdownCloseOnSelect,highlightFirst:t.highlight},transformTag(e){e.display||(e.display=e.value,e.value=encodeURIComponent(e.value)),e.display=e.display.replace(//g,">")},templates:{wrapper(e,t){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:e=>`
\n \n
\n ${e.display}\n
\n
`,dropdownItem:e=>`
\n ${e.display}\n
`}}}(t.id,n)),ee[t.id].addTags(r),void 0!==i&&ee[t.id].on("input",(e=>{!function(e,t,n,r,i,o){void 0!==te&&te.abort(),te=new AbortController,e.whitelist=null,"number"==typeof ne&&(e.DOM.scope.ownerDocument.defaultView.clearTimeout(ne),ne=void 0),i.detail.value.length{const t=i.detail.value;n.writeParameter(r,t),e.loading(!0),fetch(n.getUrl().toString(),{signal:te.signal}).then((e=>e.json())).catch((()=>{})).then((n=>{e.whitelist=n,e.loading(!1).dropdown.show(t)}))}),o))}(ee[t.id],n.suggestionStarts,i,o,e,n.autocompleteTriggerTimeout)}))}var ie;t.UI=t.UI||{},t.UI.Input=t.UI.Input||{},(ie=t.UI.Input).textarea=new l,ie.markdown=new y,ie.treeSelect=new Y(new Z(e),t.UI.menu.drilldown,{txt:e=>t.Language.txt(e)},n),ie.tagInput=ie.tag||{},ie.tagInput.init=(e,t,n,i,o)=>re(r,e,t,n,i,o),ie.tagInput.getTagifyInstance=e=>ee[e]}($,il,document,Tagify); +!function(t,e,n){"use strict";class i{textarea;remainder=null;constructor(t){if(this.textarea=document.getElementById(t),null===this.textarea)throw new Error(`Could not find textarea for input-id '${t}'.`);if(this.shouldShowRemainder()){if(this.remainder=this.textarea.parentNode.querySelector('[data-action="remainder"]'),!this.remainder instanceof HTMLSpanElement)throw new Error(`Could not find remainder-element for input-id '${t}'.`);this.textarea.addEventListener("input",(()=>{this.updateRemainderCountHook()}))}}updateRemainderCountHook(){this.shouldShowRemainder()&&null!==this.remainder&&(this.remainder.innerHTML=(this.textarea.maxLength-this.textarea.value.length).toString())}updateTextareaContent(t,e=null,n=null){if(!this.isDisabled()){if(this.isContentTooLarge(t))return this.updateRemainderCountHook(),void this.textarea.focus();e=e??this.textarea.selectionStart,n=n??this.textarea.selectionEnd,this.textarea.value=t,ethis.textarea.selectionEnd?this.textarea.selectionStart:this.textarea.selectionEnd}getLinesBeforeSelection(){return a(this.textarea.value).slice(0,s(this.getTextBeforeSelection()))}getLinesAfterSelection(){const t=a(this.textarea.value);return t.slice(s(this.getTextBeforeSelection()+this.getTextOfSelection())+1,t.length)}getLinesOfSelection(){const t=a(this.textarea.value);return t.slice(this.getLinesBeforeSelection().length,t.length-this.getLinesAfterSelection().length)}isContentTooLarge(t){const e=this.getMaxLength();return!(e<0)&&e0}getMaxLength(){return Number(this.textarea.getAttribute("maxlength")??-1)}isDisabled(){return this.textarea.disabled}}function s(t){return(t.match(/\n/g)??[]).length}function a(t){return t.split(/\n/)}class o{instances=[];init(t){if(void 0!==this.instances[t])throw new Error(`Textarea with input-id '${t}' has already been initialized.`);this.instances[t]=new i(t)}get(t){return this.instances[t]??null}}class r{preview_parameter;preview_url;constructor(t,e){this.preview_parameter=t,this.preview_url=e}async getPreviewHtmlOf(t){if(0===t.length)return"";let e=new FormData;return e.append(this.preview_parameter,t),(await fetch(this.preview_url,{method:"POST",body:e})).text()}}const l="textarea",d="preview";class c extends i{preview_history=[];preview_renderer;content_wrappers;view_controls;actions;constructor(t,e){super(e);const n=this.textarea.closest(".c-field-markdown");if(null===n)throw new Error(`Could not find input-wrapper for input-id '${e}'.`);this.preview_renderer=t,this.content_wrappers=function(t){const e=new Map;return e.set(l,t.querySelector("textarea")),e.set(d,t.querySelector(".c-field-markdown__preview")),e.forEach((t=>{if(null===t)throw new Error("Could not find all content-wrappers for markdown-input.")})),e}(n),this.view_controls=function(t){const e=t.querySelector(".il-viewcontrol-mode")?.getElementsByTagName("button");if(!e instanceof HTMLCollection||2!==e.length)throw new Error("Could not find exactly two view-controls.");return[...e]}(n),this.actions=function(t){const e=t.querySelector(".c-field-markdown__actions")?.getElementsByTagName("button");if(e instanceof HTMLCollection)return[...e];return[]}(n);let i=!0;this.textarea.addEventListener("keydown",(t=>{i=this.handleEnterKeyBeforeInsertionHook(t)})),this.textarea.addEventListener("keyup",(t=>{this.handleEnterKeyAfterInsertionHook(t,i)})),this.actions.forEach((t=>{t.addEventListener("click",(t=>{this.performMarkdownActionHook(t)}))})),this.view_controls.forEach((t=>{t.addEventListener("click",(()=>{this.toggleViewingModeHook()}))}))}handleEnterKeyAfterInsertionHook(t,e){if(!e||!p(t))return;const n=this.getLinesBeforeSelection().pop();void 0!==n&&m(n)?this.applyTransformationToSelection(u):void 0!==n&&v(n)&&this.insertSingleEnumeration()}handleEnterKeyBeforeInsertionHook(t){if(!p(t))return!1;const e=this.getLinesOfSelection().shift();if(void 0===e||!((e.match(/((^(\s*-)|(^(\s*\d+\.)))\s*)$/g)??[]).length>0))return!0;let n=this.getLinesBeforeSelection().join("\n"),i=this.getLinesAfterSelection().join("\n");return n.length>0&&(n+="\n"),i.length>0&&(i=`\n${i}`),this.updateTextareaContent(n+i,this.getAbsoluteSelectionStart()-e.length,this.getAbsoluteSelectionEnd()-e.length),t.preventDefault(),!1}performMarkdownActionHook(t){const e=function(t){const e=t.closest("span[data-action]");if(!e instanceof HTMLSpanElement)return null;if(!e.hasAttribute("data-action"))return null;return e.dataset.action}(t.target);switch(e){case"insert-heading":this.insertCharactersAroundSelection("# ","");break;case"insert-link":this.insertCharactersAroundSelection("[","](url)");break;case"insert-bold":this.insertCharactersAroundSelection("**","**");break;case"insert-italic":this.insertCharactersAroundSelection("_","_");break;case"insert-bullet-points":this.applyTransformationToSelection(u);break;case"insert-enumeration":this.isMultilineTextSelected()?this.applyTransformationToSelection(h):this.insertSingleEnumeration();break;default:throw new Error(`Could not perform markdown-action '${e}'.`)}}toggleViewingModeHook(){this.content_wrappers.forEach((t=>{g(t,"hidden")})),this.view_controls.forEach((t=>{g(t,"engaged")})),this.isDisabled()||this.actions.forEach((t=>{t.disabled=!t.disabled;const e=t.querySelector(".glyph");null!==e&&g(e,"disabled")})),this.maybeUpdatePreviewContent()}insertSingleEnumeration(){const t=this.getLinesOfSelection();if(1!==t.length)return void this.textarea.focus();const e=this.getLinesBeforeSelection(),n=e.length-1;let i=n>=0?function(t){const e=t.match(/([0-9]+)/);if(null!==e)return parseInt(e[0]);return null}(e[n])??0:0;const s=h(t,++i),a=function(t,e=0){if(t.length<1)return[];const n=[];for(const i of t){if(!v(i))break;n.push(i.replace(/([0-9]+)/,(++e).toString()))}n.length>0&&(t=n.concat(t.slice(n.length)));return t}(this.getLinesAfterSelection(),i);let o=e.join("\n");const r=a.join("\n");let l=s.join("\n");o.length>0&&l.length>0&&(o+="\n"),l.length>0&&r.length>0&&(l+="\n");const d=o+l+r,c=d.length-this.textarea.value.length;this.updateTextareaContent(d,this.getAbsoluteSelectionStart()+c,this.getAbsoluteSelectionEnd()+c)}applyTransformationToSelection(t){if(!t instanceof Function)throw new Error(`Transformation must be an instance of Function, ${typeof t} given.`);const e=t(this.getLinesOfSelection());if(!e instanceof Array)throw new Error(`Transformation must return an instance of Array, ${typeof e} returned.`);const n=e.length>1;let i=this.getLinesBeforeSelection().join("\n");const s=this.getLinesAfterSelection().join("\n");let a=e.join("\n");i.length>0&&a.length>0&&(i+="\n"),a.length>0&&s.length>0&&(a+="\n");const o=i+a+s,r=o.length-this.textarea.value.length,l=n?i.length:this.getAbsoluteSelectionStart()+r,d=n?l+a.length-1:this.getAbsoluteSelectionEnd()+r;this.updateTextareaContent(o,l,d)}insertCharactersAroundSelection(t,e){const n=this.getTextBeforeSelection()+t+this.getTextOfSelection()+e+this.getTextAfterSelection(),i=this.getAbsoluteSelectionStart()+t.length,s=this.getAbsoluteSelectionEnd()+t.length;this.updateTextareaContent(n,i,s)}maybeUpdatePreviewContent(){const t=this.preview_history[this.preview_history.length-1]??"",e=this.textarea.value;e!==t&&(this.preview_history.push(e),this.preview_renderer.getPreviewHtmlOf(e).then((t=>{this.content_wrappers.get(d).innerHTML=t})))}getBulletPointTransformation(){return u}getEnumerationTransformation(){return h}}function u(t){const e=[],n=!m(t[0]??"");for(const i of t)e.push(n?`- ${i}`:f(i));return e}function h(t,e=1){const n=[],i=!v(t[0]??"");for(const s of t)n.push(i?`${e++}. ${s}`:f(s));return n}function g(t,e){t.classList.contains(e)?t.classList.remove(e):t.classList.add(e)}function p(t){return t instanceof KeyboardEvent&&"Enter"===t.code}function f(t){return t.replace(/((^(\s*[-])|(^(\s*\d+\.)))\s*)/g,"")}function m(t){return(t.match(/^(\s*[-])/g)??[]).length>0}function v(t){return(t.match(/^(\s*\d+\.)/g)??[]).length>0}class w{instances=[];init(t,e,n){if(void 0!==this.instances[t])throw new Error(`Markdown with input-id '${t}' has already been initialized.`);this.instances[t]=new c(new r(n,e),t)}get(t){return this.instances[t]??null}}class b{constructor(t,e,n,i,s,a=null,o=null,r=null){this.id=t,this.name=e,this.element=n,this.selectButton=i,this.drilldownParentLevel=s,this.drilldownButton=a,this.listElement=o,this.renderUrl=r}}const y="data-node-id",T="data-node-name",S="data-render-url",x="data-ddindex",E="c-input-node",O="c-input-tree_select",D=`${E}__async`,I=`${E}__leaf`,N=`${E}--selected`,M="hidden",A="disabled",C=".glyph",_=`.${E}`,L=`.${O}`,k=`.${O}__selection`,B='[data-action="remove"]',j='[data-action="select"]',P=`.${E}__select`,V=".c-drilldown__menulevel--trigger";function H(t){return function(t){return t.classList.contains(D)}(t)&&t.hasAttribute(S)?t.getAttribute(S):null}function R(t){return!t.classList.contains(I)&&t.classList.contains(E)}function q(t,e=null){return t.reduce(((t,e)=>{const n=function(t){const e=t.getAttribute(y);if(null===e)throw new Error("Could not find data-node-id attribute.");return e}(e);if(t.has(n))throw new Error(`Node '${n}' has already been parsed. There might be a rendering issue.`);return t.set(n,new b(n,function(t){const e=t.querySelector(`[${T}]`);if(null===e)throw new Error("Could not find element with data-node-name attribute.");return e.textContent}(e),e,function(t){const e=t.querySelector(`:scope > ${P}`);if(null===e)throw new Error("Could not find node select button.");return e}(e),function(t){const e=t.closest(`ul[${x}]`);if(null===e)throw new Error("Could not find drilldown menu of node.");return e.getAttribute(x)}(e),function(t){if(!R(t))return null;const e=t.querySelector(`${V}`);if(null===e)throw new Error("Could not find drilldown menu button of branch node.");return e}(e),function(t){if(!R(t))return null;const e=t.querySelector("ul");if(null===e)throw new Error("Could not find list element of branch node.");return e}(e),H(e)))}),new Map(e??[]))}function F(t,e){for(let n=0;n{this.#f()})),this.#p.querySelectorAll('[data-action="close"]').forEach((t=>{t.addEventListener("click",(()=>{this.#m()}))})),this.#c.querySelectorAll("li").forEach((t=>{const e=function(t){const e=t.getAttribute(y);if(null===e)throw new Error(`Could not find '${y}' attribbute of element.`);return e}(t);this.#v(t,e),this.#w(e)})),this.#r.addEngageListener((t=>{this.#b(t)})),this.#g.addEventListener("click",(()=>{this.#y()})),this.#t.forEach((t=>{this.#T(t)})),this.#S()}unselectNode(t){if(this.#x(t),this.#S(),this.#E(t),this.#t.has(t)){const e=this.#t.get(t);$(e.element,!1),this.#O(e.selectButton,e.name),this.updateNodeSelectButtonStates()}}selectNode(t){if(this.#w(t),this.#S(),this.#t.has(t)){const e=this.#t.get(t);$(e.element,!0),this.#D(e.selectButton,e.name),this.#I(e),this.updateNodeSelectButtonStates()}}updateNodeSelectButtonStates(){this.#t.forEach(((t,e)=>{this.#e.size>0?(t.selectButton.disabled=!this.#e.has(e),t.selectButton.querySelector(C).classList.toggle(A,!this.#e.has(e))):(t.selectButton.disabled=!1,t.selectButton.querySelector(C).classList.toggle(A,!1))}))}getSelection(){return new Set(this.#e)}getNodes(){return new Map(this.#t)}async#N(t){var e,n,i;if(!this.#n.has(t.id)&&!this.#i.has(t.id))try{this.#i.add(t.id);const s=await this.#a.loadContent(t.renderUrl);t.listElement.append(...s.children),this.#r.parseLevels();const a=q((i=t.listElement,Array.from(i.querySelectorAll(_))),this.#t),o=(e=a,n=this.#t,Array.from(e.entries()).filter((([t])=>!n.has(t))).map((([,t])=>t)));this.#t=a,F(o,(t=>{this.#e.has(t.id)?this.selectNode(t.id):this.unselectNode(t.id),this.#T(t)})),this.#n.add(t.id)}catch(t){throw new Error(`Could not render async node children: ${t.message}`)}finally{this.#i.delete(t.id)}}#M(t){F(function(t,e,n=255){const i=[];let s=t;for(let t=0;t{const e=t.getAttribute(y);if(null===e||!this.#t.has(e))throw new Error(`Could not find '${y}' of node element.`);const n=this.#t.get(e);this.#A(n)}))}#A(t){const e=this.#s.createContent(this.#d).querySelector(".crumb");e.setAttribute(x,t.drilldownParentLevel),e.firstElementChild.textContent=t.name,e.addEventListener("click",(()=>{this.#r.engageLevel(t.drilldownParentLevel),t.drilldownButton.click()})),this.#l.append(e)}#f(){const t=this.#l.querySelectorAll(".crumb");t.item(t.length-1)?.remove()}#C(){F(this.#l.querySelectorAll(".crumb"),(t=>{t.remove()}))}#b(t){if("0"===t)return void this.#C();const e=this.#p.querySelector(`ul[${x}="${t}"]`)?.closest(_)?.getAttribute(y);if(null===e||!this.#t.has(e))throw new Error(`Could not find node for drilldown-level '${t}'.`);this.#C(),this.#M(this.#t.get(e))}#_(t,e){t.addEventListener("click",(()=>{null!==e.renderUrl&&this.#N(e)}))}#v(t,e){t.querySelector(B)?.addEventListener("click",(()=>{this.unselectNode(e),t.remove()}))}#L(t,e){t.addEventListener("click",(()=>{this.#e.has(e.id)?this.unselectNode(e.id):this.selectNode(e.id)}))}#I(t){if(null!==this.#c.querySelector(`li[${y}="${t.id}"]`))return;const e=this.#s.createContent(this.#u),n=e.querySelector("[data-node-id]");n.setAttribute(y,t.id),n.querySelector(`[${T}]`).textContent=t.name,n.querySelector("input").value=t.id,this.#v(n,t.id),this.#c.append(...e.children)}#E(t){this.#c.querySelector(`li[${y}="${t}"]`)?.remove()}#T(t){this.#L(t.selectButton,t),null!==t.drilldownButton&&this.#_(t.drilldownButton,t)}#O(t,e){t.querySelector(B)?.classList.add(M),t.querySelector(j)?.classList.remove(M),t.setAttribute("aria-label",this.#k("select_node",e))}#D(t,e){t.querySelector(j)?.classList.add(M),t.querySelector(B)?.classList.remove(M),t.setAttribute("aria-label",this.#k("unselect_node",e))}#S(){this.#h.disabled=this.#e.size<=0}#x(t){this.#e.has(t)&&this.#e.delete(t)}#w(t){this.#e.has(t)||this.#e.add(t)}#k(t,...e){return function(t,...e){const n=[...e];return t.replace(/%s/g,(()=>n.shift()??""))}(this.#o.txt(t),e)}#m(){this.#p.close()}#y(){this.#p.showModal()}}class W extends U{#B;constructor(t,e,n,i,s,a,o,r,l,d,c,u,h,g){super(t,e,n,i,s,a,o,r,l,d,c,u,h),this.#B=g}selectNode(t){if(!this.#B){const e=Array.from(this.getSelection().add(t));this.#j(e,this.getNodes())}super.selectNode(t)}updateNodeSelectButtonStates(){if(this.#B)return;const t=this.getNodes();t.forEach((t=>{t.selectButton.disabled=!1,t.selectButton.querySelector(C).classList.remove(A)})),this.getSelection().forEach((e=>{const n=t.get(e);null!==n&&null!==n.listElement&&n.listElement.querySelectorAll(P).forEach((t=>{t.disabled=!0,t.querySelector(C).classList.add(A)}))}))}#j(t,e){for(let i=0;i{const i=t.getAttribute(n);if(!e.has(i))throw new Error(`Element references '${i}' which does not exist.`);t.setAttribute(n,e.get(i))}))}class X{#P;constructor(t){this.#P=t}createContent(t){const e=t.content.cloneNode(!0),n=new Map;return e.querySelectorAll("[id]").forEach((t=>{const e=function(t=""){return`${t}${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`}("il_ui_fw_");n.set(t.id,e),t.id=e})),e.querySelectorAll("[for]").forEach((t=>{t.htmlFor=n.get(t.htmlFor)})),z(e,n,"aria-describedby"),z(e,n,"aria-labelledby"),z(e,n,"aria-controls"),z(e,n,"aria-owns"),K(this.#P,e.children)}}class J{#P;constructor(t){this.#P=t}loadContent(t){return fetch(t.toString()).then((t=>t.text())).then((t=>this.#V(t))).then((t=>K(this.#P,t))).catch((e=>{throw new Error(`Could not render element(s) from '${t}': ${e.message}`)}))}#H(t){const e=this.#P.createElement("script");return t.hasAttribute("type")&&e.setAttribute("type",t.getAttribute("type")),t.hasAttribute("src")&&e.setAttribute("src",t.getAttribute("src")),t.textContent.length>0&&(e.textContent=t.textContent),e}#V(t){const e=this.#P.createElement("div");return e.innerHTML=t.trim(),e.querySelectorAll("script").forEach((t=>{const e=this.#H(t);t.replaceWith(e)})),e.children}}function Q(t){return Array.from(t.querySelectorAll(_))}class G{#R=new Map;#q;#F;#o;#P;constructor(t,e,n,i){this.#q=t,this.#F=e,this.#o=n,this.#P=i}initTreeMultiSelect(t,e){if(this.#R.has(t))throw new Error(`TreeSelect '${t}' already exists.`);const[n,i,s,a,o,r,l,d]=this.#$(t),c=this.#U(i),u=new W(q(Q(l)),this.#q,new X(this.#P),new J(this.#P),this.#o,c,s,a,o,r,d,n,l,e);return this.#R.set(t,u),u}initTreeSelect(t){if(this.#R.has(t))throw new Error(`TreeSelect '${t}' already exists.`);const[e,n,i,s,a,o,r,l]=this.#$(t),d=this.#U(n),c=new U(q(Q(r)),this.#q,new X(this.#P),new J(this.#P),this.#o,d,i,s,a,o,l,e,r);return this.#R.set(t,c),c}getInstance(t){return this.#R.has(t)?this.#R.get(t):null}#$(t){const e=this.#P.getElementById(t),n=e?.closest(L),i=n?.querySelector(".breadcrumb"),s=n?.querySelector(".modal-body > template"),a=n?.querySelector(k),o=a?.querySelector(":scope > template"),r=n?.querySelector("dialog"),l=r?.querySelector(".btn-primary");if(null===i||null===s||null===a||null===o||null===l||null===e||null===r)throw new Error(`Could not find some element(s) for Tree Select Input '${t}'.`);return[e,n,i,s,a,o,r,l]}#U(t){const e=t.querySelector(".c-drilldown");if(null===e||!e.hasAttribute("id"))throw new Error("Could not find drilldown element.");const n=this.#F.getInstance(e.id);if(null===e)throw new Error("Could not find drilldown instance.");return n}}class Y{#W;constructor(t){this.#W=t}on(t,e,n){this.#W(t).on(e,n)}off(t,e,n){this.#W(t).off(e,n)}} +/* + Tagify v4.33.2 - tags input component + By: Yair Even-Or + https://github.com/yairEO/tagify + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + This Software may not be rebranded and sold as a library under any other name + other than "Tagify" (by owner) or as part of another library. + */var Z="​";function tt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n/g,">").replace(/"/g,""").replace(/`|'/g,"'"):t}function dt(t){var e=Object.prototype.toString.call(t).split(" ")[1].slice(0,-1);return t===Object(t)&&"Array"!=e&&"Function"!=e&&"RegExp"!=e&&"HTMLUnknownElement"!=e}function ct(t,e,n){var i,s;function a(t,e){for(var n in e)if(e.hasOwnProperty(n)){if(dt(e[n])){dt(t[n])?a(t[n],e[n]):t[n]=Object.assign({},e[n]);continue}if(Array.isArray(e[n])){t[n]=Object.assign([],e[n]);continue}t[n]=e[n]}}return i=t,(null!=(s=Object)&&"undefined"!=typeof Symbol&&s[Symbol.hasInstance]?s[Symbol.hasInstance](i):i instanceof s)||(t={}),a(t,e),n&&a(t,n),t}function ut(){var t=[],e={},n=!0,i=!1,s=void 0;try{for(var a,o=arguments[Symbol.iterator]();!(n=(a=o.next()).done);n=!0){var r=a.value,l=!0,d=!1,c=void 0;try{for(var u,h=r[Symbol.iterator]();!(l=(u=h.next()).done);l=!0){var g=u.value;dt(g)?e[g.value]||(t.push(g),e[g.value]=1):t.includes(g)||t.push(g)}}catch(t){d=!0,c=t}finally{try{l||null==h.return||h.return()}finally{if(d)throw c}}}}catch(t){i=!0,s=t}finally{try{n||null==o.return||o.return()}finally{if(i)throw s}}return t}function ht(t){return String.prototype.normalize?"string"==typeof t?t.normalize("NFD").replace(/[\u0300-\u036f]/g,""):void 0:t}var gt=function(){return/(?=.*chrome)(?=.*android)/i.test(navigator.userAgent)};function pt(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,(function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)}))}function ft(t){var e;return vt.call(this,t)&&(null==t||null===(e=t.classList)||void 0===e?void 0:e.contains(this.settings.classNames.tag))}function mt(t){return vt.call(this,t)&&(null==t?void 0:t.closest(this.settings.classNames.tagSelector))}function vt(t){var e;return(null==t||null===(e=t.closest)||void 0===e?void 0:e.call(t,this.settings.classNames.namespaceSelector))===this.DOM.scope}function wt(t,e){var n=window.getSelection();return e=e||n.getRangeAt(0),"string"==typeof t&&(t=document.createTextNode(t)),e&&(e.deleteContents(),e.insertNode(t)),t}function bt(t,e,n){return t?(e&&(t.__tagifyTagData=n?e:ct({},t.__tagifyTagData||{},e)),t.__tagifyTagData):(nt.warn("tag element doesn't exist",{tagElm:t,data:e}),e)}function yt(t){if(t&&t.parentNode){var e=t,n=window.getSelection(),i=n.getRangeAt(0);n.rangeCount&&(i.setStartAfter(e),i.collapse(!0),n.removeAllRanges(),n.addRange(i))}}function Tt(t,e){t.forEach((function(t){if(bt(t.previousSibling)||!t.previousSibling){var n=document.createTextNode("​");t.before(n),e&&yt(n)}}))}var St={delimiters:",",pattern:null,tagTextProp:"value",maxTags:1/0,callbacks:{},addTagOnBlur:!0,addTagOn:["blur","tab","enter"],onChangeAfterBlur:!0,duplicates:!1,whitelist:[],blacklist:[],enforceWhitelist:!1,userInput:!0,focusable:!0,keepInvalidTags:!1,createInvalidTags:!0,mixTagsAllowedAfter:/,|\.|\:|\s/,mixTagsInterpolator:["[[","]]"],backspace:!0,skipInvalid:!1,pasteAsTags:!0,editTags:{clicks:2,keepInvalid:!0},transformTag:function(){},trim:!0,a11y:{focusableTags:!1},mixMode:{insertAfterTag:"Ā "},autoComplete:{enabled:!0,rightKey:!1,tabKey:!1},classNames:{namespace:"tagify",mixMode:"tagify--mix",selectMode:"tagify--select",input:"tagify__input",focus:"tagify--focus",tagNoAnimation:"tagify--noAnim",tagInvalid:"tagify--invalid",tagNotAllowed:"tagify--notAllowed",scopeLoading:"tagify--loading",hasMaxTags:"tagify--hasMaxTags",hasNoTags:"tagify--noTags",empty:"tagify--empty",inputInvalid:"tagify__input--invalid",dropdown:"tagify__dropdown",dropdownWrapper:"tagify__dropdown__wrapper",dropdownHeader:"tagify__dropdown__header",dropdownFooter:"tagify__dropdown__footer",dropdownItem:"tagify__dropdown__item",dropdownItemActive:"tagify__dropdown__item--active",dropdownItemHidden:"tagify__dropdown__item--hidden",dropdownItemSelected:"tagify__dropdown__item--selected",dropdownInital:"tagify__dropdown--initial",tag:"tagify__tag",tagText:"tagify__tag-text",tagX:"tagify__tag__removeBtn",tagLoading:"tagify__tag--loading",tagEditing:"tagify__tag--editable",tagFlash:"tagify__tag--flash",tagHide:"tagify__tag--hide"},dropdown:{classname:"",enabled:2,maxItems:10,searchKeys:["value","searchBy"],fuzzySearch:!0,caseSensitive:!1,accentedSearch:!0,includeSelectedTags:!1,escapeHTML:!0,highlightFirst:!0,closeOnSelect:!0,clearOnSelect:!0,position:"all",appendTarget:null},hooks:{beforeRemoveTag:function(){return Promise.resolve()},beforePaste:function(){return Promise.resolve()},suggestionClick:function(){return Promise.resolve()},beforeKeyDown:function(){return Promise.resolve()}}};function xt(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function Et(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],e=this.dropdown.events.callbacks,n=this.listeners.dropdown=this.listeners.dropdown||{position:this.dropdown.position.bind(this,null),onKeyDown:e.onKeyDown.bind(this),onMouseOver:e.onMouseOver.bind(this),onMouseLeave:e.onMouseLeave.bind(this),onClick:e.onClick.bind(this),onScroll:e.onScroll.bind(this)},i=t?"addEventListener":"removeEventListener";"manual"!=this.settings.dropdown.position&&(document[i]("scroll",n.position,!0),window[i]("resize",n.position),window[i]("keydown",n.onKeyDown)),this.DOM.dropdown[i]("mouseover",n.onMouseOver),this.DOM.dropdown[i]("mouseleave",n.onMouseLeave),this.DOM.dropdown[i]("mousedown",n.onClick),this.DOM.dropdown.content[i]("scroll",n.onScroll)},callbacks:{onKeyDown:function(t){var e=this;if(this.state.hasFocus&&!this.state.composing){var n=this.settings,i=n.dropdown.includeSelectedTags,s=this.DOM.dropdown.querySelector(n.classNames.dropdownItemActiveSelector),a=this.dropdown.getSuggestionDataByNode(s),o="mix"==n.mode,r="select"==n.mode;n.hooks.beforeKeyDown(t,{tagify:this}).then((function(l){switch(t.key){case"ArrowDown":case"ArrowUp":case"Down":case"Up":t.preventDefault();var d=e.dropdown.getAllSuggestionsRefs(),c="ArrowUp"==t.key||"Up"==t.key;s&&(s=e.dropdown.getNextOrPrevOption(s,!c)),s&&s.matches(n.classNames.dropdownItemSelector)||(s=d[c?d.length-1:0]),e.dropdown.highlightOption(s,!0);break;case"PageUp":case"PageDown":var u;t.preventDefault();var h=e.dropdown.getAllSuggestionsRefs(),g=Math.floor(e.DOM.dropdown.content.clientHeight/(null===(u=h[0])||void 0===u?void 0:u.offsetHeight))||1,p="PageUp"===t.key;if(s){var f=h.indexOf(s),m=p?Math.max(0,f-g):Math.min(h.length-1,f+g);s=h[m]}else s=h[0];e.dropdown.highlightOption(s,!0);break;case"Home":case"End":t.preventDefault();var v=e.dropdown.getAllSuggestionsRefs();s=v["Home"===t.key?0:v.length-1],e.dropdown.highlightOption(s,!0);break;case"Escape":case"Esc":e.dropdown.hide();break;case"ArrowRight":if(e.state.actions.ArrowLeft||n.autoComplete.rightKey)return;case"Tab":var w=!n.autoComplete.rightKey||!n.autoComplete.tabKey;if(!o&&!r&&s&&w&&!e.state.editing&&a){t.preventDefault();var b=e.dropdown.getMappedValue(a);return e.state.autoCompleteData=a,e.input.autocomplete.set.call(e,b),!1}return!0;case"Enter":t.preventDefault(),e.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),n.hooks.suggestionClick(t,{tagify:e,tagData:a,suggestionElm:s}).then((function(){if(s){var n=i?s:e.dropdown.getNextOrPrevOption(s,!c);e.dropdown.selectOption(s,t,(function(){if(n){var t=n.getAttribute("value");n=e.dropdown.getSuggestionNodeByValue(t),e.dropdown.highlightOption(n)}}))}else e.dropdown.hide(),o||e.addTags(e.state.inputText.trim(),!0)})).catch((function(t){return nt.warn(t)}));break;case"Backspace":if(o||e.state.editing.scope)return;var y=e.input.raw.call(e);""!=y&&8203!=y.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0))}}))}},onMouseOver:function(t){var e=t.target.closest(this.settings.classNames.dropdownItemSelector);this.dropdown.highlightOption(e)},onMouseLeave:function(t){this.dropdown.highlightOption()},onClick:function(t){var e=this;if(0==t.button&&t.target!=this.DOM.dropdown&&t.target!=this.DOM.dropdown.content){var n=t.target.closest(this.settings.classNames.dropdownItemSelector),i=this.dropdown.getSuggestionDataByNode(n);this.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),this.settings.hooks.suggestionClick(t,{tagify:this,tagData:i,suggestionElm:n}).then((function(){n?e.dropdown.selectOption(n,t):e.dropdown.hide()})).catch((function(t){return nt.warn(t)}))}},onScroll:function(t){var e=t.target,n=e.scrollTop/(e.scrollHeight-e.parentNode.clientHeight)*100;this.trigger("dropdown:scroll",{percentage:Math.round(n)})}}},refilter:function(t){t=t||this.state.dropdown.query||"",this.suggestedListItems=this.dropdown.filterListItems(t),this.dropdown.fill(),this.suggestedListItems.length||this.dropdown.hide(),this.trigger("dropdown:updated",this.DOM.dropdown)},getSuggestionDataByNode:function(t){for(var e,n=t&&t.getAttribute("value"),i=this.suggestedListItems.length;i--;){if(dt(e=this.suggestedListItems[i])&&e.value==n)return e;if(e==n)return{value:e}}},getSuggestionNodeByValue:function(t){return this.dropdown.getAllSuggestionsRefs().find((function(e){return e.getAttribute("value")===t}))},getNextOrPrevOption:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.dropdown.getAllSuggestionsRefs(),i=n.findIndex((function(e){return e===t}));return e?n[i+1]:n[i-1]},highlightOption:function(t,e){var n,i=this.settings.classNames.dropdownItemActive;if(this.state.ddItemElm&&(this.state.ddItemElm.classList.remove(i),this.state.ddItemElm.removeAttribute("aria-selected")),!t)return this.state.ddItemData=null,this.state.ddItemElm=null,void this.input.autocomplete.suggest.call(this);n=this.dropdown.getSuggestionDataByNode(t),this.state.ddItemData=n,this.state.ddItemElm=t,t.classList.add(i),t.setAttribute("aria-selected",!0),e&&(t.parentNode.scrollTop=t.clientHeight+t.offsetTop-t.parentNode.clientHeight),this.settings.autoComplete&&(this.input.autocomplete.suggest.call(this,n),this.dropdown.position())},selectOption:function(t,e,n){var i=this,s=this.settings,a=s.dropdown.includeSelectedTags,o=s.dropdown,r=o.clearOnSelect,l=o.closeOnSelect;if(!t)return this.addTags(this.state.inputText,!0),void(l&&this.dropdown.hide());e=e||{};var d=t.getAttribute("value"),c="noMatch"==d,u="mix"==s.mode,h=this.suggestedListItems.find((function(t){var e;return(null!==(e=t.value)&&void 0!==e?e:t)==d}));if(this.trigger("dropdown:select",{data:h,elm:t,event:e}),h||c){if(this.state.editing){var g=this.normalizeTags([h])[0];h=s.transformTag.call(this,g)||g,this.onEditTagDone(null,ct({__isValid:!0},h))}else this[u?"addMixTags":"addTags"]([h||this.input.raw.call(this)],r);(u||this.DOM.input.parentNode)&&(setTimeout((function(){i.DOM.input.focus(),i.toggleFocusClass(!0)})),l&&setTimeout(this.dropdown.hide.bind(this)),a?n&&n():(t.addEventListener("transitionend",(function(){i.dropdown.fillHeaderFooter(),setTimeout((function(){t.remove(),i.dropdown.refilter(),n&&n()}),100)}),{once:!0}),t.classList.add(this.settings.classNames.dropdownItemHidden)))}else l&&setTimeout(this.dropdown.hide.bind(this))},selectAll:function(t){this.suggestedListItems.length=0,this.dropdown.hide(),this.dropdown.filterListItems("");var e=this.dropdown.filterListItems("");return t||(e=this.state.dropdown.suggestions),this.addTags(e,!0),this},filterListItems:function(t,e){var n,i,s,a,o,r,l=function(){var t,l,d=void 0,c=void 0;t=p[b],i=(null!=(l=Object)&&"undefined"!=typeof Symbol&&l[Symbol.hasInstance]?l[Symbol.hasInstance](t):t instanceof l)?p[b]:{value:p[b]};var f,m=Object.keys(i).some((function(t){return w.includes(t)}))?w:["value"];u.fuzzySearch&&!e.exact?(a=m.reduce((function(t,e){return t+" "+(i[e]||"")}),"").toLowerCase().trim(),u.accentedSearch&&(a=ht(a),r=ht(r)),d=0==a.indexOf(r),c=a===r,f=a,s=r.toLowerCase().split(" ").every((function(t){return f.includes(t.toLowerCase())}))):(d=!0,s=m.some((function(t){var n=""+(i[t]||"");return u.accentedSearch&&(n=ht(n),r=ht(r)),u.caseSensitive||(n=n.toLowerCase()),c=n===r,e.exact?n===r:0==n.indexOf(r)}))),o=!u.includeSelectedTags&&n.isTagDuplicate(dt(i)?i.value:i),s&&!o&&(c&&d?g.push(i):"startsWith"==u.sortby&&d?h.unshift(i):h.push(i))},d=this,c=this.settings,u=c.dropdown,h=(e=e||{},[]),g=[],p=c.whitelist,f=u.maxItems>=0?u.maxItems:1/0,m=u.includeSelectedTags,v="function"==typeof u.sortby,w=u.searchKeys,b=0;if(!(t="select"==c.mode&&this.value.length&&this.value[0][c.tagTextProp]==t?"":t)||!w.length){h=m?p:p.filter((function(t){return!d.isTagDuplicate(dt(t)?t.value:t)}));var y=v?u.sortby(h,r):h.slice(0,f);return this.state.dropdown.suggestions=y,y}for(r=u.caseSensitive?""+t:(""+t).toLowerCase();b[\r\n ]+\<").split(/>\s+<").trim():""},fillHeaderFooter:function(){var t=this.dropdown.filterListItems(this.state.dropdown.query),e=this.parseTemplate("dropdownHeader",[t]),n=this.parseTemplate("dropdownFooter",[t]),i=this.dropdown.getHeaderRef(),s=this.dropdown.getFooterRef();e&&(null==i||i.parentNode.replaceChild(e,i)),n&&(null==s||s.parentNode.replaceChild(n,s))},position:function(t){var e=this.settings.dropdown,n=this.dropdown.getAppendTarget();if("manual"!=e.position&&n){var i,s,a,o,r,l,d,c,u,h,g=this.DOM.dropdown,p=e.RTL,f=n===document.body,m=n===this.DOM.scope,v=f?window.pageYOffset:n.scrollTop,w=document.fullscreenElement||document.webkitFullscreenElement||document.documentElement,b=w.clientHeight,y=Math.max(w.clientWidth||0,window.innerWidth||0),T=y>480?e.position:"all",S=this.DOM["input"==T?"input":"scope"];if(t=t||g.clientHeight,this.state.dropdown.visible){if("text"==T?(a=(i=function(){var t=document.getSelection();if(t.rangeCount){var e,n,i=t.getRangeAt(0),s=i.startContainer,a=i.startOffset;if(a>0)return(n=document.createRange()).setStart(s,a-1),n.setEnd(s,a),{left:(e=n.getBoundingClientRect()).right,top:e.top,bottom:e.bottom};if(s.getBoundingClientRect)return s.getBoundingClientRect()}return{left:-9999,top:-9999}}()).bottom,s=i.top,o=i.left,r="auto"):(l=function(t){var e=0,n=0;for(t=t.parentNode;t&&t!=w;)e+=t.offsetTop||0,n+=t.offsetLeft||0,t=t.parentNode;return{top:e,left:n}}(n),i=S.getBoundingClientRect(),s=m?-1:i.top-l.top,a=(m?i.height:i.bottom-l.top)-1,o=m?-1:i.left-l.left,r=i.width+"px"),!f){var x=function(){for(var t=0,n=e.appendTarget.parentNode;n;)t+=n.scrollTop||0,n=n.parentNode;return t}();s+=x,a+=x}var E;s=Math.floor(s),a=Math.ceil(a),c=y-o<120,u=((d=null!==(E=e.placeAbove)&&void 0!==E?E:b-i.bottom\n ').concat(this.settings.templates.input.call(this),"\n ").concat(Z,"\n ")},input:function(){var t=this.settings,e=t.placeholder||Z;return"')},tag:function(t,e){var n=e.settings;return'\n \n
\n ').concat(t[n.tagTextProp]||t.value,"\n
\n
")},dropdown:function(t){var e=t.dropdown,n="manual"==e.position;return'
\n
\n
')},dropdownContent:function(t){var e=this.settings.templates,n=this.state.dropdown.suggestions;return"\n ".concat(e.dropdownHeader.call(this,n),"\n ").concat(t,"\n ").concat(e.dropdownFooter.call(this,n),"\n ")},dropdownItem:function(t){return"
').concat(t.mappedValue||t.value,"
")},dropdownHeader:function(t){return"
')},dropdownFooter:function(t){var e=t.length-this.settings.dropdown.maxItems;return e>0?"
\n ').concat(e," more items. Refine your search.\n
"):""},dropdownItemNoMatch:null};function Bt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],n=this.settings,i=this.events.callbacks,s=e?"addEventListener":"removeEventListener";if(!this.state.mainEvents||!e){for(var a in this.state.mainEvents=e,e&&!this.listeners.main&&(this.events.bindGlobal.call(this),this.settings.isJQueryPlugin&&jQuery(this.DOM.originalInput).on("tagify.removeAllTags",this.removeAllTags.bind(this))),t=this.listeners.main=this.listeners.main||{keydown:["input",i.onKeydown.bind(this)],click:["scope",i.onClickScope.bind(this)],dblclick:"select"!=n.mode&&["scope",i.onDoubleClickScope.bind(this)],paste:["input",i.onPaste.bind(this)],drop:["input",i.onDrop.bind(this)],compositionstart:["input",i.onCompositionStart.bind(this)],compositionend:["input",i.onCompositionEnd.bind(this)]})t[a]&&this.DOM[t[a][0]][s](a,t[a][1]);var o=this.listeners.main.inputMutationObserver||new MutationObserver(i.onInputDOMChange.bind(this));o.disconnect(),"mix"==n.mode&&o.observe(this.DOM.input,{childList:!0}),this.events.bindOriginaInputListener.call(this)}},bindOriginaInputListener:function(t){var e=(t||0)+500;this.listeners.main&&(clearInterval(this.listeners.main.originalInputValueObserverInterval),this.listeners.main.originalInputValueObserverInterval=setInterval(this.events.callbacks.observeOriginalInputValue.bind(this),e))},bindGlobal:function(t){var e,n=this.events.callbacks,i=t?"removeEventListener":"addEventListener";if(this.listeners&&(t||!this.listeners.global)){this.listeners.global=this.listeners.global||[{type:this.isIE?"keydown":"input",target:this.DOM.input,cb:n[this.isIE?"onInputIE":"onInput"].bind(this)},{type:"keydown",target:window,cb:n.onWindowKeyDown.bind(this)},{type:"focusin",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"focusout",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"click",target:document,cb:n.onClickAnywhere.bind(this),useCapture:!0}];var s=!0,a=!1,o=void 0;try{for(var r,l=this.listeners.global[Symbol.iterator]();!(s=(r=l.next()).done);s=!0)(e=r.value).target[i](e.type,e.cb,!!e.useCapture)}catch(t){a=!0,o=t}finally{try{s||null==l.return||l.return()}finally{if(a)throw o}}}},unbindGlobal:function(){this.events.bindGlobal.call(this,!0)},callbacks:{onFocusBlur:function(t){var e,n,i=this.settings,s=mt.call(this,t.relatedTarget),a=ft.call(this,t.relatedTarget),o=t.target.classList.contains(i.classNames.tagX),r="focusin"==t.type,l="focusout"==t.type;o&&"mix"!=i.mode&&this.DOM.input.focus(),s&&r&&!a&&!o&&this.toggleFocusClass(this.state.hasFocus=+new Date);var d=t.target?this.trim(this.DOM.input.textContent):"",c=null===(n=this.value)||void 0===n||null===(e=n[0])||void 0===e?void 0:e[i.tagTextProp],u=i.dropdown.enabled>=0,h={relatedTarget:t.relatedTarget},g=this.state.actions.selectOption&&(u||!i.dropdown.closeOnSelect),p=this.state.actions.addNew&&u;if(l){if(t.relatedTarget===this.DOM.scope)return this.dropdown.hide(),void this.DOM.input.focus();this.postUpdate(),i.onChangeAfterBlur&&this.triggerChangeEvent()}if(!(g||p||o))if(this.state.hasFocus=!(!r&&!s)&&+new Date,this.toggleFocusClass(this.state.hasFocus),"mix"!=i.mode){if(r){if(!i.focusable)return;var f=0===i.dropdown.enabled&&!this.state.dropdown.visible,m=!a||"select"===i.mode,v=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector);return this.trigger("focus",h),void(f&&m&&(this.dropdown.show(this.value.length?"":void 0),this.setRangeAtStartEnd(!1,v)))}if(l){if(this.trigger("blur",h),this.loading(!1),"select"==i.mode){if(this.value.length){var w=this.getTagElms()[0];d=this.trim(w.textContent)}c===d&&(d="")}d&&!this.state.actions.selectOption&&i.addTagOnBlur&&i.addTagOn.includes("blur")&&this.addTags(d,!0)}s||(this.DOM.input.removeAttribute("style"),this.dropdown.hide())}else r?this.trigger("focus",h):l&&(this.trigger("blur",h),this.loading(!1),this.dropdown.hide(),this.state.dropdown.visible=void 0,this.setStateSelection())},onCompositionStart:function(t){this.state.composing=!0},onCompositionEnd:function(t){this.state.composing=!1},onWindowKeyDown:function(t){var e,n=this.settings,i=document.activeElement,s=mt.call(this,i)&&this.DOM.scope.contains(i),a=i===this.DOM.input,o=s&&i.hasAttribute("readonly"),r=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector),l=this.state.dropdown.visible;if(("Tab"===t.key&&l||this.state.hasFocus||s&&!o)&&!a){e=i.nextElementSibling;var d=t.target.classList.contains(n.classNames.tagX);switch(t.key){case"Backspace":n.readonly||this.state.editing||(this.removeTags(i),(e||this.DOM.input).focus());break;case"Enter":if(d)return void this.removeTags(t.target.parentNode);n.a11y.focusableTags&&ft.call(this,i)&&setTimeout(this.editTag.bind(this),0,i);break;case"ArrowDown":this.state.dropdown.visible||"mix"==n.mode||this.dropdown.show();break;case"Tab":null==r||r.focus()}}},onKeydown:function(t){var e=this,n=this.settings;if(!this.state.composing&&n.userInput){"select"==n.mode&&n.enforceWhitelist&&this.value.length&&"Tab"!=t.key&&t.preventDefault();var i=this.trim(t.target.textContent);this.trigger("keydown",{event:t}),n.hooks.beforeKeyDown(t,{tagify:this}).then((function(s){if("mix"==n.mode){switch(t.key){case"Left":case"ArrowLeft":e.state.actions.ArrowLeft=!0;break;case"Delete":case"Backspace":if(e.state.editing)return;var a=document.getSelection(),o="Delete"==t.key&&a.anchorOffset==(a.anchorNode.length||0),r=a.anchorNode.previousSibling,l=1==a.anchorNode.nodeType||!a.anchorOffset&&r&&1==r.nodeType&&a.anchorNode.previousSibling;!function(t){var e=document.createElement("div");t.replace(/\&#?[0-9a-z]+;/gi,(function(t){return e.innerHTML=t,e.innerText}))}(e.DOM.input.innerHTML);var d,c,u,h=e.getTagElms(),g=1===a.anchorNode.length&&a.anchorNode.nodeValue==String.fromCharCode(8203);if("edit"==n.backspace&&l)return d=1==a.anchorNode.nodeType?null:a.anchorNode.previousElementSibling,setTimeout(e.editTag.bind(e),0,d),void t.preventDefault();if(gt()&&Ht(l,Element))return u=rt(l),l.hasAttribute("readonly")||l.remove(),e.DOM.input.focus(),void setTimeout((function(){yt(u),e.DOM.input.click()}));if("BR"==a.anchorNode.nodeName)return;if((o||l)&&1==a.anchorNode.nodeType?c=0==a.anchorOffset?o?h[0]:null:h[Math.min(h.length,a.anchorOffset)-1]:o?c=a.anchorNode.nextElementSibling:Ht(l,Element)&&(c=l),3==a.anchorNode.nodeType&&!a.anchorNode.nodeValue&&a.anchorNode.previousElementSibling&&t.preventDefault(),(l||o)&&!n.backspace)return void t.preventDefault();if("Range"!=a.type&&!a.anchorOffset&&a.anchorNode==e.DOM.input&&"Delete"!=t.key)return void t.preventDefault();if("Range"!=a.type&&c&&c.hasAttribute("readonly"))return void yt(rt(c));"Delete"==t.key&&g&&bt(a.anchorNode.nextSibling)&&e.removeTags(a.anchorNode.nextSibling)}return!0}var p="manual"==n.dropdown.position;switch(t.key){case"Backspace":"select"==n.mode&&n.enforceWhitelist&&e.value.length?e.removeTags():e.state.dropdown.visible&&"manual"!=n.dropdown.position||""!=t.target.textContent&&8203!=i.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0));break;case"Esc":case"Escape":if(e.state.dropdown.visible)return;t.target.blur();break;case"Down":case"ArrowDown":e.state.dropdown.visible||e.dropdown.show();break;case"ArrowRight":var f=e.state.inputSuggestion||e.state.ddItemData;if(f&&n.autoComplete.rightKey)return void e.addTags([f],!0);break;case"Tab":return!0;case"Enter":if(e.state.dropdown.visible&&!p)return;t.preventDefault();var m=e.state.autoCompleteData||i;setTimeout((function(){e.state.dropdown.visible&&!p||e.state.actions.selectOption||!n.addTagOn.includes(t.key.toLowerCase())||(e.addTags([m],!0),e.state.autoCompleteData=null)}))}})).catch((function(t){return t}))}},onInput:function(t){this.postUpdate();var e=this.settings;if("mix"==e.mode)return this.events.callbacks.onMixTagsInput.call(this,t);var n=this.input.normalize.call(this,void 0,{trim:!1}),i=n.length>=e.dropdown.enabled,s={value:n,inputElm:this.DOM.input},a=this.validateTag({value:n});"select"==e.mode&&this.toggleScopeValidation(a),s.isValid=a,this.state.inputText!=n&&(this.input.set.call(this,n,!1),-1!=n.search(e.delimiters)?this.addTags(n)&&this.input.set.call(this):e.dropdown.enabled>=0&&this.dropdown[i?"show":"hide"](n),this.trigger("input",s))},onMixTagsInput:function(t){var e,n,i,s,a,o,r,l,d=this,c=this.settings,u=this.value.length,h=this.getTagElms(),g=document.createDocumentFragment(),p=window.getSelection().getRangeAt(0),f=[].map.call(h,(function(t){return bt(t).value}));if("deleteContentBackward"==t.inputType&>()&&this.events.callbacks.onKeydown.call(this,{target:t.target,key:"Backspace"}),Tt(this.getTagElms()),this.value.slice().forEach((function(t){t.readonly&&!f.includes(t.value)&&g.appendChild(d.createTagElem(t))})),g.childNodes.length&&(p.insertNode(g),this.setRangeAtStartEnd(!1,g.lastChild)),h.length!=u)return this.value=[].map.call(this.getTagElms(),(function(t){return bt(t)})),void this.update({withoutChangeEvent:!0});if(this.hasMaxTags())return!0;if(window.getSelection&&(o=window.getSelection()).rangeCount>0&&3==o.anchorNode.nodeType){if((p=o.getRangeAt(0).cloneRange()).collapse(!0),p.setStart(o.focusNode,0),i=(e=p.toString().slice(0,p.endOffset)).split(c.pattern).length-1,(n=e.match(c.pattern))&&(s=e.slice(e.lastIndexOf(n[n.length-1]))),s){if(this.state.actions.ArrowLeft=!1,this.state.tag={prefix:s.match(c.pattern)[0],value:s.replace(c.pattern,"")},this.state.tag.baseOffset=o.baseOffset-this.state.tag.value.length,l=this.state.tag.value.match(c.delimiters))return this.state.tag.value=this.state.tag.value.replace(c.delimiters,""),this.state.tag.delimiters=l[0],this.addTags(this.state.tag.value,c.dropdown.clearOnSelect),void this.dropdown.hide();a=this.state.tag.value.length>=c.dropdown.enabled;try{r=(r=this.state.flaggedTags[this.state.tag.baseOffset]).prefix==this.state.tag.prefix&&r.value[0]==this.state.tag.value[0],this.state.flaggedTags[this.state.tag.baseOffset]&&!this.state.tag.value&&delete this.state.flaggedTags[this.state.tag.baseOffset]}catch(t){}(r||i500||!e.focusable)?this.state.dropdown.visible?this.dropdown.hide():0===e.dropdown.enabled&&"mix"!=e.mode&&this.dropdown.show(this.value.length?"":void 0):"select"!=e.mode||0!==e.dropdown.enabled||this.state.dropdown.visible||(this.events.callbacks.onDoubleClickScope.call(this,function(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);n.push.apply(n,i)}return n}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}(function(t){for(var e=1;e=this.settings.dropdown.enabled&&(this.state.editing&&(this.state.editing.value=o),this.dropdown.show(o)),this.trigger("edit:input",{tag:i,index:s,data:ct({},this.value[s],{newValue:o}),event:e})},onEditTagPaste:function(t,e){var n=(e.clipboardData||window.clipboardData).getData("Text");e.preventDefault();var i=wt(n);this.setRangeAtStartEnd(!1,i)},onEditTagClick:function(t,e){this.events.callbacks.onClickScope.call(this,e)},onEditTagFocus:function(t){this.state.editing={scope:t,input:t.querySelector("[contenteditable]")}},onEditTagBlur:function(t,e){var n=ft.call(this,e.relatedTarget);if("select"==this.settings.mode&&n&&e.relatedTarget.contains(e.target))this.dropdown.hide();else if(this.state.editing&&(this.state.hasFocus||this.toggleFocusClass(),this.DOM.scope.contains(document.activeElement)||this.trigger("blur",{}),this.DOM.scope.contains(t))){var i,s,a,o=this.settings,r=t.closest("."+o.classNames.tag),l=bt(r),d=this.input.normalize.call(this,t),c=(Vt(i={},o.tagTextProp,d),Vt(i,"__tagId",l.__tagId),i),u=l.__originalData,h=this.editTagChangeDetected(ct(l,c)),g=this.validateTag(c);if(d)if(h){var p;if(s=this.hasMaxTags(),a=ct({},u,(Vt(p={},o.tagTextProp,this.trim(d)),Vt(p,"__isValid",g),p)),o.transformTag.call(this,a,u),!0!==(g=(!s||!0===u.__isValid)&&this.validateTag(a))){if(this.trigger("invalid",{data:a,tag:r,message:g}),o.editTags.keepInvalid)return;o.keepInvalidTags?a.__isValid=g:a=u}else o.keepInvalidTags&&(delete a.title,delete a["aria-invalid"],delete a.class);this.onEditTagDone(r,a)}else this.onEditTagDone(r,u);else this.onEditTagDone(r)}},onEditTagkeydown:function(t,e){if(!this.state.composing)switch(this.trigger("edit:keydown",{event:t}),t.key){case"Esc":case"Escape":this.state.editing=!1,e.__tagifyTagData.__originalData.value?e.parentNode.replaceChild(e.__tagifyTagData.__originalHTML,e):e.remove();break;case"Enter":case"Tab":t.preventDefault(),setTimeout((function(){return t.target.blur()}),0)}},onDoubleClickScope:function(t){var e=t.target.closest("."+this.settings.classNames.tag);if(e){var n,i,s=bt(e),a=this.settings;!1!==(null==s?void 0:s.editable)&&(n=e.classList.contains(this.settings.classNames.tagEditing),i=e.hasAttribute("readonly"),a.readonly||n||i||!this.settings.editTags||!a.userInput||(this.events.callbacks.onEditTagFocus.call(this,e),this.editTag(e)),this.toggleFocusClass(!0),"select"!=a.mode&&this.trigger("dblclick",{tag:e,index:this.getNodeIndex(e),data:bt(e)}))}},onInputDOMChange:function(t){var e=this;t.forEach((function(t){t.addedNodes.forEach((function(t){if("

"==t.outerHTML)t.replaceWith(document.createElement("br"));else if(1==t.nodeType&&t.querySelector(e.settings.classNames.tagSelector)){var n,i=document.createTextNode("");3==t.childNodes[0].nodeType&&"BR"!=t.previousSibling.nodeName&&(i=document.createTextNode("\n")),(n=t).replaceWith.apply(n,Rt([i].concat(Rt(Rt(t.childNodes).slice(0,-1))))),yt(i)}else if(ft.call(e,t)){var s;if(3!=(null===(s=t.previousSibling)||void 0===s?void 0:s.nodeType)||t.previousSibling.textContent||t.previousSibling.remove(),t.previousSibling&&"BR"==t.previousSibling.nodeName){t.previousSibling.replaceWith("\n​");for(var a=t.nextSibling,o="";a;)o+=a.textContent,a=a.nextSibling;o.trim()&&yt(t.previousSibling)}else t.previousSibling&&!bt(t.previousSibling)||t.before("​")}})),t.removedNodes.forEach((function(t){t&&"BR"==t.nodeName&&ft.call(e,n)&&(e.removeTags(n),e.fixFirefoxLastTagNoCaret())}))}));var n=this.DOM.input.lastChild;n&&""==n.nodeValue&&n.remove(),n&&"BR"==n.nodeName||this.DOM.input.appendChild(document.createElement("br"))}}};function Ft(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n");else{try{Ut(JSON.parse(t),Array)&&(t=JSON.parse(t))}catch(t){}this.addTags(t,!0).forEach((function(t){return t&&t.classList.add(n.classNames.tagNoAnimation)}))}else this.postUpdate();this.state.lastOriginalValueReported=n.mixMode.integrated?"":this.DOM.originalInput.value},cloneEvent:function(t){var e={};for(var n in t)"path"!=n&&(e[n]=t[n]);return e},loading:function(t){return this.state.isLoading=t,this.DOM.scope.classList[t?"add":"remove"](this.settings.classNames.scopeLoading),this},tagLoading:function(t,e){return t&&t.classList[e?"add":"remove"](this.settings.classNames.tagLoading),this},toggleClass:function(t,e){"string"==typeof t&&this.DOM.scope.classList.toggle(t,e)},toggleScopeValidation:function(t){var e=!0===t||void 0===t;!this.settings.required&&t&&t===this.TEXTS.empty&&(e=!0),this.toggleClass(this.settings.classNames.tagInvalid,!e),this.DOM.scope.title=e?"":t},toggleFocusClass:function(t){this.toggleClass(this.settings.classNames.focus,!!t)},setPlaceholder:function(t){var e=this;["data","aria"].forEach((function(n){return e.DOM.input.setAttribute("".concat(n,"-placeholder"),t)}))},triggerChangeEvent:function(){if(!this.settings.mixMode.integrated){var t=this.DOM.originalInput,e=this.state.lastOriginalValueReported!==t.value,n=new CustomEvent("change",{bubbles:!0});e&&(this.state.lastOriginalValueReported=t.value,n.simulated=!0,t._valueTracker&&t._valueTracker.setValue(Math.random()),t.dispatchEvent(n),this.trigger("change",this.state.lastOriginalValueReported),t.value=this.state.lastOriginalValueReported)}},events:qt,fixFirefoxLastTagNoCaret:function(){},setRangeAtStartEnd:function(t,e){if(e){t="number"==typeof t?t:!!t,e=e.lastChild||e;var n=document.getSelection();if(Ut(n.focusNode,Element)&&!this.DOM.input.contains(n.focusNode))return!0;try{n.rangeCount>=1&&["Start","End"].forEach((function(i){return n.getRangeAt(0)["set"+i](e,t||e.length)}))}catch(t){console.warn(t)}}},insertAfterTag:function(t,e){if(e=e||this.settings.mixMode.insertAfterTag,t&&t.parentNode&&e)return e="string"==typeof e?document.createTextNode(e):e,t.parentNode.insertBefore(e,t.nextSibling),e},editTagChangeDetected:function(t){var e=t.__originalData;for(var n in e)if(!this.dataProps.includes(n)&&t[n]!=e[n])return!0;return!1},getTagTextNode:function(t){return t.querySelector(this.settings.classNames.tagTextSelector)},setTagTextNode:function(t,e){this.getTagTextNode(t).innerHTML=lt(e)},editTag:function(t,e){var n=this;t=t||this.getLastTag(),e=e||{};var i=this.settings,s=this.getTagTextNode(t),a=this.getNodeIndex(t),o=bt(t),r=this.events.callbacks,l=!0,d="select"==i.mode;if(!d&&this.dropdown.hide(),s){if(!Ut(o,Object)||!("editable"in o)||o.editable)return o=bt(t,{__originalData:ct({},o),__originalHTML:t.cloneNode(!0)}),bt(o.__originalHTML,o.__originalData),s.setAttribute("contenteditable",!0),t.classList.add(i.classNames.tagEditing),this.events.callbacks.onEditTagFocus.call(this,t),s.addEventListener("click",r.onEditTagClick.bind(this,t)),s.addEventListener("blur",r.onEditTagBlur.bind(this,this.getTagTextNode(t))),s.addEventListener("input",r.onEditTagInput.bind(this,s)),s.addEventListener("paste",r.onEditTagPaste.bind(this,s)),s.addEventListener("keydown",(function(e){return r.onEditTagkeydown.call(n,e,t)})),s.addEventListener("compositionstart",r.onCompositionStart.bind(this)),s.addEventListener("compositionend",r.onCompositionEnd.bind(this)),e.skipValidation||(l=this.editTagToggleValidity(t)),s.originalIsValid=l,this.trigger("edit:start",{tag:t,index:a,data:o,isValid:l}),s.focus(),!d&&this.setRangeAtStartEnd(!1,s),0===i.dropdown.enabled&&!d&&this.dropdown.show(),this.state.hasFocus=!0,this}else nt.warn("Cannot find element in Tag template: .",i.classNames.tagTextSelector)},editTagToggleValidity:function(t,e){var n;if(e=e||bt(t))return(n=!("__isValid"in e)||!0===e.__isValid)||this.removeTagsFromValue(t),this.update(),t.classList.toggle(this.settings.classNames.tagNotAllowed,!n),e.__isValid=n,e.__isValid;nt.warn("tag has no data: ",t,e)},onEditTagDone:function(t,e){t=t||this.state.editing.scope,e=e||{};var n,i,s=this.settings,a={tag:t,index:this.getNodeIndex(t),previousData:bt(t),data:e};this.trigger("edit:beforeUpdate",a,{cloneData:!1}),this.state.editing=!1,delete e.__originalData,delete e.__originalHTML,t&&t.parentNode&&((void 0!==(i=e[s.tagTextProp])?null===(n=(i+="").trim)||void 0===n?void 0:n.call(i):s.tagTextProp in e?void 0:e.value)?(t=this.replaceTag(t,e),this.editTagToggleValidity(t,e),s.a11y.focusableTags?t.focus():"select"!=s.mode&&yt(t)):this.removeTags(t)),this.trigger("edit:updated",a),s.dropdown.closeOnSelect&&this.dropdown.hide(),this.settings.keepInvalidTags&&this.reCheckInvalidTags()},replaceTag:function(t,e){e&&""!==e.value&&void 0!==e.value||(e=t.__tagifyTagData),e.__isValid&&1!=e.__isValid&&ct(e,this.getInvalidTagAttrs(e,e.__isValid));var n=this.createTagElem(e);return t.parentNode.replaceChild(n,t),this.updateValueByDOMTags(),n},updateValueByDOMTags:function(){var t=this;this.value.length=0;var e=this.settings.classNames,n=[e.tagNotAllowed.split(" ")[0],e.tagHide];[].forEach.call(this.getTagElms(),(function(e){Kt(e.classList).some((function(t){return n.includes(t)}))||t.value.push(bt(e))})),this.update(),this.dropdown.refilter()},injectAtCaret:function(t,e){var n;if(e=e||(null===(n=this.state.selection)||void 0===n?void 0:n.range),"string"==typeof t&&(t=document.createTextNode(t)),!e&&t)return this.appendMixTags(t),this;var i=wt(t,e);return this.setRangeAtStartEnd(!1,i),this.updateValueByDOMTags(),this.update(),this},input:{set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.settings,i=n.dropdown.closeOnSelect;this.state.inputText=t,e&&(this.DOM.input.innerHTML=lt(""+t),t&&this.toggleClass(n.classNames.empty,!this.DOM.input.innerHTML)),!t&&i&&this.dropdown.hide.bind(this),this.input.autocomplete.suggest.call(this),this.input.validate.call(this)},raw:function(){return this.DOM.input.textContent},validate:function(){var t=!this.state.inputText||!0===this.validateTag({value:this.state.inputText});return this.DOM.input.classList.toggle(this.settings.classNames.inputInvalid,!t),t},normalize:function(t,e){var n=t||this.DOM.input,i=[];n.childNodes.forEach((function(t){return 3==t.nodeType&&i.push(t.nodeValue)})),i=i.join("\n");try{i=i.replace(/(?:\r\n|\r|\n)/g,this.settings.delimiters.source.charAt(0))}catch(t){}return i=i.replace(/\s/g," "),(null==e?void 0:e.trim)?this.trim(i):i},autocomplete:{suggest:function(t){if(this.settings.autoComplete.enabled){"object"!=typeof(t=t||{value:""})&&(t={value:t});var e=this.dropdown.getMappedValue(t);if("number"!=typeof e){var n=this.state.inputText.toLowerCase(),i=e.substr(0,this.state.inputText.length).toLowerCase(),s=e.substring(this.state.inputText.length);e&&this.state.inputText&&i==n?(this.DOM.input.setAttribute("data-suggest",s),this.state.inputSuggestion=t):(this.DOM.input.removeAttribute("data-suggest"),delete this.state.inputSuggestion)}}},set:function(t){var e=this.DOM.input.getAttribute("data-suggest"),n=t||(e?this.state.inputText+e:null);return!!n&&("mix"==this.settings.mode?this.replaceTextWithNode(document.createTextNode(this.state.tag.prefix+n)):(this.input.set.call(this,n),this.setRangeAtStartEnd(!1,this.DOM.input)),this.input.autocomplete.suggest.call(this),this.dropdown.hide(),!0)}}},getTagIdx:function(t){return this.value.findIndex((function(e){return e.__tagId==(t||{}).__tagId}))},getNodeIndex:function(t){var e=0;if(t)for(;t=t.previousElementSibling;)e++;return e},getTagElms:function(){for(var t=arguments.length,e=new Array(t),n=0;n=this.settings.maxTags&&this.TEXTS.exceed},setReadonly:function(t,e){var n=this.settings;this.DOM.scope.contains(document.activeElement)&&document.activeElement.blur(),n[e||"readonly"]=t,this.DOM.scope[(t?"set":"remove")+"Attribute"](e||"readonly",!0),this.settings.userInput=!0,this.setContentEditable(!t)},setContentEditable:function(t){this.DOM.input.contentEditable=t,this.DOM.input.tabIndex=t?0:-1},setDisabled:function(t){this.setReadonly(t,"disabled")},normalizeTags:function(t){var e=this,n=this.settings,i=n.whitelist,s=n.delimiters,a=n.mode,o=n.tagTextProp,r=[],l=!!i&&Ut(i[0],Object),d=Array.isArray(t),c=d&&t[0].value,u=function(t){return(t+"").split(s).reduce((function(t,n){var i,s=e.trim(n);return s&&t.push(($t(i={},o,s),$t(i,"value",s),i)),t}),[])};if("number"==typeof t&&(t=t.toString()),"string"==typeof t){if(!t.trim())return[];t=u(t)}else d&&(t=t.reduce((function(t,n){if(dt(n)){var i=ct({},n);o in i||(o="value"),i[o]=e.trim(i[o]),(i[o]||0===i[o])&&t.push(i)}else if(null!=n&&""!==n&&void 0!==n){var s;(s=t).push.apply(s,Kt(u(n)))}return t}),[]));return l&&!c&&(t.forEach((function(t){var n=r.map((function(t){return t.value})),i=e.dropdown.filterListItems.call(e,t[o],{exact:!0});e.settings.duplicates||(i=i.filter((function(t){return!n.includes(t.value)})));var s=i.length>1?e.getWhitelistItem(t[o],o,i):i[0];s&&Ut(s,Object)?r.push(s):"mix"!=a&&(null==t.value&&(t.value=t[o]),r.push(t))})),r.length&&(t=r)),t},parseMixTags:function(t){var e=this,n=this.settings,i=n.mixTagsInterpolator,s=n.duplicates,a=n.transformTag,o=n.enforceWhitelist,r=n.maxTags,l=n.tagTextProp,d=[];t=t.split(i[0]).map((function(t,n){var c,u,h,g=t.split(i[1]),p=g[0],f=d.length==r;try{if(p==+p)throw Error;u=JSON.parse(p)}catch(t){u=e.normalizeTags(p)[0]||{value:p}}if(a.call(e,u),f||!(g.length>1)||o&&!e.isTagWhitelisted(u.value)||!s&&e.isTagDuplicate(u.value)){if(t)return n?i[0]+t:t}else u[c=u[l]?l:"value"]=e.trim(u[c]),h=e.createTagElem(u),d.push(u),h.classList.add(e.settings.classNames.tagNoAnimation),g[0]=h.outerHTML,e.value.push(u);return g.join("")})).join(""),this.DOM.input.innerHTML=t,this.DOM.input.appendChild(document.createTextNode("")),this.DOM.input.normalize();var c=this.getTagElms();return c.forEach((function(t,e){return bt(t,d[e])})),this.update({withoutChangeEvent:!0}),Tt(c,this.state.hasFocus),t},replaceTextWithNode:function(t,e){if(this.state.tag||e){e=e||this.state.tag.prefix+this.state.tag.value;var n,i,s=this.state.selection||window.getSelection(),a=s.anchorNode,o=this.state.tag.delimiters?this.state.tag.delimiters.length:0;return a.splitText(s.anchorOffset-o),-1==(n=a.nodeValue.lastIndexOf(e))||(i=a.splitText(n),t&&a.parentNode.replaceChild(t,i)),!0}},prepareNewTagNode:function(t,e){e=e||{};var n=this.settings,i=[],s={},a=Object.assign({},t,{value:t.value+""});if(t=Object.assign({},a),n.transformTag.call(this,t),t.__isValid=this.hasMaxTags()||this.validateTag(t),!0!==t.__isValid){if(e.skipInvalid)return;if(ct(s,this.getInvalidTagAttrs(t,t.__isValid),{__preInvalidData:a}),t.__isValid==this.TEXTS.duplicate&&this.flashTag(this.getTagElmByValue(t.value)),!n.createInvalidTags)return void i.push(t.value)}return"readonly"in t&&(t.readonly?s["aria-readonly"]=!0:delete t.readonly),{tagElm:this.createTagElem(t,s),tagData:t,aggregatedInvalidInput:i}},postProcessNewTagNode:function(t,e){var n=this,i=this.settings,s=e.__isValid;s&&!0===s?this.value.push(e):(this.trigger("invalid",{data:e,index:this.value.length,tag:t,message:s}),i.keepInvalidTags||setTimeout((function(){return n.removeTags(t,!0)}),1e3)),this.dropdown.position()},selectTag:function(t,e){var n=this;if(!this.settings.enforceWhitelist||this.isTagWhitelisted(e.value)){this.state.actions.selectOption&&setTimeout((function(){return n.setRangeAtStartEnd(!1,n.DOM.input)}));var i=this.getLastTag();return i?this.replaceTag(i,e):this.appendTag(t),this.value[0]=e,this.update(),this.trigger("add",{tag:t,data:e}),[t]}},addEmptyTag:function(t){var e=ct({value:""},t||{}),n=this.createTagElem(e);bt(n,e),this.appendTag(n),this.editTag(n,{skipValidation:!0}),this.toggleFocusClass(!0)},addTags:function(t,e,n){var i=this,s=[],a=this.settings,o=[],r=document.createDocumentFragment(),l=[];if(!t||0==t.length)return s;switch(t=this.normalizeTags(t),a.mode){case"mix":return this.addMixTags(t);case"select":e=!1,this.removeAllTags()}return this.DOM.input.removeAttribute("style"),t.forEach((function(t){var e=i.prepareNewTagNode(t,{skipInvalid:n||a.skipInvalid});if(e){var d=e.tagElm;if(t=e.tagData,o=e.aggregatedInvalidInput,s.push(d),"select"==a.mode)return i.selectTag(d,t);r.appendChild(d),i.postProcessNewTagNode(d,t),l.push({tagElm:d,tagData:t})}})),this.appendTag(r),l.forEach((function(t){var e=t.tagElm,n=t.tagData;return i.trigger("add",{tag:e,index:i.getTagIdx(n),data:n})})),this.update(),t.length&&e&&(this.input.set.call(this,a.createInvalidTags?"":o.join(a._delimiters)),this.setRangeAtStartEnd(!1,this.DOM.input)),this.dropdown.refilter(),s},addMixTags:function(t){var e=this;if((t=this.normalizeTags(t))[0].prefix||this.state.tag)return this.prefixedTextToTag(t[0]);var n=document.createDocumentFragment();return t.forEach((function(t){var i=e.prepareNewTagNode(t);n.appendChild(i.tagElm),e.insertAfterTag(i.tagElm),e.postProcessNewTagNode(i.tagElm,i.tagData)})),this.appendMixTags(n),n.children},appendMixTags:function(t){var e=!!this.state.selection;e?this.injectAtCaret(t):(this.DOM.input.focus(),(e=this.setStateSelection()).range.setStart(this.DOM.input,e.range.endOffset),e.range.setEnd(this.DOM.input,e.range.endOffset),this.DOM.input.appendChild(t),this.updateValueByDOMTags(),this.update())},prefixedTextToTag:function(t){var e,n,i,s=this,a=this.settings,o=null===(e=this.state.tag)||void 0===e?void 0:e.delimiters;if(t.prefix=t.prefix||this.state.tag?this.state.tag.prefix:(a.pattern.source||a.pattern)[0],i=this.prepareNewTagNode(t),n=i.tagElm,this.replaceTextWithNode(n)||this.DOM.input.appendChild(n),setTimeout((function(){return n.classList.add(s.settings.classNames.tagNoAnimation)}),300),this.update(),!o){var r=this.insertAfterTag(n)||n;setTimeout(yt,0,r)}return this.state.tag=null,this.postProcessNewTagNode(n,i.tagData),n},appendTag:function(t){var e=this.DOM,n=e.input;e.scope.insertBefore(t,n)},createTagElem:function(t,e){t.__tagId=pt();var n,i=ct({},t,Wt({value:lt(t.value+"")},e));return function(t){for(var e,n=document.createNodeIterator(t,NodeFilter.SHOW_TEXT,null,!1);e=n.nextNode();)e.textContent.trim()||e.parentNode.removeChild(e)}(n=this.parseTemplate("tag",[i,this])),bt(n,t),n},reCheckInvalidTags:function(){var t=this,e=this.settings;this.getTagElms(e.classNames.tagNotAllowed).forEach((function(n,i){var s=bt(n),a=t.hasMaxTags(),o=t.validateTag(s),r=!0===o&&!a;if("select"==e.mode&&t.toggleScopeValidation(o),r)return s=s.__preInvalidData?s.__preInvalidData:{value:s.value},t.replaceTag(n,s);n.title=a||o}))},removeTags:function(t,e,n){var i,s=this,a=this.settings;if(t=t&&Ut(t,HTMLElement)?[t]:Ut(t,Array)?t:t?[t]:[this.getLastTag()].filter((function(t){return t})),i=t.reduce((function(t,e){e&&"string"==typeof e&&(e=s.getTagElmByValue(e));var n=bt(e);return e&&n&&!n.readonly&&t.push({node:e,idx:s.getTagIdx(n),data:bt(e,{__removed:!0})}),t}),[]),n="number"==typeof n?n:this.CSSVars.tagHideTransition,"select"==a.mode&&(n=0,this.input.set.call(this)),1==i.length&&"select"!=a.mode&&i[0].node.classList.contains(a.classNames.tagNotAllowed)&&(e=!0),i.length)return a.hooks.beforeRemoveTag(i,{tagify:this}).then((function(){var t=function(t){t.node.parentNode&&(t.node.parentNode.removeChild(t.node),e?a.keepInvalidTags&&this.trigger("remove",{tag:t.node,index:t.idx}):(this.trigger("remove",{tag:t.node,index:t.idx,data:t.data}),this.dropdown.refilter(),this.dropdown.position(),this.DOM.input.normalize(),a.keepInvalidTags&&this.reCheckInvalidTags()))};n&&n>10&&1==i.length?function(e){e.node.style.width=parseFloat(window.getComputedStyle(e.node).width)+"px",document.body.clientTop,e.node.classList.add(a.classNames.tagHide),setTimeout(t.bind(this),n,e)}.call(s,i[0]):i.forEach(t.bind(s)),e||(s.removeTagsFromValue(i.map((function(t){return t.node}))),s.update(),"select"==a.mode&&a.userInput&&s.setContentEditable(!0))})).catch((function(t){}))},removeTagsFromDOM:function(){this.getTagElms().forEach((function(t){return t.remove()}))},removeTagsFromValue:function(t){var e=this;(t=Array.isArray(t)?t:[t]).forEach((function(t){var n=bt(t),i=e.getTagIdx(n);i>-1&&e.value.splice(i,1)}))},removeAllTags:function(t){var e=this;t=t||{},this.value=[],"mix"==this.settings.mode?this.DOM.input.innerHTML="":this.removeTagsFromDOM(),this.dropdown.refilter(),this.dropdown.position(),this.state.dropdown.visible&&setTimeout((function(){e.DOM.input.focus()})),"select"==this.settings.mode&&(this.input.set.call(this),this.settings.userInput&&this.setContentEditable(!0)),this.update(t)},postUpdate:function(){this.state.blockChangeEvent=!1;var t,e,n=this.settings,i=n.classNames,s="mix"==n.mode?n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value.trim():this.value.length+this.input.raw.call(this).length;this.toggleClass(i.hasMaxTags,this.value.length>=n.maxTags),this.toggleClass(i.hasNoTags,!this.value.length),this.toggleClass(i.empty,!s),"select"==n.mode&&this.toggleScopeValidation(null===(e=this.value)||void 0===e||null===(t=e[0])||void 0===t?void 0:t.__isValid)},setOriginalInputValue:function(t){var e=this.DOM.originalInput;this.settings.mixMode.integrated||(e.value=t,e.tagifyValue=e.value,this.setPersistedData(t,"value"))},update:function(t){clearTimeout(this.debouncedUpdateTimeout),this.debouncedUpdateTimeout=setTimeout(function(){var e=this.getInputValue();this.setOriginalInputValue(e),this.settings.onChangeAfterBlur&&(t||{}).withoutChangeEvent||this.state.blockChangeEvent||this.triggerChangeEvent(),this.postUpdate()}.bind(this),100),this.events.bindOriginaInputListener.call(this,100)},getInputValue:function(){var t=this.getCleanValue();return"mix"==this.settings.mode?this.getMixedTagsAsString(t):t.length?this.settings.originalInputValueFormat?this.settings.originalInputValueFormat(t):JSON.stringify(t):""},getCleanValue:function(t){return st(t||this.value,this.dataProps)},getMixedTagsAsString:function(){var t="",e=this,n=this.settings,i=n.originalInputValueFormat||JSON.stringify,s=n.mixTagsInterpolator;return function n(a){a.childNodes.forEach((function(a){if(1==a.nodeType){var o=bt(a);if("BR"==a.tagName&&(t+="\r\n"),o&&ft.call(e,a)){if(o.__removed)return;t+=s[0]+i(at(o,e.dataProps))+s[1]}else a.getAttribute("style")||["B","I","U"].includes(a.tagName)?t+=a.textContent:"DIV"!=a.tagName&&"P"!=a.tagName||(t+="\r\n",n(a))}else t+=a.textContent}))}(this.DOM.input),t}},zt.prototype.removeTag=zt.prototype.removeTags;const Xt=[];let Jt,Qt;function Gt(t,e,n,i,s,a){Xt[e.id]=new t(e,function(t,e){return{id:t,whitelist:e.options,enforceWhitelist:!e.userInput,duplicates:e.allowDuplicates,maxTags:e.maxItems,delimiters:null,originalInputValueFormat:t=>t.map((t=>t.value)),dropdown:{enabled:e.dropdownSuggestionsStartAfter,maxItems:e.dropdownMaxItems,closeOnSelect:e.dropdownCloseOnSelect,highlightFirst:e.highlight},transformTag(t){t.display||(t.display=t.value,t.value=encodeURIComponent(t.value)),t.display=t.display.replace(//g,">")},templates:{wrapper(t,e){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:t=>`
\n \n
\n ${t.display}\n
\n
`,dropdownItem:t=>`
\n ${t.display}\n
`}}}(e.id,n)),Xt[e.id].addTags(i),void 0!==s&&Xt[e.id].on("input",(t=>{!function(t,e,n,i,s,a){void 0!==Jt&&Jt.abort(),Jt=new AbortController,t.whitelist=null,"number"==typeof Qt&&(t.DOM.scope.ownerDocument.defaultView.clearTimeout(Qt),Qt=void 0),s.detail.value.length{const e=s.detail.value;n.writeParameter(i,e),t.loading(!0),fetch(n.getUrl().toString(),{signal:Jt.signal}).then((t=>t.json())).catch((()=>{})).then((n=>{t.whitelist=n,t.loading(!1).dropdown.show(e)}))}),a))}(Xt[e.id],n.suggestionStarts,s,a,t,n.autocompleteTriggerTimeout)}))}var Yt;e.UI=e.UI||{},e.UI.Input=e.UI.Input||{},(Yt=e.UI.Input).textarea=new o,Yt.markdown=new w,Yt.treeSelect=new G(new Y(t),e.UI.menu.drilldown,{txt:t=>e.Language.txt(t)},n),Yt.tagInput=Yt.tag||{},Yt.tagInput.init=(t,e,n,i,s)=>Gt(zt,t,e,n,i,s),Yt.tagInput.getTagifyInstance=t=>Xt[t]}($,il,document); diff --git a/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js b/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js index 6c4743119f0b..a1a55e0ce8d8 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js +++ b/components/ILIAS/UI/resources/js/Input/Field/rollup.config.js @@ -14,6 +14,7 @@ */ import terser from '@rollup/plugin-terser'; +import nodeResolve from '@rollup/plugin-node-resolve'; import copyright from '../../../../../../../scripts/Copyright-Checker/copyright.js'; import preserveCopyright from '../../../../../../../scripts/Copyright-Checker/preserveCopyright.js'; @@ -33,7 +34,6 @@ export default { jquery: '$', ilias: 'il', document: 'document', - Tagify: 'Tagify', }, plugins: [ terser({ @@ -43,4 +43,7 @@ export default { }), ], }, + plugins: [ + nodeResolve(), + ] }; diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js index 8456592b4b20..39c38d732e55 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js @@ -31,7 +31,7 @@ import TextareaFactory from './Textarea/textarea.factory.js'; import MarkdownFactory from './Markdown/markdown.factory.js'; import TreeSelectFactory from './TreeSelect/TreeSelectFactory.js'; import JQueryEventListener from '../../../Core/src/JQueryEventListener.js'; -import Tagify from 'Tagify'; +import Tagify from '@yaireo/tagify'; import * as tag from './Tag/tag.js'; il.UI = il.UI || {}; diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php index 49cc9f19be3c..ad51b892450a 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php @@ -866,7 +866,6 @@ protected function renderHiddenField(F\Hidden $input): string public function registerResources(ResourceRegistry $registry): void { parent::registerResources($registry); - $registry->register('assets/js/tagify.js'); $registry->register('assets/css/tagify.css'); $registry->register('assets/js/tagInput.js'); From 8d4aae2b5a3d769a0e90ef13071a76e273c15b16 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Thu, 9 Oct 2025 18:41:49 +0200 Subject: [PATCH 13/16] UI: Fix Small Type in Test Identifier --- components/ILIAS/UI/tests/Client/Input/Field/Tag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js index ecfd8ed66ada..efe31982f526 100644 --- a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js +++ b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js @@ -118,7 +118,7 @@ describe('Tag Input Field', () => { mock.reset(); }); - it('should urldecode user input.', () => { + it('should urlencode user input.', () => { const userInput = [ {value: '++1#*'}, {value: '[-2]'}, From 7eecf7538b02161ff24faafe959114c2e859173d Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Fri, 10 Oct 2025 15:02:33 +0200 Subject: [PATCH 14/16] Revert "UI: Expose Instances of TagInput" --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 32 +++++++------------ .../js/Input/Field/src/input.factory.js | 5 ++- .../Component/Input/Field/Tag.php | 1 - 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 0fddc449ba72..278938fade3c 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -38,4 +38,4 @@ This Software may not be rebranded and sold as a library under any other name other than "Tagify" (by owner) or as part of another library. - */var Z="​";function tt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n/g,">").replace(/"/g,""").replace(/`|'/g,"'"):t}function dt(t){var e=Object.prototype.toString.call(t).split(" ")[1].slice(0,-1);return t===Object(t)&&"Array"!=e&&"Function"!=e&&"RegExp"!=e&&"HTMLUnknownElement"!=e}function ct(t,e,n){var i,s;function a(t,e){for(var n in e)if(e.hasOwnProperty(n)){if(dt(e[n])){dt(t[n])?a(t[n],e[n]):t[n]=Object.assign({},e[n]);continue}if(Array.isArray(e[n])){t[n]=Object.assign([],e[n]);continue}t[n]=e[n]}}return i=t,(null!=(s=Object)&&"undefined"!=typeof Symbol&&s[Symbol.hasInstance]?s[Symbol.hasInstance](i):i instanceof s)||(t={}),a(t,e),n&&a(t,n),t}function ut(){var t=[],e={},n=!0,i=!1,s=void 0;try{for(var a,o=arguments[Symbol.iterator]();!(n=(a=o.next()).done);n=!0){var r=a.value,l=!0,d=!1,c=void 0;try{for(var u,h=r[Symbol.iterator]();!(l=(u=h.next()).done);l=!0){var g=u.value;dt(g)?e[g.value]||(t.push(g),e[g.value]=1):t.includes(g)||t.push(g)}}catch(t){d=!0,c=t}finally{try{l||null==h.return||h.return()}finally{if(d)throw c}}}}catch(t){i=!0,s=t}finally{try{n||null==o.return||o.return()}finally{if(i)throw s}}return t}function ht(t){return String.prototype.normalize?"string"==typeof t?t.normalize("NFD").replace(/[\u0300-\u036f]/g,""):void 0:t}var gt=function(){return/(?=.*chrome)(?=.*android)/i.test(navigator.userAgent)};function pt(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,(function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)}))}function ft(t){var e;return vt.call(this,t)&&(null==t||null===(e=t.classList)||void 0===e?void 0:e.contains(this.settings.classNames.tag))}function mt(t){return vt.call(this,t)&&(null==t?void 0:t.closest(this.settings.classNames.tagSelector))}function vt(t){var e;return(null==t||null===(e=t.closest)||void 0===e?void 0:e.call(t,this.settings.classNames.namespaceSelector))===this.DOM.scope}function wt(t,e){var n=window.getSelection();return e=e||n.getRangeAt(0),"string"==typeof t&&(t=document.createTextNode(t)),e&&(e.deleteContents(),e.insertNode(t)),t}function bt(t,e,n){return t?(e&&(t.__tagifyTagData=n?e:ct({},t.__tagifyTagData||{},e)),t.__tagifyTagData):(nt.warn("tag element doesn't exist",{tagElm:t,data:e}),e)}function yt(t){if(t&&t.parentNode){var e=t,n=window.getSelection(),i=n.getRangeAt(0);n.rangeCount&&(i.setStartAfter(e),i.collapse(!0),n.removeAllRanges(),n.addRange(i))}}function Tt(t,e){t.forEach((function(t){if(bt(t.previousSibling)||!t.previousSibling){var n=document.createTextNode("​");t.before(n),e&&yt(n)}}))}var St={delimiters:",",pattern:null,tagTextProp:"value",maxTags:1/0,callbacks:{},addTagOnBlur:!0,addTagOn:["blur","tab","enter"],onChangeAfterBlur:!0,duplicates:!1,whitelist:[],blacklist:[],enforceWhitelist:!1,userInput:!0,focusable:!0,keepInvalidTags:!1,createInvalidTags:!0,mixTagsAllowedAfter:/,|\.|\:|\s/,mixTagsInterpolator:["[[","]]"],backspace:!0,skipInvalid:!1,pasteAsTags:!0,editTags:{clicks:2,keepInvalid:!0},transformTag:function(){},trim:!0,a11y:{focusableTags:!1},mixMode:{insertAfterTag:"Ā "},autoComplete:{enabled:!0,rightKey:!1,tabKey:!1},classNames:{namespace:"tagify",mixMode:"tagify--mix",selectMode:"tagify--select",input:"tagify__input",focus:"tagify--focus",tagNoAnimation:"tagify--noAnim",tagInvalid:"tagify--invalid",tagNotAllowed:"tagify--notAllowed",scopeLoading:"tagify--loading",hasMaxTags:"tagify--hasMaxTags",hasNoTags:"tagify--noTags",empty:"tagify--empty",inputInvalid:"tagify__input--invalid",dropdown:"tagify__dropdown",dropdownWrapper:"tagify__dropdown__wrapper",dropdownHeader:"tagify__dropdown__header",dropdownFooter:"tagify__dropdown__footer",dropdownItem:"tagify__dropdown__item",dropdownItemActive:"tagify__dropdown__item--active",dropdownItemHidden:"tagify__dropdown__item--hidden",dropdownItemSelected:"tagify__dropdown__item--selected",dropdownInital:"tagify__dropdown--initial",tag:"tagify__tag",tagText:"tagify__tag-text",tagX:"tagify__tag__removeBtn",tagLoading:"tagify__tag--loading",tagEditing:"tagify__tag--editable",tagFlash:"tagify__tag--flash",tagHide:"tagify__tag--hide"},dropdown:{classname:"",enabled:2,maxItems:10,searchKeys:["value","searchBy"],fuzzySearch:!0,caseSensitive:!1,accentedSearch:!0,includeSelectedTags:!1,escapeHTML:!0,highlightFirst:!0,closeOnSelect:!0,clearOnSelect:!0,position:"all",appendTarget:null},hooks:{beforeRemoveTag:function(){return Promise.resolve()},beforePaste:function(){return Promise.resolve()},suggestionClick:function(){return Promise.resolve()},beforeKeyDown:function(){return Promise.resolve()}}};function xt(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function Et(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],e=this.dropdown.events.callbacks,n=this.listeners.dropdown=this.listeners.dropdown||{position:this.dropdown.position.bind(this,null),onKeyDown:e.onKeyDown.bind(this),onMouseOver:e.onMouseOver.bind(this),onMouseLeave:e.onMouseLeave.bind(this),onClick:e.onClick.bind(this),onScroll:e.onScroll.bind(this)},i=t?"addEventListener":"removeEventListener";"manual"!=this.settings.dropdown.position&&(document[i]("scroll",n.position,!0),window[i]("resize",n.position),window[i]("keydown",n.onKeyDown)),this.DOM.dropdown[i]("mouseover",n.onMouseOver),this.DOM.dropdown[i]("mouseleave",n.onMouseLeave),this.DOM.dropdown[i]("mousedown",n.onClick),this.DOM.dropdown.content[i]("scroll",n.onScroll)},callbacks:{onKeyDown:function(t){var e=this;if(this.state.hasFocus&&!this.state.composing){var n=this.settings,i=n.dropdown.includeSelectedTags,s=this.DOM.dropdown.querySelector(n.classNames.dropdownItemActiveSelector),a=this.dropdown.getSuggestionDataByNode(s),o="mix"==n.mode,r="select"==n.mode;n.hooks.beforeKeyDown(t,{tagify:this}).then((function(l){switch(t.key){case"ArrowDown":case"ArrowUp":case"Down":case"Up":t.preventDefault();var d=e.dropdown.getAllSuggestionsRefs(),c="ArrowUp"==t.key||"Up"==t.key;s&&(s=e.dropdown.getNextOrPrevOption(s,!c)),s&&s.matches(n.classNames.dropdownItemSelector)||(s=d[c?d.length-1:0]),e.dropdown.highlightOption(s,!0);break;case"PageUp":case"PageDown":var u;t.preventDefault();var h=e.dropdown.getAllSuggestionsRefs(),g=Math.floor(e.DOM.dropdown.content.clientHeight/(null===(u=h[0])||void 0===u?void 0:u.offsetHeight))||1,p="PageUp"===t.key;if(s){var f=h.indexOf(s),m=p?Math.max(0,f-g):Math.min(h.length-1,f+g);s=h[m]}else s=h[0];e.dropdown.highlightOption(s,!0);break;case"Home":case"End":t.preventDefault();var v=e.dropdown.getAllSuggestionsRefs();s=v["Home"===t.key?0:v.length-1],e.dropdown.highlightOption(s,!0);break;case"Escape":case"Esc":e.dropdown.hide();break;case"ArrowRight":if(e.state.actions.ArrowLeft||n.autoComplete.rightKey)return;case"Tab":var w=!n.autoComplete.rightKey||!n.autoComplete.tabKey;if(!o&&!r&&s&&w&&!e.state.editing&&a){t.preventDefault();var b=e.dropdown.getMappedValue(a);return e.state.autoCompleteData=a,e.input.autocomplete.set.call(e,b),!1}return!0;case"Enter":t.preventDefault(),e.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),n.hooks.suggestionClick(t,{tagify:e,tagData:a,suggestionElm:s}).then((function(){if(s){var n=i?s:e.dropdown.getNextOrPrevOption(s,!c);e.dropdown.selectOption(s,t,(function(){if(n){var t=n.getAttribute("value");n=e.dropdown.getSuggestionNodeByValue(t),e.dropdown.highlightOption(n)}}))}else e.dropdown.hide(),o||e.addTags(e.state.inputText.trim(),!0)})).catch((function(t){return nt.warn(t)}));break;case"Backspace":if(o||e.state.editing.scope)return;var y=e.input.raw.call(e);""!=y&&8203!=y.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0))}}))}},onMouseOver:function(t){var e=t.target.closest(this.settings.classNames.dropdownItemSelector);this.dropdown.highlightOption(e)},onMouseLeave:function(t){this.dropdown.highlightOption()},onClick:function(t){var e=this;if(0==t.button&&t.target!=this.DOM.dropdown&&t.target!=this.DOM.dropdown.content){var n=t.target.closest(this.settings.classNames.dropdownItemSelector),i=this.dropdown.getSuggestionDataByNode(n);this.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),this.settings.hooks.suggestionClick(t,{tagify:this,tagData:i,suggestionElm:n}).then((function(){n?e.dropdown.selectOption(n,t):e.dropdown.hide()})).catch((function(t){return nt.warn(t)}))}},onScroll:function(t){var e=t.target,n=e.scrollTop/(e.scrollHeight-e.parentNode.clientHeight)*100;this.trigger("dropdown:scroll",{percentage:Math.round(n)})}}},refilter:function(t){t=t||this.state.dropdown.query||"",this.suggestedListItems=this.dropdown.filterListItems(t),this.dropdown.fill(),this.suggestedListItems.length||this.dropdown.hide(),this.trigger("dropdown:updated",this.DOM.dropdown)},getSuggestionDataByNode:function(t){for(var e,n=t&&t.getAttribute("value"),i=this.suggestedListItems.length;i--;){if(dt(e=this.suggestedListItems[i])&&e.value==n)return e;if(e==n)return{value:e}}},getSuggestionNodeByValue:function(t){return this.dropdown.getAllSuggestionsRefs().find((function(e){return e.getAttribute("value")===t}))},getNextOrPrevOption:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.dropdown.getAllSuggestionsRefs(),i=n.findIndex((function(e){return e===t}));return e?n[i+1]:n[i-1]},highlightOption:function(t,e){var n,i=this.settings.classNames.dropdownItemActive;if(this.state.ddItemElm&&(this.state.ddItemElm.classList.remove(i),this.state.ddItemElm.removeAttribute("aria-selected")),!t)return this.state.ddItemData=null,this.state.ddItemElm=null,void this.input.autocomplete.suggest.call(this);n=this.dropdown.getSuggestionDataByNode(t),this.state.ddItemData=n,this.state.ddItemElm=t,t.classList.add(i),t.setAttribute("aria-selected",!0),e&&(t.parentNode.scrollTop=t.clientHeight+t.offsetTop-t.parentNode.clientHeight),this.settings.autoComplete&&(this.input.autocomplete.suggest.call(this,n),this.dropdown.position())},selectOption:function(t,e,n){var i=this,s=this.settings,a=s.dropdown.includeSelectedTags,o=s.dropdown,r=o.clearOnSelect,l=o.closeOnSelect;if(!t)return this.addTags(this.state.inputText,!0),void(l&&this.dropdown.hide());e=e||{};var d=t.getAttribute("value"),c="noMatch"==d,u="mix"==s.mode,h=this.suggestedListItems.find((function(t){var e;return(null!==(e=t.value)&&void 0!==e?e:t)==d}));if(this.trigger("dropdown:select",{data:h,elm:t,event:e}),h||c){if(this.state.editing){var g=this.normalizeTags([h])[0];h=s.transformTag.call(this,g)||g,this.onEditTagDone(null,ct({__isValid:!0},h))}else this[u?"addMixTags":"addTags"]([h||this.input.raw.call(this)],r);(u||this.DOM.input.parentNode)&&(setTimeout((function(){i.DOM.input.focus(),i.toggleFocusClass(!0)})),l&&setTimeout(this.dropdown.hide.bind(this)),a?n&&n():(t.addEventListener("transitionend",(function(){i.dropdown.fillHeaderFooter(),setTimeout((function(){t.remove(),i.dropdown.refilter(),n&&n()}),100)}),{once:!0}),t.classList.add(this.settings.classNames.dropdownItemHidden)))}else l&&setTimeout(this.dropdown.hide.bind(this))},selectAll:function(t){this.suggestedListItems.length=0,this.dropdown.hide(),this.dropdown.filterListItems("");var e=this.dropdown.filterListItems("");return t||(e=this.state.dropdown.suggestions),this.addTags(e,!0),this},filterListItems:function(t,e){var n,i,s,a,o,r,l=function(){var t,l,d=void 0,c=void 0;t=p[b],i=(null!=(l=Object)&&"undefined"!=typeof Symbol&&l[Symbol.hasInstance]?l[Symbol.hasInstance](t):t instanceof l)?p[b]:{value:p[b]};var f,m=Object.keys(i).some((function(t){return w.includes(t)}))?w:["value"];u.fuzzySearch&&!e.exact?(a=m.reduce((function(t,e){return t+" "+(i[e]||"")}),"").toLowerCase().trim(),u.accentedSearch&&(a=ht(a),r=ht(r)),d=0==a.indexOf(r),c=a===r,f=a,s=r.toLowerCase().split(" ").every((function(t){return f.includes(t.toLowerCase())}))):(d=!0,s=m.some((function(t){var n=""+(i[t]||"");return u.accentedSearch&&(n=ht(n),r=ht(r)),u.caseSensitive||(n=n.toLowerCase()),c=n===r,e.exact?n===r:0==n.indexOf(r)}))),o=!u.includeSelectedTags&&n.isTagDuplicate(dt(i)?i.value:i),s&&!o&&(c&&d?g.push(i):"startsWith"==u.sortby&&d?h.unshift(i):h.push(i))},d=this,c=this.settings,u=c.dropdown,h=(e=e||{},[]),g=[],p=c.whitelist,f=u.maxItems>=0?u.maxItems:1/0,m=u.includeSelectedTags,v="function"==typeof u.sortby,w=u.searchKeys,b=0;if(!(t="select"==c.mode&&this.value.length&&this.value[0][c.tagTextProp]==t?"":t)||!w.length){h=m?p:p.filter((function(t){return!d.isTagDuplicate(dt(t)?t.value:t)}));var y=v?u.sortby(h,r):h.slice(0,f);return this.state.dropdown.suggestions=y,y}for(r=u.caseSensitive?""+t:(""+t).toLowerCase();b[\r\n ]+\<").split(/>\s+<").trim():""},fillHeaderFooter:function(){var t=this.dropdown.filterListItems(this.state.dropdown.query),e=this.parseTemplate("dropdownHeader",[t]),n=this.parseTemplate("dropdownFooter",[t]),i=this.dropdown.getHeaderRef(),s=this.dropdown.getFooterRef();e&&(null==i||i.parentNode.replaceChild(e,i)),n&&(null==s||s.parentNode.replaceChild(n,s))},position:function(t){var e=this.settings.dropdown,n=this.dropdown.getAppendTarget();if("manual"!=e.position&&n){var i,s,a,o,r,l,d,c,u,h,g=this.DOM.dropdown,p=e.RTL,f=n===document.body,m=n===this.DOM.scope,v=f?window.pageYOffset:n.scrollTop,w=document.fullscreenElement||document.webkitFullscreenElement||document.documentElement,b=w.clientHeight,y=Math.max(w.clientWidth||0,window.innerWidth||0),T=y>480?e.position:"all",S=this.DOM["input"==T?"input":"scope"];if(t=t||g.clientHeight,this.state.dropdown.visible){if("text"==T?(a=(i=function(){var t=document.getSelection();if(t.rangeCount){var e,n,i=t.getRangeAt(0),s=i.startContainer,a=i.startOffset;if(a>0)return(n=document.createRange()).setStart(s,a-1),n.setEnd(s,a),{left:(e=n.getBoundingClientRect()).right,top:e.top,bottom:e.bottom};if(s.getBoundingClientRect)return s.getBoundingClientRect()}return{left:-9999,top:-9999}}()).bottom,s=i.top,o=i.left,r="auto"):(l=function(t){var e=0,n=0;for(t=t.parentNode;t&&t!=w;)e+=t.offsetTop||0,n+=t.offsetLeft||0,t=t.parentNode;return{top:e,left:n}}(n),i=S.getBoundingClientRect(),s=m?-1:i.top-l.top,a=(m?i.height:i.bottom-l.top)-1,o=m?-1:i.left-l.left,r=i.width+"px"),!f){var x=function(){for(var t=0,n=e.appendTarget.parentNode;n;)t+=n.scrollTop||0,n=n.parentNode;return t}();s+=x,a+=x}var E;s=Math.floor(s),a=Math.ceil(a),c=y-o<120,u=((d=null!==(E=e.placeAbove)&&void 0!==E?E:b-i.bottom\n ').concat(this.settings.templates.input.call(this),"\n ").concat(Z,"\n ")},input:function(){var t=this.settings,e=t.placeholder||Z;return"')},tag:function(t,e){var n=e.settings;return'\n \n
\n ').concat(t[n.tagTextProp]||t.value,"\n
\n
")},dropdown:function(t){var e=t.dropdown,n="manual"==e.position;return'
\n
\n
')},dropdownContent:function(t){var e=this.settings.templates,n=this.state.dropdown.suggestions;return"\n ".concat(e.dropdownHeader.call(this,n),"\n ").concat(t,"\n ").concat(e.dropdownFooter.call(this,n),"\n ")},dropdownItem:function(t){return"
').concat(t.mappedValue||t.value,"
")},dropdownHeader:function(t){return"
')},dropdownFooter:function(t){var e=t.length-this.settings.dropdown.maxItems;return e>0?"
\n ').concat(e," more items. Refine your search.\n
"):""},dropdownItemNoMatch:null};function Bt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],n=this.settings,i=this.events.callbacks,s=e?"addEventListener":"removeEventListener";if(!this.state.mainEvents||!e){for(var a in this.state.mainEvents=e,e&&!this.listeners.main&&(this.events.bindGlobal.call(this),this.settings.isJQueryPlugin&&jQuery(this.DOM.originalInput).on("tagify.removeAllTags",this.removeAllTags.bind(this))),t=this.listeners.main=this.listeners.main||{keydown:["input",i.onKeydown.bind(this)],click:["scope",i.onClickScope.bind(this)],dblclick:"select"!=n.mode&&["scope",i.onDoubleClickScope.bind(this)],paste:["input",i.onPaste.bind(this)],drop:["input",i.onDrop.bind(this)],compositionstart:["input",i.onCompositionStart.bind(this)],compositionend:["input",i.onCompositionEnd.bind(this)]})t[a]&&this.DOM[t[a][0]][s](a,t[a][1]);var o=this.listeners.main.inputMutationObserver||new MutationObserver(i.onInputDOMChange.bind(this));o.disconnect(),"mix"==n.mode&&o.observe(this.DOM.input,{childList:!0}),this.events.bindOriginaInputListener.call(this)}},bindOriginaInputListener:function(t){var e=(t||0)+500;this.listeners.main&&(clearInterval(this.listeners.main.originalInputValueObserverInterval),this.listeners.main.originalInputValueObserverInterval=setInterval(this.events.callbacks.observeOriginalInputValue.bind(this),e))},bindGlobal:function(t){var e,n=this.events.callbacks,i=t?"removeEventListener":"addEventListener";if(this.listeners&&(t||!this.listeners.global)){this.listeners.global=this.listeners.global||[{type:this.isIE?"keydown":"input",target:this.DOM.input,cb:n[this.isIE?"onInputIE":"onInput"].bind(this)},{type:"keydown",target:window,cb:n.onWindowKeyDown.bind(this)},{type:"focusin",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"focusout",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"click",target:document,cb:n.onClickAnywhere.bind(this),useCapture:!0}];var s=!0,a=!1,o=void 0;try{for(var r,l=this.listeners.global[Symbol.iterator]();!(s=(r=l.next()).done);s=!0)(e=r.value).target[i](e.type,e.cb,!!e.useCapture)}catch(t){a=!0,o=t}finally{try{s||null==l.return||l.return()}finally{if(a)throw o}}}},unbindGlobal:function(){this.events.bindGlobal.call(this,!0)},callbacks:{onFocusBlur:function(t){var e,n,i=this.settings,s=mt.call(this,t.relatedTarget),a=ft.call(this,t.relatedTarget),o=t.target.classList.contains(i.classNames.tagX),r="focusin"==t.type,l="focusout"==t.type;o&&"mix"!=i.mode&&this.DOM.input.focus(),s&&r&&!a&&!o&&this.toggleFocusClass(this.state.hasFocus=+new Date);var d=t.target?this.trim(this.DOM.input.textContent):"",c=null===(n=this.value)||void 0===n||null===(e=n[0])||void 0===e?void 0:e[i.tagTextProp],u=i.dropdown.enabled>=0,h={relatedTarget:t.relatedTarget},g=this.state.actions.selectOption&&(u||!i.dropdown.closeOnSelect),p=this.state.actions.addNew&&u;if(l){if(t.relatedTarget===this.DOM.scope)return this.dropdown.hide(),void this.DOM.input.focus();this.postUpdate(),i.onChangeAfterBlur&&this.triggerChangeEvent()}if(!(g||p||o))if(this.state.hasFocus=!(!r&&!s)&&+new Date,this.toggleFocusClass(this.state.hasFocus),"mix"!=i.mode){if(r){if(!i.focusable)return;var f=0===i.dropdown.enabled&&!this.state.dropdown.visible,m=!a||"select"===i.mode,v=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector);return this.trigger("focus",h),void(f&&m&&(this.dropdown.show(this.value.length?"":void 0),this.setRangeAtStartEnd(!1,v)))}if(l){if(this.trigger("blur",h),this.loading(!1),"select"==i.mode){if(this.value.length){var w=this.getTagElms()[0];d=this.trim(w.textContent)}c===d&&(d="")}d&&!this.state.actions.selectOption&&i.addTagOnBlur&&i.addTagOn.includes("blur")&&this.addTags(d,!0)}s||(this.DOM.input.removeAttribute("style"),this.dropdown.hide())}else r?this.trigger("focus",h):l&&(this.trigger("blur",h),this.loading(!1),this.dropdown.hide(),this.state.dropdown.visible=void 0,this.setStateSelection())},onCompositionStart:function(t){this.state.composing=!0},onCompositionEnd:function(t){this.state.composing=!1},onWindowKeyDown:function(t){var e,n=this.settings,i=document.activeElement,s=mt.call(this,i)&&this.DOM.scope.contains(i),a=i===this.DOM.input,o=s&&i.hasAttribute("readonly"),r=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector),l=this.state.dropdown.visible;if(("Tab"===t.key&&l||this.state.hasFocus||s&&!o)&&!a){e=i.nextElementSibling;var d=t.target.classList.contains(n.classNames.tagX);switch(t.key){case"Backspace":n.readonly||this.state.editing||(this.removeTags(i),(e||this.DOM.input).focus());break;case"Enter":if(d)return void this.removeTags(t.target.parentNode);n.a11y.focusableTags&&ft.call(this,i)&&setTimeout(this.editTag.bind(this),0,i);break;case"ArrowDown":this.state.dropdown.visible||"mix"==n.mode||this.dropdown.show();break;case"Tab":null==r||r.focus()}}},onKeydown:function(t){var e=this,n=this.settings;if(!this.state.composing&&n.userInput){"select"==n.mode&&n.enforceWhitelist&&this.value.length&&"Tab"!=t.key&&t.preventDefault();var i=this.trim(t.target.textContent);this.trigger("keydown",{event:t}),n.hooks.beforeKeyDown(t,{tagify:this}).then((function(s){if("mix"==n.mode){switch(t.key){case"Left":case"ArrowLeft":e.state.actions.ArrowLeft=!0;break;case"Delete":case"Backspace":if(e.state.editing)return;var a=document.getSelection(),o="Delete"==t.key&&a.anchorOffset==(a.anchorNode.length||0),r=a.anchorNode.previousSibling,l=1==a.anchorNode.nodeType||!a.anchorOffset&&r&&1==r.nodeType&&a.anchorNode.previousSibling;!function(t){var e=document.createElement("div");t.replace(/\&#?[0-9a-z]+;/gi,(function(t){return e.innerHTML=t,e.innerText}))}(e.DOM.input.innerHTML);var d,c,u,h=e.getTagElms(),g=1===a.anchorNode.length&&a.anchorNode.nodeValue==String.fromCharCode(8203);if("edit"==n.backspace&&l)return d=1==a.anchorNode.nodeType?null:a.anchorNode.previousElementSibling,setTimeout(e.editTag.bind(e),0,d),void t.preventDefault();if(gt()&&Ht(l,Element))return u=rt(l),l.hasAttribute("readonly")||l.remove(),e.DOM.input.focus(),void setTimeout((function(){yt(u),e.DOM.input.click()}));if("BR"==a.anchorNode.nodeName)return;if((o||l)&&1==a.anchorNode.nodeType?c=0==a.anchorOffset?o?h[0]:null:h[Math.min(h.length,a.anchorOffset)-1]:o?c=a.anchorNode.nextElementSibling:Ht(l,Element)&&(c=l),3==a.anchorNode.nodeType&&!a.anchorNode.nodeValue&&a.anchorNode.previousElementSibling&&t.preventDefault(),(l||o)&&!n.backspace)return void t.preventDefault();if("Range"!=a.type&&!a.anchorOffset&&a.anchorNode==e.DOM.input&&"Delete"!=t.key)return void t.preventDefault();if("Range"!=a.type&&c&&c.hasAttribute("readonly"))return void yt(rt(c));"Delete"==t.key&&g&&bt(a.anchorNode.nextSibling)&&e.removeTags(a.anchorNode.nextSibling)}return!0}var p="manual"==n.dropdown.position;switch(t.key){case"Backspace":"select"==n.mode&&n.enforceWhitelist&&e.value.length?e.removeTags():e.state.dropdown.visible&&"manual"!=n.dropdown.position||""!=t.target.textContent&&8203!=i.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0));break;case"Esc":case"Escape":if(e.state.dropdown.visible)return;t.target.blur();break;case"Down":case"ArrowDown":e.state.dropdown.visible||e.dropdown.show();break;case"ArrowRight":var f=e.state.inputSuggestion||e.state.ddItemData;if(f&&n.autoComplete.rightKey)return void e.addTags([f],!0);break;case"Tab":return!0;case"Enter":if(e.state.dropdown.visible&&!p)return;t.preventDefault();var m=e.state.autoCompleteData||i;setTimeout((function(){e.state.dropdown.visible&&!p||e.state.actions.selectOption||!n.addTagOn.includes(t.key.toLowerCase())||(e.addTags([m],!0),e.state.autoCompleteData=null)}))}})).catch((function(t){return t}))}},onInput:function(t){this.postUpdate();var e=this.settings;if("mix"==e.mode)return this.events.callbacks.onMixTagsInput.call(this,t);var n=this.input.normalize.call(this,void 0,{trim:!1}),i=n.length>=e.dropdown.enabled,s={value:n,inputElm:this.DOM.input},a=this.validateTag({value:n});"select"==e.mode&&this.toggleScopeValidation(a),s.isValid=a,this.state.inputText!=n&&(this.input.set.call(this,n,!1),-1!=n.search(e.delimiters)?this.addTags(n)&&this.input.set.call(this):e.dropdown.enabled>=0&&this.dropdown[i?"show":"hide"](n),this.trigger("input",s))},onMixTagsInput:function(t){var e,n,i,s,a,o,r,l,d=this,c=this.settings,u=this.value.length,h=this.getTagElms(),g=document.createDocumentFragment(),p=window.getSelection().getRangeAt(0),f=[].map.call(h,(function(t){return bt(t).value}));if("deleteContentBackward"==t.inputType&>()&&this.events.callbacks.onKeydown.call(this,{target:t.target,key:"Backspace"}),Tt(this.getTagElms()),this.value.slice().forEach((function(t){t.readonly&&!f.includes(t.value)&&g.appendChild(d.createTagElem(t))})),g.childNodes.length&&(p.insertNode(g),this.setRangeAtStartEnd(!1,g.lastChild)),h.length!=u)return this.value=[].map.call(this.getTagElms(),(function(t){return bt(t)})),void this.update({withoutChangeEvent:!0});if(this.hasMaxTags())return!0;if(window.getSelection&&(o=window.getSelection()).rangeCount>0&&3==o.anchorNode.nodeType){if((p=o.getRangeAt(0).cloneRange()).collapse(!0),p.setStart(o.focusNode,0),i=(e=p.toString().slice(0,p.endOffset)).split(c.pattern).length-1,(n=e.match(c.pattern))&&(s=e.slice(e.lastIndexOf(n[n.length-1]))),s){if(this.state.actions.ArrowLeft=!1,this.state.tag={prefix:s.match(c.pattern)[0],value:s.replace(c.pattern,"")},this.state.tag.baseOffset=o.baseOffset-this.state.tag.value.length,l=this.state.tag.value.match(c.delimiters))return this.state.tag.value=this.state.tag.value.replace(c.delimiters,""),this.state.tag.delimiters=l[0],this.addTags(this.state.tag.value,c.dropdown.clearOnSelect),void this.dropdown.hide();a=this.state.tag.value.length>=c.dropdown.enabled;try{r=(r=this.state.flaggedTags[this.state.tag.baseOffset]).prefix==this.state.tag.prefix&&r.value[0]==this.state.tag.value[0],this.state.flaggedTags[this.state.tag.baseOffset]&&!this.state.tag.value&&delete this.state.flaggedTags[this.state.tag.baseOffset]}catch(t){}(r||i500||!e.focusable)?this.state.dropdown.visible?this.dropdown.hide():0===e.dropdown.enabled&&"mix"!=e.mode&&this.dropdown.show(this.value.length?"":void 0):"select"!=e.mode||0!==e.dropdown.enabled||this.state.dropdown.visible||(this.events.callbacks.onDoubleClickScope.call(this,function(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);n.push.apply(n,i)}return n}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}(function(t){for(var e=1;e=this.settings.dropdown.enabled&&(this.state.editing&&(this.state.editing.value=o),this.dropdown.show(o)),this.trigger("edit:input",{tag:i,index:s,data:ct({},this.value[s],{newValue:o}),event:e})},onEditTagPaste:function(t,e){var n=(e.clipboardData||window.clipboardData).getData("Text");e.preventDefault();var i=wt(n);this.setRangeAtStartEnd(!1,i)},onEditTagClick:function(t,e){this.events.callbacks.onClickScope.call(this,e)},onEditTagFocus:function(t){this.state.editing={scope:t,input:t.querySelector("[contenteditable]")}},onEditTagBlur:function(t,e){var n=ft.call(this,e.relatedTarget);if("select"==this.settings.mode&&n&&e.relatedTarget.contains(e.target))this.dropdown.hide();else if(this.state.editing&&(this.state.hasFocus||this.toggleFocusClass(),this.DOM.scope.contains(document.activeElement)||this.trigger("blur",{}),this.DOM.scope.contains(t))){var i,s,a,o=this.settings,r=t.closest("."+o.classNames.tag),l=bt(r),d=this.input.normalize.call(this,t),c=(Vt(i={},o.tagTextProp,d),Vt(i,"__tagId",l.__tagId),i),u=l.__originalData,h=this.editTagChangeDetected(ct(l,c)),g=this.validateTag(c);if(d)if(h){var p;if(s=this.hasMaxTags(),a=ct({},u,(Vt(p={},o.tagTextProp,this.trim(d)),Vt(p,"__isValid",g),p)),o.transformTag.call(this,a,u),!0!==(g=(!s||!0===u.__isValid)&&this.validateTag(a))){if(this.trigger("invalid",{data:a,tag:r,message:g}),o.editTags.keepInvalid)return;o.keepInvalidTags?a.__isValid=g:a=u}else o.keepInvalidTags&&(delete a.title,delete a["aria-invalid"],delete a.class);this.onEditTagDone(r,a)}else this.onEditTagDone(r,u);else this.onEditTagDone(r)}},onEditTagkeydown:function(t,e){if(!this.state.composing)switch(this.trigger("edit:keydown",{event:t}),t.key){case"Esc":case"Escape":this.state.editing=!1,e.__tagifyTagData.__originalData.value?e.parentNode.replaceChild(e.__tagifyTagData.__originalHTML,e):e.remove();break;case"Enter":case"Tab":t.preventDefault(),setTimeout((function(){return t.target.blur()}),0)}},onDoubleClickScope:function(t){var e=t.target.closest("."+this.settings.classNames.tag);if(e){var n,i,s=bt(e),a=this.settings;!1!==(null==s?void 0:s.editable)&&(n=e.classList.contains(this.settings.classNames.tagEditing),i=e.hasAttribute("readonly"),a.readonly||n||i||!this.settings.editTags||!a.userInput||(this.events.callbacks.onEditTagFocus.call(this,e),this.editTag(e)),this.toggleFocusClass(!0),"select"!=a.mode&&this.trigger("dblclick",{tag:e,index:this.getNodeIndex(e),data:bt(e)}))}},onInputDOMChange:function(t){var e=this;t.forEach((function(t){t.addedNodes.forEach((function(t){if("

"==t.outerHTML)t.replaceWith(document.createElement("br"));else if(1==t.nodeType&&t.querySelector(e.settings.classNames.tagSelector)){var n,i=document.createTextNode("");3==t.childNodes[0].nodeType&&"BR"!=t.previousSibling.nodeName&&(i=document.createTextNode("\n")),(n=t).replaceWith.apply(n,Rt([i].concat(Rt(Rt(t.childNodes).slice(0,-1))))),yt(i)}else if(ft.call(e,t)){var s;if(3!=(null===(s=t.previousSibling)||void 0===s?void 0:s.nodeType)||t.previousSibling.textContent||t.previousSibling.remove(),t.previousSibling&&"BR"==t.previousSibling.nodeName){t.previousSibling.replaceWith("\n​");for(var a=t.nextSibling,o="";a;)o+=a.textContent,a=a.nextSibling;o.trim()&&yt(t.previousSibling)}else t.previousSibling&&!bt(t.previousSibling)||t.before("​")}})),t.removedNodes.forEach((function(t){t&&"BR"==t.nodeName&&ft.call(e,n)&&(e.removeTags(n),e.fixFirefoxLastTagNoCaret())}))}));var n=this.DOM.input.lastChild;n&&""==n.nodeValue&&n.remove(),n&&"BR"==n.nodeName||this.DOM.input.appendChild(document.createElement("br"))}}};function Ft(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n");else{try{Ut(JSON.parse(t),Array)&&(t=JSON.parse(t))}catch(t){}this.addTags(t,!0).forEach((function(t){return t&&t.classList.add(n.classNames.tagNoAnimation)}))}else this.postUpdate();this.state.lastOriginalValueReported=n.mixMode.integrated?"":this.DOM.originalInput.value},cloneEvent:function(t){var e={};for(var n in t)"path"!=n&&(e[n]=t[n]);return e},loading:function(t){return this.state.isLoading=t,this.DOM.scope.classList[t?"add":"remove"](this.settings.classNames.scopeLoading),this},tagLoading:function(t,e){return t&&t.classList[e?"add":"remove"](this.settings.classNames.tagLoading),this},toggleClass:function(t,e){"string"==typeof t&&this.DOM.scope.classList.toggle(t,e)},toggleScopeValidation:function(t){var e=!0===t||void 0===t;!this.settings.required&&t&&t===this.TEXTS.empty&&(e=!0),this.toggleClass(this.settings.classNames.tagInvalid,!e),this.DOM.scope.title=e?"":t},toggleFocusClass:function(t){this.toggleClass(this.settings.classNames.focus,!!t)},setPlaceholder:function(t){var e=this;["data","aria"].forEach((function(n){return e.DOM.input.setAttribute("".concat(n,"-placeholder"),t)}))},triggerChangeEvent:function(){if(!this.settings.mixMode.integrated){var t=this.DOM.originalInput,e=this.state.lastOriginalValueReported!==t.value,n=new CustomEvent("change",{bubbles:!0});e&&(this.state.lastOriginalValueReported=t.value,n.simulated=!0,t._valueTracker&&t._valueTracker.setValue(Math.random()),t.dispatchEvent(n),this.trigger("change",this.state.lastOriginalValueReported),t.value=this.state.lastOriginalValueReported)}},events:qt,fixFirefoxLastTagNoCaret:function(){},setRangeAtStartEnd:function(t,e){if(e){t="number"==typeof t?t:!!t,e=e.lastChild||e;var n=document.getSelection();if(Ut(n.focusNode,Element)&&!this.DOM.input.contains(n.focusNode))return!0;try{n.rangeCount>=1&&["Start","End"].forEach((function(i){return n.getRangeAt(0)["set"+i](e,t||e.length)}))}catch(t){console.warn(t)}}},insertAfterTag:function(t,e){if(e=e||this.settings.mixMode.insertAfterTag,t&&t.parentNode&&e)return e="string"==typeof e?document.createTextNode(e):e,t.parentNode.insertBefore(e,t.nextSibling),e},editTagChangeDetected:function(t){var e=t.__originalData;for(var n in e)if(!this.dataProps.includes(n)&&t[n]!=e[n])return!0;return!1},getTagTextNode:function(t){return t.querySelector(this.settings.classNames.tagTextSelector)},setTagTextNode:function(t,e){this.getTagTextNode(t).innerHTML=lt(e)},editTag:function(t,e){var n=this;t=t||this.getLastTag(),e=e||{};var i=this.settings,s=this.getTagTextNode(t),a=this.getNodeIndex(t),o=bt(t),r=this.events.callbacks,l=!0,d="select"==i.mode;if(!d&&this.dropdown.hide(),s){if(!Ut(o,Object)||!("editable"in o)||o.editable)return o=bt(t,{__originalData:ct({},o),__originalHTML:t.cloneNode(!0)}),bt(o.__originalHTML,o.__originalData),s.setAttribute("contenteditable",!0),t.classList.add(i.classNames.tagEditing),this.events.callbacks.onEditTagFocus.call(this,t),s.addEventListener("click",r.onEditTagClick.bind(this,t)),s.addEventListener("blur",r.onEditTagBlur.bind(this,this.getTagTextNode(t))),s.addEventListener("input",r.onEditTagInput.bind(this,s)),s.addEventListener("paste",r.onEditTagPaste.bind(this,s)),s.addEventListener("keydown",(function(e){return r.onEditTagkeydown.call(n,e,t)})),s.addEventListener("compositionstart",r.onCompositionStart.bind(this)),s.addEventListener("compositionend",r.onCompositionEnd.bind(this)),e.skipValidation||(l=this.editTagToggleValidity(t)),s.originalIsValid=l,this.trigger("edit:start",{tag:t,index:a,data:o,isValid:l}),s.focus(),!d&&this.setRangeAtStartEnd(!1,s),0===i.dropdown.enabled&&!d&&this.dropdown.show(),this.state.hasFocus=!0,this}else nt.warn("Cannot find element in Tag template: .",i.classNames.tagTextSelector)},editTagToggleValidity:function(t,e){var n;if(e=e||bt(t))return(n=!("__isValid"in e)||!0===e.__isValid)||this.removeTagsFromValue(t),this.update(),t.classList.toggle(this.settings.classNames.tagNotAllowed,!n),e.__isValid=n,e.__isValid;nt.warn("tag has no data: ",t,e)},onEditTagDone:function(t,e){t=t||this.state.editing.scope,e=e||{};var n,i,s=this.settings,a={tag:t,index:this.getNodeIndex(t),previousData:bt(t),data:e};this.trigger("edit:beforeUpdate",a,{cloneData:!1}),this.state.editing=!1,delete e.__originalData,delete e.__originalHTML,t&&t.parentNode&&((void 0!==(i=e[s.tagTextProp])?null===(n=(i+="").trim)||void 0===n?void 0:n.call(i):s.tagTextProp in e?void 0:e.value)?(t=this.replaceTag(t,e),this.editTagToggleValidity(t,e),s.a11y.focusableTags?t.focus():"select"!=s.mode&&yt(t)):this.removeTags(t)),this.trigger("edit:updated",a),s.dropdown.closeOnSelect&&this.dropdown.hide(),this.settings.keepInvalidTags&&this.reCheckInvalidTags()},replaceTag:function(t,e){e&&""!==e.value&&void 0!==e.value||(e=t.__tagifyTagData),e.__isValid&&1!=e.__isValid&&ct(e,this.getInvalidTagAttrs(e,e.__isValid));var n=this.createTagElem(e);return t.parentNode.replaceChild(n,t),this.updateValueByDOMTags(),n},updateValueByDOMTags:function(){var t=this;this.value.length=0;var e=this.settings.classNames,n=[e.tagNotAllowed.split(" ")[0],e.tagHide];[].forEach.call(this.getTagElms(),(function(e){Kt(e.classList).some((function(t){return n.includes(t)}))||t.value.push(bt(e))})),this.update(),this.dropdown.refilter()},injectAtCaret:function(t,e){var n;if(e=e||(null===(n=this.state.selection)||void 0===n?void 0:n.range),"string"==typeof t&&(t=document.createTextNode(t)),!e&&t)return this.appendMixTags(t),this;var i=wt(t,e);return this.setRangeAtStartEnd(!1,i),this.updateValueByDOMTags(),this.update(),this},input:{set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.settings,i=n.dropdown.closeOnSelect;this.state.inputText=t,e&&(this.DOM.input.innerHTML=lt(""+t),t&&this.toggleClass(n.classNames.empty,!this.DOM.input.innerHTML)),!t&&i&&this.dropdown.hide.bind(this),this.input.autocomplete.suggest.call(this),this.input.validate.call(this)},raw:function(){return this.DOM.input.textContent},validate:function(){var t=!this.state.inputText||!0===this.validateTag({value:this.state.inputText});return this.DOM.input.classList.toggle(this.settings.classNames.inputInvalid,!t),t},normalize:function(t,e){var n=t||this.DOM.input,i=[];n.childNodes.forEach((function(t){return 3==t.nodeType&&i.push(t.nodeValue)})),i=i.join("\n");try{i=i.replace(/(?:\r\n|\r|\n)/g,this.settings.delimiters.source.charAt(0))}catch(t){}return i=i.replace(/\s/g," "),(null==e?void 0:e.trim)?this.trim(i):i},autocomplete:{suggest:function(t){if(this.settings.autoComplete.enabled){"object"!=typeof(t=t||{value:""})&&(t={value:t});var e=this.dropdown.getMappedValue(t);if("number"!=typeof e){var n=this.state.inputText.toLowerCase(),i=e.substr(0,this.state.inputText.length).toLowerCase(),s=e.substring(this.state.inputText.length);e&&this.state.inputText&&i==n?(this.DOM.input.setAttribute("data-suggest",s),this.state.inputSuggestion=t):(this.DOM.input.removeAttribute("data-suggest"),delete this.state.inputSuggestion)}}},set:function(t){var e=this.DOM.input.getAttribute("data-suggest"),n=t||(e?this.state.inputText+e:null);return!!n&&("mix"==this.settings.mode?this.replaceTextWithNode(document.createTextNode(this.state.tag.prefix+n)):(this.input.set.call(this,n),this.setRangeAtStartEnd(!1,this.DOM.input)),this.input.autocomplete.suggest.call(this),this.dropdown.hide(),!0)}}},getTagIdx:function(t){return this.value.findIndex((function(e){return e.__tagId==(t||{}).__tagId}))},getNodeIndex:function(t){var e=0;if(t)for(;t=t.previousElementSibling;)e++;return e},getTagElms:function(){for(var t=arguments.length,e=new Array(t),n=0;n=this.settings.maxTags&&this.TEXTS.exceed},setReadonly:function(t,e){var n=this.settings;this.DOM.scope.contains(document.activeElement)&&document.activeElement.blur(),n[e||"readonly"]=t,this.DOM.scope[(t?"set":"remove")+"Attribute"](e||"readonly",!0),this.settings.userInput=!0,this.setContentEditable(!t)},setContentEditable:function(t){this.DOM.input.contentEditable=t,this.DOM.input.tabIndex=t?0:-1},setDisabled:function(t){this.setReadonly(t,"disabled")},normalizeTags:function(t){var e=this,n=this.settings,i=n.whitelist,s=n.delimiters,a=n.mode,o=n.tagTextProp,r=[],l=!!i&&Ut(i[0],Object),d=Array.isArray(t),c=d&&t[0].value,u=function(t){return(t+"").split(s).reduce((function(t,n){var i,s=e.trim(n);return s&&t.push(($t(i={},o,s),$t(i,"value",s),i)),t}),[])};if("number"==typeof t&&(t=t.toString()),"string"==typeof t){if(!t.trim())return[];t=u(t)}else d&&(t=t.reduce((function(t,n){if(dt(n)){var i=ct({},n);o in i||(o="value"),i[o]=e.trim(i[o]),(i[o]||0===i[o])&&t.push(i)}else if(null!=n&&""!==n&&void 0!==n){var s;(s=t).push.apply(s,Kt(u(n)))}return t}),[]));return l&&!c&&(t.forEach((function(t){var n=r.map((function(t){return t.value})),i=e.dropdown.filterListItems.call(e,t[o],{exact:!0});e.settings.duplicates||(i=i.filter((function(t){return!n.includes(t.value)})));var s=i.length>1?e.getWhitelistItem(t[o],o,i):i[0];s&&Ut(s,Object)?r.push(s):"mix"!=a&&(null==t.value&&(t.value=t[o]),r.push(t))})),r.length&&(t=r)),t},parseMixTags:function(t){var e=this,n=this.settings,i=n.mixTagsInterpolator,s=n.duplicates,a=n.transformTag,o=n.enforceWhitelist,r=n.maxTags,l=n.tagTextProp,d=[];t=t.split(i[0]).map((function(t,n){var c,u,h,g=t.split(i[1]),p=g[0],f=d.length==r;try{if(p==+p)throw Error;u=JSON.parse(p)}catch(t){u=e.normalizeTags(p)[0]||{value:p}}if(a.call(e,u),f||!(g.length>1)||o&&!e.isTagWhitelisted(u.value)||!s&&e.isTagDuplicate(u.value)){if(t)return n?i[0]+t:t}else u[c=u[l]?l:"value"]=e.trim(u[c]),h=e.createTagElem(u),d.push(u),h.classList.add(e.settings.classNames.tagNoAnimation),g[0]=h.outerHTML,e.value.push(u);return g.join("")})).join(""),this.DOM.input.innerHTML=t,this.DOM.input.appendChild(document.createTextNode("")),this.DOM.input.normalize();var c=this.getTagElms();return c.forEach((function(t,e){return bt(t,d[e])})),this.update({withoutChangeEvent:!0}),Tt(c,this.state.hasFocus),t},replaceTextWithNode:function(t,e){if(this.state.tag||e){e=e||this.state.tag.prefix+this.state.tag.value;var n,i,s=this.state.selection||window.getSelection(),a=s.anchorNode,o=this.state.tag.delimiters?this.state.tag.delimiters.length:0;return a.splitText(s.anchorOffset-o),-1==(n=a.nodeValue.lastIndexOf(e))||(i=a.splitText(n),t&&a.parentNode.replaceChild(t,i)),!0}},prepareNewTagNode:function(t,e){e=e||{};var n=this.settings,i=[],s={},a=Object.assign({},t,{value:t.value+""});if(t=Object.assign({},a),n.transformTag.call(this,t),t.__isValid=this.hasMaxTags()||this.validateTag(t),!0!==t.__isValid){if(e.skipInvalid)return;if(ct(s,this.getInvalidTagAttrs(t,t.__isValid),{__preInvalidData:a}),t.__isValid==this.TEXTS.duplicate&&this.flashTag(this.getTagElmByValue(t.value)),!n.createInvalidTags)return void i.push(t.value)}return"readonly"in t&&(t.readonly?s["aria-readonly"]=!0:delete t.readonly),{tagElm:this.createTagElem(t,s),tagData:t,aggregatedInvalidInput:i}},postProcessNewTagNode:function(t,e){var n=this,i=this.settings,s=e.__isValid;s&&!0===s?this.value.push(e):(this.trigger("invalid",{data:e,index:this.value.length,tag:t,message:s}),i.keepInvalidTags||setTimeout((function(){return n.removeTags(t,!0)}),1e3)),this.dropdown.position()},selectTag:function(t,e){var n=this;if(!this.settings.enforceWhitelist||this.isTagWhitelisted(e.value)){this.state.actions.selectOption&&setTimeout((function(){return n.setRangeAtStartEnd(!1,n.DOM.input)}));var i=this.getLastTag();return i?this.replaceTag(i,e):this.appendTag(t),this.value[0]=e,this.update(),this.trigger("add",{tag:t,data:e}),[t]}},addEmptyTag:function(t){var e=ct({value:""},t||{}),n=this.createTagElem(e);bt(n,e),this.appendTag(n),this.editTag(n,{skipValidation:!0}),this.toggleFocusClass(!0)},addTags:function(t,e,n){var i=this,s=[],a=this.settings,o=[],r=document.createDocumentFragment(),l=[];if(!t||0==t.length)return s;switch(t=this.normalizeTags(t),a.mode){case"mix":return this.addMixTags(t);case"select":e=!1,this.removeAllTags()}return this.DOM.input.removeAttribute("style"),t.forEach((function(t){var e=i.prepareNewTagNode(t,{skipInvalid:n||a.skipInvalid});if(e){var d=e.tagElm;if(t=e.tagData,o=e.aggregatedInvalidInput,s.push(d),"select"==a.mode)return i.selectTag(d,t);r.appendChild(d),i.postProcessNewTagNode(d,t),l.push({tagElm:d,tagData:t})}})),this.appendTag(r),l.forEach((function(t){var e=t.tagElm,n=t.tagData;return i.trigger("add",{tag:e,index:i.getTagIdx(n),data:n})})),this.update(),t.length&&e&&(this.input.set.call(this,a.createInvalidTags?"":o.join(a._delimiters)),this.setRangeAtStartEnd(!1,this.DOM.input)),this.dropdown.refilter(),s},addMixTags:function(t){var e=this;if((t=this.normalizeTags(t))[0].prefix||this.state.tag)return this.prefixedTextToTag(t[0]);var n=document.createDocumentFragment();return t.forEach((function(t){var i=e.prepareNewTagNode(t);n.appendChild(i.tagElm),e.insertAfterTag(i.tagElm),e.postProcessNewTagNode(i.tagElm,i.tagData)})),this.appendMixTags(n),n.children},appendMixTags:function(t){var e=!!this.state.selection;e?this.injectAtCaret(t):(this.DOM.input.focus(),(e=this.setStateSelection()).range.setStart(this.DOM.input,e.range.endOffset),e.range.setEnd(this.DOM.input,e.range.endOffset),this.DOM.input.appendChild(t),this.updateValueByDOMTags(),this.update())},prefixedTextToTag:function(t){var e,n,i,s=this,a=this.settings,o=null===(e=this.state.tag)||void 0===e?void 0:e.delimiters;if(t.prefix=t.prefix||this.state.tag?this.state.tag.prefix:(a.pattern.source||a.pattern)[0],i=this.prepareNewTagNode(t),n=i.tagElm,this.replaceTextWithNode(n)||this.DOM.input.appendChild(n),setTimeout((function(){return n.classList.add(s.settings.classNames.tagNoAnimation)}),300),this.update(),!o){var r=this.insertAfterTag(n)||n;setTimeout(yt,0,r)}return this.state.tag=null,this.postProcessNewTagNode(n,i.tagData),n},appendTag:function(t){var e=this.DOM,n=e.input;e.scope.insertBefore(t,n)},createTagElem:function(t,e){t.__tagId=pt();var n,i=ct({},t,Wt({value:lt(t.value+"")},e));return function(t){for(var e,n=document.createNodeIterator(t,NodeFilter.SHOW_TEXT,null,!1);e=n.nextNode();)e.textContent.trim()||e.parentNode.removeChild(e)}(n=this.parseTemplate("tag",[i,this])),bt(n,t),n},reCheckInvalidTags:function(){var t=this,e=this.settings;this.getTagElms(e.classNames.tagNotAllowed).forEach((function(n,i){var s=bt(n),a=t.hasMaxTags(),o=t.validateTag(s),r=!0===o&&!a;if("select"==e.mode&&t.toggleScopeValidation(o),r)return s=s.__preInvalidData?s.__preInvalidData:{value:s.value},t.replaceTag(n,s);n.title=a||o}))},removeTags:function(t,e,n){var i,s=this,a=this.settings;if(t=t&&Ut(t,HTMLElement)?[t]:Ut(t,Array)?t:t?[t]:[this.getLastTag()].filter((function(t){return t})),i=t.reduce((function(t,e){e&&"string"==typeof e&&(e=s.getTagElmByValue(e));var n=bt(e);return e&&n&&!n.readonly&&t.push({node:e,idx:s.getTagIdx(n),data:bt(e,{__removed:!0})}),t}),[]),n="number"==typeof n?n:this.CSSVars.tagHideTransition,"select"==a.mode&&(n=0,this.input.set.call(this)),1==i.length&&"select"!=a.mode&&i[0].node.classList.contains(a.classNames.tagNotAllowed)&&(e=!0),i.length)return a.hooks.beforeRemoveTag(i,{tagify:this}).then((function(){var t=function(t){t.node.parentNode&&(t.node.parentNode.removeChild(t.node),e?a.keepInvalidTags&&this.trigger("remove",{tag:t.node,index:t.idx}):(this.trigger("remove",{tag:t.node,index:t.idx,data:t.data}),this.dropdown.refilter(),this.dropdown.position(),this.DOM.input.normalize(),a.keepInvalidTags&&this.reCheckInvalidTags()))};n&&n>10&&1==i.length?function(e){e.node.style.width=parseFloat(window.getComputedStyle(e.node).width)+"px",document.body.clientTop,e.node.classList.add(a.classNames.tagHide),setTimeout(t.bind(this),n,e)}.call(s,i[0]):i.forEach(t.bind(s)),e||(s.removeTagsFromValue(i.map((function(t){return t.node}))),s.update(),"select"==a.mode&&a.userInput&&s.setContentEditable(!0))})).catch((function(t){}))},removeTagsFromDOM:function(){this.getTagElms().forEach((function(t){return t.remove()}))},removeTagsFromValue:function(t){var e=this;(t=Array.isArray(t)?t:[t]).forEach((function(t){var n=bt(t),i=e.getTagIdx(n);i>-1&&e.value.splice(i,1)}))},removeAllTags:function(t){var e=this;t=t||{},this.value=[],"mix"==this.settings.mode?this.DOM.input.innerHTML="":this.removeTagsFromDOM(),this.dropdown.refilter(),this.dropdown.position(),this.state.dropdown.visible&&setTimeout((function(){e.DOM.input.focus()})),"select"==this.settings.mode&&(this.input.set.call(this),this.settings.userInput&&this.setContentEditable(!0)),this.update(t)},postUpdate:function(){this.state.blockChangeEvent=!1;var t,e,n=this.settings,i=n.classNames,s="mix"==n.mode?n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value.trim():this.value.length+this.input.raw.call(this).length;this.toggleClass(i.hasMaxTags,this.value.length>=n.maxTags),this.toggleClass(i.hasNoTags,!this.value.length),this.toggleClass(i.empty,!s),"select"==n.mode&&this.toggleScopeValidation(null===(e=this.value)||void 0===e||null===(t=e[0])||void 0===t?void 0:t.__isValid)},setOriginalInputValue:function(t){var e=this.DOM.originalInput;this.settings.mixMode.integrated||(e.value=t,e.tagifyValue=e.value,this.setPersistedData(t,"value"))},update:function(t){clearTimeout(this.debouncedUpdateTimeout),this.debouncedUpdateTimeout=setTimeout(function(){var e=this.getInputValue();this.setOriginalInputValue(e),this.settings.onChangeAfterBlur&&(t||{}).withoutChangeEvent||this.state.blockChangeEvent||this.triggerChangeEvent(),this.postUpdate()}.bind(this),100),this.events.bindOriginaInputListener.call(this,100)},getInputValue:function(){var t=this.getCleanValue();return"mix"==this.settings.mode?this.getMixedTagsAsString(t):t.length?this.settings.originalInputValueFormat?this.settings.originalInputValueFormat(t):JSON.stringify(t):""},getCleanValue:function(t){return st(t||this.value,this.dataProps)},getMixedTagsAsString:function(){var t="",e=this,n=this.settings,i=n.originalInputValueFormat||JSON.stringify,s=n.mixTagsInterpolator;return function n(a){a.childNodes.forEach((function(a){if(1==a.nodeType){var o=bt(a);if("BR"==a.tagName&&(t+="\r\n"),o&&ft.call(e,a)){if(o.__removed)return;t+=s[0]+i(at(o,e.dataProps))+s[1]}else a.getAttribute("style")||["B","I","U"].includes(a.tagName)?t+=a.textContent:"DIV"!=a.tagName&&"P"!=a.tagName||(t+="\r\n",n(a))}else t+=a.textContent}))}(this.DOM.input),t}},zt.prototype.removeTag=zt.prototype.removeTags;const Xt=[];let Jt,Qt;function Gt(t,e,n,i,s,a){Xt[e.id]=new t(e,function(t,e){return{id:t,whitelist:e.options,enforceWhitelist:!e.userInput,duplicates:e.allowDuplicates,maxTags:e.maxItems,delimiters:null,originalInputValueFormat:t=>t.map((t=>t.value)),dropdown:{enabled:e.dropdownSuggestionsStartAfter,maxItems:e.dropdownMaxItems,closeOnSelect:e.dropdownCloseOnSelect,highlightFirst:e.highlight},transformTag(t){t.display||(t.display=t.value,t.value=encodeURIComponent(t.value)),t.display=t.display.replace(//g,">")},templates:{wrapper(t,e){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:t=>`
\n \n
\n ${t.display}\n
\n
`,dropdownItem:t=>`
\n ${t.display}\n
`}}}(e.id,n)),Xt[e.id].addTags(i),void 0!==s&&Xt[e.id].on("input",(t=>{!function(t,e,n,i,s,a){void 0!==Jt&&Jt.abort(),Jt=new AbortController,t.whitelist=null,"number"==typeof Qt&&(t.DOM.scope.ownerDocument.defaultView.clearTimeout(Qt),Qt=void 0),s.detail.value.length{const e=s.detail.value;n.writeParameter(i,e),t.loading(!0),fetch(n.getUrl().toString(),{signal:Jt.signal}).then((t=>t.json())).catch((()=>{})).then((n=>{t.whitelist=n,t.loading(!1).dropdown.show(e)}))}),a))}(Xt[e.id],n.suggestionStarts,s,a,t,n.autocompleteTriggerTimeout)}))}var Yt;e.UI=e.UI||{},e.UI.Input=e.UI.Input||{},(Yt=e.UI.Input).textarea=new o,Yt.markdown=new w,Yt.treeSelect=new G(new Y(t),e.UI.menu.drilldown,{txt:t=>e.Language.txt(t)},n),Yt.tagInput=Yt.tag||{},Yt.tagInput.init=(t,e,n,i,s)=>Gt(zt,t,e,n,i,s),Yt.tagInput.getTagifyInstance=t=>Xt[t]}($,il,document); + */var Z="​";function tt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n/g,">").replace(/"/g,""").replace(/`|'/g,"'"):t}function dt(t){var e=Object.prototype.toString.call(t).split(" ")[1].slice(0,-1);return t===Object(t)&&"Array"!=e&&"Function"!=e&&"RegExp"!=e&&"HTMLUnknownElement"!=e}function ct(t,e,n){var i,s;function a(t,e){for(var n in e)if(e.hasOwnProperty(n)){if(dt(e[n])){dt(t[n])?a(t[n],e[n]):t[n]=Object.assign({},e[n]);continue}if(Array.isArray(e[n])){t[n]=Object.assign([],e[n]);continue}t[n]=e[n]}}return i=t,(null!=(s=Object)&&"undefined"!=typeof Symbol&&s[Symbol.hasInstance]?s[Symbol.hasInstance](i):i instanceof s)||(t={}),a(t,e),n&&a(t,n),t}function ut(){var t=[],e={},n=!0,i=!1,s=void 0;try{for(var a,o=arguments[Symbol.iterator]();!(n=(a=o.next()).done);n=!0){var r=a.value,l=!0,d=!1,c=void 0;try{for(var u,h=r[Symbol.iterator]();!(l=(u=h.next()).done);l=!0){var g=u.value;dt(g)?e[g.value]||(t.push(g),e[g.value]=1):t.includes(g)||t.push(g)}}catch(t){d=!0,c=t}finally{try{l||null==h.return||h.return()}finally{if(d)throw c}}}}catch(t){i=!0,s=t}finally{try{n||null==o.return||o.return()}finally{if(i)throw s}}return t}function ht(t){return String.prototype.normalize?"string"==typeof t?t.normalize("NFD").replace(/[\u0300-\u036f]/g,""):void 0:t}var gt=function(){return/(?=.*chrome)(?=.*android)/i.test(navigator.userAgent)};function pt(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,(function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)}))}function ft(t){var e;return vt.call(this,t)&&(null==t||null===(e=t.classList)||void 0===e?void 0:e.contains(this.settings.classNames.tag))}function mt(t){return vt.call(this,t)&&(null==t?void 0:t.closest(this.settings.classNames.tagSelector))}function vt(t){var e;return(null==t||null===(e=t.closest)||void 0===e?void 0:e.call(t,this.settings.classNames.namespaceSelector))===this.DOM.scope}function wt(t,e){var n=window.getSelection();return e=e||n.getRangeAt(0),"string"==typeof t&&(t=document.createTextNode(t)),e&&(e.deleteContents(),e.insertNode(t)),t}function bt(t,e,n){return t?(e&&(t.__tagifyTagData=n?e:ct({},t.__tagifyTagData||{},e)),t.__tagifyTagData):(nt.warn("tag element doesn't exist",{tagElm:t,data:e}),e)}function yt(t){if(t&&t.parentNode){var e=t,n=window.getSelection(),i=n.getRangeAt(0);n.rangeCount&&(i.setStartAfter(e),i.collapse(!0),n.removeAllRanges(),n.addRange(i))}}function Tt(t,e){t.forEach((function(t){if(bt(t.previousSibling)||!t.previousSibling){var n=document.createTextNode("​");t.before(n),e&&yt(n)}}))}var St={delimiters:",",pattern:null,tagTextProp:"value",maxTags:1/0,callbacks:{},addTagOnBlur:!0,addTagOn:["blur","tab","enter"],onChangeAfterBlur:!0,duplicates:!1,whitelist:[],blacklist:[],enforceWhitelist:!1,userInput:!0,focusable:!0,keepInvalidTags:!1,createInvalidTags:!0,mixTagsAllowedAfter:/,|\.|\:|\s/,mixTagsInterpolator:["[[","]]"],backspace:!0,skipInvalid:!1,pasteAsTags:!0,editTags:{clicks:2,keepInvalid:!0},transformTag:function(){},trim:!0,a11y:{focusableTags:!1},mixMode:{insertAfterTag:"Ā "},autoComplete:{enabled:!0,rightKey:!1,tabKey:!1},classNames:{namespace:"tagify",mixMode:"tagify--mix",selectMode:"tagify--select",input:"tagify__input",focus:"tagify--focus",tagNoAnimation:"tagify--noAnim",tagInvalid:"tagify--invalid",tagNotAllowed:"tagify--notAllowed",scopeLoading:"tagify--loading",hasMaxTags:"tagify--hasMaxTags",hasNoTags:"tagify--noTags",empty:"tagify--empty",inputInvalid:"tagify__input--invalid",dropdown:"tagify__dropdown",dropdownWrapper:"tagify__dropdown__wrapper",dropdownHeader:"tagify__dropdown__header",dropdownFooter:"tagify__dropdown__footer",dropdownItem:"tagify__dropdown__item",dropdownItemActive:"tagify__dropdown__item--active",dropdownItemHidden:"tagify__dropdown__item--hidden",dropdownItemSelected:"tagify__dropdown__item--selected",dropdownInital:"tagify__dropdown--initial",tag:"tagify__tag",tagText:"tagify__tag-text",tagX:"tagify__tag__removeBtn",tagLoading:"tagify__tag--loading",tagEditing:"tagify__tag--editable",tagFlash:"tagify__tag--flash",tagHide:"tagify__tag--hide"},dropdown:{classname:"",enabled:2,maxItems:10,searchKeys:["value","searchBy"],fuzzySearch:!0,caseSensitive:!1,accentedSearch:!0,includeSelectedTags:!1,escapeHTML:!0,highlightFirst:!0,closeOnSelect:!0,clearOnSelect:!0,position:"all",appendTarget:null},hooks:{beforeRemoveTag:function(){return Promise.resolve()},beforePaste:function(){return Promise.resolve()},suggestionClick:function(){return Promise.resolve()},beforeKeyDown:function(){return Promise.resolve()}}};function xt(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function Et(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],e=this.dropdown.events.callbacks,n=this.listeners.dropdown=this.listeners.dropdown||{position:this.dropdown.position.bind(this,null),onKeyDown:e.onKeyDown.bind(this),onMouseOver:e.onMouseOver.bind(this),onMouseLeave:e.onMouseLeave.bind(this),onClick:e.onClick.bind(this),onScroll:e.onScroll.bind(this)},i=t?"addEventListener":"removeEventListener";"manual"!=this.settings.dropdown.position&&(document[i]("scroll",n.position,!0),window[i]("resize",n.position),window[i]("keydown",n.onKeyDown)),this.DOM.dropdown[i]("mouseover",n.onMouseOver),this.DOM.dropdown[i]("mouseleave",n.onMouseLeave),this.DOM.dropdown[i]("mousedown",n.onClick),this.DOM.dropdown.content[i]("scroll",n.onScroll)},callbacks:{onKeyDown:function(t){var e=this;if(this.state.hasFocus&&!this.state.composing){var n=this.settings,i=n.dropdown.includeSelectedTags,s=this.DOM.dropdown.querySelector(n.classNames.dropdownItemActiveSelector),a=this.dropdown.getSuggestionDataByNode(s),o="mix"==n.mode,r="select"==n.mode;n.hooks.beforeKeyDown(t,{tagify:this}).then((function(l){switch(t.key){case"ArrowDown":case"ArrowUp":case"Down":case"Up":t.preventDefault();var d=e.dropdown.getAllSuggestionsRefs(),c="ArrowUp"==t.key||"Up"==t.key;s&&(s=e.dropdown.getNextOrPrevOption(s,!c)),s&&s.matches(n.classNames.dropdownItemSelector)||(s=d[c?d.length-1:0]),e.dropdown.highlightOption(s,!0);break;case"PageUp":case"PageDown":var u;t.preventDefault();var h=e.dropdown.getAllSuggestionsRefs(),g=Math.floor(e.DOM.dropdown.content.clientHeight/(null===(u=h[0])||void 0===u?void 0:u.offsetHeight))||1,p="PageUp"===t.key;if(s){var f=h.indexOf(s),m=p?Math.max(0,f-g):Math.min(h.length-1,f+g);s=h[m]}else s=h[0];e.dropdown.highlightOption(s,!0);break;case"Home":case"End":t.preventDefault();var v=e.dropdown.getAllSuggestionsRefs();s=v["Home"===t.key?0:v.length-1],e.dropdown.highlightOption(s,!0);break;case"Escape":case"Esc":e.dropdown.hide();break;case"ArrowRight":if(e.state.actions.ArrowLeft||n.autoComplete.rightKey)return;case"Tab":var w=!n.autoComplete.rightKey||!n.autoComplete.tabKey;if(!o&&!r&&s&&w&&!e.state.editing&&a){t.preventDefault();var b=e.dropdown.getMappedValue(a);return e.state.autoCompleteData=a,e.input.autocomplete.set.call(e,b),!1}return!0;case"Enter":t.preventDefault(),e.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),n.hooks.suggestionClick(t,{tagify:e,tagData:a,suggestionElm:s}).then((function(){if(s){var n=i?s:e.dropdown.getNextOrPrevOption(s,!c);e.dropdown.selectOption(s,t,(function(){if(n){var t=n.getAttribute("value");n=e.dropdown.getSuggestionNodeByValue(t),e.dropdown.highlightOption(n)}}))}else e.dropdown.hide(),o||e.addTags(e.state.inputText.trim(),!0)})).catch((function(t){return nt.warn(t)}));break;case"Backspace":if(o||e.state.editing.scope)return;var y=e.input.raw.call(e);""!=y&&8203!=y.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0))}}))}},onMouseOver:function(t){var e=t.target.closest(this.settings.classNames.dropdownItemSelector);this.dropdown.highlightOption(e)},onMouseLeave:function(t){this.dropdown.highlightOption()},onClick:function(t){var e=this;if(0==t.button&&t.target!=this.DOM.dropdown&&t.target!=this.DOM.dropdown.content){var n=t.target.closest(this.settings.classNames.dropdownItemSelector),i=this.dropdown.getSuggestionDataByNode(n);this.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),this.settings.hooks.suggestionClick(t,{tagify:this,tagData:i,suggestionElm:n}).then((function(){n?e.dropdown.selectOption(n,t):e.dropdown.hide()})).catch((function(t){return nt.warn(t)}))}},onScroll:function(t){var e=t.target,n=e.scrollTop/(e.scrollHeight-e.parentNode.clientHeight)*100;this.trigger("dropdown:scroll",{percentage:Math.round(n)})}}},refilter:function(t){t=t||this.state.dropdown.query||"",this.suggestedListItems=this.dropdown.filterListItems(t),this.dropdown.fill(),this.suggestedListItems.length||this.dropdown.hide(),this.trigger("dropdown:updated",this.DOM.dropdown)},getSuggestionDataByNode:function(t){for(var e,n=t&&t.getAttribute("value"),i=this.suggestedListItems.length;i--;){if(dt(e=this.suggestedListItems[i])&&e.value==n)return e;if(e==n)return{value:e}}},getSuggestionNodeByValue:function(t){return this.dropdown.getAllSuggestionsRefs().find((function(e){return e.getAttribute("value")===t}))},getNextOrPrevOption:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.dropdown.getAllSuggestionsRefs(),i=n.findIndex((function(e){return e===t}));return e?n[i+1]:n[i-1]},highlightOption:function(t,e){var n,i=this.settings.classNames.dropdownItemActive;if(this.state.ddItemElm&&(this.state.ddItemElm.classList.remove(i),this.state.ddItemElm.removeAttribute("aria-selected")),!t)return this.state.ddItemData=null,this.state.ddItemElm=null,void this.input.autocomplete.suggest.call(this);n=this.dropdown.getSuggestionDataByNode(t),this.state.ddItemData=n,this.state.ddItemElm=t,t.classList.add(i),t.setAttribute("aria-selected",!0),e&&(t.parentNode.scrollTop=t.clientHeight+t.offsetTop-t.parentNode.clientHeight),this.settings.autoComplete&&(this.input.autocomplete.suggest.call(this,n),this.dropdown.position())},selectOption:function(t,e,n){var i=this,s=this.settings,a=s.dropdown.includeSelectedTags,o=s.dropdown,r=o.clearOnSelect,l=o.closeOnSelect;if(!t)return this.addTags(this.state.inputText,!0),void(l&&this.dropdown.hide());e=e||{};var d=t.getAttribute("value"),c="noMatch"==d,u="mix"==s.mode,h=this.suggestedListItems.find((function(t){var e;return(null!==(e=t.value)&&void 0!==e?e:t)==d}));if(this.trigger("dropdown:select",{data:h,elm:t,event:e}),h||c){if(this.state.editing){var g=this.normalizeTags([h])[0];h=s.transformTag.call(this,g)||g,this.onEditTagDone(null,ct({__isValid:!0},h))}else this[u?"addMixTags":"addTags"]([h||this.input.raw.call(this)],r);(u||this.DOM.input.parentNode)&&(setTimeout((function(){i.DOM.input.focus(),i.toggleFocusClass(!0)})),l&&setTimeout(this.dropdown.hide.bind(this)),a?n&&n():(t.addEventListener("transitionend",(function(){i.dropdown.fillHeaderFooter(),setTimeout((function(){t.remove(),i.dropdown.refilter(),n&&n()}),100)}),{once:!0}),t.classList.add(this.settings.classNames.dropdownItemHidden)))}else l&&setTimeout(this.dropdown.hide.bind(this))},selectAll:function(t){this.suggestedListItems.length=0,this.dropdown.hide(),this.dropdown.filterListItems("");var e=this.dropdown.filterListItems("");return t||(e=this.state.dropdown.suggestions),this.addTags(e,!0),this},filterListItems:function(t,e){var n,i,s,a,o,r,l=function(){var t,l,d=void 0,c=void 0;t=p[b],i=(null!=(l=Object)&&"undefined"!=typeof Symbol&&l[Symbol.hasInstance]?l[Symbol.hasInstance](t):t instanceof l)?p[b]:{value:p[b]};var f,m=Object.keys(i).some((function(t){return w.includes(t)}))?w:["value"];u.fuzzySearch&&!e.exact?(a=m.reduce((function(t,e){return t+" "+(i[e]||"")}),"").toLowerCase().trim(),u.accentedSearch&&(a=ht(a),r=ht(r)),d=0==a.indexOf(r),c=a===r,f=a,s=r.toLowerCase().split(" ").every((function(t){return f.includes(t.toLowerCase())}))):(d=!0,s=m.some((function(t){var n=""+(i[t]||"");return u.accentedSearch&&(n=ht(n),r=ht(r)),u.caseSensitive||(n=n.toLowerCase()),c=n===r,e.exact?n===r:0==n.indexOf(r)}))),o=!u.includeSelectedTags&&n.isTagDuplicate(dt(i)?i.value:i),s&&!o&&(c&&d?g.push(i):"startsWith"==u.sortby&&d?h.unshift(i):h.push(i))},d=this,c=this.settings,u=c.dropdown,h=(e=e||{},[]),g=[],p=c.whitelist,f=u.maxItems>=0?u.maxItems:1/0,m=u.includeSelectedTags,v="function"==typeof u.sortby,w=u.searchKeys,b=0;if(!(t="select"==c.mode&&this.value.length&&this.value[0][c.tagTextProp]==t?"":t)||!w.length){h=m?p:p.filter((function(t){return!d.isTagDuplicate(dt(t)?t.value:t)}));var y=v?u.sortby(h,r):h.slice(0,f);return this.state.dropdown.suggestions=y,y}for(r=u.caseSensitive?""+t:(""+t).toLowerCase();b[\r\n ]+\<").split(/>\s+<").trim():""},fillHeaderFooter:function(){var t=this.dropdown.filterListItems(this.state.dropdown.query),e=this.parseTemplate("dropdownHeader",[t]),n=this.parseTemplate("dropdownFooter",[t]),i=this.dropdown.getHeaderRef(),s=this.dropdown.getFooterRef();e&&(null==i||i.parentNode.replaceChild(e,i)),n&&(null==s||s.parentNode.replaceChild(n,s))},position:function(t){var e=this.settings.dropdown,n=this.dropdown.getAppendTarget();if("manual"!=e.position&&n){var i,s,a,o,r,l,d,c,u,h,g=this.DOM.dropdown,p=e.RTL,f=n===document.body,m=n===this.DOM.scope,v=f?window.pageYOffset:n.scrollTop,w=document.fullscreenElement||document.webkitFullscreenElement||document.documentElement,b=w.clientHeight,y=Math.max(w.clientWidth||0,window.innerWidth||0),T=y>480?e.position:"all",S=this.DOM["input"==T?"input":"scope"];if(t=t||g.clientHeight,this.state.dropdown.visible){if("text"==T?(a=(i=function(){var t=document.getSelection();if(t.rangeCount){var e,n,i=t.getRangeAt(0),s=i.startContainer,a=i.startOffset;if(a>0)return(n=document.createRange()).setStart(s,a-1),n.setEnd(s,a),{left:(e=n.getBoundingClientRect()).right,top:e.top,bottom:e.bottom};if(s.getBoundingClientRect)return s.getBoundingClientRect()}return{left:-9999,top:-9999}}()).bottom,s=i.top,o=i.left,r="auto"):(l=function(t){var e=0,n=0;for(t=t.parentNode;t&&t!=w;)e+=t.offsetTop||0,n+=t.offsetLeft||0,t=t.parentNode;return{top:e,left:n}}(n),i=S.getBoundingClientRect(),s=m?-1:i.top-l.top,a=(m?i.height:i.bottom-l.top)-1,o=m?-1:i.left-l.left,r=i.width+"px"),!f){var x=function(){for(var t=0,n=e.appendTarget.parentNode;n;)t+=n.scrollTop||0,n=n.parentNode;return t}();s+=x,a+=x}var E;s=Math.floor(s),a=Math.ceil(a),c=y-o<120,u=((d=null!==(E=e.placeAbove)&&void 0!==E?E:b-i.bottom\n ').concat(this.settings.templates.input.call(this),"\n ").concat(Z,"\n ")},input:function(){var t=this.settings,e=t.placeholder||Z;return"')},tag:function(t,e){var n=e.settings;return'\n \n
\n ').concat(t[n.tagTextProp]||t.value,"\n
\n
")},dropdown:function(t){var e=t.dropdown,n="manual"==e.position;return'
\n
\n
')},dropdownContent:function(t){var e=this.settings.templates,n=this.state.dropdown.suggestions;return"\n ".concat(e.dropdownHeader.call(this,n),"\n ").concat(t,"\n ").concat(e.dropdownFooter.call(this,n),"\n ")},dropdownItem:function(t){return"
').concat(t.mappedValue||t.value,"
")},dropdownHeader:function(t){return"
')},dropdownFooter:function(t){var e=t.length-this.settings.dropdown.maxItems;return e>0?"
\n ').concat(e," more items. Refine your search.\n
"):""},dropdownItemNoMatch:null};function Bt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],n=this.settings,i=this.events.callbacks,s=e?"addEventListener":"removeEventListener";if(!this.state.mainEvents||!e){for(var a in this.state.mainEvents=e,e&&!this.listeners.main&&(this.events.bindGlobal.call(this),this.settings.isJQueryPlugin&&jQuery(this.DOM.originalInput).on("tagify.removeAllTags",this.removeAllTags.bind(this))),t=this.listeners.main=this.listeners.main||{keydown:["input",i.onKeydown.bind(this)],click:["scope",i.onClickScope.bind(this)],dblclick:"select"!=n.mode&&["scope",i.onDoubleClickScope.bind(this)],paste:["input",i.onPaste.bind(this)],drop:["input",i.onDrop.bind(this)],compositionstart:["input",i.onCompositionStart.bind(this)],compositionend:["input",i.onCompositionEnd.bind(this)]})t[a]&&this.DOM[t[a][0]][s](a,t[a][1]);var o=this.listeners.main.inputMutationObserver||new MutationObserver(i.onInputDOMChange.bind(this));o.disconnect(),"mix"==n.mode&&o.observe(this.DOM.input,{childList:!0}),this.events.bindOriginaInputListener.call(this)}},bindOriginaInputListener:function(t){var e=(t||0)+500;this.listeners.main&&(clearInterval(this.listeners.main.originalInputValueObserverInterval),this.listeners.main.originalInputValueObserverInterval=setInterval(this.events.callbacks.observeOriginalInputValue.bind(this),e))},bindGlobal:function(t){var e,n=this.events.callbacks,i=t?"removeEventListener":"addEventListener";if(this.listeners&&(t||!this.listeners.global)){this.listeners.global=this.listeners.global||[{type:this.isIE?"keydown":"input",target:this.DOM.input,cb:n[this.isIE?"onInputIE":"onInput"].bind(this)},{type:"keydown",target:window,cb:n.onWindowKeyDown.bind(this)},{type:"focusin",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"focusout",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"click",target:document,cb:n.onClickAnywhere.bind(this),useCapture:!0}];var s=!0,a=!1,o=void 0;try{for(var r,l=this.listeners.global[Symbol.iterator]();!(s=(r=l.next()).done);s=!0)(e=r.value).target[i](e.type,e.cb,!!e.useCapture)}catch(t){a=!0,o=t}finally{try{s||null==l.return||l.return()}finally{if(a)throw o}}}},unbindGlobal:function(){this.events.bindGlobal.call(this,!0)},callbacks:{onFocusBlur:function(t){var e,n,i=this.settings,s=mt.call(this,t.relatedTarget),a=ft.call(this,t.relatedTarget),o=t.target.classList.contains(i.classNames.tagX),r="focusin"==t.type,l="focusout"==t.type;o&&"mix"!=i.mode&&this.DOM.input.focus(),s&&r&&!a&&!o&&this.toggleFocusClass(this.state.hasFocus=+new Date);var d=t.target?this.trim(this.DOM.input.textContent):"",c=null===(n=this.value)||void 0===n||null===(e=n[0])||void 0===e?void 0:e[i.tagTextProp],u=i.dropdown.enabled>=0,h={relatedTarget:t.relatedTarget},g=this.state.actions.selectOption&&(u||!i.dropdown.closeOnSelect),p=this.state.actions.addNew&&u;if(l){if(t.relatedTarget===this.DOM.scope)return this.dropdown.hide(),void this.DOM.input.focus();this.postUpdate(),i.onChangeAfterBlur&&this.triggerChangeEvent()}if(!(g||p||o))if(this.state.hasFocus=!(!r&&!s)&&+new Date,this.toggleFocusClass(this.state.hasFocus),"mix"!=i.mode){if(r){if(!i.focusable)return;var f=0===i.dropdown.enabled&&!this.state.dropdown.visible,m=!a||"select"===i.mode,v=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector);return this.trigger("focus",h),void(f&&m&&(this.dropdown.show(this.value.length?"":void 0),this.setRangeAtStartEnd(!1,v)))}if(l){if(this.trigger("blur",h),this.loading(!1),"select"==i.mode){if(this.value.length){var w=this.getTagElms()[0];d=this.trim(w.textContent)}c===d&&(d="")}d&&!this.state.actions.selectOption&&i.addTagOnBlur&&i.addTagOn.includes("blur")&&this.addTags(d,!0)}s||(this.DOM.input.removeAttribute("style"),this.dropdown.hide())}else r?this.trigger("focus",h):l&&(this.trigger("blur",h),this.loading(!1),this.dropdown.hide(),this.state.dropdown.visible=void 0,this.setStateSelection())},onCompositionStart:function(t){this.state.composing=!0},onCompositionEnd:function(t){this.state.composing=!1},onWindowKeyDown:function(t){var e,n=this.settings,i=document.activeElement,s=mt.call(this,i)&&this.DOM.scope.contains(i),a=i===this.DOM.input,o=s&&i.hasAttribute("readonly"),r=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector),l=this.state.dropdown.visible;if(("Tab"===t.key&&l||this.state.hasFocus||s&&!o)&&!a){e=i.nextElementSibling;var d=t.target.classList.contains(n.classNames.tagX);switch(t.key){case"Backspace":n.readonly||this.state.editing||(this.removeTags(i),(e||this.DOM.input).focus());break;case"Enter":if(d)return void this.removeTags(t.target.parentNode);n.a11y.focusableTags&&ft.call(this,i)&&setTimeout(this.editTag.bind(this),0,i);break;case"ArrowDown":this.state.dropdown.visible||"mix"==n.mode||this.dropdown.show();break;case"Tab":null==r||r.focus()}}},onKeydown:function(t){var e=this,n=this.settings;if(!this.state.composing&&n.userInput){"select"==n.mode&&n.enforceWhitelist&&this.value.length&&"Tab"!=t.key&&t.preventDefault();var i=this.trim(t.target.textContent);this.trigger("keydown",{event:t}),n.hooks.beforeKeyDown(t,{tagify:this}).then((function(s){if("mix"==n.mode){switch(t.key){case"Left":case"ArrowLeft":e.state.actions.ArrowLeft=!0;break;case"Delete":case"Backspace":if(e.state.editing)return;var a=document.getSelection(),o="Delete"==t.key&&a.anchorOffset==(a.anchorNode.length||0),r=a.anchorNode.previousSibling,l=1==a.anchorNode.nodeType||!a.anchorOffset&&r&&1==r.nodeType&&a.anchorNode.previousSibling;!function(t){var e=document.createElement("div");t.replace(/\&#?[0-9a-z]+;/gi,(function(t){return e.innerHTML=t,e.innerText}))}(e.DOM.input.innerHTML);var d,c,u,h=e.getTagElms(),g=1===a.anchorNode.length&&a.anchorNode.nodeValue==String.fromCharCode(8203);if("edit"==n.backspace&&l)return d=1==a.anchorNode.nodeType?null:a.anchorNode.previousElementSibling,setTimeout(e.editTag.bind(e),0,d),void t.preventDefault();if(gt()&&Ht(l,Element))return u=rt(l),l.hasAttribute("readonly")||l.remove(),e.DOM.input.focus(),void setTimeout((function(){yt(u),e.DOM.input.click()}));if("BR"==a.anchorNode.nodeName)return;if((o||l)&&1==a.anchorNode.nodeType?c=0==a.anchorOffset?o?h[0]:null:h[Math.min(h.length,a.anchorOffset)-1]:o?c=a.anchorNode.nextElementSibling:Ht(l,Element)&&(c=l),3==a.anchorNode.nodeType&&!a.anchorNode.nodeValue&&a.anchorNode.previousElementSibling&&t.preventDefault(),(l||o)&&!n.backspace)return void t.preventDefault();if("Range"!=a.type&&!a.anchorOffset&&a.anchorNode==e.DOM.input&&"Delete"!=t.key)return void t.preventDefault();if("Range"!=a.type&&c&&c.hasAttribute("readonly"))return void yt(rt(c));"Delete"==t.key&&g&&bt(a.anchorNode.nextSibling)&&e.removeTags(a.anchorNode.nextSibling)}return!0}var p="manual"==n.dropdown.position;switch(t.key){case"Backspace":"select"==n.mode&&n.enforceWhitelist&&e.value.length?e.removeTags():e.state.dropdown.visible&&"manual"!=n.dropdown.position||""!=t.target.textContent&&8203!=i.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0));break;case"Esc":case"Escape":if(e.state.dropdown.visible)return;t.target.blur();break;case"Down":case"ArrowDown":e.state.dropdown.visible||e.dropdown.show();break;case"ArrowRight":var f=e.state.inputSuggestion||e.state.ddItemData;if(f&&n.autoComplete.rightKey)return void e.addTags([f],!0);break;case"Tab":return!0;case"Enter":if(e.state.dropdown.visible&&!p)return;t.preventDefault();var m=e.state.autoCompleteData||i;setTimeout((function(){e.state.dropdown.visible&&!p||e.state.actions.selectOption||!n.addTagOn.includes(t.key.toLowerCase())||(e.addTags([m],!0),e.state.autoCompleteData=null)}))}})).catch((function(t){return t}))}},onInput:function(t){this.postUpdate();var e=this.settings;if("mix"==e.mode)return this.events.callbacks.onMixTagsInput.call(this,t);var n=this.input.normalize.call(this,void 0,{trim:!1}),i=n.length>=e.dropdown.enabled,s={value:n,inputElm:this.DOM.input},a=this.validateTag({value:n});"select"==e.mode&&this.toggleScopeValidation(a),s.isValid=a,this.state.inputText!=n&&(this.input.set.call(this,n,!1),-1!=n.search(e.delimiters)?this.addTags(n)&&this.input.set.call(this):e.dropdown.enabled>=0&&this.dropdown[i?"show":"hide"](n),this.trigger("input",s))},onMixTagsInput:function(t){var e,n,i,s,a,o,r,l,d=this,c=this.settings,u=this.value.length,h=this.getTagElms(),g=document.createDocumentFragment(),p=window.getSelection().getRangeAt(0),f=[].map.call(h,(function(t){return bt(t).value}));if("deleteContentBackward"==t.inputType&>()&&this.events.callbacks.onKeydown.call(this,{target:t.target,key:"Backspace"}),Tt(this.getTagElms()),this.value.slice().forEach((function(t){t.readonly&&!f.includes(t.value)&&g.appendChild(d.createTagElem(t))})),g.childNodes.length&&(p.insertNode(g),this.setRangeAtStartEnd(!1,g.lastChild)),h.length!=u)return this.value=[].map.call(this.getTagElms(),(function(t){return bt(t)})),void this.update({withoutChangeEvent:!0});if(this.hasMaxTags())return!0;if(window.getSelection&&(o=window.getSelection()).rangeCount>0&&3==o.anchorNode.nodeType){if((p=o.getRangeAt(0).cloneRange()).collapse(!0),p.setStart(o.focusNode,0),i=(e=p.toString().slice(0,p.endOffset)).split(c.pattern).length-1,(n=e.match(c.pattern))&&(s=e.slice(e.lastIndexOf(n[n.length-1]))),s){if(this.state.actions.ArrowLeft=!1,this.state.tag={prefix:s.match(c.pattern)[0],value:s.replace(c.pattern,"")},this.state.tag.baseOffset=o.baseOffset-this.state.tag.value.length,l=this.state.tag.value.match(c.delimiters))return this.state.tag.value=this.state.tag.value.replace(c.delimiters,""),this.state.tag.delimiters=l[0],this.addTags(this.state.tag.value,c.dropdown.clearOnSelect),void this.dropdown.hide();a=this.state.tag.value.length>=c.dropdown.enabled;try{r=(r=this.state.flaggedTags[this.state.tag.baseOffset]).prefix==this.state.tag.prefix&&r.value[0]==this.state.tag.value[0],this.state.flaggedTags[this.state.tag.baseOffset]&&!this.state.tag.value&&delete this.state.flaggedTags[this.state.tag.baseOffset]}catch(t){}(r||i500||!e.focusable)?this.state.dropdown.visible?this.dropdown.hide():0===e.dropdown.enabled&&"mix"!=e.mode&&this.dropdown.show(this.value.length?"":void 0):"select"!=e.mode||0!==e.dropdown.enabled||this.state.dropdown.visible||(this.events.callbacks.onDoubleClickScope.call(this,function(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);n.push.apply(n,i)}return n}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}(function(t){for(var e=1;e=this.settings.dropdown.enabled&&(this.state.editing&&(this.state.editing.value=o),this.dropdown.show(o)),this.trigger("edit:input",{tag:i,index:s,data:ct({},this.value[s],{newValue:o}),event:e})},onEditTagPaste:function(t,e){var n=(e.clipboardData||window.clipboardData).getData("Text");e.preventDefault();var i=wt(n);this.setRangeAtStartEnd(!1,i)},onEditTagClick:function(t,e){this.events.callbacks.onClickScope.call(this,e)},onEditTagFocus:function(t){this.state.editing={scope:t,input:t.querySelector("[contenteditable]")}},onEditTagBlur:function(t,e){var n=ft.call(this,e.relatedTarget);if("select"==this.settings.mode&&n&&e.relatedTarget.contains(e.target))this.dropdown.hide();else if(this.state.editing&&(this.state.hasFocus||this.toggleFocusClass(),this.DOM.scope.contains(document.activeElement)||this.trigger("blur",{}),this.DOM.scope.contains(t))){var i,s,a,o=this.settings,r=t.closest("."+o.classNames.tag),l=bt(r),d=this.input.normalize.call(this,t),c=(Vt(i={},o.tagTextProp,d),Vt(i,"__tagId",l.__tagId),i),u=l.__originalData,h=this.editTagChangeDetected(ct(l,c)),g=this.validateTag(c);if(d)if(h){var p;if(s=this.hasMaxTags(),a=ct({},u,(Vt(p={},o.tagTextProp,this.trim(d)),Vt(p,"__isValid",g),p)),o.transformTag.call(this,a,u),!0!==(g=(!s||!0===u.__isValid)&&this.validateTag(a))){if(this.trigger("invalid",{data:a,tag:r,message:g}),o.editTags.keepInvalid)return;o.keepInvalidTags?a.__isValid=g:a=u}else o.keepInvalidTags&&(delete a.title,delete a["aria-invalid"],delete a.class);this.onEditTagDone(r,a)}else this.onEditTagDone(r,u);else this.onEditTagDone(r)}},onEditTagkeydown:function(t,e){if(!this.state.composing)switch(this.trigger("edit:keydown",{event:t}),t.key){case"Esc":case"Escape":this.state.editing=!1,e.__tagifyTagData.__originalData.value?e.parentNode.replaceChild(e.__tagifyTagData.__originalHTML,e):e.remove();break;case"Enter":case"Tab":t.preventDefault(),setTimeout((function(){return t.target.blur()}),0)}},onDoubleClickScope:function(t){var e=t.target.closest("."+this.settings.classNames.tag);if(e){var n,i,s=bt(e),a=this.settings;!1!==(null==s?void 0:s.editable)&&(n=e.classList.contains(this.settings.classNames.tagEditing),i=e.hasAttribute("readonly"),a.readonly||n||i||!this.settings.editTags||!a.userInput||(this.events.callbacks.onEditTagFocus.call(this,e),this.editTag(e)),this.toggleFocusClass(!0),"select"!=a.mode&&this.trigger("dblclick",{tag:e,index:this.getNodeIndex(e),data:bt(e)}))}},onInputDOMChange:function(t){var e=this;t.forEach((function(t){t.addedNodes.forEach((function(t){if("

"==t.outerHTML)t.replaceWith(document.createElement("br"));else if(1==t.nodeType&&t.querySelector(e.settings.classNames.tagSelector)){var n,i=document.createTextNode("");3==t.childNodes[0].nodeType&&"BR"!=t.previousSibling.nodeName&&(i=document.createTextNode("\n")),(n=t).replaceWith.apply(n,Rt([i].concat(Rt(Rt(t.childNodes).slice(0,-1))))),yt(i)}else if(ft.call(e,t)){var s;if(3!=(null===(s=t.previousSibling)||void 0===s?void 0:s.nodeType)||t.previousSibling.textContent||t.previousSibling.remove(),t.previousSibling&&"BR"==t.previousSibling.nodeName){t.previousSibling.replaceWith("\n​");for(var a=t.nextSibling,o="";a;)o+=a.textContent,a=a.nextSibling;o.trim()&&yt(t.previousSibling)}else t.previousSibling&&!bt(t.previousSibling)||t.before("​")}})),t.removedNodes.forEach((function(t){t&&"BR"==t.nodeName&&ft.call(e,n)&&(e.removeTags(n),e.fixFirefoxLastTagNoCaret())}))}));var n=this.DOM.input.lastChild;n&&""==n.nodeValue&&n.remove(),n&&"BR"==n.nodeName||this.DOM.input.appendChild(document.createElement("br"))}}};function Ft(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.map((t=>t.value)),dropdown:{enabled:e.dropdownSuggestionsStartAfter,maxItems:e.dropdownMaxItems,closeOnSelect:e.dropdownCloseOnSelect,highlightFirst:e.highlight},transformTag(t){t.display||(t.display=t.value,t.value=encodeURIComponent(t.value)),t.display=t.display.replace(//g,">")},templates:{wrapper(t,e){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:t=>`
\n \n
\n ${t.display}\n
\n
`,dropdownItem:t=>`
\n ${t.display}\n
`}}}(e.id,n));o.addTags(i),void 0!==s&&o.on("input",(t=>{!function(t,e,n,i,s,a){void 0!==Xt&&Xt.abort(),Xt=new AbortController,t.whitelist=null,"number"==typeof Jt&&(t.DOM.scope.ownerDocument.defaultView.clearTimeout(Jt),Jt=void 0),s.detail.value.length{const e=s.detail.value;n.writeParameter(i,e),t.loading(!0),fetch(n.getUrl().toString(),{signal:Xt.signal}).then((t=>t.json())).catch((()=>{})).then((n=>{t.whitelist=n,t.loading(!1).dropdown.show(e)}))}),a))}(o,n.suggestionStarts,s,a,t,n.autocompleteTriggerTimeout)}))}var Gt;zt.prototype={_dropdown:Ct,placeCaretAfterNode:yt,getSetTagData:bt,helpers:{sameStr:it,removeCollectionProp:st,omit:at,isObject:dt,parseHTML:ot,escapeHTML:lt,extend:ct,concatWithoutDups:ut,getUID:pt,isNodeTag:ft},customEventsList:["change","add","remove","invalid","input","paste","click","keydown","focus","blur","edit:input","edit:beforeUpdate","edit:updated","edit:start","edit:keydown","dropdown:show","dropdown:hide","dropdown:select","dropdown:updated","dropdown:noMatch","dropdown:scroll"],dataProps:["__isValid","__removed","__originalData","__originalHTML","__tagId"],trim:function(t){return this.settings.trim&&t&&"string"==typeof t?t.trim():t},parseHTML:ot,templates:kt,parseTemplate:function(t,e){return ot((t=this.settings.templates[t]||t).apply(this,e))},set whitelist(t){var e=t&&Array.isArray(t);this.settings.whitelist=e?t:[],this.setPersistedData(e?t:[],"whitelist")},get whitelist(){return this.settings.whitelist},set userInput(t){this.settings.userInput=!!t,this.setContentEditable(!!t)},get userInput(){return this.settings.userInput},generateClassSelectors:function(t){var e=function(e){var n=e;Object.defineProperty(t,n+"Selector",{get:function(){return"."+this[n].split(" ")[0]}})};for(var n in t)e(n)},applySettings:function(t,e){var n,i;St.templates=this.templates;var s=ct({},St,"mix"==e.mode?{dropdown:{position:"text"}}:{}),a=this.settings=ct({},s,e);if(a.disabled=t.hasAttribute("disabled"),a.readonly=a.readonly||t.hasAttribute("readonly"),a.placeholder=lt(t.getAttribute("placeholder")||a.placeholder||""),a.required=t.hasAttribute("required"),this.generateClassSelectors(a.classNames),this.isIE&&(a.autoComplete=!1),["whitelist","blacklist"].forEach((function(e){var n=t.getAttribute("data-"+e);n&&Ut(n=n.split(a.delimiters),Array)&&(a[e]=n)})),"autoComplete"in e&&!dt(e.autoComplete)&&(a.autoComplete=St.autoComplete,a.autoComplete.enabled=e.autoComplete),"mix"==a.mode&&(a.pattern=a.pattern||/@/,a.autoComplete.rightKey=!0,a.delimiters=e.delimiters||null,a.tagTextProp&&!a.dropdown.searchKeys.includes(a.tagTextProp)&&a.dropdown.searchKeys.push(a.tagTextProp)),t.pattern)try{a.pattern=new RegExp(t.pattern)}catch(t){}if(a.delimiters){a._delimiters=a.delimiters;try{a.delimiters=new RegExp(this.settings.delimiters,"g")}catch(t){}}a.disabled&&(a.userInput=!1),this.TEXTS=Wt({},Lt,a.texts||{}),"select"==a.mode&&(a.dropdown.includeSelectedTags=!0),("select"!=a.mode||(null===(n=e.dropdown)||void 0===n?void 0:n.enabled))&&a.userInput||(a.dropdown.enabled=0),a.dropdown.appendTarget=(null===(i=e.dropdown)||void 0===i?void 0:i.appendTarget)||document.body,void 0===a.dropdown.includeSelectedTags&&(a.dropdown.includeSelectedTags=a.duplicates);var o=this.getPersistedData("whitelist");Array.isArray(o)&&(this.whitelist=Array.isArray(a.whitelist)?ut(a.whitelist,o):o)},getAttributes:function(t){var e,n=this.getCustomAttributes(t),i="";for(e in n)i+=" "+e+(void 0!==t[e]?'="'.concat(n[e],'"'):"");return i},getCustomAttributes:function(t){if(!dt(t))return"";var e,n={};for(e in t)"__"!=e.slice(0,2)&&"class"!=e&&t.hasOwnProperty(e)&&void 0!==t[e]&&(n[e]=lt(t[e]));return n},setStateSelection:function(){var t=window.getSelection(),e={anchorOffset:t.anchorOffset,anchorNode:t.anchorNode,range:t.getRangeAt&&t.rangeCount&&t.getRangeAt(0)};return this.state.selection=e,e},getCSSVars:function(){var t,e,n=getComputedStyle(this.DOM.scope,null);this.CSSVars={tagHideTransition:(t=function(t){if(!t)return{};var e=(t=t.trim().split(" ")[0]).split(/\d+/g).filter((function(t){return t})).pop().trim();return{value:+t.split(e).filter((function(t){return t}))[0].trim(),unit:e}}(("tag-hide-transition",n.getPropertyValue("--tag-hide-transition"))),e=t.value,"s"==t.unit?1e3*e:e)}},build:function(t){var e=this.DOM,n=t.closest("label");this.settings.mixMode.integrated?(e.originalInput=null,e.scope=t,e.input=t):(e.originalInput=t,e.originalInput_tabIndex=t.tabIndex,e.scope=this.parseTemplate("wrapper",[t,this.settings]),e.input=e.scope.querySelector(this.settings.classNames.inputSelector),t.parentNode.insertBefore(e.scope,t),t.tabIndex=-1),n&&n.setAttribute("for","")},destroy:function(){var t;this.events.unbindGlobal.call(this),null===(t=this.DOM.scope.parentNode)||void 0===t||t.removeChild(this.DOM.scope),this.DOM.originalInput.tabIndex=this.DOM.originalInput_tabIndex,delete this.DOM.originalInput.__tagify,this.dropdown.hide(!0),this.removeAllCustomListeners(),clearTimeout(this.dropdownHide__bindEventsTimeout),clearInterval(this.listeners.main.originalInputValueObserverInterval)},loadOriginalValues:function(t){var e,n=this.settings;if(this.state.blockChangeEvent=!0,void 0===t){var i=this.getPersistedData("value");t=i&&!this.DOM.originalInput.value?i:n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value}if(this.removeAllTags(),t)if("mix"==n.mode)this.parseMixTags(t),(e=this.DOM.input.lastChild)&&"BR"==e.tagName||this.DOM.input.insertAdjacentHTML("beforeend","
");else{try{Ut(JSON.parse(t),Array)&&(t=JSON.parse(t))}catch(t){}this.addTags(t,!0).forEach((function(t){return t&&t.classList.add(n.classNames.tagNoAnimation)}))}else this.postUpdate();this.state.lastOriginalValueReported=n.mixMode.integrated?"":this.DOM.originalInput.value},cloneEvent:function(t){var e={};for(var n in t)"path"!=n&&(e[n]=t[n]);return e},loading:function(t){return this.state.isLoading=t,this.DOM.scope.classList[t?"add":"remove"](this.settings.classNames.scopeLoading),this},tagLoading:function(t,e){return t&&t.classList[e?"add":"remove"](this.settings.classNames.tagLoading),this},toggleClass:function(t,e){"string"==typeof t&&this.DOM.scope.classList.toggle(t,e)},toggleScopeValidation:function(t){var e=!0===t||void 0===t;!this.settings.required&&t&&t===this.TEXTS.empty&&(e=!0),this.toggleClass(this.settings.classNames.tagInvalid,!e),this.DOM.scope.title=e?"":t},toggleFocusClass:function(t){this.toggleClass(this.settings.classNames.focus,!!t)},setPlaceholder:function(t){var e=this;["data","aria"].forEach((function(n){return e.DOM.input.setAttribute("".concat(n,"-placeholder"),t)}))},triggerChangeEvent:function(){if(!this.settings.mixMode.integrated){var t=this.DOM.originalInput,e=this.state.lastOriginalValueReported!==t.value,n=new CustomEvent("change",{bubbles:!0});e&&(this.state.lastOriginalValueReported=t.value,n.simulated=!0,t._valueTracker&&t._valueTracker.setValue(Math.random()),t.dispatchEvent(n),this.trigger("change",this.state.lastOriginalValueReported),t.value=this.state.lastOriginalValueReported)}},events:qt,fixFirefoxLastTagNoCaret:function(){},setRangeAtStartEnd:function(t,e){if(e){t="number"==typeof t?t:!!t,e=e.lastChild||e;var n=document.getSelection();if(Ut(n.focusNode,Element)&&!this.DOM.input.contains(n.focusNode))return!0;try{n.rangeCount>=1&&["Start","End"].forEach((function(i){return n.getRangeAt(0)["set"+i](e,t||e.length)}))}catch(t){console.warn(t)}}},insertAfterTag:function(t,e){if(e=e||this.settings.mixMode.insertAfterTag,t&&t.parentNode&&e)return e="string"==typeof e?document.createTextNode(e):e,t.parentNode.insertBefore(e,t.nextSibling),e},editTagChangeDetected:function(t){var e=t.__originalData;for(var n in e)if(!this.dataProps.includes(n)&&t[n]!=e[n])return!0;return!1},getTagTextNode:function(t){return t.querySelector(this.settings.classNames.tagTextSelector)},setTagTextNode:function(t,e){this.getTagTextNode(t).innerHTML=lt(e)},editTag:function(t,e){var n=this;t=t||this.getLastTag(),e=e||{};var i=this.settings,s=this.getTagTextNode(t),a=this.getNodeIndex(t),o=bt(t),r=this.events.callbacks,l=!0,d="select"==i.mode;if(!d&&this.dropdown.hide(),s){if(!Ut(o,Object)||!("editable"in o)||o.editable)return o=bt(t,{__originalData:ct({},o),__originalHTML:t.cloneNode(!0)}),bt(o.__originalHTML,o.__originalData),s.setAttribute("contenteditable",!0),t.classList.add(i.classNames.tagEditing),this.events.callbacks.onEditTagFocus.call(this,t),s.addEventListener("click",r.onEditTagClick.bind(this,t)),s.addEventListener("blur",r.onEditTagBlur.bind(this,this.getTagTextNode(t))),s.addEventListener("input",r.onEditTagInput.bind(this,s)),s.addEventListener("paste",r.onEditTagPaste.bind(this,s)),s.addEventListener("keydown",(function(e){return r.onEditTagkeydown.call(n,e,t)})),s.addEventListener("compositionstart",r.onCompositionStart.bind(this)),s.addEventListener("compositionend",r.onCompositionEnd.bind(this)),e.skipValidation||(l=this.editTagToggleValidity(t)),s.originalIsValid=l,this.trigger("edit:start",{tag:t,index:a,data:o,isValid:l}),s.focus(),!d&&this.setRangeAtStartEnd(!1,s),0===i.dropdown.enabled&&!d&&this.dropdown.show(),this.state.hasFocus=!0,this}else nt.warn("Cannot find element in Tag template: .",i.classNames.tagTextSelector)},editTagToggleValidity:function(t,e){var n;if(e=e||bt(t))return(n=!("__isValid"in e)||!0===e.__isValid)||this.removeTagsFromValue(t),this.update(),t.classList.toggle(this.settings.classNames.tagNotAllowed,!n),e.__isValid=n,e.__isValid;nt.warn("tag has no data: ",t,e)},onEditTagDone:function(t,e){t=t||this.state.editing.scope,e=e||{};var n,i,s=this.settings,a={tag:t,index:this.getNodeIndex(t),previousData:bt(t),data:e};this.trigger("edit:beforeUpdate",a,{cloneData:!1}),this.state.editing=!1,delete e.__originalData,delete e.__originalHTML,t&&t.parentNode&&((void 0!==(i=e[s.tagTextProp])?null===(n=(i+="").trim)||void 0===n?void 0:n.call(i):s.tagTextProp in e?void 0:e.value)?(t=this.replaceTag(t,e),this.editTagToggleValidity(t,e),s.a11y.focusableTags?t.focus():"select"!=s.mode&&yt(t)):this.removeTags(t)),this.trigger("edit:updated",a),s.dropdown.closeOnSelect&&this.dropdown.hide(),this.settings.keepInvalidTags&&this.reCheckInvalidTags()},replaceTag:function(t,e){e&&""!==e.value&&void 0!==e.value||(e=t.__tagifyTagData),e.__isValid&&1!=e.__isValid&&ct(e,this.getInvalidTagAttrs(e,e.__isValid));var n=this.createTagElem(e);return t.parentNode.replaceChild(n,t),this.updateValueByDOMTags(),n},updateValueByDOMTags:function(){var t=this;this.value.length=0;var e=this.settings.classNames,n=[e.tagNotAllowed.split(" ")[0],e.tagHide];[].forEach.call(this.getTagElms(),(function(e){Kt(e.classList).some((function(t){return n.includes(t)}))||t.value.push(bt(e))})),this.update(),this.dropdown.refilter()},injectAtCaret:function(t,e){var n;if(e=e||(null===(n=this.state.selection)||void 0===n?void 0:n.range),"string"==typeof t&&(t=document.createTextNode(t)),!e&&t)return this.appendMixTags(t),this;var i=wt(t,e);return this.setRangeAtStartEnd(!1,i),this.updateValueByDOMTags(),this.update(),this},input:{set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.settings,i=n.dropdown.closeOnSelect;this.state.inputText=t,e&&(this.DOM.input.innerHTML=lt(""+t),t&&this.toggleClass(n.classNames.empty,!this.DOM.input.innerHTML)),!t&&i&&this.dropdown.hide.bind(this),this.input.autocomplete.suggest.call(this),this.input.validate.call(this)},raw:function(){return this.DOM.input.textContent},validate:function(){var t=!this.state.inputText||!0===this.validateTag({value:this.state.inputText});return this.DOM.input.classList.toggle(this.settings.classNames.inputInvalid,!t),t},normalize:function(t,e){var n=t||this.DOM.input,i=[];n.childNodes.forEach((function(t){return 3==t.nodeType&&i.push(t.nodeValue)})),i=i.join("\n");try{i=i.replace(/(?:\r\n|\r|\n)/g,this.settings.delimiters.source.charAt(0))}catch(t){}return i=i.replace(/\s/g," "),(null==e?void 0:e.trim)?this.trim(i):i},autocomplete:{suggest:function(t){if(this.settings.autoComplete.enabled){"object"!=typeof(t=t||{value:""})&&(t={value:t});var e=this.dropdown.getMappedValue(t);if("number"!=typeof e){var n=this.state.inputText.toLowerCase(),i=e.substr(0,this.state.inputText.length).toLowerCase(),s=e.substring(this.state.inputText.length);e&&this.state.inputText&&i==n?(this.DOM.input.setAttribute("data-suggest",s),this.state.inputSuggestion=t):(this.DOM.input.removeAttribute("data-suggest"),delete this.state.inputSuggestion)}}},set:function(t){var e=this.DOM.input.getAttribute("data-suggest"),n=t||(e?this.state.inputText+e:null);return!!n&&("mix"==this.settings.mode?this.replaceTextWithNode(document.createTextNode(this.state.tag.prefix+n)):(this.input.set.call(this,n),this.setRangeAtStartEnd(!1,this.DOM.input)),this.input.autocomplete.suggest.call(this),this.dropdown.hide(),!0)}}},getTagIdx:function(t){return this.value.findIndex((function(e){return e.__tagId==(t||{}).__tagId}))},getNodeIndex:function(t){var e=0;if(t)for(;t=t.previousElementSibling;)e++;return e},getTagElms:function(){for(var t=arguments.length,e=new Array(t),n=0;n=this.settings.maxTags&&this.TEXTS.exceed},setReadonly:function(t,e){var n=this.settings;this.DOM.scope.contains(document.activeElement)&&document.activeElement.blur(),n[e||"readonly"]=t,this.DOM.scope[(t?"set":"remove")+"Attribute"](e||"readonly",!0),this.settings.userInput=!0,this.setContentEditable(!t)},setContentEditable:function(t){this.DOM.input.contentEditable=t,this.DOM.input.tabIndex=t?0:-1},setDisabled:function(t){this.setReadonly(t,"disabled")},normalizeTags:function(t){var e=this,n=this.settings,i=n.whitelist,s=n.delimiters,a=n.mode,o=n.tagTextProp,r=[],l=!!i&&Ut(i[0],Object),d=Array.isArray(t),c=d&&t[0].value,u=function(t){return(t+"").split(s).reduce((function(t,n){var i,s=e.trim(n);return s&&t.push(($t(i={},o,s),$t(i,"value",s),i)),t}),[])};if("number"==typeof t&&(t=t.toString()),"string"==typeof t){if(!t.trim())return[];t=u(t)}else d&&(t=t.reduce((function(t,n){if(dt(n)){var i=ct({},n);o in i||(o="value"),i[o]=e.trim(i[o]),(i[o]||0===i[o])&&t.push(i)}else if(null!=n&&""!==n&&void 0!==n){var s;(s=t).push.apply(s,Kt(u(n)))}return t}),[]));return l&&!c&&(t.forEach((function(t){var n=r.map((function(t){return t.value})),i=e.dropdown.filterListItems.call(e,t[o],{exact:!0});e.settings.duplicates||(i=i.filter((function(t){return!n.includes(t.value)})));var s=i.length>1?e.getWhitelistItem(t[o],o,i):i[0];s&&Ut(s,Object)?r.push(s):"mix"!=a&&(null==t.value&&(t.value=t[o]),r.push(t))})),r.length&&(t=r)),t},parseMixTags:function(t){var e=this,n=this.settings,i=n.mixTagsInterpolator,s=n.duplicates,a=n.transformTag,o=n.enforceWhitelist,r=n.maxTags,l=n.tagTextProp,d=[];t=t.split(i[0]).map((function(t,n){var c,u,h,g=t.split(i[1]),p=g[0],f=d.length==r;try{if(p==+p)throw Error;u=JSON.parse(p)}catch(t){u=e.normalizeTags(p)[0]||{value:p}}if(a.call(e,u),f||!(g.length>1)||o&&!e.isTagWhitelisted(u.value)||!s&&e.isTagDuplicate(u.value)){if(t)return n?i[0]+t:t}else u[c=u[l]?l:"value"]=e.trim(u[c]),h=e.createTagElem(u),d.push(u),h.classList.add(e.settings.classNames.tagNoAnimation),g[0]=h.outerHTML,e.value.push(u);return g.join("")})).join(""),this.DOM.input.innerHTML=t,this.DOM.input.appendChild(document.createTextNode("")),this.DOM.input.normalize();var c=this.getTagElms();return c.forEach((function(t,e){return bt(t,d[e])})),this.update({withoutChangeEvent:!0}),Tt(c,this.state.hasFocus),t},replaceTextWithNode:function(t,e){if(this.state.tag||e){e=e||this.state.tag.prefix+this.state.tag.value;var n,i,s=this.state.selection||window.getSelection(),a=s.anchorNode,o=this.state.tag.delimiters?this.state.tag.delimiters.length:0;return a.splitText(s.anchorOffset-o),-1==(n=a.nodeValue.lastIndexOf(e))||(i=a.splitText(n),t&&a.parentNode.replaceChild(t,i)),!0}},prepareNewTagNode:function(t,e){e=e||{};var n=this.settings,i=[],s={},a=Object.assign({},t,{value:t.value+""});if(t=Object.assign({},a),n.transformTag.call(this,t),t.__isValid=this.hasMaxTags()||this.validateTag(t),!0!==t.__isValid){if(e.skipInvalid)return;if(ct(s,this.getInvalidTagAttrs(t,t.__isValid),{__preInvalidData:a}),t.__isValid==this.TEXTS.duplicate&&this.flashTag(this.getTagElmByValue(t.value)),!n.createInvalidTags)return void i.push(t.value)}return"readonly"in t&&(t.readonly?s["aria-readonly"]=!0:delete t.readonly),{tagElm:this.createTagElem(t,s),tagData:t,aggregatedInvalidInput:i}},postProcessNewTagNode:function(t,e){var n=this,i=this.settings,s=e.__isValid;s&&!0===s?this.value.push(e):(this.trigger("invalid",{data:e,index:this.value.length,tag:t,message:s}),i.keepInvalidTags||setTimeout((function(){return n.removeTags(t,!0)}),1e3)),this.dropdown.position()},selectTag:function(t,e){var n=this;if(!this.settings.enforceWhitelist||this.isTagWhitelisted(e.value)){this.state.actions.selectOption&&setTimeout((function(){return n.setRangeAtStartEnd(!1,n.DOM.input)}));var i=this.getLastTag();return i?this.replaceTag(i,e):this.appendTag(t),this.value[0]=e,this.update(),this.trigger("add",{tag:t,data:e}),[t]}},addEmptyTag:function(t){var e=ct({value:""},t||{}),n=this.createTagElem(e);bt(n,e),this.appendTag(n),this.editTag(n,{skipValidation:!0}),this.toggleFocusClass(!0)},addTags:function(t,e,n){var i=this,s=[],a=this.settings,o=[],r=document.createDocumentFragment(),l=[];if(!t||0==t.length)return s;switch(t=this.normalizeTags(t),a.mode){case"mix":return this.addMixTags(t);case"select":e=!1,this.removeAllTags()}return this.DOM.input.removeAttribute("style"),t.forEach((function(t){var e=i.prepareNewTagNode(t,{skipInvalid:n||a.skipInvalid});if(e){var d=e.tagElm;if(t=e.tagData,o=e.aggregatedInvalidInput,s.push(d),"select"==a.mode)return i.selectTag(d,t);r.appendChild(d),i.postProcessNewTagNode(d,t),l.push({tagElm:d,tagData:t})}})),this.appendTag(r),l.forEach((function(t){var e=t.tagElm,n=t.tagData;return i.trigger("add",{tag:e,index:i.getTagIdx(n),data:n})})),this.update(),t.length&&e&&(this.input.set.call(this,a.createInvalidTags?"":o.join(a._delimiters)),this.setRangeAtStartEnd(!1,this.DOM.input)),this.dropdown.refilter(),s},addMixTags:function(t){var e=this;if((t=this.normalizeTags(t))[0].prefix||this.state.tag)return this.prefixedTextToTag(t[0]);var n=document.createDocumentFragment();return t.forEach((function(t){var i=e.prepareNewTagNode(t);n.appendChild(i.tagElm),e.insertAfterTag(i.tagElm),e.postProcessNewTagNode(i.tagElm,i.tagData)})),this.appendMixTags(n),n.children},appendMixTags:function(t){var e=!!this.state.selection;e?this.injectAtCaret(t):(this.DOM.input.focus(),(e=this.setStateSelection()).range.setStart(this.DOM.input,e.range.endOffset),e.range.setEnd(this.DOM.input,e.range.endOffset),this.DOM.input.appendChild(t),this.updateValueByDOMTags(),this.update())},prefixedTextToTag:function(t){var e,n,i,s=this,a=this.settings,o=null===(e=this.state.tag)||void 0===e?void 0:e.delimiters;if(t.prefix=t.prefix||this.state.tag?this.state.tag.prefix:(a.pattern.source||a.pattern)[0],i=this.prepareNewTagNode(t),n=i.tagElm,this.replaceTextWithNode(n)||this.DOM.input.appendChild(n),setTimeout((function(){return n.classList.add(s.settings.classNames.tagNoAnimation)}),300),this.update(),!o){var r=this.insertAfterTag(n)||n;setTimeout(yt,0,r)}return this.state.tag=null,this.postProcessNewTagNode(n,i.tagData),n},appendTag:function(t){var e=this.DOM,n=e.input;e.scope.insertBefore(t,n)},createTagElem:function(t,e){t.__tagId=pt();var n,i=ct({},t,Wt({value:lt(t.value+"")},e));return function(t){for(var e,n=document.createNodeIterator(t,NodeFilter.SHOW_TEXT,null,!1);e=n.nextNode();)e.textContent.trim()||e.parentNode.removeChild(e)}(n=this.parseTemplate("tag",[i,this])),bt(n,t),n},reCheckInvalidTags:function(){var t=this,e=this.settings;this.getTagElms(e.classNames.tagNotAllowed).forEach((function(n,i){var s=bt(n),a=t.hasMaxTags(),o=t.validateTag(s),r=!0===o&&!a;if("select"==e.mode&&t.toggleScopeValidation(o),r)return s=s.__preInvalidData?s.__preInvalidData:{value:s.value},t.replaceTag(n,s);n.title=a||o}))},removeTags:function(t,e,n){var i,s=this,a=this.settings;if(t=t&&Ut(t,HTMLElement)?[t]:Ut(t,Array)?t:t?[t]:[this.getLastTag()].filter((function(t){return t})),i=t.reduce((function(t,e){e&&"string"==typeof e&&(e=s.getTagElmByValue(e));var n=bt(e);return e&&n&&!n.readonly&&t.push({node:e,idx:s.getTagIdx(n),data:bt(e,{__removed:!0})}),t}),[]),n="number"==typeof n?n:this.CSSVars.tagHideTransition,"select"==a.mode&&(n=0,this.input.set.call(this)),1==i.length&&"select"!=a.mode&&i[0].node.classList.contains(a.classNames.tagNotAllowed)&&(e=!0),i.length)return a.hooks.beforeRemoveTag(i,{tagify:this}).then((function(){var t=function(t){t.node.parentNode&&(t.node.parentNode.removeChild(t.node),e?a.keepInvalidTags&&this.trigger("remove",{tag:t.node,index:t.idx}):(this.trigger("remove",{tag:t.node,index:t.idx,data:t.data}),this.dropdown.refilter(),this.dropdown.position(),this.DOM.input.normalize(),a.keepInvalidTags&&this.reCheckInvalidTags()))};n&&n>10&&1==i.length?function(e){e.node.style.width=parseFloat(window.getComputedStyle(e.node).width)+"px",document.body.clientTop,e.node.classList.add(a.classNames.tagHide),setTimeout(t.bind(this),n,e)}.call(s,i[0]):i.forEach(t.bind(s)),e||(s.removeTagsFromValue(i.map((function(t){return t.node}))),s.update(),"select"==a.mode&&a.userInput&&s.setContentEditable(!0))})).catch((function(t){}))},removeTagsFromDOM:function(){this.getTagElms().forEach((function(t){return t.remove()}))},removeTagsFromValue:function(t){var e=this;(t=Array.isArray(t)?t:[t]).forEach((function(t){var n=bt(t),i=e.getTagIdx(n);i>-1&&e.value.splice(i,1)}))},removeAllTags:function(t){var e=this;t=t||{},this.value=[],"mix"==this.settings.mode?this.DOM.input.innerHTML="":this.removeTagsFromDOM(),this.dropdown.refilter(),this.dropdown.position(),this.state.dropdown.visible&&setTimeout((function(){e.DOM.input.focus()})),"select"==this.settings.mode&&(this.input.set.call(this),this.settings.userInput&&this.setContentEditable(!0)),this.update(t)},postUpdate:function(){this.state.blockChangeEvent=!1;var t,e,n=this.settings,i=n.classNames,s="mix"==n.mode?n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value.trim():this.value.length+this.input.raw.call(this).length;this.toggleClass(i.hasMaxTags,this.value.length>=n.maxTags),this.toggleClass(i.hasNoTags,!this.value.length),this.toggleClass(i.empty,!s),"select"==n.mode&&this.toggleScopeValidation(null===(e=this.value)||void 0===e||null===(t=e[0])||void 0===t?void 0:t.__isValid)},setOriginalInputValue:function(t){var e=this.DOM.originalInput;this.settings.mixMode.integrated||(e.value=t,e.tagifyValue=e.value,this.setPersistedData(t,"value"))},update:function(t){clearTimeout(this.debouncedUpdateTimeout),this.debouncedUpdateTimeout=setTimeout(function(){var e=this.getInputValue();this.setOriginalInputValue(e),this.settings.onChangeAfterBlur&&(t||{}).withoutChangeEvent||this.state.blockChangeEvent||this.triggerChangeEvent(),this.postUpdate()}.bind(this),100),this.events.bindOriginaInputListener.call(this,100)},getInputValue:function(){var t=this.getCleanValue();return"mix"==this.settings.mode?this.getMixedTagsAsString(t):t.length?this.settings.originalInputValueFormat?this.settings.originalInputValueFormat(t):JSON.stringify(t):""},getCleanValue:function(t){return st(t||this.value,this.dataProps)},getMixedTagsAsString:function(){var t="",e=this,n=this.settings,i=n.originalInputValueFormat||JSON.stringify,s=n.mixTagsInterpolator;return function n(a){a.childNodes.forEach((function(a){if(1==a.nodeType){var o=bt(a);if("BR"==a.tagName&&(t+="\r\n"),o&&ft.call(e,a)){if(o.__removed)return;t+=s[0]+i(at(o,e.dataProps))+s[1]}else a.getAttribute("style")||["B","I","U"].includes(a.tagName)?t+=a.textContent:"DIV"!=a.tagName&&"P"!=a.tagName||(t+="\r\n",n(a))}else t+=a.textContent}))}(this.DOM.input),t}},zt.prototype.removeTag=zt.prototype.removeTags,e.UI=e.UI||{},e.UI.Input=e.UI.Input||{},(Gt=e.UI.Input).textarea=new o,Gt.markdown=new w,Gt.treeSelect=new G(new Y(t),e.UI.menu.drilldown,{txt:t=>e.Language.txt(t)},n),Gt.tagInput=Gt.tag||{},Gt.tagInput.init=(t,e,n,i,s)=>Qt(zt,t,e,n,i,s)}($,il,document); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index 8d6486834bf5..bae34d83c624 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -13,12 +13,6 @@ * https://github.com/ILIAS-eLearning */ -/** - * - * @type {Array} - */ -const instances = []; - /** * * @type {AbortController} @@ -142,15 +136,6 @@ function retrieveAutocomplete( ); } -/** - * - * @param {string} instanceId - * @returns {Tagify} - */ -export function getTagifyInstance(instanceId) { - return instances[instanceId]; -} - /** * @param {Tagify} Tagify * @param {HTMLInput} input @@ -159,16 +144,23 @@ export function getTagifyInstance(instanceId) { * @param {URLBuilder} autocompleteEndpoint * @param {URLBuilderToken} autocompleteToken */ -export function init(Tagify, input, config, value, autocompleteEndpoint, autocompleteToken) { - instances[input.id] = new Tagify( +export default function init( + Tagify, + input, + config, + value, + autocompleteEndpoint, + autocompleteToken, +) { + const instance = new Tagify( input, buildSettings(input.id, config), ); - instances[input.id].addTags(value); + instance.addTags(value); if (typeof autocompleteEndpoint !== 'undefined') { - instances[input.id].on('input', (event) => { + instance.on('input', (event) => { retrieveAutocomplete( - instances[input.id], + instance, config.suggestionStarts, autocompleteEndpoint, autocompleteToken, diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js index 39c38d732e55..57acf74b20eb 100755 --- a/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/input.factory.js @@ -32,7 +32,7 @@ import MarkdownFactory from './Markdown/markdown.factory.js'; import TreeSelectFactory from './TreeSelect/TreeSelectFactory.js'; import JQueryEventListener from '../../../Core/src/JQueryEventListener.js'; import Tagify from '@yaireo/tagify'; -import * as tag from './Tag/tag.js'; +import tag from './Tag/tag.js'; il.UI = il.UI || {}; il.UI.Input = il.UI.Input || {}; @@ -48,7 +48,6 @@ il.UI.Input = il.UI.Input || {}; document, ); Input.tagInput = Input.tag || {}; - Input.tagInput.init = (input, config, value, autocompleteEndpoint, autocompleteToken) => tag.init( + Input.tagInput.init = (input, config, value, autocompleteEndpoint, autocompleteToken) => tag( Tagify, input, config, value, autocompleteEndpoint, autocompleteToken); - Input.tagInput.getTagifyInstance = (input_id) => tag.getTagifyInstance(input_id); }(il.UI.Input)); diff --git a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php index 6c843ad8b0d4..f6f5a442abe3 100755 --- a/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php +++ b/components/ILIAS/UI/src/Implementation/Component/Input/Field/Tag.php @@ -22,7 +22,6 @@ use ILIAS\Data\Factory as DataFactory; use ILIAS\Data\Result\Ok; -use ILIAS\Data\URI; use ILIAS\UI\Component as C; use ILIAS\UI\Component\Signal; use ILIAS\UI\Component\Input\InputData; From dd9cd00f417f2eb56dc23eab896d7b964bda5767 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Fri, 10 Oct 2025 15:55:01 +0200 Subject: [PATCH 15/16] UI: Additional Fixes After Review --- .../js/Input/Field/dist/input.factory.min.js | 2 +- .../resources/js/Input/Field/src/Tag/tag.js | 23 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js index 278938fade3c..e000aa95bfaa 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js +++ b/components/ILIAS/UI/resources/js/Input/Field/dist/input.factory.min.js @@ -38,4 +38,4 @@ This Software may not be rebranded and sold as a library under any other name other than "Tagify" (by owner) or as part of another library. - */var Z="​";function tt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n/g,">").replace(/"/g,""").replace(/`|'/g,"'"):t}function dt(t){var e=Object.prototype.toString.call(t).split(" ")[1].slice(0,-1);return t===Object(t)&&"Array"!=e&&"Function"!=e&&"RegExp"!=e&&"HTMLUnknownElement"!=e}function ct(t,e,n){var i,s;function a(t,e){for(var n in e)if(e.hasOwnProperty(n)){if(dt(e[n])){dt(t[n])?a(t[n],e[n]):t[n]=Object.assign({},e[n]);continue}if(Array.isArray(e[n])){t[n]=Object.assign([],e[n]);continue}t[n]=e[n]}}return i=t,(null!=(s=Object)&&"undefined"!=typeof Symbol&&s[Symbol.hasInstance]?s[Symbol.hasInstance](i):i instanceof s)||(t={}),a(t,e),n&&a(t,n),t}function ut(){var t=[],e={},n=!0,i=!1,s=void 0;try{for(var a,o=arguments[Symbol.iterator]();!(n=(a=o.next()).done);n=!0){var r=a.value,l=!0,d=!1,c=void 0;try{for(var u,h=r[Symbol.iterator]();!(l=(u=h.next()).done);l=!0){var g=u.value;dt(g)?e[g.value]||(t.push(g),e[g.value]=1):t.includes(g)||t.push(g)}}catch(t){d=!0,c=t}finally{try{l||null==h.return||h.return()}finally{if(d)throw c}}}}catch(t){i=!0,s=t}finally{try{n||null==o.return||o.return()}finally{if(i)throw s}}return t}function ht(t){return String.prototype.normalize?"string"==typeof t?t.normalize("NFD").replace(/[\u0300-\u036f]/g,""):void 0:t}var gt=function(){return/(?=.*chrome)(?=.*android)/i.test(navigator.userAgent)};function pt(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,(function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)}))}function ft(t){var e;return vt.call(this,t)&&(null==t||null===(e=t.classList)||void 0===e?void 0:e.contains(this.settings.classNames.tag))}function mt(t){return vt.call(this,t)&&(null==t?void 0:t.closest(this.settings.classNames.tagSelector))}function vt(t){var e;return(null==t||null===(e=t.closest)||void 0===e?void 0:e.call(t,this.settings.classNames.namespaceSelector))===this.DOM.scope}function wt(t,e){var n=window.getSelection();return e=e||n.getRangeAt(0),"string"==typeof t&&(t=document.createTextNode(t)),e&&(e.deleteContents(),e.insertNode(t)),t}function bt(t,e,n){return t?(e&&(t.__tagifyTagData=n?e:ct({},t.__tagifyTagData||{},e)),t.__tagifyTagData):(nt.warn("tag element doesn't exist",{tagElm:t,data:e}),e)}function yt(t){if(t&&t.parentNode){var e=t,n=window.getSelection(),i=n.getRangeAt(0);n.rangeCount&&(i.setStartAfter(e),i.collapse(!0),n.removeAllRanges(),n.addRange(i))}}function Tt(t,e){t.forEach((function(t){if(bt(t.previousSibling)||!t.previousSibling){var n=document.createTextNode("​");t.before(n),e&&yt(n)}}))}var St={delimiters:",",pattern:null,tagTextProp:"value",maxTags:1/0,callbacks:{},addTagOnBlur:!0,addTagOn:["blur","tab","enter"],onChangeAfterBlur:!0,duplicates:!1,whitelist:[],blacklist:[],enforceWhitelist:!1,userInput:!0,focusable:!0,keepInvalidTags:!1,createInvalidTags:!0,mixTagsAllowedAfter:/,|\.|\:|\s/,mixTagsInterpolator:["[[","]]"],backspace:!0,skipInvalid:!1,pasteAsTags:!0,editTags:{clicks:2,keepInvalid:!0},transformTag:function(){},trim:!0,a11y:{focusableTags:!1},mixMode:{insertAfterTag:"Ā "},autoComplete:{enabled:!0,rightKey:!1,tabKey:!1},classNames:{namespace:"tagify",mixMode:"tagify--mix",selectMode:"tagify--select",input:"tagify__input",focus:"tagify--focus",tagNoAnimation:"tagify--noAnim",tagInvalid:"tagify--invalid",tagNotAllowed:"tagify--notAllowed",scopeLoading:"tagify--loading",hasMaxTags:"tagify--hasMaxTags",hasNoTags:"tagify--noTags",empty:"tagify--empty",inputInvalid:"tagify__input--invalid",dropdown:"tagify__dropdown",dropdownWrapper:"tagify__dropdown__wrapper",dropdownHeader:"tagify__dropdown__header",dropdownFooter:"tagify__dropdown__footer",dropdownItem:"tagify__dropdown__item",dropdownItemActive:"tagify__dropdown__item--active",dropdownItemHidden:"tagify__dropdown__item--hidden",dropdownItemSelected:"tagify__dropdown__item--selected",dropdownInital:"tagify__dropdown--initial",tag:"tagify__tag",tagText:"tagify__tag-text",tagX:"tagify__tag__removeBtn",tagLoading:"tagify__tag--loading",tagEditing:"tagify__tag--editable",tagFlash:"tagify__tag--flash",tagHide:"tagify__tag--hide"},dropdown:{classname:"",enabled:2,maxItems:10,searchKeys:["value","searchBy"],fuzzySearch:!0,caseSensitive:!1,accentedSearch:!0,includeSelectedTags:!1,escapeHTML:!0,highlightFirst:!0,closeOnSelect:!0,clearOnSelect:!0,position:"all",appendTarget:null},hooks:{beforeRemoveTag:function(){return Promise.resolve()},beforePaste:function(){return Promise.resolve()},suggestionClick:function(){return Promise.resolve()},beforeKeyDown:function(){return Promise.resolve()}}};function xt(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function Et(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],e=this.dropdown.events.callbacks,n=this.listeners.dropdown=this.listeners.dropdown||{position:this.dropdown.position.bind(this,null),onKeyDown:e.onKeyDown.bind(this),onMouseOver:e.onMouseOver.bind(this),onMouseLeave:e.onMouseLeave.bind(this),onClick:e.onClick.bind(this),onScroll:e.onScroll.bind(this)},i=t?"addEventListener":"removeEventListener";"manual"!=this.settings.dropdown.position&&(document[i]("scroll",n.position,!0),window[i]("resize",n.position),window[i]("keydown",n.onKeyDown)),this.DOM.dropdown[i]("mouseover",n.onMouseOver),this.DOM.dropdown[i]("mouseleave",n.onMouseLeave),this.DOM.dropdown[i]("mousedown",n.onClick),this.DOM.dropdown.content[i]("scroll",n.onScroll)},callbacks:{onKeyDown:function(t){var e=this;if(this.state.hasFocus&&!this.state.composing){var n=this.settings,i=n.dropdown.includeSelectedTags,s=this.DOM.dropdown.querySelector(n.classNames.dropdownItemActiveSelector),a=this.dropdown.getSuggestionDataByNode(s),o="mix"==n.mode,r="select"==n.mode;n.hooks.beforeKeyDown(t,{tagify:this}).then((function(l){switch(t.key){case"ArrowDown":case"ArrowUp":case"Down":case"Up":t.preventDefault();var d=e.dropdown.getAllSuggestionsRefs(),c="ArrowUp"==t.key||"Up"==t.key;s&&(s=e.dropdown.getNextOrPrevOption(s,!c)),s&&s.matches(n.classNames.dropdownItemSelector)||(s=d[c?d.length-1:0]),e.dropdown.highlightOption(s,!0);break;case"PageUp":case"PageDown":var u;t.preventDefault();var h=e.dropdown.getAllSuggestionsRefs(),g=Math.floor(e.DOM.dropdown.content.clientHeight/(null===(u=h[0])||void 0===u?void 0:u.offsetHeight))||1,p="PageUp"===t.key;if(s){var f=h.indexOf(s),m=p?Math.max(0,f-g):Math.min(h.length-1,f+g);s=h[m]}else s=h[0];e.dropdown.highlightOption(s,!0);break;case"Home":case"End":t.preventDefault();var v=e.dropdown.getAllSuggestionsRefs();s=v["Home"===t.key?0:v.length-1],e.dropdown.highlightOption(s,!0);break;case"Escape":case"Esc":e.dropdown.hide();break;case"ArrowRight":if(e.state.actions.ArrowLeft||n.autoComplete.rightKey)return;case"Tab":var w=!n.autoComplete.rightKey||!n.autoComplete.tabKey;if(!o&&!r&&s&&w&&!e.state.editing&&a){t.preventDefault();var b=e.dropdown.getMappedValue(a);return e.state.autoCompleteData=a,e.input.autocomplete.set.call(e,b),!1}return!0;case"Enter":t.preventDefault(),e.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),n.hooks.suggestionClick(t,{tagify:e,tagData:a,suggestionElm:s}).then((function(){if(s){var n=i?s:e.dropdown.getNextOrPrevOption(s,!c);e.dropdown.selectOption(s,t,(function(){if(n){var t=n.getAttribute("value");n=e.dropdown.getSuggestionNodeByValue(t),e.dropdown.highlightOption(n)}}))}else e.dropdown.hide(),o||e.addTags(e.state.inputText.trim(),!0)})).catch((function(t){return nt.warn(t)}));break;case"Backspace":if(o||e.state.editing.scope)return;var y=e.input.raw.call(e);""!=y&&8203!=y.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0))}}))}},onMouseOver:function(t){var e=t.target.closest(this.settings.classNames.dropdownItemSelector);this.dropdown.highlightOption(e)},onMouseLeave:function(t){this.dropdown.highlightOption()},onClick:function(t){var e=this;if(0==t.button&&t.target!=this.DOM.dropdown&&t.target!=this.DOM.dropdown.content){var n=t.target.closest(this.settings.classNames.dropdownItemSelector),i=this.dropdown.getSuggestionDataByNode(n);this.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),this.settings.hooks.suggestionClick(t,{tagify:this,tagData:i,suggestionElm:n}).then((function(){n?e.dropdown.selectOption(n,t):e.dropdown.hide()})).catch((function(t){return nt.warn(t)}))}},onScroll:function(t){var e=t.target,n=e.scrollTop/(e.scrollHeight-e.parentNode.clientHeight)*100;this.trigger("dropdown:scroll",{percentage:Math.round(n)})}}},refilter:function(t){t=t||this.state.dropdown.query||"",this.suggestedListItems=this.dropdown.filterListItems(t),this.dropdown.fill(),this.suggestedListItems.length||this.dropdown.hide(),this.trigger("dropdown:updated",this.DOM.dropdown)},getSuggestionDataByNode:function(t){for(var e,n=t&&t.getAttribute("value"),i=this.suggestedListItems.length;i--;){if(dt(e=this.suggestedListItems[i])&&e.value==n)return e;if(e==n)return{value:e}}},getSuggestionNodeByValue:function(t){return this.dropdown.getAllSuggestionsRefs().find((function(e){return e.getAttribute("value")===t}))},getNextOrPrevOption:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.dropdown.getAllSuggestionsRefs(),i=n.findIndex((function(e){return e===t}));return e?n[i+1]:n[i-1]},highlightOption:function(t,e){var n,i=this.settings.classNames.dropdownItemActive;if(this.state.ddItemElm&&(this.state.ddItemElm.classList.remove(i),this.state.ddItemElm.removeAttribute("aria-selected")),!t)return this.state.ddItemData=null,this.state.ddItemElm=null,void this.input.autocomplete.suggest.call(this);n=this.dropdown.getSuggestionDataByNode(t),this.state.ddItemData=n,this.state.ddItemElm=t,t.classList.add(i),t.setAttribute("aria-selected",!0),e&&(t.parentNode.scrollTop=t.clientHeight+t.offsetTop-t.parentNode.clientHeight),this.settings.autoComplete&&(this.input.autocomplete.suggest.call(this,n),this.dropdown.position())},selectOption:function(t,e,n){var i=this,s=this.settings,a=s.dropdown.includeSelectedTags,o=s.dropdown,r=o.clearOnSelect,l=o.closeOnSelect;if(!t)return this.addTags(this.state.inputText,!0),void(l&&this.dropdown.hide());e=e||{};var d=t.getAttribute("value"),c="noMatch"==d,u="mix"==s.mode,h=this.suggestedListItems.find((function(t){var e;return(null!==(e=t.value)&&void 0!==e?e:t)==d}));if(this.trigger("dropdown:select",{data:h,elm:t,event:e}),h||c){if(this.state.editing){var g=this.normalizeTags([h])[0];h=s.transformTag.call(this,g)||g,this.onEditTagDone(null,ct({__isValid:!0},h))}else this[u?"addMixTags":"addTags"]([h||this.input.raw.call(this)],r);(u||this.DOM.input.parentNode)&&(setTimeout((function(){i.DOM.input.focus(),i.toggleFocusClass(!0)})),l&&setTimeout(this.dropdown.hide.bind(this)),a?n&&n():(t.addEventListener("transitionend",(function(){i.dropdown.fillHeaderFooter(),setTimeout((function(){t.remove(),i.dropdown.refilter(),n&&n()}),100)}),{once:!0}),t.classList.add(this.settings.classNames.dropdownItemHidden)))}else l&&setTimeout(this.dropdown.hide.bind(this))},selectAll:function(t){this.suggestedListItems.length=0,this.dropdown.hide(),this.dropdown.filterListItems("");var e=this.dropdown.filterListItems("");return t||(e=this.state.dropdown.suggestions),this.addTags(e,!0),this},filterListItems:function(t,e){var n,i,s,a,o,r,l=function(){var t,l,d=void 0,c=void 0;t=p[b],i=(null!=(l=Object)&&"undefined"!=typeof Symbol&&l[Symbol.hasInstance]?l[Symbol.hasInstance](t):t instanceof l)?p[b]:{value:p[b]};var f,m=Object.keys(i).some((function(t){return w.includes(t)}))?w:["value"];u.fuzzySearch&&!e.exact?(a=m.reduce((function(t,e){return t+" "+(i[e]||"")}),"").toLowerCase().trim(),u.accentedSearch&&(a=ht(a),r=ht(r)),d=0==a.indexOf(r),c=a===r,f=a,s=r.toLowerCase().split(" ").every((function(t){return f.includes(t.toLowerCase())}))):(d=!0,s=m.some((function(t){var n=""+(i[t]||"");return u.accentedSearch&&(n=ht(n),r=ht(r)),u.caseSensitive||(n=n.toLowerCase()),c=n===r,e.exact?n===r:0==n.indexOf(r)}))),o=!u.includeSelectedTags&&n.isTagDuplicate(dt(i)?i.value:i),s&&!o&&(c&&d?g.push(i):"startsWith"==u.sortby&&d?h.unshift(i):h.push(i))},d=this,c=this.settings,u=c.dropdown,h=(e=e||{},[]),g=[],p=c.whitelist,f=u.maxItems>=0?u.maxItems:1/0,m=u.includeSelectedTags,v="function"==typeof u.sortby,w=u.searchKeys,b=0;if(!(t="select"==c.mode&&this.value.length&&this.value[0][c.tagTextProp]==t?"":t)||!w.length){h=m?p:p.filter((function(t){return!d.isTagDuplicate(dt(t)?t.value:t)}));var y=v?u.sortby(h,r):h.slice(0,f);return this.state.dropdown.suggestions=y,y}for(r=u.caseSensitive?""+t:(""+t).toLowerCase();b[\r\n ]+\<").split(/>\s+<").trim():""},fillHeaderFooter:function(){var t=this.dropdown.filterListItems(this.state.dropdown.query),e=this.parseTemplate("dropdownHeader",[t]),n=this.parseTemplate("dropdownFooter",[t]),i=this.dropdown.getHeaderRef(),s=this.dropdown.getFooterRef();e&&(null==i||i.parentNode.replaceChild(e,i)),n&&(null==s||s.parentNode.replaceChild(n,s))},position:function(t){var e=this.settings.dropdown,n=this.dropdown.getAppendTarget();if("manual"!=e.position&&n){var i,s,a,o,r,l,d,c,u,h,g=this.DOM.dropdown,p=e.RTL,f=n===document.body,m=n===this.DOM.scope,v=f?window.pageYOffset:n.scrollTop,w=document.fullscreenElement||document.webkitFullscreenElement||document.documentElement,b=w.clientHeight,y=Math.max(w.clientWidth||0,window.innerWidth||0),T=y>480?e.position:"all",S=this.DOM["input"==T?"input":"scope"];if(t=t||g.clientHeight,this.state.dropdown.visible){if("text"==T?(a=(i=function(){var t=document.getSelection();if(t.rangeCount){var e,n,i=t.getRangeAt(0),s=i.startContainer,a=i.startOffset;if(a>0)return(n=document.createRange()).setStart(s,a-1),n.setEnd(s,a),{left:(e=n.getBoundingClientRect()).right,top:e.top,bottom:e.bottom};if(s.getBoundingClientRect)return s.getBoundingClientRect()}return{left:-9999,top:-9999}}()).bottom,s=i.top,o=i.left,r="auto"):(l=function(t){var e=0,n=0;for(t=t.parentNode;t&&t!=w;)e+=t.offsetTop||0,n+=t.offsetLeft||0,t=t.parentNode;return{top:e,left:n}}(n),i=S.getBoundingClientRect(),s=m?-1:i.top-l.top,a=(m?i.height:i.bottom-l.top)-1,o=m?-1:i.left-l.left,r=i.width+"px"),!f){var x=function(){for(var t=0,n=e.appendTarget.parentNode;n;)t+=n.scrollTop||0,n=n.parentNode;return t}();s+=x,a+=x}var E;s=Math.floor(s),a=Math.ceil(a),c=y-o<120,u=((d=null!==(E=e.placeAbove)&&void 0!==E?E:b-i.bottom\n ').concat(this.settings.templates.input.call(this),"\n ").concat(Z,"\n ")},input:function(){var t=this.settings,e=t.placeholder||Z;return"')},tag:function(t,e){var n=e.settings;return'\n \n
\n ').concat(t[n.tagTextProp]||t.value,"\n
\n
")},dropdown:function(t){var e=t.dropdown,n="manual"==e.position;return'
\n
\n
')},dropdownContent:function(t){var e=this.settings.templates,n=this.state.dropdown.suggestions;return"\n ".concat(e.dropdownHeader.call(this,n),"\n ").concat(t,"\n ").concat(e.dropdownFooter.call(this,n),"\n ")},dropdownItem:function(t){return"
').concat(t.mappedValue||t.value,"
")},dropdownHeader:function(t){return"
')},dropdownFooter:function(t){var e=t.length-this.settings.dropdown.maxItems;return e>0?"
\n ').concat(e," more items. Refine your search.\n
"):""},dropdownItemNoMatch:null};function Bt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],n=this.settings,i=this.events.callbacks,s=e?"addEventListener":"removeEventListener";if(!this.state.mainEvents||!e){for(var a in this.state.mainEvents=e,e&&!this.listeners.main&&(this.events.bindGlobal.call(this),this.settings.isJQueryPlugin&&jQuery(this.DOM.originalInput).on("tagify.removeAllTags",this.removeAllTags.bind(this))),t=this.listeners.main=this.listeners.main||{keydown:["input",i.onKeydown.bind(this)],click:["scope",i.onClickScope.bind(this)],dblclick:"select"!=n.mode&&["scope",i.onDoubleClickScope.bind(this)],paste:["input",i.onPaste.bind(this)],drop:["input",i.onDrop.bind(this)],compositionstart:["input",i.onCompositionStart.bind(this)],compositionend:["input",i.onCompositionEnd.bind(this)]})t[a]&&this.DOM[t[a][0]][s](a,t[a][1]);var o=this.listeners.main.inputMutationObserver||new MutationObserver(i.onInputDOMChange.bind(this));o.disconnect(),"mix"==n.mode&&o.observe(this.DOM.input,{childList:!0}),this.events.bindOriginaInputListener.call(this)}},bindOriginaInputListener:function(t){var e=(t||0)+500;this.listeners.main&&(clearInterval(this.listeners.main.originalInputValueObserverInterval),this.listeners.main.originalInputValueObserverInterval=setInterval(this.events.callbacks.observeOriginalInputValue.bind(this),e))},bindGlobal:function(t){var e,n=this.events.callbacks,i=t?"removeEventListener":"addEventListener";if(this.listeners&&(t||!this.listeners.global)){this.listeners.global=this.listeners.global||[{type:this.isIE?"keydown":"input",target:this.DOM.input,cb:n[this.isIE?"onInputIE":"onInput"].bind(this)},{type:"keydown",target:window,cb:n.onWindowKeyDown.bind(this)},{type:"focusin",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"focusout",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"click",target:document,cb:n.onClickAnywhere.bind(this),useCapture:!0}];var s=!0,a=!1,o=void 0;try{for(var r,l=this.listeners.global[Symbol.iterator]();!(s=(r=l.next()).done);s=!0)(e=r.value).target[i](e.type,e.cb,!!e.useCapture)}catch(t){a=!0,o=t}finally{try{s||null==l.return||l.return()}finally{if(a)throw o}}}},unbindGlobal:function(){this.events.bindGlobal.call(this,!0)},callbacks:{onFocusBlur:function(t){var e,n,i=this.settings,s=mt.call(this,t.relatedTarget),a=ft.call(this,t.relatedTarget),o=t.target.classList.contains(i.classNames.tagX),r="focusin"==t.type,l="focusout"==t.type;o&&"mix"!=i.mode&&this.DOM.input.focus(),s&&r&&!a&&!o&&this.toggleFocusClass(this.state.hasFocus=+new Date);var d=t.target?this.trim(this.DOM.input.textContent):"",c=null===(n=this.value)||void 0===n||null===(e=n[0])||void 0===e?void 0:e[i.tagTextProp],u=i.dropdown.enabled>=0,h={relatedTarget:t.relatedTarget},g=this.state.actions.selectOption&&(u||!i.dropdown.closeOnSelect),p=this.state.actions.addNew&&u;if(l){if(t.relatedTarget===this.DOM.scope)return this.dropdown.hide(),void this.DOM.input.focus();this.postUpdate(),i.onChangeAfterBlur&&this.triggerChangeEvent()}if(!(g||p||o))if(this.state.hasFocus=!(!r&&!s)&&+new Date,this.toggleFocusClass(this.state.hasFocus),"mix"!=i.mode){if(r){if(!i.focusable)return;var f=0===i.dropdown.enabled&&!this.state.dropdown.visible,m=!a||"select"===i.mode,v=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector);return this.trigger("focus",h),void(f&&m&&(this.dropdown.show(this.value.length?"":void 0),this.setRangeAtStartEnd(!1,v)))}if(l){if(this.trigger("blur",h),this.loading(!1),"select"==i.mode){if(this.value.length){var w=this.getTagElms()[0];d=this.trim(w.textContent)}c===d&&(d="")}d&&!this.state.actions.selectOption&&i.addTagOnBlur&&i.addTagOn.includes("blur")&&this.addTags(d,!0)}s||(this.DOM.input.removeAttribute("style"),this.dropdown.hide())}else r?this.trigger("focus",h):l&&(this.trigger("blur",h),this.loading(!1),this.dropdown.hide(),this.state.dropdown.visible=void 0,this.setStateSelection())},onCompositionStart:function(t){this.state.composing=!0},onCompositionEnd:function(t){this.state.composing=!1},onWindowKeyDown:function(t){var e,n=this.settings,i=document.activeElement,s=mt.call(this,i)&&this.DOM.scope.contains(i),a=i===this.DOM.input,o=s&&i.hasAttribute("readonly"),r=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector),l=this.state.dropdown.visible;if(("Tab"===t.key&&l||this.state.hasFocus||s&&!o)&&!a){e=i.nextElementSibling;var d=t.target.classList.contains(n.classNames.tagX);switch(t.key){case"Backspace":n.readonly||this.state.editing||(this.removeTags(i),(e||this.DOM.input).focus());break;case"Enter":if(d)return void this.removeTags(t.target.parentNode);n.a11y.focusableTags&&ft.call(this,i)&&setTimeout(this.editTag.bind(this),0,i);break;case"ArrowDown":this.state.dropdown.visible||"mix"==n.mode||this.dropdown.show();break;case"Tab":null==r||r.focus()}}},onKeydown:function(t){var e=this,n=this.settings;if(!this.state.composing&&n.userInput){"select"==n.mode&&n.enforceWhitelist&&this.value.length&&"Tab"!=t.key&&t.preventDefault();var i=this.trim(t.target.textContent);this.trigger("keydown",{event:t}),n.hooks.beforeKeyDown(t,{tagify:this}).then((function(s){if("mix"==n.mode){switch(t.key){case"Left":case"ArrowLeft":e.state.actions.ArrowLeft=!0;break;case"Delete":case"Backspace":if(e.state.editing)return;var a=document.getSelection(),o="Delete"==t.key&&a.anchorOffset==(a.anchorNode.length||0),r=a.anchorNode.previousSibling,l=1==a.anchorNode.nodeType||!a.anchorOffset&&r&&1==r.nodeType&&a.anchorNode.previousSibling;!function(t){var e=document.createElement("div");t.replace(/\&#?[0-9a-z]+;/gi,(function(t){return e.innerHTML=t,e.innerText}))}(e.DOM.input.innerHTML);var d,c,u,h=e.getTagElms(),g=1===a.anchorNode.length&&a.anchorNode.nodeValue==String.fromCharCode(8203);if("edit"==n.backspace&&l)return d=1==a.anchorNode.nodeType?null:a.anchorNode.previousElementSibling,setTimeout(e.editTag.bind(e),0,d),void t.preventDefault();if(gt()&&Ht(l,Element))return u=rt(l),l.hasAttribute("readonly")||l.remove(),e.DOM.input.focus(),void setTimeout((function(){yt(u),e.DOM.input.click()}));if("BR"==a.anchorNode.nodeName)return;if((o||l)&&1==a.anchorNode.nodeType?c=0==a.anchorOffset?o?h[0]:null:h[Math.min(h.length,a.anchorOffset)-1]:o?c=a.anchorNode.nextElementSibling:Ht(l,Element)&&(c=l),3==a.anchorNode.nodeType&&!a.anchorNode.nodeValue&&a.anchorNode.previousElementSibling&&t.preventDefault(),(l||o)&&!n.backspace)return void t.preventDefault();if("Range"!=a.type&&!a.anchorOffset&&a.anchorNode==e.DOM.input&&"Delete"!=t.key)return void t.preventDefault();if("Range"!=a.type&&c&&c.hasAttribute("readonly"))return void yt(rt(c));"Delete"==t.key&&g&&bt(a.anchorNode.nextSibling)&&e.removeTags(a.anchorNode.nextSibling)}return!0}var p="manual"==n.dropdown.position;switch(t.key){case"Backspace":"select"==n.mode&&n.enforceWhitelist&&e.value.length?e.removeTags():e.state.dropdown.visible&&"manual"!=n.dropdown.position||""!=t.target.textContent&&8203!=i.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0));break;case"Esc":case"Escape":if(e.state.dropdown.visible)return;t.target.blur();break;case"Down":case"ArrowDown":e.state.dropdown.visible||e.dropdown.show();break;case"ArrowRight":var f=e.state.inputSuggestion||e.state.ddItemData;if(f&&n.autoComplete.rightKey)return void e.addTags([f],!0);break;case"Tab":return!0;case"Enter":if(e.state.dropdown.visible&&!p)return;t.preventDefault();var m=e.state.autoCompleteData||i;setTimeout((function(){e.state.dropdown.visible&&!p||e.state.actions.selectOption||!n.addTagOn.includes(t.key.toLowerCase())||(e.addTags([m],!0),e.state.autoCompleteData=null)}))}})).catch((function(t){return t}))}},onInput:function(t){this.postUpdate();var e=this.settings;if("mix"==e.mode)return this.events.callbacks.onMixTagsInput.call(this,t);var n=this.input.normalize.call(this,void 0,{trim:!1}),i=n.length>=e.dropdown.enabled,s={value:n,inputElm:this.DOM.input},a=this.validateTag({value:n});"select"==e.mode&&this.toggleScopeValidation(a),s.isValid=a,this.state.inputText!=n&&(this.input.set.call(this,n,!1),-1!=n.search(e.delimiters)?this.addTags(n)&&this.input.set.call(this):e.dropdown.enabled>=0&&this.dropdown[i?"show":"hide"](n),this.trigger("input",s))},onMixTagsInput:function(t){var e,n,i,s,a,o,r,l,d=this,c=this.settings,u=this.value.length,h=this.getTagElms(),g=document.createDocumentFragment(),p=window.getSelection().getRangeAt(0),f=[].map.call(h,(function(t){return bt(t).value}));if("deleteContentBackward"==t.inputType&>()&&this.events.callbacks.onKeydown.call(this,{target:t.target,key:"Backspace"}),Tt(this.getTagElms()),this.value.slice().forEach((function(t){t.readonly&&!f.includes(t.value)&&g.appendChild(d.createTagElem(t))})),g.childNodes.length&&(p.insertNode(g),this.setRangeAtStartEnd(!1,g.lastChild)),h.length!=u)return this.value=[].map.call(this.getTagElms(),(function(t){return bt(t)})),void this.update({withoutChangeEvent:!0});if(this.hasMaxTags())return!0;if(window.getSelection&&(o=window.getSelection()).rangeCount>0&&3==o.anchorNode.nodeType){if((p=o.getRangeAt(0).cloneRange()).collapse(!0),p.setStart(o.focusNode,0),i=(e=p.toString().slice(0,p.endOffset)).split(c.pattern).length-1,(n=e.match(c.pattern))&&(s=e.slice(e.lastIndexOf(n[n.length-1]))),s){if(this.state.actions.ArrowLeft=!1,this.state.tag={prefix:s.match(c.pattern)[0],value:s.replace(c.pattern,"")},this.state.tag.baseOffset=o.baseOffset-this.state.tag.value.length,l=this.state.tag.value.match(c.delimiters))return this.state.tag.value=this.state.tag.value.replace(c.delimiters,""),this.state.tag.delimiters=l[0],this.addTags(this.state.tag.value,c.dropdown.clearOnSelect),void this.dropdown.hide();a=this.state.tag.value.length>=c.dropdown.enabled;try{r=(r=this.state.flaggedTags[this.state.tag.baseOffset]).prefix==this.state.tag.prefix&&r.value[0]==this.state.tag.value[0],this.state.flaggedTags[this.state.tag.baseOffset]&&!this.state.tag.value&&delete this.state.flaggedTags[this.state.tag.baseOffset]}catch(t){}(r||i500||!e.focusable)?this.state.dropdown.visible?this.dropdown.hide():0===e.dropdown.enabled&&"mix"!=e.mode&&this.dropdown.show(this.value.length?"":void 0):"select"!=e.mode||0!==e.dropdown.enabled||this.state.dropdown.visible||(this.events.callbacks.onDoubleClickScope.call(this,function(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);n.push.apply(n,i)}return n}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}(function(t){for(var e=1;e=this.settings.dropdown.enabled&&(this.state.editing&&(this.state.editing.value=o),this.dropdown.show(o)),this.trigger("edit:input",{tag:i,index:s,data:ct({},this.value[s],{newValue:o}),event:e})},onEditTagPaste:function(t,e){var n=(e.clipboardData||window.clipboardData).getData("Text");e.preventDefault();var i=wt(n);this.setRangeAtStartEnd(!1,i)},onEditTagClick:function(t,e){this.events.callbacks.onClickScope.call(this,e)},onEditTagFocus:function(t){this.state.editing={scope:t,input:t.querySelector("[contenteditable]")}},onEditTagBlur:function(t,e){var n=ft.call(this,e.relatedTarget);if("select"==this.settings.mode&&n&&e.relatedTarget.contains(e.target))this.dropdown.hide();else if(this.state.editing&&(this.state.hasFocus||this.toggleFocusClass(),this.DOM.scope.contains(document.activeElement)||this.trigger("blur",{}),this.DOM.scope.contains(t))){var i,s,a,o=this.settings,r=t.closest("."+o.classNames.tag),l=bt(r),d=this.input.normalize.call(this,t),c=(Vt(i={},o.tagTextProp,d),Vt(i,"__tagId",l.__tagId),i),u=l.__originalData,h=this.editTagChangeDetected(ct(l,c)),g=this.validateTag(c);if(d)if(h){var p;if(s=this.hasMaxTags(),a=ct({},u,(Vt(p={},o.tagTextProp,this.trim(d)),Vt(p,"__isValid",g),p)),o.transformTag.call(this,a,u),!0!==(g=(!s||!0===u.__isValid)&&this.validateTag(a))){if(this.trigger("invalid",{data:a,tag:r,message:g}),o.editTags.keepInvalid)return;o.keepInvalidTags?a.__isValid=g:a=u}else o.keepInvalidTags&&(delete a.title,delete a["aria-invalid"],delete a.class);this.onEditTagDone(r,a)}else this.onEditTagDone(r,u);else this.onEditTagDone(r)}},onEditTagkeydown:function(t,e){if(!this.state.composing)switch(this.trigger("edit:keydown",{event:t}),t.key){case"Esc":case"Escape":this.state.editing=!1,e.__tagifyTagData.__originalData.value?e.parentNode.replaceChild(e.__tagifyTagData.__originalHTML,e):e.remove();break;case"Enter":case"Tab":t.preventDefault(),setTimeout((function(){return t.target.blur()}),0)}},onDoubleClickScope:function(t){var e=t.target.closest("."+this.settings.classNames.tag);if(e){var n,i,s=bt(e),a=this.settings;!1!==(null==s?void 0:s.editable)&&(n=e.classList.contains(this.settings.classNames.tagEditing),i=e.hasAttribute("readonly"),a.readonly||n||i||!this.settings.editTags||!a.userInput||(this.events.callbacks.onEditTagFocus.call(this,e),this.editTag(e)),this.toggleFocusClass(!0),"select"!=a.mode&&this.trigger("dblclick",{tag:e,index:this.getNodeIndex(e),data:bt(e)}))}},onInputDOMChange:function(t){var e=this;t.forEach((function(t){t.addedNodes.forEach((function(t){if("

"==t.outerHTML)t.replaceWith(document.createElement("br"));else if(1==t.nodeType&&t.querySelector(e.settings.classNames.tagSelector)){var n,i=document.createTextNode("");3==t.childNodes[0].nodeType&&"BR"!=t.previousSibling.nodeName&&(i=document.createTextNode("\n")),(n=t).replaceWith.apply(n,Rt([i].concat(Rt(Rt(t.childNodes).slice(0,-1))))),yt(i)}else if(ft.call(e,t)){var s;if(3!=(null===(s=t.previousSibling)||void 0===s?void 0:s.nodeType)||t.previousSibling.textContent||t.previousSibling.remove(),t.previousSibling&&"BR"==t.previousSibling.nodeName){t.previousSibling.replaceWith("\n​");for(var a=t.nextSibling,o="";a;)o+=a.textContent,a=a.nextSibling;o.trim()&&yt(t.previousSibling)}else t.previousSibling&&!bt(t.previousSibling)||t.before("​")}})),t.removedNodes.forEach((function(t){t&&"BR"==t.nodeName&&ft.call(e,n)&&(e.removeTags(n),e.fixFirefoxLastTagNoCaret())}))}));var n=this.DOM.input.lastChild;n&&""==n.nodeValue&&n.remove(),n&&"BR"==n.nodeName||this.DOM.input.appendChild(document.createElement("br"))}}};function Ft(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.map((t=>t.value)),dropdown:{enabled:e.dropdownSuggestionsStartAfter,maxItems:e.dropdownMaxItems,closeOnSelect:e.dropdownCloseOnSelect,highlightFirst:e.highlight},transformTag(t){t.display||(t.display=t.value,t.value=encodeURIComponent(t.value)),t.display=t.display.replace(//g,">")},templates:{wrapper(t,e){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:t=>`
\n \n
\n ${t.display}\n
\n
`,dropdownItem:t=>`
\n ${t.display}\n
`}}}(e.id,n));o.addTags(i),void 0!==s&&o.on("input",(t=>{!function(t,e,n,i,s,a){void 0!==Xt&&Xt.abort(),Xt=new AbortController,t.whitelist=null,"number"==typeof Jt&&(t.DOM.scope.ownerDocument.defaultView.clearTimeout(Jt),Jt=void 0),s.detail.value.length{const e=s.detail.value;n.writeParameter(i,e),t.loading(!0),fetch(n.getUrl().toString(),{signal:Xt.signal}).then((t=>t.json())).catch((()=>{})).then((n=>{t.whitelist=n,t.loading(!1).dropdown.show(e)}))}),a))}(o,n.suggestionStarts,s,a,t,n.autocompleteTriggerTimeout)}))}var Gt;zt.prototype={_dropdown:Ct,placeCaretAfterNode:yt,getSetTagData:bt,helpers:{sameStr:it,removeCollectionProp:st,omit:at,isObject:dt,parseHTML:ot,escapeHTML:lt,extend:ct,concatWithoutDups:ut,getUID:pt,isNodeTag:ft},customEventsList:["change","add","remove","invalid","input","paste","click","keydown","focus","blur","edit:input","edit:beforeUpdate","edit:updated","edit:start","edit:keydown","dropdown:show","dropdown:hide","dropdown:select","dropdown:updated","dropdown:noMatch","dropdown:scroll"],dataProps:["__isValid","__removed","__originalData","__originalHTML","__tagId"],trim:function(t){return this.settings.trim&&t&&"string"==typeof t?t.trim():t},parseHTML:ot,templates:kt,parseTemplate:function(t,e){return ot((t=this.settings.templates[t]||t).apply(this,e))},set whitelist(t){var e=t&&Array.isArray(t);this.settings.whitelist=e?t:[],this.setPersistedData(e?t:[],"whitelist")},get whitelist(){return this.settings.whitelist},set userInput(t){this.settings.userInput=!!t,this.setContentEditable(!!t)},get userInput(){return this.settings.userInput},generateClassSelectors:function(t){var e=function(e){var n=e;Object.defineProperty(t,n+"Selector",{get:function(){return"."+this[n].split(" ")[0]}})};for(var n in t)e(n)},applySettings:function(t,e){var n,i;St.templates=this.templates;var s=ct({},St,"mix"==e.mode?{dropdown:{position:"text"}}:{}),a=this.settings=ct({},s,e);if(a.disabled=t.hasAttribute("disabled"),a.readonly=a.readonly||t.hasAttribute("readonly"),a.placeholder=lt(t.getAttribute("placeholder")||a.placeholder||""),a.required=t.hasAttribute("required"),this.generateClassSelectors(a.classNames),this.isIE&&(a.autoComplete=!1),["whitelist","blacklist"].forEach((function(e){var n=t.getAttribute("data-"+e);n&&Ut(n=n.split(a.delimiters),Array)&&(a[e]=n)})),"autoComplete"in e&&!dt(e.autoComplete)&&(a.autoComplete=St.autoComplete,a.autoComplete.enabled=e.autoComplete),"mix"==a.mode&&(a.pattern=a.pattern||/@/,a.autoComplete.rightKey=!0,a.delimiters=e.delimiters||null,a.tagTextProp&&!a.dropdown.searchKeys.includes(a.tagTextProp)&&a.dropdown.searchKeys.push(a.tagTextProp)),t.pattern)try{a.pattern=new RegExp(t.pattern)}catch(t){}if(a.delimiters){a._delimiters=a.delimiters;try{a.delimiters=new RegExp(this.settings.delimiters,"g")}catch(t){}}a.disabled&&(a.userInput=!1),this.TEXTS=Wt({},Lt,a.texts||{}),"select"==a.mode&&(a.dropdown.includeSelectedTags=!0),("select"!=a.mode||(null===(n=e.dropdown)||void 0===n?void 0:n.enabled))&&a.userInput||(a.dropdown.enabled=0),a.dropdown.appendTarget=(null===(i=e.dropdown)||void 0===i?void 0:i.appendTarget)||document.body,void 0===a.dropdown.includeSelectedTags&&(a.dropdown.includeSelectedTags=a.duplicates);var o=this.getPersistedData("whitelist");Array.isArray(o)&&(this.whitelist=Array.isArray(a.whitelist)?ut(a.whitelist,o):o)},getAttributes:function(t){var e,n=this.getCustomAttributes(t),i="";for(e in n)i+=" "+e+(void 0!==t[e]?'="'.concat(n[e],'"'):"");return i},getCustomAttributes:function(t){if(!dt(t))return"";var e,n={};for(e in t)"__"!=e.slice(0,2)&&"class"!=e&&t.hasOwnProperty(e)&&void 0!==t[e]&&(n[e]=lt(t[e]));return n},setStateSelection:function(){var t=window.getSelection(),e={anchorOffset:t.anchorOffset,anchorNode:t.anchorNode,range:t.getRangeAt&&t.rangeCount&&t.getRangeAt(0)};return this.state.selection=e,e},getCSSVars:function(){var t,e,n=getComputedStyle(this.DOM.scope,null);this.CSSVars={tagHideTransition:(t=function(t){if(!t)return{};var e=(t=t.trim().split(" ")[0]).split(/\d+/g).filter((function(t){return t})).pop().trim();return{value:+t.split(e).filter((function(t){return t}))[0].trim(),unit:e}}(("tag-hide-transition",n.getPropertyValue("--tag-hide-transition"))),e=t.value,"s"==t.unit?1e3*e:e)}},build:function(t){var e=this.DOM,n=t.closest("label");this.settings.mixMode.integrated?(e.originalInput=null,e.scope=t,e.input=t):(e.originalInput=t,e.originalInput_tabIndex=t.tabIndex,e.scope=this.parseTemplate("wrapper",[t,this.settings]),e.input=e.scope.querySelector(this.settings.classNames.inputSelector),t.parentNode.insertBefore(e.scope,t),t.tabIndex=-1),n&&n.setAttribute("for","")},destroy:function(){var t;this.events.unbindGlobal.call(this),null===(t=this.DOM.scope.parentNode)||void 0===t||t.removeChild(this.DOM.scope),this.DOM.originalInput.tabIndex=this.DOM.originalInput_tabIndex,delete this.DOM.originalInput.__tagify,this.dropdown.hide(!0),this.removeAllCustomListeners(),clearTimeout(this.dropdownHide__bindEventsTimeout),clearInterval(this.listeners.main.originalInputValueObserverInterval)},loadOriginalValues:function(t){var e,n=this.settings;if(this.state.blockChangeEvent=!0,void 0===t){var i=this.getPersistedData("value");t=i&&!this.DOM.originalInput.value?i:n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value}if(this.removeAllTags(),t)if("mix"==n.mode)this.parseMixTags(t),(e=this.DOM.input.lastChild)&&"BR"==e.tagName||this.DOM.input.insertAdjacentHTML("beforeend","
");else{try{Ut(JSON.parse(t),Array)&&(t=JSON.parse(t))}catch(t){}this.addTags(t,!0).forEach((function(t){return t&&t.classList.add(n.classNames.tagNoAnimation)}))}else this.postUpdate();this.state.lastOriginalValueReported=n.mixMode.integrated?"":this.DOM.originalInput.value},cloneEvent:function(t){var e={};for(var n in t)"path"!=n&&(e[n]=t[n]);return e},loading:function(t){return this.state.isLoading=t,this.DOM.scope.classList[t?"add":"remove"](this.settings.classNames.scopeLoading),this},tagLoading:function(t,e){return t&&t.classList[e?"add":"remove"](this.settings.classNames.tagLoading),this},toggleClass:function(t,e){"string"==typeof t&&this.DOM.scope.classList.toggle(t,e)},toggleScopeValidation:function(t){var e=!0===t||void 0===t;!this.settings.required&&t&&t===this.TEXTS.empty&&(e=!0),this.toggleClass(this.settings.classNames.tagInvalid,!e),this.DOM.scope.title=e?"":t},toggleFocusClass:function(t){this.toggleClass(this.settings.classNames.focus,!!t)},setPlaceholder:function(t){var e=this;["data","aria"].forEach((function(n){return e.DOM.input.setAttribute("".concat(n,"-placeholder"),t)}))},triggerChangeEvent:function(){if(!this.settings.mixMode.integrated){var t=this.DOM.originalInput,e=this.state.lastOriginalValueReported!==t.value,n=new CustomEvent("change",{bubbles:!0});e&&(this.state.lastOriginalValueReported=t.value,n.simulated=!0,t._valueTracker&&t._valueTracker.setValue(Math.random()),t.dispatchEvent(n),this.trigger("change",this.state.lastOriginalValueReported),t.value=this.state.lastOriginalValueReported)}},events:qt,fixFirefoxLastTagNoCaret:function(){},setRangeAtStartEnd:function(t,e){if(e){t="number"==typeof t?t:!!t,e=e.lastChild||e;var n=document.getSelection();if(Ut(n.focusNode,Element)&&!this.DOM.input.contains(n.focusNode))return!0;try{n.rangeCount>=1&&["Start","End"].forEach((function(i){return n.getRangeAt(0)["set"+i](e,t||e.length)}))}catch(t){console.warn(t)}}},insertAfterTag:function(t,e){if(e=e||this.settings.mixMode.insertAfterTag,t&&t.parentNode&&e)return e="string"==typeof e?document.createTextNode(e):e,t.parentNode.insertBefore(e,t.nextSibling),e},editTagChangeDetected:function(t){var e=t.__originalData;for(var n in e)if(!this.dataProps.includes(n)&&t[n]!=e[n])return!0;return!1},getTagTextNode:function(t){return t.querySelector(this.settings.classNames.tagTextSelector)},setTagTextNode:function(t,e){this.getTagTextNode(t).innerHTML=lt(e)},editTag:function(t,e){var n=this;t=t||this.getLastTag(),e=e||{};var i=this.settings,s=this.getTagTextNode(t),a=this.getNodeIndex(t),o=bt(t),r=this.events.callbacks,l=!0,d="select"==i.mode;if(!d&&this.dropdown.hide(),s){if(!Ut(o,Object)||!("editable"in o)||o.editable)return o=bt(t,{__originalData:ct({},o),__originalHTML:t.cloneNode(!0)}),bt(o.__originalHTML,o.__originalData),s.setAttribute("contenteditable",!0),t.classList.add(i.classNames.tagEditing),this.events.callbacks.onEditTagFocus.call(this,t),s.addEventListener("click",r.onEditTagClick.bind(this,t)),s.addEventListener("blur",r.onEditTagBlur.bind(this,this.getTagTextNode(t))),s.addEventListener("input",r.onEditTagInput.bind(this,s)),s.addEventListener("paste",r.onEditTagPaste.bind(this,s)),s.addEventListener("keydown",(function(e){return r.onEditTagkeydown.call(n,e,t)})),s.addEventListener("compositionstart",r.onCompositionStart.bind(this)),s.addEventListener("compositionend",r.onCompositionEnd.bind(this)),e.skipValidation||(l=this.editTagToggleValidity(t)),s.originalIsValid=l,this.trigger("edit:start",{tag:t,index:a,data:o,isValid:l}),s.focus(),!d&&this.setRangeAtStartEnd(!1,s),0===i.dropdown.enabled&&!d&&this.dropdown.show(),this.state.hasFocus=!0,this}else nt.warn("Cannot find element in Tag template: .",i.classNames.tagTextSelector)},editTagToggleValidity:function(t,e){var n;if(e=e||bt(t))return(n=!("__isValid"in e)||!0===e.__isValid)||this.removeTagsFromValue(t),this.update(),t.classList.toggle(this.settings.classNames.tagNotAllowed,!n),e.__isValid=n,e.__isValid;nt.warn("tag has no data: ",t,e)},onEditTagDone:function(t,e){t=t||this.state.editing.scope,e=e||{};var n,i,s=this.settings,a={tag:t,index:this.getNodeIndex(t),previousData:bt(t),data:e};this.trigger("edit:beforeUpdate",a,{cloneData:!1}),this.state.editing=!1,delete e.__originalData,delete e.__originalHTML,t&&t.parentNode&&((void 0!==(i=e[s.tagTextProp])?null===(n=(i+="").trim)||void 0===n?void 0:n.call(i):s.tagTextProp in e?void 0:e.value)?(t=this.replaceTag(t,e),this.editTagToggleValidity(t,e),s.a11y.focusableTags?t.focus():"select"!=s.mode&&yt(t)):this.removeTags(t)),this.trigger("edit:updated",a),s.dropdown.closeOnSelect&&this.dropdown.hide(),this.settings.keepInvalidTags&&this.reCheckInvalidTags()},replaceTag:function(t,e){e&&""!==e.value&&void 0!==e.value||(e=t.__tagifyTagData),e.__isValid&&1!=e.__isValid&&ct(e,this.getInvalidTagAttrs(e,e.__isValid));var n=this.createTagElem(e);return t.parentNode.replaceChild(n,t),this.updateValueByDOMTags(),n},updateValueByDOMTags:function(){var t=this;this.value.length=0;var e=this.settings.classNames,n=[e.tagNotAllowed.split(" ")[0],e.tagHide];[].forEach.call(this.getTagElms(),(function(e){Kt(e.classList).some((function(t){return n.includes(t)}))||t.value.push(bt(e))})),this.update(),this.dropdown.refilter()},injectAtCaret:function(t,e){var n;if(e=e||(null===(n=this.state.selection)||void 0===n?void 0:n.range),"string"==typeof t&&(t=document.createTextNode(t)),!e&&t)return this.appendMixTags(t),this;var i=wt(t,e);return this.setRangeAtStartEnd(!1,i),this.updateValueByDOMTags(),this.update(),this},input:{set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.settings,i=n.dropdown.closeOnSelect;this.state.inputText=t,e&&(this.DOM.input.innerHTML=lt(""+t),t&&this.toggleClass(n.classNames.empty,!this.DOM.input.innerHTML)),!t&&i&&this.dropdown.hide.bind(this),this.input.autocomplete.suggest.call(this),this.input.validate.call(this)},raw:function(){return this.DOM.input.textContent},validate:function(){var t=!this.state.inputText||!0===this.validateTag({value:this.state.inputText});return this.DOM.input.classList.toggle(this.settings.classNames.inputInvalid,!t),t},normalize:function(t,e){var n=t||this.DOM.input,i=[];n.childNodes.forEach((function(t){return 3==t.nodeType&&i.push(t.nodeValue)})),i=i.join("\n");try{i=i.replace(/(?:\r\n|\r|\n)/g,this.settings.delimiters.source.charAt(0))}catch(t){}return i=i.replace(/\s/g," "),(null==e?void 0:e.trim)?this.trim(i):i},autocomplete:{suggest:function(t){if(this.settings.autoComplete.enabled){"object"!=typeof(t=t||{value:""})&&(t={value:t});var e=this.dropdown.getMappedValue(t);if("number"!=typeof e){var n=this.state.inputText.toLowerCase(),i=e.substr(0,this.state.inputText.length).toLowerCase(),s=e.substring(this.state.inputText.length);e&&this.state.inputText&&i==n?(this.DOM.input.setAttribute("data-suggest",s),this.state.inputSuggestion=t):(this.DOM.input.removeAttribute("data-suggest"),delete this.state.inputSuggestion)}}},set:function(t){var e=this.DOM.input.getAttribute("data-suggest"),n=t||(e?this.state.inputText+e:null);return!!n&&("mix"==this.settings.mode?this.replaceTextWithNode(document.createTextNode(this.state.tag.prefix+n)):(this.input.set.call(this,n),this.setRangeAtStartEnd(!1,this.DOM.input)),this.input.autocomplete.suggest.call(this),this.dropdown.hide(),!0)}}},getTagIdx:function(t){return this.value.findIndex((function(e){return e.__tagId==(t||{}).__tagId}))},getNodeIndex:function(t){var e=0;if(t)for(;t=t.previousElementSibling;)e++;return e},getTagElms:function(){for(var t=arguments.length,e=new Array(t),n=0;n=this.settings.maxTags&&this.TEXTS.exceed},setReadonly:function(t,e){var n=this.settings;this.DOM.scope.contains(document.activeElement)&&document.activeElement.blur(),n[e||"readonly"]=t,this.DOM.scope[(t?"set":"remove")+"Attribute"](e||"readonly",!0),this.settings.userInput=!0,this.setContentEditable(!t)},setContentEditable:function(t){this.DOM.input.contentEditable=t,this.DOM.input.tabIndex=t?0:-1},setDisabled:function(t){this.setReadonly(t,"disabled")},normalizeTags:function(t){var e=this,n=this.settings,i=n.whitelist,s=n.delimiters,a=n.mode,o=n.tagTextProp,r=[],l=!!i&&Ut(i[0],Object),d=Array.isArray(t),c=d&&t[0].value,u=function(t){return(t+"").split(s).reduce((function(t,n){var i,s=e.trim(n);return s&&t.push(($t(i={},o,s),$t(i,"value",s),i)),t}),[])};if("number"==typeof t&&(t=t.toString()),"string"==typeof t){if(!t.trim())return[];t=u(t)}else d&&(t=t.reduce((function(t,n){if(dt(n)){var i=ct({},n);o in i||(o="value"),i[o]=e.trim(i[o]),(i[o]||0===i[o])&&t.push(i)}else if(null!=n&&""!==n&&void 0!==n){var s;(s=t).push.apply(s,Kt(u(n)))}return t}),[]));return l&&!c&&(t.forEach((function(t){var n=r.map((function(t){return t.value})),i=e.dropdown.filterListItems.call(e,t[o],{exact:!0});e.settings.duplicates||(i=i.filter((function(t){return!n.includes(t.value)})));var s=i.length>1?e.getWhitelistItem(t[o],o,i):i[0];s&&Ut(s,Object)?r.push(s):"mix"!=a&&(null==t.value&&(t.value=t[o]),r.push(t))})),r.length&&(t=r)),t},parseMixTags:function(t){var e=this,n=this.settings,i=n.mixTagsInterpolator,s=n.duplicates,a=n.transformTag,o=n.enforceWhitelist,r=n.maxTags,l=n.tagTextProp,d=[];t=t.split(i[0]).map((function(t,n){var c,u,h,g=t.split(i[1]),p=g[0],f=d.length==r;try{if(p==+p)throw Error;u=JSON.parse(p)}catch(t){u=e.normalizeTags(p)[0]||{value:p}}if(a.call(e,u),f||!(g.length>1)||o&&!e.isTagWhitelisted(u.value)||!s&&e.isTagDuplicate(u.value)){if(t)return n?i[0]+t:t}else u[c=u[l]?l:"value"]=e.trim(u[c]),h=e.createTagElem(u),d.push(u),h.classList.add(e.settings.classNames.tagNoAnimation),g[0]=h.outerHTML,e.value.push(u);return g.join("")})).join(""),this.DOM.input.innerHTML=t,this.DOM.input.appendChild(document.createTextNode("")),this.DOM.input.normalize();var c=this.getTagElms();return c.forEach((function(t,e){return bt(t,d[e])})),this.update({withoutChangeEvent:!0}),Tt(c,this.state.hasFocus),t},replaceTextWithNode:function(t,e){if(this.state.tag||e){e=e||this.state.tag.prefix+this.state.tag.value;var n,i,s=this.state.selection||window.getSelection(),a=s.anchorNode,o=this.state.tag.delimiters?this.state.tag.delimiters.length:0;return a.splitText(s.anchorOffset-o),-1==(n=a.nodeValue.lastIndexOf(e))||(i=a.splitText(n),t&&a.parentNode.replaceChild(t,i)),!0}},prepareNewTagNode:function(t,e){e=e||{};var n=this.settings,i=[],s={},a=Object.assign({},t,{value:t.value+""});if(t=Object.assign({},a),n.transformTag.call(this,t),t.__isValid=this.hasMaxTags()||this.validateTag(t),!0!==t.__isValid){if(e.skipInvalid)return;if(ct(s,this.getInvalidTagAttrs(t,t.__isValid),{__preInvalidData:a}),t.__isValid==this.TEXTS.duplicate&&this.flashTag(this.getTagElmByValue(t.value)),!n.createInvalidTags)return void i.push(t.value)}return"readonly"in t&&(t.readonly?s["aria-readonly"]=!0:delete t.readonly),{tagElm:this.createTagElem(t,s),tagData:t,aggregatedInvalidInput:i}},postProcessNewTagNode:function(t,e){var n=this,i=this.settings,s=e.__isValid;s&&!0===s?this.value.push(e):(this.trigger("invalid",{data:e,index:this.value.length,tag:t,message:s}),i.keepInvalidTags||setTimeout((function(){return n.removeTags(t,!0)}),1e3)),this.dropdown.position()},selectTag:function(t,e){var n=this;if(!this.settings.enforceWhitelist||this.isTagWhitelisted(e.value)){this.state.actions.selectOption&&setTimeout((function(){return n.setRangeAtStartEnd(!1,n.DOM.input)}));var i=this.getLastTag();return i?this.replaceTag(i,e):this.appendTag(t),this.value[0]=e,this.update(),this.trigger("add",{tag:t,data:e}),[t]}},addEmptyTag:function(t){var e=ct({value:""},t||{}),n=this.createTagElem(e);bt(n,e),this.appendTag(n),this.editTag(n,{skipValidation:!0}),this.toggleFocusClass(!0)},addTags:function(t,e,n){var i=this,s=[],a=this.settings,o=[],r=document.createDocumentFragment(),l=[];if(!t||0==t.length)return s;switch(t=this.normalizeTags(t),a.mode){case"mix":return this.addMixTags(t);case"select":e=!1,this.removeAllTags()}return this.DOM.input.removeAttribute("style"),t.forEach((function(t){var e=i.prepareNewTagNode(t,{skipInvalid:n||a.skipInvalid});if(e){var d=e.tagElm;if(t=e.tagData,o=e.aggregatedInvalidInput,s.push(d),"select"==a.mode)return i.selectTag(d,t);r.appendChild(d),i.postProcessNewTagNode(d,t),l.push({tagElm:d,tagData:t})}})),this.appendTag(r),l.forEach((function(t){var e=t.tagElm,n=t.tagData;return i.trigger("add",{tag:e,index:i.getTagIdx(n),data:n})})),this.update(),t.length&&e&&(this.input.set.call(this,a.createInvalidTags?"":o.join(a._delimiters)),this.setRangeAtStartEnd(!1,this.DOM.input)),this.dropdown.refilter(),s},addMixTags:function(t){var e=this;if((t=this.normalizeTags(t))[0].prefix||this.state.tag)return this.prefixedTextToTag(t[0]);var n=document.createDocumentFragment();return t.forEach((function(t){var i=e.prepareNewTagNode(t);n.appendChild(i.tagElm),e.insertAfterTag(i.tagElm),e.postProcessNewTagNode(i.tagElm,i.tagData)})),this.appendMixTags(n),n.children},appendMixTags:function(t){var e=!!this.state.selection;e?this.injectAtCaret(t):(this.DOM.input.focus(),(e=this.setStateSelection()).range.setStart(this.DOM.input,e.range.endOffset),e.range.setEnd(this.DOM.input,e.range.endOffset),this.DOM.input.appendChild(t),this.updateValueByDOMTags(),this.update())},prefixedTextToTag:function(t){var e,n,i,s=this,a=this.settings,o=null===(e=this.state.tag)||void 0===e?void 0:e.delimiters;if(t.prefix=t.prefix||this.state.tag?this.state.tag.prefix:(a.pattern.source||a.pattern)[0],i=this.prepareNewTagNode(t),n=i.tagElm,this.replaceTextWithNode(n)||this.DOM.input.appendChild(n),setTimeout((function(){return n.classList.add(s.settings.classNames.tagNoAnimation)}),300),this.update(),!o){var r=this.insertAfterTag(n)||n;setTimeout(yt,0,r)}return this.state.tag=null,this.postProcessNewTagNode(n,i.tagData),n},appendTag:function(t){var e=this.DOM,n=e.input;e.scope.insertBefore(t,n)},createTagElem:function(t,e){t.__tagId=pt();var n,i=ct({},t,Wt({value:lt(t.value+"")},e));return function(t){for(var e,n=document.createNodeIterator(t,NodeFilter.SHOW_TEXT,null,!1);e=n.nextNode();)e.textContent.trim()||e.parentNode.removeChild(e)}(n=this.parseTemplate("tag",[i,this])),bt(n,t),n},reCheckInvalidTags:function(){var t=this,e=this.settings;this.getTagElms(e.classNames.tagNotAllowed).forEach((function(n,i){var s=bt(n),a=t.hasMaxTags(),o=t.validateTag(s),r=!0===o&&!a;if("select"==e.mode&&t.toggleScopeValidation(o),r)return s=s.__preInvalidData?s.__preInvalidData:{value:s.value},t.replaceTag(n,s);n.title=a||o}))},removeTags:function(t,e,n){var i,s=this,a=this.settings;if(t=t&&Ut(t,HTMLElement)?[t]:Ut(t,Array)?t:t?[t]:[this.getLastTag()].filter((function(t){return t})),i=t.reduce((function(t,e){e&&"string"==typeof e&&(e=s.getTagElmByValue(e));var n=bt(e);return e&&n&&!n.readonly&&t.push({node:e,idx:s.getTagIdx(n),data:bt(e,{__removed:!0})}),t}),[]),n="number"==typeof n?n:this.CSSVars.tagHideTransition,"select"==a.mode&&(n=0,this.input.set.call(this)),1==i.length&&"select"!=a.mode&&i[0].node.classList.contains(a.classNames.tagNotAllowed)&&(e=!0),i.length)return a.hooks.beforeRemoveTag(i,{tagify:this}).then((function(){var t=function(t){t.node.parentNode&&(t.node.parentNode.removeChild(t.node),e?a.keepInvalidTags&&this.trigger("remove",{tag:t.node,index:t.idx}):(this.trigger("remove",{tag:t.node,index:t.idx,data:t.data}),this.dropdown.refilter(),this.dropdown.position(),this.DOM.input.normalize(),a.keepInvalidTags&&this.reCheckInvalidTags()))};n&&n>10&&1==i.length?function(e){e.node.style.width=parseFloat(window.getComputedStyle(e.node).width)+"px",document.body.clientTop,e.node.classList.add(a.classNames.tagHide),setTimeout(t.bind(this),n,e)}.call(s,i[0]):i.forEach(t.bind(s)),e||(s.removeTagsFromValue(i.map((function(t){return t.node}))),s.update(),"select"==a.mode&&a.userInput&&s.setContentEditable(!0))})).catch((function(t){}))},removeTagsFromDOM:function(){this.getTagElms().forEach((function(t){return t.remove()}))},removeTagsFromValue:function(t){var e=this;(t=Array.isArray(t)?t:[t]).forEach((function(t){var n=bt(t),i=e.getTagIdx(n);i>-1&&e.value.splice(i,1)}))},removeAllTags:function(t){var e=this;t=t||{},this.value=[],"mix"==this.settings.mode?this.DOM.input.innerHTML="":this.removeTagsFromDOM(),this.dropdown.refilter(),this.dropdown.position(),this.state.dropdown.visible&&setTimeout((function(){e.DOM.input.focus()})),"select"==this.settings.mode&&(this.input.set.call(this),this.settings.userInput&&this.setContentEditable(!0)),this.update(t)},postUpdate:function(){this.state.blockChangeEvent=!1;var t,e,n=this.settings,i=n.classNames,s="mix"==n.mode?n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value.trim():this.value.length+this.input.raw.call(this).length;this.toggleClass(i.hasMaxTags,this.value.length>=n.maxTags),this.toggleClass(i.hasNoTags,!this.value.length),this.toggleClass(i.empty,!s),"select"==n.mode&&this.toggleScopeValidation(null===(e=this.value)||void 0===e||null===(t=e[0])||void 0===t?void 0:t.__isValid)},setOriginalInputValue:function(t){var e=this.DOM.originalInput;this.settings.mixMode.integrated||(e.value=t,e.tagifyValue=e.value,this.setPersistedData(t,"value"))},update:function(t){clearTimeout(this.debouncedUpdateTimeout),this.debouncedUpdateTimeout=setTimeout(function(){var e=this.getInputValue();this.setOriginalInputValue(e),this.settings.onChangeAfterBlur&&(t||{}).withoutChangeEvent||this.state.blockChangeEvent||this.triggerChangeEvent(),this.postUpdate()}.bind(this),100),this.events.bindOriginaInputListener.call(this,100)},getInputValue:function(){var t=this.getCleanValue();return"mix"==this.settings.mode?this.getMixedTagsAsString(t):t.length?this.settings.originalInputValueFormat?this.settings.originalInputValueFormat(t):JSON.stringify(t):""},getCleanValue:function(t){return st(t||this.value,this.dataProps)},getMixedTagsAsString:function(){var t="",e=this,n=this.settings,i=n.originalInputValueFormat||JSON.stringify,s=n.mixTagsInterpolator;return function n(a){a.childNodes.forEach((function(a){if(1==a.nodeType){var o=bt(a);if("BR"==a.tagName&&(t+="\r\n"),o&&ft.call(e,a)){if(o.__removed)return;t+=s[0]+i(at(o,e.dataProps))+s[1]}else a.getAttribute("style")||["B","I","U"].includes(a.tagName)?t+=a.textContent:"DIV"!=a.tagName&&"P"!=a.tagName||(t+="\r\n",n(a))}else t+=a.textContent}))}(this.DOM.input),t}},zt.prototype.removeTag=zt.prototype.removeTags,e.UI=e.UI||{},e.UI.Input=e.UI.Input||{},(Gt=e.UI.Input).textarea=new o,Gt.markdown=new w,Gt.treeSelect=new G(new Y(t),e.UI.menu.drilldown,{txt:t=>e.Language.txt(t)},n),Gt.tagInput=Gt.tag||{},Gt.tagInput.init=(t,e,n,i,s)=>Qt(zt,t,e,n,i,s)}($,il,document); + */var Z="​";function tt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);n/g,">").replace(/"/g,""").replace(/`|'/g,"'"):t}function dt(t){var e=Object.prototype.toString.call(t).split(" ")[1].slice(0,-1);return t===Object(t)&&"Array"!=e&&"Function"!=e&&"RegExp"!=e&&"HTMLUnknownElement"!=e}function ct(t,e,n){var i,s;function a(t,e){for(var n in e)if(e.hasOwnProperty(n)){if(dt(e[n])){dt(t[n])?a(t[n],e[n]):t[n]=Object.assign({},e[n]);continue}if(Array.isArray(e[n])){t[n]=Object.assign([],e[n]);continue}t[n]=e[n]}}return i=t,(null!=(s=Object)&&"undefined"!=typeof Symbol&&s[Symbol.hasInstance]?s[Symbol.hasInstance](i):i instanceof s)||(t={}),a(t,e),n&&a(t,n),t}function ut(){var t=[],e={},n=!0,i=!1,s=void 0;try{for(var a,o=arguments[Symbol.iterator]();!(n=(a=o.next()).done);n=!0){var r=a.value,l=!0,d=!1,c=void 0;try{for(var u,h=r[Symbol.iterator]();!(l=(u=h.next()).done);l=!0){var g=u.value;dt(g)?e[g.value]||(t.push(g),e[g.value]=1):t.includes(g)||t.push(g)}}catch(t){d=!0,c=t}finally{try{l||null==h.return||h.return()}finally{if(d)throw c}}}}catch(t){i=!0,s=t}finally{try{n||null==o.return||o.return()}finally{if(i)throw s}}return t}function ht(t){return String.prototype.normalize?"string"==typeof t?t.normalize("NFD").replace(/[\u0300-\u036f]/g,""):void 0:t}var gt=function(){return/(?=.*chrome)(?=.*android)/i.test(navigator.userAgent)};function pt(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,(function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)}))}function ft(t){var e;return vt.call(this,t)&&(null==t||null===(e=t.classList)||void 0===e?void 0:e.contains(this.settings.classNames.tag))}function mt(t){return vt.call(this,t)&&(null==t?void 0:t.closest(this.settings.classNames.tagSelector))}function vt(t){var e;return(null==t||null===(e=t.closest)||void 0===e?void 0:e.call(t,this.settings.classNames.namespaceSelector))===this.DOM.scope}function wt(t,e){var n=window.getSelection();return e=e||n.getRangeAt(0),"string"==typeof t&&(t=document.createTextNode(t)),e&&(e.deleteContents(),e.insertNode(t)),t}function bt(t,e,n){return t?(e&&(t.__tagifyTagData=n?e:ct({},t.__tagifyTagData||{},e)),t.__tagifyTagData):(nt.warn("tag element doesn't exist",{tagElm:t,data:e}),e)}function yt(t){if(t&&t.parentNode){var e=t,n=window.getSelection(),i=n.getRangeAt(0);n.rangeCount&&(i.setStartAfter(e),i.collapse(!0),n.removeAllRanges(),n.addRange(i))}}function Tt(t,e){t.forEach((function(t){if(bt(t.previousSibling)||!t.previousSibling){var n=document.createTextNode("​");t.before(n),e&&yt(n)}}))}var St={delimiters:",",pattern:null,tagTextProp:"value",maxTags:1/0,callbacks:{},addTagOnBlur:!0,addTagOn:["blur","tab","enter"],onChangeAfterBlur:!0,duplicates:!1,whitelist:[],blacklist:[],enforceWhitelist:!1,userInput:!0,focusable:!0,keepInvalidTags:!1,createInvalidTags:!0,mixTagsAllowedAfter:/,|\.|\:|\s/,mixTagsInterpolator:["[[","]]"],backspace:!0,skipInvalid:!1,pasteAsTags:!0,editTags:{clicks:2,keepInvalid:!0},transformTag:function(){},trim:!0,a11y:{focusableTags:!1},mixMode:{insertAfterTag:"Ā "},autoComplete:{enabled:!0,rightKey:!1,tabKey:!1},classNames:{namespace:"tagify",mixMode:"tagify--mix",selectMode:"tagify--select",input:"tagify__input",focus:"tagify--focus",tagNoAnimation:"tagify--noAnim",tagInvalid:"tagify--invalid",tagNotAllowed:"tagify--notAllowed",scopeLoading:"tagify--loading",hasMaxTags:"tagify--hasMaxTags",hasNoTags:"tagify--noTags",empty:"tagify--empty",inputInvalid:"tagify__input--invalid",dropdown:"tagify__dropdown",dropdownWrapper:"tagify__dropdown__wrapper",dropdownHeader:"tagify__dropdown__header",dropdownFooter:"tagify__dropdown__footer",dropdownItem:"tagify__dropdown__item",dropdownItemActive:"tagify__dropdown__item--active",dropdownItemHidden:"tagify__dropdown__item--hidden",dropdownItemSelected:"tagify__dropdown__item--selected",dropdownInital:"tagify__dropdown--initial",tag:"tagify__tag",tagText:"tagify__tag-text",tagX:"tagify__tag__removeBtn",tagLoading:"tagify__tag--loading",tagEditing:"tagify__tag--editable",tagFlash:"tagify__tag--flash",tagHide:"tagify__tag--hide"},dropdown:{classname:"",enabled:2,maxItems:10,searchKeys:["value","searchBy"],fuzzySearch:!0,caseSensitive:!1,accentedSearch:!0,includeSelectedTags:!1,escapeHTML:!0,highlightFirst:!0,closeOnSelect:!0,clearOnSelect:!0,position:"all",appendTarget:null},hooks:{beforeRemoveTag:function(){return Promise.resolve()},beforePaste:function(){return Promise.resolve()},suggestionClick:function(){return Promise.resolve()},beforeKeyDown:function(){return Promise.resolve()}}};function xt(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function Et(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],e=this.dropdown.events.callbacks,n=this.listeners.dropdown=this.listeners.dropdown||{position:this.dropdown.position.bind(this,null),onKeyDown:e.onKeyDown.bind(this),onMouseOver:e.onMouseOver.bind(this),onMouseLeave:e.onMouseLeave.bind(this),onClick:e.onClick.bind(this),onScroll:e.onScroll.bind(this)},i=t?"addEventListener":"removeEventListener";"manual"!=this.settings.dropdown.position&&(document[i]("scroll",n.position,!0),window[i]("resize",n.position),window[i]("keydown",n.onKeyDown)),this.DOM.dropdown[i]("mouseover",n.onMouseOver),this.DOM.dropdown[i]("mouseleave",n.onMouseLeave),this.DOM.dropdown[i]("mousedown",n.onClick),this.DOM.dropdown.content[i]("scroll",n.onScroll)},callbacks:{onKeyDown:function(t){var e=this;if(this.state.hasFocus&&!this.state.composing){var n=this.settings,i=n.dropdown.includeSelectedTags,s=this.DOM.dropdown.querySelector(n.classNames.dropdownItemActiveSelector),a=this.dropdown.getSuggestionDataByNode(s),o="mix"==n.mode,r="select"==n.mode;n.hooks.beforeKeyDown(t,{tagify:this}).then((function(l){switch(t.key){case"ArrowDown":case"ArrowUp":case"Down":case"Up":t.preventDefault();var d=e.dropdown.getAllSuggestionsRefs(),c="ArrowUp"==t.key||"Up"==t.key;s&&(s=e.dropdown.getNextOrPrevOption(s,!c)),s&&s.matches(n.classNames.dropdownItemSelector)||(s=d[c?d.length-1:0]),e.dropdown.highlightOption(s,!0);break;case"PageUp":case"PageDown":var u;t.preventDefault();var h=e.dropdown.getAllSuggestionsRefs(),g=Math.floor(e.DOM.dropdown.content.clientHeight/(null===(u=h[0])||void 0===u?void 0:u.offsetHeight))||1,p="PageUp"===t.key;if(s){var f=h.indexOf(s),m=p?Math.max(0,f-g):Math.min(h.length-1,f+g);s=h[m]}else s=h[0];e.dropdown.highlightOption(s,!0);break;case"Home":case"End":t.preventDefault();var v=e.dropdown.getAllSuggestionsRefs();s=v["Home"===t.key?0:v.length-1],e.dropdown.highlightOption(s,!0);break;case"Escape":case"Esc":e.dropdown.hide();break;case"ArrowRight":if(e.state.actions.ArrowLeft||n.autoComplete.rightKey)return;case"Tab":var w=!n.autoComplete.rightKey||!n.autoComplete.tabKey;if(!o&&!r&&s&&w&&!e.state.editing&&a){t.preventDefault();var b=e.dropdown.getMappedValue(a);return e.state.autoCompleteData=a,e.input.autocomplete.set.call(e,b),!1}return!0;case"Enter":t.preventDefault(),e.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),n.hooks.suggestionClick(t,{tagify:e,tagData:a,suggestionElm:s}).then((function(){if(s){var n=i?s:e.dropdown.getNextOrPrevOption(s,!c);e.dropdown.selectOption(s,t,(function(){if(n){var t=n.getAttribute("value");n=e.dropdown.getSuggestionNodeByValue(t),e.dropdown.highlightOption(n)}}))}else e.dropdown.hide(),o||e.addTags(e.state.inputText.trim(),!0)})).catch((function(t){return nt.warn(t)}));break;case"Backspace":if(o||e.state.editing.scope)return;var y=e.input.raw.call(e);""!=y&&8203!=y.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0))}}))}},onMouseOver:function(t){var e=t.target.closest(this.settings.classNames.dropdownItemSelector);this.dropdown.highlightOption(e)},onMouseLeave:function(t){this.dropdown.highlightOption()},onClick:function(t){var e=this;if(0==t.button&&t.target!=this.DOM.dropdown&&t.target!=this.DOM.dropdown.content){var n=t.target.closest(this.settings.classNames.dropdownItemSelector),i=this.dropdown.getSuggestionDataByNode(n);this.state.actions.selectOption=!0,setTimeout((function(){return e.state.actions.selectOption=!1}),100),this.settings.hooks.suggestionClick(t,{tagify:this,tagData:i,suggestionElm:n}).then((function(){n?e.dropdown.selectOption(n,t):e.dropdown.hide()})).catch((function(t){return nt.warn(t)}))}},onScroll:function(t){var e=t.target,n=e.scrollTop/(e.scrollHeight-e.parentNode.clientHeight)*100;this.trigger("dropdown:scroll",{percentage:Math.round(n)})}}},refilter:function(t){t=t||this.state.dropdown.query||"",this.suggestedListItems=this.dropdown.filterListItems(t),this.dropdown.fill(),this.suggestedListItems.length||this.dropdown.hide(),this.trigger("dropdown:updated",this.DOM.dropdown)},getSuggestionDataByNode:function(t){for(var e,n=t&&t.getAttribute("value"),i=this.suggestedListItems.length;i--;){if(dt(e=this.suggestedListItems[i])&&e.value==n)return e;if(e==n)return{value:e}}},getSuggestionNodeByValue:function(t){return this.dropdown.getAllSuggestionsRefs().find((function(e){return e.getAttribute("value")===t}))},getNextOrPrevOption:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.dropdown.getAllSuggestionsRefs(),i=n.findIndex((function(e){return e===t}));return e?n[i+1]:n[i-1]},highlightOption:function(t,e){var n,i=this.settings.classNames.dropdownItemActive;if(this.state.ddItemElm&&(this.state.ddItemElm.classList.remove(i),this.state.ddItemElm.removeAttribute("aria-selected")),!t)return this.state.ddItemData=null,this.state.ddItemElm=null,void this.input.autocomplete.suggest.call(this);n=this.dropdown.getSuggestionDataByNode(t),this.state.ddItemData=n,this.state.ddItemElm=t,t.classList.add(i),t.setAttribute("aria-selected",!0),e&&(t.parentNode.scrollTop=t.clientHeight+t.offsetTop-t.parentNode.clientHeight),this.settings.autoComplete&&(this.input.autocomplete.suggest.call(this,n),this.dropdown.position())},selectOption:function(t,e,n){var i=this,s=this.settings,a=s.dropdown.includeSelectedTags,o=s.dropdown,r=o.clearOnSelect,l=o.closeOnSelect;if(!t)return this.addTags(this.state.inputText,!0),void(l&&this.dropdown.hide());e=e||{};var d=t.getAttribute("value"),c="noMatch"==d,u="mix"==s.mode,h=this.suggestedListItems.find((function(t){var e;return(null!==(e=t.value)&&void 0!==e?e:t)==d}));if(this.trigger("dropdown:select",{data:h,elm:t,event:e}),h||c){if(this.state.editing){var g=this.normalizeTags([h])[0];h=s.transformTag.call(this,g)||g,this.onEditTagDone(null,ct({__isValid:!0},h))}else this[u?"addMixTags":"addTags"]([h||this.input.raw.call(this)],r);(u||this.DOM.input.parentNode)&&(setTimeout((function(){i.DOM.input.focus(),i.toggleFocusClass(!0)})),l&&setTimeout(this.dropdown.hide.bind(this)),a?n&&n():(t.addEventListener("transitionend",(function(){i.dropdown.fillHeaderFooter(),setTimeout((function(){t.remove(),i.dropdown.refilter(),n&&n()}),100)}),{once:!0}),t.classList.add(this.settings.classNames.dropdownItemHidden)))}else l&&setTimeout(this.dropdown.hide.bind(this))},selectAll:function(t){this.suggestedListItems.length=0,this.dropdown.hide(),this.dropdown.filterListItems("");var e=this.dropdown.filterListItems("");return t||(e=this.state.dropdown.suggestions),this.addTags(e,!0),this},filterListItems:function(t,e){var n,i,s,a,o,r,l=function(){var t,l,d=void 0,c=void 0;t=p[b],i=(null!=(l=Object)&&"undefined"!=typeof Symbol&&l[Symbol.hasInstance]?l[Symbol.hasInstance](t):t instanceof l)?p[b]:{value:p[b]};var f,m=Object.keys(i).some((function(t){return w.includes(t)}))?w:["value"];u.fuzzySearch&&!e.exact?(a=m.reduce((function(t,e){return t+" "+(i[e]||"")}),"").toLowerCase().trim(),u.accentedSearch&&(a=ht(a),r=ht(r)),d=0==a.indexOf(r),c=a===r,f=a,s=r.toLowerCase().split(" ").every((function(t){return f.includes(t.toLowerCase())}))):(d=!0,s=m.some((function(t){var n=""+(i[t]||"");return u.accentedSearch&&(n=ht(n),r=ht(r)),u.caseSensitive||(n=n.toLowerCase()),c=n===r,e.exact?n===r:0==n.indexOf(r)}))),o=!u.includeSelectedTags&&n.isTagDuplicate(dt(i)?i.value:i),s&&!o&&(c&&d?g.push(i):"startsWith"==u.sortby&&d?h.unshift(i):h.push(i))},d=this,c=this.settings,u=c.dropdown,h=(e=e||{},[]),g=[],p=c.whitelist,f=u.maxItems>=0?u.maxItems:1/0,m=u.includeSelectedTags,v="function"==typeof u.sortby,w=u.searchKeys,b=0;if(!(t="select"==c.mode&&this.value.length&&this.value[0][c.tagTextProp]==t?"":t)||!w.length){h=m?p:p.filter((function(t){return!d.isTagDuplicate(dt(t)?t.value:t)}));var y=v?u.sortby(h,r):h.slice(0,f);return this.state.dropdown.suggestions=y,y}for(r=u.caseSensitive?""+t:(""+t).toLowerCase();b[\r\n ]+\<").split(/>\s+<").trim():""},fillHeaderFooter:function(){var t=this.dropdown.filterListItems(this.state.dropdown.query),e=this.parseTemplate("dropdownHeader",[t]),n=this.parseTemplate("dropdownFooter",[t]),i=this.dropdown.getHeaderRef(),s=this.dropdown.getFooterRef();e&&(null==i||i.parentNode.replaceChild(e,i)),n&&(null==s||s.parentNode.replaceChild(n,s))},position:function(t){var e=this.settings.dropdown,n=this.dropdown.getAppendTarget();if("manual"!=e.position&&n){var i,s,a,o,r,l,d,c,u,h,g=this.DOM.dropdown,p=e.RTL,f=n===document.body,m=n===this.DOM.scope,v=f?window.pageYOffset:n.scrollTop,w=document.fullscreenElement||document.webkitFullscreenElement||document.documentElement,b=w.clientHeight,y=Math.max(w.clientWidth||0,window.innerWidth||0),T=y>480?e.position:"all",S=this.DOM["input"==T?"input":"scope"];if(t=t||g.clientHeight,this.state.dropdown.visible){if("text"==T?(a=(i=function(){var t=document.getSelection();if(t.rangeCount){var e,n,i=t.getRangeAt(0),s=i.startContainer,a=i.startOffset;if(a>0)return(n=document.createRange()).setStart(s,a-1),n.setEnd(s,a),{left:(e=n.getBoundingClientRect()).right,top:e.top,bottom:e.bottom};if(s.getBoundingClientRect)return s.getBoundingClientRect()}return{left:-9999,top:-9999}}()).bottom,s=i.top,o=i.left,r="auto"):(l=function(t){var e=0,n=0;for(t=t.parentNode;t&&t!=w;)e+=t.offsetTop||0,n+=t.offsetLeft||0,t=t.parentNode;return{top:e,left:n}}(n),i=S.getBoundingClientRect(),s=m?-1:i.top-l.top,a=(m?i.height:i.bottom-l.top)-1,o=m?-1:i.left-l.left,r=i.width+"px"),!f){var x=function(){for(var t=0,n=e.appendTarget.parentNode;n;)t+=n.scrollTop||0,n=n.parentNode;return t}();s+=x,a+=x}var E;s=Math.floor(s),a=Math.ceil(a),c=y-o<120,u=((d=null!==(E=e.placeAbove)&&void 0!==E?E:b-i.bottom\n ').concat(this.settings.templates.input.call(this),"\n ").concat(Z,"\n ")},input:function(){var t=this.settings,e=t.placeholder||Z;return"')},tag:function(t,e){var n=e.settings;return'\n \n
\n ').concat(t[n.tagTextProp]||t.value,"\n
\n
")},dropdown:function(t){var e=t.dropdown,n="manual"==e.position;return'
\n
\n
')},dropdownContent:function(t){var e=this.settings.templates,n=this.state.dropdown.suggestions;return"\n ".concat(e.dropdownHeader.call(this,n),"\n ").concat(t,"\n ").concat(e.dropdownFooter.call(this,n),"\n ")},dropdownItem:function(t){return"
').concat(t.mappedValue||t.value,"
")},dropdownHeader:function(t){return"
')},dropdownFooter:function(t){var e=t.length-this.settings.dropdown.maxItems;return e>0?"
\n ').concat(e," more items. Refine your search.\n
"):""},dropdownItemNoMatch:null};function Bt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.length)&&(e=t.length);for(var n=0,i=new Array(e);n0&&void 0!==arguments[0])||arguments[0],n=this.settings,i=this.events.callbacks,s=e?"addEventListener":"removeEventListener";if(!this.state.mainEvents||!e){for(var a in this.state.mainEvents=e,e&&!this.listeners.main&&(this.events.bindGlobal.call(this),this.settings.isJQueryPlugin&&jQuery(this.DOM.originalInput).on("tagify.removeAllTags",this.removeAllTags.bind(this))),t=this.listeners.main=this.listeners.main||{keydown:["input",i.onKeydown.bind(this)],click:["scope",i.onClickScope.bind(this)],dblclick:"select"!=n.mode&&["scope",i.onDoubleClickScope.bind(this)],paste:["input",i.onPaste.bind(this)],drop:["input",i.onDrop.bind(this)],compositionstart:["input",i.onCompositionStart.bind(this)],compositionend:["input",i.onCompositionEnd.bind(this)]})t[a]&&this.DOM[t[a][0]][s](a,t[a][1]);var o=this.listeners.main.inputMutationObserver||new MutationObserver(i.onInputDOMChange.bind(this));o.disconnect(),"mix"==n.mode&&o.observe(this.DOM.input,{childList:!0}),this.events.bindOriginaInputListener.call(this)}},bindOriginaInputListener:function(t){var e=(t||0)+500;this.listeners.main&&(clearInterval(this.listeners.main.originalInputValueObserverInterval),this.listeners.main.originalInputValueObserverInterval=setInterval(this.events.callbacks.observeOriginalInputValue.bind(this),e))},bindGlobal:function(t){var e,n=this.events.callbacks,i=t?"removeEventListener":"addEventListener";if(this.listeners&&(t||!this.listeners.global)){this.listeners.global=this.listeners.global||[{type:this.isIE?"keydown":"input",target:this.DOM.input,cb:n[this.isIE?"onInputIE":"onInput"].bind(this)},{type:"keydown",target:window,cb:n.onWindowKeyDown.bind(this)},{type:"focusin",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"focusout",target:this.DOM.scope,cb:n.onFocusBlur.bind(this)},{type:"click",target:document,cb:n.onClickAnywhere.bind(this),useCapture:!0}];var s=!0,a=!1,o=void 0;try{for(var r,l=this.listeners.global[Symbol.iterator]();!(s=(r=l.next()).done);s=!0)(e=r.value).target[i](e.type,e.cb,!!e.useCapture)}catch(t){a=!0,o=t}finally{try{s||null==l.return||l.return()}finally{if(a)throw o}}}},unbindGlobal:function(){this.events.bindGlobal.call(this,!0)},callbacks:{onFocusBlur:function(t){var e,n,i=this.settings,s=mt.call(this,t.relatedTarget),a=ft.call(this,t.relatedTarget),o=t.target.classList.contains(i.classNames.tagX),r="focusin"==t.type,l="focusout"==t.type;o&&"mix"!=i.mode&&this.DOM.input.focus(),s&&r&&!a&&!o&&this.toggleFocusClass(this.state.hasFocus=+new Date);var d=t.target?this.trim(this.DOM.input.textContent):"",c=null===(n=this.value)||void 0===n||null===(e=n[0])||void 0===e?void 0:e[i.tagTextProp],u=i.dropdown.enabled>=0,h={relatedTarget:t.relatedTarget},g=this.state.actions.selectOption&&(u||!i.dropdown.closeOnSelect),p=this.state.actions.addNew&&u;if(l){if(t.relatedTarget===this.DOM.scope)return this.dropdown.hide(),void this.DOM.input.focus();this.postUpdate(),i.onChangeAfterBlur&&this.triggerChangeEvent()}if(!(g||p||o))if(this.state.hasFocus=!(!r&&!s)&&+new Date,this.toggleFocusClass(this.state.hasFocus),"mix"!=i.mode){if(r){if(!i.focusable)return;var f=0===i.dropdown.enabled&&!this.state.dropdown.visible,m=!a||"select"===i.mode,v=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector);return this.trigger("focus",h),void(f&&m&&(this.dropdown.show(this.value.length?"":void 0),this.setRangeAtStartEnd(!1,v)))}if(l){if(this.trigger("blur",h),this.loading(!1),"select"==i.mode){if(this.value.length){var w=this.getTagElms()[0];d=this.trim(w.textContent)}c===d&&(d="")}d&&!this.state.actions.selectOption&&i.addTagOnBlur&&i.addTagOn.includes("blur")&&this.addTags(d,!0)}s||(this.DOM.input.removeAttribute("style"),this.dropdown.hide())}else r?this.trigger("focus",h):l&&(this.trigger("blur",h),this.loading(!1),this.dropdown.hide(),this.state.dropdown.visible=void 0,this.setStateSelection())},onCompositionStart:function(t){this.state.composing=!0},onCompositionEnd:function(t){this.state.composing=!1},onWindowKeyDown:function(t){var e,n=this.settings,i=document.activeElement,s=mt.call(this,i)&&this.DOM.scope.contains(i),a=i===this.DOM.input,o=s&&i.hasAttribute("readonly"),r=this.DOM.scope.querySelector(this.settings.classNames.tagTextSelector),l=this.state.dropdown.visible;if(("Tab"===t.key&&l||this.state.hasFocus||s&&!o)&&!a){e=i.nextElementSibling;var d=t.target.classList.contains(n.classNames.tagX);switch(t.key){case"Backspace":n.readonly||this.state.editing||(this.removeTags(i),(e||this.DOM.input).focus());break;case"Enter":if(d)return void this.removeTags(t.target.parentNode);n.a11y.focusableTags&&ft.call(this,i)&&setTimeout(this.editTag.bind(this),0,i);break;case"ArrowDown":this.state.dropdown.visible||"mix"==n.mode||this.dropdown.show();break;case"Tab":null==r||r.focus()}}},onKeydown:function(t){var e=this,n=this.settings;if(!this.state.composing&&n.userInput){"select"==n.mode&&n.enforceWhitelist&&this.value.length&&"Tab"!=t.key&&t.preventDefault();var i=this.trim(t.target.textContent);this.trigger("keydown",{event:t}),n.hooks.beforeKeyDown(t,{tagify:this}).then((function(s){if("mix"==n.mode){switch(t.key){case"Left":case"ArrowLeft":e.state.actions.ArrowLeft=!0;break;case"Delete":case"Backspace":if(e.state.editing)return;var a=document.getSelection(),o="Delete"==t.key&&a.anchorOffset==(a.anchorNode.length||0),r=a.anchorNode.previousSibling,l=1==a.anchorNode.nodeType||!a.anchorOffset&&r&&1==r.nodeType&&a.anchorNode.previousSibling;!function(t){var e=document.createElement("div");t.replace(/\&#?[0-9a-z]+;/gi,(function(t){return e.innerHTML=t,e.innerText}))}(e.DOM.input.innerHTML);var d,c,u,h=e.getTagElms(),g=1===a.anchorNode.length&&a.anchorNode.nodeValue==String.fromCharCode(8203);if("edit"==n.backspace&&l)return d=1==a.anchorNode.nodeType?null:a.anchorNode.previousElementSibling,setTimeout(e.editTag.bind(e),0,d),void t.preventDefault();if(gt()&&Ht(l,Element))return u=rt(l),l.hasAttribute("readonly")||l.remove(),e.DOM.input.focus(),void setTimeout((function(){yt(u),e.DOM.input.click()}));if("BR"==a.anchorNode.nodeName)return;if((o||l)&&1==a.anchorNode.nodeType?c=0==a.anchorOffset?o?h[0]:null:h[Math.min(h.length,a.anchorOffset)-1]:o?c=a.anchorNode.nextElementSibling:Ht(l,Element)&&(c=l),3==a.anchorNode.nodeType&&!a.anchorNode.nodeValue&&a.anchorNode.previousElementSibling&&t.preventDefault(),(l||o)&&!n.backspace)return void t.preventDefault();if("Range"!=a.type&&!a.anchorOffset&&a.anchorNode==e.DOM.input&&"Delete"!=t.key)return void t.preventDefault();if("Range"!=a.type&&c&&c.hasAttribute("readonly"))return void yt(rt(c));"Delete"==t.key&&g&&bt(a.anchorNode.nextSibling)&&e.removeTags(a.anchorNode.nextSibling)}return!0}var p="manual"==n.dropdown.position;switch(t.key){case"Backspace":"select"==n.mode&&n.enforceWhitelist&&e.value.length?e.removeTags():e.state.dropdown.visible&&"manual"!=n.dropdown.position||""!=t.target.textContent&&8203!=i.charCodeAt(0)||(!0===n.backspace?e.removeTags():"edit"==n.backspace&&setTimeout(e.editTag.bind(e),0));break;case"Esc":case"Escape":if(e.state.dropdown.visible)return;t.target.blur();break;case"Down":case"ArrowDown":e.state.dropdown.visible||e.dropdown.show();break;case"ArrowRight":var f=e.state.inputSuggestion||e.state.ddItemData;if(f&&n.autoComplete.rightKey)return void e.addTags([f],!0);break;case"Tab":return!0;case"Enter":if(e.state.dropdown.visible&&!p)return;t.preventDefault();var m=e.state.autoCompleteData||i;setTimeout((function(){e.state.dropdown.visible&&!p||e.state.actions.selectOption||!n.addTagOn.includes(t.key.toLowerCase())||(e.addTags([m],!0),e.state.autoCompleteData=null)}))}})).catch((function(t){return t}))}},onInput:function(t){this.postUpdate();var e=this.settings;if("mix"==e.mode)return this.events.callbacks.onMixTagsInput.call(this,t);var n=this.input.normalize.call(this,void 0,{trim:!1}),i=n.length>=e.dropdown.enabled,s={value:n,inputElm:this.DOM.input},a=this.validateTag({value:n});"select"==e.mode&&this.toggleScopeValidation(a),s.isValid=a,this.state.inputText!=n&&(this.input.set.call(this,n,!1),-1!=n.search(e.delimiters)?this.addTags(n)&&this.input.set.call(this):e.dropdown.enabled>=0&&this.dropdown[i?"show":"hide"](n),this.trigger("input",s))},onMixTagsInput:function(t){var e,n,i,s,a,o,r,l,d=this,c=this.settings,u=this.value.length,h=this.getTagElms(),g=document.createDocumentFragment(),p=window.getSelection().getRangeAt(0),f=[].map.call(h,(function(t){return bt(t).value}));if("deleteContentBackward"==t.inputType&>()&&this.events.callbacks.onKeydown.call(this,{target:t.target,key:"Backspace"}),Tt(this.getTagElms()),this.value.slice().forEach((function(t){t.readonly&&!f.includes(t.value)&&g.appendChild(d.createTagElem(t))})),g.childNodes.length&&(p.insertNode(g),this.setRangeAtStartEnd(!1,g.lastChild)),h.length!=u)return this.value=[].map.call(this.getTagElms(),(function(t){return bt(t)})),void this.update({withoutChangeEvent:!0});if(this.hasMaxTags())return!0;if(window.getSelection&&(o=window.getSelection()).rangeCount>0&&3==o.anchorNode.nodeType){if((p=o.getRangeAt(0).cloneRange()).collapse(!0),p.setStart(o.focusNode,0),i=(e=p.toString().slice(0,p.endOffset)).split(c.pattern).length-1,(n=e.match(c.pattern))&&(s=e.slice(e.lastIndexOf(n[n.length-1]))),s){if(this.state.actions.ArrowLeft=!1,this.state.tag={prefix:s.match(c.pattern)[0],value:s.replace(c.pattern,"")},this.state.tag.baseOffset=o.baseOffset-this.state.tag.value.length,l=this.state.tag.value.match(c.delimiters))return this.state.tag.value=this.state.tag.value.replace(c.delimiters,""),this.state.tag.delimiters=l[0],this.addTags(this.state.tag.value,c.dropdown.clearOnSelect),void this.dropdown.hide();a=this.state.tag.value.length>=c.dropdown.enabled;try{r=(r=this.state.flaggedTags[this.state.tag.baseOffset]).prefix==this.state.tag.prefix&&r.value[0]==this.state.tag.value[0],this.state.flaggedTags[this.state.tag.baseOffset]&&!this.state.tag.value&&delete this.state.flaggedTags[this.state.tag.baseOffset]}catch(t){}(r||i500||!e.focusable)?this.state.dropdown.visible?this.dropdown.hide():0===e.dropdown.enabled&&"mix"!=e.mode&&this.dropdown.show(this.value.length?"":void 0):"select"!=e.mode||0!==e.dropdown.enabled||this.state.dropdown.visible||(this.events.callbacks.onDoubleClickScope.call(this,function(t,e){return e=null!=e?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):function(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);n.push.apply(n,i)}return n}(Object(e)).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t}(function(t){for(var e=1;e=this.settings.dropdown.enabled&&(this.state.editing&&(this.state.editing.value=o),this.dropdown.show(o)),this.trigger("edit:input",{tag:i,index:s,data:ct({},this.value[s],{newValue:o}),event:e})},onEditTagPaste:function(t,e){var n=(e.clipboardData||window.clipboardData).getData("Text");e.preventDefault();var i=wt(n);this.setRangeAtStartEnd(!1,i)},onEditTagClick:function(t,e){this.events.callbacks.onClickScope.call(this,e)},onEditTagFocus:function(t){this.state.editing={scope:t,input:t.querySelector("[contenteditable]")}},onEditTagBlur:function(t,e){var n=ft.call(this,e.relatedTarget);if("select"==this.settings.mode&&n&&e.relatedTarget.contains(e.target))this.dropdown.hide();else if(this.state.editing&&(this.state.hasFocus||this.toggleFocusClass(),this.DOM.scope.contains(document.activeElement)||this.trigger("blur",{}),this.DOM.scope.contains(t))){var i,s,a,o=this.settings,r=t.closest("."+o.classNames.tag),l=bt(r),d=this.input.normalize.call(this,t),c=(Vt(i={},o.tagTextProp,d),Vt(i,"__tagId",l.__tagId),i),u=l.__originalData,h=this.editTagChangeDetected(ct(l,c)),g=this.validateTag(c);if(d)if(h){var p;if(s=this.hasMaxTags(),a=ct({},u,(Vt(p={},o.tagTextProp,this.trim(d)),Vt(p,"__isValid",g),p)),o.transformTag.call(this,a,u),!0!==(g=(!s||!0===u.__isValid)&&this.validateTag(a))){if(this.trigger("invalid",{data:a,tag:r,message:g}),o.editTags.keepInvalid)return;o.keepInvalidTags?a.__isValid=g:a=u}else o.keepInvalidTags&&(delete a.title,delete a["aria-invalid"],delete a.class);this.onEditTagDone(r,a)}else this.onEditTagDone(r,u);else this.onEditTagDone(r)}},onEditTagkeydown:function(t,e){if(!this.state.composing)switch(this.trigger("edit:keydown",{event:t}),t.key){case"Esc":case"Escape":this.state.editing=!1,e.__tagifyTagData.__originalData.value?e.parentNode.replaceChild(e.__tagifyTagData.__originalHTML,e):e.remove();break;case"Enter":case"Tab":t.preventDefault(),setTimeout((function(){return t.target.blur()}),0)}},onDoubleClickScope:function(t){var e=t.target.closest("."+this.settings.classNames.tag);if(e){var n,i,s=bt(e),a=this.settings;!1!==(null==s?void 0:s.editable)&&(n=e.classList.contains(this.settings.classNames.tagEditing),i=e.hasAttribute("readonly"),a.readonly||n||i||!this.settings.editTags||!a.userInput||(this.events.callbacks.onEditTagFocus.call(this,e),this.editTag(e)),this.toggleFocusClass(!0),"select"!=a.mode&&this.trigger("dblclick",{tag:e,index:this.getNodeIndex(e),data:bt(e)}))}},onInputDOMChange:function(t){var e=this;t.forEach((function(t){t.addedNodes.forEach((function(t){if("

"==t.outerHTML)t.replaceWith(document.createElement("br"));else if(1==t.nodeType&&t.querySelector(e.settings.classNames.tagSelector)){var n,i=document.createTextNode("");3==t.childNodes[0].nodeType&&"BR"!=t.previousSibling.nodeName&&(i=document.createTextNode("\n")),(n=t).replaceWith.apply(n,Rt([i].concat(Rt(Rt(t.childNodes).slice(0,-1))))),yt(i)}else if(ft.call(e,t)){var s;if(3!=(null===(s=t.previousSibling)||void 0===s?void 0:s.nodeType)||t.previousSibling.textContent||t.previousSibling.remove(),t.previousSibling&&"BR"==t.previousSibling.nodeName){t.previousSibling.replaceWith("\n​");for(var a=t.nextSibling,o="";a;)o+=a.textContent,a=a.nextSibling;o.trim()&&yt(t.previousSibling)}else t.previousSibling&&!bt(t.previousSibling)||t.before("​")}})),t.removedNodes.forEach((function(t){t&&"BR"==t.nodeName&&ft.call(e,n)&&(e.removeTags(n),e.fixFirefoxLastTagNoCaret())}))}));var n=this.DOM.input.lastChild;n&&""==n.nodeValue&&n.remove(),n&&"BR"==n.nodeName||this.DOM.input.appendChild(document.createElement("br"))}}};function Ft(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=new Array(e);nt.map((t=>t.value)),dropdown:{enabled:e.dropdownSuggestionsStartAfter,maxItems:e.dropdownMaxItems,closeOnSelect:e.dropdownCloseOnSelect,highlightFirst:e.highlight},transformTag(t){t.display||(t.display=t.value,t.value=encodeURIComponent(t.value)),t.display=t.display.replace(//g,">")},templates:{wrapper(t,e){return`
\n ${this.settings.templates.input.call(this)}\n ​\n
`},tag:t=>`
\n \n
\n ${t.display}\n
\n
`,dropdownItem:t=>`
\n ${t.display}\n
`}}}(e.id,n));o.addTags(i),void 0!==s&&o.on("input",(t=>{!function(t,e,n,i,s,a){Xt instanceof AbortController&&Xt.abort(),Xt=new AbortController,t.whitelist=null,void 0!==Jt&&(t.DOM.scope.ownerDocument.defaultView.clearTimeout(Jt),Jt=void 0),s.detail.value.length{const e=s.detail.value;n.writeParameter(i,e),t.loading(!0),fetch(n.getUrl().toString(),{signal:Xt.signal}).then((t=>t.json())).catch((()=>{})).then((n=>{t.whitelist=n,t.loading(!1).dropdown.show(e)}))}),a))}(o,n.suggestionStarts,s,a,t,n.autocompleteTriggerTimeout)}))}var Gt;zt.prototype={_dropdown:Ct,placeCaretAfterNode:yt,getSetTagData:bt,helpers:{sameStr:it,removeCollectionProp:st,omit:at,isObject:dt,parseHTML:ot,escapeHTML:lt,extend:ct,concatWithoutDups:ut,getUID:pt,isNodeTag:ft},customEventsList:["change","add","remove","invalid","input","paste","click","keydown","focus","blur","edit:input","edit:beforeUpdate","edit:updated","edit:start","edit:keydown","dropdown:show","dropdown:hide","dropdown:select","dropdown:updated","dropdown:noMatch","dropdown:scroll"],dataProps:["__isValid","__removed","__originalData","__originalHTML","__tagId"],trim:function(t){return this.settings.trim&&t&&"string"==typeof t?t.trim():t},parseHTML:ot,templates:kt,parseTemplate:function(t,e){return ot((t=this.settings.templates[t]||t).apply(this,e))},set whitelist(t){var e=t&&Array.isArray(t);this.settings.whitelist=e?t:[],this.setPersistedData(e?t:[],"whitelist")},get whitelist(){return this.settings.whitelist},set userInput(t){this.settings.userInput=!!t,this.setContentEditable(!!t)},get userInput(){return this.settings.userInput},generateClassSelectors:function(t){var e=function(e){var n=e;Object.defineProperty(t,n+"Selector",{get:function(){return"."+this[n].split(" ")[0]}})};for(var n in t)e(n)},applySettings:function(t,e){var n,i;St.templates=this.templates;var s=ct({},St,"mix"==e.mode?{dropdown:{position:"text"}}:{}),a=this.settings=ct({},s,e);if(a.disabled=t.hasAttribute("disabled"),a.readonly=a.readonly||t.hasAttribute("readonly"),a.placeholder=lt(t.getAttribute("placeholder")||a.placeholder||""),a.required=t.hasAttribute("required"),this.generateClassSelectors(a.classNames),this.isIE&&(a.autoComplete=!1),["whitelist","blacklist"].forEach((function(e){var n=t.getAttribute("data-"+e);n&&Ut(n=n.split(a.delimiters),Array)&&(a[e]=n)})),"autoComplete"in e&&!dt(e.autoComplete)&&(a.autoComplete=St.autoComplete,a.autoComplete.enabled=e.autoComplete),"mix"==a.mode&&(a.pattern=a.pattern||/@/,a.autoComplete.rightKey=!0,a.delimiters=e.delimiters||null,a.tagTextProp&&!a.dropdown.searchKeys.includes(a.tagTextProp)&&a.dropdown.searchKeys.push(a.tagTextProp)),t.pattern)try{a.pattern=new RegExp(t.pattern)}catch(t){}if(a.delimiters){a._delimiters=a.delimiters;try{a.delimiters=new RegExp(this.settings.delimiters,"g")}catch(t){}}a.disabled&&(a.userInput=!1),this.TEXTS=Wt({},Lt,a.texts||{}),"select"==a.mode&&(a.dropdown.includeSelectedTags=!0),("select"!=a.mode||(null===(n=e.dropdown)||void 0===n?void 0:n.enabled))&&a.userInput||(a.dropdown.enabled=0),a.dropdown.appendTarget=(null===(i=e.dropdown)||void 0===i?void 0:i.appendTarget)||document.body,void 0===a.dropdown.includeSelectedTags&&(a.dropdown.includeSelectedTags=a.duplicates);var o=this.getPersistedData("whitelist");Array.isArray(o)&&(this.whitelist=Array.isArray(a.whitelist)?ut(a.whitelist,o):o)},getAttributes:function(t){var e,n=this.getCustomAttributes(t),i="";for(e in n)i+=" "+e+(void 0!==t[e]?'="'.concat(n[e],'"'):"");return i},getCustomAttributes:function(t){if(!dt(t))return"";var e,n={};for(e in t)"__"!=e.slice(0,2)&&"class"!=e&&t.hasOwnProperty(e)&&void 0!==t[e]&&(n[e]=lt(t[e]));return n},setStateSelection:function(){var t=window.getSelection(),e={anchorOffset:t.anchorOffset,anchorNode:t.anchorNode,range:t.getRangeAt&&t.rangeCount&&t.getRangeAt(0)};return this.state.selection=e,e},getCSSVars:function(){var t,e,n=getComputedStyle(this.DOM.scope,null);this.CSSVars={tagHideTransition:(t=function(t){if(!t)return{};var e=(t=t.trim().split(" ")[0]).split(/\d+/g).filter((function(t){return t})).pop().trim();return{value:+t.split(e).filter((function(t){return t}))[0].trim(),unit:e}}(("tag-hide-transition",n.getPropertyValue("--tag-hide-transition"))),e=t.value,"s"==t.unit?1e3*e:e)}},build:function(t){var e=this.DOM,n=t.closest("label");this.settings.mixMode.integrated?(e.originalInput=null,e.scope=t,e.input=t):(e.originalInput=t,e.originalInput_tabIndex=t.tabIndex,e.scope=this.parseTemplate("wrapper",[t,this.settings]),e.input=e.scope.querySelector(this.settings.classNames.inputSelector),t.parentNode.insertBefore(e.scope,t),t.tabIndex=-1),n&&n.setAttribute("for","")},destroy:function(){var t;this.events.unbindGlobal.call(this),null===(t=this.DOM.scope.parentNode)||void 0===t||t.removeChild(this.DOM.scope),this.DOM.originalInput.tabIndex=this.DOM.originalInput_tabIndex,delete this.DOM.originalInput.__tagify,this.dropdown.hide(!0),this.removeAllCustomListeners(),clearTimeout(this.dropdownHide__bindEventsTimeout),clearInterval(this.listeners.main.originalInputValueObserverInterval)},loadOriginalValues:function(t){var e,n=this.settings;if(this.state.blockChangeEvent=!0,void 0===t){var i=this.getPersistedData("value");t=i&&!this.DOM.originalInput.value?i:n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value}if(this.removeAllTags(),t)if("mix"==n.mode)this.parseMixTags(t),(e=this.DOM.input.lastChild)&&"BR"==e.tagName||this.DOM.input.insertAdjacentHTML("beforeend","
");else{try{Ut(JSON.parse(t),Array)&&(t=JSON.parse(t))}catch(t){}this.addTags(t,!0).forEach((function(t){return t&&t.classList.add(n.classNames.tagNoAnimation)}))}else this.postUpdate();this.state.lastOriginalValueReported=n.mixMode.integrated?"":this.DOM.originalInput.value},cloneEvent:function(t){var e={};for(var n in t)"path"!=n&&(e[n]=t[n]);return e},loading:function(t){return this.state.isLoading=t,this.DOM.scope.classList[t?"add":"remove"](this.settings.classNames.scopeLoading),this},tagLoading:function(t,e){return t&&t.classList[e?"add":"remove"](this.settings.classNames.tagLoading),this},toggleClass:function(t,e){"string"==typeof t&&this.DOM.scope.classList.toggle(t,e)},toggleScopeValidation:function(t){var e=!0===t||void 0===t;!this.settings.required&&t&&t===this.TEXTS.empty&&(e=!0),this.toggleClass(this.settings.classNames.tagInvalid,!e),this.DOM.scope.title=e?"":t},toggleFocusClass:function(t){this.toggleClass(this.settings.classNames.focus,!!t)},setPlaceholder:function(t){var e=this;["data","aria"].forEach((function(n){return e.DOM.input.setAttribute("".concat(n,"-placeholder"),t)}))},triggerChangeEvent:function(){if(!this.settings.mixMode.integrated){var t=this.DOM.originalInput,e=this.state.lastOriginalValueReported!==t.value,n=new CustomEvent("change",{bubbles:!0});e&&(this.state.lastOriginalValueReported=t.value,n.simulated=!0,t._valueTracker&&t._valueTracker.setValue(Math.random()),t.dispatchEvent(n),this.trigger("change",this.state.lastOriginalValueReported),t.value=this.state.lastOriginalValueReported)}},events:qt,fixFirefoxLastTagNoCaret:function(){},setRangeAtStartEnd:function(t,e){if(e){t="number"==typeof t?t:!!t,e=e.lastChild||e;var n=document.getSelection();if(Ut(n.focusNode,Element)&&!this.DOM.input.contains(n.focusNode))return!0;try{n.rangeCount>=1&&["Start","End"].forEach((function(i){return n.getRangeAt(0)["set"+i](e,t||e.length)}))}catch(t){console.warn(t)}}},insertAfterTag:function(t,e){if(e=e||this.settings.mixMode.insertAfterTag,t&&t.parentNode&&e)return e="string"==typeof e?document.createTextNode(e):e,t.parentNode.insertBefore(e,t.nextSibling),e},editTagChangeDetected:function(t){var e=t.__originalData;for(var n in e)if(!this.dataProps.includes(n)&&t[n]!=e[n])return!0;return!1},getTagTextNode:function(t){return t.querySelector(this.settings.classNames.tagTextSelector)},setTagTextNode:function(t,e){this.getTagTextNode(t).innerHTML=lt(e)},editTag:function(t,e){var n=this;t=t||this.getLastTag(),e=e||{};var i=this.settings,s=this.getTagTextNode(t),a=this.getNodeIndex(t),o=bt(t),r=this.events.callbacks,l=!0,d="select"==i.mode;if(!d&&this.dropdown.hide(),s){if(!Ut(o,Object)||!("editable"in o)||o.editable)return o=bt(t,{__originalData:ct({},o),__originalHTML:t.cloneNode(!0)}),bt(o.__originalHTML,o.__originalData),s.setAttribute("contenteditable",!0),t.classList.add(i.classNames.tagEditing),this.events.callbacks.onEditTagFocus.call(this,t),s.addEventListener("click",r.onEditTagClick.bind(this,t)),s.addEventListener("blur",r.onEditTagBlur.bind(this,this.getTagTextNode(t))),s.addEventListener("input",r.onEditTagInput.bind(this,s)),s.addEventListener("paste",r.onEditTagPaste.bind(this,s)),s.addEventListener("keydown",(function(e){return r.onEditTagkeydown.call(n,e,t)})),s.addEventListener("compositionstart",r.onCompositionStart.bind(this)),s.addEventListener("compositionend",r.onCompositionEnd.bind(this)),e.skipValidation||(l=this.editTagToggleValidity(t)),s.originalIsValid=l,this.trigger("edit:start",{tag:t,index:a,data:o,isValid:l}),s.focus(),!d&&this.setRangeAtStartEnd(!1,s),0===i.dropdown.enabled&&!d&&this.dropdown.show(),this.state.hasFocus=!0,this}else nt.warn("Cannot find element in Tag template: .",i.classNames.tagTextSelector)},editTagToggleValidity:function(t,e){var n;if(e=e||bt(t))return(n=!("__isValid"in e)||!0===e.__isValid)||this.removeTagsFromValue(t),this.update(),t.classList.toggle(this.settings.classNames.tagNotAllowed,!n),e.__isValid=n,e.__isValid;nt.warn("tag has no data: ",t,e)},onEditTagDone:function(t,e){t=t||this.state.editing.scope,e=e||{};var n,i,s=this.settings,a={tag:t,index:this.getNodeIndex(t),previousData:bt(t),data:e};this.trigger("edit:beforeUpdate",a,{cloneData:!1}),this.state.editing=!1,delete e.__originalData,delete e.__originalHTML,t&&t.parentNode&&((void 0!==(i=e[s.tagTextProp])?null===(n=(i+="").trim)||void 0===n?void 0:n.call(i):s.tagTextProp in e?void 0:e.value)?(t=this.replaceTag(t,e),this.editTagToggleValidity(t,e),s.a11y.focusableTags?t.focus():"select"!=s.mode&&yt(t)):this.removeTags(t)),this.trigger("edit:updated",a),s.dropdown.closeOnSelect&&this.dropdown.hide(),this.settings.keepInvalidTags&&this.reCheckInvalidTags()},replaceTag:function(t,e){e&&""!==e.value&&void 0!==e.value||(e=t.__tagifyTagData),e.__isValid&&1!=e.__isValid&&ct(e,this.getInvalidTagAttrs(e,e.__isValid));var n=this.createTagElem(e);return t.parentNode.replaceChild(n,t),this.updateValueByDOMTags(),n},updateValueByDOMTags:function(){var t=this;this.value.length=0;var e=this.settings.classNames,n=[e.tagNotAllowed.split(" ")[0],e.tagHide];[].forEach.call(this.getTagElms(),(function(e){Kt(e.classList).some((function(t){return n.includes(t)}))||t.value.push(bt(e))})),this.update(),this.dropdown.refilter()},injectAtCaret:function(t,e){var n;if(e=e||(null===(n=this.state.selection)||void 0===n?void 0:n.range),"string"==typeof t&&(t=document.createTextNode(t)),!e&&t)return this.appendMixTags(t),this;var i=wt(t,e);return this.setRangeAtStartEnd(!1,i),this.updateValueByDOMTags(),this.update(),this},input:{set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this.settings,i=n.dropdown.closeOnSelect;this.state.inputText=t,e&&(this.DOM.input.innerHTML=lt(""+t),t&&this.toggleClass(n.classNames.empty,!this.DOM.input.innerHTML)),!t&&i&&this.dropdown.hide.bind(this),this.input.autocomplete.suggest.call(this),this.input.validate.call(this)},raw:function(){return this.DOM.input.textContent},validate:function(){var t=!this.state.inputText||!0===this.validateTag({value:this.state.inputText});return this.DOM.input.classList.toggle(this.settings.classNames.inputInvalid,!t),t},normalize:function(t,e){var n=t||this.DOM.input,i=[];n.childNodes.forEach((function(t){return 3==t.nodeType&&i.push(t.nodeValue)})),i=i.join("\n");try{i=i.replace(/(?:\r\n|\r|\n)/g,this.settings.delimiters.source.charAt(0))}catch(t){}return i=i.replace(/\s/g," "),(null==e?void 0:e.trim)?this.trim(i):i},autocomplete:{suggest:function(t){if(this.settings.autoComplete.enabled){"object"!=typeof(t=t||{value:""})&&(t={value:t});var e=this.dropdown.getMappedValue(t);if("number"!=typeof e){var n=this.state.inputText.toLowerCase(),i=e.substr(0,this.state.inputText.length).toLowerCase(),s=e.substring(this.state.inputText.length);e&&this.state.inputText&&i==n?(this.DOM.input.setAttribute("data-suggest",s),this.state.inputSuggestion=t):(this.DOM.input.removeAttribute("data-suggest"),delete this.state.inputSuggestion)}}},set:function(t){var e=this.DOM.input.getAttribute("data-suggest"),n=t||(e?this.state.inputText+e:null);return!!n&&("mix"==this.settings.mode?this.replaceTextWithNode(document.createTextNode(this.state.tag.prefix+n)):(this.input.set.call(this,n),this.setRangeAtStartEnd(!1,this.DOM.input)),this.input.autocomplete.suggest.call(this),this.dropdown.hide(),!0)}}},getTagIdx:function(t){return this.value.findIndex((function(e){return e.__tagId==(t||{}).__tagId}))},getNodeIndex:function(t){var e=0;if(t)for(;t=t.previousElementSibling;)e++;return e},getTagElms:function(){for(var t=arguments.length,e=new Array(t),n=0;n=this.settings.maxTags&&this.TEXTS.exceed},setReadonly:function(t,e){var n=this.settings;this.DOM.scope.contains(document.activeElement)&&document.activeElement.blur(),n[e||"readonly"]=t,this.DOM.scope[(t?"set":"remove")+"Attribute"](e||"readonly",!0),this.settings.userInput=!0,this.setContentEditable(!t)},setContentEditable:function(t){this.DOM.input.contentEditable=t,this.DOM.input.tabIndex=t?0:-1},setDisabled:function(t){this.setReadonly(t,"disabled")},normalizeTags:function(t){var e=this,n=this.settings,i=n.whitelist,s=n.delimiters,a=n.mode,o=n.tagTextProp,r=[],l=!!i&&Ut(i[0],Object),d=Array.isArray(t),c=d&&t[0].value,u=function(t){return(t+"").split(s).reduce((function(t,n){var i,s=e.trim(n);return s&&t.push(($t(i={},o,s),$t(i,"value",s),i)),t}),[])};if("number"==typeof t&&(t=t.toString()),"string"==typeof t){if(!t.trim())return[];t=u(t)}else d&&(t=t.reduce((function(t,n){if(dt(n)){var i=ct({},n);o in i||(o="value"),i[o]=e.trim(i[o]),(i[o]||0===i[o])&&t.push(i)}else if(null!=n&&""!==n&&void 0!==n){var s;(s=t).push.apply(s,Kt(u(n)))}return t}),[]));return l&&!c&&(t.forEach((function(t){var n=r.map((function(t){return t.value})),i=e.dropdown.filterListItems.call(e,t[o],{exact:!0});e.settings.duplicates||(i=i.filter((function(t){return!n.includes(t.value)})));var s=i.length>1?e.getWhitelistItem(t[o],o,i):i[0];s&&Ut(s,Object)?r.push(s):"mix"!=a&&(null==t.value&&(t.value=t[o]),r.push(t))})),r.length&&(t=r)),t},parseMixTags:function(t){var e=this,n=this.settings,i=n.mixTagsInterpolator,s=n.duplicates,a=n.transformTag,o=n.enforceWhitelist,r=n.maxTags,l=n.tagTextProp,d=[];t=t.split(i[0]).map((function(t,n){var c,u,h,g=t.split(i[1]),p=g[0],f=d.length==r;try{if(p==+p)throw Error;u=JSON.parse(p)}catch(t){u=e.normalizeTags(p)[0]||{value:p}}if(a.call(e,u),f||!(g.length>1)||o&&!e.isTagWhitelisted(u.value)||!s&&e.isTagDuplicate(u.value)){if(t)return n?i[0]+t:t}else u[c=u[l]?l:"value"]=e.trim(u[c]),h=e.createTagElem(u),d.push(u),h.classList.add(e.settings.classNames.tagNoAnimation),g[0]=h.outerHTML,e.value.push(u);return g.join("")})).join(""),this.DOM.input.innerHTML=t,this.DOM.input.appendChild(document.createTextNode("")),this.DOM.input.normalize();var c=this.getTagElms();return c.forEach((function(t,e){return bt(t,d[e])})),this.update({withoutChangeEvent:!0}),Tt(c,this.state.hasFocus),t},replaceTextWithNode:function(t,e){if(this.state.tag||e){e=e||this.state.tag.prefix+this.state.tag.value;var n,i,s=this.state.selection||window.getSelection(),a=s.anchorNode,o=this.state.tag.delimiters?this.state.tag.delimiters.length:0;return a.splitText(s.anchorOffset-o),-1==(n=a.nodeValue.lastIndexOf(e))||(i=a.splitText(n),t&&a.parentNode.replaceChild(t,i)),!0}},prepareNewTagNode:function(t,e){e=e||{};var n=this.settings,i=[],s={},a=Object.assign({},t,{value:t.value+""});if(t=Object.assign({},a),n.transformTag.call(this,t),t.__isValid=this.hasMaxTags()||this.validateTag(t),!0!==t.__isValid){if(e.skipInvalid)return;if(ct(s,this.getInvalidTagAttrs(t,t.__isValid),{__preInvalidData:a}),t.__isValid==this.TEXTS.duplicate&&this.flashTag(this.getTagElmByValue(t.value)),!n.createInvalidTags)return void i.push(t.value)}return"readonly"in t&&(t.readonly?s["aria-readonly"]=!0:delete t.readonly),{tagElm:this.createTagElem(t,s),tagData:t,aggregatedInvalidInput:i}},postProcessNewTagNode:function(t,e){var n=this,i=this.settings,s=e.__isValid;s&&!0===s?this.value.push(e):(this.trigger("invalid",{data:e,index:this.value.length,tag:t,message:s}),i.keepInvalidTags||setTimeout((function(){return n.removeTags(t,!0)}),1e3)),this.dropdown.position()},selectTag:function(t,e){var n=this;if(!this.settings.enforceWhitelist||this.isTagWhitelisted(e.value)){this.state.actions.selectOption&&setTimeout((function(){return n.setRangeAtStartEnd(!1,n.DOM.input)}));var i=this.getLastTag();return i?this.replaceTag(i,e):this.appendTag(t),this.value[0]=e,this.update(),this.trigger("add",{tag:t,data:e}),[t]}},addEmptyTag:function(t){var e=ct({value:""},t||{}),n=this.createTagElem(e);bt(n,e),this.appendTag(n),this.editTag(n,{skipValidation:!0}),this.toggleFocusClass(!0)},addTags:function(t,e,n){var i=this,s=[],a=this.settings,o=[],r=document.createDocumentFragment(),l=[];if(!t||0==t.length)return s;switch(t=this.normalizeTags(t),a.mode){case"mix":return this.addMixTags(t);case"select":e=!1,this.removeAllTags()}return this.DOM.input.removeAttribute("style"),t.forEach((function(t){var e=i.prepareNewTagNode(t,{skipInvalid:n||a.skipInvalid});if(e){var d=e.tagElm;if(t=e.tagData,o=e.aggregatedInvalidInput,s.push(d),"select"==a.mode)return i.selectTag(d,t);r.appendChild(d),i.postProcessNewTagNode(d,t),l.push({tagElm:d,tagData:t})}})),this.appendTag(r),l.forEach((function(t){var e=t.tagElm,n=t.tagData;return i.trigger("add",{tag:e,index:i.getTagIdx(n),data:n})})),this.update(),t.length&&e&&(this.input.set.call(this,a.createInvalidTags?"":o.join(a._delimiters)),this.setRangeAtStartEnd(!1,this.DOM.input)),this.dropdown.refilter(),s},addMixTags:function(t){var e=this;if((t=this.normalizeTags(t))[0].prefix||this.state.tag)return this.prefixedTextToTag(t[0]);var n=document.createDocumentFragment();return t.forEach((function(t){var i=e.prepareNewTagNode(t);n.appendChild(i.tagElm),e.insertAfterTag(i.tagElm),e.postProcessNewTagNode(i.tagElm,i.tagData)})),this.appendMixTags(n),n.children},appendMixTags:function(t){var e=!!this.state.selection;e?this.injectAtCaret(t):(this.DOM.input.focus(),(e=this.setStateSelection()).range.setStart(this.DOM.input,e.range.endOffset),e.range.setEnd(this.DOM.input,e.range.endOffset),this.DOM.input.appendChild(t),this.updateValueByDOMTags(),this.update())},prefixedTextToTag:function(t){var e,n,i,s=this,a=this.settings,o=null===(e=this.state.tag)||void 0===e?void 0:e.delimiters;if(t.prefix=t.prefix||this.state.tag?this.state.tag.prefix:(a.pattern.source||a.pattern)[0],i=this.prepareNewTagNode(t),n=i.tagElm,this.replaceTextWithNode(n)||this.DOM.input.appendChild(n),setTimeout((function(){return n.classList.add(s.settings.classNames.tagNoAnimation)}),300),this.update(),!o){var r=this.insertAfterTag(n)||n;setTimeout(yt,0,r)}return this.state.tag=null,this.postProcessNewTagNode(n,i.tagData),n},appendTag:function(t){var e=this.DOM,n=e.input;e.scope.insertBefore(t,n)},createTagElem:function(t,e){t.__tagId=pt();var n,i=ct({},t,Wt({value:lt(t.value+"")},e));return function(t){for(var e,n=document.createNodeIterator(t,NodeFilter.SHOW_TEXT,null,!1);e=n.nextNode();)e.textContent.trim()||e.parentNode.removeChild(e)}(n=this.parseTemplate("tag",[i,this])),bt(n,t),n},reCheckInvalidTags:function(){var t=this,e=this.settings;this.getTagElms(e.classNames.tagNotAllowed).forEach((function(n,i){var s=bt(n),a=t.hasMaxTags(),o=t.validateTag(s),r=!0===o&&!a;if("select"==e.mode&&t.toggleScopeValidation(o),r)return s=s.__preInvalidData?s.__preInvalidData:{value:s.value},t.replaceTag(n,s);n.title=a||o}))},removeTags:function(t,e,n){var i,s=this,a=this.settings;if(t=t&&Ut(t,HTMLElement)?[t]:Ut(t,Array)?t:t?[t]:[this.getLastTag()].filter((function(t){return t})),i=t.reduce((function(t,e){e&&"string"==typeof e&&(e=s.getTagElmByValue(e));var n=bt(e);return e&&n&&!n.readonly&&t.push({node:e,idx:s.getTagIdx(n),data:bt(e,{__removed:!0})}),t}),[]),n="number"==typeof n?n:this.CSSVars.tagHideTransition,"select"==a.mode&&(n=0,this.input.set.call(this)),1==i.length&&"select"!=a.mode&&i[0].node.classList.contains(a.classNames.tagNotAllowed)&&(e=!0),i.length)return a.hooks.beforeRemoveTag(i,{tagify:this}).then((function(){var t=function(t){t.node.parentNode&&(t.node.parentNode.removeChild(t.node),e?a.keepInvalidTags&&this.trigger("remove",{tag:t.node,index:t.idx}):(this.trigger("remove",{tag:t.node,index:t.idx,data:t.data}),this.dropdown.refilter(),this.dropdown.position(),this.DOM.input.normalize(),a.keepInvalidTags&&this.reCheckInvalidTags()))};n&&n>10&&1==i.length?function(e){e.node.style.width=parseFloat(window.getComputedStyle(e.node).width)+"px",document.body.clientTop,e.node.classList.add(a.classNames.tagHide),setTimeout(t.bind(this),n,e)}.call(s,i[0]):i.forEach(t.bind(s)),e||(s.removeTagsFromValue(i.map((function(t){return t.node}))),s.update(),"select"==a.mode&&a.userInput&&s.setContentEditable(!0))})).catch((function(t){}))},removeTagsFromDOM:function(){this.getTagElms().forEach((function(t){return t.remove()}))},removeTagsFromValue:function(t){var e=this;(t=Array.isArray(t)?t:[t]).forEach((function(t){var n=bt(t),i=e.getTagIdx(n);i>-1&&e.value.splice(i,1)}))},removeAllTags:function(t){var e=this;t=t||{},this.value=[],"mix"==this.settings.mode?this.DOM.input.innerHTML="":this.removeTagsFromDOM(),this.dropdown.refilter(),this.dropdown.position(),this.state.dropdown.visible&&setTimeout((function(){e.DOM.input.focus()})),"select"==this.settings.mode&&(this.input.set.call(this),this.settings.userInput&&this.setContentEditable(!0)),this.update(t)},postUpdate:function(){this.state.blockChangeEvent=!1;var t,e,n=this.settings,i=n.classNames,s="mix"==n.mode?n.mixMode.integrated?this.DOM.input.textContent:this.DOM.originalInput.value.trim():this.value.length+this.input.raw.call(this).length;this.toggleClass(i.hasMaxTags,this.value.length>=n.maxTags),this.toggleClass(i.hasNoTags,!this.value.length),this.toggleClass(i.empty,!s),"select"==n.mode&&this.toggleScopeValidation(null===(e=this.value)||void 0===e||null===(t=e[0])||void 0===t?void 0:t.__isValid)},setOriginalInputValue:function(t){var e=this.DOM.originalInput;this.settings.mixMode.integrated||(e.value=t,e.tagifyValue=e.value,this.setPersistedData(t,"value"))},update:function(t){clearTimeout(this.debouncedUpdateTimeout),this.debouncedUpdateTimeout=setTimeout(function(){var e=this.getInputValue();this.setOriginalInputValue(e),this.settings.onChangeAfterBlur&&(t||{}).withoutChangeEvent||this.state.blockChangeEvent||this.triggerChangeEvent(),this.postUpdate()}.bind(this),100),this.events.bindOriginaInputListener.call(this,100)},getInputValue:function(){var t=this.getCleanValue();return"mix"==this.settings.mode?this.getMixedTagsAsString(t):t.length?this.settings.originalInputValueFormat?this.settings.originalInputValueFormat(t):JSON.stringify(t):""},getCleanValue:function(t){return st(t||this.value,this.dataProps)},getMixedTagsAsString:function(){var t="",e=this,n=this.settings,i=n.originalInputValueFormat||JSON.stringify,s=n.mixTagsInterpolator;return function n(a){a.childNodes.forEach((function(a){if(1==a.nodeType){var o=bt(a);if("BR"==a.tagName&&(t+="\r\n"),o&&ft.call(e,a)){if(o.__removed)return;t+=s[0]+i(at(o,e.dataProps))+s[1]}else a.getAttribute("style")||["B","I","U"].includes(a.tagName)?t+=a.textContent:"DIV"!=a.tagName&&"P"!=a.tagName||(t+="\r\n",n(a))}else t+=a.textContent}))}(this.DOM.input),t}},zt.prototype.removeTag=zt.prototype.removeTags,e.UI=e.UI||{},e.UI.Input=e.UI.Input||{},(Gt=e.UI.Input).textarea=new o,Gt.markdown=new w,Gt.treeSelect=new G(new Y(t),e.UI.menu.drilldown,{txt:t=>e.Language.txt(t)},n),Gt.tagInput=Gt.tag||{},Gt.tagInput.init=(t,e,n,i,s)=>Qt(zt,t,e,n,i,s)}($,il,document); diff --git a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js index bae34d83c624..d47cb0c15dbc 100644 --- a/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js +++ b/components/ILIAS/UI/resources/js/Input/Field/src/Tag/tag.js @@ -15,18 +15,18 @@ /** * - * @type {AbortController} + * @type {undefined|AbortController} */ let abortController; /** * - * @type {number} + * @type {undefined|number} */ let timeout; -/* - * @param {HTMLInput} input +/** + * @param {string} inputId * @param {Object} config * @returns {Object} */ @@ -93,7 +93,6 @@ function buildSettings(inputId, config) { * @param {URLBuilderToken} autocompleteToken * @param {InputEvent} event * @param {number} tagAutocompleteTriggerTimeout - * @returns {void} */ function retrieveAutocomplete( instance, @@ -103,14 +102,14 @@ function retrieveAutocomplete( event, tagAutocompleteTriggerTimeout, ) { - if (typeof abortController !== 'undefined') { + if (abortController instanceof AbortController) { abortController.abort(); } abortController = new AbortController(); instance.whitelist = null; - if (typeof timeout === 'number') { + if (timeout !== undefined) { instance.DOM.scope.ownerDocument.defaultView.clearTimeout(timeout); timeout = undefined; } @@ -138,11 +137,11 @@ function retrieveAutocomplete( /** * @param {Tagify} Tagify - * @param {HTMLInput} input + * @param {HTMLElement} input * @param {Object} config - * @param {array} value - * @param {URLBuilder} autocompleteEndpoint - * @param {URLBuilderToken} autocompleteToken + * @param {Array} value + * @param {undefined|URLBuilder} autocompleteEndpoint + * @param {undefined|URLBuilderToken} autocompleteToken */ export default function init( Tagify, @@ -157,7 +156,7 @@ export default function init( buildSettings(input.id, config), ); instance.addTags(value); - if (typeof autocompleteEndpoint !== 'undefined') { + if (autocompleteEndpoint !== undefined) { instance.on('input', (event) => { retrieveAutocomplete( instance, From e012b002c3ff79535e55fa5b1374f29bee71e071 Mon Sep 17 00:00:00 2001 From: Stephan Kergomard Date: Fri, 10 Oct 2025 16:02:33 +0200 Subject: [PATCH 16/16] UI: Fix Tag Tests --- components/ILIAS/UI/tests/Client/Input/Field/Tag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js index efe31982f526..faa760d702aa 100644 --- a/components/ILIAS/UI/tests/Client/Input/Field/Tag.js +++ b/components/ILIAS/UI/tests/Client/Input/Field/Tag.js @@ -17,7 +17,7 @@ import { describe, it, mock } from 'node:test'; import * as assert from 'node:assert'; -import { init } from '../../../../resources/js/Input/Field/src/Tag/tag.js'; +import init from '../../../../resources/js/Input/Field/src/Tag/tag.js'; describe('Tag Input Field', () => { const pseudoConfig = {