comparison core/misc/tableresponsive.es6.js @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children a9cd425dd02b
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 /**
2 * @file
3 * Responsive table functionality.
4 */
5
6 (function ($, Drupal, window) {
7 /**
8 * Attach the tableResponsive function to {@link Drupal.behaviors}.
9 *
10 * @type {Drupal~behavior}
11 *
12 * @prop {Drupal~behaviorAttach} attach
13 * Attaches tableResponsive functionality.
14 */
15 Drupal.behaviors.tableResponsive = {
16 attach(context, settings) {
17 const $tables = $(context).find('table.responsive-enabled').once('tableresponsive');
18 if ($tables.length) {
19 const il = $tables.length;
20 for (let i = 0; i < il; i++) {
21 TableResponsive.tables.push(new TableResponsive($tables[i]));
22 }
23 }
24 },
25 };
26
27 /**
28 * The TableResponsive object optimizes table presentation for screen size.
29 *
30 * A responsive table hides columns at small screen sizes, leaving the most
31 * important columns visible to the end user. Users should not be prevented
32 * from accessing all columns, however. This class adds a toggle to a table
33 * with hidden columns that exposes the columns. Exposing the columns will
34 * likely break layouts, but it provides the user with a means to access
35 * data, which is a guiding principle of responsive design.
36 *
37 * @constructor Drupal.TableResponsive
38 *
39 * @param {HTMLElement} table
40 * The table element to initialize the responsive table on.
41 */
42 function TableResponsive(table) {
43 this.table = table;
44 this.$table = $(table);
45 this.showText = Drupal.t('Show all columns');
46 this.hideText = Drupal.t('Hide lower priority columns');
47 // Store a reference to the header elements of the table so that the DOM is
48 // traversed only once to find them.
49 this.$headers = this.$table.find('th');
50 // Add a link before the table for users to show or hide weight columns.
51 this.$link = $('<button type="button" class="link tableresponsive-toggle"></button>')
52 .attr('title', Drupal.t('Show table cells that were hidden to make the table fit within a small screen.'))
53 .on('click', $.proxy(this, 'eventhandlerToggleColumns'));
54
55 this.$table.before($('<div class="tableresponsive-toggle-columns"></div>').append(this.$link));
56
57 // Attach a resize handler to the window.
58 $(window)
59 .on('resize.tableresponsive', $.proxy(this, 'eventhandlerEvaluateColumnVisibility'))
60 .trigger('resize.tableresponsive');
61 }
62
63 /**
64 * Extend the TableResponsive function with a list of managed tables.
65 */
66 $.extend(TableResponsive, /** @lends Drupal.TableResponsive */{
67
68 /**
69 * Store all created instances.
70 *
71 * @type {Array.<Drupal.TableResponsive>}
72 */
73 tables: [],
74 });
75
76 /**
77 * Associates an action link with the table that will show hidden columns.
78 *
79 * Columns are assumed to be hidden if their header has the class priority-low
80 * or priority-medium.
81 */
82 $.extend(TableResponsive.prototype, /** @lends Drupal.TableResponsive# */{
83
84 /**
85 * @param {jQuery.Event} e
86 * The event triggered.
87 */
88 eventhandlerEvaluateColumnVisibility(e) {
89 const pegged = parseInt(this.$link.data('pegged'), 10);
90 const hiddenLength = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden').length;
91 // If the table has hidden columns, associate an action link with the
92 // table to show the columns.
93 if (hiddenLength > 0) {
94 this.$link.show().text(this.showText);
95 }
96 // When the toggle is pegged, its presence is maintained because the user
97 // has interacted with it. This is necessary to keep the link visible if
98 // the user adjusts screen size and changes the visibility of columns.
99 if (!pegged && hiddenLength === 0) {
100 this.$link.hide().text(this.hideText);
101 }
102 },
103
104 /**
105 * Toggle the visibility of columns based on their priority.
106 *
107 * Columns are classed with either 'priority-low' or 'priority-medium'.
108 *
109 * @param {jQuery.Event} e
110 * The event triggered.
111 */
112 eventhandlerToggleColumns(e) {
113 e.preventDefault();
114 const self = this;
115 const $hiddenHeaders = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden');
116 this.$revealedCells = this.$revealedCells || $();
117 // Reveal hidden columns.
118 if ($hiddenHeaders.length > 0) {
119 $hiddenHeaders.each(function (index, element) {
120 const $header = $(this);
121 const position = $header.prevAll('th').length;
122 self.$table.find('tbody tr').each(function () {
123 const $cells = $(this).find('td').eq(position);
124 $cells.show();
125 // Keep track of the revealed cells, so they can be hidden later.
126 self.$revealedCells = $().add(self.$revealedCells).add($cells);
127 });
128 $header.show();
129 // Keep track of the revealed headers, so they can be hidden later.
130 self.$revealedCells = $().add(self.$revealedCells).add($header);
131 });
132 this.$link.text(this.hideText).data('pegged', 1);
133 }
134 // Hide revealed columns.
135 else {
136 this.$revealedCells.hide();
137 // Strip the 'display:none' declaration from the style attributes of
138 // the table cells that .hide() added.
139 this.$revealedCells.each(function (index, element) {
140 const $cell = $(this);
141 const properties = $cell.attr('style').split(';');
142 const newProps = [];
143 // The hide method adds display none to the element. The element
144 // should be returned to the same state it was in before the columns
145 // were revealed, so it is necessary to remove the display none value
146 // from the style attribute.
147 const match = /^display\s*:\s*none$/;
148 for (let i = 0; i < properties.length; i++) {
149 const prop = properties[i];
150 prop.trim();
151 // Find the display:none property and remove it.
152 const isDisplayNone = match.exec(prop);
153 if (isDisplayNone) {
154 continue;
155 }
156 newProps.push(prop);
157 }
158 // Return the rest of the style attribute values to the element.
159 $cell.attr('style', newProps.join(';'));
160 });
161 this.$link.text(this.showText).data('pegged', 0);
162 // Refresh the toggle link.
163 $(window).trigger('resize.tableresponsive');
164 }
165 },
166 });
167
168 // Make the TableResponsive object available in the Drupal namespace.
169 Drupal.TableResponsive = TableResponsive;
170 }(jQuery, Drupal, window));