2015-08-17 17:00:26 -07:00
/ * *
* @ file
* Responsive table functionality .
* /
( function ( $ , Drupal , window ) {
2015-10-21 21:44:50 -07:00
'use strict' ;
2015-08-17 17:00:26 -07:00
/ * *
* 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 ) ;