vicowa-web-components
Version:
2 lines • 11 kB
JavaScript
import{WebComponentBaseClass as t}from"/third_party/web-component-base-class/dist/web-component-base-class.js";import"../vicowa-string/vicowa-string.js";import"../vicowa-input/vicowa-input.js";import"/third_party/lodash/lodash.js";import e from"../utilities/debug.js";const i=Symbol("originalItem");window.customElements.define("vicowa-editable-list",class VicowaEditableList extends t{#t;constructor(){super(),this.#t={startItem:0,workList:[],retrievedData:{items:[],totalItemCount:0}},this.factory=null,this.getData=null,this.continueDelete=async()=>!0,this.itemInterface={setItemData(t,e){t.data=e},getItemData:t=>t.data,startEdit(t){t.startEdit()},stopEdit(t){t.stopEdit()},doSave:t=>t.doSave(),doCancel(t){t.doCancel()},hasData:t=>t.hasData,setReadyHandler(t,e){t.onReady=e},setChangeHandler(t,e){t.onChange=e},isValid:t=>t.valid}}get valid(){return this.#t.valid}static get properties(){return{static:{type:Boolean,value:!1,reflectToAttribute:!0},maxPageItems:{type:Number,value:100,reflectToAttribute:!0},filter:{type:Boolean,value:!1,reflectToAttribute:!0},noEdit:{type:Boolean,value:!1,reflectToAttribute:!0},noDelete:{type:Boolean,value:!1,reflectToAttribute:!0},noAdd:{type:Boolean,value:!1,reflectToAttribute:!0},noSave:{type:Boolean,value:!1,reflectToAttribute:!0},noCancel:{type:Boolean,value:!1,reflectToAttribute:!0},select:{type:Boolean,value:!1,reflectToAttribute:!0},single:{type:Boolean,value:!1,reflectToAttribute:!0},multi:{type:Boolean,value:!1,reflectToAttribute:!0}}}attached(){this.addAutoEventListener(this.$.add,"click",(()=>{this.#e(((t,e)=>{this.itemInterface.startEdit(t),e.classList.add("editing")}))})),this.$.jumpTo.onChange=()=>{this.#i()},this.addAutoEventListener(this.$.jump,"click",(()=>{const t=parseInt(this.$.jumpTo.value,10);this.#a((t-1)*this.maxPageItems,this.maxPageItems,this.$.filter.value)})),this.addAutoEventListener(this.$.items,"click",(t=>{if(this.select){const e=t.target.closest(".edit-area");e&&(this.single?(this.$$$("#items .edit-area").forEach((t=>{t.classList.remove("selected")})),e.classList.add("selected")):this.multi&&e.classList.toggle("selected")),this.onSelect&&this.onSelect(this.$$$("#items .edit-area").filter((t=>t.classList.contains("selected"))).map((t=>this.itemInterface.getItemData(t.item))))}})),this.#i()}initialize(t){e.assert(!t||["setItemData","getItemData","startEdit","stopEdit","doSave","doCancel","hasData","setReadyHandler","setChangeHandler","isValid"].every((e=>"function"==typeof t[e])),"setItemData, startEdit, stopEdit, doSave, doCancel, hasData, setReadyHandler, setChangeHandler and isValid should be functions"),this.$.filter.onChange=window._.debounce((()=>{this.#a(0,this.maxPageItems,this.$.filter.value)}),250),this.itemInterface=t||this.itemInterface,this.reloadData()}reloadData(){const t=this.#t;this.#a(t.startItem,this.maxPageItems,this.$.filter.value||"")}#e(t){if(!this.factory)throw new Error("a factory function should be specified");{const e=this.#t,a=document.importNode(this.$.item.content,!0),n=this.factory(),s=a.querySelector(".edit-area");s.item=n;const o=a.querySelector('[name="save"]'),d=()=>{const t=Array.from(this.$.items.querySelectorAll(".edit-area")).map((t=>this.itemInterface.getItemData(t.item)));if(!window._.isEqual(t,e.workList)){const a=e.retrievedData.items;if(e.retrievedData.items=window._.cloneDeepWith(t),e.workList=window._.cloneDeepWith(e.retrievedData.items),this.onChange){const n=window._.differenceWith(t,a,window._.isEqual),s=n.filter((t=>void 0===t[i])),o=n.filter((t=>void 0!==t[i])),d=window._.differenceWith(a,t,window._.isEqual).filter((t=>!o.find((e=>e[i]===t[i]))));this.onChange(e.retrievedData.items,a,{newItems:s,modifiedItems:o,removedItems:d})}}},r={startEditing(){s.classList.add("editing")},update(){d()},stopEditing(){s.classList.remove("editing")},removeEditArea(){s.parentElement.removeChild(s)}};a.querySelector('[name="editable-item"]').appendChild(n),n.applyActions=r,this.addAutoEventListener(a.querySelector('[name="edit"]'),"click",(()=>{this.itemInterface.startEdit(n),r.startEditing()})),this.addAutoEventListener(o,"click",(()=>{this.itemInterface.doSave(n)&&(this.itemInterface.stopEdit(n),r.stopEditing(),r.update())})),this.addAutoEventListener(a.querySelector('[name="cancel"]'),"click",(()=>{this.itemInterface.doCancel(n),this.itemInterface.stopEdit(n),r.stopEditing(),this.itemInterface.hasData(n)||r.removeEditArea()})),this.addAutoEventListener(a.querySelector('[name="delete"]'),"click",(async()=>{await this.continueDelete(s.item)&&(r.removeEditArea(),r.update())})),this.itemInterface.setReadyHandler(n,(()=>{t(n,s)})),this.itemInterface.setChangeHandler(n,(()=>{o.disabled=!this.itemInterface.isValid(n)})),this.$.items.appendChild(a)}}#i(){const t=this.#t,e=parseInt(this.$.jumpTo.value,10);this.$.jump.disabled=isNaN(e)||e<1||e>Math.ceil(t.retrievedData.totalItemCount/this.maxPageItems)}async#a(t,e,a){const n=this.#t;n.startItem=t,n.retrievedData=await this.getData(t,e,a),n.retrievedData.items=n.retrievedData.items.map(((t,e)=>(t[i]=e,t))),this.classList.toggle("pages",n.retrievedData.totalItemCount>this.maxPageItems);const s=this.$.pageLinks;if(s.innerHTML="",n.retrievedData.totalItemCount>this.maxPageItems){const e=Math.ceil(t/this.maxPageItems),i=Math.ceil(n.retrievedData.totalItemCount/this.maxPageItems);if(this.#i(),i>10){if(e>4){const t=document.createElement("button");if(t.addEventListener("click",(()=>{this.#a(0,this.maxPageItems,a)})),t.textContent="1",s.appendChild(t),e>5){const t=document.createElement("span");t.textContent="...",s.appendChild(t)}}const t=Math.min(i-8,Math.max(e-4,0)),n=Math.min(t+8,i);for(let i=t;i<n;i++){const t=document.createElement("button");t.addEventListener("click",(()=>{this.#a(i*this.maxPageItems,this.maxPageItems,a)})),t.textContent=i+1,i===e&&(t.disabled=!0,t.classList.add("active")),s.appendChild(t)}if(i-e>4){if(i-e>5){const t=document.createElement("span");t.textContent="...",s.appendChild(t)}const t=document.createElement("button");t.addEventListener("click",(()=>{this.#a((i-1)*this.maxPageItems,this.maxPageItems,a)})),t.textContent=i,s.appendChild(t)}}else for(let t=0;t<i;t++){const i=document.createElement("button");i.addEventListener("click",(()=>{this.#a(t*this.maxPageItems,this.maxPageItems,a)})),i.textContent=t+1,t===e&&(i.disabled=!0,i.classList.add("active")),s.appendChild(i)}}if(n.retrievedData.items){n.workList=window._.cloneDeepWith(n.retrievedData.items);const t=Array.from(this.$.items.children);for(let e=n.retrievedData.items.length;e<t.length;e++)this.$.items.removeChild(t[e]);n.workList.forEach(((e,i)=>{i<t.length?this.itemInterface.setItemData(t[i].item,window._.cloneDeep(e)):this.#e((t=>{e&&this.itemInterface.setItemData(t,window._.cloneDeep(e))}))}))}else this.$.items.innerHTML=""}static get template(){return'\n\t\t\t<style>\n\t\t\t\t:host {\n\t\t\t\t\tdisplay: block;\n\t\t\t\t\tposition: relative;\n\t\t\t\t\toverflow: auto;\n\t\t\t\t}\n\t\t\n\t\t\t\t:host([static]) #add,\n\t\t\t\t\tdiv[name="edit-area"].editing [name="edit"],\n\t\t\t\t\tdiv[name="edit-area"].editing [name="delete"],\n\t\t\t\t:host([static]) [name="edit"],\n\t\t\t\t:host([static]) [name="delete"],\n\t\t\t\t:host([static]) [name="save"],\n\t\t\t\t\tdiv[name="edit-area"]:not(.editing) [name="save"],\n\t\t\t\t\tdiv[name="edit-area"]:not(.editing) [name="cancel"] {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\n\t\t\t\t.edit-area,\n\t\t\t\t.button-area {\n\t\t\t\t\tbox-sizing: border-box;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: row;\n\t\t\t\t}\n\t\t\n\t\t\t\t#items .edit-area:not(.editing) {\n\t\t\t\t\tbackground: var(--vicowa-editable-list-item-background, transparent);\n\t\t\t\t\tborder: var(--vicowa-editable-list-item-border, 0);\n\t\t\t\t\tborder-bottom: 0;\n\t\t\t\t}\n\t\t\n\t\t\t\t#items .edit-area:not(.editing):last-child {\n\t\t\t\t\tborder: var(--vicowa-editable-list-item-border, 0);\n\t\t\t\t}\n\t\t\n\t\t\t\t#items .edit-area:nth-child(even):not(.editing) {\n\t\t\t\t\tbackground: var(--vicowa-editable-list-item-even-background, transparent);\n\t\t\t\t}\n\t\t\n\t\t\t\t.button-area {\n\t\t\t\t\tpadding-right: 5px;\n\t\t\t\t\twidth: var(--vicowa-editable-list-button-area-width, auto);\n\t\t\t\t}\n\t\t\n\t\t\t\t.edit-area.editing {\n\t\t\t\t\tflex-direction: column;\n\t\t\t\t\tmargin: 1em;\n\t\t\t\t\tpadding: 1em;\n\t\t\t\t\tbox-shadow: 0 0 6px gray;\n\t\t\t\t}\n\t\t\n\t\t\t\t.filter {\n\t\t\t\t\tmargin-bottom: 1em;\n\t\t\t\t}\n\t\t\n\t\t\t\t#pages {\n\t\t\t\t\tmargin-bottom: 1em;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t}\n\t\t\n\t\t\t\t:host(:not([filter])) .filter,\n\t\t\t\t:host(:not(.pages)) #pages,\n\t\t\t\t:host([no-edit]) button[name="edit"],\n\t\t\t\t:host([no-delete]) button[name="delete"],\n\t\t\t\t:host([no-save]) button[name="save"],\n\t\t\t\t:host([no-cancel]) button[name="cancel"],\n\t\t\t\t:host([no-add]) #add {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\n\t\t\t\t#page-links {\n\t\t\t\t\tmargin-right: 1em;\n\t\t\t\t}\n\t\t\n\t\t\t\t.edit-area.editing .button-area {\n\t\t\t\t\torder: 2;\n\t\t\t\t}\n\t\t\n\t\t\t\t#add {\n\t\t\t\t\tmargin-top: 5px;\n\t\t\t\t}\n\t\t\n\t\t\t\t:host([select]) .edit-area,\n\t\t\t\t:host([select]) vicowa-input,\n\t\t\t\t:host([select]) .edit-area:hover {\n\t\t\t\t\tcursor: pointer;\n\t\t\t\t}\n\t\t\n\t\t\t\t:host([select]) #items .edit-area:not(.editing):hover {\n\t\t\t\t\tbackground: var(--vicowa-editable-list-hover-background, #88f);\n\t\t\t\t\tcolor: var(--vicowa-editable-list-hover-color, white);\n\t\t\t\t}\n\t\t\t\t:host([select]) #items .edit-area:not(.editing).selected {\n\t\t\t\t\tbackground: var(--vicowa-editable-list-select-background, blue);\n\t\t\t\t\tcolor: var(--vicowa-editable-list-select-color, white);\n\t\t\t\t}\n\t\t\t</style>\n\t\t\t<div>\n\t\t\t<div class="item-area">\n\t\t\t\t<vicowa-input class="filter" id="filter" label="Filter items"></vicowa-input>\n\t\t\t\t<div id="pages">\n\t\t\t\t\t<div id="page-links"></div>\n\t\t\t\t\t<vicowa-input id="jump-to" hide-label></vicowa-input>\n\t\t\t\t\t<button id="jump"><vicowa-string>Jump to page</vicowa-string></button>\n\t\t\t\t</div>\n\t\t\t\t<p><vicowa-string id="heading" string=""></vicowa-string></p>\n\t\t\t\t<slot name="header"></slot>\n\t\t\t\t\t<div id="items">\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class="button-area">\n\t\t\t\t\t\t<button id="add"><vicowa-string>Add</vicowa-string></button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<template id="item">\n\t\t\t\t<div name="edit-area" class="edit-area">\n\t\t\t\t\t<div class="button-area">\n\t\t\t\t\t\t<button name="edit"><vicowa-string>Edit</vicowa-string></button>\n\t\t\t\t\t\t<button name="delete"><vicowa-string>Delete</vicowa-string></button>\n\t\t\t\t\t\t<button name="save"><vicowa-string>Save</vicowa-string></button>\n\t\t\t\t\t\t<button name="cancel"><vicowa-string>Cancel</vicowa-string></button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div name="editable-item">\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</template>\n\t\t'}});
//# sourceMappingURL=vicowa-editable-list.js.map