OILS / vendor / souffle / profile / htmlJsTableSort.h View on Github | oilshell.org

270 lines, 6 significant
1#include <string>
2
3namespace souffle {
4namespace profile {
5namespace html {
6std::string jsTableSort = R"___(
7/*!
8 * tablesort v4.1.0 (2016-12-29)
9 * http://tristen.ca/tablesort/demo/
10 * Copyright (c) 2016 ; Licensed MIT
11 */
12(function() {
13 function Tablesort(el, options) {
14 if (!(this instanceof Tablesort)) return new Tablesort(el, options);
15
16 if (!el || el.tagName !== 'TABLE') {
17 throw new Error('Element must be a table');
18 }
19 this.init(el, options || {});
20 }
21
22 var sortOptions = [];
23
24 var createEvent = function(name) {
25 var evt;
26
27 if (!window.CustomEvent || typeof window.CustomEvent !== 'function') {
28 evt = document.createEvent('CustomEvent');
29 evt.initCustomEvent(name, false, false, undefined);
30 } else {
31 evt = new CustomEvent(name);
32 }
33
34 return evt;
35 };
36
37 var getInnerText = function(el) {
38 return el.getAttribute('data-sort') || el.textContent || el.innerText || '';
39 };
40
41 // Default sort method if no better sort method is found
42 var caseInsensitiveSort = function(a, b) {
43 a = a.toLowerCase();
44 b = b.toLowerCase();
45
46 if (a === b) return 0;
47 if (a < b) return 1;
48
49 return -1;
50 };
51
52 // Stable sort function
53 // If two elements are equal under the original sort function,
54 // then there relative order is reversed
55 var stabilize = function(sort, antiStabilize) {
56 return function(a, b) {
57 var unstableResult = sort(a.td, b.td);
58
59 if (unstableResult === 0) {
60 if (antiStabilize) return b.index - a.index;
61 return a.index - b.index;
62 }
63
64 return unstableResult;
65 };
66 };
67
68 Tablesort.extend = function(name, pattern, sort) {
69 if (typeof pattern !== 'function' || typeof sort !== 'function') {
70 throw new Error('Pattern and sort must be a function');
71 }
72
73 sortOptions.push({
74 name: name,
75 pattern: pattern,
76 sort: sort
77 });
78 };
79
80 Tablesort.prototype = {
81
82 init: function(el, options) {
83 var that = this,
84 firstRow,
85 defaultSort,
86 i,
87 cell;
88
89 that.table = el;
90 that.thead = false;
91 that.options = options;
92
93 if (el.rows && el.rows.length > 0) {
94 if (el.tHead && el.tHead.rows.length > 0) {
95 for (i = 0; i < el.tHead.rows.length; i++) {
96 if (el.tHead.rows[i].getAttribute('data-sort-method') === 'thead') {
97 firstRow = el.tHead.rows[i];
98 break;
99 }
100 }
101 if (!firstRow) {
102 firstRow = el.tHead.rows[el.tHead.rows.length - 1];
103 }
104 that.thead = true;
105 } else {
106 firstRow = el.rows[0];
107 }
108 }
109
110 if (!firstRow) return;
111
112 var onClick = function() {
113 if (that.current && that.current !== this) {
114 that.current.removeAttribute('aria-sort');
115 }
116
117 that.current = this;
118 that.sortTable(this);
119 };
120
121 // Assume first row is the header and attach a click handler to each.
122 for (i = 0; i < firstRow.cells.length; i++) {
123 cell = firstRow.cells[i];
124 cell.setAttribute('role','columnheader');
125 if (cell.getAttribute('data-sort-method') !== 'none') {
126 cell.tabindex = 0;
127 cell.addEventListener('click', onClick, false);
128
129 if (cell.getAttribute('data-sort-default') !== null) {
130 defaultSort = cell;
131 }
132 }
133 }
134
135 if (defaultSort) {
136 that.current = defaultSort;
137 that.sortTable(defaultSort);
138 }
139 },
140
141 sortTable: function(header, update) {
142 var that = this,
143 column = header.cellIndex,
144 sortFunction = caseInsensitiveSort,
145 item = '',
146 items = [],
147 i = that.thead ? 0 : 1,
148 sortMethod = header.getAttribute('data-sort-method'),
149 sortOrder = header.getAttribute('aria-sort');
150
151 that.table.dispatchEvent(createEvent('beforeSort'));
152
153 // If updating an existing sort, direction should remain unchanged.
154 if (!update) {
155 if (sortOrder === 'ascending') {
156 sortOrder = 'descending';
157 } else if (sortOrder === 'descending') {
158 sortOrder = 'ascending';
159 } else {
160 sortOrder = that.options.descending ? 'ascending' : 'descending';
161 }
162
163 header.setAttribute('aria-sort', sortOrder);
164 }
165
166 if (that.table.rows.length < 2) return;
167
168 // If we force a sort method, it is not necessary to check rows
169 if (!sortMethod) {
170 while (items.length < 3 && i < that.table.tBodies[0].rows.length) {
171 item = getInnerText(that.table.tBodies[0].rows[i].cells[column]);
172 item = item.trim();
173
174 if (item.length > 0) {
175 items.push(item);
176 }
177
178 i++;
179 }
180
181 if (!items) return;
182 }
183
184 for (i = 0; i < sortOptions.length; i++) {
185 item = sortOptions[i];
186
187 if (sortMethod) {
188 if (item.name === sortMethod) {
189 sortFunction = item.sort;
190 break;
191 }
192 } else if (items.every(item.pattern)) {
193 sortFunction = item.sort;
194 break;
195 }
196 }
197
198 that.col = column;
199
200 for (i = 0; i < that.table.tBodies.length; i++) {
201 var newRows = [],
202 noSorts = {},
203 j,
204 totalRows = 0,
205 noSortsSoFar = 0;
206
207 if (that.table.tBodies[i].rows.length < 2) continue;
208
209 for (j = 0; j < that.table.tBodies[i].rows.length; j++) {
210 item = that.table.tBodies[i].rows[j];
211 if (item.getAttribute('data-sort-method') === 'none') {
212 // keep no-sorts in separate list to be able to insert
213 // them back at their original position later
214 noSorts[totalRows] = item;
215 } else {
216 // Save the index for stable sorting
217 newRows.push({
218 tr: item,
219 td: getInnerText(item.cells[that.col]),
220 index: totalRows
221 });
222 }
223 totalRows++;
224 }
225 // Before we append should we reverse the new array or not?
226 // If we reverse, the sort needs to be `anti-stable` so that
227 // the double negatives cancel out
228 if (sortOrder === 'descending') {
229 newRows.sort(stabilize(sortFunction, true));
230 newRows.reverse();
231 } else {
232 newRows.sort(stabilize(sortFunction, false));
233 }
234
235 // append rows that already exist rather than creating new ones
236 for (j = 0; j < totalRows; j++) {
237 if (noSorts[j]) {
238 // We have a no-sort row for this position, insert it here.
239 item = noSorts[j];
240 noSortsSoFar++;
241 } else {
242 item = newRows[j - noSortsSoFar].tr;
243 }
244
245 // appendChild(x) moves x if already present somewhere else in the DOM
246 that.table.tBodies[i].appendChild(item);
247 }
248 }
249
250 that.table.dispatchEvent(createEvent('afterSort'));
251 },
252
253 refresh: function() {
254 if (this.current !== undefined) {
255 this.sortTable(this.current, true);
256 }
257 }
258 };
259
260 if (typeof module !== 'undefined' && module.exports) {
261 module.exports = Tablesort;
262 } else {
263 window.Tablesort = Tablesort;
264 }
265})();
266
267)___";
268}
269} // namespace profile
270} // namespace souffle