1window.tablelayout = window.tablelayout || {};
2
3(function (exports) {
4    'use strict';
5    var atomicrowIndex = null;
6    exports.getNumberOfTableCols = function ($table) {
7        var $rows = $table.find('tr');
8        var max = 0;
9        $rows.each(function (index, row) {
10            if (max < row.cells.length) {
11                max = row.cells.length;
12                atomicrowIndex = index;
13            }
14        });
15        return max;
16    };
17
18    exports.floatTable = function ($table, direction) {
19        if ($table.width() > jQuery('div.page').width()) {
20            return;
21        }
22        var $parentDiv = $table.closest('div.table');
23        var $elements = jQuery([]);
24        $elements = $elements.add($parentDiv.prev('div.plugin_tablelayout_placeholder'));
25        $elements = $elements.add($parentDiv);
26        $elements = $elements.add($parentDiv.next('div.secedit.editbutton_table'));
27        $elements.wrapAll('<div class="floatwrapper">');
28        $elements.parent('div.floatwrapper').addClass(direction);
29    };
30
31    exports.applyStylesToTable = function ($table, layoutdata) {
32        if (!layoutdata.colwidth) {
33            layoutdata.colwidth = [];
34        }
35        exports.styleColumnWidths($table, layoutdata.colwidth);
36        exports.fixColumnWidths($table);
37        if (layoutdata.rowsHeader > 0 && layoutdata.rowsVisible > 0) {
38            exports.freezeTableRows($table, layoutdata.rowsHeader, layoutdata.rowsVisible);
39        }
40        if (layoutdata.float === 'right' || layoutdata.float === 'left' || layoutdata.float === 'center') {
41            exports.floatTable($table, layoutdata.float);
42        }
43    };
44
45    exports.fixColumnWidths = function ($table) {
46        var $cols = $table.find('colgroup col');
47        var $atomicrow = $table.find('.row' + atomicrowIndex);
48        $cols.each(function (index, col) {
49            var width = $atomicrow['0'].cells.item(index).offsetWidth;
50            if (!col.style.width) {
51                jQuery(col).css('width', width);
52            }
53        });
54        $table.addClass('widthsfixed');
55    };
56
57    exports.styleColumnWidths = function ($table, colwidths) {
58        var numCols = exports.getNumberOfTableCols($table);
59        var $colgroup = jQuery('<colgroup>');
60        for (var i = 0; i < numCols; i += 1) {
61            var $col = jQuery('<col>');
62            if (colwidths[i]) {
63                $col.css('width', colwidths[i]);
64            }
65            $colgroup.append($col);
66        }
67        $table.prepend($colgroup);
68
69        if (colwidths.length === numCols) {
70            // todo: should we throw an error if there are MORE widths defined than cols in the table?
71            $table.addClass('flexiblewidth');
72        }
73    };
74
75    exports.freezeTableRows = function ($table, rowsToFreeze, rowsVisible) {
76        rowsToFreeze = parseInt(rowsToFreeze);
77        rowsVisible = parseInt(rowsVisible);
78        if ($table.find('tr').length <= rowsToFreeze + rowsVisible) {
79            return;
80        }
81        var tableWidth = $table.width();
82        var $frozenTable = $table.clone();
83        $table.addClass('tablelayout_body');
84        $frozenTable.addClass('tablelayout_head');
85        var $frozenRows = $frozenTable.find('tr');
86        for (var i = $table.find('tr').length - 1; i >= rowsToFreeze; i -= 1) {
87            jQuery($frozenRows[i]).remove();
88        }
89        if (!$frozenTable.find('tbody').children().length) {
90            $frozenTable.find('tbody').remove();
91        }
92        var $tableRows = $table.find('tr');
93        for (i = 0; i < rowsToFreeze; i += 1) {
94            jQuery($tableRows[i]).remove();
95        }
96        $frozenTable.append($table.find('.searchSortRow'));
97        if (!$table.find('thead').children().length) {
98            $table.find('thead').remove();
99        }
100        $table.parent().prepend($frozenTable);
101        // move search above the table header
102        if ($table.parent().hasClass('hasSearch')) {
103            $table.parent().prepend($table.parent().find('.globalSearch'));
104        }
105
106        var SCROLLBAR_WIDTH = 17;
107        $frozenTable.wrap(jQuery('<div></div>').width(tableWidth + SCROLLBAR_WIDTH));
108        var height = 0;
109        for (i = rowsToFreeze; i < rowsToFreeze + rowsVisible; i += 1) {
110            height += jQuery($tableRows[i]).height();
111        }
112        var tableWrapper = jQuery('<div></div>').css({'overflow-y': 'scroll'}).height(height).width(tableWidth + SCROLLBAR_WIDTH);
113        $table.wrap(tableWrapper);
114    };
115
116    exports.initLayout = function (json) {
117        var layout = {};
118        if (json) {
119            layout = JSON.parse(json);
120        }
121
122        if (typeof layout.colwidth === 'undefined') {
123            layout.colwidth = [];
124        }
125        return layout;
126    };
127
128    exports.sortTable = function ($tableRows, sortColumnIndex, order) {
129        var sortModifier = order === 'asc' ? 1 : -1;
130        var compare = function compare(rowA, rowB) {
131            var tda = jQuery(rowA).find('td,th').eq(sortColumnIndex).text().toLowerCase();
132            var tdb = jQuery(rowB).find('td,th').eq(sortColumnIndex).text().toLowerCase();
133            if (tda < tdb) {
134                return -1 * sortModifier;
135            }
136
137            if (tda > tdb) {
138                return sortModifier;
139            }
140
141            return 0;
142        };
143        return $tableRows.sort(compare);
144    };
145
146    /**
147     * split all rowspans and colspans in a continuous set of table rows and multiply the content for all rows
148     *
149     * Please note that this functions modifies the argument as well.
150     *
151     * @param {jQuery[]} $tableRows jQuery set of continuoues table rows
152     *
153     * @return {jQuery[]} the adjust array of rows
154     */
155    exports.splitMerges = function splitMerges($tableRows) {
156        var $splitRows = $tableRows;
157        $splitRows.find('td[colspan],th[colspan]').each(function (index, cell) {
158            var $cell = jQuery(cell);
159            var colspan = $cell.attr('colspan') - 1;
160            $cell.removeAttr('colspan');
161            for (var i = 0; i < colspan; i += 1) {
162                $cell.after($cell.clone(true, true));
163            }
164        });
165        $splitRows.find('td[rowspan],th[rowspan]').each(function (index, cell) {
166            var $cell = jQuery(cell);
167            var rowspan = $cell.attr('rowspan') - 1;
168            $cell.removeAttr('rowspan');
169            var colIndex = 0;
170            $cell.prevAll('td,th').each(function () {
171                colIndex += this.colSpan;
172            });
173            for (var i = 0; i < rowspan; i += 1) {
174                var $rowMissingCell = $cell.closest('tr').nextAll().eq(i);
175                var $rowCells = $rowMissingCell.find('td,th');
176                if ($rowCells.length === colIndex) {
177                    $rowCells.last().after($cell.clone(true, true));
178                } else {
179                    $rowCells.eq(colIndex).before($cell.clone(true, true));
180                }
181            }
182        });
183        return $splitRows;
184    };
185
186    return exports;
187}(window.tablelayout));
188