diff default/node_modules/tablesaw/src/tables.sortable.js @ 0:1d038bc9b3d2 default tip

Up:default
author Liny <dev@neowd.com>
date Sat, 31 May 2025 09:21:51 +0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/default/node_modules/tablesaw/src/tables.sortable.js	Sat May 31 09:21:51 2025 +0800
@@ -0,0 +1,392 @@
+/*
+* tablesaw: A set of plugins for responsive tables
+* Sortable column headers
+* Copyright (c) 2013 Filament Group, Inc.
+* MIT License
+*/
+
+(function() {
+	function getSortValue(cell) {
+		var text = [];
+		$(cell.childNodes).each(function() {
+			var $el = $(this);
+			if ($el.is("input, select")) {
+				text.push($el.val());
+			} else if ($el.is(".tablesaw-cell-label")) {
+			} else {
+				text.push(($el.text() || "").replace(/^\s+|\s+$/g, ""));
+			}
+		});
+
+		return text.join("");
+	}
+
+	var pluginName = "tablesaw-sortable",
+		initSelector = "table[data-" + pluginName + "]",
+		sortableSwitchSelector = "[data-" + pluginName + "-switch]",
+		attrs = {
+			sortCol: "data-tablesaw-sortable-col",
+			defaultCol: "data-tablesaw-sortable-default-col",
+			numericCol: "data-tablesaw-sortable-numeric",
+			subRow: "data-tablesaw-subrow",
+			ignoreRow: "data-tablesaw-ignorerow"
+		},
+		classes = {
+			head: pluginName + "-head",
+			ascend: pluginName + "-ascending",
+			descend: pluginName + "-descending",
+			switcher: pluginName + "-switch",
+			tableToolbar: "tablesaw-bar-section",
+			sortButton: pluginName + "-btn"
+		},
+		methods = {
+			_create: function(o) {
+				return $(this).each(function() {
+					var init = $(this).data(pluginName + "-init");
+					if (init) {
+						return false;
+					}
+					$(this)
+						.data(pluginName + "-init", true)
+						.trigger("beforecreate." + pluginName)
+						[pluginName]("_init", o)
+						.trigger("create." + pluginName);
+				});
+			},
+			_init: function() {
+				var el = $(this);
+				var tblsaw = el.data("tablesaw");
+				var heads;
+				var $switcher;
+
+				function addClassToHeads(h) {
+					$.each(h, function(i, v) {
+						$(v).addClass(classes.head);
+					});
+				}
+
+				function makeHeadsActionable(h, fn) {
+					$.each(h, function(i, col) {
+						var b = $("<button class='" + classes.sortButton + "'/>");
+						b.on("click", { col: col }, fn);
+						$(col)
+							.wrapInner(b)
+							.find("button")
+							.append("<span class='tablesaw-sortable-arrow'>");
+					});
+				}
+
+				function clearOthers(headcells) {
+					$.each(headcells, function(i, v) {
+						var col = $(v);
+						col.removeAttr(attrs.defaultCol);
+						col.removeClass(classes.ascend);
+						col.removeClass(classes.descend);
+					});
+				}
+
+				function headsOnAction(e) {
+					if ($(e.target).is("a[href]")) {
+						return;
+					}
+
+					e.stopPropagation();
+					var headCell = $(e.target).closest("[" + attrs.sortCol + "]"),
+						v = e.data.col,
+						newSortValue = heads.index(headCell[0]);
+
+					clearOthers(
+						headCell
+							.closest("thead")
+							.find("th")
+							.filter(function() {
+								return this !== headCell[0];
+							})
+					);
+					if (headCell.is("." + classes.descend) || !headCell.is("." + classes.ascend)) {
+						el[pluginName]("sortBy", v, true);
+						newSortValue += "_asc";
+					} else {
+						el[pluginName]("sortBy", v);
+						newSortValue += "_desc";
+					}
+					if ($switcher) {
+						$switcher
+							.find("select")
+							.val(newSortValue)
+							.trigger("refresh");
+					}
+
+					e.preventDefault();
+				}
+
+				function handleDefault(heads) {
+					$.each(heads, function(idx, el) {
+						var $el = $(el);
+						if ($el.is("[" + attrs.defaultCol + "]")) {
+							if (!$el.is("." + classes.descend)) {
+								$el.addClass(classes.ascend);
+							}
+						}
+					});
+				}
+
+				function addSwitcher(heads) {
+					$switcher = $("<div>")
+						.addClass(classes.switcher)
+						.addClass(classes.tableToolbar);
+
+					var html = ["<label>" + Tablesaw.i18n.sort + ":"];
+
+					// TODO next major version: remove .btn
+					html.push('<span class="btn tablesaw-btn"><select>');
+					heads.each(function(j) {
+						var $t = $(this);
+						var isDefaultCol = $t.is("[" + attrs.defaultCol + "]");
+						var isDescending = $t.is("." + classes.descend);
+
+						var hasNumericAttribute = $t.is("[" + attrs.numericCol + "]");
+						var numericCount = 0;
+						// Check only the first four rows to see if the column is numbers.
+						var numericCountMax = 5;
+
+						$(this.cells.slice(0, numericCountMax)).each(function() {
+							if (!isNaN(parseInt(getSortValue(this), 10))) {
+								numericCount++;
+							}
+						});
+						var isNumeric = numericCount === numericCountMax;
+						if (!hasNumericAttribute) {
+							$t.attr(attrs.numericCol, isNumeric ? "" : "false");
+						}
+
+						html.push(
+							"<option" +
+								(isDefaultCol && !isDescending ? " selected" : "") +
+								' value="' +
+								j +
+								'_asc">' +
+								$t.text() +
+								" " +
+								(isNumeric ? "&#x2191;" : "(A-Z)") +
+								"</option>"
+						);
+						html.push(
+							"<option" +
+								(isDefaultCol && isDescending ? " selected" : "") +
+								' value="' +
+								j +
+								'_desc">' +
+								$t.text() +
+								" " +
+								(isNumeric ? "&#x2193;" : "(Z-A)") +
+								"</option>"
+						);
+					});
+					html.push("</select></span></label>");
+
+					$switcher.html(html.join(""));
+
+					var $firstChild = tblsaw.$toolbar.children().eq(0);
+					if ($firstChild.length) {
+						$switcher.insertBefore($firstChild);
+					} else {
+						$switcher.appendTo(tblsaw.$toolbar);
+					}
+					$switcher.find(".tablesaw-btn").tablesawbtn();
+					$switcher.find("select").on("change", function() {
+						var val = $(this)
+								.val()
+								.split("_"),
+							head = heads.eq(val[0]);
+
+						clearOthers(head.siblings());
+						el[pluginName]("sortBy", head.get(0), val[1] === "asc");
+					});
+				}
+
+				el.addClass(pluginName);
+
+				heads = el
+					.children()
+					.filter("thead")
+					.find("th[" + attrs.sortCol + "]");
+
+				addClassToHeads(heads);
+				makeHeadsActionable(heads, headsOnAction);
+				handleDefault(heads);
+
+				if (el.is(sortableSwitchSelector)) {
+					addSwitcher(heads);
+				}
+			},
+			sortRows: function(rows, colNum, ascending, col, tbody) {
+				function convertCells(cellArr, belongingToTbody) {
+					var cells = [];
+					$.each(cellArr, function(i, cell) {
+						var row = cell.parentNode;
+						var $row = $(row);
+						// next row is a subrow
+						var subrows = [];
+						var $next = $row.next();
+						while ($next.is("[" + attrs.subRow + "]")) {
+							subrows.push($next[0]);
+							$next = $next.next();
+						}
+
+						var tbody = row.parentNode;
+
+						// current row is a subrow
+						if ($row.is("[" + attrs.subRow + "]")) {
+						} else if (tbody === belongingToTbody) {
+							cells.push({
+								element: cell,
+								cell: getSortValue(cell),
+								row: row,
+								subrows: subrows.length ? subrows : null,
+								ignored: $row.is("[" + attrs.ignoreRow + "]")
+							});
+						}
+					});
+					return cells;
+				}
+
+				function getSortFxn(ascending, forceNumeric) {
+					var fn,
+						regex = /[^\-\+\d\.]/g;
+					if (ascending) {
+						fn = function(a, b) {
+							if (a.ignored || b.ignored) {
+								return 0;
+							}
+							if (forceNumeric) {
+								return (
+									parseFloat(a.cell.replace(regex, "")) - parseFloat(b.cell.replace(regex, ""))
+								);
+							} else {
+								return a.cell.toLowerCase() > b.cell.toLowerCase() ? 1 : -1;
+							}
+						};
+					} else {
+						fn = function(a, b) {
+							if (a.ignored || b.ignored) {
+								return 0;
+							}
+							if (forceNumeric) {
+								return (
+									parseFloat(b.cell.replace(regex, "")) - parseFloat(a.cell.replace(regex, ""))
+								);
+							} else {
+								return a.cell.toLowerCase() < b.cell.toLowerCase() ? 1 : -1;
+							}
+						};
+					}
+					return fn;
+				}
+
+				function convertToRows(sorted) {
+					var newRows = [],
+						i,
+						l;
+					for (i = 0, l = sorted.length; i < l; i++) {
+						newRows.push(sorted[i].row);
+						if (sorted[i].subrows) {
+							newRows.push(sorted[i].subrows);
+						}
+					}
+					return newRows;
+				}
+
+				var fn;
+				var sorted;
+				var cells = convertCells(col.cells, tbody);
+
+				var customFn = $(col).data("tablesaw-sort");
+
+				fn =
+					(customFn && typeof customFn === "function" ? customFn(ascending) : false) ||
+					getSortFxn(
+						ascending,
+						$(col).is("[" + attrs.numericCol + "]") &&
+							!$(col).is("[" + attrs.numericCol + '="false"]')
+					);
+
+				sorted = cells.sort(fn);
+
+				rows = convertToRows(sorted);
+
+				return rows;
+			},
+			makeColDefault: function(col, a) {
+				var c = $(col);
+				c.attr(attrs.defaultCol, "true");
+				if (a) {
+					c.removeClass(classes.descend);
+					c.addClass(classes.ascend);
+				} else {
+					c.removeClass(classes.ascend);
+					c.addClass(classes.descend);
+				}
+			},
+			sortBy: function(col, ascending) {
+				var el = $(this);
+				var colNum;
+				var tbl = el.data("tablesaw");
+				tbl.$tbody.each(function() {
+					var tbody = this;
+					var $tbody = $(this);
+					var rows = tbl.getBodyRows(tbody);
+					var sortedRows;
+					var map = tbl.headerMapping[0];
+					var j, k;
+
+					// find the column number that we’re sorting
+					for (j = 0, k = map.length; j < k; j++) {
+						if (map[j] === col) {
+							colNum = j;
+							break;
+						}
+					}
+
+					sortedRows = el[pluginName]("sortRows", rows, colNum, ascending, col, tbody);
+
+					// replace Table rows
+					for (j = 0, k = sortedRows.length; j < k; j++) {
+						$tbody.append(sortedRows[j]);
+					}
+				});
+
+				el[pluginName]("makeColDefault", col, ascending);
+
+				el.trigger("tablesaw-sorted");
+			}
+		};
+
+	// Collection method.
+	$.fn[pluginName] = function(arrg) {
+		var args = Array.prototype.slice.call(arguments, 1),
+			returnVal;
+
+		// if it's a method
+		if (arrg && typeof arrg === "string") {
+			returnVal = $.fn[pluginName].prototype[arrg].apply(this[0], args);
+			return typeof returnVal !== "undefined" ? returnVal : $(this);
+		}
+		// check init
+		if (!$(this).data(pluginName + "-active")) {
+			$(this).data(pluginName + "-active", true);
+			$.fn[pluginName].prototype._create.call(this, arrg);
+		}
+		return $(this);
+	};
+	// add methods
+	$.extend($.fn[pluginName].prototype, methods);
+
+	$(document).on(Tablesaw.events.create, function(e, Tablesaw) {
+		if (Tablesaw.$table.is(initSelector)) {
+			Tablesaw.$table[pluginName]();
+		}
+	});
+
+	// TODO OOP this and add to Tablesaw object
+})();