tablesaw-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,93 @@
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( win, $, undefined ){
9
+
10
+ var classes = {
11
+ stackTable: 'tablesaw-stack',
12
+ cellLabels: 'tablesaw-cell-label'
13
+ };
14
+
15
+ var data = {
16
+ obj: 'tablesaw-stack'
17
+ };
18
+
19
+ var attrs = {
20
+ labelless: 'data-no-labels'
21
+ };
22
+
23
+ var Stack = function( element ) {
24
+
25
+ this.$table = $( element );
26
+
27
+ this.labelless = this.$table.is( '[' + attrs.labelless + ']' );
28
+
29
+ if( !this.labelless ) {
30
+ // allHeaders references headers, plus all THs in the thead, which may include several rows, or not
31
+ this.allHeaders = this.$table.find( "th" );
32
+ }
33
+
34
+ this.$table.data( data.obj, this );
35
+ };
36
+
37
+ Stack.prototype.init = function( colstart ) {
38
+ this.$table.addClass( classes.stackTable );
39
+
40
+ if( this.labelless ) {
41
+ return;
42
+ }
43
+
44
+ // get headers in reverse order so that top-level headers are appended last
45
+ var reverseHeaders = $( this.allHeaders );
46
+
47
+ // create the hide/show toggles
48
+ reverseHeaders.each(function(){
49
+ var $cells = $( this.cells ).filter(function() {
50
+ return !$( this ).parent().is( "[" + attrs.labelless + "]" );
51
+ }),
52
+ hierarchyClass = $cells.not( this ).filter( "thead th" ).length && " tablesaw-cell-label-top",
53
+ text = $(this).text();
54
+
55
+ if( text !== "" ){
56
+ if( hierarchyClass ){
57
+ var iteration = parseInt( $( this ).attr( "colspan" ), 10 ),
58
+ filter = "";
59
+
60
+ if( iteration ){
61
+ filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
62
+ }
63
+ $cells.filter( filter ).prepend( "<b class='" + classes.cellLabels + hierarchyClass + "'>" + text + "</b>" );
64
+ } else {
65
+ $cells.prepend( "<b class='" + classes.cellLabels + "'>" + text + "</b>" );
66
+ }
67
+ }
68
+ });
69
+ };
70
+
71
+ Stack.prototype.destroy = function() {
72
+ this.$table.removeClass( classes.stackTable );
73
+ this.$table.find( '.' + classes.cellLabels ).remove();
74
+ };
75
+
76
+ // on tablecreate, init
77
+ $( document ).on( "tablesawcreate", function( e, Tablesaw, colstart ){
78
+ if( Tablesaw.mode === 'stack' ){
79
+ var table = new Stack( Tablesaw.table );
80
+ table.init( colstart );
81
+ }
82
+
83
+ } );
84
+
85
+ $( document ).on( "tablesawdestroy", function( e, Tablesaw ){
86
+
87
+ if( Tablesaw.mode === 'stack' ){
88
+ $( Tablesaw.table ).data( data.obj ).destroy();
89
+ }
90
+
91
+ } );
92
+
93
+ }( this, jQuery ));
@@ -0,0 +1,248 @@
1
+ /*
2
+ * tablesaw: A set of plugins for responsive tables
3
+ * Swipe Toggle: swipe gesture (or buttons) to navigate which columns are shown.
4
+ * Copyright (c) 2013 Filament Group, Inc.
5
+ * MIT License
6
+ */
7
+
8
+ ;(function( win, $, undefined ){
9
+
10
+
11
+ function createSwipeTable( $table ){
12
+
13
+ var $btns = $( "<div class='tablesaw-advance'></div>" ),
14
+ $prevBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro left' title='Previous Column'></a>" ).appendTo( $btns ),
15
+ $nextBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro right' title='Next Column'></a>" ).appendTo( $btns ),
16
+ hideBtn = 'disabled',
17
+ persistWidths = 'tablesaw-fix-persist',
18
+ $headerCells = $table.find( "thead th" ),
19
+ $headerCellsNoPersist = $headerCells.not( '[data-priority="persist"]' ),
20
+ headerWidths = [],
21
+ $head = $( document.head || 'head' ),
22
+ tableId = $table.attr( 'id' ),
23
+ // TODO switch this to an nth-child feature test
24
+ isIE8 = $( 'html' ).is( '.ie-lte8' );
25
+
26
+ if( !$headerCells.length ) {
27
+ throw new Error( "tablesaw swipe: no header cells found. Are you using <th> inside of <thead>?" );
28
+ }
29
+
30
+ // Calculate initial widths
31
+ $table.css('width', 'auto');
32
+ $headerCells.each(function() {
33
+ headerWidths.push( $( this ).outerWidth() );
34
+ });
35
+ $table.css( 'width', '' );
36
+
37
+ $btns.appendTo( $table.prev( '.tablesaw-bar' ) );
38
+
39
+ $table.addClass( "tablesaw-swipe" );
40
+
41
+ if( !tableId ) {
42
+ tableId = 'tableswipe-' + Math.round( Math.random() * 10000 );
43
+ $table.attr( 'id', tableId );
44
+ }
45
+
46
+ function $getCells( headerCell ) {
47
+ return $( headerCell.cells ).add( headerCell );
48
+ }
49
+
50
+ function showColumn( headerCell ) {
51
+ $getCells( headerCell ).removeClass( 'tablesaw-cell-hidden' );
52
+ }
53
+
54
+ function hideColumn( headerCell ) {
55
+ $getCells( headerCell ).addClass( 'tablesaw-cell-hidden' );
56
+ }
57
+
58
+ function persistColumn( headerCell ) {
59
+ $getCells( headerCell ).addClass( 'tablesaw-cell-persist' );
60
+ }
61
+
62
+ function isPersistent( headerCell ) {
63
+ return $( headerCell ).is( '[data-priority="persist"]' );
64
+ }
65
+
66
+ function unmaintainWidths() {
67
+ $table.removeClass( persistWidths );
68
+ $( '#' + tableId + '-persist' ).remove();
69
+ }
70
+
71
+ function maintainWidths() {
72
+ var prefix = '#' + tableId + ' ',
73
+ styles = [],
74
+ tableWidth = $table.width();
75
+
76
+ $headerCells.each(function( index ) {
77
+ var width;
78
+ if( isPersistent( this ) ) {
79
+ width = $( this ).outerWidth();
80
+
81
+ // Only save width on non-greedy columns (take up less than 75% of table width)
82
+ if( width < tableWidth * 0.75 ) {
83
+ styles.push( prefix + ' .tablesaw-cell-persist:nth-child(' + ( index + 1 ) + ') { width: ' + width + 'px; }' );
84
+ }
85
+ }
86
+ });
87
+
88
+ unmaintainWidths();
89
+ $table.addClass( persistWidths );
90
+ $head.append( $( '<style>' + styles.join( "\n" ) + '</style>' ).attr( 'id', tableId + '-persist' ) );
91
+ }
92
+
93
+ function getNext(){
94
+ var next = [],
95
+ checkFound;
96
+
97
+ $headerCellsNoPersist.each(function( i ) {
98
+ var $t = $( this ),
99
+ isHidden = $t.css( "display" ) === "none" || $t.is( ".tablesaw-cell-hidden" );
100
+
101
+ if( !isHidden && !checkFound ) {
102
+ checkFound = true;
103
+ next[ 0 ] = i;
104
+ } else if( isHidden && checkFound ) {
105
+ next[ 1 ] = i;
106
+
107
+ return false;
108
+ }
109
+ });
110
+
111
+ return next;
112
+ }
113
+
114
+ function getPrev(){
115
+ var next = getNext();
116
+ return [ next[ 1 ] - 1 , next[ 0 ] - 1 ];
117
+ }
118
+
119
+ function nextpair( fwd ){
120
+ return fwd ? getNext() : getPrev();
121
+ }
122
+
123
+ function canAdvance( pair ){
124
+ return pair[ 1 ] > -1 && pair[ 1 ] < $headerCellsNoPersist.length;
125
+ }
126
+
127
+ function fakeBreakpoints() {
128
+ var extraPaddingPixels = 20,
129
+ containerWidth = $table.parent().width(),
130
+ sum = 0;
131
+
132
+ $headerCells.each(function( index ) {
133
+ var $t = $( this ),
134
+ isPersist = $t.is( '[data-priority="persist"]' );
135
+ sum += headerWidths[ index ] + ( isPersist ? 0 : extraPaddingPixels );
136
+
137
+ if( isPersist ) {
138
+ // for visual box-shadow
139
+ persistColumn( this );
140
+ return;
141
+ }
142
+
143
+ if( sum > containerWidth ) {
144
+ hideColumn( this );
145
+ } else {
146
+ showColumn( this );
147
+ }
148
+
149
+ });
150
+
151
+ if( !isIE8 ) {
152
+ unmaintainWidths();
153
+ }
154
+ $table.trigger( 'tablesawcolumns' );
155
+ }
156
+
157
+ function advance( fwd ){
158
+ var pair = nextpair( fwd );
159
+ if( canAdvance( pair ) ){
160
+ if( isNaN( pair[ 0 ] ) ){
161
+ if( fwd ){
162
+ pair[0] = 0;
163
+ }
164
+ else {
165
+ pair[0] = $headerCellsNoPersist.length - 1;
166
+ }
167
+ }
168
+
169
+ if( !isIE8 ) {
170
+ maintainWidths();
171
+ }
172
+
173
+ hideColumn( $headerCellsNoPersist.get( pair[ 0 ] ) );
174
+ showColumn( $headerCellsNoPersist.get( pair[ 1 ] ) );
175
+
176
+ $table.trigger( 'tablesawcolumns' );
177
+ }
178
+ }
179
+
180
+ $prevBtn.add( $nextBtn ).click(function( e ){
181
+ advance( !!$( e.target ).closest( $nextBtn ).length );
182
+ e.preventDefault();
183
+ });
184
+
185
+ $table
186
+ .bind( "touchstart.swipetoggle", function( e ){
187
+ var originX = ( e.touches || e.originalEvent.touches )[ 0 ].pageX,
188
+ originY = ( e.touches || e.originalEvent.touches )[ 0 ].pageY,
189
+ x,
190
+ y;
191
+
192
+ $( this )
193
+ .bind( "touchmove", function( e ){
194
+ x = ( e.touches || e.originalEvent.touches )[ 0 ].pageX;
195
+ y = ( e.touches || e.originalEvent.touches )[ 0 ].pageY;
196
+
197
+ if( Math.abs( x - originX ) > 15 && Math.abs( y - originY ) < 20 ) {
198
+ e.preventDefault();
199
+ }
200
+ })
201
+ .bind( "touchend.swipetoggle", function(){
202
+ if( x - originX < 15 ){
203
+ advance( true );
204
+ }
205
+ if( x - originX > -15 ){
206
+ advance( false );
207
+ }
208
+
209
+ $( this ).unbind( "touchmove touchend" );
210
+ });
211
+
212
+ })
213
+ .bind( "tablesawcolumns.swipetoggle", function(){
214
+ $prevBtn[ canAdvance( getPrev() ) ? "removeClass" : "addClass" ]( hideBtn );
215
+ $nextBtn[ canAdvance( getNext() ) ? "removeClass" : "addClass" ]( hideBtn );
216
+ })
217
+ .bind( "tablesawnext.swipetoggle", function(){
218
+ advance( true );
219
+ } )
220
+ .bind( "tablesawprev.swipetoggle", function(){
221
+ advance( false );
222
+ } )
223
+ .bind( "tablesawdestroy.swipetoggle", function(){
224
+ var $t = $( this );
225
+
226
+ $t.removeClass( 'tablesaw-swipe' );
227
+ $t.prev( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
228
+ $( win ).off( "resize", fakeBreakpoints );
229
+
230
+ $t.unbind( ".swipetoggle" );
231
+ });
232
+
233
+ fakeBreakpoints();
234
+ $( win ).on( "resize", fakeBreakpoints );
235
+ }
236
+
237
+
238
+
239
+ // on tablecreate, init
240
+ $( document ).on( "tablesawcreate", function( e, Tablesaw ){
241
+
242
+ if( Tablesaw.mode === 'swipe' ){
243
+ createSwipeTable( Tablesaw.$table );
244
+ }
245
+
246
+ } );
247
+
248
+ }( this, jQuery ));
@@ -0,0 +1,156 @@
1
+ /*
2
+ Styles for the table columntoggle mode
3
+ */
4
+
5
+ /* see Gruntfile.js for grunticon selector */
6
+ .btn.tablesaw-columntoggle-btn {
7
+ float: right;
8
+ }
9
+
10
+ .btn.tablesaw-columntoggle-btn span {
11
+ text-indent: -9999px;
12
+ display: inline-block;
13
+ }
14
+
15
+ .tablesaw-columntoggle-btnwrap .dialog-content {
16
+ padding: .5em;
17
+ }
18
+ .tablesaw-columntoggle tbody td {
19
+ line-height: 1.5;
20
+ }
21
+
22
+
23
+ /* Remove top/bottom margins around the fieldcontain on check list */
24
+ .tablesaw-columntoggle-popup {
25
+ display: none;
26
+ }
27
+ .tablesaw-columntoggle-btnwrap.visible .tablesaw-columntoggle-popup {
28
+ display: block;
29
+ position: absolute;
30
+ top: 2em;
31
+ right: 0;
32
+ background-color: #fff;
33
+ padding: .5em .8em;
34
+ border: 1px solid #ccc;
35
+ box-shadow: 0 1px 2px #ccc;
36
+ border-radius: .2em;
37
+ z-index: 1;
38
+ }
39
+ .tablesaw-columntoggle-popup fieldset {
40
+ margin:0;
41
+ }
42
+
43
+ /* Hide all prioritized columns by default */
44
+ @media only all {
45
+ .tablesaw-columntoggle th.tablesaw-priority-6,
46
+ .tablesaw-columntoggle td.tablesaw-priority-6,
47
+ .tablesaw-columntoggle th.tablesaw-priority-5,
48
+ .tablesaw-columntoggle td.tablesaw-priority-5,
49
+ .tablesaw-columntoggle th.tablesaw-priority-4,
50
+ .tablesaw-columntoggle td.tablesaw-priority-4,
51
+ .tablesaw-columntoggle th.tablesaw-priority-3,
52
+ .tablesaw-columntoggle td.tablesaw-priority-3,
53
+ .tablesaw-columntoggle th.tablesaw-priority-2,
54
+ .tablesaw-columntoggle td.tablesaw-priority-2,
55
+ .tablesaw-columntoggle th.tablesaw-priority-1,
56
+ .tablesaw-columntoggle td.tablesaw-priority-1 {
57
+ display: none;
58
+ }
59
+ }
60
+
61
+ .tablesaw-columntoggle-btnwrap {
62
+ position: relative;
63
+ float: right;
64
+ }
65
+ .tablesaw-columntoggle-btnwrap .dialog-content {
66
+ top: 0 !important;
67
+ right: 1em;
68
+ left: auto !important;
69
+ width: 12em;
70
+ max-width: 18em;
71
+ margin: -.5em auto 0;
72
+ }
73
+ .tablesaw-columntoggle-btnwrap .dialog-content:focus {
74
+ outline-style: none;
75
+ }
76
+
77
+ /* Preset breakpoints if "" class added to table */
78
+
79
+ /* Show priority 1 at 320px (20em x 16px) */
80
+ @media (min-width: 20em) {
81
+ .tablesaw-columntoggle th.tablesaw-priority-1,
82
+ .tablesaw-columntoggle td.tablesaw-priority-1 {
83
+ display: table-cell;
84
+ }
85
+ }
86
+ /* Show priority 2 at 480px (30em x 16px) */
87
+ @media (min-width: 30em) {
88
+ .tablesaw-columntoggle th.tablesaw-priority-2,
89
+ .tablesaw-columntoggle td.tablesaw-priority-2 {
90
+ display: table-cell;
91
+ }
92
+ }
93
+ /* Show priority 3 at 640px (40em x 16px) */
94
+ @media (min-width: 40em) {
95
+ .tablesaw-columntoggle th.tablesaw-priority-3,
96
+ .tablesaw-columntoggle td.tablesaw-priority-3 {
97
+ display: table-cell;
98
+ }
99
+
100
+ .tablesaw-columntoggle tbody td {
101
+ line-height: 2;
102
+ }
103
+ }
104
+ /* Show priority 4 at 800px (50em x 16px) */
105
+ @media (min-width: 50em) {
106
+ .tablesaw-columntoggle th.tablesaw-priority-4,
107
+ .tablesaw-columntoggle td.tablesaw-priority-4 {
108
+ display: table-cell;
109
+ }
110
+ }
111
+ /* Show priority 5 at 960px (60em x 16px) */
112
+ @media (min-width: 60em) {
113
+ .tablesaw-columntoggle th.tablesaw-priority-5,
114
+ .tablesaw-columntoggle td.tablesaw-priority-5 {
115
+ display: table-cell;
116
+ }
117
+ }
118
+ /* Show priority 6 at 1,120px (70em x 16px) */
119
+ @media (min-width: 70em) {
120
+ .tablesaw-columntoggle th.tablesaw-priority-6,
121
+ .tablesaw-columntoggle td.tablesaw-priority-6 {
122
+ display: table-cell;
123
+ }
124
+ }
125
+
126
+ @media only all {
127
+ .tablesaw-swipe .tablesaw-cell-persist {
128
+ border-right: 1px solid #e4e1de;
129
+ }
130
+ .tablesaw-swipe .tablesaw-cell-persist {
131
+ box-shadow: 3px 0 4px -1px #e4e1de;
132
+ }
133
+
134
+ /* Unchecked manually: Always hide */
135
+ .tablesaw-swipe th.tablesaw-cell-hidden,
136
+ .tablesaw-swipe td.tablesaw-cell-hidden,
137
+ .tablesaw-columntoggle th.tablesaw-cell-hidden,
138
+ .tablesaw-columntoggle td.tablesaw-cell-hidden {
139
+ display: none;
140
+ }
141
+
142
+ /* Checked manually: Always show */
143
+ .tablesaw-columntoggle th.tablesaw-cell-visible,
144
+ .tablesaw-columntoggle td.tablesaw-cell-visible {
145
+ display: table-cell;
146
+ }
147
+ }
148
+
149
+ .tablesaw-columntoggle-popup .btn-group > label {
150
+ display: block;
151
+ padding: .2em 0;
152
+ white-space: nowrap;
153
+ }
154
+ .tablesaw-columntoggle-popup .btn-group > label input {
155
+ margin-right: .8em;
156
+ }