annotate core/misc/tableresponsive.es6.js @ 19:fa3358dc1485 tip

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