123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076 |
- /*! Tablesaw - v3.0.9 - 2018-02-14
- * https://github.com/filamentgroup/tablesaw
- * Copyright (c) 2018 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;
- var domContentLoadedTriggered = false;
- 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) {
- 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 $headers = this._getPrimaryHeaderCells($headerRow);
- 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($headers[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) {
- $(e.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)
- .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($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='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)
- .refreshPriority();
- }
- });
- 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 $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 = [];
- // Calculate initial widths
- $headerCells.each(function() {
- headerWidths.push(this.offsetWidth);
- });
- // 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 ",
- styles = [],
- tableWidth = $table.width(),
- hash = [],
- 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;
- 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);
- }
- }
- }
- function getNext() {
- var next = [],
- checkFound;
- $headerCellsNoPersist.each(function(i) {
- var $t = $(this),
- 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 nextpair(fwd) {
- return fwd ? getNext() : getPrev();
- }
- function canAdvance(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);
- }
- });
- $headerCells.each(function(index) {
- if (persist[index]) {
- // for visual box-shadow
- persistColumn(this);
- return;
- }
- if (sums[index] <= containerWidth || needsNonPersistentColumn) {
- needsNonPersistentColumn = false;
- showColumn(this);
- tblsaw.updateColspanCells(classes.hiddenCol, this, true);
- }
- });
- unmaintainWidths();
- $table.trigger("tablesawcolumns");
- }
- function advance(fwd) {
- var pair = nextpair(fwd);
- if (canAdvance(pair)) {
- if (isNaN(pair[0])) {
- if (fwd) {
- pair[0] = 0;
- } else {
- pair[0] = $headerCellsNoPersist.length - 1;
- }
- }
- // TODO just blindly hiding the previous column and showing the next column can result in
- // column content overflow
- maintainWidths();
- hideColumn($headerCellsNoPersist.get(pair[0]));
- tblsaw.updateColspanCells(classes.hiddenCol, $headerCellsNoPersist.get(pair[0]), false);
- showColumn($headerCellsNoPersist.get(pair[1]));
- tblsaw.updateColspanCells(classes.hiddenCol, $headerCellsNoPersist.get(pair[1]), true);
- $table.trigger("tablesawcolumns");
- }
- }
- $prevBtn.add($nextBtn).on("click", function(e) {
- advance(!!$(e.target).closest($nextBtn).length);
- 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) {
- advance(true);
- }
- if (x - originX > horizontalThreshold) {
- advance(false);
- }
- }
- window.setTimeout(function() {
- $(window).on(Tablesaw.events.resize, fakeBreakpoints);
- }, 300);
- $(this).off("touchmove.swipetoggle touchend.swipetoggle");
- });
- });
- }
- $table
- .on("tablesawcolumns.swipetoggle", function() {
- var canGoPrev = canAdvance(getPrev());
- var canGoNext = canAdvance(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() {
- advance(true);
- })
- .on("tablesawprev.swipetoggle", function() {
- advance(false);
- })
- .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;
- }));
|