1 | #include <string>
|
2 |
|
3 | namespace souffle {
|
4 | namespace profile {
|
5 | namespace html {
|
6 | std::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
|