diff --git a/assets/js/live_select.js b/assets/js/live_select.js index d105f35..8f14348 100644 --- a/assets/js/live_select.js +++ b/assets/js/live_select.js @@ -92,6 +92,7 @@ export default { this.handleEvent("select", ({ id, selection, mode, current_text, input_event, parent_event }) => { if (this.el.id === id) { this.selection = selection + this._skipNextScroll = true if (current_text != null) { this.setInputValue(current_text) } @@ -105,6 +106,10 @@ export default { }) this.handleEvent("scroll_to_option", ({ id, idx }) => { if (this.el.id === id) { + if (this._skipNextScroll) { + this._skipNextScroll = false + return + } const option = this.el.querySelector(`div[data-idx="${idx}"]`) if (option) { option.scrollIntoView({ block: "nearest", behavior: "instant", container: "nearest" }) @@ -113,7 +118,18 @@ export default { }) this.attachDomEventHandlers() }, + beforeUpdate() { + const dropdown = this.el.querySelector("ul") + this._dropdownScrollTop = dropdown ? dropdown.scrollTop : null + }, updated() { + if (this._dropdownScrollTop != null) { + const dropdown = this.el.querySelector("ul") + if (dropdown) { + dropdown.scrollTop = this._dropdownScrollTop + } + this._dropdownScrollTop = null + } this.maybeStyleClearButtons() this.attachDomEventHandlers() }, diff --git a/priv/static/live_select.min.js b/priv/static/live_select.min.js index a799072..7e0f779 100644 --- a/priv/static/live_select.min.js +++ b/priv/static/live_select.min.js @@ -1 +1 @@ -function o(e,t){let i;return(...s)=>{clearTimeout(i),i=setTimeout(()=>{e.apply(this,s)},t)}}export default{LiveSelect:{textInput(){return this.el.querySelector("input[type=text]")},debounceMsec(){return parseInt(this.el.dataset.debounce)},updateMinLen(){return parseInt(this.el.dataset.updateMinLen)},maybeStyleClearButtons(){const e=this.el.querySelector("button.ls-clear-button");e&&(this.textInput().parentElement.style.position="relative",this.textInput().parentElement.style.display="flex",this.textInput().parentElement.style.alignItems="center",e.style.minHeight="20px",e.style.minWidth="20px",e.style.position="absolute",e.style.right="5px",e.style.display="block"),this.el.querySelectorAll("button.ls-clear-tag-button").forEach(t=>{t.style.minHeight="20px",t.style.minWidth="20px"})},pushEventToParent(e,t){const i=this.el.dataset.phxTarget;i?this.pushEventTo(i,e,t):this.pushEvent(e,t)},attachDomEventHandlers(){this.textInput().onkeydown=t=>{t.code==="Enter"&&t.preventDefault(),this.pushEventTo(this.el,"keydown",{key:t.code})},this.changeEvents=o((t,i,s)=>{this.pushEventTo(this.el,"change",{text:s}),this.pushEventToParent("live_select_change",{id:this.el.id,field:i,text:s})},this.debounceMsec()),this.textInput().oninput=t=>{const i=t.target.value.trim(),s=this.el.dataset.field;i.length>=this.updateMinLen()?this.changeEvents(this.el.id,s,i):this.pushEventTo(this.el,"options_clear",{})};const e=this.el.querySelector("ul");e&&(e.onmousedown=t=>{const i=t.target.closest("div[data-idx]");i&&(this.pushEventTo(this.el,"option_click",{idx:i.dataset.idx}),t.preventDefault())}),this.el.querySelectorAll("button[data-idx]").forEach(t=>{t.onclick=i=>{this.pushEventTo(this.el,"option_remove",{idx:t.dataset.idx})}})},setInputValue(e){this.textInput().value=e},inputEvent(e,t){const i=t==="single"?"input.single-mode":e.length===0?"input[data-live-select-empty]":"input[type=hidden]";this.el.querySelector(i).dispatchEvent(new Event("input",{bubbles:!0}))},mounted(){this.maybeStyleClearButtons(),this.handleEvent("select",({id:e,selection:t,mode:i,current_text:s,input_event:l,parent_event:n})=>{this.el.id===e&&(this.selection=t,s!=null&&this.setInputValue(s),l&&this.inputEvent(t,i),n&&this.pushEventToParent(n,{id:e}))}),this.handleEvent("scroll_to_option",({id:e,idx:t})=>{if(this.el.id===e){const i=this.el.querySelector(`div[data-idx="${t}"]`);i&&i.scrollIntoView({block:"nearest",behavior:"instant",container:"nearest"})}}),this.attachDomEventHandlers()},updated(){this.maybeStyleClearButtons(),this.attachDomEventHandlers()},reconnected(){this.selection&&this.selection.length>0&&this.pushEventTo(this.el,"selection_recovery",this.selection)}}}; +function o(t,e){let i;return(...s)=>{clearTimeout(i),i=setTimeout(()=>{t.apply(this,s)},e)}}export default{LiveSelect:{textInput(){return this.el.querySelector("input[type=text]")},debounceMsec(){return parseInt(this.el.dataset.debounce)},updateMinLen(){return parseInt(this.el.dataset.updateMinLen)},maybeStyleClearButtons(){const t=this.el.querySelector("button.ls-clear-button");t&&(this.textInput().parentElement.style.position="relative",this.textInput().parentElement.style.display="flex",this.textInput().parentElement.style.alignItems="center",t.style.minHeight="20px",t.style.minWidth="20px",t.style.position="absolute",t.style.right="5px",t.style.display="block"),this.el.querySelectorAll("button.ls-clear-tag-button").forEach(e=>{e.style.minHeight="20px",e.style.minWidth="20px"})},pushEventToParent(t,e){const i=this.el.dataset.phxTarget;i?this.pushEventTo(i,t,e):this.pushEvent(t,e)},attachDomEventHandlers(){this.textInput().onkeydown=e=>{e.code==="Enter"&&e.preventDefault(),this.pushEventTo(this.el,"keydown",{key:e.code})},this.changeEvents=o((e,i,s)=>{this.pushEventTo(this.el,"change",{text:s}),this.pushEventToParent("live_select_change",{id:this.el.id,field:i,text:s})},this.debounceMsec()),this.textInput().oninput=e=>{const i=e.target.value.trim(),s=this.el.dataset.field;i.length>=this.updateMinLen()?this.changeEvents(this.el.id,s,i):this.pushEventTo(this.el,"options_clear",{})};const t=this.el.querySelector("ul");t&&(t.onmousedown=e=>{const i=e.target.closest("div[data-idx]");i&&(this.pushEventTo(this.el,"option_click",{idx:i.dataset.idx}),e.preventDefault())}),this.el.querySelectorAll("button[data-idx]").forEach(e=>{e.onclick=i=>{this.pushEventTo(this.el,"option_remove",{idx:e.dataset.idx})}})},setInputValue(t){this.textInput().value=t},inputEvent(t,e){const i=e==="single"?"input.single-mode":t.length===0?"input[data-live-select-empty]":"input[type=hidden]";this.el.querySelector(i).dispatchEvent(new Event("input",{bubbles:!0}))},mounted(){this.maybeStyleClearButtons(),this.handleEvent("select",({id:t,selection:e,mode:i,current_text:s,input_event:l,parent_event:n})=>{this.el.id===t&&(this.selection=e,this._skipNextScroll=!0,s!=null&&this.setInputValue(s),l&&this.inputEvent(e,i),n&&this.pushEventToParent(n,{id:t}))}),this.handleEvent("scroll_to_option",({id:t,idx:e})=>{if(this.el.id===t){if(this._skipNextScroll){this._skipNextScroll=!1;return}const i=this.el.querySelector(`div[data-idx="${e}"]`);i&&i.scrollIntoView({block:"nearest",behavior:"instant",container:"nearest"})}}),this.attachDomEventHandlers()},beforeUpdate(){const t=this.el.querySelector("ul");this._dropdownScrollTop=t?t.scrollTop:null},updated(){if(this._dropdownScrollTop!=null){const t=this.el.querySelector("ul");t&&(t.scrollTop=this._dropdownScrollTop),this._dropdownScrollTop=null}this.maybeStyleClearButtons(),this.attachDomEventHandlers()},reconnected(){this.selection&&this.selection.length>0&&this.pushEventTo(this.el,"selection_recovery",this.selection)}}};