1window.tablelayout = window.tablelayout || {}; 2 3jQuery(window).on('load', function () { 4 'use strict'; 5 6 /** 7 * 8 * @param {jQuery} $secedit_form jQuery object of the section edit form associated with the table 9 * 10 * @return {void} 11 */ 12 function addPrintButtonToTable($secedit_form) { 13 var range = $secedit_form.find('input[name="range"]').val(); 14 var target = $secedit_form.closest('form').attr('action'); 15 var layout = $secedit_form.find('input[name="tablelayout"]').val(); 16 var params = [ 17 'do=tablelayout_printtable', 18 'range=' + encodeURIComponent(range), 19 'id=' + encodeURIComponent(window.JSINFO.id) 20 ]; 21 22 if (typeof layout !== 'undefined' && layout.length > 0) { 23 var json = JSON.parse(layout); 24 var colwidth = json.colwidth; 25 params.push('colwidth=' + colwidth); 26 } 27 28 var href = target + '?' + params.join('&'); 29 var $link = jQuery('<a>' + window.LANG.plugins.tablelayout.print + '</a>').attr({ 30 'href': href, 31 'target': '_blank' 32 }).addClass('button print'); 33 $secedit_form.closest('div.secedit').append($link); 34 } 35 36 /** 37 * Add a row for the search fields and filter buttons below the table header 38 * 39 * @param {JQuery} $table jQuery-object of the table 40 * @param {int} numHeaderRows the number of rows in the header of the table 41 * @param {int} columnCount the number of columns in the table 42 * @return {JQuery} the searchSortRow object, that has been added to the table 43 */ 44 function addSearchSortRow($table, numHeaderRows, columnCount) { 45 var $searchSortRow = jQuery('<tr class="searchSortRow">' + '<th><div></div></th>'.repeat(columnCount) + '</tr>'); 46 var $lastHeaderRow; 47 if ($table.hasClass('tablelayout_body')) { 48 $lastHeaderRow = $table.closest('.table').find('table.tablelayout_head tr').last(); 49 $lastHeaderRow.after($searchSortRow); 50 } else if(numHeaderRows === 0) { 51 $table.find('tr').first().before($searchSortRow); 52 } else { 53 $lastHeaderRow = $table.find('tr').slice(numHeaderRows - 1).first(); 54 $lastHeaderRow.after($searchSortRow); 55 } 56 return $searchSortRow; 57 } 58 59 /** 60 * 61 * @param {JQuery} $table jQuery-object of the table 62 * @param {JQuery} $searchSortRow the special row where the sort-buttons will be placed 63 * @param {int} numHeaderRows the number of rows in the header of the table 64 * 65 * @return {void} 66 */ 67 function addSortFunctionality($table, $searchSortRow, numHeaderRows) { 68 var $rowsToBeSorted; 69 if ($table.hasClass('tablelayout_body')) { 70 $rowsToBeSorted = $table.find('tr'); 71 } else { 72 $rowsToBeSorted = $table.find('tr').slice(parseInt(numHeaderRows) + 1); 73 } 74 var $tableSortRowCells = $searchSortRow.find('td > div,th > div'); 75 $tableSortRowCells.append(jQuery('<button>')); 76 var $tableSortRowCellsButtons = $tableSortRowCells.find('button'); 77 $tableSortRowCellsButtons.addClass('sortable unsorted'); 78 $tableSortRowCellsButtons.click(function () { 79 window.tablelayout.splitMerges($rowsToBeSorted); 80 var $this = jQuery(this); 81 var sortDirection = $this.hasClass('sorted_asc') ? 'desc' : 'asc'; 82 $tableSortRowCellsButtons.removeClass('sorted_asc sorted_desc').addClass('unsorted'); 83 $this.addClass('sorted_' + sortDirection).removeClass('unsorted'); 84 var colIndex = $this.closest('td,th').prevAll('td,th').length; 85 var sortedRows = window.tablelayout.sortTable($rowsToBeSorted.detach(), colIndex, sortDirection); 86 $table.append(sortedRows); 87 return false; 88 }); 89 } 90 91 /** 92 * 93 * @param {JQuery} $table jQuery-object of the table 94 * @param {JQuery} $searchSortRow the special row where the sort-buttons will be placed 95 * @param {int} numHeaderRows the number of rows in the header of the table 96 * 97 * @return {void} 98 */ 99 function addSearchFunctionality($table, $searchSortRow, numHeaderRows) { 100 var $rowsToBeSearched; 101 var $container = $searchSortRow.closest('.table'); 102 $container.addClass('hasSearch'); 103 if ($table.hasClass('tablelayout_body')) { 104 $rowsToBeSearched = $table.find('tr'); 105 } else { 106 $rowsToBeSearched = $table.find('tr').slice(parseInt(numHeaderRows) + 1); 107 } 108 109 $searchSortRow.find('td > div,th > div').prepend(jQuery('<input>')); 110 var $globalSearch = jQuery('<div class="globalSearch"><label><span>' + window.LANG.plugins.tablelayout.search + '</span><input name="globalSearch" type="text"></label></div>'); 111 $container.prepend($globalSearch); 112 var $searchInputs = $searchSortRow.find('input').add($globalSearch.find('input')); 113 $searchInputs.on('input', function () { 114 window.tablelayout.splitMerges($rowsToBeSearched); 115 var globalSearchText = $globalSearch.find('input').val().trim().toLowerCase(); 116 $rowsToBeSearched.each(function (index, row) { 117 var globalRowShow = false; 118 var hideRow = jQuery(row).find('td,th').toArray().some(function (cell, index) { 119 var $this = jQuery(cell); 120 var cellText = $this.text().trim().toLowerCase(); 121 globalRowShow = globalRowShow || (cellText.indexOf(globalSearchText) !== -1); 122 var colFilterIndex = index + 1; 123 var searchText = $searchInputs.eq(colFilterIndex).val().trim().toLowerCase(); 124 return cellText.indexOf(searchText) === -1; 125 }); 126 jQuery(row).css('display', (globalRowShow && !hideRow) ? 'table-row' : 'none'); 127 }); 128 }); 129 } 130 131 /** 132 * 133 * @param {JQuery} $table jQuery-object of the table 134 * @param {JQuery} $secedit_form the section edit form element for the table 135 * @param {object} layoutdata the configuration object 136 * 137 * @return {void} 138 */ 139 function applyFunctionalityToTable($table, $secedit_form, layoutdata) { 140 if (layoutdata.tablePrint) { 141 addPrintButtonToTable($secedit_form); 142 } 143 144 if (layoutdata.tableSort || layoutdata.tableSearch) { 145 var columnCount = $table.find('tr').toArray().reduce(function (max, row) { 146 return Math.max(max, jQuery(row).find('td,th').length); 147 }, 0); 148 var searchSortRow = addSearchSortRow($table, layoutdata.rowsHeader, columnCount); 149 } 150 151 if (layoutdata.tableSort) { 152 addSortFunctionality($table, searchSortRow, layoutdata.rowsHeader); 153 } 154 155 if (layoutdata.tableSearch) { 156 addSearchFunctionality($table, searchSortRow, layoutdata.rowsHeader) 157 } 158 } 159 160 var allowedModes = ['mode_show', 'mode_preview', 'mode_tablelayout_printtable', 'act_show', 'act_preview']; 161 if (!allowedModes.some(function (allowedModeClass) {return jQuery('.dokuwiki').hasClass(allowedModeClass)})) { 162 return; 163 } 164 165 jQuery('.page .table').each(function (index, element) { 166 var $table = jQuery(element).find('table'); 167 var layoutdata = jQuery(element).prev().data('tablelayout'); 168 if (typeof layoutdata === 'undefined') { 169 var featureDefault = Boolean(window.JSINFO.plugins.tablelayout.features_active_by_default); 170 layoutdata = { 171 rowsHeaderSource: 'Auto', 172 tableSearch: featureDefault, 173 tableSort: featureDefault, 174 tablePrint: featureDefault 175 }; 176 } 177 var numHeaderRowsAuto = $table.find('thead tr').length; 178 layoutdata.rowsHeader = layoutdata.rowsHeaderSource === 'Auto' ? numHeaderRowsAuto : layoutdata.rowsHeaderSource; 179 180 var $secedit_form = jQuery(element).next('.secedit').find('form div.no'); 181 if ($secedit_form.length) { 182 var $input = jQuery('<input name="tablelayout" type="hidden">').val(JSON.stringify(layoutdata)); 183 $secedit_form.prepend($input); 184 } 185 applyFunctionalityToTable($table, $secedit_form, layoutdata); 186 187 if (layoutdata.colwidth || layoutdata.rowsVisible) { 188 window.tablelayout.applyStylesToTable($table, layoutdata); 189 } 190 191 }); 192 193 if (jQuery('#tablelayout_printthis').length) { 194 window.print(); 195 } 196}); 197