souffle  2.0.2-371-g6315b36
htmlJsTableSort.h
Go to the documentation of this file.
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
souffle::profile::html::jsTableSort
std::string jsTableSort
Definition: htmlJsTableSort.h:6
souffle
Definition: AggregateOp.h:25