169 lines
6.2 KiB
JavaScript
169 lines
6.2 KiB
JavaScript
/**
|
|
* @file
|
|
* Responsive table functionality.
|
|
*/
|
|
|
|
(function ($, Drupal, window) {
|
|
|
|
"use strict";
|
|
|
|
/**
|
|
* Attach the tableResponsive function to {@link Drupal.behaviors}.
|
|
*
|
|
* @type {Drupal~behavior}
|
|
*/
|
|
Drupal.behaviors.tableResponsive = {
|
|
attach: function (context, settings) {
|
|
var $tables = $(context).find('table.responsive-enabled').once('tableresponsive');
|
|
if ($tables.length) {
|
|
var il = $tables.length;
|
|
for (var i = 0; i < il; i++) {
|
|
TableResponsive.tables.push(new TableResponsive($tables[i]));
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* The TableResponsive object optimizes table presentation for screen size.
|
|
*
|
|
* A responsive table hides columns at small screen sizes, leaving the most
|
|
* important columns visible to the end user. Users should not be prevented
|
|
* from accessing all columns, however. This class adds a toggle to a table
|
|
* with hidden columns that exposes the columns. Exposing the columns will
|
|
* likely break layouts, but it provides the user with a means to access
|
|
* data, which is a guiding principle of responsive design.
|
|
*
|
|
* @constructor Drupal.TableResponsive
|
|
*
|
|
* @param {HTMLElement} table
|
|
*/
|
|
function TableResponsive(table) {
|
|
this.table = table;
|
|
this.$table = $(table);
|
|
this.showText = Drupal.t('Show all columns');
|
|
this.hideText = Drupal.t('Hide lower priority columns');
|
|
// Store a reference to the header elements of the table so that the DOM is
|
|
// traversed only once to find them.
|
|
this.$headers = this.$table.find('th');
|
|
// Add a link before the table for users to show or hide weight columns.
|
|
this.$link = $('<button type="button" class="link tableresponsive-toggle"></button>')
|
|
.attr('title', Drupal.t('Show table cells that were hidden to make the table fit within a small screen.'))
|
|
.on('click', $.proxy(this, 'eventhandlerToggleColumns'));
|
|
|
|
this.$table.before($('<div class="tableresponsive-toggle-columns"></div>').append(this.$link));
|
|
|
|
// Attach a resize handler to the window.
|
|
$(window)
|
|
.on('resize.tableresponsive', $.proxy(this, 'eventhandlerEvaluateColumnVisibility'))
|
|
.trigger('resize.tableresponsive');
|
|
}
|
|
|
|
/**
|
|
* Extend the TableResponsive function with a list of managed tables.
|
|
*/
|
|
$.extend(TableResponsive, /** @lends Drupal.TableResponsive */{
|
|
|
|
/**
|
|
* Store all created instances.
|
|
*
|
|
* @type {Array.<Drupal.TableResponsive>}
|
|
*/
|
|
tables: []
|
|
});
|
|
|
|
/**
|
|
* Associates an action link with the table that will show hidden columns.
|
|
*
|
|
* Columns are assumed to be hidden if their header has the class priority-low
|
|
* or priority-medium.
|
|
*/
|
|
$.extend(TableResponsive.prototype, /** @lends Drupal.TableResponsive# */{
|
|
|
|
/**
|
|
* @param {jQuery.Event} e
|
|
*/
|
|
eventhandlerEvaluateColumnVisibility: function (e) {
|
|
var pegged = parseInt(this.$link.data('pegged'), 10);
|
|
var hiddenLength = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden').length;
|
|
// If the table has hidden columns, associate an action link with the
|
|
// table to show the columns.
|
|
if (hiddenLength > 0) {
|
|
this.$link.show().text(this.showText);
|
|
}
|
|
// When the toggle is pegged, its presence is maintained because the user
|
|
// has interacted with it. This is necessary to keep the link visible if
|
|
// the user adjusts screen size and changes the visibility of columns.
|
|
if (!pegged && hiddenLength === 0) {
|
|
this.$link.hide().text(this.hideText);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Toggle the visibility of columns based on their priority.
|
|
*
|
|
* Columns are classed with either 'priority-low' or 'priority-medium'.
|
|
*
|
|
* @param {jQuery.Event} e
|
|
*/
|
|
eventhandlerToggleColumns: function (e) {
|
|
e.preventDefault();
|
|
var self = this;
|
|
var $hiddenHeaders = this.$headers.filter('.priority-medium:hidden, .priority-low:hidden');
|
|
this.$revealedCells = this.$revealedCells || $();
|
|
// Reveal hidden columns.
|
|
if ($hiddenHeaders.length > 0) {
|
|
$hiddenHeaders.each(function (index, element) {
|
|
var $header = $(this);
|
|
var position = $header.prevAll('th').length;
|
|
self.$table.find('tbody tr').each(function () {
|
|
var $cells = $(this).find('td').eq(position);
|
|
$cells.show();
|
|
// Keep track of the revealed cells, so they can be hidden later.
|
|
self.$revealedCells = $().add(self.$revealedCells).add($cells);
|
|
});
|
|
$header.show();
|
|
// Keep track of the revealed headers, so they can be hidden later.
|
|
self.$revealedCells = $().add(self.$revealedCells).add($header);
|
|
});
|
|
this.$link.text(this.hideText).data('pegged', 1);
|
|
}
|
|
// Hide revealed columns.
|
|
else {
|
|
this.$revealedCells.hide();
|
|
// Strip the 'display:none' declaration from the style attributes of
|
|
// the table cells that .hide() added.
|
|
this.$revealedCells.each(function (index, element) {
|
|
var $cell = $(this);
|
|
var properties = $cell.attr('style').split(';');
|
|
var newProps = [];
|
|
// The hide method adds display none to the element. The element
|
|
// should be returned to the same state it was in before the columns
|
|
// were revealed, so it is necessary to remove the display none value
|
|
// from the style attribute.
|
|
var match = /^display\s*\:\s*none$/;
|
|
for (var i = 0; i < properties.length; i++) {
|
|
var prop = properties[i];
|
|
prop.trim();
|
|
// Find the display:none property and remove it.
|
|
var isDisplayNone = match.exec(prop);
|
|
if (isDisplayNone) {
|
|
continue;
|
|
}
|
|
newProps.push(prop);
|
|
}
|
|
// Return the rest of the style attribute values to the element.
|
|
$cell.attr('style', newProps.join(';'));
|
|
});
|
|
this.$link.text(this.showText).data('pegged', 0);
|
|
// Refresh the toggle link.
|
|
$(window).trigger('resize.tableresponsive');
|
|
}
|
|
}
|
|
});
|
|
|
|
// Make the TableResponsive object available in the Drupal namespace.
|
|
Drupal.TableResponsive = TableResponsive;
|
|
|
|
})(jQuery, Drupal, window);
|