primo commit
This commit is contained in:
		
							
								
								
									
										183
									
								
								media/system/js/table-columns.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								media/system/js/table-columns.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,183 @@ | ||||
| /** | ||||
|  * TableColumns class for toggle visibility of <table> columns. | ||||
|  */ | ||||
| class TableColumns { | ||||
|   constructor($table, tableName) { | ||||
|     this.$table = $table; | ||||
|     this.tableName = tableName; | ||||
|     this.storageKey = `joomla-tablecolumns-${this.tableName}`; | ||||
|     this.$headers = [].slice.call($table.querySelector('thead tr').children); | ||||
|     this.$rows = $table.querySelectorAll('tbody tr'); | ||||
|     this.listOfHidden = []; | ||||
|  | ||||
|     // Load previous state | ||||
|     this.loadState(); | ||||
|  | ||||
|     // Find protected columns | ||||
|     this.protectedCols = [0]; | ||||
|     if (this.$rows[0]) { | ||||
|       [].slice.call(this.$rows[0].children).forEach(($el, index) => { | ||||
|         if ($el.nodeName === 'TH') { | ||||
|           this.protectedCols.push(index); | ||||
|  | ||||
|           // Make sure it's not in the list of hidden | ||||
|           const ih = this.listOfHidden.indexOf(index); | ||||
|           if (ih !== -1) { | ||||
|             this.listOfHidden.splice(ih, 1); | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     // Set up toggle menu | ||||
|     this.createControls(); | ||||
|  | ||||
|     // Restore state | ||||
|     this.listOfHidden.forEach(index => { | ||||
|       this.toggleColumn(index, true); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Create a controls to select visible columns | ||||
|    */ | ||||
|   createControls() { | ||||
|     const $divouter = document.createElement('div'); | ||||
|     $divouter.setAttribute('class', 'dropdown float-end pb-2'); | ||||
|     const $divinner = document.createElement('div'); | ||||
|     $divinner.setAttribute('class', 'dropdown-menu dropdown-menu-end'); | ||||
|     $divinner.setAttribute('data-bs-popper', 'static'); | ||||
|  | ||||
|     // Create a toggle button | ||||
|     const $button = document.createElement('button'); | ||||
|     $button.type = 'button'; | ||||
|     $button.textContent = Joomla.Text._('JGLOBAL_COLUMNS'); | ||||
|     $button.classList.add('btn', 'btn-primary', 'btn-sm', 'dropdown-toggle'); | ||||
|     $button.setAttribute('data-bs-toggle', 'dropdown'); | ||||
|     $button.setAttribute('data-bs-auto-close', 'false'); | ||||
|     $button.setAttribute('aria-haspopup', 'true'); | ||||
|     $button.setAttribute('aria-expanded', 'false'); | ||||
|     const $ul = document.createElement('ul'); | ||||
|     $ul.setAttribute('class', 'list-unstyled p-2 text-nowrap mb-0'); | ||||
|     $ul.setAttribute('id', 'columnList'); | ||||
|  | ||||
|     // Collect a list of headers for dropdown | ||||
|     this.$headers.forEach(($el, index) => { | ||||
|       // Skip the first column, unless it's a th, as we don't want to display the checkboxes | ||||
|       if (index === 0 && $el.nodeName !== 'TH') return; | ||||
|       const $li = document.createElement('li'); | ||||
|       const $label = document.createElement('label'); | ||||
|       const $input = document.createElement('input'); | ||||
|       $input.classList.add('form-check-input', 'me-1'); | ||||
|       $input.type = 'checkbox'; | ||||
|       $input.name = 'table[column][]'; | ||||
|       $input.checked = this.listOfHidden.indexOf(index) === -1; | ||||
|       $input.disabled = this.protectedCols.indexOf(index) !== -1; | ||||
|       $input.value = index; | ||||
|  | ||||
|       // Find the header name | ||||
|       let $titleEl = $el.querySelector('span'); | ||||
|       let title = $titleEl ? $titleEl.textContent.trim() : ''; | ||||
|       if (!title) { | ||||
|         $titleEl = $el.querySelector('span.visually-hidden') || $el; | ||||
|         title = $titleEl.textContent.trim(); | ||||
|       } | ||||
|       if (title.includes(':')) { | ||||
|         title = title.split(':', 2)[1].trim(); | ||||
|       } | ||||
|       $label.textContent = title; | ||||
|       $label.insertAdjacentElement('afterbegin', $input); | ||||
|       $li.appendChild($label); | ||||
|       $ul.appendChild($li); | ||||
|     }); | ||||
|     this.$table.insertAdjacentElement('beforebegin', $divouter); | ||||
|     $divouter.appendChild($button); | ||||
|     $divouter.appendChild($divinner); | ||||
|     $divinner.appendChild($ul); | ||||
|  | ||||
|     // Listen to checkboxes change | ||||
|     $ul.addEventListener('change', event => { | ||||
|       this.toggleColumn(parseInt(event.target.value, 10)); | ||||
|       this.saveState(); | ||||
|     }); | ||||
|  | ||||
|     // Remove "media query" classes, which may prevent toggling from working. | ||||
|     this.$headers.forEach($el => { | ||||
|       $el.classList.remove('d-none', 'd-xs-table-cell', 'd-sm-table-cell', 'd-md-table-cell', 'd-lg-table-cell', 'd-xl-table-cell', 'd-xxl-table-cell'); | ||||
|     }); | ||||
|     this.$rows.forEach($row => { | ||||
|       [].slice.call($row.children).forEach($el => { | ||||
|         $el.classList.remove('d-none', 'd-xs-table-cell', 'd-sm-table-cell', 'd-md-table-cell', 'd-lg-table-cell', 'd-xl-table-cell', 'd-xxl-table-cell'); | ||||
|       }); | ||||
|     }); | ||||
|     this.$button = $button; | ||||
|     this.$menu = $ul; | ||||
|     this.updateCounter(); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Update button text | ||||
|    */ | ||||
|   updateCounter() { | ||||
|     // Don't count the checkboxes column in the total | ||||
|     const total = this.$headers.length - 1; | ||||
|     const visible = total - this.listOfHidden.length; | ||||
|     this.$button.textContent = `${visible}/${total} ${Joomla.Text._('JGLOBAL_COLUMNS')}`; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Toggle column visibility | ||||
|    * | ||||
|    * @param {Number} index  The column index | ||||
|    * @param {Boolean} force To force hide | ||||
|    */ | ||||
|   toggleColumn(index, force) { | ||||
|     // Skip incorrect index | ||||
|     if (!this.$headers[index]) return; | ||||
|  | ||||
|     // Skip the protected columns | ||||
|     if (this.protectedCols.indexOf(index) !== -1) return; | ||||
|     const i = this.listOfHidden.indexOf(index); | ||||
|     if (i === -1) { | ||||
|       this.listOfHidden.push(index); | ||||
|     } else if (force !== true) { | ||||
|       this.listOfHidden.splice(i, 1); | ||||
|     } | ||||
|     this.$headers[index].classList.toggle('d-none', force); | ||||
|     this.$rows.forEach($col => { | ||||
|       $col.children[index].classList.toggle('d-none', force); | ||||
|     }); | ||||
|     this.updateCounter(); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Save state, list of hidden columns | ||||
|    */ | ||||
|   saveState() { | ||||
|     window.localStorage.setItem(this.storageKey, this.listOfHidden.join(',')); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Load state, list of hidden columns | ||||
|    */ | ||||
|   loadState() { | ||||
|     const stored = window.localStorage.getItem(this.storageKey); | ||||
|     if (stored) { | ||||
|       this.listOfHidden = stored.split(',').map(val => parseInt(val, 10)); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| if (window.innerWidth > 992) { | ||||
|   // Look for dataset name else page-title | ||||
|   [...document.querySelectorAll('table:not(.columns-order-ignore)')].forEach($table => { | ||||
|     const tableName = $table.dataset.name ? $table.dataset.name : document.querySelector('.page-title').textContent.trim().replace(/[^a-z0-9]/gi, '-').toLowerCase(); | ||||
|  | ||||
|     // Skip unnamed table | ||||
|     if (!tableName) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     /* eslint-disable-next-line no-new */ | ||||
|     new TableColumns($table, tableName); | ||||
|   }); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user