diff --git a/data-grid.js b/data-grid.js
index 81b97aa..2f4f81d 100644
--- a/data-grid.js
+++ b/data-grid.js
@@ -634,19 +634,20 @@ class DataGrid extends HTMLElement {
return len;
}
computeDefaultHeight() {
- this.defaultHeight = this.root.querySelector("table").offsetHeight;
-
- // If we have a fixed height, make sure we have overflowY set
- if (this.style.height) {
- this.style.height = this.defaultHeight + "px";
- this.style.overflowY = "auto";
- // Otherwise incomplete row would not look good
- this.root.querySelector("table").style.height = "100%";
- }
- // If our min height is too small, make sure we adjust the value
- if (this.style.minHeight && parseInt(this.style.minHeight) > this.defaultHeight) {
- this.style.minHeight = this.defaultHeight + "px";
- }
+ // Wait until height is fully computed
+ requestAnimationFrame(() => {
+ this.defaultHeight = this.root.querySelector("table").offsetHeight;
+
+ // If we have a fixed height, make sure we have overflowY set
+ if (this.style.height) {
+ this.style.height = this.defaultHeight + "px";
+ this.style.overflowY = "auto";
+ }
+ // If our min height is too small, make sure we adjust the value
+ if (this.style.minHeight && parseInt(this.style.minHeight) > this.defaultHeight) {
+ this.style.minHeight = this.defaultHeight + "px";
+ }
+ });
}
configureUi() {
this.createMenu();
@@ -908,7 +909,7 @@ class DataGrid extends HTMLElement {
this.log("sort data");
// Early exit
- if(col && this.getColProp(col.getAttribute("field"), "noSort")) {
+ if (col && this.getColProp(col.getAttribute("field"), "noSort")) {
return;
}
diff --git a/data-grid.min.css b/data-grid.min.css
index 7dcf591..8147d2d 100644
--- a/data-grid.min.css
+++ b/data-grid.min.css
@@ -1,2 +1,2 @@
-data-grid{--padding: 0.5rem;--padding-half: calc(var(--padding) / 2);--header-scale: 1.5;--color-rgb: var(--bs-primary-rgb, 13, 110, 253);--color: rgb(var(--color-rgb));--highlight-color: #fffcee;--header-background: var(--bs-gray-200, #e9ecef);--header-color: var(--bs-dark, #212529);--btn-background: var(--white, #ffffff);--btn-color: var(--color);--body-color: var(--bs-body-color, #212529);--icon-scale: 1;--border-radius: 0.25rem;--row-border-color: #f2f2f2;--responsive-width: 60%;--black: var(--bs-black, #000);--white: var(--bs-white, #fff);--gray: var(--bs-gray, #6c757d);--gray-dark: var(--bs-gray-dark, #343a40);--gray-100: var(--bs-gray-100, #f8f9fa);--gray-200: var(--bs-gray-200, #e9ecef);--gray-300: var(--bs-gray-300, #dee2e6);--gray-400: var(--bs-gray-400, #ced4da);--gray-500: var(--bs-gray-500, #adb5bd);--gray-600: var(--bs-gray-600, #6c757d);--gray-700: var(--bs-gray-700, #495057);--gray-800: var(--bs-gray-800, #343a40);--gray-900: var(--bs-gray-900, #212529);display:block;contain:content;background:var(--header-background);min-height:6rem}data-grid img{border:none;height:auto;max-width:100%;vertical-align:middle}data-grid [hidden]{display:none}data-grid table{display:table;border-collapse:collapse;table-layout:fixed;width:100%;max-width:100%;white-space:normal}data-grid th,data-grid td{empty-cells:show;padding:var(--padding);text-align:left}data-grid th[tabindex],data-grid td[tabindex]{outline:none;word-break:normal}data-grid th{font-weight:bold;padding:calc(var(--padding) * var(--header-scale)) var(--padding)}data-grid th,data-grid td{position:relative;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}data-grid table tbody tr{cursor:pointer}data-grid table tbody tr.dg-expanded td{white-space:normal}@media only screen and (max-width: 768px){data-grid[responsive] table,data-grid[responsive] thead,data-grid[responsive] tbody,data-grid[responsive] tfoot,data-grid[responsive] th,data-grid[responsive] td,data-grid[responsive] tr:not([hidden]){display:block}data-grid[responsive] thead tr{position:absolute;top:-9999px;left:-9999px}data-grid[responsive] tbody tr{padding:0;border:1px solid var(--header-background)}data-grid[responsive] tbody td{border:none;border-bottom:1px solid var(--row-border-color);position:relative;padding-left:calc(100% - var(--responsive-width))}data-grid[responsive] tbody td:last-child{border:0}data-grid[responsive] tbody td:before{position:absolute;top:0;left:0;padding:var(--padding);width:calc(100% - var(--responsive-width) - (var(--padding) * 4));white-space:nowrap;content:attr(data-name);display:block;font-weight:bold;background-color:var(--header-background)}}data-grid[sticky] table thead,data-grid[sticky] table tfoot{z-index:2;position:sticky;margin:0;border:0}data-grid[sticky] table thead{inset-block-start:-1px}data-grid[sticky] table tfoot{inset-block-end:-1px}data-grid .dg-nav-icon,data-grid .dg-skip-icon{width:22px;height:22px;box-sizing:border-box;position:absolute;display:block;top:50%;left:50%;transform:translate(-50%, -50%) scale(var(--icon-scale, 1))}data-grid .dg-nav-icon:before,data-grid .dg-nav-icon:after,data-grid .dg-skip-icon:before,data-grid .dg-skip-icon:after{content:"";display:block;box-sizing:border-box;position:absolute}data-grid .dg-nav-icon::before{width:0;height:10px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:6px solid;top:6px;left:9px}data-grid .dg-skip-icon::before{width:3px;height:10px;background:currentColor;top:6px;left:14px}data-grid .dg-skip-icon::after{width:0;height:10px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:6px solid;top:6px;left:7px}data-grid .dg-rotate{transform:rotate(-180deg)}data-grid button{background-color:var(--white);border:solid 1px var(--gray-100);border-radius:var(--border-radius);color:var(--color);height:2rem;margin:0 .2rem;padding:0 .5rem;pointer-events:all;text-align:center;cursor:pointer}data-grid button:hover{background-color:var(--gray-200);border-color:var(--gray-300)}data-grid button:disabled:hover{background-color:inherit;border-color:inherit}data-grid input[type=checkbox]{margin:0}data-grid input:not([type=checkbox]),data-grid select{background-color:#fff;box-sizing:border-box;border:solid 1px #f0f0f0;border-radius:var(--border-radius);height:2rem;margin:0 .2rem;padding:0 var(--padding)}data-grid input:not([type=checkbox]):focus,data-grid select:focus,data-grid button:focus{box-shadow:0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25);outline:0}data-grid input:not([type=checkbox])[disabled],data-grid input:not([type=checkbox]):disabled,data-grid select[disabled],data-grid select:disabled,data-grid button[disabled],data-grid button:disabled{opacity:.35;pointer-events:none}data-grid thead tr,data-grid tfoot tr{background-color:var(--header-background);color:var(--header-color)}data-grid thead tr:nth-child(2) th{padding:0;background-color:var(--white)}data-grid thead tr:nth-child(2) th input{width:100%;border-radius:0;margin:0}data-grid tbody td input.dg-editable{width:100%;background:transparent;border:0;border-radius:0;margin:0}data-grid tbody td input.dg-editable:hover{box-shadow:0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25)}data-grid:not([url]) tbody:before{position:absolute;top:50%;left:50%;content:attr(data-empty);transform:translate(-50%, -50%);opacity:.5;font-size:2rem}data-grid tbody tr:nth-child(odd){background-color:var(--bs-white, #ffffff);color:var(--bs-dark, #212529)}data-grid tbody tr:nth-child(even){background-color:var(--bs-light, #f8f9fa);color:var(--bs-dark, #212529)}data-grid tbody tr{border-bottom:solid 1px var(--row-border-color)}data-grid tbody tr:hover{background-color:var(--highlight-color)}data-grid tbody tr:focus{background-color:var(--highlight-color);border-bottom-color:var(--highlight-color);outline:none}data-grid tfoot td{padding:calc(var(--padding) * var(--header-scale)) var(--padding)}data-grid tfoot .dg-page-nav{display:flex;align-items:center}data-grid tfoot .dg-input-page{width:4rem}data-grid tfoot .dg-footer{display:flex;align-items:center;flex-direction:row;justify-content:space-between}data-grid tfoot .dg-pagination{display:flex;text-align:center}data-grid tfoot .dg-pagination button{position:relative;width:2rem}data-grid tfoot .dg-meta{min-width:160px;text-align:right}data-grid [aria-sort]{cursor:pointer;padding-right:1.5rem}data-grid [aria-sort=none]:after,data-grid [aria-sort=none]:before,data-grid [aria-sort=ascending]:before,data-grid [aria-sort=descending]:after{right:.5rem;top:calc(50% - 0.5rem);border:solid transparent;content:" ";height:0;width:0;position:absolute;border-color:rgba(0,0,0,0);border-width:.25rem;margin-left:-0.25rem}data-grid [aria-sort=none]:before{border-bottom-color:var(--bs-gray-400, #ced4da);top:calc(50% - 0.6rem)}data-grid [aria-sort=none]:after{border-top-color:var(--bs-gray-400, #ced4da);bottom:calc(50% - 0.5rem);top:auto}data-grid [aria-sort=ascending]:before{border-bottom-color:var(--bs-dark, #212529)}data-grid [aria-sort=descending]:after{border-top-color:var(--bs-dark, #212529);bottom:calc(50% - 0.5rem);top:auto}data-grid[dir=rtl] th,data-grid[dir=rtl] td{text-align:right}data-grid[dir=rtl] [aria-sort]{padding-left:1rem;padding-right:.5rem}data-grid[dir=rtl] [aria-sort=none]:after,data-grid[dir=rtl] [aria-sort=none]:before,data-grid[dir=rtl] [aria-sort=ascending]:before,data-grid[dir=rtl] [aria-sort=descending]:after{left:.75rem;right:auto}data-grid[dir=rtl] tfoot .dg-meta{text-align:left}data-grid .dg-menu{position:absolute;z-index:3;background:var(--white);list-style:none;max-width:150px;margin:0;padding:var(--padding);box-shadow:0 0 1rem rgba(0,0,0,.25);border-radius:var(--border-radius)}data-grid .dg-menu li{margin:0;padding:0}data-grid .dg-menu label{display:flex;align-items:center;margin-bottom:.25em}data-grid .dg-menu input{margin-right:.5em}data-grid .dg-selectable{position:relative}data-grid .dg-selectable label{margin:0;position:absolute;top:0;left:0;width:100%;height:100%;cursor:pointer;display:flex;align-items:center;justify-content:center}data-grid .dg-actions{text-align:center}data-grid tr.dg-actionable{cursor:pointer}data-grid tr.dg-actionable:hover td{background-color:var(--highlight-color)}data-grid .dg-resizer{position:absolute;top:0;right:0;width:6px;z-index:2;cursor:col-resize;-webkit-user-select:none;-moz-user-select:none;user-select:none}data-grid .dg-resizer:before{content:"";display:block;position:absolute;top:calc(var(--padding) * var(--header-scale));height:1.5rem;right:0;width:2px;background:var(--gray-400)}data-grid .dg-resizer:hover:before{background:var(--color)}data-grid .dg-resizer.dg-resizer-active{border-right:1px dashed var(--color)}data-grid .dg-resizer.dg-resizer-active:before{background:var(--color)}@media only screen and (max-width: 768px){data-grid tfoot .dg-meta{display:none}}
+data-grid{--padding: 0.5rem;--padding-half: calc(var(--padding) / 2);--header-scale: 1.5;--color-rgb: var(--bs-primary-rgb, 13, 110, 253);--color: rgb(var(--color-rgb));--highlight-color: #fffcee;--header-background: var(--bs-gray-200, #e9ecef);--header-color: var(--bs-dark, #212529);--btn-background: var(--white, #ffffff);--btn-color: var(--color);--body-color: var(--bs-body-color, #212529);--icon-scale: 1;--border-radius: 0.25rem;--row-border-color: #f2f2f2;--responsive-width: 60%;--black: var(--bs-black, #000);--white: var(--bs-white, #fff);--gray: var(--bs-gray, #6c757d);--gray-dark: var(--bs-gray-dark, #343a40);--gray-100: var(--bs-gray-100, #f8f9fa);--gray-200: var(--bs-gray-200, #e9ecef);--gray-300: var(--bs-gray-300, #dee2e6);--gray-400: var(--bs-gray-400, #ced4da);--gray-500: var(--bs-gray-500, #adb5bd);--gray-600: var(--bs-gray-600, #6c757d);--gray-700: var(--bs-gray-700, #495057);--gray-800: var(--bs-gray-800, #343a40);--gray-900: var(--bs-gray-900, #212529);display:block;contain:content;background:var(--header-background);min-height:6rem}data-grid img{border:none;height:auto;max-width:100%;vertical-align:middle}data-grid [hidden]{display:none}data-grid table{display:table;border-collapse:collapse;table-layout:fixed;width:100%;max-width:100%;white-space:normal;}data-grid th,data-grid td{empty-cells:show;padding:var(--padding);text-align:left}data-grid th[tabindex],data-grid td[tabindex]{outline:none;word-break:normal}data-grid th{font-weight:bold;padding:calc(var(--padding) * var(--header-scale)) var(--padding)}data-grid th,data-grid td{position:relative;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}data-grid table tbody tr{cursor:pointer}data-grid table tbody tr.dg-expanded td{white-space:normal}@media only screen and (max-width: 768px){data-grid[responsive] table,data-grid[responsive] thead,data-grid[responsive] tbody,data-grid[responsive] tfoot,data-grid[responsive] th,data-grid[responsive] td,data-grid[responsive] tr:not([hidden]){display:block}data-grid[responsive] thead tr{position:absolute;top:-9999px;left:-9999px}data-grid[responsive] tbody tr{padding:0;border:1px solid var(--header-background)}data-grid[responsive] tbody td{border:none;border-bottom:1px solid var(--row-border-color);position:relative;padding-left:calc(100% - var(--responsive-width))}data-grid[responsive] tbody td:last-child{border:0}data-grid[responsive] tbody td:before{position:absolute;top:0;left:0;padding:var(--padding);width:calc(100% - var(--responsive-width) - (var(--padding) * 4));white-space:nowrap;content:attr(data-name);display:block;font-weight:bold;background-color:var(--header-background)}}data-grid[sticky] table thead,data-grid[sticky] table tfoot{z-index:2;position:sticky;margin:0;border:0}data-grid[sticky] table thead{inset-block-start:-1px}data-grid[sticky] table tfoot{inset-block-end:-1px}data-grid .dg-nav-icon,data-grid .dg-skip-icon{width:22px;height:22px;box-sizing:border-box;position:absolute;display:block;top:50%;left:50%;transform:translate(-50%, -50%) scale(var(--icon-scale, 1))}data-grid .dg-nav-icon:before,data-grid .dg-nav-icon:after,data-grid .dg-skip-icon:before,data-grid .dg-skip-icon:after{content:"";display:block;box-sizing:border-box;position:absolute}data-grid .dg-nav-icon::before{width:0;height:10px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:6px solid;top:6px;left:9px}data-grid .dg-skip-icon::before{width:3px;height:10px;background:currentColor;top:6px;left:14px}data-grid .dg-skip-icon::after{width:0;height:10px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:6px solid;top:6px;left:7px}data-grid .dg-rotate{transform:rotate(-180deg)}data-grid button{background-color:var(--white);border:solid 1px var(--gray-100);border-radius:var(--border-radius);color:var(--color);height:2rem;margin:0 .2rem;padding:0 .5rem;pointer-events:all;text-align:center;cursor:pointer}data-grid button:hover{background-color:var(--gray-200);border-color:var(--gray-300)}data-grid button:disabled:hover{background-color:inherit;border-color:inherit}data-grid input[type=checkbox]{margin:0}data-grid input:not([type=checkbox]),data-grid select{background-color:#fff;box-sizing:border-box;border:solid 1px #f0f0f0;border-radius:var(--border-radius);height:2rem;margin:0 .2rem;padding:0 var(--padding)}data-grid input:not([type=checkbox]):focus,data-grid select:focus,data-grid button:focus{box-shadow:0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25);outline:0}data-grid input:not([type=checkbox])[disabled],data-grid input:not([type=checkbox]):disabled,data-grid select[disabled],data-grid select:disabled,data-grid button[disabled],data-grid button:disabled{opacity:.35;pointer-events:none}data-grid thead tr,data-grid tfoot tr{background-color:var(--header-background);color:var(--header-color)}data-grid thead tr:nth-child(2) th{padding:0;background-color:var(--white)}data-grid thead tr:nth-child(2) th input{width:100%;border-radius:0;margin:0}data-grid tbody td input.dg-editable{width:100%;background:transparent;border:0;border-radius:0;margin:0}data-grid tbody td input.dg-editable:hover{box-shadow:0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25)}data-grid:not([url]) tbody:before{position:absolute;top:50%;left:50%;content:attr(data-empty);transform:translate(-50%, -50%);opacity:.5;font-size:2rem}data-grid tbody tr:nth-child(odd){background-color:var(--bs-white, #ffffff);color:var(--bs-dark, #212529)}data-grid tbody tr:nth-child(even){background-color:var(--bs-light, #f8f9fa);color:var(--bs-dark, #212529)}data-grid tbody tr{border-bottom:solid 1px var(--row-border-color)}data-grid tbody tr:hover{background-color:var(--highlight-color)}data-grid tbody tr:focus{background-color:var(--highlight-color);border-bottom-color:var(--highlight-color);outline:none}data-grid tfoot td{padding:calc(var(--padding) * var(--header-scale)) var(--padding)}data-grid tfoot .dg-page-nav{display:flex;align-items:center}data-grid tfoot .dg-input-page{width:4rem}data-grid tfoot .dg-footer{display:flex;align-items:center;flex-direction:row;justify-content:space-between}data-grid tfoot .dg-pagination{display:flex;text-align:center}data-grid tfoot .dg-pagination button{position:relative;width:2rem}data-grid tfoot .dg-meta{min-width:160px;text-align:right}data-grid [aria-sort]{cursor:pointer;padding-right:1.5rem}data-grid [aria-sort=none]:after,data-grid [aria-sort=none]:before,data-grid [aria-sort=ascending]:before,data-grid [aria-sort=descending]:after{right:.5rem;top:calc(50% - 0.5rem);border:solid transparent;content:" ";height:0;width:0;position:absolute;border-color:rgba(0,0,0,0);border-width:.25rem;margin-left:-0.25rem}data-grid [aria-sort=none]:before{border-bottom-color:var(--bs-gray-400, #ced4da);top:calc(50% - 0.6rem)}data-grid [aria-sort=none]:after{border-top-color:var(--bs-gray-400, #ced4da);bottom:calc(50% - 0.5rem);top:auto}data-grid [aria-sort=ascending]:before{border-bottom-color:var(--bs-dark, #212529)}data-grid [aria-sort=descending]:after{border-top-color:var(--bs-dark, #212529);bottom:calc(50% - 0.5rem);top:auto}data-grid[dir=rtl] th,data-grid[dir=rtl] td{text-align:right}data-grid[dir=rtl] [aria-sort]{padding-left:1rem;padding-right:.5rem}data-grid[dir=rtl] [aria-sort=none]:after,data-grid[dir=rtl] [aria-sort=none]:before,data-grid[dir=rtl] [aria-sort=ascending]:before,data-grid[dir=rtl] [aria-sort=descending]:after{left:.75rem;right:auto}data-grid[dir=rtl] tfoot .dg-meta{text-align:left}data-grid .dg-menu{position:absolute;z-index:3;background:var(--white);list-style:none;max-width:150px;margin:0;padding:var(--padding);box-shadow:0 0 1rem rgba(0,0,0,.25);border-radius:var(--border-radius)}data-grid .dg-menu li{margin:0;padding:0}data-grid .dg-menu label{display:flex;align-items:center;margin-bottom:.25em}data-grid .dg-menu input{margin-right:.5em}data-grid .dg-selectable{position:relative}data-grid .dg-selectable label{margin:0;position:absolute;top:0;left:0;width:100%;height:100%;cursor:pointer;display:flex;align-items:center;justify-content:center}data-grid .dg-actions{text-align:center}data-grid tr.dg-actionable{cursor:pointer}data-grid tr.dg-actionable:hover td{background-color:var(--highlight-color)}data-grid .dg-resizer{position:absolute;top:0;right:0;width:6px;z-index:2;cursor:col-resize;-webkit-user-select:none;-moz-user-select:none;user-select:none}data-grid .dg-resizer:before{content:"";display:block;position:absolute;top:calc(var(--padding) * var(--header-scale));height:1.5rem;right:0;width:2px;background:var(--gray-400)}data-grid .dg-resizer:hover:before{background:var(--color)}data-grid .dg-resizer.dg-resizer-active{border-right:1px dashed var(--color)}data-grid .dg-resizer.dg-resizer-active:before{background:var(--color)}@media only screen and (max-width: 768px){data-grid tfoot .dg-meta{display:none}}
/*# sourceMappingURL=data-grid.min.css.map */
\ No newline at end of file
diff --git a/data-grid.min.js b/data-grid.min.js
index 792fb5e..76b6409 100644
--- a/data-grid.min.js
+++ b/data-grid.min.js
@@ -36,5 +36,5 @@
-`;var h=class extends HTMLElement{constructor(t={}){super();this.appendChild(m.content.cloneNode(!0)),this.root=this,this.state={url:null,page:1,perPage:10,debug:!1,filter:!1,sort:!1,server:!1,defaultSort:"",reorder:!1,dir:"ltr",pages:0,perPageValues:[10,25,50,100,250],columns:[],actions:[]},this.setOptions(t),this.data=[],this.originalData=[],this.isInitialized=!1,this.touch=null,this.isResizing=!1,this.defaultHeight=0,this.meta={},this.hasAttribute("id")||this.setAttribute("id",h.randstr("dg-")),this.log("constructor")}static interpolate(t,e){return t.replace(/\{([^\}]+)?\}/g,function(i,s){return e[s]})}static getParentNode(t,e,i="nodeName"){let s=t;for(;s[i]!=e;)s=s.parentNode;return s}static getTextWidth(t,e=document.body){let i=window.getComputedStyle(e,null),s=i.getPropertyValue("font-weight")||"normal",a=i.getPropertyValue("font-size")||"1rem",o=i.getPropertyValue("font-family")||"Arial",l=(h.getTextWidth.canvas||(h.getTextWidth.canvas=document.createElement("canvas"))).getContext("2d");l.font=`${s} ${a} ${o}`;let n=l.measureText(t);return parseInt(n.width)}static addSelectOption(t,e,i,s=!1){let a=document.createElement("option");a.value=e,s&&(a.selected="selected"),a.label=i,t.appendChild(a)}static randstr(t){return Math.random().toString(36).replace("0.",t||"")}static convertArray(t){return typeof t=="string"?t[0]==="{"?JSON.parse(t):t.split(","):(Array.isArray(t)||console.error("Invalid array",t),t)}static elementOffset(t){var e=t.getBoundingClientRect(),i=window.pageXOffset||document.documentElement.scrollLeft,s=window.pageYOffset||document.documentElement.scrollTop;return{top:e.top+s,left:e.left+i}}static applyColumnDefinition(t,e){e.width&&t.setAttribute("width",e.width),e.class&&t.setAttribute("class",e.class)}static convertColumns(t){let e=[];return typeof t=="object"&&!Array.isArray(t)?Object.keys(t).forEach(i=>{let s={};s.title=t[i],s.field=i,e.push(s)}):t.forEach(i=>{let s={};typeof i=="string"?(s.title=i,s.field=i):typeof i=="object"?(s=i,s.field||console.error("Invalid column definition",i)):console.error("Column definition must be a string or an object"),e.push(s)}),e}static get observedAttributes(){return["url","page","per-page","debug","filter","sort","default-sort","dir","reorder"]}attributeChangedCallback(t,e,i){switch(this.log("attributeChangedCallback: "+t),t){case"url":this.state.url=i,this.isInitialized&&i&&this.loadData().then(()=>{this.configureUi()});break;case"page":this.state.page=Number(i),this.isInitialized&&this.loadData().finally(()=>{this.fixPage(),this.server?this.renderBody():this.paginate()});break;case"per-page":this.state.perPage=Number(i),this.isInitialized&&(this.selectPerPage.value=i,this.loadData().finally(()=>{this.fixPage(),this.server?this.renderBody():this.paginate(),this.sticky&&window.scroll({top:h.elementOffset(this.selectPerPage).top-this.defaultHeight})}));break;case"debug":this.state.debug=i==="true";break;case"dir":this.state.dir=i,this.root.querySelector(".dg-wrapper").dir=this.state.dir;break;case"filter":this.state.filter=i==="true",this.isInitialized&&this.toggleFilter();break;case"reorder":this.state.reorder=i==="true",this.isInitialized&&this.toggleReorder();break;case"sort":this.state.sort=i==="true",this.isInitialized&&this.toggleSort();break;case"default-sort":this.state.defaultSort=i,this.isInitialized&&this.toggleSort();break}}get page(){return this.getAttribute("page")}set page(t){this.setAttribute("page",t)}get perPage(){return this.getAttribute("per-page")}set perPage(t){this.setAttribute("per-page",t)}get debug(){return this.getAttribute("debug")==="true"}set debug(t){this.setAttribute("debug",t)}get dir(){return this.getAttribute("dir")}set dir(t){this.setAttribute("dir",t)}get filter(){return this.getAttribute("filter")==="true"}set filter(t){this.setAttribute("filter",t)}get reorder(){return this.getAttribute("reorder")==="true"}set reorder(t){this.setAttribute("reorder",t)}get sort(){return this.getAttribute("sort")==="true"}set sort(t){this.setAttribute("sort",t)}get defaultSort(){return this.getAttribute("default-sort")}set defaultSort(t){this.setAttribute("default-sort",t)}get url(){return this.getAttribute("url")}set url(t){t?this.setAttribute("url",t):this.removeAttribute("url")}get server(){return this.hasAttribute("server")}set server(t){t?this.setAttribute("server",""):this.removeAttribute("server")}get autosize(){return this.hasAttribute("autosize")}set autosize(t){t?this.setAttribute("autosize",""):this.removeAttribute("autosize")}get resizable(){return this.hasAttribute("resizable")}set resizable(t){t?this.setAttribute("resizable",""):this.removeAttribute("resizable")}get sticky(){return this.hasAttribute("sticky")}set sticky(t){t?this.setAttribute("sticky",""):this.removeAttribute("sticky")}get responsive(){return this.hasAttribute("responsive")}set responsive(t){t?this.setAttribute("responsive",""):this.removeAttribute("responsive")}get expand(){return this.hasAttribute("expand")}set expand(t){t?this.setAttribute("expand",""):this.removeAttribute("expand")}get selectable(){return this.hasAttribute("selectable")}set selectable(t){t?this.setAttribute("selectable",""):this.removeAttribute("selectable")}get perPageValues(){return this.state.perPageValues}set perPageValues(t){if(Array.isArray(t)&&(this.state.perPageValues=t,this.selectPerPage)){for(;this.selectPerPage.lastChild;)this.selectPerPage.removeChild(this.selectPerPage.lastChild);this.state.perPageValues.forEach(e=>{h.addSelectOption(this.selectPerPage,e,e)})}}get columns(){return this.state.columns}set columns(t){this.state.columns=h.convertColumns(h.convertArray(t))}get actions(){return this.state.actions}set actions(t){this.state.actions=h.convertArray(t)}connectedCallback(){this.log("connectedCallback"),this.btnFirst=this.root.querySelector(".dg-btn-first"),this.btnPrev=this.root.querySelector(".dg-btn-prev"),this.btnNext=this.root.querySelector(".dg-btn-next"),this.btnLast=this.root.querySelector(".dg-btn-last"),this.selectPerPage=this.root.querySelector(".dg-select-per-page"),this.inputPage=this.root.querySelector(".dg-input-page"),this.getFirst=this.getFirst.bind(this),this.getPrev=this.getPrev.bind(this),this.getNext=this.getNext.bind(this),this.getLast=this.getLast.bind(this),this.changePerPage=this.changePerPage.bind(this),this.gotoPage=this.gotoPage.bind(this),this.btnFirst.addEventListener("click",this.getFirst),this.btnPrev.addEventListener("click",this.getPrev),this.btnNext.addEventListener("click",this.getNext),this.btnLast.addEventListener("click",this.getLast),this.selectPerPage.addEventListener("change",this.changePerPage,{passive:!0}),this.inputPage.addEventListener("input",this.gotoPage),this.touchstart=this.touchstart.bind(this),this.touchmove=this.touchmove.bind(this),document.addEventListener("touchstart",this.touchstart),document.addEventListener("touchmove",this.touchmove),this.perPageValues=this.state.perPageValues,this.loadData().finally(()=>{this.configureUi(),this.toggleSort(),this.toggleFilter(),this.toggleReorder(),this.root.classList.add("dg-initialized"),this.isInitialized=!0})}disconnectedCallback(){this.log("disconnectedCallback"),this.btnFirst.removeEventListener("click",this.getFirst),this.btnPrev.removeEventListener("click",this.getPrev),this.btnNext.removeEventListener("click",this.getNext),this.btnLast.removeEventListener("click",this.getLast),this.selectPerPage.removeEventListener("change",this.changePerPage,{passive:!0}),this.inputPage.removeEventListener("input",this.gotoPage),document.removeEventListener("touchstart",this.touchstart),document.removeEventListener("touchmove",this.touchmove),this.selectAll&&this.selectAll.removeEventListener("change",this.toggleSelectAll),this.headerRow&&this.headerRow.removeEventListener("contextmenu",this.showContextMenu)}toggleSelectAll(){this.root.querySelectorAll("tbody .dg-selectable input").forEach(t=>{t.checked=this.selectAll.checked})}touchstart(t){this.touch=t.touches[0]}touchmove(t){if(!this.touch)return;let e=this.touch.clientX-t.touches[0].clientX,i=this.touch.clientY-t.touches[0].clientY;Math.abs(e)>Math.abs(i)&&(e>0?this.getNext():this.getPrev()),this.touch=null}setOptions(t){for(let[e,i]of Object.entries(t))e in this&&(this[e]=i,this.state[e]=i)}getColProp(t,e){let i=null;return this.state.columns.forEach(s=>{if(s.field==t){i=s[e];return}}),i}setColProp(t,e,i){this.state.columns.forEach(s=>{s.field==t&&(s[e]=i)})}startIndex(){return this.selectable?2:1}columnsLength(t=!1){let e=0;return this.state.columns.forEach(i=>{t&&i.hidden||i.attr||e++}),this.selectable&&e++,this.state.actions.length&&e++,e}computeDefaultHeight(){this.defaultHeight=this.root.querySelector("table").offsetHeight,this.style.height&&(this.style.height=this.defaultHeight+"px",this.style.overflowY="auto",this.root.querySelector("table").style.height="100%"),this.style.minHeight&&parseInt(this.style.minHeight)>this.defaultHeight&&(this.style.minHeight=this.defaultHeight+"px")}configureUi(){this.createMenu(),this.root.querySelector("table").setAttribute("aria-rowcount",this.data.length),this.root.querySelector("tfoot").removeAttribute("hidden"),this.renderHeader(),this.rowHeight||(this.rowHeight=this.root.querySelector("tbody tr").offsetHeight)}fixPage(){this.state.pages=this.totalPages(),this.state.pages{t.classList.contains("dg-selectable")||t.classList.contains("dg-actions")||(this.state.reorder?t.draggable=!0:t.removeAttribute("draggable"))})}toggleSort(){this.log("toggle sort"),this.root.querySelectorAll("thead tr.dg-head-columns th").forEach(t=>{t.classList.contains("dg-selectable")||t.classList.contains("dg-actions")||(this.state.sort&&!this.getColProp(t.getAttribute("field"),"noSort")?t.setAttribute("aria-sort","none"):t.removeAttribute("aria-sort"))})}addRow(t){this.log("Add row"),this.originalData.push(t),this.data=this.originalData.slice(),this.fixPage(),this.sortData()}removeRow(t=null,e=null){e===null&&(e=this.columns[0].field),t===null&&(t=this.originalData[this.originalData.length-1][e]),this.log("Removing "+e+":"+t);for(let i=0;i{this.root.querySelector("tbody tr[aria-rowindex='"+(s+1)+"']").querySelector(".dg-selectable input").checked&&(t?e.push(i[t]):e.push(i))}),e}getData(){return this.originalData}clearData(){this.state.url=null,this.data.length!==0&&(this.data=this.originalData=[],this.fixPage(),this.renderHeader(),this.computeDefaultHeight())}loadData(){return!this.server&&this.originalData.length?(this.log("skip loadData"),new Promise((t,e)=>{t()})):(this.log("loadData"),this.fetchData().then(t=>{if(Array.isArray(t))this.data=t;else{if(!t.data){console.error("Invalid response, it should contain a data key with an array or be a plain array",t);return}t.options&&this.setOptions(t.options),t.meta&&(this.meta=t.meta),this.data=t.data}this.originalData=this.data.slice(),this.fixPage(),this.state.columns.length===0&&this.originalData.length&&(this.state.columns=h.convertColumns(Object.keys(this.originalData[0])))}).catch(t=>{this.url=null,this.log(t)}))}getFirst(){this.page=1}getLast(){this.page=this.state.pages}getPrev(){this.page=this.state.page-1}getNext(){this.page=this.state.page+1}refresh(){return this.data=this.originalData=[],this.loadData()}changePerPage(){this.perPage=this.selectPerPage.options[this.selectPerPage.selectedIndex].value}gotoPage(t){if(t.type==="keypress"){let e=t.keyCode||t.key;if(e===13||e==="Enter")t.preventDefault();else return}this.page=this.inputPage.value}getSort(){let t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']");return t?t.getAttribute("field"):this.defaultSort}getSortDir(){let t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']");return t&&t.getAttribute("aria-sort")||""}getFilters(){let t=[];return this.root.querySelectorAll("thead tr.dg-head-filters input").forEach(e=>{t[e.dataset.name]=e.value}),t}clearFilters(){this.root.querySelectorAll("thead tr.dg-head-filters input").forEach(t=>{t.value=""}),this.filterData()}filterData(){if(this.log("filter data"),this.server)this.loadData().finally(()=>{this.fixPage(),this.renderBody()});else{this.data=this.originalData.slice(),this.root.querySelectorAll("thead tr.dg-head-filters input").forEach(e=>{let i=e.value;if(i){let s=e.dataset.name;this.data=this.data.filter(a=>(a[s]+"").toLowerCase().indexOf(i.toLowerCase())!==-1)}}),this.fixPage();let t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']");this.state.sort&&t?this.sortData(t):this.renderBody()}}sortData(t=null){if(this.log("sort data"),!(t&&this.getColProp(t.getAttribute("field"),"noSort")))if(t!==null?(this.root.querySelectorAll("thead tr:first-child th").forEach(e=>{e.classList.contains("dg-selectable")||e.classList.contains("dg-actions")||e!==t&&e.setAttribute("aria-sort","none")}),!t.hasAttribute("aria-sort")||t.getAttribute("aria-sort")==="none"?t.setAttribute("aria-sort","ascending"):t.getAttribute("aria-sort")==="ascending"?t.setAttribute("aria-sort","descending"):t.getAttribute("aria-sort")==="descending"&&t.setAttribute("aria-sort","none")):t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']"),this.server)this.loadData().finally(()=>{this.renderBody()});else{let e=t?t.getAttribute("aria-sort"):"none";if(e==="none"){let i=[];this.originalData.some(s=>(this.data.some(a=>JSON.stringify(s)===JSON.stringify(a)?(i.push(a),!0):!1),i.length===this.data.length)),this.data=i}else{let i=t.getAttribute("field");this.data.sort((s,a)=>{if(!isNaN(s[i])&&!isNaN(a[i]))return e==="ascending"?s[i]-a[i]:a[i]-s[i];let o=e==="ascending"?s[i].toUpperCase():a[i].toUpperCase(),r=e==="ascending"?a[i].toUpperCase():s[i].toUpperCase();switch(!0){case o>r:return 1;case os("No url set"));let t=new URL(this.url,window.location.href),e={r:Math.ceil(Math.random()*9999999)};return this.server&&(e.start=this.state.page-1,e.length=this.state.perPage,e.search=this.getFilters(),e.sort=this.getSort()||"",e.sortDir=this.getSortDir()),Object.keys(e).forEach(i=>{Array.isArray(e[i])?Object.keys(e[i]).forEach(s=>t.searchParams.append(i+"["+s+"]",e[i][s])):t.searchParams.append(i,e[i])}),fetch(t).then(i=>i.json())}renderHeader(){this.log("render header");let t,e,i=this.root.querySelector("thead");this.createColumnHeaders(i),this.state.defaultSort&&(e=this.root.querySelector("thead tr.dg-head-columns th[field='"+this.state.defaultSort+"']")),this.createColumnFilters(i),this.root.querySelector("table").setAttribute("aria-colcount",this.columnsLength(!0).toString()),this.root.querySelector("tfoot").querySelector("td").setAttribute("colspan",this.columnsLength(!0).toString()),e?this.sortData(e):this.renderBody(),this.root.querySelector("tfoot").style.display="",this.resizable&&this.renderResizer()}createColumnHeaders(t){let e=parseInt(t.offsetWidth/this.columnsLength(!0)*2),i=0,s;if(s=document.createElement("tr"),this.headerRow=s,s.setAttribute("role","row"),s.setAttribute("aria-rowindex",1),s.setAttribute("class","dg-head-columns"),this.selectable){let o=document.createElement("th");o.setAttribute("role","columnheader button"),o.setAttribute("aria-colindex",1),o.classList.add("dg-selectable"),o.tabIndex=0,this.selectAll=document.createElement("input"),this.selectAll.type="checkbox",this.selectAll.classList.add("dg-select-all"),this.toggleSelectAll=this.toggleSelectAll.bind(this),this.selectAll.addEventListener("change",this.toggleSelectAll);let r=document.createElement("label");r.appendChild(this.selectAll),o.appendChild(r),o.setAttribute("width",40),s.appendChild(o)}i=0;let a=0;if(this.state.columns.forEach((o,r)=>{if(o.attr)return;let l=document.createElement("th");l.setAttribute("role","columnheader button"),l.setAttribute("aria-colindex",i+this.startIndex()),l.setAttribute("id",h.randstr("dg-col-")),this.state.sort&&l.setAttribute("aria-sort","none"),l.setAttribute("field",o.field),l.dataset.minWidth=h.getTextWidth(o.title,l)+40,h.applyColumnDefinition(l,o),l.tabIndex=0,l.textContent=o.title,o.hidden&&l.setAttribute("hidden",!0),this.autosize&&!l.getAttribute("width")&&(a+=this.autosizeColumn(l,o,l.dataset.minWidth,e)),this.state.reorder&&this.makeHeaderDraggable(l),s.appendChild(l),i++}),a{o.addEventListener("click",()=>this.sortData(o))})}createColumnFilters(t){let e=0,i;if(i=document.createElement("tr"),this.filterRow=i,i.setAttribute("role","row"),i.setAttribute("aria-rowindex",2),i.setAttribute("class","dg-head-filters"),this.state.filter||i.setAttribute("hidden",!0),this.selectable){let s=document.createElement("th");s.setAttribute("role","columnheader button"),s.setAttribute("aria-colindex",1),s.classList.add("dg-selectable"),s.tabIndex=0,i.appendChild(s)}if(this.state.columns.forEach((s,a)=>{if(s.attr)return;let o=t.querySelector("tr.dg-head-columns th[aria-colindex='"+(e+this.startIndex())+"']"),r=document.createElement("th");r.setAttribute("aria-colindex",e+this.startIndex());let l=document.createElement("input");l.type="text",l.autocomplete="off",l.spellcheck=!1,l.dataset.name=s.field,l.id=h.randstr("dg-filter-"),l.setAttribute("aria-labelledby",o.getAttribute("id")),this.state.filter?l.tabIndex=0:r.tabIndex=0,s.hidden&&r.setAttribute("hidden",!0),r.appendChild(l),i.appendChild(r),e++}),this.state.actions.length){let s=document.createElement("th");s.setAttribute("role","columnheader button"),s.setAttribute("aria-colindex",this.columnsLength(!0)),s.classList.add("dg-actions"),s.tabIndex=0,i.appendChild(s)}t.replaceChild(i,t.querySelector("tr.dg-head-filters")),i.querySelectorAll("input").forEach(s=>{s.addEventListener("keypress",a=>{let o=a.keyCode||a.key;(o===13||o==="Enter")&&this.filterData.call(this)})})}autosizeColumn(t,e,i,s){let a=this.data[0][e.field].toString(),o=this.data[this.data.length-1][e.field].toString();o.length>a.length&&(a=o);let r=0;return a.length<=6?r=i:a.length>50?r=s:r=h.getTextWidth(a,t),rs.width&&(a-=i.offsetWidth,i.style.left=`${a}px`);let r=l=>{i.contains(l.target)||(i.setAttribute("hidden",!0),document.removeEventListener("click",r))};document.addEventListener("click",r)}createMenu(){let t=this.root.querySelector(".dg-menu");this.state.columns.forEach(e=>{if(e.attr)return;let i=e.field,s=document.createElement("li"),a=document.createElement("label"),o=document.createElement("input");o.setAttribute("type","checkbox"),e.hidden||(o.checked=!0),o.addEventListener("change",l=>{l.target.checked?this.showColumn(i,l.target):this.hideColumn(i,l.target)});let r=document.createTextNode(e.title);a.appendChild(o),a.appendChild(r),s.appendChild(a),t.appendChild(s)})}showColumn(t,e=null){e&&(e.checked=!0),this.setColProp(t,"hidden",!1),this.renderHeader()}hideColumn(t,e=null){if(this.state.columns.filter(s=>s.hidden===!0).length===this.columnsLength()-1){e&&(e.checked=!0);return}this.setColProp(t,"hidden",!0),this.renderHeader()}makeHeaderDraggable(t){t.draggable=!0,t.addEventListener("dragstart",e=>{if(this.isResizing&&e.preventDefault){e.preventDefault();return}this.log("reorder col"),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",e.target.getAttribute("aria-colindex"))}),t.addEventListener("dragover",e=>(e.preventDefault&&e.preventDefault(),e.dataTransfer.dropEffect="move",!1)),t.addEventListener("drop",e=>{e.stopPropagation&&e.stopPropagation();let i=h.getParentNode(e.target,"TH"),s=e.dataTransfer.getData("text/plain"),a=i.getAttribute("aria-colindex");if(s===a){this.log("reordered col stayed the same");return}this.log("reordered col from "+s+" to "+a);let o=this.state.columns[s-1];this.state.columns[s-1]=this.columns[a-1],this.state.columns[a-1]=o;let r=(l,n)=>{let u=n.parentNode.getAttribute("aria-rowindex"),d=this.root.querySelector(l+" tr[aria-rowindex='"+u+"'] [aria-colindex='"+a+"']");n.setAttribute("aria-colindex",a),d.setAttribute("aria-colindex",s);let g=document.createElement("th");n.parentNode.insertBefore(g,n),d.parentNode.replaceChild(n,d),g.parentNode.replaceChild(d,g)};return this.root.querySelectorAll("thead th[aria-colindex='"+s+"']").forEach(l=>{r("thead",l)}),this.root.querySelectorAll('tbody td[aria-colindex="'+s+'"]').forEach(l=>{r("tbody",l)}),!1})}renderResizer(){let t=this.root.querySelector("table"),e=this.root.querySelectorAll("thead tr.dg-head-columns th");e.forEach(i=>{if(i.classList.contains("dg-selectable")||i.classList.contains("dg-actions"))return;let s=document.createElement("div");s.classList.add("dg-resizer"),s.ariaLabel=c.resizeColumn,i.appendChild(s);let a=0,o=0,r=0,l=0,n=d=>{if(d.clientX>l)return;let g=o+(d.clientX-a);i.dataset.minWidth&&g>i.dataset.minWidth&&(i.width=g)},u=()=>{this.log("resized column"),this.isResizing=!1,s.classList.remove("dg-resizer-active"),this.state.reorder&&(i.draggable=!0),i.style.overflow="hidden",document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",u)};s.addEventListener("click",d=>{d.stopPropagation()}),s.addEventListener("mousedown",d=>{d.stopPropagation(),this.isResizing=!0;let g=this.root.querySelectorAll(".dg-head-columns th"),b=Array.from(g).filter(f=>!f.hasAttribute("hidden")),p=Array.from(b).findIndex(f=>f==d.target.parentNode);this.log("resize column"),s.classList.add("dg-resizer-active"),i.hasAttribute("draggable")&&i.removeAttribute("draggable"),i.style.overflow="visible",s.style.height=t.offsetHeight-1+"px",a=d.clientX,o=i.offsetWidth,r=(b.length-p)*30,l=h.elementOffset(this).left+this.offsetWidth-r,i.setAttribute("width",o);for(let f=0;fp&&e[f].removeAttribute("width");document.addEventListener("mousemove",n),document.addEventListener("mouseup",u)})})}renderBody(){this.log("render body");let t,e,i,s=document.createElement("tbody");this.data.forEach((a,o)=>{if(t=document.createElement("tr"),t.setAttribute("role","row"),t.setAttribute("hidden",!0),t.setAttribute("aria-rowindex",o+1),t.tabIndex=0,this.selectable){e=document.createElement("td"),e.setAttribute("role","gridcell button"),e.setAttribute("aria-colindex",1),e.classList.add("dg-selectable");let r=document.createElement("input");r.type="checkbox";let l=document.createElement("label");l.appendChild(r),e.appendChild(l),t.appendChild(e)}this.expand&&t.addEventListener("click",function(r){this.classList.toggle("dg-expanded")}),i=0,this.state.columns.forEach((r,l)=>{if(r||console.log(this.state.columns),r.attr){t.setAttribute(r.attr,a[r.field]);return}if(e=document.createElement("td"),e.setAttribute("role","gridcell"),e.setAttribute("aria-colindex",i+this.startIndex()),h.applyColumnDefinition(e,r),e.setAttribute("data-name",r.title),e.tabIndex=-1,r.editable){let n=document.createElement("input");n.type="text",n.autocomplete="off",n.spellcheck=!1,n.tabIndex=0,n.classList.add("dg-editable"),n.name=this.getAttribute("id").replace("-","_")+"["+(o+1)+"]["+r.field+"]",n.value=a[r.field],n.dataset.field=r.field,n.addEventListener("click",u=>u.stopPropagation()),n.addEventListener("keypress",u=>{if(u.type==="keypress"){let d=u.keyCode||u.key;(d===13||d==="Enter")&&n.blur()}}),n.addEventListener("blur",u=>{if(n.value==a[n.dataset.field])return;a[n.dataset.field]=n.value;let d=new CustomEvent("edit",{bubbles:!0,detail:{data:a,value:n.value}});this.dispatchEvent(d)}),e.appendChild(n)}else e.textContent=a[r.field];r.hidden&&e.setAttribute("hidden",!0),t.appendChild(e),i++}),this.state.actions.length&&(e=document.createElement("td"),e.setAttribute("role","gridcell"),e.setAttribute("aria-colindex",this.columnsLength(!0)),e.classList.add("dg-actions"),e.tabIndex=0,this.state.actions.forEach(r=>{let l=document.createElement("button");r.html?l.innerHTML=r.html:l.innerText=r.title??r.name,r.url&&(l.type="submit",l.formAction=h.interpolate(r.url,a)),r.class&&l.classList.add(r.class);let n=u=>{if(u.stopPropagation(),r.confirm&&!confirm(c.areYouSure)){u.preventDefault();return}let d=new CustomEvent("action",{bubbles:!0,detail:{data:a,action:r.name}});this.dispatchEvent(d)};l.addEventListener("click",n),e.appendChild(l),r.default&&(t.classList.add("dg-actionable"),t.addEventListener("click",n))}),t.appendChild(e)),s.appendChild(t)}),s.setAttribute("role","rowgroup"),this.root.querySelector("table").replaceChild(s,this.root.querySelector("tbody")),t=document.createElement("tr"),t.setAttribute("role","row"),t.setAttribute("hidden",!0),t.classList.add("dg-fake-row"),t.tabIndex=0,s.appendChild(t),this.paginate()}paginate(){this.log("paginate");let t=this.totalRecords(),e=this.totalPages(),i,s=this.state.page*this.state.perPage,a=s-this.state.perPage+1,o=this.root.querySelector("tbody"),r=this.root.querySelector("tfoot");s>t&&(s=t),t||(a=0),o.querySelectorAll("tr").forEach(n=>{if(this.server){n.removeAttribute("hidden");return}i=Number(n.getAttribute("aria-rowindex")),i>s||ithis.querySelector("tbody").offsetHeight){let n=this.state.perPage-(t-(e-1)*this.state.perPage);l.setAttribute("height",n*this.rowHeight)}else l.removeAttribute("height");else l.removeAttribute("height");this.btnFirst&&(this.btnFirst.disabled=this.state.page<=1,this.btnPrev.disabled=this.state.page<=1,this.btnNext.disabled=this.state.page>=this.state.pages,this.btnLast.disabled=this.state.page>=this.state.pages),r.querySelector(".dg-low").textContent=a.toString(),r.querySelector(".dg-high").textContent=s.toString(),r.querySelector(".dg-total").textContent=this.totalRecords()}totalPages(){return Math.ceil(this.totalRecords()/this.state.perPage)}totalRecords(){return this.server?this.meta.filtered:this.data.length.toString()}log(t){this.debug&&console.log("["+this.getAttribute("id")+"] "+t)}};customElements.define("data-grid",h);var v=h;export{v as default};
+`;var h=class extends HTMLElement{constructor(t={}){super();this.appendChild(m.content.cloneNode(!0)),this.root=this,this.state={url:null,page:1,perPage:10,debug:!1,filter:!1,sort:!1,server:!1,defaultSort:"",reorder:!1,dir:"ltr",pages:0,perPageValues:[10,25,50,100,250],columns:[],actions:[]},this.setOptions(t),this.data=[],this.originalData=[],this.isInitialized=!1,this.touch=null,this.isResizing=!1,this.defaultHeight=0,this.meta={},this.hasAttribute("id")||this.setAttribute("id",h.randstr("dg-")),this.log("constructor")}static interpolate(t,e){return t.replace(/\{([^\}]+)?\}/g,function(i,s){return e[s]})}static getParentNode(t,e,i="nodeName"){let s=t;for(;s[i]!=e;)s=s.parentNode;return s}static getTextWidth(t,e=document.body){let i=window.getComputedStyle(e,null),s=i.getPropertyValue("font-weight")||"normal",a=i.getPropertyValue("font-size")||"1rem",o=i.getPropertyValue("font-family")||"Arial",l=(h.getTextWidth.canvas||(h.getTextWidth.canvas=document.createElement("canvas"))).getContext("2d");l.font=`${s} ${a} ${o}`;let n=l.measureText(t);return parseInt(n.width)}static addSelectOption(t,e,i,s=!1){let a=document.createElement("option");a.value=e,s&&(a.selected="selected"),a.label=i,t.appendChild(a)}static randstr(t){return Math.random().toString(36).replace("0.",t||"")}static convertArray(t){return typeof t=="string"?t[0]==="{"?JSON.parse(t):t.split(","):(Array.isArray(t)||console.error("Invalid array",t),t)}static elementOffset(t){var e=t.getBoundingClientRect(),i=window.pageXOffset||document.documentElement.scrollLeft,s=window.pageYOffset||document.documentElement.scrollTop;return{top:e.top+s,left:e.left+i}}static applyColumnDefinition(t,e){e.width&&t.setAttribute("width",e.width),e.class&&t.setAttribute("class",e.class)}static convertColumns(t){let e=[];return typeof t=="object"&&!Array.isArray(t)?Object.keys(t).forEach(i=>{let s={};s.title=t[i],s.field=i,e.push(s)}):t.forEach(i=>{let s={};typeof i=="string"?(s.title=i,s.field=i):typeof i=="object"?(s=i,s.field||console.error("Invalid column definition",i)):console.error("Column definition must be a string or an object"),e.push(s)}),e}static get observedAttributes(){return["url","page","per-page","debug","filter","sort","default-sort","dir","reorder"]}attributeChangedCallback(t,e,i){switch(this.log("attributeChangedCallback: "+t),t){case"url":this.state.url=i,this.isInitialized&&i&&this.loadData().then(()=>{this.configureUi()});break;case"page":this.state.page=Number(i),this.isInitialized&&this.loadData().finally(()=>{this.fixPage(),this.server?this.renderBody():this.paginate()});break;case"per-page":this.state.perPage=Number(i),this.isInitialized&&(this.selectPerPage.value=i,this.loadData().finally(()=>{this.fixPage(),this.server?this.renderBody():this.paginate(),this.sticky&&window.scroll({top:h.elementOffset(this.selectPerPage).top-this.defaultHeight})}));break;case"debug":this.state.debug=i==="true";break;case"dir":this.state.dir=i,this.root.querySelector(".dg-wrapper").dir=this.state.dir;break;case"filter":this.state.filter=i==="true",this.isInitialized&&this.toggleFilter();break;case"reorder":this.state.reorder=i==="true",this.isInitialized&&this.toggleReorder();break;case"sort":this.state.sort=i==="true",this.isInitialized&&this.toggleSort();break;case"default-sort":this.state.defaultSort=i,this.isInitialized&&this.toggleSort();break}}get page(){return this.getAttribute("page")}set page(t){this.setAttribute("page",t)}get perPage(){return this.getAttribute("per-page")}set perPage(t){this.setAttribute("per-page",t)}get debug(){return this.getAttribute("debug")==="true"}set debug(t){this.setAttribute("debug",t)}get dir(){return this.getAttribute("dir")}set dir(t){this.setAttribute("dir",t)}get filter(){return this.getAttribute("filter")==="true"}set filter(t){this.setAttribute("filter",t)}get reorder(){return this.getAttribute("reorder")==="true"}set reorder(t){this.setAttribute("reorder",t)}get sort(){return this.getAttribute("sort")==="true"}set sort(t){this.setAttribute("sort",t)}get defaultSort(){return this.getAttribute("default-sort")}set defaultSort(t){this.setAttribute("default-sort",t)}get url(){return this.getAttribute("url")}set url(t){t?this.setAttribute("url",t):this.removeAttribute("url")}get server(){return this.hasAttribute("server")}set server(t){t?this.setAttribute("server",""):this.removeAttribute("server")}get autosize(){return this.hasAttribute("autosize")}set autosize(t){t?this.setAttribute("autosize",""):this.removeAttribute("autosize")}get resizable(){return this.hasAttribute("resizable")}set resizable(t){t?this.setAttribute("resizable",""):this.removeAttribute("resizable")}get sticky(){return this.hasAttribute("sticky")}set sticky(t){t?this.setAttribute("sticky",""):this.removeAttribute("sticky")}get responsive(){return this.hasAttribute("responsive")}set responsive(t){t?this.setAttribute("responsive",""):this.removeAttribute("responsive")}get expand(){return this.hasAttribute("expand")}set expand(t){t?this.setAttribute("expand",""):this.removeAttribute("expand")}get selectable(){return this.hasAttribute("selectable")}set selectable(t){t?this.setAttribute("selectable",""):this.removeAttribute("selectable")}get perPageValues(){return this.state.perPageValues}set perPageValues(t){if(Array.isArray(t)&&(this.state.perPageValues=t,this.selectPerPage)){for(;this.selectPerPage.lastChild;)this.selectPerPage.removeChild(this.selectPerPage.lastChild);this.state.perPageValues.forEach(e=>{h.addSelectOption(this.selectPerPage,e,e)})}}get columns(){return this.state.columns}set columns(t){this.state.columns=h.convertColumns(h.convertArray(t))}get actions(){return this.state.actions}set actions(t){this.state.actions=h.convertArray(t)}connectedCallback(){this.log("connectedCallback"),this.btnFirst=this.root.querySelector(".dg-btn-first"),this.btnPrev=this.root.querySelector(".dg-btn-prev"),this.btnNext=this.root.querySelector(".dg-btn-next"),this.btnLast=this.root.querySelector(".dg-btn-last"),this.selectPerPage=this.root.querySelector(".dg-select-per-page"),this.inputPage=this.root.querySelector(".dg-input-page"),this.getFirst=this.getFirst.bind(this),this.getPrev=this.getPrev.bind(this),this.getNext=this.getNext.bind(this),this.getLast=this.getLast.bind(this),this.changePerPage=this.changePerPage.bind(this),this.gotoPage=this.gotoPage.bind(this),this.btnFirst.addEventListener("click",this.getFirst),this.btnPrev.addEventListener("click",this.getPrev),this.btnNext.addEventListener("click",this.getNext),this.btnLast.addEventListener("click",this.getLast),this.selectPerPage.addEventListener("change",this.changePerPage,{passive:!0}),this.inputPage.addEventListener("input",this.gotoPage),this.touchstart=this.touchstart.bind(this),this.touchmove=this.touchmove.bind(this),document.addEventListener("touchstart",this.touchstart),document.addEventListener("touchmove",this.touchmove),this.perPageValues=this.state.perPageValues,this.loadData().finally(()=>{this.configureUi(),this.toggleSort(),this.toggleFilter(),this.toggleReorder(),this.root.classList.add("dg-initialized"),this.isInitialized=!0})}disconnectedCallback(){this.log("disconnectedCallback"),this.btnFirst.removeEventListener("click",this.getFirst),this.btnPrev.removeEventListener("click",this.getPrev),this.btnNext.removeEventListener("click",this.getNext),this.btnLast.removeEventListener("click",this.getLast),this.selectPerPage.removeEventListener("change",this.changePerPage,{passive:!0}),this.inputPage.removeEventListener("input",this.gotoPage),document.removeEventListener("touchstart",this.touchstart),document.removeEventListener("touchmove",this.touchmove),this.selectAll&&this.selectAll.removeEventListener("change",this.toggleSelectAll),this.headerRow&&this.headerRow.removeEventListener("contextmenu",this.showContextMenu)}toggleSelectAll(){this.root.querySelectorAll("tbody .dg-selectable input").forEach(t=>{t.checked=this.selectAll.checked})}touchstart(t){this.touch=t.touches[0]}touchmove(t){if(!this.touch)return;let e=this.touch.clientX-t.touches[0].clientX,i=this.touch.clientY-t.touches[0].clientY;Math.abs(e)>Math.abs(i)&&(e>0?this.getNext():this.getPrev()),this.touch=null}setOptions(t){for(let[e,i]of Object.entries(t))e in this&&(this[e]=i,this.state[e]=i)}getColProp(t,e){let i=null;return this.state.columns.forEach(s=>{if(s.field==t){i=s[e];return}}),i}setColProp(t,e,i){this.state.columns.forEach(s=>{s.field==t&&(s[e]=i)})}startIndex(){return this.selectable?2:1}columnsLength(t=!1){let e=0;return this.state.columns.forEach(i=>{t&&i.hidden||i.attr||e++}),this.selectable&&e++,this.state.actions.length&&e++,e}computeDefaultHeight(){requestAnimationFrame(()=>{this.defaultHeight=this.root.querySelector("table").offsetHeight,this.style.height&&(this.style.height=this.defaultHeight+"px",this.style.overflowY="auto"),this.style.minHeight&&parseInt(this.style.minHeight)>this.defaultHeight&&(this.style.minHeight=this.defaultHeight+"px")})}configureUi(){this.createMenu(),this.root.querySelector("table").setAttribute("aria-rowcount",this.data.length),this.root.querySelector("tfoot").removeAttribute("hidden"),this.renderHeader(),this.rowHeight||(this.rowHeight=this.root.querySelector("tbody tr").offsetHeight)}fixPage(){this.state.pages=this.totalPages(),this.state.pages{t.classList.contains("dg-selectable")||t.classList.contains("dg-actions")||(this.state.reorder?t.draggable=!0:t.removeAttribute("draggable"))})}toggleSort(){this.log("toggle sort"),this.root.querySelectorAll("thead tr.dg-head-columns th").forEach(t=>{t.classList.contains("dg-selectable")||t.classList.contains("dg-actions")||(this.state.sort&&!this.getColProp(t.getAttribute("field"),"noSort")?t.setAttribute("aria-sort","none"):t.removeAttribute("aria-sort"))})}addRow(t){this.log("Add row"),this.originalData.push(t),this.data=this.originalData.slice(),this.fixPage(),this.sortData()}removeRow(t=null,e=null){e===null&&(e=this.columns[0].field),t===null&&(t=this.originalData[this.originalData.length-1][e]),this.log("Removing "+e+":"+t);for(let i=0;i{this.root.querySelector("tbody tr[aria-rowindex='"+(s+1)+"']").querySelector(".dg-selectable input").checked&&(t?e.push(i[t]):e.push(i))}),e}getData(){return this.originalData}clearData(){this.state.url=null,this.data.length!==0&&(this.data=this.originalData=[],this.fixPage(),this.renderHeader(),this.computeDefaultHeight())}loadData(){return!this.server&&this.originalData.length?(this.log("skip loadData"),new Promise((t,e)=>{t()})):(this.log("loadData"),this.fetchData().then(t=>{if(Array.isArray(t))this.data=t;else{if(!t.data){console.error("Invalid response, it should contain a data key with an array or be a plain array",t);return}t.options&&this.setOptions(t.options),t.meta&&(this.meta=t.meta),this.data=t.data}this.originalData=this.data.slice(),this.fixPage(),this.state.columns.length===0&&this.originalData.length&&(this.state.columns=h.convertColumns(Object.keys(this.originalData[0])))}).catch(t=>{this.url=null,this.log(t)}))}getFirst(){this.page=1}getLast(){this.page=this.state.pages}getPrev(){this.page=this.state.page-1}getNext(){this.page=this.state.page+1}refresh(){return this.data=this.originalData=[],this.loadData()}changePerPage(){this.perPage=this.selectPerPage.options[this.selectPerPage.selectedIndex].value}gotoPage(t){if(t.type==="keypress"){let e=t.keyCode||t.key;if(e===13||e==="Enter")t.preventDefault();else return}this.page=this.inputPage.value}getSort(){let t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']");return t?t.getAttribute("field"):this.defaultSort}getSortDir(){let t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']");return t&&t.getAttribute("aria-sort")||""}getFilters(){let t=[];return this.root.querySelectorAll("thead tr.dg-head-filters input").forEach(e=>{t[e.dataset.name]=e.value}),t}clearFilters(){this.root.querySelectorAll("thead tr.dg-head-filters input").forEach(t=>{t.value=""}),this.filterData()}filterData(){if(this.log("filter data"),this.server)this.loadData().finally(()=>{this.fixPage(),this.renderBody()});else{this.data=this.originalData.slice(),this.root.querySelectorAll("thead tr.dg-head-filters input").forEach(e=>{let i=e.value;if(i){let s=e.dataset.name;this.data=this.data.filter(a=>(a[s]+"").toLowerCase().indexOf(i.toLowerCase())!==-1)}}),this.fixPage();let t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']");this.state.sort&&t?this.sortData(t):this.renderBody()}}sortData(t=null){if(this.log("sort data"),!(t&&this.getColProp(t.getAttribute("field"),"noSort")))if(t!==null?(this.root.querySelectorAll("thead tr:first-child th").forEach(e=>{e.classList.contains("dg-selectable")||e.classList.contains("dg-actions")||e!==t&&e.setAttribute("aria-sort","none")}),!t.hasAttribute("aria-sort")||t.getAttribute("aria-sort")==="none"?t.setAttribute("aria-sort","ascending"):t.getAttribute("aria-sort")==="ascending"?t.setAttribute("aria-sort","descending"):t.getAttribute("aria-sort")==="descending"&&t.setAttribute("aria-sort","none")):t=this.root.querySelector("thead tr.dg-head-columns th[aria-sort$='scending']"),this.server)this.loadData().finally(()=>{this.renderBody()});else{let e=t?t.getAttribute("aria-sort"):"none";if(e==="none"){let i=[];this.originalData.some(s=>(this.data.some(a=>JSON.stringify(s)===JSON.stringify(a)?(i.push(a),!0):!1),i.length===this.data.length)),this.data=i}else{let i=t.getAttribute("field");this.data.sort((s,a)=>{if(!isNaN(s[i])&&!isNaN(a[i]))return e==="ascending"?s[i]-a[i]:a[i]-s[i];let o=e==="ascending"?s[i].toUpperCase():a[i].toUpperCase(),r=e==="ascending"?a[i].toUpperCase():s[i].toUpperCase();switch(!0){case o>r:return 1;case os("No url set"));let t=new URL(this.url,window.location.href),e={r:Math.ceil(Math.random()*9999999)};return this.server&&(e.start=this.state.page-1,e.length=this.state.perPage,e.search=this.getFilters(),e.sort=this.getSort()||"",e.sortDir=this.getSortDir()),Object.keys(e).forEach(i=>{Array.isArray(e[i])?Object.keys(e[i]).forEach(s=>t.searchParams.append(i+"["+s+"]",e[i][s])):t.searchParams.append(i,e[i])}),fetch(t).then(i=>i.json())}renderHeader(){this.log("render header");let t,e,i=this.root.querySelector("thead");this.createColumnHeaders(i),this.state.defaultSort&&(e=this.root.querySelector("thead tr.dg-head-columns th[field='"+this.state.defaultSort+"']")),this.createColumnFilters(i),this.root.querySelector("table").setAttribute("aria-colcount",this.columnsLength(!0).toString()),this.root.querySelector("tfoot").querySelector("td").setAttribute("colspan",this.columnsLength(!0).toString()),e?this.sortData(e):this.renderBody(),this.root.querySelector("tfoot").style.display="",this.resizable&&this.renderResizer()}createColumnHeaders(t){let e=parseInt(t.offsetWidth/this.columnsLength(!0)*2),i=0,s;if(s=document.createElement("tr"),this.headerRow=s,s.setAttribute("role","row"),s.setAttribute("aria-rowindex",1),s.setAttribute("class","dg-head-columns"),this.selectable){let o=document.createElement("th");o.setAttribute("role","columnheader button"),o.setAttribute("aria-colindex",1),o.classList.add("dg-selectable"),o.tabIndex=0,this.selectAll=document.createElement("input"),this.selectAll.type="checkbox",this.selectAll.classList.add("dg-select-all"),this.toggleSelectAll=this.toggleSelectAll.bind(this),this.selectAll.addEventListener("change",this.toggleSelectAll);let r=document.createElement("label");r.appendChild(this.selectAll),o.appendChild(r),o.setAttribute("width",40),s.appendChild(o)}i=0;let a=0;if(this.state.columns.forEach((o,r)=>{if(o.attr)return;let l=document.createElement("th");l.setAttribute("role","columnheader button"),l.setAttribute("aria-colindex",i+this.startIndex()),l.setAttribute("id",h.randstr("dg-col-")),this.state.sort&&l.setAttribute("aria-sort","none"),l.setAttribute("field",o.field),l.dataset.minWidth=h.getTextWidth(o.title,l)+40,h.applyColumnDefinition(l,o),l.tabIndex=0,l.textContent=o.title,o.hidden&&l.setAttribute("hidden",!0),this.autosize&&!l.getAttribute("width")&&(a+=this.autosizeColumn(l,o,l.dataset.minWidth,e)),this.state.reorder&&this.makeHeaderDraggable(l),s.appendChild(l),i++}),a{o.addEventListener("click",()=>this.sortData(o))})}createColumnFilters(t){let e=0,i;if(i=document.createElement("tr"),this.filterRow=i,i.setAttribute("role","row"),i.setAttribute("aria-rowindex",2),i.setAttribute("class","dg-head-filters"),this.state.filter||i.setAttribute("hidden",!0),this.selectable){let s=document.createElement("th");s.setAttribute("role","columnheader button"),s.setAttribute("aria-colindex",1),s.classList.add("dg-selectable"),s.tabIndex=0,i.appendChild(s)}if(this.state.columns.forEach((s,a)=>{if(s.attr)return;let o=t.querySelector("tr.dg-head-columns th[aria-colindex='"+(e+this.startIndex())+"']"),r=document.createElement("th");r.setAttribute("aria-colindex",e+this.startIndex());let l=document.createElement("input");l.type="text",l.autocomplete="off",l.spellcheck=!1,l.dataset.name=s.field,l.id=h.randstr("dg-filter-"),l.setAttribute("aria-labelledby",o.getAttribute("id")),this.state.filter?l.tabIndex=0:r.tabIndex=0,s.hidden&&r.setAttribute("hidden",!0),r.appendChild(l),i.appendChild(r),e++}),this.state.actions.length){let s=document.createElement("th");s.setAttribute("role","columnheader button"),s.setAttribute("aria-colindex",this.columnsLength(!0)),s.classList.add("dg-actions"),s.tabIndex=0,i.appendChild(s)}t.replaceChild(i,t.querySelector("tr.dg-head-filters")),i.querySelectorAll("input").forEach(s=>{s.addEventListener("keypress",a=>{let o=a.keyCode||a.key;(o===13||o==="Enter")&&this.filterData.call(this)})})}autosizeColumn(t,e,i,s){let a=this.data[0][e.field].toString(),o=this.data[this.data.length-1][e.field].toString();o.length>a.length&&(a=o);let r=0;return a.length<=6?r=i:a.length>50?r=s:r=h.getTextWidth(a,t),rs.width&&(a-=i.offsetWidth,i.style.left=`${a}px`);let r=l=>{i.contains(l.target)||(i.setAttribute("hidden",!0),document.removeEventListener("click",r))};document.addEventListener("click",r)}createMenu(){let t=this.root.querySelector(".dg-menu");this.state.columns.forEach(e=>{if(e.attr)return;let i=e.field,s=document.createElement("li"),a=document.createElement("label"),o=document.createElement("input");o.setAttribute("type","checkbox"),e.hidden||(o.checked=!0),o.addEventListener("change",l=>{l.target.checked?this.showColumn(i,l.target):this.hideColumn(i,l.target)});let r=document.createTextNode(e.title);a.appendChild(o),a.appendChild(r),s.appendChild(a),t.appendChild(s)})}showColumn(t,e=null){e&&(e.checked=!0),this.setColProp(t,"hidden",!1),this.renderHeader()}hideColumn(t,e=null){if(this.state.columns.filter(s=>s.hidden===!0).length===this.columnsLength()-1){e&&(e.checked=!0);return}this.setColProp(t,"hidden",!0),this.renderHeader()}makeHeaderDraggable(t){t.draggable=!0,t.addEventListener("dragstart",e=>{if(this.isResizing&&e.preventDefault){e.preventDefault();return}this.log("reorder col"),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",e.target.getAttribute("aria-colindex"))}),t.addEventListener("dragover",e=>(e.preventDefault&&e.preventDefault(),e.dataTransfer.dropEffect="move",!1)),t.addEventListener("drop",e=>{e.stopPropagation&&e.stopPropagation();let i=h.getParentNode(e.target,"TH"),s=e.dataTransfer.getData("text/plain"),a=i.getAttribute("aria-colindex");if(s===a){this.log("reordered col stayed the same");return}this.log("reordered col from "+s+" to "+a);let o=this.state.columns[s-1];this.state.columns[s-1]=this.columns[a-1],this.state.columns[a-1]=o;let r=(l,n)=>{let u=n.parentNode.getAttribute("aria-rowindex"),d=this.root.querySelector(l+" tr[aria-rowindex='"+u+"'] [aria-colindex='"+a+"']");n.setAttribute("aria-colindex",a),d.setAttribute("aria-colindex",s);let g=document.createElement("th");n.parentNode.insertBefore(g,n),d.parentNode.replaceChild(n,d),g.parentNode.replaceChild(d,g)};return this.root.querySelectorAll("thead th[aria-colindex='"+s+"']").forEach(l=>{r("thead",l)}),this.root.querySelectorAll('tbody td[aria-colindex="'+s+'"]').forEach(l=>{r("tbody",l)}),!1})}renderResizer(){let t=this.root.querySelector("table"),e=this.root.querySelectorAll("thead tr.dg-head-columns th");e.forEach(i=>{if(i.classList.contains("dg-selectable")||i.classList.contains("dg-actions"))return;let s=document.createElement("div");s.classList.add("dg-resizer"),s.ariaLabel=c.resizeColumn,i.appendChild(s);let a=0,o=0,r=0,l=0,n=d=>{if(d.clientX>l)return;let g=o+(d.clientX-a);i.dataset.minWidth&&g>i.dataset.minWidth&&(i.width=g)},u=()=>{this.log("resized column"),this.isResizing=!1,s.classList.remove("dg-resizer-active"),this.state.reorder&&(i.draggable=!0),i.style.overflow="hidden",document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",u)};s.addEventListener("click",d=>{d.stopPropagation()}),s.addEventListener("mousedown",d=>{d.stopPropagation(),this.isResizing=!0;let g=this.root.querySelectorAll(".dg-head-columns th"),b=Array.from(g).filter(f=>!f.hasAttribute("hidden")),p=Array.from(b).findIndex(f=>f==d.target.parentNode);this.log("resize column"),s.classList.add("dg-resizer-active"),i.hasAttribute("draggable")&&i.removeAttribute("draggable"),i.style.overflow="visible",s.style.height=t.offsetHeight-1+"px",a=d.clientX,o=i.offsetWidth,r=(b.length-p)*30,l=h.elementOffset(this).left+this.offsetWidth-r,i.setAttribute("width",o);for(let f=0;fp&&e[f].removeAttribute("width");document.addEventListener("mousemove",n),document.addEventListener("mouseup",u)})})}renderBody(){this.log("render body");let t,e,i,s=document.createElement("tbody");this.data.forEach((a,o)=>{if(t=document.createElement("tr"),t.setAttribute("role","row"),t.setAttribute("hidden",!0),t.setAttribute("aria-rowindex",o+1),t.tabIndex=0,this.selectable){e=document.createElement("td"),e.setAttribute("role","gridcell button"),e.setAttribute("aria-colindex",1),e.classList.add("dg-selectable");let r=document.createElement("input");r.type="checkbox";let l=document.createElement("label");l.appendChild(r),e.appendChild(l),t.appendChild(e)}this.expand&&t.addEventListener("click",function(r){this.classList.toggle("dg-expanded")}),i=0,this.state.columns.forEach((r,l)=>{if(r||console.log(this.state.columns),r.attr){t.setAttribute(r.attr,a[r.field]);return}if(e=document.createElement("td"),e.setAttribute("role","gridcell"),e.setAttribute("aria-colindex",i+this.startIndex()),h.applyColumnDefinition(e,r),e.setAttribute("data-name",r.title),e.tabIndex=-1,r.editable){let n=document.createElement("input");n.type="text",n.autocomplete="off",n.spellcheck=!1,n.tabIndex=0,n.classList.add("dg-editable"),n.name=this.getAttribute("id").replace("-","_")+"["+(o+1)+"]["+r.field+"]",n.value=a[r.field],n.dataset.field=r.field,n.addEventListener("click",u=>u.stopPropagation()),n.addEventListener("keypress",u=>{if(u.type==="keypress"){let d=u.keyCode||u.key;(d===13||d==="Enter")&&n.blur()}}),n.addEventListener("blur",u=>{if(n.value==a[n.dataset.field])return;a[n.dataset.field]=n.value;let d=new CustomEvent("edit",{bubbles:!0,detail:{data:a,value:n.value}});this.dispatchEvent(d)}),e.appendChild(n)}else e.textContent=a[r.field];r.hidden&&e.setAttribute("hidden",!0),t.appendChild(e),i++}),this.state.actions.length&&(e=document.createElement("td"),e.setAttribute("role","gridcell"),e.setAttribute("aria-colindex",this.columnsLength(!0)),e.classList.add("dg-actions"),e.tabIndex=0,this.state.actions.forEach(r=>{let l=document.createElement("button");r.html?l.innerHTML=r.html:l.innerText=r.title??r.name,r.url&&(l.type="submit",l.formAction=h.interpolate(r.url,a)),r.class&&l.classList.add(r.class);let n=u=>{if(u.stopPropagation(),r.confirm&&!confirm(c.areYouSure)){u.preventDefault();return}let d=new CustomEvent("action",{bubbles:!0,detail:{data:a,action:r.name}});this.dispatchEvent(d)};l.addEventListener("click",n),e.appendChild(l),r.default&&(t.classList.add("dg-actionable"),t.addEventListener("click",n))}),t.appendChild(e)),s.appendChild(t)}),s.setAttribute("role","rowgroup"),this.root.querySelector("table").replaceChild(s,this.root.querySelector("tbody")),t=document.createElement("tr"),t.setAttribute("role","row"),t.setAttribute("hidden",!0),t.classList.add("dg-fake-row"),t.tabIndex=0,s.appendChild(t),this.paginate()}paginate(){this.log("paginate");let t=this.totalRecords(),e=this.totalPages(),i,s=this.state.page*this.state.perPage,a=s-this.state.perPage+1,o=this.root.querySelector("tbody"),r=this.root.querySelector("tfoot");s>t&&(s=t),t||(a=0),o.querySelectorAll("tr").forEach(n=>{if(this.server){n.removeAttribute("hidden");return}i=Number(n.getAttribute("aria-rowindex")),i>s||ithis.querySelector("tbody").offsetHeight){let n=this.state.perPage-(t-(e-1)*this.state.perPage);l.setAttribute("height",n*this.rowHeight)}else l.removeAttribute("height");else l.removeAttribute("height");this.btnFirst&&(this.btnFirst.disabled=this.state.page<=1,this.btnPrev.disabled=this.state.page<=1,this.btnNext.disabled=this.state.page>=this.state.pages,this.btnLast.disabled=this.state.page>=this.state.pages),r.querySelector(".dg-low").textContent=a.toString(),r.querySelector(".dg-high").textContent=s.toString(),r.querySelector(".dg-total").textContent=this.totalRecords()}totalPages(){return Math.ceil(this.totalRecords()/this.state.perPage)}totalRecords(){return this.server?this.meta.filtered:this.data.length.toString()}log(t){this.debug&&console.log("["+this.getAttribute("id")+"] "+t)}};customElements.define("data-grid",h);var v=h;export{v as default};
//# sourceMappingURL=data-grid.min.js.map
diff --git a/data-grid.min.js.map b/data-grid.min.js.map
index a19ecbd..ab49e71 100644
--- a/data-grid.min.js.map
+++ b/data-grid.min.js.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["data-grid.js"],
- "sourcesContent": ["/**\n * Data Grid Web component\n *\n * Credits for inspiration\n * @link https://github.com/riverside/zino-grid\n */\n\"use strict\";\n\n/**\n * @typedef Column\n * @property {string} field - the key in the data\n * @property {string} title - the title to display in the header (defaults to \"field\" if not set)\n * @property {number} width - the width of the column (auto otherwise)\n * @property {string} class - class to set on the column (target body or header with th.class or td.class)\n * @property {string} attr - don't render the column and set a matching attribute on the row with the value of the field\n * @property {boolean} hidden - hide the column\n * @property {boolean} editable - replace with input\n * @property {boolean} noSort - allow disabling sort for a given column\n */\n\n/**\n * @typedef Action\n * @property {string} title - the title of the button\n * @property {string} url - link for the action\n * @property {string} html - custom button data\n * @property {boolean} confirm - needs confirmation\n * @property {boolean} default - is the default row action\n */\n\nconst labels = Object.assign(\n {\n itemsPerPage: \"Items per page\",\n gotoPage: \"Go to page\",\n gotoFirstPage: \"Go to first page\",\n gotoPrevPage: \"Go to previous page\",\n gotoNextPage: \"Go to next page\",\n gotoLastPage: \"Go to last page\",\n of: \"of\",\n items: \"items\",\n resizeColumn: \"Resize column\",\n noData: \"No data\",\n areYouSure: \"Are you sure?\",\n },\n window.DataGridLabels || {}\n);\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = `\n\n \n
\n
\n \n \n \n \n \n \n | \n
\n \n \n
\n`;\n\n/**\n * @property {Column[]} state.columns\n * @property {Action[]} state.actions\n */\nclass DataGrid extends HTMLElement {\n constructor(options = {}) {\n super();\n\n // Don't use shadow dom as it makes theming super hard\n this.appendChild(template.content.cloneNode(true));\n this.root = this;\n\n this.state = {\n // reflected and observed\n url: null,\n page: 1,\n perPage: 10,\n debug: false,\n filter: false,\n sort: false,\n server: false,\n defaultSort: \"\",\n reorder: false,\n dir: \"ltr\",\n // not reflected\n pages: 0,\n perPageValues: [10, 25, 50, 100, 250],\n columns: [],\n actions: [],\n };\n this.setOptions(options);\n\n // The grid displays data\n this.data = [];\n // We store the data in this\n this.originalData = [];\n\n // Init values\n this.isInitialized = false;\n this.touch = null;\n this.isResizing = false;\n this.defaultHeight = 0;\n this.meta = {};\n\n // Set id\n if (!this.hasAttribute(\"id\")) {\n this.setAttribute(\"id\", DataGrid.randstr(\"dg-\"));\n }\n\n this.log(\"constructor\");\n }\n\n // utils\n\n /**\n * @param {string} str\n * @param {Object} data\n * @returns {string}\n */\n static interpolate(str, data) {\n return str.replace(/\\{([^\\}]+)?\\}/g, function ($1, $2) {\n return data[$2];\n });\n }\n\n /**\n * @param {HTMLElement} el\n * @param {string} type\n * @param {string} prop\n * @returns {HTMLElement}\n */\n static getParentNode(el, type, prop = \"nodeName\") {\n let parent = el;\n while (parent[prop] != type) {\n parent = parent.parentNode;\n }\n return parent;\n }\n\n /**\n * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.\n * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\n * @param {string} text The text to be rendered.\n * @param {HTMLElement} el Target element (defaults to body)\n * @return {number}\n */\n static getTextWidth(text, el = document.body) {\n const styles = window.getComputedStyle(el, null);\n const fontWeight = styles.getPropertyValue(\"font-weight\") || \"normal\";\n const fontSize = styles.getPropertyValue(\"font-size\") || \"1rem\";\n const fontFamily = styles.getPropertyValue(\"font-family\") || \"Arial\";\n\n // re-use canvas object for better performance\n const canvas = DataGrid.getTextWidth.canvas || (DataGrid.getTextWidth.canvas = document.createElement(\"canvas\"));\n const context = canvas.getContext(\"2d\");\n context.font = `${fontWeight} ${fontSize} ${fontFamily}`;\n const metrics = context.measureText(text);\n return parseInt(metrics.width);\n }\n\n /**\n * @param {HTMLElement} el\n * @param {string} value\n * @param {string} label\n * @param {boolean} checked\n */\n static addSelectOption(el, value, label, checked = false) {\n let opt = document.createElement(\"option\");\n opt.value = value;\n if (checked) {\n opt.selected = \"selected\";\n }\n opt.label = label;\n el.appendChild(opt);\n }\n /**\n * @param {string} prefix\n * @returns {string}\n */\n static randstr(prefix) {\n return Math.random()\n .toString(36)\n .replace(\"0.\", prefix || \"\");\n }\n /**\n * @param {string|Array} v\n * @returns\n */\n static convertArray(v) {\n if (typeof v === \"string\") {\n if (v[0] === \"{\") {\n return JSON.parse(v);\n }\n return v.split(\",\");\n }\n if (!Array.isArray(v)) {\n console.error(\"Invalid array\", v);\n }\n return v;\n }\n /**\n * @param {HTMLElement} el\n * @returns {Object}\n */\n static elementOffset(el) {\n var rect = el.getBoundingClientRect(),\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\n }\n /**\n * @param {HTMLElement} el\n * @param {Object} definition\n */\n static applyColumnDefinition(el, definition) {\n if (definition.width) {\n el.setAttribute(\"width\", definition.width);\n }\n if (definition.class) {\n el.setAttribute(\"class\", definition.class);\n }\n }\n /**\n * @param {Object|Array} columns\n * @returns {Object}\n */\n static convertColumns(columns) {\n let cols = [];\n // Convert objects to array\n if (typeof columns === \"object\" && !Array.isArray(columns)) {\n Object.keys(columns).forEach((key) => {\n let col = {};\n col.title = columns[key];\n col.field = key;\n cols.push(col);\n });\n } else {\n columns.forEach((item) => {\n let col = {};\n if (typeof item === \"string\") {\n col.title = item;\n col.field = item;\n } else if (typeof item === \"object\") {\n col = item;\n if (!col.field) {\n console.error(\"Invalid column definition\", item);\n }\n } else {\n console.error(\"Column definition must be a string or an object\");\n }\n cols.push(col);\n });\n }\n return cols;\n }\n\n // reflected attrs, see https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dom-attributes\n\n static get observedAttributes() {\n return [\"url\", \"page\", \"per-page\", \"debug\", \"filter\", \"sort\", \"default-sort\", \"dir\", \"reorder\"];\n }\n attributeChangedCallback(attributeName, oldValue, newValue) {\n this.log(\"attributeChangedCallback: \" + attributeName);\n\n // Update state but only trigger events if initialized\n switch (attributeName) {\n case \"url\":\n this.state.url = newValue;\n if (this.isInitialized && newValue) {\n this.loadData().then(() => {\n this.configureUi();\n });\n }\n break;\n case \"page\":\n this.state.page = Number(newValue);\n if (this.isInitialized) {\n this.loadData().finally(() => {\n this.fixPage();\n this.server ? this.renderBody() : this.paginate();\n });\n }\n break;\n case \"per-page\":\n this.state.perPage = Number(newValue);\n if (this.isInitialized) {\n this.selectPerPage.value = newValue;\n this.loadData().finally(() => {\n this.fixPage();\n this.server ? this.renderBody() : this.paginate();\n\n // Scroll and keep a sizable amount of data displayed\n if (this.sticky) {\n window.scroll({ top: DataGrid.elementOffset(this.selectPerPage).top - this.defaultHeight });\n }\n });\n }\n break;\n case \"debug\":\n this.state.debug = newValue === \"true\";\n break;\n case \"dir\":\n this.state.dir = newValue;\n this.root.querySelector(\".dg-wrapper\").dir = this.state.dir;\n break;\n case \"filter\":\n this.state.filter = newValue === \"true\";\n if (this.isInitialized) {\n this.toggleFilter();\n }\n break;\n case \"reorder\":\n this.state.reorder = newValue === \"true\";\n if (this.isInitialized) {\n this.toggleReorder();\n }\n break;\n case \"sort\":\n this.state.sort = newValue === \"true\";\n if (this.isInitialized) {\n this.toggleSort();\n }\n break;\n case \"default-sort\":\n this.state.defaultSort = newValue;\n if (this.isInitialized) {\n this.toggleSort();\n }\n break;\n }\n }\n get page() {\n return this.getAttribute(\"page\");\n }\n set page(val) {\n this.setAttribute(\"page\", val);\n }\n get perPage() {\n return this.getAttribute(\"per-page\");\n }\n set perPage(val) {\n this.setAttribute(\"per-page\", val);\n }\n get debug() {\n return this.getAttribute(\"debug\") === \"true\";\n }\n set debug(val) {\n this.setAttribute(\"debug\", val);\n }\n get dir() {\n return this.getAttribute(\"dir\");\n }\n set dir(val) {\n this.setAttribute(\"dir\", val);\n }\n get filter() {\n return this.getAttribute(\"filter\") === \"true\";\n }\n set filter(val) {\n this.setAttribute(\"filter\", val);\n }\n get reorder() {\n return this.getAttribute(\"reorder\") === \"true\";\n }\n set reorder(val) {\n this.setAttribute(\"reorder\", val);\n }\n get sort() {\n return this.getAttribute(\"sort\") === \"true\";\n }\n set sort(val) {\n this.setAttribute(\"sort\", val);\n }\n get defaultSort() {\n return this.getAttribute(\"default-sort\");\n }\n set defaultSort(val) {\n this.setAttribute(\"default-sort\", val);\n }\n get url() {\n return this.getAttribute(\"url\");\n }\n set url(val) {\n val ? this.setAttribute(\"url\", val) : this.removeAttribute(\"url\");\n }\n\n // Boolean\n\n get server() {\n return this.hasAttribute(\"server\");\n }\n set server(val) {\n val ? this.setAttribute(\"server\", \"\") : this.removeAttribute(\"server\");\n }\n get autosize() {\n return this.hasAttribute(\"autosize\");\n }\n set autosize(val) {\n val ? this.setAttribute(\"autosize\", \"\") : this.removeAttribute(\"autosize\");\n }\n get resizable() {\n return this.hasAttribute(\"resizable\");\n }\n set resizable(val) {\n val ? this.setAttribute(\"resizable\", \"\") : this.removeAttribute(\"resizable\");\n }\n get sticky() {\n return this.hasAttribute(\"sticky\");\n }\n set sticky(val) {\n val ? this.setAttribute(\"sticky\", \"\") : this.removeAttribute(\"sticky\");\n }\n get responsive() {\n return this.hasAttribute(\"responsive\");\n }\n set responsive(val) {\n val ? this.setAttribute(\"responsive\", \"\") : this.removeAttribute(\"responsive\");\n }\n get expand() {\n return this.hasAttribute(\"expand\");\n }\n set expand(val) {\n val ? this.setAttribute(\"expand\", \"\") : this.removeAttribute(\"expand\");\n }\n get selectable() {\n return this.hasAttribute(\"selectable\");\n }\n set selectable(val) {\n val ? this.setAttribute(\"selectable\", \"\") : this.removeAttribute(\"selectable\");\n }\n\n // Not reflected\n\n get perPageValues() {\n return this.state.perPageValues;\n }\n set perPageValues(val) {\n if (Array.isArray(val)) {\n this.state.perPageValues = val;\n if (this.selectPerPage) {\n while (this.selectPerPage.lastChild) {\n this.selectPerPage.removeChild(this.selectPerPage.lastChild);\n }\n this.state.perPageValues.forEach((v) => {\n DataGrid.addSelectOption(this.selectPerPage, v, v);\n });\n }\n }\n }\n get columns() {\n return this.state.columns;\n }\n set columns(val) {\n this.state.columns = DataGrid.convertColumns(DataGrid.convertArray(val));\n }\n get actions() {\n return this.state.actions;\n }\n set actions(val) {\n this.state.actions = DataGrid.convertArray(val);\n }\n connectedCallback() {\n this.log(\"connectedCallback\");\n\n this.btnFirst = this.root.querySelector(\".dg-btn-first\");\n this.btnPrev = this.root.querySelector(\".dg-btn-prev\");\n this.btnNext = this.root.querySelector(\".dg-btn-next\");\n this.btnLast = this.root.querySelector(\".dg-btn-last\");\n this.selectPerPage = this.root.querySelector(\".dg-select-per-page\");\n this.inputPage = this.root.querySelector(\".dg-input-page\");\n\n this.getFirst = this.getFirst.bind(this);\n this.getPrev = this.getPrev.bind(this);\n this.getNext = this.getNext.bind(this);\n this.getLast = this.getLast.bind(this);\n this.changePerPage = this.changePerPage.bind(this);\n this.gotoPage = this.gotoPage.bind(this);\n\n this.btnFirst.addEventListener(\"click\", this.getFirst);\n this.btnPrev.addEventListener(\"click\", this.getPrev);\n this.btnNext.addEventListener(\"click\", this.getNext);\n this.btnLast.addEventListener(\"click\", this.getLast);\n this.selectPerPage.addEventListener(\"change\", this.changePerPage, {\n passive: true,\n });\n this.inputPage.addEventListener(\"input\", this.gotoPage);\n\n // Touch support\n this.touchstart = this.touchstart.bind(this);\n this.touchmove = this.touchmove.bind(this);\n document.addEventListener(\"touchstart\", this.touchstart);\n document.addEventListener(\"touchmove\", this.touchmove);\n\n // Populate\n this.perPageValues = this.state.perPageValues;\n\n this.loadData().finally(() => {\n this.configureUi();\n\n this.toggleSort();\n this.toggleFilter();\n this.toggleReorder();\n\n this.root.classList.add(\"dg-initialized\");\n this.isInitialized = true;\n });\n }\n disconnectedCallback() {\n this.log(\"disconnectedCallback\");\n\n this.btnFirst.removeEventListener(\"click\", this.getFirst);\n this.btnPrev.removeEventListener(\"click\", this.getPrev);\n this.btnNext.removeEventListener(\"click\", this.getNext);\n this.btnLast.removeEventListener(\"click\", this.getLast);\n this.selectPerPage.removeEventListener(\"change\", this.changePerPage, {\n passive: true,\n });\n this.inputPage.removeEventListener(\"input\", this.gotoPage);\n\n // Touch support\n document.removeEventListener(\"touchstart\", this.touchstart);\n document.removeEventListener(\"touchmove\", this.touchmove);\n\n // Selectable\n if (this.selectAll) {\n this.selectAll.removeEventListener(\"change\", this.toggleSelectAll);\n }\n\n // Context menu\n if (this.headerRow) {\n this.headerRow.removeEventListener(\"contextmenu\", this.showContextMenu);\n }\n\n // TODO: what about the others listeners?\n }\n toggleSelectAll() {\n this.root.querySelectorAll(\"tbody .dg-selectable input\").forEach((cb) => {\n cb.checked = this.selectAll.checked;\n });\n }\n touchstart(e) {\n this.touch = e.touches[0];\n }\n touchmove(e) {\n if (!this.touch) {\n return;\n }\n const xDiff = this.touch.clientX - e.touches[0].clientX;\n const yDiff = this.touch.clientY - e.touches[0].clientY;\n\n if (Math.abs(xDiff) > Math.abs(yDiff)) {\n if (xDiff > 0) {\n this.getNext();\n } else {\n this.getPrev();\n }\n }\n this.touch = null;\n }\n\n /**\n * @param {Object} options\n */\n setOptions(options) {\n for (const [key, value] of Object.entries(options)) {\n if (key in this) {\n this[key] = value;\n this.state[key] = value;\n }\n }\n }\n getColProp(field, prop) {\n let v = null;\n this.state.columns.forEach((col) => {\n if (col.field == field) {\n v = col[prop];\n return;\n }\n });\n return v;\n }\n setColProp(field, prop, val) {\n this.state.columns.forEach((col) => {\n if (col.field == field) {\n col[prop] = val;\n }\n });\n }\n startIndex() {\n return this.selectable ? 2 : 1;\n }\n columnsLength(visibleOnly = false) {\n let len = 0;\n this.state.columns.forEach((col) => {\n if (visibleOnly && col.hidden) {\n return;\n }\n if (!col.attr) {\n len++;\n }\n });\n if (this.selectable) {\n len++;\n }\n if (this.state.actions.length) {\n len++;\n }\n return len;\n }\n computeDefaultHeight() {\n this.defaultHeight = this.root.querySelector(\"table\").offsetHeight;\n\n // If we have a fixed height, make sure we have overflowY set\n if (this.style.height) {\n this.style.height = this.defaultHeight + \"px\";\n this.style.overflowY = \"auto\";\n // Otherwise incomplete row would not look good\n this.root.querySelector(\"table\").style.height = \"100%\";\n }\n // If our min height is too small, make sure we adjust the value\n if (this.style.minHeight && parseInt(this.style.minHeight) > this.defaultHeight) {\n this.style.minHeight = this.defaultHeight + \"px\";\n }\n }\n configureUi() {\n this.createMenu();\n this.root.querySelector(\"table\").setAttribute(\"aria-rowcount\", this.data.length);\n this.root.querySelector(\"tfoot\").removeAttribute(\"hidden\");\n this.renderHeader();\n\n // Store row height for later usage\n if (!this.rowHeight) {\n this.rowHeight = this.root.querySelector(\"tbody tr\").offsetHeight;\n }\n }\n /**\n * This needs to be called each time the data changes or the perPage value changes\n */\n fixPage() {\n this.state.pages = this.totalPages();\n\n // Constrain values\n if (this.state.pages < this.state.page) {\n this.state.page = this.state.pages;\n }\n if (this.state.page < 1) {\n this.state.page = 1;\n }\n\n // Show current page in input\n this.inputPage.setAttribute(\"max\", this.state.pages);\n this.inputPage.value = this.state.page;\n this.inputPage.disabled = this.state.pages === 1;\n }\n toggleFilter() {\n const row = this.root.querySelector(\"thead tr.dg-head-filters\");\n if (this.state.filter) {\n row.removeAttribute(\"hidden\");\n } else {\n row.setAttribute(\"hidden\", true);\n }\n }\n toggleReorder() {\n this.root.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (this.state.reorder) {\n th.draggable = true;\n } else {\n th.removeAttribute(\"draggable\");\n }\n });\n }\n toggleSort() {\n this.log(\"toggle sort\");\n this.root.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (this.state.sort && !this.getColProp(th.getAttribute(\"field\"), \"noSort\")) {\n th.setAttribute(\"aria-sort\", \"none\");\n } else {\n th.removeAttribute(\"aria-sort\");\n }\n });\n }\n addRow(row) {\n this.log(\"Add row\");\n this.originalData.push(row);\n this.data = this.originalData.slice();\n this.fixPage();\n this.sortData();\n }\n removeRow(value = null, key = null) {\n if (key === null) {\n key = this.columns[0][\"field\"];\n }\n if (value === null) {\n value = this.originalData[this.originalData.length - 1][key];\n }\n this.log(\"Removing \" + key + \":\" + value);\n for (let i = 0; i < this.originalData.length; i++) {\n if (this.originalData[i][key] === value) {\n this.originalData.splice(i, 1);\n break;\n }\n }\n this.data = this.originalData.slice();\n this.fixPage();\n this.sortData();\n }\n getSelection(key = null) {\n let selectedData = [];\n this.data.forEach((item, i) => {\n const row = this.root.querySelector(\"tbody tr[aria-rowindex='\" + (i + 1) + \"']\");\n const checkbox = row.querySelector(\".dg-selectable input\");\n if (checkbox.checked) {\n if (key) {\n selectedData.push(item[key]);\n } else {\n selectedData.push(item);\n }\n }\n });\n return selectedData;\n }\n getData() {\n return this.originalData;\n }\n clearData() {\n // Clear the state but keep attribute so we can reload\n this.state.url = null;\n if (this.data.length === 0) {\n return;\n }\n this.data = this.originalData = [];\n this.fixPage();\n this.renderHeader();\n this.computeDefaultHeight();\n }\n /**\n * @returns {Promise}\n */\n loadData() {\n if (!this.server && this.originalData.length) {\n this.log(\"skip loadData\");\n return new Promise((resolve, reject) => {\n resolve();\n });\n }\n this.log(\"loadData\");\n return this.fetchData()\n .then((response) => {\n if (Array.isArray(response)) {\n this.data = response;\n } else {\n if (!response.data) {\n console.error(\"Invalid response, it should contain a data key with an array or be a plain array\", response);\n return;\n }\n\n // We may have a config object\n if (response.options) {\n this.setOptions(response.options);\n }\n if (response.meta) {\n this.meta = response.meta;\n }\n\n this.data = response.data;\n }\n this.originalData = this.data.slice();\n this.fixPage();\n\n // Make sure we have a proper set of columns\n if (this.state.columns.length === 0 && this.originalData.length) {\n this.state.columns = DataGrid.convertColumns(Object.keys(this.originalData[0]));\n }\n })\n .catch((err) => {\n this.url = null;\n this.log(err);\n });\n }\n getFirst() {\n this.page = 1;\n }\n getLast() {\n this.page = this.state.pages;\n }\n getPrev() {\n this.page = this.state.page - 1;\n }\n getNext() {\n this.page = this.state.page + 1;\n }\n /**\n * @returns {Promise}\n */\n refresh() {\n this.data = this.originalData = [];\n return this.loadData();\n }\n changePerPage() {\n this.perPage = this.selectPerPage.options[this.selectPerPage.selectedIndex].value;\n }\n gotoPage(event) {\n if (event.type === \"keypress\") {\n const key = event.keyCode || event.key;\n if (key === 13 || key === \"Enter\") {\n event.preventDefault();\n } else {\n return;\n }\n }\n this.page = this.inputPage.value;\n }\n getSort() {\n let col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"field\");\n }\n return this.defaultSort;\n }\n getSortDir() {\n let col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"aria-sort\") || \"\";\n }\n return \"\";\n }\n getFilters() {\n let filters = [];\n this.root.querySelectorAll(\"thead tr.dg-head-filters input\").forEach((input) => {\n filters[input.dataset.name] = input.value;\n });\n return filters;\n }\n clearFilters() {\n this.root.querySelectorAll(\"thead tr.dg-head-filters input\").forEach((input) => {\n input.value = \"\";\n });\n this.filterData();\n }\n filterData() {\n this.log(\"filter data\");\n\n if (this.server) {\n this.loadData().finally(() => {\n this.fixPage();\n this.renderBody();\n });\n } else {\n this.data = this.originalData.slice();\n\n this.root.querySelectorAll(\"thead tr.dg-head-filters input\").forEach((input) => {\n let value = input.value;\n if (value) {\n let name = input.dataset.name;\n this.data = this.data.filter((item) => {\n let str = item[name] + \"\";\n return str.toLowerCase().indexOf(value.toLowerCase()) !== -1;\n });\n }\n });\n\n this.fixPage();\n let col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (this.state.sort && col) {\n this.sortData(col);\n } else {\n this.renderBody();\n }\n }\n }\n /**\n * Data will be sorted then rendered using renderBody\n * @param {HTMLElement} col The column that was clicked or null to use current sort\n */\n sortData(col = null) {\n this.log(\"sort data\");\n\n // Early exit\n if(col && this.getColProp(col.getAttribute(\"field\"), \"noSort\")) {\n return;\n }\n\n // We clicked on a column, update sort state\n if (col !== null) {\n // Remove active sort if any\n this.root.querySelectorAll(\"thead tr:first-child th\").forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (th !== col) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n });\n\n // Set three-state col\n if (!col.hasAttribute(\"aria-sort\") || col.getAttribute(\"aria-sort\") === \"none\") {\n col.setAttribute(\"aria-sort\", \"ascending\");\n } else if (col.getAttribute(\"aria-sort\") === \"ascending\") {\n col.setAttribute(\"aria-sort\", \"descending\");\n } else if (col.getAttribute(\"aria-sort\") === \"descending\") {\n col.setAttribute(\"aria-sort\", \"none\");\n }\n } else {\n // Or fetch current sort\n col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n }\n\n if (this.server) {\n // Reload data with updated sort\n this.loadData().finally(() => {\n this.renderBody();\n });\n } else {\n const sort = col ? col.getAttribute(\"aria-sort\") : \"none\";\n if (sort === \"none\") {\n let stack = [];\n\n // Restore order while keeping filters\n this.originalData.some((itemA) => {\n this.data.some((itemB) => {\n if (JSON.stringify(itemA) === JSON.stringify(itemB)) {\n stack.push(itemB);\n return true;\n }\n return false;\n });\n return stack.length === this.data.length;\n });\n\n this.data = stack;\n } else {\n const field = col.getAttribute(\"field\");\n this.data.sort((a, b) => {\n if (!isNaN(a[field]) && !isNaN(b[field])) {\n return sort === \"ascending\" ? a[field] - b[field] : b[field] - a[field];\n }\n const valA = sort === \"ascending\" ? a[field].toUpperCase() : b[field].toUpperCase();\n const valB = sort === \"ascending\" ? b[field].toUpperCase() : a[field].toUpperCase();\n\n switch (true) {\n case valA > valB:\n return 1;\n case valA < valB:\n return -1;\n case valA === valB:\n return 0;\n }\n });\n this.renderBody();\n }\n }\n }\n fetchData() {\n if (!this.url) {\n return new Promise((resolve, reject) => reject(\"No url set\"));\n }\n let url = new URL(this.url, window.location.href);\n let params = {\n r: Math.ceil(Math.random() * 9999999),\n };\n if (this.server) {\n // 0 based\n params[\"start\"] = this.state.page - 1;\n params[\"length\"] = this.state.perPage;\n params[\"search\"] = this.getFilters();\n params[\"sort\"] = this.getSort() || \"\";\n params[\"sortDir\"] = this.getSortDir();\n }\n\n Object.keys(params).forEach((key) => {\n if (Array.isArray(params[key])) {\n Object.keys(params[key]).forEach((k) => url.searchParams.append(key + \"[\" + k + \"]\", params[key][k]));\n } else {\n url.searchParams.append(key, params[key]);\n }\n });\n\n return fetch(url).then((response) => {\n return response.json();\n });\n }\n renderHeader() {\n this.log(\"render header\");\n let tr;\n let sortedColumn;\n let thead = this.root.querySelector(\"thead\");\n\n this.createColumnHeaders(thead);\n if (this.state.defaultSort) {\n // We can have a default sort even with sort disabled\n sortedColumn = this.root.querySelector(\"thead tr.dg-head-columns th[field='\" + this.state.defaultSort + \"']\");\n }\n\n // Create column filters\n this.createColumnFilters(thead);\n\n // Configure table\n this.root.querySelector(\"table\").setAttribute(\"aria-colcount\", this.columnsLength(true).toString());\n this.root.querySelector(\"tfoot\").querySelector(\"td\").setAttribute(\"colspan\", this.columnsLength(true).toString());\n\n if (sortedColumn) {\n this.sortData(sortedColumn);\n } else {\n this.renderBody();\n }\n\n this.root.querySelector(\"tfoot\").style.display = \"\";\n if (this.resizable) {\n this.renderResizer();\n }\n }\n createColumnHeaders(thead) {\n const colMaxWidth = parseInt((thead.offsetWidth / this.columnsLength(true)) * 2);\n\n let idx = 0;\n let tr;\n\n // Create row\n tr = document.createElement(\"tr\");\n this.headerRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", 1);\n tr.setAttribute(\"class\", \"dg-head-columns\");\n\n // Selectable\n if (this.selectable) {\n let selectableTh = document.createElement(\"th\");\n selectableTh.setAttribute(\"role\", \"columnheader button\");\n selectableTh.setAttribute(\"aria-colindex\", 1);\n selectableTh.classList.add(\"dg-selectable\");\n selectableTh.tabIndex = 0;\n\n this.selectAll = document.createElement(\"input\");\n this.selectAll.type = \"checkbox\";\n this.selectAll.classList.add(\"dg-select-all\");\n\n this.toggleSelectAll = this.toggleSelectAll.bind(this);\n this.selectAll.addEventListener(\"change\", this.toggleSelectAll);\n\n let label = document.createElement(\"label\");\n label.appendChild(this.selectAll);\n\n selectableTh.appendChild(label);\n selectableTh.setAttribute(\"width\", 40);\n tr.appendChild(selectableTh);\n }\n\n // Create columns\n idx = 0;\n let totalWidth = 0;\n this.state.columns.forEach((column, i) => {\n if (column.attr) {\n return;\n }\n let th = document.createElement(\"th\");\n th.setAttribute(\"role\", \"columnheader button\");\n th.setAttribute(\"aria-colindex\", idx + this.startIndex());\n th.setAttribute(\"id\", DataGrid.randstr(\"dg-col-\"));\n if (this.state.sort) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n th.setAttribute(\"field\", column.field);\n th.dataset.minWidth = DataGrid.getTextWidth(column.title, th) + 40;\n DataGrid.applyColumnDefinition(th, column);\n th.tabIndex = 0;\n th.textContent = column.title;\n\n if (column.hidden) {\n th.setAttribute(\"hidden\", true);\n }\n\n // Autosize small based on first/last row ?\n if (this.autosize && !th.getAttribute(\"width\")) {\n totalWidth += this.autosizeColumn(th, column, th.dataset.minWidth, colMaxWidth);\n }\n\n // Reorder columns with drag/drop\n if (this.state.reorder) {\n this.makeHeaderDraggable(th);\n }\n tr.appendChild(th);\n idx++;\n });\n\n // There is too much width, and we want to avoid fixed layout to split remaining amount\n if (totalWidth < thead.offsetWidth) {\n let lastTh = tr.lastChild;\n if (lastTh) {\n lastTh.removeAttribute(\"width\");\n }\n }\n\n // Actions\n if (this.state.actions.length) {\n let actionsTh = document.createElement(\"th\");\n actionsTh.setAttribute(\"role\", \"columnheader button\");\n actionsTh.setAttribute(\"aria-colindex\", this.columnsLength(true));\n actionsTh.classList.add(\"dg-actions\");\n actionsTh.tabIndex = 0;\n tr.appendChild(actionsTh);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-columns\"));\n\n // Context menu\n this.showContextMenu = this.showContextMenu.bind(this);\n tr.addEventListener(\"contextmenu\", this.showContextMenu);\n\n // Sort col on click\n tr.querySelectorAll(\"[aria-sort]\").forEach((sortableRow) => {\n sortableRow.addEventListener(\"click\", () => this.sortData(sortableRow));\n });\n }\n createColumnFilters(thead) {\n let idx = 0;\n let tr;\n\n // Create row for filters\n tr = document.createElement(\"tr\");\n this.filterRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", 2);\n tr.setAttribute(\"class\", \"dg-head-filters\");\n if (!this.state.filter) {\n tr.setAttribute(\"hidden\", true);\n }\n\n // Selectable\n if (this.selectable) {\n let th = document.createElement(\"th\");\n th.setAttribute(\"role\", \"columnheader button\");\n th.setAttribute(\"aria-colindex\", 1);\n th.classList.add(\"dg-selectable\");\n th.tabIndex = 0;\n tr.appendChild(th);\n }\n\n this.state.columns.forEach((column, i) => {\n if (column.attr) {\n return;\n }\n let relatedTh = thead.querySelector(\"tr.dg-head-columns th[aria-colindex='\" + (idx + this.startIndex()) + \"']\");\n let th = document.createElement(\"th\");\n th.setAttribute(\"aria-colindex\", idx + this.startIndex());\n\n let input = document.createElement(\"input\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n // Allows binding filter to this column\n input.dataset.name = column.field;\n input.id = DataGrid.randstr(\"dg-filter-\");\n // Don't use aria-label as it triggers autocomplete\n input.setAttribute(\"aria-labelledby\", relatedTh.getAttribute(\"id\"));\n if (!this.state.filter) {\n th.tabIndex = 0;\n } else {\n input.tabIndex = 0;\n }\n\n if (column.hidden) {\n th.setAttribute(\"hidden\", true);\n }\n\n th.appendChild(input);\n tr.appendChild(th);\n idx++;\n });\n\n // Actions\n if (this.state.actions.length) {\n let actionsTh = document.createElement(\"th\");\n actionsTh.setAttribute(\"role\", \"columnheader button\");\n actionsTh.setAttribute(\"aria-colindex\", this.columnsLength(true));\n actionsTh.classList.add(\"dg-actions\");\n actionsTh.tabIndex = 0;\n tr.appendChild(actionsTh);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-filters\"));\n\n // Filter content on enter\n tr.querySelectorAll(\"input\").forEach((input) => {\n input.addEventListener(\"keypress\", (e) => {\n const key = e.keyCode || e.key;\n if (key === 13 || key === \"Enter\") {\n this.filterData.call(this);\n }\n });\n });\n }\n autosizeColumn(th, column, min, max) {\n let v = this.data[0][column.field].toString();\n let v2 = this.data[this.data.length - 1][column.field].toString();\n if (v2.length > v.length) {\n v = v2;\n }\n let width = 0;\n if (v.length <= 6) {\n width = min;\n } else if (v.length > 50) {\n width = max;\n } else {\n width = DataGrid.getTextWidth(v, th);\n }\n if (width < min) {\n width = min;\n }\n th.setAttribute(\"width\", width);\n return parseInt(width);\n }\n showContextMenu(e) {\n e.preventDefault();\n\n const target = DataGrid.getParentNode(e.target, \"THEAD\");\n const menu = this.root.querySelector(\".dg-menu\");\n const rect = target.getBoundingClientRect();\n let x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n menu.style.top = `${y}px`;\n menu.style.left = `${x}px`;\n\n menu.removeAttribute(\"hidden\");\n if (x + 150 > rect.width) {\n x -= menu.offsetWidth;\n menu.style.left = `${x}px`;\n }\n\n const documentClickHandler = (e) => {\n if (!menu.contains(e.target)) {\n menu.setAttribute(\"hidden\", true);\n document.removeEventListener(\"click\", documentClickHandler);\n }\n };\n document.addEventListener(\"click\", documentClickHandler);\n }\n createMenu() {\n const menu = this.root.querySelector(\".dg-menu\");\n this.state.columns.forEach((col) => {\n if (col.attr) {\n return;\n }\n const field = col.field;\n const li = document.createElement(\"li\");\n const label = document.createElement(\"label\");\n const checkbox = document.createElement(\"input\");\n checkbox.setAttribute(\"type\", \"checkbox\");\n if (!col.hidden) {\n checkbox.checked = true;\n }\n checkbox.addEventListener(\"change\", (e) => {\n e.target.checked ? this.showColumn(field, e.target) : this.hideColumn(field, e.target);\n });\n\n const text = document.createTextNode(col.title);\n\n label.appendChild(checkbox);\n label.appendChild(text);\n\n li.appendChild(label);\n menu.appendChild(li);\n });\n }\n showColumn(field, checkbox = null) {\n if (checkbox) {\n checkbox.checked = true;\n }\n this.setColProp(field, \"hidden\", false);\n this.renderHeader();\n }\n hideColumn(field, checkbox = null) {\n const numHiddenCols = this.state.columns.filter((th) => {\n return th.hidden === true;\n }).length;\n\n if (numHiddenCols === this.columnsLength() - 1) {\n // Restore checkbox value\n if (checkbox) {\n checkbox.checked = true;\n }\n return;\n }\n this.setColProp(field, \"hidden\", true);\n this.renderHeader();\n }\n makeHeaderDraggable(th) {\n th.draggable = true;\n th.addEventListener(\"dragstart\", (e) => {\n if (this.isResizing && e.preventDefault) {\n e.preventDefault();\n return;\n }\n this.log(\"reorder col\");\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", e.target.getAttribute(\"aria-colindex\"));\n });\n th.addEventListener(\"dragover\", (e) => {\n if (e.preventDefault) {\n e.preventDefault();\n }\n e.dataTransfer.dropEffect = \"move\";\n return false;\n });\n th.addEventListener(\"drop\", (e) => {\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n const target = DataGrid.getParentNode(e.target, \"TH\");\n const index = e.dataTransfer.getData(\"text/plain\");\n const targetIndex = target.getAttribute(\"aria-colindex\");\n\n if (index === targetIndex) {\n this.log(\"reordered col stayed the same\");\n return;\n }\n this.log(\"reordered col from \" + index + \" to \" + targetIndex);\n\n const tmp = this.state.columns[index - 1];\n this.state.columns[index - 1] = this.columns[targetIndex - 1];\n this.state.columns[targetIndex - 1] = tmp;\n\n const swapNodes = (selector, el1) => {\n const rowIndex = el1.parentNode.getAttribute(\"aria-rowindex\");\n const el2 = this.root.querySelector(selector + \" tr[aria-rowindex='\" + rowIndex + \"'] [aria-colindex='\" + targetIndex + \"']\");\n el1.setAttribute(\"aria-colindex\", targetIndex);\n el2.setAttribute(\"aria-colindex\", index);\n const newNode = document.createElement(\"th\");\n el1.parentNode.insertBefore(newNode, el1);\n el2.parentNode.replaceChild(el1, el2);\n newNode.parentNode.replaceChild(el2, newNode);\n };\n\n // Swap all rows in header and body\n this.root.querySelectorAll(\"thead th[aria-colindex='\" + index + \"']\").forEach((el1) => {\n swapNodes(\"thead\", el1);\n });\n this.root.querySelectorAll('tbody td[aria-colindex=\"' + index + '\"]').forEach((el1) => {\n swapNodes(\"tbody\", el1);\n });\n\n return false;\n });\n }\n renderResizer() {\n const table = this.root.querySelector(\"table\");\n const cols = this.root.querySelectorAll(\"thead tr.dg-head-columns th\");\n\n cols.forEach((col) => {\n if (col.classList.contains(\"dg-selectable\") || col.classList.contains(\"dg-actions\")) {\n return;\n }\n // Create a resizer element\n const resizer = document.createElement(\"div\");\n resizer.classList.add(\"dg-resizer\");\n resizer.ariaLabel = labels.resizeColumn;\n\n // Add a resizer element to the column\n col.appendChild(resizer);\n\n // Handle resizing\n let startX = 0;\n let startW = 0;\n let remainingSpace = 0;\n let max = 0;\n\n const mouseMoveHandler = (e) => {\n if (e.clientX > max) {\n return;\n }\n const newWidth = startW + (e.clientX - startX);\n if (col.dataset.minWidth && newWidth > col.dataset.minWidth) {\n col.width = newWidth;\n }\n };\n\n // When user releases the mouse, remove the existing event listeners\n const mouseUpHandler = () => {\n this.log(\"resized column\");\n\n this.isResizing = false;\n resizer.classList.remove(\"dg-resizer-active\");\n if (this.state.reorder) {\n col.draggable = true;\n }\n col.style.overflow = \"hidden\";\n\n document.removeEventListener(\"mousemove\", mouseMoveHandler);\n document.removeEventListener(\"mouseup\", mouseUpHandler);\n };\n\n // Otherwise it could sort the col\n resizer.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n });\n\n resizer.addEventListener(\"mousedown\", (e) => {\n e.stopPropagation();\n this.isResizing = true;\n\n const currentCols = this.root.querySelectorAll(\".dg-head-columns th\");\n const visibleCols = Array.from(currentCols).filter((col) => {\n return !col.hasAttribute(\"hidden\");\n });\n const columns = Array.from(visibleCols);\n const columnIndex = columns.findIndex((column) => column == e.target.parentNode);\n this.log(\"resize column\");\n\n resizer.classList.add(\"dg-resizer-active\");\n\n // Make sure we don't drag it\n if (col.hasAttribute(\"draggable\")) {\n col.removeAttribute(\"draggable\");\n }\n\n // Allow overflow when resizing\n col.style.overflow = \"visible\";\n\n // Show full column height (-1 to avoid scrollbar)\n resizer.style.height = table.offsetHeight - 1 + \"px\";\n\n // Register initial data\n startX = e.clientX;\n startW = col.offsetWidth;\n\n remainingSpace = (visibleCols.length - columnIndex) * 30;\n max = DataGrid.elementOffset(this).left + this.offsetWidth - remainingSpace;\n\n // Remove width from next columns to allow auto layout\n col.setAttribute(\"width\", startW);\n for (let j = 0; j < visibleCols.length; j++) {\n if (j > columnIndex) {\n cols[j].removeAttribute(\"width\");\n }\n }\n\n // Attach handlers\n document.addEventListener(\"mousemove\", mouseMoveHandler);\n document.addEventListener(\"mouseup\", mouseUpHandler);\n });\n });\n }\n /**\n * Render the data as rows in tbody\n * It will call paginate() at the end\n */\n renderBody() {\n this.log(\"render body\");\n let tr;\n let td;\n let idx;\n let tbody = document.createElement(\"tbody\");\n this.data.forEach((item, i) => {\n tr = document.createElement(\"tr\");\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"hidden\", true);\n tr.setAttribute(\"aria-rowindex\", i + 1);\n tr.tabIndex = 0;\n\n // Selectable\n if (this.selectable) {\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell button\");\n td.setAttribute(\"aria-colindex\", 1);\n td.classList.add(\"dg-selectable\");\n\n let selectOne = document.createElement(\"input\");\n selectOne.type = \"checkbox\";\n let label = document.createElement(\"label\");\n label.appendChild(selectOne);\n td.appendChild(label);\n\n tr.appendChild(td);\n }\n\n // Expandable\n if (this.expand) {\n tr.addEventListener(\"click\", function (ev) {\n this.classList.toggle(\"dg-expanded\");\n });\n }\n\n idx = 0;\n this.state.columns.forEach((column, j) => {\n if (!column) {\n console.log(this.state.columns);\n }\n // It should be applied as an attr of the row\n if (column.attr) {\n tr.setAttribute(column.attr, item[column.field]);\n return;\n }\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell\");\n td.setAttribute(\"aria-colindex\", idx + this.startIndex());\n DataGrid.applyColumnDefinition(td, column);\n td.setAttribute(\"data-name\", column.title);\n td.tabIndex = -1;\n\n // Inline editing\n if (column.editable) {\n let input = document.createElement(\"input\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n input.tabIndex = 0;\n input.classList.add(\"dg-editable\");\n input.name = this.getAttribute(\"id\").replace(\"-\", \"_\") + \"[\" + (i + 1) + \"]\" + \"[\" + column.field + \"]\";\n input.value = item[column.field];\n input.dataset.field = column.field;\n\n input.addEventListener(\"click\", (ev) => ev.stopPropagation());\n input.addEventListener(\"keypress\", (ev) => {\n if (ev.type === \"keypress\") {\n const key = ev.keyCode || ev.key;\n if (key === 13 || key === \"Enter\") {\n input.blur();\n }\n }\n });\n input.addEventListener(\"blur\", (ev) => {\n // Only fire on update\n if (input.value == item[input.dataset.field]) {\n return;\n }\n // Update underlying data\n item[input.dataset.field] = input.value;\n // Notify\n const event = new CustomEvent(\"edit\", {\n bubbles: true,\n detail: {\n data: item,\n value: input.value,\n },\n });\n this.dispatchEvent(event);\n });\n td.appendChild(input);\n } else {\n td.textContent = item[column.field];\n }\n if (column.hidden) {\n td.setAttribute(\"hidden\", true);\n }\n tr.appendChild(td);\n idx++;\n });\n\n // Actions\n if (this.state.actions.length) {\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell\");\n td.setAttribute(\"aria-colindex\", this.columnsLength(true));\n td.classList.add(\"dg-actions\");\n td.tabIndex = 0;\n\n this.state.actions.forEach((action) => {\n let button = document.createElement(\"button\");\n if (action.html) {\n button.innerHTML = action.html;\n } else {\n button.innerText = action.title ?? action.name;\n }\n if (action.url) {\n button.type = \"submit\";\n button.formAction = DataGrid.interpolate(action.url, item);\n }\n if (action.class) {\n button.classList.add(action.class);\n }\n const actionHandler = (ev) => {\n ev.stopPropagation();\n if (action.confirm) {\n let c = confirm(labels.areYouSure);\n if (!c) {\n ev.preventDefault();\n return;\n }\n }\n const event = new CustomEvent(\"action\", {\n bubbles: true,\n detail: {\n data: item,\n action: action.name,\n },\n });\n this.dispatchEvent(event);\n };\n button.addEventListener(\"click\", actionHandler);\n td.appendChild(button);\n\n // Row action\n if (action.default) {\n tr.classList.add(\"dg-actionable\");\n tr.addEventListener(\"click\", actionHandler);\n }\n });\n\n tr.appendChild(td);\n }\n\n tbody.appendChild(tr);\n });\n\n tbody.setAttribute(\"role\", \"rowgroup\");\n\n this.root.querySelector(\"table\").replaceChild(tbody, this.root.querySelector(\"tbody\"));\n\n // Let's add a fake row to adjust any missing height, simply multiply by rowHeight the number of missing lines\n tr = document.createElement(\"tr\");\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"hidden\", true);\n tr.classList.add(\"dg-fake-row\");\n tr.tabIndex = 0;\n tbody.appendChild(tr);\n\n this.paginate();\n }\n paginate() {\n this.log(\"paginate\");\n\n const total = this.totalRecords();\n const pages = this.totalPages();\n\n let index;\n let high = this.state.page * this.state.perPage;\n let low = high - this.state.perPage + 1;\n let tbody = this.root.querySelector(\"tbody\");\n let tfoot = this.root.querySelector(\"tfoot\");\n\n if (high > total) {\n high = total;\n }\n if (!total) {\n low = 0;\n }\n\n tbody.querySelectorAll(\"tr\").forEach((tr) => {\n if (this.server) {\n tr.removeAttribute(\"hidden\");\n return;\n }\n index = Number(tr.getAttribute(\"aria-rowindex\"));\n if (index > high || index < low) {\n tr.setAttribute(\"hidden\", true);\n } else {\n tr.removeAttribute(\"hidden\");\n }\n });\n\n // Store default height and update styles if needed\n if (this.defaultHeight == 0) {\n this.computeDefaultHeight();\n }\n\n // On last page, adjust height if using fixed height\n let fakeRow = this.querySelector(\".dg-fake-row\");\n if (this.style.height) {\n if (this.state.page == pages) {\n // Check if we are below set height\n if (parseInt(this.style.height) > this.querySelector(\"tbody\").offsetHeight) {\n const missing = this.state.perPage - (total - (pages - 1) * this.state.perPage);\n fakeRow.setAttribute(\"height\", missing * this.rowHeight);\n } else {\n fakeRow.removeAttribute(\"height\");\n }\n } else {\n fakeRow.removeAttribute(\"height\");\n }\n }\n\n // Enable/disable buttons\n if (this.btnFirst) {\n this.btnFirst.disabled = this.state.page <= 1;\n this.btnPrev.disabled = this.state.page <= 1;\n this.btnNext.disabled = this.state.page >= this.state.pages;\n this.btnLast.disabled = this.state.page >= this.state.pages;\n }\n tfoot.querySelector(\".dg-low\").textContent = low.toString();\n tfoot.querySelector(\".dg-high\").textContent = high.toString();\n tfoot.querySelector(\".dg-total\").textContent = this.totalRecords();\n }\n totalPages() {\n return Math.ceil(this.totalRecords() / this.state.perPage);\n }\n totalRecords() {\n if (this.server) {\n return this.meta.filtered;\n }\n return this.data.length.toString();\n }\n /**\n * @param {string|Error} message\n */\n log(message) {\n if (this.debug) {\n console.log(\"[\" + this.getAttribute(\"id\") + \"] \" + message);\n }\n }\n}\n\ncustomElements.define(\"data-grid\", DataGrid);\n\nexport default DataGrid;\n"],
- "mappings": "AAMA,aAuBA,GAAM,GAAS,OAAO,OACpB,CACE,aAAc,iBACd,SAAU,aACV,cAAe,mBACf,aAAc,sBACd,aAAc,kBACd,aAAc,kBACd,GAAI,KACJ,MAAO,QACP,aAAc,gBACd,OAAQ,UACR,WAAY,iBAEd,OAAO,gBAAkB,IAErB,EAAW,SAAS,cAAc,YACxC,EAAS,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAMoB,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mEAMmB,EAAO;AAAA;AAAA;AAAA,gFAGM,EAAO,8BAA8B,EAAO;AAAA;AAAA;AAAA,+EAG7C,EAAO,6BAA6B,EAAO;AAAA;AAAA;AAAA,sGAGpB,EAAO;AAAA,qEACxC,EAAO,6BAA6B,EAAO;AAAA;AAAA;AAAA,qEAG3C,EAAO,6BAA6B,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,mFAK7B,EAAO,sCAAsC,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcvI,mBAAuB,YAAY,CACjC,YAAY,EAAU,GAAI,CACxB,QAGA,KAAK,YAAY,EAAS,QAAQ,UAAU,KAC5C,KAAK,KAAO,KAEZ,KAAK,MAAQ,CAEX,IAAK,KACL,KAAM,EACN,QAAS,GACT,MAAO,GACP,OAAQ,GACR,KAAM,GACN,OAAQ,GACR,YAAa,GACb,QAAS,GACT,IAAK,MAEL,MAAO,EACP,cAAe,CAAC,GAAI,GAAI,GAAI,IAAK,KACjC,QAAS,GACT,QAAS,IAEX,KAAK,WAAW,GAGhB,KAAK,KAAO,GAEZ,KAAK,aAAe,GAGpB,KAAK,cAAgB,GACrB,KAAK,MAAQ,KACb,KAAK,WAAa,GAClB,KAAK,cAAgB,EACrB,KAAK,KAAO,GAGP,KAAK,aAAa,OACrB,KAAK,aAAa,KAAM,EAAS,QAAQ,QAG3C,KAAK,IAAI,qBAUJ,aAAY,EAAK,EAAM,CAC5B,MAAO,GAAI,QAAQ,iBAAkB,SAAU,EAAI,EAAI,CACrD,MAAO,GAAK,WAUT,eAAc,EAAI,EAAM,EAAO,WAAY,CAChD,GAAI,GAAS,EACb,KAAO,EAAO,IAAS,GACrB,EAAS,EAAO,WAElB,MAAO,SAUF,cAAa,EAAM,EAAK,SAAS,KAAM,CAC5C,GAAM,GAAS,OAAO,iBAAiB,EAAI,MACrC,EAAa,EAAO,iBAAiB,gBAAkB,SACvD,EAAW,EAAO,iBAAiB,cAAgB,OACnD,EAAa,EAAO,iBAAiB,gBAAkB,QAIvD,EAAU,AADD,GAAS,aAAa,QAAW,GAAS,aAAa,OAAS,SAAS,cAAc,YAC/E,WAAW,MAClC,EAAQ,KAAO,GAAG,KAAc,KAAY,IAC5C,GAAM,GAAU,EAAQ,YAAY,GACpC,MAAO,UAAS,EAAQ,aASnB,iBAAgB,EAAI,EAAO,EAAO,EAAU,GAAO,CACxD,GAAI,GAAM,SAAS,cAAc,UACjC,EAAI,MAAQ,EACR,GACF,GAAI,SAAW,YAEjB,EAAI,MAAQ,EACZ,EAAG,YAAY,SAMV,SAAQ,EAAQ,CACrB,MAAO,MAAK,SACT,SAAS,IACT,QAAQ,KAAM,GAAU,UAMtB,cAAa,EAAG,CACrB,MAAI,OAAO,IAAM,SACX,EAAE,KAAO,IACJ,KAAK,MAAM,GAEb,EAAE,MAAM,KAEZ,OAAM,QAAQ,IACjB,QAAQ,MAAM,gBAAiB,GAE1B,SAMF,eAAc,EAAI,CACvB,GAAI,GAAO,EAAG,wBACZ,EAAa,OAAO,aAAe,SAAS,gBAAgB,WAC5D,EAAY,OAAO,aAAe,SAAS,gBAAgB,UAC7D,MAAO,CAAE,IAAK,EAAK,IAAM,EAAW,KAAM,EAAK,KAAO,SAMjD,uBAAsB,EAAI,EAAY,CAC3C,AAAI,EAAW,OACb,EAAG,aAAa,QAAS,EAAW,OAElC,EAAW,OACb,EAAG,aAAa,QAAS,EAAW,aAOjC,gBAAe,EAAS,CAC7B,GAAI,GAAO,GAEX,MAAI,OAAO,IAAY,UAAY,CAAC,MAAM,QAAQ,GAChD,OAAO,KAAK,GAAS,QAAQ,AAAC,GAAQ,CACpC,GAAI,GAAM,GACV,EAAI,MAAQ,EAAQ,GACpB,EAAI,MAAQ,EACZ,EAAK,KAAK,KAGZ,EAAQ,QAAQ,AAAC,GAAS,CACxB,GAAI,GAAM,GACV,AAAI,MAAO,IAAS,SAClB,GAAI,MAAQ,EACZ,EAAI,MAAQ,GACP,AAAI,MAAO,IAAS,SACzB,GAAM,EACD,EAAI,OACP,QAAQ,MAAM,4BAA6B,IAG7C,QAAQ,MAAM,mDAEhB,EAAK,KAAK,KAGP,YAKE,qBAAqB,CAC9B,MAAO,CAAC,MAAO,OAAQ,WAAY,QAAS,SAAU,OAAQ,eAAgB,MAAO,WAEvF,yBAAyB,EAAe,EAAU,EAAU,CAI1D,OAHA,KAAK,IAAI,6BAA+B,GAGhC,OACD,MACH,KAAK,MAAM,IAAM,EACb,KAAK,eAAiB,GACxB,KAAK,WAAW,KAAK,IAAM,CACzB,KAAK,gBAGT,UACG,OACH,KAAK,MAAM,KAAO,OAAO,GACrB,KAAK,eACP,KAAK,WAAW,QAAQ,IAAM,CAC5B,KAAK,UACL,KAAK,OAAS,KAAK,aAAe,KAAK,aAG3C,UACG,WACH,KAAK,MAAM,QAAU,OAAO,GACxB,KAAK,eACP,MAAK,cAAc,MAAQ,EAC3B,KAAK,WAAW,QAAQ,IAAM,CAC5B,KAAK,UACL,KAAK,OAAS,KAAK,aAAe,KAAK,WAGnC,KAAK,QACP,OAAO,OAAO,CAAE,IAAK,EAAS,cAAc,KAAK,eAAe,IAAM,KAAK,mBAIjF,UACG,QACH,KAAK,MAAM,MAAQ,IAAa,OAChC,UACG,MACH,KAAK,MAAM,IAAM,EACjB,KAAK,KAAK,cAAc,eAAe,IAAM,KAAK,MAAM,IACxD,UACG,SACH,KAAK,MAAM,OAAS,IAAa,OAC7B,KAAK,eACP,KAAK,eAEP,UACG,UACH,KAAK,MAAM,QAAU,IAAa,OAC9B,KAAK,eACP,KAAK,gBAEP,UACG,OACH,KAAK,MAAM,KAAO,IAAa,OAC3B,KAAK,eACP,KAAK,aAEP,UACG,eACH,KAAK,MAAM,YAAc,EACrB,KAAK,eACP,KAAK,aAEP,UAGF,OAAO,CACT,MAAO,MAAK,aAAa,WAEvB,MAAK,EAAK,CACZ,KAAK,aAAa,OAAQ,MAExB,UAAU,CACZ,MAAO,MAAK,aAAa,eAEvB,SAAQ,EAAK,CACf,KAAK,aAAa,WAAY,MAE5B,QAAQ,CACV,MAAO,MAAK,aAAa,WAAa,UAEpC,OAAM,EAAK,CACb,KAAK,aAAa,QAAS,MAEzB,MAAM,CACR,MAAO,MAAK,aAAa,UAEvB,KAAI,EAAK,CACX,KAAK,aAAa,MAAO,MAEvB,SAAS,CACX,MAAO,MAAK,aAAa,YAAc,UAErC,QAAO,EAAK,CACd,KAAK,aAAa,SAAU,MAE1B,UAAU,CACZ,MAAO,MAAK,aAAa,aAAe,UAEtC,SAAQ,EAAK,CACf,KAAK,aAAa,UAAW,MAE3B,OAAO,CACT,MAAO,MAAK,aAAa,UAAY,UAEnC,MAAK,EAAK,CACZ,KAAK,aAAa,OAAQ,MAExB,cAAc,CAChB,MAAO,MAAK,aAAa,mBAEvB,aAAY,EAAK,CACnB,KAAK,aAAa,eAAgB,MAEhC,MAAM,CACR,MAAO,MAAK,aAAa,UAEvB,KAAI,EAAK,CACX,EAAM,KAAK,aAAa,MAAO,GAAO,KAAK,gBAAgB,UAKzD,SAAS,CACX,MAAO,MAAK,aAAa,aAEvB,QAAO,EAAK,CACd,EAAM,KAAK,aAAa,SAAU,IAAM,KAAK,gBAAgB,aAE3D,WAAW,CACb,MAAO,MAAK,aAAa,eAEvB,UAAS,EAAK,CAChB,EAAM,KAAK,aAAa,WAAY,IAAM,KAAK,gBAAgB,eAE7D,YAAY,CACd,MAAO,MAAK,aAAa,gBAEvB,WAAU,EAAK,CACjB,EAAM,KAAK,aAAa,YAAa,IAAM,KAAK,gBAAgB,gBAE9D,SAAS,CACX,MAAO,MAAK,aAAa,aAEvB,QAAO,EAAK,CACd,EAAM,KAAK,aAAa,SAAU,IAAM,KAAK,gBAAgB,aAE3D,aAAa,CACf,MAAO,MAAK,aAAa,iBAEvB,YAAW,EAAK,CAClB,EAAM,KAAK,aAAa,aAAc,IAAM,KAAK,gBAAgB,iBAE/D,SAAS,CACX,MAAO,MAAK,aAAa,aAEvB,QAAO,EAAK,CACd,EAAM,KAAK,aAAa,SAAU,IAAM,KAAK,gBAAgB,aAE3D,aAAa,CACf,MAAO,MAAK,aAAa,iBAEvB,YAAW,EAAK,CAClB,EAAM,KAAK,aAAa,aAAc,IAAM,KAAK,gBAAgB,iBAK/D,gBAAgB,CAClB,MAAO,MAAK,MAAM,iBAEhB,eAAc,EAAK,CACrB,GAAI,MAAM,QAAQ,IAChB,MAAK,MAAM,cAAgB,EACvB,KAAK,eAAe,CACtB,KAAO,KAAK,cAAc,WACxB,KAAK,cAAc,YAAY,KAAK,cAAc,WAEpD,KAAK,MAAM,cAAc,QAAQ,AAAC,GAAM,CACtC,EAAS,gBAAgB,KAAK,cAAe,EAAG,SAKpD,UAAU,CACZ,MAAO,MAAK,MAAM,WAEhB,SAAQ,EAAK,CACf,KAAK,MAAM,QAAU,EAAS,eAAe,EAAS,aAAa,OAEjE,UAAU,CACZ,MAAO,MAAK,MAAM,WAEhB,SAAQ,EAAK,CACf,KAAK,MAAM,QAAU,EAAS,aAAa,GAE7C,mBAAoB,CAClB,KAAK,IAAI,qBAET,KAAK,SAAW,KAAK,KAAK,cAAc,iBACxC,KAAK,QAAU,KAAK,KAAK,cAAc,gBACvC,KAAK,QAAU,KAAK,KAAK,cAAc,gBACvC,KAAK,QAAU,KAAK,KAAK,cAAc,gBACvC,KAAK,cAAgB,KAAK,KAAK,cAAc,uBAC7C,KAAK,UAAY,KAAK,KAAK,cAAc,kBAEzC,KAAK,SAAW,KAAK,SAAS,KAAK,MACnC,KAAK,QAAU,KAAK,QAAQ,KAAK,MACjC,KAAK,QAAU,KAAK,QAAQ,KAAK,MACjC,KAAK,QAAU,KAAK,QAAQ,KAAK,MACjC,KAAK,cAAgB,KAAK,cAAc,KAAK,MAC7C,KAAK,SAAW,KAAK,SAAS,KAAK,MAEnC,KAAK,SAAS,iBAAiB,QAAS,KAAK,UAC7C,KAAK,QAAQ,iBAAiB,QAAS,KAAK,SAC5C,KAAK,QAAQ,iBAAiB,QAAS,KAAK,SAC5C,KAAK,QAAQ,iBAAiB,QAAS,KAAK,SAC5C,KAAK,cAAc,iBAAiB,SAAU,KAAK,cAAe,CAChE,QAAS,KAEX,KAAK,UAAU,iBAAiB,QAAS,KAAK,UAG9C,KAAK,WAAa,KAAK,WAAW,KAAK,MACvC,KAAK,UAAY,KAAK,UAAU,KAAK,MACrC,SAAS,iBAAiB,aAAc,KAAK,YAC7C,SAAS,iBAAiB,YAAa,KAAK,WAG5C,KAAK,cAAgB,KAAK,MAAM,cAEhC,KAAK,WAAW,QAAQ,IAAM,CAC5B,KAAK,cAEL,KAAK,aACL,KAAK,eACL,KAAK,gBAEL,KAAK,KAAK,UAAU,IAAI,kBACxB,KAAK,cAAgB,KAGzB,sBAAuB,CACrB,KAAK,IAAI,wBAET,KAAK,SAAS,oBAAoB,QAAS,KAAK,UAChD,KAAK,QAAQ,oBAAoB,QAAS,KAAK,SAC/C,KAAK,QAAQ,oBAAoB,QAAS,KAAK,SAC/C,KAAK,QAAQ,oBAAoB,QAAS,KAAK,SAC/C,KAAK,cAAc,oBAAoB,SAAU,KAAK,cAAe,CACnE,QAAS,KAEX,KAAK,UAAU,oBAAoB,QAAS,KAAK,UAGjD,SAAS,oBAAoB,aAAc,KAAK,YAChD,SAAS,oBAAoB,YAAa,KAAK,WAG3C,KAAK,WACP,KAAK,UAAU,oBAAoB,SAAU,KAAK,iBAIhD,KAAK,WACP,KAAK,UAAU,oBAAoB,cAAe,KAAK,iBAK3D,iBAAkB,CAChB,KAAK,KAAK,iBAAiB,8BAA8B,QAAQ,AAAC,GAAO,CACvE,EAAG,QAAU,KAAK,UAAU,UAGhC,WAAW,EAAG,CACZ,KAAK,MAAQ,EAAE,QAAQ,GAEzB,UAAU,EAAG,CACX,GAAI,CAAC,KAAK,MACR,OAEF,GAAM,GAAQ,KAAK,MAAM,QAAU,EAAE,QAAQ,GAAG,QAC1C,EAAQ,KAAK,MAAM,QAAU,EAAE,QAAQ,GAAG,QAEhD,AAAI,KAAK,IAAI,GAAS,KAAK,IAAI,IAC7B,CAAI,EAAQ,EACV,KAAK,UAEL,KAAK,WAGT,KAAK,MAAQ,KAMf,WAAW,EAAS,CAClB,OAAW,CAAC,EAAK,IAAU,QAAO,QAAQ,GACxC,AAAI,IAAO,OACT,MAAK,GAAO,EACZ,KAAK,MAAM,GAAO,GAIxB,WAAW,EAAO,EAAM,CACtB,GAAI,GAAI,KACR,YAAK,MAAM,QAAQ,QAAQ,AAAC,GAAQ,CAClC,GAAI,EAAI,OAAS,EAAO,CACtB,EAAI,EAAI,GACR,UAGG,EAET,WAAW,EAAO,EAAM,EAAK,CAC3B,KAAK,MAAM,QAAQ,QAAQ,AAAC,GAAQ,CAClC,AAAI,EAAI,OAAS,GACf,GAAI,GAAQ,KAIlB,YAAa,CACX,MAAO,MAAK,WAAa,EAAI,EAE/B,cAAc,EAAc,GAAO,CACjC,GAAI,GAAM,EACV,YAAK,MAAM,QAAQ,QAAQ,AAAC,GAAQ,CAClC,AAAI,GAAe,EAAI,QAGlB,EAAI,MACP,MAGA,KAAK,YACP,IAEE,KAAK,MAAM,QAAQ,QACrB,IAEK,EAET,sBAAuB,CACrB,KAAK,cAAgB,KAAK,KAAK,cAAc,SAAS,aAGlD,KAAK,MAAM,QACb,MAAK,MAAM,OAAS,KAAK,cAAgB,KACzC,KAAK,MAAM,UAAY,OAEvB,KAAK,KAAK,cAAc,SAAS,MAAM,OAAS,QAG9C,KAAK,MAAM,WAAa,SAAS,KAAK,MAAM,WAAa,KAAK,eAChE,MAAK,MAAM,UAAY,KAAK,cAAgB,MAGhD,aAAc,CACZ,KAAK,aACL,KAAK,KAAK,cAAc,SAAS,aAAa,gBAAiB,KAAK,KAAK,QACzE,KAAK,KAAK,cAAc,SAAS,gBAAgB,UACjD,KAAK,eAGA,KAAK,WACR,MAAK,UAAY,KAAK,KAAK,cAAc,YAAY,cAMzD,SAAU,CACR,KAAK,MAAM,MAAQ,KAAK,aAGpB,KAAK,MAAM,MAAQ,KAAK,MAAM,MAChC,MAAK,MAAM,KAAO,KAAK,MAAM,OAE3B,KAAK,MAAM,KAAO,GACpB,MAAK,MAAM,KAAO,GAIpB,KAAK,UAAU,aAAa,MAAO,KAAK,MAAM,OAC9C,KAAK,UAAU,MAAQ,KAAK,MAAM,KAClC,KAAK,UAAU,SAAW,KAAK,MAAM,QAAU,EAEjD,cAAe,CACb,GAAM,GAAM,KAAK,KAAK,cAAc,4BACpC,AAAI,KAAK,MAAM,OACb,EAAI,gBAAgB,UAEpB,EAAI,aAAa,SAAU,IAG/B,eAAgB,CACd,KAAK,KAAK,iBAAiB,+BAA+B,QAAQ,AAAC,GAAO,CACxE,AAAI,EAAG,UAAU,SAAS,kBAAoB,EAAG,UAAU,SAAS,eAGpE,CAAI,KAAK,MAAM,QACb,EAAG,UAAY,GAEf,EAAG,gBAAgB,gBAIzB,YAAa,CACX,KAAK,IAAI,eACT,KAAK,KAAK,iBAAiB,+BAA+B,QAAQ,AAAC,GAAO,CACxE,AAAI,EAAG,UAAU,SAAS,kBAAoB,EAAG,UAAU,SAAS,eAGpE,CAAI,KAAK,MAAM,MAAQ,CAAC,KAAK,WAAW,EAAG,aAAa,SAAU,UAChE,EAAG,aAAa,YAAa,QAE7B,EAAG,gBAAgB,gBAIzB,OAAO,EAAK,CACV,KAAK,IAAI,WACT,KAAK,aAAa,KAAK,GACvB,KAAK,KAAO,KAAK,aAAa,QAC9B,KAAK,UACL,KAAK,WAEP,UAAU,EAAQ,KAAM,EAAM,KAAM,CAClC,AAAI,IAAQ,MACV,GAAM,KAAK,QAAQ,GAAG,OAEpB,IAAU,MACZ,GAAQ,KAAK,aAAa,KAAK,aAAa,OAAS,GAAG,IAE1D,KAAK,IAAI,YAAc,EAAM,IAAM,GACnC,OAAS,GAAI,EAAG,EAAI,KAAK,aAAa,OAAQ,IAC5C,GAAI,KAAK,aAAa,GAAG,KAAS,EAAO,CACvC,KAAK,aAAa,OAAO,EAAG,GAC5B,MAGJ,KAAK,KAAO,KAAK,aAAa,QAC9B,KAAK,UACL,KAAK,WAEP,aAAa,EAAM,KAAM,CACvB,GAAI,GAAe,GACnB,YAAK,KAAK,QAAQ,CAAC,EAAM,IAAM,CAG7B,AAAI,AADa,AADL,KAAK,KAAK,cAAc,2BAA8B,GAAI,GAAK,MACtD,cAAc,wBACtB,SACX,CAAI,EACF,EAAa,KAAK,EAAK,IAEvB,EAAa,KAAK,MAIjB,EAET,SAAU,CACR,MAAO,MAAK,aAEd,WAAY,CAGV,AADA,KAAK,MAAM,IAAM,KACb,KAAK,KAAK,SAAW,GAGzB,MAAK,KAAO,KAAK,aAAe,GAChC,KAAK,UACL,KAAK,eACL,KAAK,wBAKP,UAAW,CACT,MAAI,CAAC,KAAK,QAAU,KAAK,aAAa,OACpC,MAAK,IAAI,iBACF,GAAI,SAAQ,CAAC,EAAS,IAAW,CACtC,OAGJ,MAAK,IAAI,YACF,KAAK,YACT,KAAK,AAAC,GAAa,CAClB,GAAI,MAAM,QAAQ,GAChB,KAAK,KAAO,MACP,CACL,GAAI,CAAC,EAAS,KAAM,CAClB,QAAQ,MAAM,mFAAoF,GAClG,OAIF,AAAI,EAAS,SACX,KAAK,WAAW,EAAS,SAEvB,EAAS,MACX,MAAK,KAAO,EAAS,MAGvB,KAAK,KAAO,EAAS,KAEvB,KAAK,aAAe,KAAK,KAAK,QAC9B,KAAK,UAGD,KAAK,MAAM,QAAQ,SAAW,GAAK,KAAK,aAAa,QACvD,MAAK,MAAM,QAAU,EAAS,eAAe,OAAO,KAAK,KAAK,aAAa,QAG9E,MAAM,AAAC,GAAQ,CACd,KAAK,IAAM,KACX,KAAK,IAAI,MAGf,UAAW,CACT,KAAK,KAAO,EAEd,SAAU,CACR,KAAK,KAAO,KAAK,MAAM,MAEzB,SAAU,CACR,KAAK,KAAO,KAAK,MAAM,KAAO,EAEhC,SAAU,CACR,KAAK,KAAO,KAAK,MAAM,KAAO,EAKhC,SAAU,CACR,YAAK,KAAO,KAAK,aAAe,GACzB,KAAK,WAEd,eAAgB,CACd,KAAK,QAAU,KAAK,cAAc,QAAQ,KAAK,cAAc,eAAe,MAE9E,SAAS,EAAO,CACd,GAAI,EAAM,OAAS,WAAY,CAC7B,GAAM,GAAM,EAAM,SAAW,EAAM,IACnC,GAAI,IAAQ,IAAM,IAAQ,QACxB,EAAM,qBAEN,QAGJ,KAAK,KAAO,KAAK,UAAU,MAE7B,SAAU,CACR,GAAI,GAAM,KAAK,KAAK,cAAc,sDAClC,MAAI,GACK,EAAI,aAAa,SAEnB,KAAK,YAEd,YAAa,CACX,GAAI,GAAM,KAAK,KAAK,cAAc,sDAClC,MAAI,IACK,EAAI,aAAa,cAAgB,GAI5C,YAAa,CACX,GAAI,GAAU,GACd,YAAK,KAAK,iBAAiB,kCAAkC,QAAQ,AAAC,GAAU,CAC9E,EAAQ,EAAM,QAAQ,MAAQ,EAAM,QAE/B,EAET,cAAe,CACb,KAAK,KAAK,iBAAiB,kCAAkC,QAAQ,AAAC,GAAU,CAC9E,EAAM,MAAQ,KAEhB,KAAK,aAEP,YAAa,CAGX,GAFA,KAAK,IAAI,eAEL,KAAK,OACP,KAAK,WAAW,QAAQ,IAAM,CAC5B,KAAK,UACL,KAAK,mBAEF,CACL,KAAK,KAAO,KAAK,aAAa,QAE9B,KAAK,KAAK,iBAAiB,kCAAkC,QAAQ,AAAC,GAAU,CAC9E,GAAI,GAAQ,EAAM,MAClB,GAAI,EAAO,CACT,GAAI,GAAO,EAAM,QAAQ,KACzB,KAAK,KAAO,KAAK,KAAK,OAAO,AAAC,GAErB,AADG,GAAK,GAAQ,IACZ,cAAc,QAAQ,EAAM,iBAAmB,OAKhE,KAAK,UACL,GAAI,GAAM,KAAK,KAAK,cAAc,sDAClC,AAAI,KAAK,MAAM,MAAQ,EACrB,KAAK,SAAS,GAEd,KAAK,cAQX,SAAS,EAAM,KAAM,CAInB,GAHA,KAAK,IAAI,aAGN,KAAO,KAAK,WAAW,EAAI,aAAa,SAAU,WA6BrD,GAxBA,AAAI,IAAQ,KAEV,MAAK,KAAK,iBAAiB,2BAA2B,QAAQ,AAAC,GAAO,CACpE,AAAI,EAAG,UAAU,SAAS,kBAAoB,EAAG,UAAU,SAAS,eAGhE,IAAO,GACT,EAAG,aAAa,YAAa,UAKjC,AAAI,CAAC,EAAI,aAAa,cAAgB,EAAI,aAAa,eAAiB,OACtE,EAAI,aAAa,YAAa,aACzB,AAAI,EAAI,aAAa,eAAiB,YAC3C,EAAI,aAAa,YAAa,cACrB,EAAI,aAAa,eAAiB,cAC3C,EAAI,aAAa,YAAa,SAIhC,EAAM,KAAK,KAAK,cAAc,sDAG5B,KAAK,OAEP,KAAK,WAAW,QAAQ,IAAM,CAC5B,KAAK,mBAEF,CACL,GAAM,GAAO,EAAM,EAAI,aAAa,aAAe,OACnD,GAAI,IAAS,OAAQ,CACnB,GAAI,GAAQ,GAGZ,KAAK,aAAa,KAAK,AAAC,GACtB,MAAK,KAAK,KAAK,AAAC,GACV,KAAK,UAAU,KAAW,KAAK,UAAU,GAC3C,GAAM,KAAK,GACJ,IAEF,IAEF,EAAM,SAAW,KAAK,KAAK,SAGpC,KAAK,KAAO,MACP,CACL,GAAM,GAAQ,EAAI,aAAa,SAC/B,KAAK,KAAK,KAAK,CAAC,EAAG,IAAM,CACvB,GAAI,CAAC,MAAM,EAAE,KAAW,CAAC,MAAM,EAAE,IAC/B,MAAO,KAAS,YAAc,EAAE,GAAS,EAAE,GAAS,EAAE,GAAS,EAAE,GAEnE,GAAM,GAAO,IAAS,YAAc,EAAE,GAAO,cAAgB,EAAE,GAAO,cAChE,EAAO,IAAS,YAAc,EAAE,GAAO,cAAgB,EAAE,GAAO,cAEtE,OAAQ,QACD,GAAO,EACV,MAAO,OACJ,GAAO,EACV,MAAO,OACJ,KAAS,EACZ,MAAO,MAGb,KAAK,eAIX,WAAY,CACV,GAAI,CAAC,KAAK,IACR,MAAO,IAAI,SAAQ,CAAC,EAAS,IAAW,EAAO,eAEjD,GAAI,GAAM,GAAI,KAAI,KAAK,IAAK,OAAO,SAAS,MACxC,EAAS,CACX,EAAG,KAAK,KAAK,KAAK,SAAW,UAE/B,MAAI,MAAK,QAEP,GAAO,MAAW,KAAK,MAAM,KAAO,EACpC,EAAO,OAAY,KAAK,MAAM,QAC9B,EAAO,OAAY,KAAK,aACxB,EAAO,KAAU,KAAK,WAAa,GACnC,EAAO,QAAa,KAAK,cAG3B,OAAO,KAAK,GAAQ,QAAQ,AAAC,GAAQ,CACnC,AAAI,MAAM,QAAQ,EAAO,IACvB,OAAO,KAAK,EAAO,IAAM,QAAQ,AAAC,GAAM,EAAI,aAAa,OAAO,EAAM,IAAM,EAAI,IAAK,EAAO,GAAK,KAEjG,EAAI,aAAa,OAAO,EAAK,EAAO,MAIjC,MAAM,GAAK,KAAK,AAAC,GACf,EAAS,QAGpB,cAAe,CACb,KAAK,IAAI,iBACT,GAAI,GACA,EACA,EAAQ,KAAK,KAAK,cAAc,SAEpC,KAAK,oBAAoB,GACrB,KAAK,MAAM,aAEb,GAAe,KAAK,KAAK,cAAc,sCAAwC,KAAK,MAAM,YAAc,OAI1G,KAAK,oBAAoB,GAGzB,KAAK,KAAK,cAAc,SAAS,aAAa,gBAAiB,KAAK,cAAc,IAAM,YACxF,KAAK,KAAK,cAAc,SAAS,cAAc,MAAM,aAAa,UAAW,KAAK,cAAc,IAAM,YAEtG,AAAI,EACF,KAAK,SAAS,GAEd,KAAK,aAGP,KAAK,KAAK,cAAc,SAAS,MAAM,QAAU,GAC7C,KAAK,WACP,KAAK,gBAGT,oBAAoB,EAAO,CACzB,GAAM,GAAc,SAAU,EAAM,YAAc,KAAK,cAAc,IAAS,GAE1E,EAAM,EACN,EAUJ,GAPA,EAAK,SAAS,cAAc,MAC5B,KAAK,UAAY,EACjB,EAAG,aAAa,OAAQ,OACxB,EAAG,aAAa,gBAAiB,GACjC,EAAG,aAAa,QAAS,mBAGrB,KAAK,WAAY,CACnB,GAAI,GAAe,SAAS,cAAc,MAC1C,EAAa,aAAa,OAAQ,uBAClC,EAAa,aAAa,gBAAiB,GAC3C,EAAa,UAAU,IAAI,iBAC3B,EAAa,SAAW,EAExB,KAAK,UAAY,SAAS,cAAc,SACxC,KAAK,UAAU,KAAO,WACtB,KAAK,UAAU,UAAU,IAAI,iBAE7B,KAAK,gBAAkB,KAAK,gBAAgB,KAAK,MACjD,KAAK,UAAU,iBAAiB,SAAU,KAAK,iBAE/C,GAAI,GAAQ,SAAS,cAAc,SACnC,EAAM,YAAY,KAAK,WAEvB,EAAa,YAAY,GACzB,EAAa,aAAa,QAAS,IACnC,EAAG,YAAY,GAIjB,EAAM,EACN,GAAI,GAAa,EAoCjB,GAnCA,KAAK,MAAM,QAAQ,QAAQ,CAAC,EAAQ,IAAM,CACxC,GAAI,EAAO,KACT,OAEF,GAAI,GAAK,SAAS,cAAc,MAChC,EAAG,aAAa,OAAQ,uBACxB,EAAG,aAAa,gBAAiB,EAAM,KAAK,cAC5C,EAAG,aAAa,KAAM,EAAS,QAAQ,YACnC,KAAK,MAAM,MACb,EAAG,aAAa,YAAa,QAE/B,EAAG,aAAa,QAAS,EAAO,OAChC,EAAG,QAAQ,SAAW,EAAS,aAAa,EAAO,MAAO,GAAM,GAChE,EAAS,sBAAsB,EAAI,GACnC,EAAG,SAAW,EACd,EAAG,YAAc,EAAO,MAEpB,EAAO,QACT,EAAG,aAAa,SAAU,IAIxB,KAAK,UAAY,CAAC,EAAG,aAAa,UACpC,IAAc,KAAK,eAAe,EAAI,EAAQ,EAAG,QAAQ,SAAU,IAIjE,KAAK,MAAM,SACb,KAAK,oBAAoB,GAE3B,EAAG,YAAY,GACf,MAIE,EAAa,EAAM,YAAa,CAClC,GAAI,GAAS,EAAG,UAChB,AAAI,GACF,EAAO,gBAAgB,SAK3B,GAAI,KAAK,MAAM,QAAQ,OAAQ,CAC7B,GAAI,GAAY,SAAS,cAAc,MACvC,EAAU,aAAa,OAAQ,uBAC/B,EAAU,aAAa,gBAAiB,KAAK,cAAc,KAC3D,EAAU,UAAU,IAAI,cACxB,EAAU,SAAW,EACrB,EAAG,YAAY,GAGjB,EAAM,aAAa,EAAI,EAAM,cAAc,uBAG3C,KAAK,gBAAkB,KAAK,gBAAgB,KAAK,MACjD,EAAG,iBAAiB,cAAe,KAAK,iBAGxC,EAAG,iBAAiB,eAAe,QAAQ,AAAC,GAAgB,CAC1D,EAAY,iBAAiB,QAAS,IAAM,KAAK,SAAS,MAG9D,oBAAoB,EAAO,CACzB,GAAI,GAAM,EACN,EAaJ,GAVA,EAAK,SAAS,cAAc,MAC5B,KAAK,UAAY,EACjB,EAAG,aAAa,OAAQ,OACxB,EAAG,aAAa,gBAAiB,GACjC,EAAG,aAAa,QAAS,mBACpB,KAAK,MAAM,QACd,EAAG,aAAa,SAAU,IAIxB,KAAK,WAAY,CACnB,GAAI,GAAK,SAAS,cAAc,MAChC,EAAG,aAAa,OAAQ,uBACxB,EAAG,aAAa,gBAAiB,GACjC,EAAG,UAAU,IAAI,iBACjB,EAAG,SAAW,EACd,EAAG,YAAY,GAoCjB,GAjCA,KAAK,MAAM,QAAQ,QAAQ,CAAC,EAAQ,IAAM,CACxC,GAAI,EAAO,KACT,OAEF,GAAI,GAAY,EAAM,cAAc,wCAA2C,GAAM,KAAK,cAAgB,MACtG,EAAK,SAAS,cAAc,MAChC,EAAG,aAAa,gBAAiB,EAAM,KAAK,cAE5C,GAAI,GAAQ,SAAS,cAAc,SACnC,EAAM,KAAO,OACb,EAAM,aAAe,MACrB,EAAM,WAAa,GAEnB,EAAM,QAAQ,KAAO,EAAO,MAC5B,EAAM,GAAK,EAAS,QAAQ,cAE5B,EAAM,aAAa,kBAAmB,EAAU,aAAa,OAC7D,AAAK,KAAK,MAAM,OAGd,EAAM,SAAW,EAFjB,EAAG,SAAW,EAKZ,EAAO,QACT,EAAG,aAAa,SAAU,IAG5B,EAAG,YAAY,GACf,EAAG,YAAY,GACf,MAIE,KAAK,MAAM,QAAQ,OAAQ,CAC7B,GAAI,GAAY,SAAS,cAAc,MACvC,EAAU,aAAa,OAAQ,uBAC/B,EAAU,aAAa,gBAAiB,KAAK,cAAc,KAC3D,EAAU,UAAU,IAAI,cACxB,EAAU,SAAW,EACrB,EAAG,YAAY,GAGjB,EAAM,aAAa,EAAI,EAAM,cAAc,uBAG3C,EAAG,iBAAiB,SAAS,QAAQ,AAAC,GAAU,CAC9C,EAAM,iBAAiB,WAAY,AAAC,GAAM,CACxC,GAAM,GAAM,EAAE,SAAW,EAAE,IAC3B,AAAI,KAAQ,IAAM,IAAQ,UACxB,KAAK,WAAW,KAAK,UAK7B,eAAe,EAAI,EAAQ,EAAK,EAAK,CACnC,GAAI,GAAI,KAAK,KAAK,GAAG,EAAO,OAAO,WAC/B,EAAK,KAAK,KAAK,KAAK,KAAK,OAAS,GAAG,EAAO,OAAO,WACvD,AAAI,EAAG,OAAS,EAAE,QAChB,GAAI,GAEN,GAAI,GAAQ,EACZ,MAAI,GAAE,QAAU,EACd,EAAQ,EACH,AAAI,EAAE,OAAS,GACpB,EAAQ,EAER,EAAQ,EAAS,aAAa,EAAG,GAE/B,EAAQ,GACV,GAAQ,GAEV,EAAG,aAAa,QAAS,GAClB,SAAS,GAElB,gBAAgB,EAAG,CACjB,EAAE,iBAEF,GAAM,GAAS,EAAS,cAAc,EAAE,OAAQ,SAC1C,EAAO,KAAK,KAAK,cAAc,YAC/B,EAAO,EAAO,wBAChB,EAAI,EAAE,QAAU,EAAK,KACnB,EAAI,EAAE,QAAU,EAAK,IAE3B,EAAK,MAAM,IAAM,GAAG,MACpB,EAAK,MAAM,KAAO,GAAG,MAErB,EAAK,gBAAgB,UACjB,EAAI,IAAM,EAAK,OACjB,IAAK,EAAK,YACV,EAAK,MAAM,KAAO,GAAG,OAGvB,GAAM,GAAuB,AAAC,GAAM,CAClC,AAAK,EAAK,SAAS,EAAE,SACnB,GAAK,aAAa,SAAU,IAC5B,SAAS,oBAAoB,QAAS,KAG1C,SAAS,iBAAiB,QAAS,GAErC,YAAa,CACX,GAAM,GAAO,KAAK,KAAK,cAAc,YACrC,KAAK,MAAM,QAAQ,QAAQ,AAAC,GAAQ,CAClC,GAAI,EAAI,KACN,OAEF,GAAM,GAAQ,EAAI,MACZ,EAAK,SAAS,cAAc,MAC5B,EAAQ,SAAS,cAAc,SAC/B,EAAW,SAAS,cAAc,SACxC,EAAS,aAAa,OAAQ,YACzB,EAAI,QACP,GAAS,QAAU,IAErB,EAAS,iBAAiB,SAAU,AAAC,GAAM,CACzC,EAAE,OAAO,QAAU,KAAK,WAAW,EAAO,EAAE,QAAU,KAAK,WAAW,EAAO,EAAE,UAGjF,GAAM,GAAO,SAAS,eAAe,EAAI,OAEzC,EAAM,YAAY,GAClB,EAAM,YAAY,GAElB,EAAG,YAAY,GACf,EAAK,YAAY,KAGrB,WAAW,EAAO,EAAW,KAAM,CACjC,AAAI,GACF,GAAS,QAAU,IAErB,KAAK,WAAW,EAAO,SAAU,IACjC,KAAK,eAEP,WAAW,EAAO,EAAW,KAAM,CAKjC,GAAI,AAJkB,KAAK,MAAM,QAAQ,OAAO,AAAC,GACxC,EAAG,SAAW,IACpB,SAEmB,KAAK,gBAAkB,EAAG,CAE9C,AAAI,GACF,GAAS,QAAU,IAErB,OAEF,KAAK,WAAW,EAAO,SAAU,IACjC,KAAK,eAEP,oBAAoB,EAAI,CACtB,EAAG,UAAY,GACf,EAAG,iBAAiB,YAAa,AAAC,GAAM,CACtC,GAAI,KAAK,YAAc,EAAE,eAAgB,CACvC,EAAE,iBACF,OAEF,KAAK,IAAI,eACT,EAAE,aAAa,cAAgB,OAC/B,EAAE,aAAa,QAAQ,aAAc,EAAE,OAAO,aAAa,oBAE7D,EAAG,iBAAiB,WAAY,AAAC,GAC3B,GAAE,gBACJ,EAAE,iBAEJ,EAAE,aAAa,WAAa,OACrB,KAET,EAAG,iBAAiB,OAAQ,AAAC,GAAM,CACjC,AAAI,EAAE,iBACJ,EAAE,kBAEJ,GAAM,GAAS,EAAS,cAAc,EAAE,OAAQ,MAC1C,EAAQ,EAAE,aAAa,QAAQ,cAC/B,EAAc,EAAO,aAAa,iBAExC,GAAI,IAAU,EAAa,CACzB,KAAK,IAAI,iCACT,OAEF,KAAK,IAAI,sBAAwB,EAAQ,OAAS,GAElD,GAAM,GAAM,KAAK,MAAM,QAAQ,EAAQ,GACvC,KAAK,MAAM,QAAQ,EAAQ,GAAK,KAAK,QAAQ,EAAc,GAC3D,KAAK,MAAM,QAAQ,EAAc,GAAK,EAEtC,GAAM,GAAY,CAAC,EAAU,IAAQ,CACnC,GAAM,GAAW,EAAI,WAAW,aAAa,iBACvC,EAAM,KAAK,KAAK,cAAc,EAAW,sBAAwB,EAAW,sBAAwB,EAAc,MACxH,EAAI,aAAa,gBAAiB,GAClC,EAAI,aAAa,gBAAiB,GAClC,GAAM,GAAU,SAAS,cAAc,MACvC,EAAI,WAAW,aAAa,EAAS,GACrC,EAAI,WAAW,aAAa,EAAK,GACjC,EAAQ,WAAW,aAAa,EAAK,IAIvC,YAAK,KAAK,iBAAiB,2BAA6B,EAAQ,MAAM,QAAQ,AAAC,GAAQ,CACrF,EAAU,QAAS,KAErB,KAAK,KAAK,iBAAiB,2BAA6B,EAAQ,MAAM,QAAQ,AAAC,GAAQ,CACrF,EAAU,QAAS,KAGd,KAGX,eAAgB,CACd,GAAM,GAAQ,KAAK,KAAK,cAAc,SAChC,EAAO,KAAK,KAAK,iBAAiB,+BAExC,EAAK,QAAQ,AAAC,GAAQ,CACpB,GAAI,EAAI,UAAU,SAAS,kBAAoB,EAAI,UAAU,SAAS,cACpE,OAGF,GAAM,GAAU,SAAS,cAAc,OACvC,EAAQ,UAAU,IAAI,cACtB,EAAQ,UAAY,EAAO,aAG3B,EAAI,YAAY,GAGhB,GAAI,GAAS,EACT,EAAS,EACT,EAAiB,EACjB,EAAM,EAEJ,EAAmB,AAAC,GAAM,CAC9B,GAAI,EAAE,QAAU,EACd,OAEF,GAAM,GAAW,EAAU,GAAE,QAAU,GACvC,AAAI,EAAI,QAAQ,UAAY,EAAW,EAAI,QAAQ,UACjD,GAAI,MAAQ,IAKV,EAAiB,IAAM,CAC3B,KAAK,IAAI,kBAET,KAAK,WAAa,GAClB,EAAQ,UAAU,OAAO,qBACrB,KAAK,MAAM,SACb,GAAI,UAAY,IAElB,EAAI,MAAM,SAAW,SAErB,SAAS,oBAAoB,YAAa,GAC1C,SAAS,oBAAoB,UAAW,IAI1C,EAAQ,iBAAiB,QAAS,AAAC,GAAM,CACvC,EAAE,oBAGJ,EAAQ,iBAAiB,YAAa,AAAC,GAAM,CAC3C,EAAE,kBACF,KAAK,WAAa,GAElB,GAAM,GAAc,KAAK,KAAK,iBAAiB,uBACzC,EAAc,MAAM,KAAK,GAAa,OAAO,AAAC,GAC3C,CAAC,EAAI,aAAa,WAGrB,EAAc,AADJ,MAAM,KAAK,GACC,UAAU,AAAC,GAAW,GAAU,EAAE,OAAO,YACrE,KAAK,IAAI,iBAET,EAAQ,UAAU,IAAI,qBAGlB,EAAI,aAAa,cACnB,EAAI,gBAAgB,aAItB,EAAI,MAAM,SAAW,UAGrB,EAAQ,MAAM,OAAS,EAAM,aAAe,EAAI,KAGhD,EAAS,EAAE,QACX,EAAS,EAAI,YAEb,EAAkB,GAAY,OAAS,GAAe,GACtD,EAAM,EAAS,cAAc,MAAM,KAAO,KAAK,YAAc,EAG7D,EAAI,aAAa,QAAS,GAC1B,OAAS,GAAI,EAAG,EAAI,EAAY,OAAQ,IACtC,AAAI,EAAI,GACN,EAAK,GAAG,gBAAgB,SAK5B,SAAS,iBAAiB,YAAa,GACvC,SAAS,iBAAiB,UAAW,OAQ3C,YAAa,CACX,KAAK,IAAI,eACT,GAAI,GACA,EACA,EACA,EAAQ,SAAS,cAAc,SACnC,KAAK,KAAK,QAAQ,CAAC,EAAM,IAAM,CAQ7B,GAPA,EAAK,SAAS,cAAc,MAC5B,EAAG,aAAa,OAAQ,OACxB,EAAG,aAAa,SAAU,IAC1B,EAAG,aAAa,gBAAiB,EAAI,GACrC,EAAG,SAAW,EAGV,KAAK,WAAY,CACnB,EAAK,SAAS,cAAc,MAC5B,EAAG,aAAa,OAAQ,mBACxB,EAAG,aAAa,gBAAiB,GACjC,EAAG,UAAU,IAAI,iBAEjB,GAAI,GAAY,SAAS,cAAc,SACvC,EAAU,KAAO,WACjB,GAAI,GAAQ,SAAS,cAAc,SACnC,EAAM,YAAY,GAClB,EAAG,YAAY,GAEf,EAAG,YAAY,GAIjB,AAAI,KAAK,QACP,EAAG,iBAAiB,QAAS,SAAU,EAAI,CACzC,KAAK,UAAU,OAAO,iBAI1B,EAAM,EACN,KAAK,MAAM,QAAQ,QAAQ,CAAC,EAAQ,IAAM,CAKxC,GAJK,GACH,QAAQ,IAAI,KAAK,MAAM,SAGrB,EAAO,KAAM,CACf,EAAG,aAAa,EAAO,KAAM,EAAK,EAAO,QACzC,OAUF,GARA,EAAK,SAAS,cAAc,MAC5B,EAAG,aAAa,OAAQ,YACxB,EAAG,aAAa,gBAAiB,EAAM,KAAK,cAC5C,EAAS,sBAAsB,EAAI,GACnC,EAAG,aAAa,YAAa,EAAO,OACpC,EAAG,SAAW,GAGV,EAAO,SAAU,CACnB,GAAI,GAAQ,SAAS,cAAc,SACnC,EAAM,KAAO,OACb,EAAM,aAAe,MACrB,EAAM,WAAa,GACnB,EAAM,SAAW,EACjB,EAAM,UAAU,IAAI,eACpB,EAAM,KAAO,KAAK,aAAa,MAAM,QAAQ,IAAK,KAAO,IAAO,GAAI,GAAK,KAAY,EAAO,MAAQ,IACpG,EAAM,MAAQ,EAAK,EAAO,OAC1B,EAAM,QAAQ,MAAQ,EAAO,MAE7B,EAAM,iBAAiB,QAAS,AAAC,GAAO,EAAG,mBAC3C,EAAM,iBAAiB,WAAY,AAAC,GAAO,CACzC,GAAI,EAAG,OAAS,WAAY,CAC1B,GAAM,GAAM,EAAG,SAAW,EAAG,IAC7B,AAAI,KAAQ,IAAM,IAAQ,UACxB,EAAM,UAIZ,EAAM,iBAAiB,OAAQ,AAAC,GAAO,CAErC,GAAI,EAAM,OAAS,EAAK,EAAM,QAAQ,OACpC,OAGF,EAAK,EAAM,QAAQ,OAAS,EAAM,MAElC,GAAM,GAAQ,GAAI,aAAY,OAAQ,CACpC,QAAS,GACT,OAAQ,CACN,KAAM,EACN,MAAO,EAAM,SAGjB,KAAK,cAAc,KAErB,EAAG,YAAY,OAEf,GAAG,YAAc,EAAK,EAAO,OAE/B,AAAI,EAAO,QACT,EAAG,aAAa,SAAU,IAE5B,EAAG,YAAY,GACf,MAIE,KAAK,MAAM,QAAQ,QACrB,GAAK,SAAS,cAAc,MAC5B,EAAG,aAAa,OAAQ,YACxB,EAAG,aAAa,gBAAiB,KAAK,cAAc,KACpD,EAAG,UAAU,IAAI,cACjB,EAAG,SAAW,EAEd,KAAK,MAAM,QAAQ,QAAQ,AAAC,GAAW,CACrC,GAAI,GAAS,SAAS,cAAc,UACpC,AAAI,EAAO,KACT,EAAO,UAAY,EAAO,KAE1B,EAAO,UAAY,EAAO,OAAS,EAAO,KAExC,EAAO,KACT,GAAO,KAAO,SACd,EAAO,WAAa,EAAS,YAAY,EAAO,IAAK,IAEnD,EAAO,OACT,EAAO,UAAU,IAAI,EAAO,OAE9B,GAAM,GAAgB,AAAC,GAAO,CAE5B,GADA,EAAG,kBACC,EAAO,SAEL,CADI,QAAQ,EAAO,YACf,CACN,EAAG,iBACH,OAGJ,GAAM,GAAQ,GAAI,aAAY,SAAU,CACtC,QAAS,GACT,OAAQ,CACN,KAAM,EACN,OAAQ,EAAO,QAGnB,KAAK,cAAc,IAErB,EAAO,iBAAiB,QAAS,GACjC,EAAG,YAAY,GAGX,EAAO,SACT,GAAG,UAAU,IAAI,iBACjB,EAAG,iBAAiB,QAAS,MAIjC,EAAG,YAAY,IAGjB,EAAM,YAAY,KAGpB,EAAM,aAAa,OAAQ,YAE3B,KAAK,KAAK,cAAc,SAAS,aAAa,EAAO,KAAK,KAAK,cAAc,UAG7E,EAAK,SAAS,cAAc,MAC5B,EAAG,aAAa,OAAQ,OACxB,EAAG,aAAa,SAAU,IAC1B,EAAG,UAAU,IAAI,eACjB,EAAG,SAAW,EACd,EAAM,YAAY,GAElB,KAAK,WAEP,UAAW,CACT,KAAK,IAAI,YAET,GAAM,GAAQ,KAAK,eACb,EAAQ,KAAK,aAEf,EACA,EAAO,KAAK,MAAM,KAAO,KAAK,MAAM,QACpC,EAAM,EAAO,KAAK,MAAM,QAAU,EAClC,EAAQ,KAAK,KAAK,cAAc,SAChC,EAAQ,KAAK,KAAK,cAAc,SAEpC,AAAI,EAAO,GACT,GAAO,GAEJ,GACH,GAAM,GAGR,EAAM,iBAAiB,MAAM,QAAQ,AAAC,GAAO,CAC3C,GAAI,KAAK,OAAQ,CACf,EAAG,gBAAgB,UACnB,OAEF,EAAQ,OAAO,EAAG,aAAa,kBAC/B,AAAI,EAAQ,GAAQ,EAAQ,EAC1B,EAAG,aAAa,SAAU,IAE1B,EAAG,gBAAgB,YAKnB,KAAK,eAAiB,GACxB,KAAK,uBAIP,GAAI,GAAU,KAAK,cAAc,gBACjC,GAAI,KAAK,MAAM,OACb,GAAI,KAAK,MAAM,MAAQ,EAErB,GAAI,SAAS,KAAK,MAAM,QAAU,KAAK,cAAc,SAAS,aAAc,CAC1E,GAAM,GAAU,KAAK,MAAM,QAAW,GAAS,GAAQ,GAAK,KAAK,MAAM,SACvE,EAAQ,aAAa,SAAU,EAAU,KAAK,eAE9C,GAAQ,gBAAgB,cAG1B,GAAQ,gBAAgB,UAK5B,AAAI,KAAK,UACP,MAAK,SAAS,SAAW,KAAK,MAAM,MAAQ,EAC5C,KAAK,QAAQ,SAAW,KAAK,MAAM,MAAQ,EAC3C,KAAK,QAAQ,SAAW,KAAK,MAAM,MAAQ,KAAK,MAAM,MACtD,KAAK,QAAQ,SAAW,KAAK,MAAM,MAAQ,KAAK,MAAM,OAExD,EAAM,cAAc,WAAW,YAAc,EAAI,WACjD,EAAM,cAAc,YAAY,YAAc,EAAK,WACnD,EAAM,cAAc,aAAa,YAAc,KAAK,eAEtD,YAAa,CACX,MAAO,MAAK,KAAK,KAAK,eAAiB,KAAK,MAAM,SAEpD,cAAe,CACb,MAAI,MAAK,OACA,KAAK,KAAK,SAEZ,KAAK,KAAK,OAAO,WAK1B,IAAI,EAAS,CACX,AAAI,KAAK,OACP,QAAQ,IAAI,IAAM,KAAK,aAAa,MAAQ,KAAO,KAKzD,eAAe,OAAO,YAAa,GAEnC,GAAO,GAAQ",
+ "sourcesContent": ["/**\n * Data Grid Web component\n *\n * Credits for inspiration\n * @link https://github.com/riverside/zino-grid\n */\n\"use strict\";\n\n/**\n * @typedef Column\n * @property {string} field - the key in the data\n * @property {string} title - the title to display in the header (defaults to \"field\" if not set)\n * @property {number} width - the width of the column (auto otherwise)\n * @property {string} class - class to set on the column (target body or header with th.class or td.class)\n * @property {string} attr - don't render the column and set a matching attribute on the row with the value of the field\n * @property {boolean} hidden - hide the column\n * @property {boolean} editable - replace with input\n * @property {boolean} noSort - allow disabling sort for a given column\n */\n\n/**\n * @typedef Action\n * @property {string} title - the title of the button\n * @property {string} url - link for the action\n * @property {string} html - custom button data\n * @property {boolean} confirm - needs confirmation\n * @property {boolean} default - is the default row action\n */\n\nconst labels = Object.assign(\n {\n itemsPerPage: \"Items per page\",\n gotoPage: \"Go to page\",\n gotoFirstPage: \"Go to first page\",\n gotoPrevPage: \"Go to previous page\",\n gotoNextPage: \"Go to next page\",\n gotoLastPage: \"Go to last page\",\n of: \"of\",\n items: \"items\",\n resizeColumn: \"Resize column\",\n noData: \"No data\",\n areYouSure: \"Are you sure?\",\n },\n window.DataGridLabels || {}\n);\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = `\n\n \n
\n
\n \n \n \n \n \n \n | \n
\n \n \n
\n`;\n\n/**\n * @property {Column[]} state.columns\n * @property {Action[]} state.actions\n */\nclass DataGrid extends HTMLElement {\n constructor(options = {}) {\n super();\n\n // Don't use shadow dom as it makes theming super hard\n this.appendChild(template.content.cloneNode(true));\n this.root = this;\n\n this.state = {\n // reflected and observed\n url: null,\n page: 1,\n perPage: 10,\n debug: false,\n filter: false,\n sort: false,\n server: false,\n defaultSort: \"\",\n reorder: false,\n dir: \"ltr\",\n // not reflected\n pages: 0,\n perPageValues: [10, 25, 50, 100, 250],\n columns: [],\n actions: [],\n };\n this.setOptions(options);\n\n // The grid displays data\n this.data = [];\n // We store the data in this\n this.originalData = [];\n\n // Init values\n this.isInitialized = false;\n this.touch = null;\n this.isResizing = false;\n this.defaultHeight = 0;\n this.meta = {};\n\n // Set id\n if (!this.hasAttribute(\"id\")) {\n this.setAttribute(\"id\", DataGrid.randstr(\"dg-\"));\n }\n\n this.log(\"constructor\");\n }\n\n // utils\n\n /**\n * @param {string} str\n * @param {Object} data\n * @returns {string}\n */\n static interpolate(str, data) {\n return str.replace(/\\{([^\\}]+)?\\}/g, function ($1, $2) {\n return data[$2];\n });\n }\n\n /**\n * @param {HTMLElement} el\n * @param {string} type\n * @param {string} prop\n * @returns {HTMLElement}\n */\n static getParentNode(el, type, prop = \"nodeName\") {\n let parent = el;\n while (parent[prop] != type) {\n parent = parent.parentNode;\n }\n return parent;\n }\n\n /**\n * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.\n * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\n * @param {string} text The text to be rendered.\n * @param {HTMLElement} el Target element (defaults to body)\n * @return {number}\n */\n static getTextWidth(text, el = document.body) {\n const styles = window.getComputedStyle(el, null);\n const fontWeight = styles.getPropertyValue(\"font-weight\") || \"normal\";\n const fontSize = styles.getPropertyValue(\"font-size\") || \"1rem\";\n const fontFamily = styles.getPropertyValue(\"font-family\") || \"Arial\";\n\n // re-use canvas object for better performance\n const canvas = DataGrid.getTextWidth.canvas || (DataGrid.getTextWidth.canvas = document.createElement(\"canvas\"));\n const context = canvas.getContext(\"2d\");\n context.font = `${fontWeight} ${fontSize} ${fontFamily}`;\n const metrics = context.measureText(text);\n return parseInt(metrics.width);\n }\n\n /**\n * @param {HTMLElement} el\n * @param {string} value\n * @param {string} label\n * @param {boolean} checked\n */\n static addSelectOption(el, value, label, checked = false) {\n let opt = document.createElement(\"option\");\n opt.value = value;\n if (checked) {\n opt.selected = \"selected\";\n }\n opt.label = label;\n el.appendChild(opt);\n }\n /**\n * @param {string} prefix\n * @returns {string}\n */\n static randstr(prefix) {\n return Math.random()\n .toString(36)\n .replace(\"0.\", prefix || \"\");\n }\n /**\n * @param {string|Array} v\n * @returns\n */\n static convertArray(v) {\n if (typeof v === \"string\") {\n if (v[0] === \"{\") {\n return JSON.parse(v);\n }\n return v.split(\",\");\n }\n if (!Array.isArray(v)) {\n console.error(\"Invalid array\", v);\n }\n return v;\n }\n /**\n * @param {HTMLElement} el\n * @returns {Object}\n */\n static elementOffset(el) {\n var rect = el.getBoundingClientRect(),\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\n }\n /**\n * @param {HTMLElement} el\n * @param {Object} definition\n */\n static applyColumnDefinition(el, definition) {\n if (definition.width) {\n el.setAttribute(\"width\", definition.width);\n }\n if (definition.class) {\n el.setAttribute(\"class\", definition.class);\n }\n }\n /**\n * @param {Object|Array} columns\n * @returns {Object}\n */\n static convertColumns(columns) {\n let cols = [];\n // Convert objects to array\n if (typeof columns === \"object\" && !Array.isArray(columns)) {\n Object.keys(columns).forEach((key) => {\n let col = {};\n col.title = columns[key];\n col.field = key;\n cols.push(col);\n });\n } else {\n columns.forEach((item) => {\n let col = {};\n if (typeof item === \"string\") {\n col.title = item;\n col.field = item;\n } else if (typeof item === \"object\") {\n col = item;\n if (!col.field) {\n console.error(\"Invalid column definition\", item);\n }\n } else {\n console.error(\"Column definition must be a string or an object\");\n }\n cols.push(col);\n });\n }\n return cols;\n }\n\n // reflected attrs, see https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dom-attributes\n\n static get observedAttributes() {\n return [\"url\", \"page\", \"per-page\", \"debug\", \"filter\", \"sort\", \"default-sort\", \"dir\", \"reorder\"];\n }\n attributeChangedCallback(attributeName, oldValue, newValue) {\n this.log(\"attributeChangedCallback: \" + attributeName);\n\n // Update state but only trigger events if initialized\n switch (attributeName) {\n case \"url\":\n this.state.url = newValue;\n if (this.isInitialized && newValue) {\n this.loadData().then(() => {\n this.configureUi();\n });\n }\n break;\n case \"page\":\n this.state.page = Number(newValue);\n if (this.isInitialized) {\n this.loadData().finally(() => {\n this.fixPage();\n this.server ? this.renderBody() : this.paginate();\n });\n }\n break;\n case \"per-page\":\n this.state.perPage = Number(newValue);\n if (this.isInitialized) {\n this.selectPerPage.value = newValue;\n this.loadData().finally(() => {\n this.fixPage();\n this.server ? this.renderBody() : this.paginate();\n\n // Scroll and keep a sizable amount of data displayed\n if (this.sticky) {\n window.scroll({ top: DataGrid.elementOffset(this.selectPerPage).top - this.defaultHeight });\n }\n });\n }\n break;\n case \"debug\":\n this.state.debug = newValue === \"true\";\n break;\n case \"dir\":\n this.state.dir = newValue;\n this.root.querySelector(\".dg-wrapper\").dir = this.state.dir;\n break;\n case \"filter\":\n this.state.filter = newValue === \"true\";\n if (this.isInitialized) {\n this.toggleFilter();\n }\n break;\n case \"reorder\":\n this.state.reorder = newValue === \"true\";\n if (this.isInitialized) {\n this.toggleReorder();\n }\n break;\n case \"sort\":\n this.state.sort = newValue === \"true\";\n if (this.isInitialized) {\n this.toggleSort();\n }\n break;\n case \"default-sort\":\n this.state.defaultSort = newValue;\n if (this.isInitialized) {\n this.toggleSort();\n }\n break;\n }\n }\n get page() {\n return this.getAttribute(\"page\");\n }\n set page(val) {\n this.setAttribute(\"page\", val);\n }\n get perPage() {\n return this.getAttribute(\"per-page\");\n }\n set perPage(val) {\n this.setAttribute(\"per-page\", val);\n }\n get debug() {\n return this.getAttribute(\"debug\") === \"true\";\n }\n set debug(val) {\n this.setAttribute(\"debug\", val);\n }\n get dir() {\n return this.getAttribute(\"dir\");\n }\n set dir(val) {\n this.setAttribute(\"dir\", val);\n }\n get filter() {\n return this.getAttribute(\"filter\") === \"true\";\n }\n set filter(val) {\n this.setAttribute(\"filter\", val);\n }\n get reorder() {\n return this.getAttribute(\"reorder\") === \"true\";\n }\n set reorder(val) {\n this.setAttribute(\"reorder\", val);\n }\n get sort() {\n return this.getAttribute(\"sort\") === \"true\";\n }\n set sort(val) {\n this.setAttribute(\"sort\", val);\n }\n get defaultSort() {\n return this.getAttribute(\"default-sort\");\n }\n set defaultSort(val) {\n this.setAttribute(\"default-sort\", val);\n }\n get url() {\n return this.getAttribute(\"url\");\n }\n set url(val) {\n val ? this.setAttribute(\"url\", val) : this.removeAttribute(\"url\");\n }\n\n // Boolean\n\n get server() {\n return this.hasAttribute(\"server\");\n }\n set server(val) {\n val ? this.setAttribute(\"server\", \"\") : this.removeAttribute(\"server\");\n }\n get autosize() {\n return this.hasAttribute(\"autosize\");\n }\n set autosize(val) {\n val ? this.setAttribute(\"autosize\", \"\") : this.removeAttribute(\"autosize\");\n }\n get resizable() {\n return this.hasAttribute(\"resizable\");\n }\n set resizable(val) {\n val ? this.setAttribute(\"resizable\", \"\") : this.removeAttribute(\"resizable\");\n }\n get sticky() {\n return this.hasAttribute(\"sticky\");\n }\n set sticky(val) {\n val ? this.setAttribute(\"sticky\", \"\") : this.removeAttribute(\"sticky\");\n }\n get responsive() {\n return this.hasAttribute(\"responsive\");\n }\n set responsive(val) {\n val ? this.setAttribute(\"responsive\", \"\") : this.removeAttribute(\"responsive\");\n }\n get expand() {\n return this.hasAttribute(\"expand\");\n }\n set expand(val) {\n val ? this.setAttribute(\"expand\", \"\") : this.removeAttribute(\"expand\");\n }\n get selectable() {\n return this.hasAttribute(\"selectable\");\n }\n set selectable(val) {\n val ? this.setAttribute(\"selectable\", \"\") : this.removeAttribute(\"selectable\");\n }\n\n // Not reflected\n\n get perPageValues() {\n return this.state.perPageValues;\n }\n set perPageValues(val) {\n if (Array.isArray(val)) {\n this.state.perPageValues = val;\n if (this.selectPerPage) {\n while (this.selectPerPage.lastChild) {\n this.selectPerPage.removeChild(this.selectPerPage.lastChild);\n }\n this.state.perPageValues.forEach((v) => {\n DataGrid.addSelectOption(this.selectPerPage, v, v);\n });\n }\n }\n }\n get columns() {\n return this.state.columns;\n }\n set columns(val) {\n this.state.columns = DataGrid.convertColumns(DataGrid.convertArray(val));\n }\n get actions() {\n return this.state.actions;\n }\n set actions(val) {\n this.state.actions = DataGrid.convertArray(val);\n }\n connectedCallback() {\n this.log(\"connectedCallback\");\n\n this.btnFirst = this.root.querySelector(\".dg-btn-first\");\n this.btnPrev = this.root.querySelector(\".dg-btn-prev\");\n this.btnNext = this.root.querySelector(\".dg-btn-next\");\n this.btnLast = this.root.querySelector(\".dg-btn-last\");\n this.selectPerPage = this.root.querySelector(\".dg-select-per-page\");\n this.inputPage = this.root.querySelector(\".dg-input-page\");\n\n this.getFirst = this.getFirst.bind(this);\n this.getPrev = this.getPrev.bind(this);\n this.getNext = this.getNext.bind(this);\n this.getLast = this.getLast.bind(this);\n this.changePerPage = this.changePerPage.bind(this);\n this.gotoPage = this.gotoPage.bind(this);\n\n this.btnFirst.addEventListener(\"click\", this.getFirst);\n this.btnPrev.addEventListener(\"click\", this.getPrev);\n this.btnNext.addEventListener(\"click\", this.getNext);\n this.btnLast.addEventListener(\"click\", this.getLast);\n this.selectPerPage.addEventListener(\"change\", this.changePerPage, {\n passive: true,\n });\n this.inputPage.addEventListener(\"input\", this.gotoPage);\n\n // Touch support\n this.touchstart = this.touchstart.bind(this);\n this.touchmove = this.touchmove.bind(this);\n document.addEventListener(\"touchstart\", this.touchstart);\n document.addEventListener(\"touchmove\", this.touchmove);\n\n // Populate\n this.perPageValues = this.state.perPageValues;\n\n this.loadData().finally(() => {\n this.configureUi();\n\n this.toggleSort();\n this.toggleFilter();\n this.toggleReorder();\n\n this.root.classList.add(\"dg-initialized\");\n this.isInitialized = true;\n });\n }\n disconnectedCallback() {\n this.log(\"disconnectedCallback\");\n\n this.btnFirst.removeEventListener(\"click\", this.getFirst);\n this.btnPrev.removeEventListener(\"click\", this.getPrev);\n this.btnNext.removeEventListener(\"click\", this.getNext);\n this.btnLast.removeEventListener(\"click\", this.getLast);\n this.selectPerPage.removeEventListener(\"change\", this.changePerPage, {\n passive: true,\n });\n this.inputPage.removeEventListener(\"input\", this.gotoPage);\n\n // Touch support\n document.removeEventListener(\"touchstart\", this.touchstart);\n document.removeEventListener(\"touchmove\", this.touchmove);\n\n // Selectable\n if (this.selectAll) {\n this.selectAll.removeEventListener(\"change\", this.toggleSelectAll);\n }\n\n // Context menu\n if (this.headerRow) {\n this.headerRow.removeEventListener(\"contextmenu\", this.showContextMenu);\n }\n\n // TODO: what about the others listeners?\n }\n toggleSelectAll() {\n this.root.querySelectorAll(\"tbody .dg-selectable input\").forEach((cb) => {\n cb.checked = this.selectAll.checked;\n });\n }\n touchstart(e) {\n this.touch = e.touches[0];\n }\n touchmove(e) {\n if (!this.touch) {\n return;\n }\n const xDiff = this.touch.clientX - e.touches[0].clientX;\n const yDiff = this.touch.clientY - e.touches[0].clientY;\n\n if (Math.abs(xDiff) > Math.abs(yDiff)) {\n if (xDiff > 0) {\n this.getNext();\n } else {\n this.getPrev();\n }\n }\n this.touch = null;\n }\n\n /**\n * @param {Object} options\n */\n setOptions(options) {\n for (const [key, value] of Object.entries(options)) {\n if (key in this) {\n this[key] = value;\n this.state[key] = value;\n }\n }\n }\n getColProp(field, prop) {\n let v = null;\n this.state.columns.forEach((col) => {\n if (col.field == field) {\n v = col[prop];\n return;\n }\n });\n return v;\n }\n setColProp(field, prop, val) {\n this.state.columns.forEach((col) => {\n if (col.field == field) {\n col[prop] = val;\n }\n });\n }\n startIndex() {\n return this.selectable ? 2 : 1;\n }\n columnsLength(visibleOnly = false) {\n let len = 0;\n this.state.columns.forEach((col) => {\n if (visibleOnly && col.hidden) {\n return;\n }\n if (!col.attr) {\n len++;\n }\n });\n if (this.selectable) {\n len++;\n }\n if (this.state.actions.length) {\n len++;\n }\n return len;\n }\n computeDefaultHeight() {\n // Wait until height is fully computed\n requestAnimationFrame(() => {\n this.defaultHeight = this.root.querySelector(\"table\").offsetHeight;\n\n // If we have a fixed height, make sure we have overflowY set\n if (this.style.height) {\n this.style.height = this.defaultHeight + \"px\";\n this.style.overflowY = \"auto\";\n }\n // If our min height is too small, make sure we adjust the value\n if (this.style.minHeight && parseInt(this.style.minHeight) > this.defaultHeight) {\n this.style.minHeight = this.defaultHeight + \"px\";\n }\n });\n }\n configureUi() {\n this.createMenu();\n this.root.querySelector(\"table\").setAttribute(\"aria-rowcount\", this.data.length);\n this.root.querySelector(\"tfoot\").removeAttribute(\"hidden\");\n this.renderHeader();\n\n // Store row height for later usage\n if (!this.rowHeight) {\n this.rowHeight = this.root.querySelector(\"tbody tr\").offsetHeight;\n }\n }\n /**\n * This needs to be called each time the data changes or the perPage value changes\n */\n fixPage() {\n this.state.pages = this.totalPages();\n\n // Constrain values\n if (this.state.pages < this.state.page) {\n this.state.page = this.state.pages;\n }\n if (this.state.page < 1) {\n this.state.page = 1;\n }\n\n // Show current page in input\n this.inputPage.setAttribute(\"max\", this.state.pages);\n this.inputPage.value = this.state.page;\n this.inputPage.disabled = this.state.pages === 1;\n }\n toggleFilter() {\n const row = this.root.querySelector(\"thead tr.dg-head-filters\");\n if (this.state.filter) {\n row.removeAttribute(\"hidden\");\n } else {\n row.setAttribute(\"hidden\", true);\n }\n }\n toggleReorder() {\n this.root.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (this.state.reorder) {\n th.draggable = true;\n } else {\n th.removeAttribute(\"draggable\");\n }\n });\n }\n toggleSort() {\n this.log(\"toggle sort\");\n this.root.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (this.state.sort && !this.getColProp(th.getAttribute(\"field\"), \"noSort\")) {\n th.setAttribute(\"aria-sort\", \"none\");\n } else {\n th.removeAttribute(\"aria-sort\");\n }\n });\n }\n addRow(row) {\n this.log(\"Add row\");\n this.originalData.push(row);\n this.data = this.originalData.slice();\n this.fixPage();\n this.sortData();\n }\n removeRow(value = null, key = null) {\n if (key === null) {\n key = this.columns[0][\"field\"];\n }\n if (value === null) {\n value = this.originalData[this.originalData.length - 1][key];\n }\n this.log(\"Removing \" + key + \":\" + value);\n for (let i = 0; i < this.originalData.length; i++) {\n if (this.originalData[i][key] === value) {\n this.originalData.splice(i, 1);\n break;\n }\n }\n this.data = this.originalData.slice();\n this.fixPage();\n this.sortData();\n }\n getSelection(key = null) {\n let selectedData = [];\n this.data.forEach((item, i) => {\n const row = this.root.querySelector(\"tbody tr[aria-rowindex='\" + (i + 1) + \"']\");\n const checkbox = row.querySelector(\".dg-selectable input\");\n if (checkbox.checked) {\n if (key) {\n selectedData.push(item[key]);\n } else {\n selectedData.push(item);\n }\n }\n });\n return selectedData;\n }\n getData() {\n return this.originalData;\n }\n clearData() {\n // Clear the state but keep attribute so we can reload\n this.state.url = null;\n if (this.data.length === 0) {\n return;\n }\n this.data = this.originalData = [];\n this.fixPage();\n this.renderHeader();\n this.computeDefaultHeight();\n }\n /**\n * @returns {Promise}\n */\n loadData() {\n if (!this.server && this.originalData.length) {\n this.log(\"skip loadData\");\n return new Promise((resolve, reject) => {\n resolve();\n });\n }\n this.log(\"loadData\");\n return this.fetchData()\n .then((response) => {\n if (Array.isArray(response)) {\n this.data = response;\n } else {\n if (!response.data) {\n console.error(\"Invalid response, it should contain a data key with an array or be a plain array\", response);\n return;\n }\n\n // We may have a config object\n if (response.options) {\n this.setOptions(response.options);\n }\n if (response.meta) {\n this.meta = response.meta;\n }\n\n this.data = response.data;\n }\n this.originalData = this.data.slice();\n this.fixPage();\n\n // Make sure we have a proper set of columns\n if (this.state.columns.length === 0 && this.originalData.length) {\n this.state.columns = DataGrid.convertColumns(Object.keys(this.originalData[0]));\n }\n })\n .catch((err) => {\n this.url = null;\n this.log(err);\n });\n }\n getFirst() {\n this.page = 1;\n }\n getLast() {\n this.page = this.state.pages;\n }\n getPrev() {\n this.page = this.state.page - 1;\n }\n getNext() {\n this.page = this.state.page + 1;\n }\n /**\n * @returns {Promise}\n */\n refresh() {\n this.data = this.originalData = [];\n return this.loadData();\n }\n changePerPage() {\n this.perPage = this.selectPerPage.options[this.selectPerPage.selectedIndex].value;\n }\n gotoPage(event) {\n if (event.type === \"keypress\") {\n const key = event.keyCode || event.key;\n if (key === 13 || key === \"Enter\") {\n event.preventDefault();\n } else {\n return;\n }\n }\n this.page = this.inputPage.value;\n }\n getSort() {\n let col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"field\");\n }\n return this.defaultSort;\n }\n getSortDir() {\n let col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"aria-sort\") || \"\";\n }\n return \"\";\n }\n getFilters() {\n let filters = [];\n this.root.querySelectorAll(\"thead tr.dg-head-filters input\").forEach((input) => {\n filters[input.dataset.name] = input.value;\n });\n return filters;\n }\n clearFilters() {\n this.root.querySelectorAll(\"thead tr.dg-head-filters input\").forEach((input) => {\n input.value = \"\";\n });\n this.filterData();\n }\n filterData() {\n this.log(\"filter data\");\n\n if (this.server) {\n this.loadData().finally(() => {\n this.fixPage();\n this.renderBody();\n });\n } else {\n this.data = this.originalData.slice();\n\n this.root.querySelectorAll(\"thead tr.dg-head-filters input\").forEach((input) => {\n let value = input.value;\n if (value) {\n let name = input.dataset.name;\n this.data = this.data.filter((item) => {\n let str = item[name] + \"\";\n return str.toLowerCase().indexOf(value.toLowerCase()) !== -1;\n });\n }\n });\n\n this.fixPage();\n let col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (this.state.sort && col) {\n this.sortData(col);\n } else {\n this.renderBody();\n }\n }\n }\n /**\n * Data will be sorted then rendered using renderBody\n * @param {HTMLElement} col The column that was clicked or null to use current sort\n */\n sortData(col = null) {\n this.log(\"sort data\");\n\n // Early exit\n if (col && this.getColProp(col.getAttribute(\"field\"), \"noSort\")) {\n return;\n }\n\n // We clicked on a column, update sort state\n if (col !== null) {\n // Remove active sort if any\n this.root.querySelectorAll(\"thead tr:first-child th\").forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (th !== col) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n });\n\n // Set three-state col\n if (!col.hasAttribute(\"aria-sort\") || col.getAttribute(\"aria-sort\") === \"none\") {\n col.setAttribute(\"aria-sort\", \"ascending\");\n } else if (col.getAttribute(\"aria-sort\") === \"ascending\") {\n col.setAttribute(\"aria-sort\", \"descending\");\n } else if (col.getAttribute(\"aria-sort\") === \"descending\") {\n col.setAttribute(\"aria-sort\", \"none\");\n }\n } else {\n // Or fetch current sort\n col = this.root.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n }\n\n if (this.server) {\n // Reload data with updated sort\n this.loadData().finally(() => {\n this.renderBody();\n });\n } else {\n const sort = col ? col.getAttribute(\"aria-sort\") : \"none\";\n if (sort === \"none\") {\n let stack = [];\n\n // Restore order while keeping filters\n this.originalData.some((itemA) => {\n this.data.some((itemB) => {\n if (JSON.stringify(itemA) === JSON.stringify(itemB)) {\n stack.push(itemB);\n return true;\n }\n return false;\n });\n return stack.length === this.data.length;\n });\n\n this.data = stack;\n } else {\n const field = col.getAttribute(\"field\");\n this.data.sort((a, b) => {\n if (!isNaN(a[field]) && !isNaN(b[field])) {\n return sort === \"ascending\" ? a[field] - b[field] : b[field] - a[field];\n }\n const valA = sort === \"ascending\" ? a[field].toUpperCase() : b[field].toUpperCase();\n const valB = sort === \"ascending\" ? b[field].toUpperCase() : a[field].toUpperCase();\n\n switch (true) {\n case valA > valB:\n return 1;\n case valA < valB:\n return -1;\n case valA === valB:\n return 0;\n }\n });\n this.renderBody();\n }\n }\n }\n fetchData() {\n if (!this.url) {\n return new Promise((resolve, reject) => reject(\"No url set\"));\n }\n let url = new URL(this.url, window.location.href);\n let params = {\n r: Math.ceil(Math.random() * 9999999),\n };\n if (this.server) {\n // 0 based\n params[\"start\"] = this.state.page - 1;\n params[\"length\"] = this.state.perPage;\n params[\"search\"] = this.getFilters();\n params[\"sort\"] = this.getSort() || \"\";\n params[\"sortDir\"] = this.getSortDir();\n }\n\n Object.keys(params).forEach((key) => {\n if (Array.isArray(params[key])) {\n Object.keys(params[key]).forEach((k) => url.searchParams.append(key + \"[\" + k + \"]\", params[key][k]));\n } else {\n url.searchParams.append(key, params[key]);\n }\n });\n\n return fetch(url).then((response) => {\n return response.json();\n });\n }\n renderHeader() {\n this.log(\"render header\");\n let tr;\n let sortedColumn;\n let thead = this.root.querySelector(\"thead\");\n\n this.createColumnHeaders(thead);\n if (this.state.defaultSort) {\n // We can have a default sort even with sort disabled\n sortedColumn = this.root.querySelector(\"thead tr.dg-head-columns th[field='\" + this.state.defaultSort + \"']\");\n }\n\n // Create column filters\n this.createColumnFilters(thead);\n\n // Configure table\n this.root.querySelector(\"table\").setAttribute(\"aria-colcount\", this.columnsLength(true).toString());\n this.root.querySelector(\"tfoot\").querySelector(\"td\").setAttribute(\"colspan\", this.columnsLength(true).toString());\n\n if (sortedColumn) {\n this.sortData(sortedColumn);\n } else {\n this.renderBody();\n }\n\n this.root.querySelector(\"tfoot\").style.display = \"\";\n if (this.resizable) {\n this.renderResizer();\n }\n }\n createColumnHeaders(thead) {\n const colMaxWidth = parseInt((thead.offsetWidth / this.columnsLength(true)) * 2);\n\n let idx = 0;\n let tr;\n\n // Create row\n tr = document.createElement(\"tr\");\n this.headerRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", 1);\n tr.setAttribute(\"class\", \"dg-head-columns\");\n\n // Selectable\n if (this.selectable) {\n let selectableTh = document.createElement(\"th\");\n selectableTh.setAttribute(\"role\", \"columnheader button\");\n selectableTh.setAttribute(\"aria-colindex\", 1);\n selectableTh.classList.add(\"dg-selectable\");\n selectableTh.tabIndex = 0;\n\n this.selectAll = document.createElement(\"input\");\n this.selectAll.type = \"checkbox\";\n this.selectAll.classList.add(\"dg-select-all\");\n\n this.toggleSelectAll = this.toggleSelectAll.bind(this);\n this.selectAll.addEventListener(\"change\", this.toggleSelectAll);\n\n let label = document.createElement(\"label\");\n label.appendChild(this.selectAll);\n\n selectableTh.appendChild(label);\n selectableTh.setAttribute(\"width\", 40);\n tr.appendChild(selectableTh);\n }\n\n // Create columns\n idx = 0;\n let totalWidth = 0;\n this.state.columns.forEach((column, i) => {\n if (column.attr) {\n return;\n }\n let th = document.createElement(\"th\");\n th.setAttribute(\"role\", \"columnheader button\");\n th.setAttribute(\"aria-colindex\", idx + this.startIndex());\n th.setAttribute(\"id\", DataGrid.randstr(\"dg-col-\"));\n if (this.state.sort) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n th.setAttribute(\"field\", column.field);\n th.dataset.minWidth = DataGrid.getTextWidth(column.title, th) + 40;\n DataGrid.applyColumnDefinition(th, column);\n th.tabIndex = 0;\n th.textContent = column.title;\n\n if (column.hidden) {\n th.setAttribute(\"hidden\", true);\n }\n\n // Autosize small based on first/last row ?\n if (this.autosize && !th.getAttribute(\"width\")) {\n totalWidth += this.autosizeColumn(th, column, th.dataset.minWidth, colMaxWidth);\n }\n\n // Reorder columns with drag/drop\n if (this.state.reorder) {\n this.makeHeaderDraggable(th);\n }\n tr.appendChild(th);\n idx++;\n });\n\n // There is too much width, and we want to avoid fixed layout to split remaining amount\n if (totalWidth < thead.offsetWidth) {\n let lastTh = tr.lastChild;\n if (lastTh) {\n lastTh.removeAttribute(\"width\");\n }\n }\n\n // Actions\n if (this.state.actions.length) {\n let actionsTh = document.createElement(\"th\");\n actionsTh.setAttribute(\"role\", \"columnheader button\");\n actionsTh.setAttribute(\"aria-colindex\", this.columnsLength(true));\n actionsTh.classList.add(\"dg-actions\");\n actionsTh.tabIndex = 0;\n tr.appendChild(actionsTh);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-columns\"));\n\n // Context menu\n this.showContextMenu = this.showContextMenu.bind(this);\n tr.addEventListener(\"contextmenu\", this.showContextMenu);\n\n // Sort col on click\n tr.querySelectorAll(\"[aria-sort]\").forEach((sortableRow) => {\n sortableRow.addEventListener(\"click\", () => this.sortData(sortableRow));\n });\n }\n createColumnFilters(thead) {\n let idx = 0;\n let tr;\n\n // Create row for filters\n tr = document.createElement(\"tr\");\n this.filterRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", 2);\n tr.setAttribute(\"class\", \"dg-head-filters\");\n if (!this.state.filter) {\n tr.setAttribute(\"hidden\", true);\n }\n\n // Selectable\n if (this.selectable) {\n let th = document.createElement(\"th\");\n th.setAttribute(\"role\", \"columnheader button\");\n th.setAttribute(\"aria-colindex\", 1);\n th.classList.add(\"dg-selectable\");\n th.tabIndex = 0;\n tr.appendChild(th);\n }\n\n this.state.columns.forEach((column, i) => {\n if (column.attr) {\n return;\n }\n let relatedTh = thead.querySelector(\"tr.dg-head-columns th[aria-colindex='\" + (idx + this.startIndex()) + \"']\");\n let th = document.createElement(\"th\");\n th.setAttribute(\"aria-colindex\", idx + this.startIndex());\n\n let input = document.createElement(\"input\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n // Allows binding filter to this column\n input.dataset.name = column.field;\n input.id = DataGrid.randstr(\"dg-filter-\");\n // Don't use aria-label as it triggers autocomplete\n input.setAttribute(\"aria-labelledby\", relatedTh.getAttribute(\"id\"));\n if (!this.state.filter) {\n th.tabIndex = 0;\n } else {\n input.tabIndex = 0;\n }\n\n if (column.hidden) {\n th.setAttribute(\"hidden\", true);\n }\n\n th.appendChild(input);\n tr.appendChild(th);\n idx++;\n });\n\n // Actions\n if (this.state.actions.length) {\n let actionsTh = document.createElement(\"th\");\n actionsTh.setAttribute(\"role\", \"columnheader button\");\n actionsTh.setAttribute(\"aria-colindex\", this.columnsLength(true));\n actionsTh.classList.add(\"dg-actions\");\n actionsTh.tabIndex = 0;\n tr.appendChild(actionsTh);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-filters\"));\n\n // Filter content on enter\n tr.querySelectorAll(\"input\").forEach((input) => {\n input.addEventListener(\"keypress\", (e) => {\n const key = e.keyCode || e.key;\n if (key === 13 || key === \"Enter\") {\n this.filterData.call(this);\n }\n });\n });\n }\n autosizeColumn(th, column, min, max) {\n let v = this.data[0][column.field].toString();\n let v2 = this.data[this.data.length - 1][column.field].toString();\n if (v2.length > v.length) {\n v = v2;\n }\n let width = 0;\n if (v.length <= 6) {\n width = min;\n } else if (v.length > 50) {\n width = max;\n } else {\n width = DataGrid.getTextWidth(v, th);\n }\n if (width < min) {\n width = min;\n }\n th.setAttribute(\"width\", width);\n return parseInt(width);\n }\n showContextMenu(e) {\n e.preventDefault();\n\n const target = DataGrid.getParentNode(e.target, \"THEAD\");\n const menu = this.root.querySelector(\".dg-menu\");\n const rect = target.getBoundingClientRect();\n let x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n menu.style.top = `${y}px`;\n menu.style.left = `${x}px`;\n\n menu.removeAttribute(\"hidden\");\n if (x + 150 > rect.width) {\n x -= menu.offsetWidth;\n menu.style.left = `${x}px`;\n }\n\n const documentClickHandler = (e) => {\n if (!menu.contains(e.target)) {\n menu.setAttribute(\"hidden\", true);\n document.removeEventListener(\"click\", documentClickHandler);\n }\n };\n document.addEventListener(\"click\", documentClickHandler);\n }\n createMenu() {\n const menu = this.root.querySelector(\".dg-menu\");\n this.state.columns.forEach((col) => {\n if (col.attr) {\n return;\n }\n const field = col.field;\n const li = document.createElement(\"li\");\n const label = document.createElement(\"label\");\n const checkbox = document.createElement(\"input\");\n checkbox.setAttribute(\"type\", \"checkbox\");\n if (!col.hidden) {\n checkbox.checked = true;\n }\n checkbox.addEventListener(\"change\", (e) => {\n e.target.checked ? this.showColumn(field, e.target) : this.hideColumn(field, e.target);\n });\n\n const text = document.createTextNode(col.title);\n\n label.appendChild(checkbox);\n label.appendChild(text);\n\n li.appendChild(label);\n menu.appendChild(li);\n });\n }\n showColumn(field, checkbox = null) {\n if (checkbox) {\n checkbox.checked = true;\n }\n this.setColProp(field, \"hidden\", false);\n this.renderHeader();\n }\n hideColumn(field, checkbox = null) {\n const numHiddenCols = this.state.columns.filter((th) => {\n return th.hidden === true;\n }).length;\n\n if (numHiddenCols === this.columnsLength() - 1) {\n // Restore checkbox value\n if (checkbox) {\n checkbox.checked = true;\n }\n return;\n }\n this.setColProp(field, \"hidden\", true);\n this.renderHeader();\n }\n makeHeaderDraggable(th) {\n th.draggable = true;\n th.addEventListener(\"dragstart\", (e) => {\n if (this.isResizing && e.preventDefault) {\n e.preventDefault();\n return;\n }\n this.log(\"reorder col\");\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", e.target.getAttribute(\"aria-colindex\"));\n });\n th.addEventListener(\"dragover\", (e) => {\n if (e.preventDefault) {\n e.preventDefault();\n }\n e.dataTransfer.dropEffect = \"move\";\n return false;\n });\n th.addEventListener(\"drop\", (e) => {\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n const target = DataGrid.getParentNode(e.target, \"TH\");\n const index = e.dataTransfer.getData(\"text/plain\");\n const targetIndex = target.getAttribute(\"aria-colindex\");\n\n if (index === targetIndex) {\n this.log(\"reordered col stayed the same\");\n return;\n }\n this.log(\"reordered col from \" + index + \" to \" + targetIndex);\n\n const tmp = this.state.columns[index - 1];\n this.state.columns[index - 1] = this.columns[targetIndex - 1];\n this.state.columns[targetIndex - 1] = tmp;\n\n const swapNodes = (selector, el1) => {\n const rowIndex = el1.parentNode.getAttribute(\"aria-rowindex\");\n const el2 = this.root.querySelector(selector + \" tr[aria-rowindex='\" + rowIndex + \"'] [aria-colindex='\" + targetIndex + \"']\");\n el1.setAttribute(\"aria-colindex\", targetIndex);\n el2.setAttribute(\"aria-colindex\", index);\n const newNode = document.createElement(\"th\");\n el1.parentNode.insertBefore(newNode, el1);\n el2.parentNode.replaceChild(el1, el2);\n newNode.parentNode.replaceChild(el2, newNode);\n };\n\n // Swap all rows in header and body\n this.root.querySelectorAll(\"thead th[aria-colindex='\" + index + \"']\").forEach((el1) => {\n swapNodes(\"thead\", el1);\n });\n this.root.querySelectorAll('tbody td[aria-colindex=\"' + index + '\"]').forEach((el1) => {\n swapNodes(\"tbody\", el1);\n });\n\n return false;\n });\n }\n renderResizer() {\n const table = this.root.querySelector(\"table\");\n const cols = this.root.querySelectorAll(\"thead tr.dg-head-columns th\");\n\n cols.forEach((col) => {\n if (col.classList.contains(\"dg-selectable\") || col.classList.contains(\"dg-actions\")) {\n return;\n }\n // Create a resizer element\n const resizer = document.createElement(\"div\");\n resizer.classList.add(\"dg-resizer\");\n resizer.ariaLabel = labels.resizeColumn;\n\n // Add a resizer element to the column\n col.appendChild(resizer);\n\n // Handle resizing\n let startX = 0;\n let startW = 0;\n let remainingSpace = 0;\n let max = 0;\n\n const mouseMoveHandler = (e) => {\n if (e.clientX > max) {\n return;\n }\n const newWidth = startW + (e.clientX - startX);\n if (col.dataset.minWidth && newWidth > col.dataset.minWidth) {\n col.width = newWidth;\n }\n };\n\n // When user releases the mouse, remove the existing event listeners\n const mouseUpHandler = () => {\n this.log(\"resized column\");\n\n this.isResizing = false;\n resizer.classList.remove(\"dg-resizer-active\");\n if (this.state.reorder) {\n col.draggable = true;\n }\n col.style.overflow = \"hidden\";\n\n document.removeEventListener(\"mousemove\", mouseMoveHandler);\n document.removeEventListener(\"mouseup\", mouseUpHandler);\n };\n\n // Otherwise it could sort the col\n resizer.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n });\n\n resizer.addEventListener(\"mousedown\", (e) => {\n e.stopPropagation();\n this.isResizing = true;\n\n const currentCols = this.root.querySelectorAll(\".dg-head-columns th\");\n const visibleCols = Array.from(currentCols).filter((col) => {\n return !col.hasAttribute(\"hidden\");\n });\n const columns = Array.from(visibleCols);\n const columnIndex = columns.findIndex((column) => column == e.target.parentNode);\n this.log(\"resize column\");\n\n resizer.classList.add(\"dg-resizer-active\");\n\n // Make sure we don't drag it\n if (col.hasAttribute(\"draggable\")) {\n col.removeAttribute(\"draggable\");\n }\n\n // Allow overflow when resizing\n col.style.overflow = \"visible\";\n\n // Show full column height (-1 to avoid scrollbar)\n resizer.style.height = table.offsetHeight - 1 + \"px\";\n\n // Register initial data\n startX = e.clientX;\n startW = col.offsetWidth;\n\n remainingSpace = (visibleCols.length - columnIndex) * 30;\n max = DataGrid.elementOffset(this).left + this.offsetWidth - remainingSpace;\n\n // Remove width from next columns to allow auto layout\n col.setAttribute(\"width\", startW);\n for (let j = 0; j < visibleCols.length; j++) {\n if (j > columnIndex) {\n cols[j].removeAttribute(\"width\");\n }\n }\n\n // Attach handlers\n document.addEventListener(\"mousemove\", mouseMoveHandler);\n document.addEventListener(\"mouseup\", mouseUpHandler);\n });\n });\n }\n /**\n * Render the data as rows in tbody\n * It will call paginate() at the end\n */\n renderBody() {\n this.log(\"render body\");\n let tr;\n let td;\n let idx;\n let tbody = document.createElement(\"tbody\");\n this.data.forEach((item, i) => {\n tr = document.createElement(\"tr\");\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"hidden\", true);\n tr.setAttribute(\"aria-rowindex\", i + 1);\n tr.tabIndex = 0;\n\n // Selectable\n if (this.selectable) {\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell button\");\n td.setAttribute(\"aria-colindex\", 1);\n td.classList.add(\"dg-selectable\");\n\n let selectOne = document.createElement(\"input\");\n selectOne.type = \"checkbox\";\n let label = document.createElement(\"label\");\n label.appendChild(selectOne);\n td.appendChild(label);\n\n tr.appendChild(td);\n }\n\n // Expandable\n if (this.expand) {\n tr.addEventListener(\"click\", function (ev) {\n this.classList.toggle(\"dg-expanded\");\n });\n }\n\n idx = 0;\n this.state.columns.forEach((column, j) => {\n if (!column) {\n console.log(this.state.columns);\n }\n // It should be applied as an attr of the row\n if (column.attr) {\n tr.setAttribute(column.attr, item[column.field]);\n return;\n }\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell\");\n td.setAttribute(\"aria-colindex\", idx + this.startIndex());\n DataGrid.applyColumnDefinition(td, column);\n td.setAttribute(\"data-name\", column.title);\n td.tabIndex = -1;\n\n // Inline editing\n if (column.editable) {\n let input = document.createElement(\"input\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n input.tabIndex = 0;\n input.classList.add(\"dg-editable\");\n input.name = this.getAttribute(\"id\").replace(\"-\", \"_\") + \"[\" + (i + 1) + \"]\" + \"[\" + column.field + \"]\";\n input.value = item[column.field];\n input.dataset.field = column.field;\n\n input.addEventListener(\"click\", (ev) => ev.stopPropagation());\n input.addEventListener(\"keypress\", (ev) => {\n if (ev.type === \"keypress\") {\n const key = ev.keyCode || ev.key;\n if (key === 13 || key === \"Enter\") {\n input.blur();\n }\n }\n });\n input.addEventListener(\"blur\", (ev) => {\n // Only fire on update\n if (input.value == item[input.dataset.field]) {\n return;\n }\n // Update underlying data\n item[input.dataset.field] = input.value;\n // Notify\n const event = new CustomEvent(\"edit\", {\n bubbles: true,\n detail: {\n data: item,\n value: input.value,\n },\n });\n this.dispatchEvent(event);\n });\n td.appendChild(input);\n } else {\n td.textContent = item[column.field];\n }\n if (column.hidden) {\n td.setAttribute(\"hidden\", true);\n }\n tr.appendChild(td);\n idx++;\n });\n\n // Actions\n if (this.state.actions.length) {\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell\");\n td.setAttribute(\"aria-colindex\", this.columnsLength(true));\n td.classList.add(\"dg-actions\");\n td.tabIndex = 0;\n\n this.state.actions.forEach((action) => {\n let button = document.createElement(\"button\");\n if (action.html) {\n button.innerHTML = action.html;\n } else {\n button.innerText = action.title ?? action.name;\n }\n if (action.url) {\n button.type = \"submit\";\n button.formAction = DataGrid.interpolate(action.url, item);\n }\n if (action.class) {\n button.classList.add(action.class);\n }\n const actionHandler = (ev) => {\n ev.stopPropagation();\n if (action.confirm) {\n let c = confirm(labels.areYouSure);\n if (!c) {\n ev.preventDefault();\n return;\n }\n }\n const event = new CustomEvent(\"action\", {\n bubbles: true,\n detail: {\n data: item,\n action: action.name,\n },\n });\n this.dispatchEvent(event);\n };\n button.addEventListener(\"click\", actionHandler);\n td.appendChild(button);\n\n // Row action\n if (action.default) {\n tr.classList.add(\"dg-actionable\");\n tr.addEventListener(\"click\", actionHandler);\n }\n });\n\n tr.appendChild(td);\n }\n\n tbody.appendChild(tr);\n });\n\n tbody.setAttribute(\"role\", \"rowgroup\");\n\n this.root.querySelector(\"table\").replaceChild(tbody, this.root.querySelector(\"tbody\"));\n\n // Let's add a fake row to adjust any missing height, simply multiply by rowHeight the number of missing lines\n tr = document.createElement(\"tr\");\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"hidden\", true);\n tr.classList.add(\"dg-fake-row\");\n tr.tabIndex = 0;\n tbody.appendChild(tr);\n\n this.paginate();\n }\n paginate() {\n this.log(\"paginate\");\n\n const total = this.totalRecords();\n const pages = this.totalPages();\n\n let index;\n let high = this.state.page * this.state.perPage;\n let low = high - this.state.perPage + 1;\n let tbody = this.root.querySelector(\"tbody\");\n let tfoot = this.root.querySelector(\"tfoot\");\n\n if (high > total) {\n high = total;\n }\n if (!total) {\n low = 0;\n }\n\n tbody.querySelectorAll(\"tr\").forEach((tr) => {\n if (this.server) {\n tr.removeAttribute(\"hidden\");\n return;\n }\n index = Number(tr.getAttribute(\"aria-rowindex\"));\n if (index > high || index < low) {\n tr.setAttribute(\"hidden\", true);\n } else {\n tr.removeAttribute(\"hidden\");\n }\n });\n\n // Store default height and update styles if needed\n if (this.defaultHeight == 0) {\n this.computeDefaultHeight();\n }\n\n // On last page, adjust height if using fixed height\n let fakeRow = this.querySelector(\".dg-fake-row\");\n if (this.style.height) {\n if (this.state.page == pages) {\n // Check if we are below set height\n if (parseInt(this.style.height) > this.querySelector(\"tbody\").offsetHeight) {\n const missing = this.state.perPage - (total - (pages - 1) * this.state.perPage);\n fakeRow.setAttribute(\"height\", missing * this.rowHeight);\n } else {\n fakeRow.removeAttribute(\"height\");\n }\n } else {\n fakeRow.removeAttribute(\"height\");\n }\n }\n\n // Enable/disable buttons\n if (this.btnFirst) {\n this.btnFirst.disabled = this.state.page <= 1;\n this.btnPrev.disabled = this.state.page <= 1;\n this.btnNext.disabled = this.state.page >= this.state.pages;\n this.btnLast.disabled = this.state.page >= this.state.pages;\n }\n tfoot.querySelector(\".dg-low\").textContent = low.toString();\n tfoot.querySelector(\".dg-high\").textContent = high.toString();\n tfoot.querySelector(\".dg-total\").textContent = this.totalRecords();\n }\n totalPages() {\n return Math.ceil(this.totalRecords() / this.state.perPage);\n }\n totalRecords() {\n if (this.server) {\n return this.meta.filtered;\n }\n return this.data.length.toString();\n }\n /**\n * @param {string|Error} message\n */\n log(message) {\n if (this.debug) {\n console.log(\"[\" + this.getAttribute(\"id\") + \"] \" + message);\n }\n }\n}\n\ncustomElements.define(\"data-grid\", DataGrid);\n\nexport default DataGrid;\n"],
+ "mappings": "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",
"names": []
}
diff --git a/demo-server.html b/demo-server.html
index 1dd0981..d03552a 100644
--- a/demo-server.html
+++ b/demo-server.html
@@ -22,8 +22,35 @@
+
@@ -44,12 +71,25 @@ Server usage
Server parameters are sent as query string and are start
, length
and search
.
To enable server mode, use server=true
-
+
+
+
-
+
+
+
+
+ Hello, world! This is a toast message.
+
+
+