From 36617802e07463175bf463edecfcab5e8815f52e Mon Sep 17 00:00:00 2001 From: Mottie Date: Wed, 5 Feb 2014 22:20:25 -0600 Subject: [PATCH] Column selector widget: add attachTo function for popup dynamic elements --- docs/example-widget-column-selector.html | 302 ++++++++++++++++++----- js/widgets/widget-columnSelector.js | 70 +++++- 2 files changed, 300 insertions(+), 72 deletions(-) diff --git a/docs/example-widget-column-selector.html b/docs/example-widget-column-selector.html index 287f5886..7a481c39 100644 --- a/docs/example-widget-column-selector.html +++ b/docs/example-widget-column-selector.html @@ -10,6 +10,8 @@ + + @@ -21,10 +23,18 @@ + - +} + +/*** Bootstrap popover ***/ +#popover-target label { + margin: 0 5px; +} +#popover-target input { + margin-right: 5px; +} + @@ -128,7 +171,8 @@
  • This widget may not work properly if the table header includes rows with row or column spans.
  • The responsive part of this widget @@ -140,57 +184,134 @@

    Options

    -

    Column selector widget default options (added inside of tablesorter widgetOptions)

    -
      -
    • columnSelector_container (null) - Target an element within the current page where the column selector will be inserted. -
        -
      • This can be either a jQuery selector string ( e.g. '#columnSelector' )
      • -
      • or, a jQuery object ( e.g. $('#columnSelector') ).
      • -
      -
    • -
    • columnSelector_columns ({}; empty object) - Assigns a column status for each selector: -
        -
      • To disable, or remove a column from the column selector, include the key word "disable" - this is one of many ways to remove a column from the column selector popup
      • -
      • Set a column status to true to initially display a column. This is the default for undefined columns.
      • -
      • Set a column status to false to initially hide a column.
      • -
      • Examples: -
        widgetOptions : {
        +			

        Column selector widget default options (added inside of tablesorter widgetOptions)

        + + + + + + + + + + + + + + + -
      • columnSelector_name ("data-selector-name") - The data-attribute within the table header cell which contains an alternate column selector name. -
          -
        • If the header cell does not have this attribute defined, the column selector name will be taken from the header cell internal text.
        • -
        • If defined, the text contained within this attribute will replace the {name} string within the layout option above.
        • -
        -
      • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        OptionDescription
        columnSelector_container + Target an element within the current page where the column selector will be inserted. +
          +
        • This setting is optional. If not set, you can use the following function to attach it to another element - see the Bootstrap example below +
          $.tablesorter.columnSelector.attachTo( $('table'), '.selector-target' );
          +
        • +
        • This can be either a jQuery selector string ( e.g. '#columnSelector' )
        • +
        • or, a jQuery object ( e.g. $('#columnSelector') ).
        • +
        + Default value: null +
        columnSelector_columns + Assigns a column status for each selector: +
          +
        • To disable, or remove a column from the column selector, include the key word "disable" - this is one of many ways to remove a column from the column selector popup
        • +
        • Set a column status to true to initially display a column. This is the default for undefined columns.
        • +
        • Set a column status to false to initially hide a column.
        • +
        • Examples: +
          widgetOptions : {
             columnSelector_columns : {
               0 : "disable", /* disable; i.e. remove column from selector */
               1 : false,     /* start with column hidden */
               2 : true,      /* start with column visible; default for undefined columns */
             }
           }
        • -
        • columnSelector_saveColumns (true) - Save the current manually set column status (not the column's responsive state). This option requires the storage utility contained within the tablesorter widgets file (jquery.tablesorter.widgets.js).
        • -
        • columnSelector_layout ('<label><input type="checkbox">{name}</label>') - This option defines the markup used for each column selector within the popup. The only required parameter is the {name} string which will be replaced with the appropriate column name/title.
        • +
        + Default value: {}; empty object +
        columnSelector_saveColumnsSave the current manually set column status (not the column's responsive state). This option requires the storage utility contained within the tablesorter widgets file (jquery.tablesorter.widgets.js).
        +
        + Default value: true +
        columnSelector_layout + This option defines the markup used for each column selector within the popup. The only available parameter is the {name} string which will be replaced with the appropriate column name/title.
        +
        + An <input type="checkbox"> is required within this setting!
        +
        + Default value: '<label><input type="checkbox">{name}</label>' +
        columnSelector_name + The data-attribute within the table header cell which contains an alternate column selector name. +
          +
        • If the header cell does not have this attribute defined, the column selector name will be taken from the header cell internal text.
        • +
        • If defined, the text contained within this attribute will replace the {name} string within the layout option above.
        • +
        + Default value: "data-selector-name" +
        columnSelector_mediaquerySet this option to add (true) or not add (false) the media query functionality of this widget.
        +
        + Default value: true +
        columnSelector_mediaqueryNameWhen the media query checkbox is added (it also uses the columnSelector_layout markup), this is the name that is added. Set as "Auto" to signify to the user that columns disappearing and/or reappearing is automatically done.
        +
        + Default value: "Auto: " +
        columnSelector_mediaqueryStateSet this option to false to start with the media query disabled (manual column selection mode).
        +
        + Default value: true +
        columnSelector_breakpoints +
          +
        • This option defines the media query breakpoints with which to use when a column with the associated priority is hidden or revealed.
        • +
        • For example, the last entry "70em" (1,120px) is assigned to data-priority 6. When the browser width is below this dimension, all columns with a data-priority of six will be hidden. Then when a browser width less than "60em" (960px) is reached, all columns of data-priority 5 and above will be hidden. At "50em" (800px), all columns of data-priority 4 and above are hidden, etc.
        • +
        • Adjust these values as desired, but a maximum of six data-priorities is set.
        • +
        + Default value: [ "20em", "30em", "40em", "50em", "60em", "70em" ] +
        columnSelector_priority + This is the assigned data-attribute which contains the defined data priority for a table column. +
          +
        • Values of 1 through 6 set the breakpoints of that particular column.
        • +
        • A value of 1 has the highest priority, meaning it is the last column(s) to be hidden when the browser width goes below "20em" (320px).
        • +
        • A value of 7 has the lowest priority, meaning it is the first column(s) to be hidden when the browser width goes below "70em" (1,120px).
        • +
        • Any named priority value, (e.g. "critical" or "persistent") will flag the widget to remove that column from the selector list.
        • +
        • Undefined priorities will default to a priority value of 1.
        • +
        + Default value: "data-priority" +
        -
      • columnSelector_mediaquery (true) - Set this option to add (true) or not add (false) the media query functionality of this widget.
      • -
      • columnSelector_mediaqueryName ("Auto: ") - When the media query checkbox is added (it also uses the columnSelector_layout markup), this is the name that is added. Set as "Auto" to signify to the user that columns disappearing and/or reappearing is automatically done.
      • -
      • columnSelector_mediaqueryState (true) - Set this option to false to start with the media query disabled (manual column selection mode).
      • -
      • columnSelector_breakpoints ([ "20em", "30em", "40em", "50em", "60em", "70em" ]) -
          -
        • This option defines the media query breakpoints with which to use when a column with the associated priority is hidden or revealed.
        • -
        • For example, the last entry "70em" (1,120px) is assigned to data-priority 6. When the browser width is below this dimension, all columns with a data-priority of six will be hidden. Then when a browser width less than "60em" (960px) is reached, all columns of data-priority 5 and above will be hidden. At "50em" (800px), all columns of data-priority 4 and above are hidden, etc.
        • -
        • Adjust these values as desired, but a maximum of six data-priorities is set.
        • -
        -
      • -
      • columnSelector_priority ("data-priority") - This is the assigned data-attribute which contains the defined data priority for a table column. -
          -
        • Values of 1 through 6 set the breakpoints of that particular column.
        • -
        • A value of 1 has the highest priority, meaning it is the last column(s) to be hidden when the browser width goes below "20em" (320px).
        • -
        • A value of 7 has the lowest priority, meaning it is the first column(s) to be hidden when the browser width goes below "70em" (1,120px).
        • -
        • Any named priority value, (e.g. "critical" or "persistent") will flag the widget to remove that column from the selector list.
        • -
        • Undefined priorities will default to a priority value of 1.
        • -
        -
      • -

    Removing a column from the selector

    @@ -215,6 +336,8 @@

    Demo

    + +

    CSS only popup

    @@ -222,14 +345,14 @@
    -
    + (When "Auto" is set, the table becomes responsive; resize the browser window to see it work) - +
    - + @@ -242,6 +365,9 @@ + + + @@ -251,21 +377,49 @@ - - - - - - - + +
    Name Major Sex English
    NameMajorSexEnglishJapaneseCalculusGeometry
    Student03Languagesfemale85958085
    Student04Languagesmale6055100100
    Student05Languagesfemale68809580
    Student12Mathematicsfemale100757085
    Student13Languagesfemale1008010090
    Student14Languagesfemale50455590
    Student18Mathematicsmale30495575
    Student19Languagesmale68908870
    Student20Mathematicsmale40454080
    Student21Languagesmale5045100100
    Student22Mathematicsmale1009910090
    Student23Languagesfemale85808080
    Student01Languagesmale80707580
    Student02Mathematicsmale908810090
    Student03Languagesfemale85958085
    Student04Languagesmale6055100100
    Student05Languagesfemale68809580
    Student06Mathematicsmale1009910090
    Student07Mathematicsmale85689090
    Student08Languagesmale100909085
    Student09Mathematicsmale80506575
    Student10Languagesmale8510010090
    Student11Languagesmale8685100100
    Student24Languagesfemale100911382
    + +

    Bootstrap Popover

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RankFirst NameLast NameAgeTotalDiscountDate
    1Philip Aaron WongJohnson Sr Esq25$5.9522%Jun 26, 2004 7:22 AM
    11AaronHibert12$2.995%Aug 21, 2009 12:21 PM
    12Brandon ClarkHenry Jr51$42.2918%Oct 13, 2000 1:15 PM
    111PeterParker28$9.9920%Jul 6, 2006 8:14 AM
    21JohnHood33$19.9925%Dec 10, 2002 5:14 AM
    013ClarkKent Sr.18$15.8944%Jan 12, 2003 11:14 AM
    005BruceAlmighty Esq45$153.1944%Jan 18, 2021 9:12 AM
    10AlexDumass13$5.294%Jan 8, 2012 5:11 PM
    16JimFranco24$14.1914%Jan 14, 2004 11:23 AM
    166Bruce LeeEvans22$13.1911%Jan 18, 2007 9:12 AM
    100Brenda DexterMcMasters18$55.2015%Feb 12, 2010 7:23 PM
    55DennisBronson65$123.0032%Jan 20, 2001 1:12 PM
    9MarthadelFuego25$22.0917%Jun 11, 2011 10:55 AM
    @@ -276,7 +430,8 @@

    HTML

    -
    <!-- This selector markup is completely customizable -->
    +		
    <h3>CSS only popup</h3>
    +<!-- This selector markup is completely customizable -->
     <div class="columnSelectorWrapper">
     	<input id="colSelect1" type="checkbox" class="hidden">
     	<label class="columnSelectorButton" for="colSelect1">Column</label>
    @@ -285,7 +440,7 @@
     	</div>
     </div>
     
    -<table class="tablesorter">
    +<table class="tablesorter custom-popup">
     	<thead>
     		<tr>
     			<th data-priority="critical">Name</th>
    @@ -305,6 +460,29 @@
     	<tbody>
     		<!-- ... -->
     	</tbody>
    +</table>
    +
    +<h3>Bootstrap Popover</h3>
    +<!-- Bootstrap popover button -->
    +<button id="popover" type="button" class="btn btn-default">
    +	Select Column
    +</button>
    +
    +<table class="tablesorter bootstrap-popup">
    +	<thead>
    +		<tr>
    +			<th data-priority="critical">Rank</th>
    +			<th data-priority="3">First Name</th>
    +			<th data-priority="critical">Last Name</th>
    +			<th data-priority="4">Age</th>
    +			<th data-priority="4">Total</th>
    +			<th data-priority="5">Discount</th>
    +			<th data-priority="6">Date</th>
    +		</tr>
    +	</thead>
    +	<tbody>
    +		<!-- ... -->
    +	</tbody>
     </table>
    diff --git a/js/widgets/widget-columnSelector.js b/js/widgets/widget-columnSelector.js index 848c5957..4d5a118f 100644 --- a/js/widgets/widget-columnSelector.js +++ b/js/widgets/widget-columnSelector.js @@ -15,14 +15,23 @@ tsColSel = ts.columnSelector = { queryBreak : '@media screen and (min-width: [size]) { [columns] { display: table-cell; } }', init: function(table, c, wo) { - var colSel; + var $t, colSel; + + // abort if no input is contained within the layout + $t = $(wo.columnSelector_layout); + if (!$t.find('input').add( $t.filter('input') ).length) { + if (c.debug) { + ts.log('*** ERROR: Column Selector aborting, no input found in the layout! ***'); + } + return; + } // unique table class name c.tableId = 'tablesorter' + new Date().getTime(); c.$table.addClass( c.tableId ); // build column selector/state array - colSel = c.selector = { $container : $(wo.columnSelector_container) }; + colSel = c.selector = { $container : $(wo.columnSelector_container || '
    ') }; tsColSel.setupSelector(table, c, wo); if (wo.columnSelector_mediaquery) { @@ -73,7 +82,8 @@ tsColSel = ts.columnSelector = { if ($container.length) { colSel.$wrapper[colId] = $(wo.columnSelector_layout.replace(/\{name\}/g, name)).appendTo($container); colSel.$checkbox[colId] = colSel.$wrapper[colId] - .find('input') + // input may not be wrapped within the layout template + .find('input').add( colSel.$wrapper[colId].filter('input') ) .attr('data-column', colId) .prop('checked', colSel.states[colId]) .bind('change', function(){ @@ -86,7 +96,7 @@ tsColSel = ts.columnSelector = { }, setupBreakpoints: function(c, wo){ - var colSel = c.selector; + var $auto, colSel = c.selector; // add responsive breakpoints if (wo.columnSelector_mediaquery) { @@ -104,9 +114,11 @@ tsColSel = ts.columnSelector = { if (colSel.$container.length) { // Add media queries toggle if (wo.columnSelector_mediaquery && wo.columnSelector_mediaquery) { - $( wo.columnSelector_layout.replace(/\{name\}/g, wo.columnSelector_mediaqueryName) ) - .prependTo(colSel.$container) - .find('input') + $auto = $( wo.columnSelector_layout.replace(/\{name\}/g, wo.columnSelector_mediaqueryName) ).prependTo(colSel.$container); + $auto + // needed in case the input in the layout is not wrapped + .find('input').add( $auto.filter('input') ) + .attr('data-column', 'auto') .prop('checked', wo.columnSelector_mediaqueryState) .bind('change', function(){ wo.columnSelector_mediaqueryState = this.checked; @@ -118,6 +130,15 @@ tsColSel = ts.columnSelector = { }); tsColSel.updateBreakpoints(c, wo); tsColSel.updateCols(c, wo); + // copy the column selector to a popup/tooltip + if (c.selector.$popup) { + c.selector.$popup.find('.tablesorter-column-selector') + .html( colSel.$container.html() ) + .find('input').each(function(){ + var indx = $(this).attr('data-column') + $(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] ) + }); + } }).change(); } // Add a bind on update to re-run col setup @@ -127,8 +148,7 @@ tsColSel = ts.columnSelector = { } }, - - updateBreakpoints: function(c, wo){ + updateBreakpoints: function(c, wo) { var priority, column, breaks, colSel = c.selector, prefix = '.' + c.tableId, @@ -169,7 +189,7 @@ tsColSel = ts.columnSelector = { var column, styles = [], prefix = '.' + c.tableId; - c.selector.$container.find('input[data-column]').each(function(){ + c.selector.$container.find('input[data-column]').filter('[data-column!="auto"]').each(function(){ if (!this.checked) { column = parseInt( $(this).attr('data-column'), 10 ) + 1; styles.push(prefix + ' tr th:nth-child(' + column + ')'); @@ -185,6 +205,35 @@ tsColSel = ts.columnSelector = { if (wo.columnSelector_saveColumns && ts.storage) { ts.storage( c.$table[0], 'tablesorter-columnSelector', c.selector.states ); } + }, + + attachTo : function(table, elm) { + var colSel, wo, indx, + table = $(table)[0], + c = table.config, + $popup = $(elm); + if ($popup.length && c) { + if (!$popup.find('.tablesorter-column-selector').length) { + // add a wrapper to add the selector into, in case the popup has other content + $popup.append(''); + } + colSel = c.selector; + wo = c.widgetOptions; + $popup.find('.tablesorter-column-selector') + .html( colSel.$container.html() ) + .find('input').each(function(){ + var indx = $(this).attr('data-column'); + $(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] ) + }); + colSel.$popup = $popup.on('change', 'input', function(){ + // data input + indx = $(this).attr('data-column'); + // update original popup + colSel.$container.find('input[data-column="' + indx + '"]') + .prop('checked', this.checked) + .trigger('change'); + }); + } } }; @@ -229,6 +278,7 @@ ts.addWidget({ remove: function(table, c){ var csel = c.selector; csel.$container.empty(); + csel.$popup.empty(); csel.$style.remove(); csel.$breakpoints.remove(); c.$table.unbind('updateAll' + namespace + ',update' + namespace);