0
|
1 /*
|
|
2 * tablesaw: A set of plugins for responsive tables
|
|
3 * Stack: switches from column layout to rows with inline labels
|
|
4 * Copyright (c) 2013 Filament Group, Inc.
|
|
5 * MIT License
|
|
6 */
|
|
7
|
|
8 (function() {
|
|
9 var classes = {
|
|
10 stackTable: "tablesaw-stack",
|
|
11 cellLabels: "tablesaw-cell-label",
|
|
12 cellContentLabels: "tablesaw-cell-content"
|
|
13 };
|
|
14
|
|
15 var data = {
|
|
16 key: "tablesaw-stack"
|
|
17 };
|
|
18
|
|
19 var attrs = {
|
|
20 labelless: "data-tablesaw-no-labels",
|
|
21 hideempty: "data-tablesaw-hide-empty"
|
|
22 };
|
|
23
|
|
24 var Stack = function(element, tablesaw) {
|
|
25 this.tablesaw = tablesaw;
|
|
26 this.$table = $(element);
|
|
27
|
|
28 this.labelless = this.$table.is("[" + attrs.labelless + "]");
|
|
29 this.hideempty = this.$table.is("[" + attrs.hideempty + "]");
|
|
30
|
|
31 this.$table.data(data.key, this);
|
|
32 };
|
|
33
|
|
34 Stack.prototype.init = function() {
|
|
35 this.$table.addClass(classes.stackTable);
|
|
36
|
|
37 if (this.labelless) {
|
|
38 return;
|
|
39 }
|
|
40
|
|
41 var self = this;
|
|
42
|
|
43 this.$table
|
|
44 .find("th, td")
|
|
45 .filter(function() {
|
|
46 return !$(this).closest("thead").length;
|
|
47 })
|
|
48 .filter(function() {
|
|
49 return (
|
|
50 !$(this)
|
|
51 .closest("tr")
|
|
52 .is("[" + attrs.labelless + "]") &&
|
|
53 (!self.hideempty || !!$(this).html())
|
|
54 );
|
|
55 })
|
|
56 .each(function() {
|
|
57 var $newHeader = $(document.createElement("b")).addClass(classes.cellLabels);
|
|
58 var $cell = $(this);
|
|
59
|
|
60 $(self.tablesaw._findPrimaryHeadersForCell(this)).each(function(index) {
|
|
61 var $header = $(this.cloneNode(true));
|
|
62 // TODO decouple from sortable better
|
|
63 // Changed from .text() in https://github.com/filamentgroup/tablesaw/commit/b9c12a8f893ec192830ec3ba2d75f062642f935b
|
|
64 // to preserve structural html in headers, like <a>
|
|
65 var $sortableButton = $header.find(".tablesaw-sortable-btn");
|
|
66 $header.find(".tablesaw-sortable-arrow").remove();
|
|
67
|
|
68 // TODO decouple from checkall better
|
|
69 var $checkall = $header.find("[data-tablesaw-checkall]");
|
|
70 $checkall.closest("label").remove();
|
|
71 if ($checkall.length) {
|
|
72 $newHeader = $([]);
|
|
73 return;
|
|
74 }
|
|
75
|
|
76 if (index > 0) {
|
|
77 $newHeader.append(document.createTextNode(", "));
|
|
78 }
|
|
79 $newHeader.append(
|
|
80 $sortableButton.length ? $sortableButton[0].childNodes : $header[0].childNodes
|
|
81 );
|
|
82 });
|
|
83
|
|
84 if ($newHeader.length && !$cell.find("." + classes.cellContentLabels).length) {
|
|
85 $cell.wrapInner("<span class='" + classes.cellContentLabels + "'></span>");
|
|
86 }
|
|
87
|
|
88 // Update if already exists.
|
|
89 var $label = $cell.find("." + classes.cellLabels);
|
|
90 if (!$label.length) {
|
|
91 $cell.prepend($newHeader);
|
|
92 } else {
|
|
93 // only if changed
|
|
94 $label.replaceWith($newHeader);
|
|
95 }
|
|
96 });
|
|
97 };
|
|
98
|
|
99 Stack.prototype.destroy = function() {
|
|
100 this.$table.removeClass(classes.stackTable);
|
|
101 this.$table.find("." + classes.cellLabels).remove();
|
|
102 this.$table.find("." + classes.cellContentLabels).each(function() {
|
|
103 $(this).replaceWith(this.childNodes);
|
|
104 });
|
|
105 };
|
|
106
|
|
107 // on tablecreate, init
|
|
108 $(document)
|
|
109 .on(Tablesaw.events.create, function(e, tablesaw) {
|
|
110 if (tablesaw.mode === "stack") {
|
|
111 var table = new Stack(tablesaw.table, tablesaw);
|
|
112 table.init();
|
|
113 }
|
|
114 })
|
|
115 .on(Tablesaw.events.refresh, function(e, tablesaw) {
|
|
116 if (tablesaw.mode === "stack") {
|
|
117 $(tablesaw.table)
|
|
118 .data(data.key)
|
|
119 .init();
|
|
120 }
|
|
121 })
|
|
122 .on(Tablesaw.events.destroy, function(e, tablesaw) {
|
|
123 if (tablesaw.mode === "stack") {
|
|
124 $(tablesaw.table)
|
|
125 .data(data.key)
|
|
126 .destroy();
|
|
127 }
|
|
128 });
|
|
129
|
|
130 Tablesaw.Stack = Stack;
|
|
131 })();
|