12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156 |
- /*! Tablesaw - v3.1.2 - 2019-03-19
- * https://github.com/filamentgroup/tablesaw
- * Copyright (c) 2019 Filament Group; Licensed MIT */
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define(["jquery"], function (jQuery) {
- return (root.Tablesaw = factory(jQuery, root));
- });
- } else if (typeof exports === 'object') {
- if( "document" in root ) {
- module.exports = factory(require('jquery'), root);
- } else {
- // special jQuery case for CommonJS (pass in a window)
- module.exports = factory(require('jquery')(root), root);
- }
- } else {
- root.Tablesaw = factory(jQuery, root);
- }
- }(typeof window !== "undefined" ? window : this, function ($, window) {
- "use strict";
- var document = window.document;
- // Account for Tablesaw being loaded either before or after the DOMContentLoaded event is fired.
- var domContentLoadedTriggered = /complete|loaded/.test(document.readyState);
- document.addEventListener("DOMContentLoaded", function() {
- domContentLoadedTriggered = true;
- });
- var Tablesaw = {
- i18n: {
- modeStack: "Stack",
- modeSwipe: "Swipe",
- modeToggle: "Toggle",
- modeSwitchColumnsAbbreviated: "Cols",
- modeSwitchColumns: "Columns",
- columnToggleButton: "Columns",
- columnToggleError: "No eligible columns.",
- sort: "Sort",
- swipePreviousColumn: "Previous column",
- swipeNextColumn: "Next column"
- },
- // cut the mustard
- mustard:
- "head" in document && // IE9+, Firefox 4+, Safari 5.1+, Mobile Safari 4.1+, Opera 11.5+, Android 2.3+
- (!window.blackberry || window.WebKitPoint) && // only WebKit Blackberry (OS 6+)
- !window.operamini,
- $: $,
- _init: function(element) {
- Tablesaw.$(element || document).trigger("enhance.tablesaw");
- },
- init: function(element) {
- // Account for Tablesaw being loaded either before or after the DOMContentLoaded event is fired.
- domContentLoadedTriggered =
- domContentLoadedTriggered || /complete|loaded/.test(document.readyState);
- if (!domContentLoadedTriggered) {
- if ("addEventListener" in document) {
- // Use raw DOMContentLoaded instead of shoestring (may have issues in Android 2.3, exhibited by stack table)
- document.addEventListener("DOMContentLoaded", function() {
- Tablesaw._init(element);
- });
- }
- } else {
- Tablesaw._init(element);
- }
- }
- };
- $(document).on("enhance.tablesaw", function() {
- // Extend i18n config, if one exists.
- if (typeof TablesawConfig !== "undefined" && TablesawConfig.i18n) {
- Tablesaw.i18n = $.extend(Tablesaw.i18n, TablesawConfig.i18n || {});
- }
- Tablesaw.i18n.modes = [
- Tablesaw.i18n.modeStack,
- Tablesaw.i18n.modeSwipe,
- Tablesaw.i18n.modeToggle
- ];
- });
- if (Tablesaw.mustard) {
- $(document.documentElement).addClass("tablesaw-enhanced");
- }
- (function() {
- var pluginName = "tablesaw";
- var classes = {
- toolbar: "tablesaw-bar"
- };
- var events = {
- create: "tablesawcreate",
- destroy: "tablesawdestroy",
- refresh: "tablesawrefresh",
- resize: "tablesawresize"
- };
- var defaultMode = "stack";
- var initSelector = "table";
- var initFilterSelector = "[data-tablesaw],[data-tablesaw-mode],[data-tablesaw-sortable]";
- var defaultConfig = {};
- Tablesaw.events = events;
- var Table = function(element) {
- if (!element) {
- throw new Error("Tablesaw requires an element.");
- }
- this.table = element;
- this.$table = $(element);
- // only one <thead> and <tfoot> are allowed, per the specification
- this.$thead = this.$table
- .children()
- .filter("thead")
- .eq(0);
- // multiple <tbody> are allowed, per the specification
- this.$tbody = this.$table.children().filter("tbody");
- this.mode = this.$table.attr("data-tablesaw-mode") || defaultMode;
- this.$toolbar = null;
- this.attributes = {
- subrow: "data-tablesaw-subrow",
- ignorerow: "data-tablesaw-ignorerow"
- };
- this.init();
- };
- Table.prototype.init = function() {
- if (!this.$thead.length) {
- throw new Error("tablesaw: a <thead> is required, but none was found.");
- }
- if (!this.$thead.find("th").length) {
- throw new Error("tablesaw: no header cells found. Are you using <th> inside of <thead>?");
- }
- // assign an id if there is none
- if (!this.$table.attr("id")) {
- this.$table.attr("id", pluginName + "-" + Math.round(Math.random() * 10000));
- }
- this.createToolbar();
- this._initCells();
- this.$table.data(pluginName, this);
- this.$table.trigger(events.create, [this]);
- };
- Table.prototype.getConfig = function(pluginSpecificConfig) {
- // shoestring extend doesn’t support arbitrary args
- var configs = $.extend(defaultConfig, pluginSpecificConfig || {});
- return $.extend(configs, typeof TablesawConfig !== "undefined" ? TablesawConfig : {});
- };
- Table.prototype._getPrimaryHeaderRow = function() {
- return this._getHeaderRows().eq(0);
- };
- Table.prototype._getHeaderRows = function() {
- return this.$thead
- .children()
- .filter("tr")
- .filter(function() {
- return !$(this).is("[data-tablesaw-ignorerow]");
- });
- };
- Table.prototype._getRowIndex = function($row) {
- return $row.prevAll().length;
- };
- Table.prototype._getHeaderRowIndeces = function() {
- var self = this;
- var indeces = [];
- this._getHeaderRows().each(function() {
- indeces.push(self._getRowIndex($(this)));
- });
- return indeces;
- };
- Table.prototype._getPrimaryHeaderCells = function($row) {
- return ($row || this._getPrimaryHeaderRow()).find("th");
- };
- Table.prototype._$getCells = function(th) {
- var self = this;
- return $(th)
- .add(th.cells)
- .filter(function() {
- var $t = $(this);
- var $row = $t.parent();
- var hasColspan = $t.is("[colspan]");
- // no subrows or ignored rows (keep cells in ignored rows that do not have a colspan)
- return (
- !$row.is("[" + self.attributes.subrow + "]") &&
- (!$row.is("[" + self.attributes.ignorerow + "]") || !hasColspan)
- );
- });
- };
- Table.prototype._getVisibleColspan = function() {
- var colspan = 0;
- this._getPrimaryHeaderCells().each(function() {
- var $t = $(this);
- if ($t.css("display") !== "none") {
- colspan += parseInt($t.attr("colspan"), 10) || 1;
- }
- });
- return colspan;
- };
- Table.prototype.getColspanForCell = function($cell) {
- var visibleColspan = this._getVisibleColspan();
- var visibleSiblingColumns = 0;
- if ($cell.closest("tr").data("tablesaw-rowspanned")) {
- visibleSiblingColumns++;
- }
- $cell.siblings().each(function() {
- var $t = $(this);
- var colColspan = parseInt($t.attr("colspan"), 10) || 1;
- if ($t.css("display") !== "none") {
- visibleSiblingColumns += colColspan;
- }
- });
- // console.log( $cell[ 0 ], visibleColspan, visibleSiblingColumns );
- return visibleColspan - visibleSiblingColumns;
- };
- Table.prototype.isCellInColumn = function(header, cell) {
- return $(header)
- .add(header.cells)
- .filter(function() {
- return this === cell;
- }).length;
- };
- Table.prototype.updateColspanCells = function(cls, header, userAction) {
- var self = this;
- var primaryHeaderRow = self._getPrimaryHeaderRow();
- // find persistent column rowspans
- this.$table.find("[rowspan][data-tablesaw-priority]").each(function() {
- var $t = $(this);
- if ($t.attr("data-tablesaw-priority") !== "persist") {
- return;
- }
- var $row = $t.closest("tr");
- var rowspan = parseInt($t.attr("rowspan"), 10);
- if (rowspan > 1) {
- $row = $row.next();
- $row.data("tablesaw-rowspanned", true);
- rowspan--;
- }
- });
- this.$table
- .find("[colspan],[data-tablesaw-maxcolspan]")
- .filter(function() {
- // is not in primary header row
- return $(this).closest("tr")[0] !== primaryHeaderRow[0];
- })
- .each(function() {
- var $cell = $(this);
- if (userAction === undefined || self.isCellInColumn(header, this)) {
- } else {
- // if is not a user action AND the cell is not in the updating column, kill it
- return;
- }
- var colspan = self.getColspanForCell($cell);
- if (cls && userAction !== undefined) {
- // console.log( colspan === 0 ? "addClass" : "removeClass", $cell );
- $cell[colspan === 0 ? "addClass" : "removeClass"](cls);
- }
- // cache original colspan
- var maxColspan = parseInt($cell.attr("data-tablesaw-maxcolspan"), 10);
- if (!maxColspan) {
- $cell.attr("data-tablesaw-maxcolspan", $cell.attr("colspan"));
- } else if (colspan > maxColspan) {
- colspan = maxColspan;
- }
- // console.log( this, "setting colspan to ", colspan );
- $cell.attr("colspan", colspan);
- });
- };
- Table.prototype._findPrimaryHeadersForCell = function(cell) {
- var $headerRow = this._getPrimaryHeaderRow();
- var headerRowIndex = this._getRowIndex($headerRow);
- var results = [];
- for (var rowNumber = 0; rowNumber < this.headerMapping.length; rowNumber++) {
- if (rowNumber === headerRowIndex) {
- continue;
- }
- for (var colNumber = 0; colNumber < this.headerMapping[rowNumber].length; colNumber++) {
- if (this.headerMapping[rowNumber][colNumber] === cell) {
- results.push(this.headerMapping[headerRowIndex][colNumber]);
- }
- }
- }
- return results;
- };
- // used by init cells
- Table.prototype.getRows = function() {
- var self = this;
- return this.$table.find("tr").filter(function() {
- return $(this)
- .closest("table")
- .is(self.$table);
- });
- };
- // used by sortable
- Table.prototype.getBodyRows = function(tbody) {
- return (tbody ? $(tbody) : this.$tbody).children().filter("tr");
- };
- Table.prototype.getHeaderCellIndex = function(cell) {
- var lookup = this.headerMapping[0];
- for (var colIndex = 0; colIndex < lookup.length; colIndex++) {
- if (lookup[colIndex] === cell) {
- return colIndex;
- }
- }
- return -1;
- };
- Table.prototype._initCells = function() {
- // re-establish original colspans
- this.$table.find("[data-tablesaw-maxcolspan]").each(function() {
- var $t = $(this);
- $t.attr("colspan", $t.attr("data-tablesaw-maxcolspan"));
- });
- var $rows = this.getRows();
- var columnLookup = [];
- $rows.each(function(rowNumber) {
- columnLookup[rowNumber] = [];
- });
- $rows.each(function(rowNumber) {
- var coltally = 0;
- var $t = $(this);
- var children = $t.children();
- children.each(function() {
- var colspan = parseInt(
- this.getAttribute("data-tablesaw-maxcolspan") || this.getAttribute("colspan"),
- 10
- );
- var rowspan = parseInt(this.getAttribute("rowspan"), 10);
- // set in a previous rowspan
- while (columnLookup[rowNumber][coltally]) {
- coltally++;
- }
- columnLookup[rowNumber][coltally] = this;
- // TODO? both colspan and rowspan
- if (colspan) {
- for (var k = 0; k < colspan - 1; k++) {
- coltally++;
- columnLookup[rowNumber][coltally] = this;
- }
- }
- if (rowspan) {
- for (var j = 1; j < rowspan; j++) {
- columnLookup[rowNumber + j][coltally] = this;
- }
- }
- coltally++;
- });
- });
- var headerRowIndeces = this._getHeaderRowIndeces();
- for (var colNumber = 0; colNumber < columnLookup[0].length; colNumber++) {
- for (var headerIndex = 0, k = headerRowIndeces.length; headerIndex < k; headerIndex++) {
- var headerCol = columnLookup[headerRowIndeces[headerIndex]][colNumber];
- var rowNumber = headerRowIndeces[headerIndex];
- var rowCell;
- if (!headerCol.cells) {
- headerCol.cells = [];
- }
- while (rowNumber < columnLookup.length) {
- rowCell = columnLookup[rowNumber][colNumber];
- if (headerCol !== rowCell) {
- headerCol.cells.push(rowCell);
- }
- rowNumber++;
- }
- }
- }
- this.headerMapping = columnLookup;
- };
- Table.prototype.refresh = function() {
- this._initCells();
- this.$table.trigger(events.refresh, [this]);
- };
- Table.prototype._getToolbarAnchor = function() {
- var $parent = this.$table.parent();
- if ($parent.is(".tablesaw-overflow")) {
- return $parent;
- }
- return this.$table;
- };
- Table.prototype._getToolbar = function($anchor) {
- if (!$anchor) {
- $anchor = this._getToolbarAnchor();
- }
- return $anchor.prev().filter("." + classes.toolbar);
- };
- Table.prototype.createToolbar = function() {
- // Insert the toolbar
- // TODO move this into a separate component
- var $anchor = this._getToolbarAnchor();
- var $toolbar = this._getToolbar($anchor);
- if (!$toolbar.length) {
- $toolbar = $("<div>")
- .addClass(classes.toolbar)
- .insertBefore($anchor);
- }
- this.$toolbar = $toolbar;
- if (this.mode) {
- this.$toolbar.addClass("tablesaw-mode-" + this.mode);
- }
- };
- Table.prototype.destroy = function() {
- // Don’t remove the toolbar, just erase the classes on it.
- // Some of the table features are not yet destroy-friendly.
- this._getToolbar().each(function() {
- this.className = this.className.replace(/\btablesaw-mode\-\w*\b/gi, "");
- });
- var tableId = this.$table.attr("id");
- $(document).off("." + tableId);
- $(window).off("." + tableId);
- // other plugins
- this.$table.trigger(events.destroy, [this]);
- this.$table.removeData(pluginName);
- };
- // Collection method.
- $.fn[pluginName] = function() {
- return this.each(function() {
- var $t = $(this);
- if ($t.data(pluginName)) {
- return;
- }
- new Table(this);
- });
- };
- var $doc = $(document);
- $doc.on("enhance.tablesaw", function(e) {
- // Cut the mustard
- if (Tablesaw.mustard) {
- var $target = $(e.target);
- if ($target.parent().length) {
- $target = $target.parent();
- }
- $target
- .find(initSelector)
- .filter(initFilterSelector)
- [pluginName]();
- }
- });
- // Avoid a resize during scroll:
- // Some Mobile devices trigger a resize during scroll (sometimes when
- // doing elastic stretch at the end of the document or from the
- // location bar hide)
- var isScrolling = false;
- var scrollTimeout;
- $doc.on("scroll.tablesaw", function() {
- isScrolling = true;
- window.clearTimeout(scrollTimeout);
- scrollTimeout = window.setTimeout(function() {
- isScrolling = false;
- }, 300); // must be greater than the resize timeout below
- });
- var resizeTimeout;
- $(window).on("resize", function() {
- if (!isScrolling) {
- window.clearTimeout(resizeTimeout);
- resizeTimeout = window.setTimeout(function() {
- $doc.trigger(events.resize);
- }, 150); // must be less than the scrolling timeout above.
- }
- });
- Tablesaw.Table = Table;
- })();
- (function() {
- var classes = {
- stackTable: "tablesaw-stack",
- cellLabels: "tablesaw-cell-label",
- cellContentLabels: "tablesaw-cell-content"
- };
- var data = {
- key: "tablesaw-stack"
- };
- var attrs = {
- labelless: "data-tablesaw-no-labels",
- hideempty: "data-tablesaw-hide-empty"
- };
- var Stack = function(element, tablesaw) {
- this.tablesaw = tablesaw;
- this.$table = $(element);
- this.labelless = this.$table.is("[" + attrs.labelless + "]");
- this.hideempty = this.$table.is("[" + attrs.hideempty + "]");
- this.$table.data(data.key, this);
- };
- Stack.prototype.init = function() {
- this.$table.addClass(classes.stackTable);
- if (this.labelless) {
- return;
- }
- var self = this;
- this.$table
- .find("th, td")
- .filter(function() {
- return !$(this).closest("thead").length;
- })
- .filter(function() {
- return (
- !$(this).is("[" + attrs.labelless + "]") &&
- !$(this)
- .closest("tr")
- .is("[" + attrs.labelless + "]") &&
- (!self.hideempty || !!$(this).html())
- );
- })
- .each(function() {
- var $newHeader = $(document.createElement("b")).addClass(classes.cellLabels);
- var $cell = $(this);
- $(self.tablesaw._findPrimaryHeadersForCell(this)).each(function(index) {
- var $header = $(this.cloneNode(true));
- // TODO decouple from sortable better
- // Changed from .text() in https://github.com/filamentgroup/tablesaw/commit/b9c12a8f893ec192830ec3ba2d75f062642f935b
- // to preserve structural html in headers, like <a>
- var $sortableButton = $header.find(".tablesaw-sortable-btn");
- $header.find(".tablesaw-sortable-arrow").remove();
- // TODO decouple from checkall better
- var $checkall = $header.find("[data-tablesaw-checkall]");
- $checkall.closest("label").remove();
- if ($checkall.length) {
- $newHeader = $([]);
- return;
- }
- if (index > 0) {
- $newHeader.append(document.createTextNode(", "));
- }
- var parentNode = $sortableButton.length ? $sortableButton[0] : $header[0];
- var el;
- while ((el = parentNode.firstChild)) {
- $newHeader[0].appendChild(el);
- }
- });
- if ($newHeader.length && !$cell.find("." + classes.cellContentLabels).length) {
- $cell.wrapInner("<span class='" + classes.cellContentLabels + "'></span>");
- }
- // Update if already exists.
- var $label = $cell.find("." + classes.cellLabels);
- if (!$label.length) {
- $cell.prepend(document.createTextNode(" "));
- $cell.prepend($newHeader);
- } else {
- // only if changed
- $label.replaceWith($newHeader);
- }
- });
- };
- Stack.prototype.destroy = function() {
- this.$table.removeClass(classes.stackTable);
- this.$table.find("." + classes.cellLabels).remove();
- this.$table.find("." + classes.cellContentLabels).each(function() {
- $(this).replaceWith($(this.childNodes));
- });
- };
- // on tablecreate, init
- $(document)
- .on(Tablesaw.events.create, function(e, tablesaw) {
- if (tablesaw.mode === "stack") {
- var table = new Stack(tablesaw.table, tablesaw);
- table.init();
- }
- })
- .on(Tablesaw.events.refresh, function(e, tablesaw) {
- if (tablesaw.mode === "stack") {
- $(tablesaw.table)
- .data(data.key)
- .init();
- }
- })
- .on(Tablesaw.events.destroy, function(e, tablesaw) {
- if (tablesaw.mode === "stack") {
- $(tablesaw.table)
- .data(data.key)
- .destroy();
- }
- });
- Tablesaw.Stack = Stack;
- })();
- (function() {
- var pluginName = "tablesawbtn",
- methods = {
- _create: function() {
- return $(this).each(function() {
- $(this)
- .trigger("beforecreate." + pluginName)
- [pluginName]("_init")
- .trigger("create." + pluginName);
- });
- },
- _init: function() {
- var oEl = $(this),
- sel = this.getElementsByTagName("select")[0];
- if (sel) {
- // TODO next major version: remove .btn-select
- $(this)
- .addClass("btn-select tablesaw-btn-select")
- [pluginName]("_select", sel);
- }
- return oEl;
- },
- _select: function(sel) {
- var update = function(oEl, sel) {
- var opts = $(sel).find("option");
- var label = document.createElement("span");
- var el;
- var children;
- var found = false;
- label.setAttribute("aria-hidden", "true");
- label.innerHTML = " ";
- opts.each(function() {
- var opt = this;
- if (opt.selected) {
- label.innerHTML = opt.text;
- }
- });
- children = oEl.childNodes;
- if (opts.length > 0) {
- for (var i = 0, l = children.length; i < l; i++) {
- el = children[i];
- if (el && el.nodeName.toUpperCase() === "SPAN") {
- oEl.replaceChild(label, el);
- found = true;
- }
- }
- if (!found) {
- oEl.insertBefore(label, oEl.firstChild);
- }
- }
- };
- update(this, sel);
- // todo should this be tablesawrefresh?
- $(this).on("change refresh", function() {
- update(this, sel);
- });
- }
- };
- // Collection method.
- $.fn[pluginName] = function(arrg, a, b, c) {
- return this.each(function() {
- // if it's a method
- if (arrg && typeof arrg === "string") {
- return $.fn[pluginName].prototype[arrg].call(this, a, b, c);
- }
- // don't re-init
- if ($(this).data(pluginName + "active")) {
- return $(this);
- }
- $(this).data(pluginName + "active", true);
- $.fn[pluginName].prototype._create.call(this);
- });
- };
- // add methods
- $.extend($.fn[pluginName].prototype, methods);
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var data = {
- key: "tablesaw-coltoggle"
- };
- var ColumnToggle = function(element) {
- this.$table = $(element);
- if (!this.$table.length) {
- return;
- }
- this.tablesaw = this.$table.data("tablesaw");
- this.attributes = {
- btnTarget: "data-tablesaw-columntoggle-btn-target",
- set: "data-tablesaw-columntoggle-set"
- };
- this.classes = {
- columnToggleTable: "tablesaw-columntoggle",
- columnBtnContain: "tablesaw-columntoggle-btnwrap tablesaw-advance",
- columnBtn: "tablesaw-columntoggle-btn tablesaw-nav-btn down",
- popup: "tablesaw-columntoggle-popup",
- priorityPrefix: "tablesaw-priority-"
- };
- this.set = [];
- this.$headers = this.tablesaw._getPrimaryHeaderCells();
- this.$table.data(data.key, this);
- };
- // Column Toggle Sets (one column chooser can control multiple tables)
- ColumnToggle.prototype.initSet = function() {
- var set = this.$table.attr(this.attributes.set);
- if (set) {
- // Should not include the current table
- var table = this.$table[0];
- this.set = $("table[" + this.attributes.set + "='" + set + "']")
- .filter(function() {
- return this !== table;
- })
- .get();
- }
- };
- ColumnToggle.prototype.init = function() {
- if (!this.$table.length) {
- return;
- }
- var tableId,
- id,
- $menuButton,
- $popup,
- $menu,
- $btnContain,
- self = this;
- var cfg = this.tablesaw.getConfig({
- getColumnToggleLabelTemplate: function(text) {
- return "<label><input type='checkbox' checked>" + text + "</label>";
- }
- });
- this.$table.addClass(this.classes.columnToggleTable);
- tableId = this.$table.attr("id");
- id = tableId + "-popup";
- $btnContain = $("<div class='" + this.classes.columnBtnContain + "'></div>");
- // TODO next major version: remove .btn
- $menuButton = $(
- "<a href='#" +
- id +
- "' class='btn tablesaw-btn btn-micro " +
- this.classes.columnBtn +
- "' data-popup-link>" +
- "<span>" +
- Tablesaw.i18n.columnToggleButton +
- "</span></a>"
- );
- $popup = $("<div class='" + this.classes.popup + "' id='" + id + "'></div>");
- $menu = $("<div class='tablesaw-btn-group'></div>");
- this.$popup = $popup;
- var hasNonPersistentHeaders = false;
- this.$headers.each(function() {
- var $this = $(this),
- priority = $this.attr("data-tablesaw-priority"),
- $cells = self.tablesaw._$getCells(this);
- if (priority && priority !== "persist") {
- $cells.addClass(self.classes.priorityPrefix + priority);
- $(cfg.getColumnToggleLabelTemplate($this.text()))
- .appendTo($menu)
- .find('input[type="checkbox"]')
- .data("tablesaw-header", this);
- hasNonPersistentHeaders = true;
- }
- });
- if (!hasNonPersistentHeaders) {
- $menu.append("<label>" + Tablesaw.i18n.columnToggleError + "</label>");
- }
- $menu.appendTo($popup);
- function onToggleCheckboxChange(checkbox) {
- var checked = checkbox.checked;
- var header = self.getHeaderFromCheckbox(checkbox);
- var $cells = self.tablesaw._$getCells(header);
- $cells[!checked ? "addClass" : "removeClass"]("tablesaw-toggle-cellhidden");
- $cells[checked ? "addClass" : "removeClass"]("tablesaw-toggle-cellvisible");
- self.updateColspanCells(header, checked);
- self.$table.trigger("tablesawcolumns");
- }
- // bind change event listeners to inputs - TODO: move to a private method?
- $menu.find('input[type="checkbox"]').on("change", function(e) {
- onToggleCheckboxChange(e.target);
- if (self.set.length) {
- var index;
- $(self.$popup)
- .find("input[type='checkbox']")
- .each(function(j) {
- if (this === e.target) {
- index = j;
- return false;
- }
- });
- $(self.set).each(function() {
- var checkbox = $(this)
- .data(data.key)
- .$popup.find("input[type='checkbox']")
- .get(index);
- if (checkbox) {
- checkbox.checked = e.target.checked;
- onToggleCheckboxChange(checkbox);
- }
- });
- }
- });
- $menuButton.appendTo($btnContain);
- // Use a different target than the toolbar
- var $btnTarget = $(this.$table.attr(this.attributes.btnTarget));
- $btnContain.appendTo($btnTarget.length ? $btnTarget : this.tablesaw.$toolbar);
- function closePopup(event) {
- // Click came from inside the popup, ignore.
- if (event && $(event.target).closest("." + self.classes.popup).length) {
- return;
- }
- $(document).off("click." + tableId);
- $menuButton.removeClass("up").addClass("down");
- $btnContain.removeClass("visible");
- }
- var closeTimeout;
- function openPopup() {
- $btnContain.addClass("visible");
- $menuButton.removeClass("down").addClass("up");
- $(document).off("click." + tableId, closePopup);
- window.clearTimeout(closeTimeout);
- closeTimeout = window.setTimeout(function() {
- $(document).on("click." + tableId, closePopup);
- }, 15);
- }
- $menuButton.on("click.tablesaw", function(event) {
- event.preventDefault();
- if (!$btnContain.is(".visible")) {
- openPopup();
- } else {
- closePopup();
- }
- });
- $popup.appendTo($btnContain);
- this.$menu = $menu;
- // Fix for iOS not rendering shadows correctly when using `-webkit-overflow-scrolling`
- var $overflow = this.$table.closest(".tablesaw-overflow");
- if ($overflow.css("-webkit-overflow-scrolling")) {
- var timeout;
- $overflow.on("scroll", function() {
- var $div = $(this);
- window.clearTimeout(timeout);
- timeout = window.setTimeout(function() {
- $div.css("-webkit-overflow-scrolling", "auto");
- window.setTimeout(function() {
- $div.css("-webkit-overflow-scrolling", "touch");
- }, 0);
- }, 100);
- });
- }
- $(window).on(Tablesaw.events.resize + "." + tableId, function() {
- self.refreshToggle();
- });
- this.initSet();
- this.refreshToggle();
- };
- ColumnToggle.prototype.getHeaderFromCheckbox = function(checkbox) {
- return $(checkbox).data("tablesaw-header");
- };
- ColumnToggle.prototype.refreshToggle = function() {
- var self = this;
- var invisibleColumns = 0;
- this.$menu.find("input").each(function() {
- var header = self.getHeaderFromCheckbox(this);
- this.checked =
- self.tablesaw
- ._$getCells(header)
- .eq(0)
- .css("display") === "table-cell";
- });
- this.updateColspanCells();
- };
- ColumnToggle.prototype.updateColspanCells = function(header, userAction) {
- this.tablesaw.updateColspanCells("tablesaw-toggle-cellhidden", header, userAction);
- };
- ColumnToggle.prototype.destroy = function() {
- this.$table.removeClass(this.classes.columnToggleTable);
- this.$table.find("th, td").each(function() {
- var $cell = $(this);
- $cell.removeClass("tablesaw-toggle-cellhidden").removeClass("tablesaw-toggle-cellvisible");
- this.className = this.className.replace(/\bui\-table\-priority\-\d\b/g, "");
- });
- };
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- if (tablesaw.mode === "columntoggle") {
- var table = new ColumnToggle(tablesaw.table);
- table.init();
- }
- });
- $(document).on(Tablesaw.events.destroy, function(e, tablesaw) {
- if (tablesaw.mode === "columntoggle") {
- $(tablesaw.table)
- .data(data.key)
- .destroy();
- }
- });
- $(document).on(Tablesaw.events.refresh, function(e, tablesaw) {
- if (tablesaw.mode === "columntoggle") {
- $(tablesaw.table)
- .data(data.key)
- .refreshToggle();
- }
- });
- Tablesaw.ColumnToggle = ColumnToggle;
- })();
- (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 ? "↑" : "(A-Z)") +
- "</option>"
- );
- html.push(
- "<option" +
- (isDefaultCol && isDescending ? " selected" : "") +
- ' value="' +
- j +
- '_desc">' +
- $t.text() +
- " " +
- (isNumeric ? "↓" : "(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
- })();
- (function() {
- var classes = {
- hideBtn: "disabled",
- persistWidths: "tablesaw-fix-persist",
- hiddenCol: "tablesaw-swipe-cellhidden",
- persistCol: "tablesaw-swipe-cellpersist",
- allColumnsVisible: "tablesaw-all-cols-visible"
- };
- var attrs = {
- disableTouchEvents: "data-tablesaw-no-touch",
- ignorerow: "data-tablesaw-ignorerow",
- subrow: "data-tablesaw-subrow"
- };
- function createSwipeTable(tbl, $table) {
- var tblsaw = $table.data("tablesaw");
- var $btns = $("<div class='tablesaw-advance'></div>");
- // TODO next major version: remove .btn
- var $prevBtn = $(
- "<a href='#' class='btn tablesaw-nav-btn tablesaw-btn btn-micro left'>" +
- Tablesaw.i18n.swipePreviousColumn +
- "</a>"
- ).appendTo($btns);
- // TODO next major version: remove .btn
- var $nextBtn = $(
- "<a href='#' class='btn tablesaw-nav-btn tablesaw-btn btn-micro right'>" +
- Tablesaw.i18n.swipeNextColumn +
- "</a>"
- ).appendTo($btns);
- var $headerCells = tbl._getPrimaryHeaderCells();
- var $headerCellsNoPersist = $headerCells.not('[data-tablesaw-priority="persist"]');
- var headerWidths = [];
- var headerWidthsNoPersist = [];
- var $head = $(document.head || "head");
- var tableId = $table.attr("id");
- if (!$headerCells.length) {
- throw new Error("tablesaw swipe: no header cells found.");
- }
- $table.addClass("tablesaw-swipe");
- function initMinHeaderWidths() {
- $table.css({
- width: "1px"
- });
- // remove any hidden columns
- $table.find("." + classes.hiddenCol).removeClass(classes.hiddenCol);
- headerWidths = [];
- headerWidthsNoPersist = [];
- // Calculate initial widths
- $headerCells.each(function() {
- var width = this.offsetWidth;
- headerWidths.push(width);
- if (!isPersistent(this)) {
- headerWidthsNoPersist.push(width);
- }
- });
- // reset props
- $table.css({
- width: ""
- });
- }
- initMinHeaderWidths();
- $btns.appendTo(tblsaw.$toolbar);
- if (!tableId) {
- tableId = "tableswipe-" + Math.round(Math.random() * 10000);
- $table.attr("id", tableId);
- }
- function showColumn(headerCell) {
- tblsaw._$getCells(headerCell).removeClass(classes.hiddenCol);
- }
- function hideColumn(headerCell) {
- tblsaw._$getCells(headerCell).addClass(classes.hiddenCol);
- }
- function persistColumn(headerCell) {
- tblsaw._$getCells(headerCell).addClass(classes.persistCol);
- }
- function isPersistent(headerCell) {
- return $(headerCell).is('[data-tablesaw-priority="persist"]');
- }
- function unmaintainWidths() {
- $table.removeClass(classes.persistWidths);
- $("#" + tableId + "-persist").remove();
- }
- function maintainWidths() {
- var prefix = "#" + tableId + ".tablesaw-swipe ";
- var styles = [];
- var tableWidth = $table.width();
- var tableWidthNoPersistantColumns = tableWidth;
- var hash = [];
- var newHash;
- // save persistent column widths (as long as they take up less than 75% of table width)
- $headerCells.each(function(index) {
- var width;
- if (isPersistent(this)) {
- width = this.offsetWidth;
- tableWidthNoPersistantColumns -= width;
- if (width < tableWidth * 0.75) {
- hash.push(index + "-" + width);
- styles.push(
- prefix +
- " ." +
- classes.persistCol +
- ":nth-child(" +
- (index + 1) +
- ") { width: " +
- width +
- "px; }"
- );
- }
- }
- });
- newHash = hash.join("_");
- if (styles.length) {
- $table.addClass(classes.persistWidths);
- var $style = $("#" + tableId + "-persist");
- // If style element not yet added OR if the widths have changed
- if (!$style.length || $style.data("tablesaw-hash") !== newHash) {
- // Remove existing
- $style.remove();
- $("<style>" + styles.join("\n") + "</style>")
- .attr("id", tableId + "-persist")
- .data("tablesaw-hash", newHash)
- .appendTo($head);
- }
- }
- return tableWidthNoPersistantColumns;
- }
- function getNext() {
- var next = [];
- var checkFound;
- $headerCellsNoPersist.each(function(i) {
- var $t = $(this);
- var isHidden = $t.css("display") === "none" || $t.is("." + classes.hiddenCol);
- if (!isHidden && !checkFound) {
- checkFound = true;
- next[0] = i;
- } else if (isHidden && checkFound) {
- next[1] = i;
- return false;
- }
- });
- return next;
- }
- function getPrev() {
- var next = getNext();
- return [next[1] - 1, next[0] - 1];
- }
- function canNavigate(pair) {
- return pair[1] > -1 && pair[1] < $headerCellsNoPersist.length;
- }
- function matchesMedia() {
- var matchMedia = $table.attr("data-tablesaw-swipe-media");
- return !matchMedia || ("matchMedia" in window && window.matchMedia(matchMedia).matches);
- }
- function fakeBreakpoints() {
- if (!matchesMedia()) {
- return;
- }
- var containerWidth = $table.parent().width(),
- persist = [],
- sum = 0,
- sums = [],
- visibleNonPersistantCount = $headerCells.length;
- $headerCells.each(function(index) {
- var $t = $(this),
- isPersist = $t.is('[data-tablesaw-priority="persist"]');
- persist.push(isPersist);
- sum += headerWidths[index];
- sums.push(sum);
- // is persistent or is hidden
- if (isPersist || sum > containerWidth) {
- visibleNonPersistantCount--;
- }
- });
- // We need at least one column to swipe.
- var needsNonPersistentColumn = visibleNonPersistantCount === 0;
- $headerCells.each(function(index) {
- if (sums[index] > containerWidth) {
- hideColumn(this);
- }
- });
- var firstPersist = true;
- $headerCells.each(function(index) {
- if (persist[index]) {
- // for visual box-shadow
- persistColumn(this);
- if (firstPersist) {
- tblsaw._$getCells(this).css("width", sums[index] + "px");
- firstPersist = false;
- }
- return;
- }
- if (sums[index] <= containerWidth || needsNonPersistentColumn) {
- needsNonPersistentColumn = false;
- showColumn(this);
- tblsaw.updateColspanCells(classes.hiddenCol, this, true);
- }
- });
- unmaintainWidths();
- $table.trigger("tablesawcolumns");
- }
- function goForward() {
- navigate(true);
- }
- function goBackward() {
- navigate(false);
- }
- function navigate(isNavigateForward) {
- var pair;
- if (isNavigateForward) {
- pair = getNext();
- } else {
- pair = getPrev();
- }
- if (canNavigate(pair)) {
- if (isNaN(pair[0])) {
- if (isNavigateForward) {
- pair[0] = 0;
- } else {
- pair[0] = $headerCellsNoPersist.length - 1;
- }
- }
- var roomForColumnsWidth = maintainWidths();
- var hideColumnIndex = pair[0];
- var showColumnIndex = pair[1];
- // Hide one column, show one or more based on how much space was freed up
- var columnToShow;
- var columnToHide = $headerCellsNoPersist.get(hideColumnIndex);
- var wasAtLeastOneColumnShown = false;
- var atLeastOneColumnIsVisible = false;
- hideColumn(columnToHide);
- tblsaw.updateColspanCells(classes.hiddenCol, columnToHide, true);
- var columnIndex = hideColumnIndex + (isNavigateForward ? 1 : -1);
- while (columnIndex >= 0 && columnIndex < headerWidthsNoPersist.length) {
- roomForColumnsWidth -= headerWidthsNoPersist[columnIndex];
- var $columnToShow = $headerCellsNoPersist.eq(columnIndex);
- if ($columnToShow.is(".tablesaw-swipe-cellhidden")) {
- if (roomForColumnsWidth > 0) {
- columnToShow = $columnToShow.get(0);
- wasAtLeastOneColumnShown = true;
- atLeastOneColumnIsVisible = true;
- showColumn(columnToShow);
- tblsaw.updateColspanCells(classes.hiddenCol, columnToShow, false);
- }
- } else {
- atLeastOneColumnIsVisible = true;
- }
- if (isNavigateForward) {
- columnIndex++;
- } else {
- columnIndex--;
- }
- }
- if (!atLeastOneColumnIsVisible) {
- // if no columns are showing, at least show the first one we were aiming for.
- columnToShow = $headerCellsNoPersist.get(showColumnIndex);
- showColumn(columnToShow);
- tblsaw.updateColspanCells(classes.hiddenCol, columnToShow, false);
- } else if (
- !wasAtLeastOneColumnShown &&
- canNavigate(isNavigateForward ? getNext() : getPrev())
- ) {
- // if our one new column was hidden but no new columns were shown, let’s navigate again automatically.
- navigate(isNavigateForward);
- }
- $table.trigger("tablesawcolumns");
- }
- }
- $prevBtn.add($nextBtn).on("click", function(e) {
- if (!!$(e.target).closest($nextBtn).length) {
- goForward();
- } else {
- goBackward();
- }
- e.preventDefault();
- });
- function getCoord(event, key) {
- return (event.touches || event.originalEvent.touches)[0][key];
- }
- if (!$table.is("[" + attrs.disableTouchEvents + "]")) {
- $table.on("touchstart.swipetoggle", function(e) {
- var originX = getCoord(e, "pageX");
- var originY = getCoord(e, "pageY");
- var x;
- var y;
- var scrollTop = window.pageYOffset;
- $(window).off(Tablesaw.events.resize, fakeBreakpoints);
- $(this)
- .on("touchmove.swipetoggle", function(e) {
- x = getCoord(e, "pageX");
- y = getCoord(e, "pageY");
- })
- .on("touchend.swipetoggle", function() {
- var cfg = tbl.getConfig({
- swipeHorizontalThreshold: 30,
- swipeVerticalThreshold: 30
- });
- // This config code is a little awkward because shoestring doesn’t support deep $.extend
- // Trying to work around when devs only override one of (not both) horizontalThreshold or
- // verticalThreshold in their TablesawConfig.
- // @TODO major version bump: remove cfg.swipe, move to just use the swipePrefix keys
- var verticalThreshold = cfg.swipe
- ? cfg.swipe.verticalThreshold
- : cfg.swipeVerticalThreshold;
- var horizontalThreshold = cfg.swipe
- ? cfg.swipe.horizontalThreshold
- : cfg.swipeHorizontalThreshold;
- var isPageScrolled = Math.abs(window.pageYOffset - scrollTop) >= verticalThreshold;
- var isVerticalSwipe = Math.abs(y - originY) >= verticalThreshold;
- if (!isVerticalSwipe && !isPageScrolled) {
- if (x - originX < -1 * horizontalThreshold) {
- goForward();
- }
- if (x - originX > horizontalThreshold) {
- goBackward();
- }
- }
- window.setTimeout(function() {
- $(window).on(Tablesaw.events.resize, fakeBreakpoints);
- }, 300);
- $(this).off("touchmove.swipetoggle touchend.swipetoggle");
- });
- });
- }
- $table
- .on("tablesawcolumns.swipetoggle", function() {
- var canGoPrev = canNavigate(getPrev());
- var canGoNext = canNavigate(getNext());
- $prevBtn[canGoPrev ? "removeClass" : "addClass"](classes.hideBtn);
- $nextBtn[canGoNext ? "removeClass" : "addClass"](classes.hideBtn);
- tblsaw.$toolbar[!canGoPrev && !canGoNext ? "addClass" : "removeClass"](
- classes.allColumnsVisible
- );
- })
- .on("tablesawnext.swipetoggle", function() {
- goForward();
- })
- .on("tablesawprev.swipetoggle", function() {
- goBackward();
- })
- .on(Tablesaw.events.destroy + ".swipetoggle", function() {
- var $t = $(this);
- $t.removeClass("tablesaw-swipe");
- tblsaw.$toolbar.find(".tablesaw-advance").remove();
- $(window).off(Tablesaw.events.resize, fakeBreakpoints);
- $t.off(".swipetoggle");
- })
- .on(Tablesaw.events.refresh, function() {
- unmaintainWidths();
- initMinHeaderWidths();
- fakeBreakpoints();
- });
- fakeBreakpoints();
- $(window).on(Tablesaw.events.resize, fakeBreakpoints);
- }
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- if (tablesaw.mode === "swipe") {
- createSwipeTable(tablesaw, tablesaw.$table);
- }
- });
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var MiniMap = {
- attr: {
- init: "data-tablesaw-minimap"
- },
- show: function(table) {
- var mq = table.getAttribute(MiniMap.attr.init);
- if (mq === "") {
- // value-less but exists
- return true;
- } else if (mq && "matchMedia" in window) {
- // has a mq value
- return window.matchMedia(mq).matches;
- }
- return false;
- }
- };
- function createMiniMap($table) {
- var tblsaw = $table.data("tablesaw");
- var $btns = $('<div class="tablesaw-advance minimap">');
- var $dotNav = $('<ul class="tablesaw-advance-dots">').appendTo($btns);
- var hideDot = "tablesaw-advance-dots-hide";
- var $headerCells = $table.data("tablesaw")._getPrimaryHeaderCells();
- // populate dots
- $headerCells.each(function() {
- $dotNav.append("<li><i></i></li>");
- });
- $btns.appendTo(tblsaw.$toolbar);
- function showHideNav() {
- if (!MiniMap.show($table[0])) {
- $btns.css("display", "none");
- return;
- }
- $btns.css("display", "block");
- // show/hide dots
- var dots = $dotNav.find("li").removeClass(hideDot);
- $table.find("thead th").each(function(i) {
- if ($(this).css("display") === "none") {
- dots.eq(i).addClass(hideDot);
- }
- });
- }
- // run on init and resize
- showHideNav();
- $(window).on(Tablesaw.events.resize, showHideNav);
- $table
- .on("tablesawcolumns.minimap", function() {
- showHideNav();
- })
- .on(Tablesaw.events.destroy + ".minimap", function() {
- var $t = $(this);
- tblsaw.$toolbar.find(".tablesaw-advance").remove();
- $(window).off(Tablesaw.events.resize, showHideNav);
- $t.off(".minimap");
- });
- }
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- if (
- (tablesaw.mode === "swipe" || tablesaw.mode === "columntoggle") &&
- tablesaw.$table.is("[ " + MiniMap.attr.init + "]")
- ) {
- createMiniMap(tablesaw.$table);
- }
- });
- // TODO OOP this better
- Tablesaw.MiniMap = MiniMap;
- })();
- (function() {
- var S = {
- selectors: {
- init: "table[data-tablesaw-mode-switch]"
- },
- attributes: {
- excludeMode: "data-tablesaw-mode-exclude"
- },
- classes: {
- main: "tablesaw-modeswitch",
- toolbar: "tablesaw-bar-section"
- },
- modes: ["stack", "swipe", "columntoggle"],
- init: function(table) {
- var $table = $(table);
- var tblsaw = $table.data("tablesaw");
- var ignoreMode = $table.attr(S.attributes.excludeMode);
- var $toolbar = tblsaw.$toolbar;
- var $switcher = $("<div>").addClass(S.classes.main + " " + S.classes.toolbar);
- var html = [
- '<label><span class="abbreviated">' +
- Tablesaw.i18n.modeSwitchColumnsAbbreviated +
- '</span><span class="longform">' +
- Tablesaw.i18n.modeSwitchColumns +
- "</span>:"
- ],
- dataMode = $table.attr("data-tablesaw-mode"),
- isSelected;
- // TODO next major version: remove .btn
- html.push('<span class="btn tablesaw-btn"><select>');
- for (var j = 0, k = S.modes.length; j < k; j++) {
- if (ignoreMode && ignoreMode.toLowerCase() === S.modes[j]) {
- continue;
- }
- isSelected = dataMode === S.modes[j];
- html.push(
- "<option" +
- (isSelected ? " selected" : "") +
- ' value="' +
- S.modes[j] +
- '">' +
- Tablesaw.i18n.modes[j] +
- "</option>"
- );
- }
- html.push("</select></span></label>");
- $switcher.html(html.join(""));
- var $otherToolbarItems = $toolbar.find(".tablesaw-advance").eq(0);
- if ($otherToolbarItems.length) {
- $switcher.insertBefore($otherToolbarItems);
- } else {
- $switcher.appendTo($toolbar);
- }
- $switcher.find(".tablesaw-btn").tablesawbtn();
- $switcher.find("select").on("change", function(event) {
- return S.onModeChange.call(table, event, $(this).val());
- });
- },
- onModeChange: function(event, val) {
- var $table = $(this);
- var tblsaw = $table.data("tablesaw");
- var $switcher = tblsaw.$toolbar.find("." + S.classes.main);
- $switcher.remove();
- tblsaw.destroy();
- $table.attr("data-tablesaw-mode", val);
- $table.tablesaw();
- }
- };
- $(document).on(Tablesaw.events.create, function(e, Tablesaw) {
- if (Tablesaw.$table.is(S.selectors.init)) {
- S.init(Tablesaw.table);
- }
- });
- // TODO OOP this and add to Tablesaw object
- })();
- (function() {
- var pluginName = "tablesawCheckAll";
- function CheckAll(tablesaw) {
- this.tablesaw = tablesaw;
- this.$table = tablesaw.$table;
- this.attr = "data-tablesaw-checkall";
- this.checkAllSelector = "[" + this.attr + "]";
- this.forceCheckedSelector = "[" + this.attr + "-checked]";
- this.forceUncheckedSelector = "[" + this.attr + "-unchecked]";
- this.checkboxSelector = 'input[type="checkbox"]';
- this.$triggers = null;
- this.$checkboxes = null;
- if (this.$table.data(pluginName)) {
- return;
- }
- this.$table.data(pluginName, this);
- this.init();
- }
- CheckAll.prototype._filterCells = function($checkboxes) {
- return $checkboxes
- .filter(function() {
- return !$(this)
- .closest("tr")
- .is("[data-tablesaw-subrow],[data-tablesaw-ignorerow]");
- })
- .find(this.checkboxSelector)
- .not(this.checkAllSelector);
- };
- // With buttons you can use a scoping selector like: data-tablesaw-checkall="#my-scoped-id input[type='checkbox']"
- CheckAll.prototype.getCheckboxesForButton = function(button) {
- return this._filterCells($($(button).attr(this.attr)));
- };
- CheckAll.prototype.getCheckboxesForCheckbox = function(checkbox) {
- return this._filterCells($($(checkbox).closest("th")[0].cells));
- };
- CheckAll.prototype.init = function() {
- var self = this;
- this.$table.find(this.checkAllSelector).each(function() {
- var $trigger = $(this);
- if ($trigger.is(self.checkboxSelector)) {
- self.addCheckboxEvents(this);
- } else {
- self.addButtonEvents(this);
- }
- });
- };
- CheckAll.prototype.addButtonEvents = function(trigger) {
- var self = this;
- // Update body checkboxes when header checkbox is changed
- $(trigger).on("click", function(event) {
- event.preventDefault();
- var $checkboxes = self.getCheckboxesForButton(this);
- var allChecked = true;
- $checkboxes.each(function() {
- if (!this.checked) {
- allChecked = false;
- }
- });
- var setChecked;
- if ($(this).is(self.forceCheckedSelector)) {
- setChecked = true;
- } else if ($(this).is(self.forceUncheckedSelector)) {
- setChecked = false;
- } else {
- setChecked = allChecked ? false : true;
- }
- $checkboxes.each(function() {
- this.checked = setChecked;
- $(this).trigger("change." + pluginName);
- });
- });
- };
- CheckAll.prototype.addCheckboxEvents = function(trigger) {
- var self = this;
- // Update body checkboxes when header checkbox is changed
- $(trigger).on("change", function() {
- var setChecked = this.checked;
- self.getCheckboxesForCheckbox(this).each(function() {
- this.checked = setChecked;
- });
- });
- var $checkboxes = self.getCheckboxesForCheckbox(trigger);
- // Update header checkbox when body checkboxes are changed
- $checkboxes.on("change." + pluginName, function() {
- var checkedCount = 0;
- $checkboxes.each(function() {
- if (this.checked) {
- checkedCount++;
- }
- });
- var allSelected = checkedCount === $checkboxes.length;
- trigger.checked = allSelected;
- // only indeterminate if some are selected (not all and not none)
- trigger.indeterminate = checkedCount !== 0 && !allSelected;
- });
- };
- // on tablecreate, init
- $(document).on(Tablesaw.events.create, function(e, tablesaw) {
- new CheckAll(tablesaw);
- });
- Tablesaw.CheckAll = CheckAll;
- })();
- return Tablesaw;
- }));
|