/** * Scripts to display simple data tables. * 2/1/2020 Mack Pexton (mack@mackpexton.com) * * This is a collection of scripts from the web that are intended to enhance usage of html data tables. * There are three main scripts bundled below. They provide: * 1) sorting the table on a column * 2) freezing the table header at the top of the screen when it scrolls out of view * 3) resizing table columns * * These tools are for simple data tables on the main scrollable page with a structure like the following: * *
* * * * * * ... * * * * ... * *
Column 1Column 2
* * Tables will be coerced into this pattern at run time if needed. * * The width of the table is controlled by it's containing element which for touch devices needs to have the * class name "table-wrapper" assigned to it if you want fixed headers. It is automatically added if needed. * Tables can dynamically expand and contract according to the browser window width. * * If the user expands a column width, the width of the table is also expanded. User settings are remembered between * screen refreshes. The table width will snap back to it's bounding container when the browser window is resized. * Double-clicking a column guideline will remove the user setting and reset the column width back to its original width. * Double-clicking the last column guideline will remove all user settings and reset all the columns back to their original widths. * Putting a parameter "reset" in the url will remove the saved user's settings for the tables on the page. Rendering the * page in a new browser tab does the same. * * The script packages below are grouped in order and have been modified so that they work together * and so they all can be automatically setup on tables by using class names and data attributes. * * The class names used are: * table-sortable -- Make each table column sortable by clicking on the column header. * table-fixed-header -- Turn table's section into a header that sticks to the top of page. * table-col-resizable -- Make columns resizable. * * The optional
data attributes modifying behavior are: * data-topoffset -- Pixels from top of screen where headers will "freeze". * data-topheader -- Selector of an element that when visible, it's height is used for data-topoffset. * * It is possible to use the global variable window.TopOffset to set the top of screen where headers will "freeze". * It's easier to use when there are multiple tables on a page. Alternately you can assign the class name "top-header" * to an element whose bottom offset will be used for the window top offset. * * The optional '); var $tr = $(''); var converttag = $('th',$firstrow).length ? false : true; // Transfer first row to new thead section. $('td,th',$firstrow).each(function(i,el) { var $th = (converttag && el.nodeName == 'TD') ? $( el.outerHTML.replace(/^$/i,'') ) : $(el).clone(true); $tr.append($th); }); this.prepend( $thead.append($tr) ); $firstrow.remove(); } // Remove colgroup section if it exists (it confuses colResizable). if ( $('colgroup',this).length ) $('colgroup',this).remove(); // Wrap table with bounding div for touch devices horizontal scroll. if (this.hasClass('table-fixed-header') && ('ontouchstart' in document.documentElement)) { // Ensure table is wrapped with table-wrapper div. if (! this.parent().hasClass('table-wrapper')) { this.wrap( $('
').addClass('table-wrapper') ); } } this.data('simpleDataTable',true); return this; }; })(jQuery); /*---------------- sortable.js -----------------------------------------------------------------*/ /* sortable.js by Adam Schwartz at https://github.com/HubSpot/sortable */ /* For options and custom comparators, see https://github.hubspot.com/sortable/api/options/ /* * Changes: mack: * Wrap function with jQuery to sync execution with following packages. * Restrict processing of
sections. * Identify sortable tables with the class "table-sortable" in addition to it's default "data-sortable" attribute. * Added compatibility with table-fixed-header.js library. Used jQuery.on() for events so they can be cloned. * Added \n' ); //##setTimeout(sortable.init, 0); sortable.init(); // init() needs to run first before fixedHeader() below //## Add event handler to set up dynamically generated tables. $(document).on('tableSetup',function(e){ sortable.init(); }); //## Add event handler to unset sortable on tables. $(document).on('tableUnsetup',function(e){ // Remove settings initially setup by sortable. $('table.table-sortable,table[data-sortable]') .each(function(){ $('thead tr th,thead tr td',this).each(function(){ $(this).removeAttr('data-sorted'); }); }) .removeAttr('data-sortable-initialized'); }); if (typeof define === 'function' && define.amd) { define(function() { return sortable; }); } else if (typeof exports !== 'undefined') { module.exports = sortable; } else { window.Sortable = sortable; } //##}).call(this); }); /*---------------- table-fixed-header.js -------------------------------------------------------*/ /* * table-fixed-header - Freeze table headers when they get to the top of page. * * Usage: add "table-fixed-header" class to table with a thead header. * If needed, add "data-topoffset" attribute to the table with the offset from top of screen. * Optional "data-topheader" attribute has id of fixed top header whose bottom coordinate gives the top offset. * Optional window.TopOffset global variable with the offset from the top of screen. * * Derived from: http://github.com/oma/table-fixed-header * Note: this adds a second thead section to the table which violates HTML5 standard but seems to work everywhere. * Changes: mack: * Added auto-invocation code at bottom automatically setting up tables with class "table-fixed-header". * Got rid of thead selectors by using closures. * Corrected resizing cloned header when expanding table widths. * Add class table-header-fixed to the thead tag that's fixed to top of page. * Removed comments and hacks by jeffen@pactera, made into prepHeaderCopy(). * Added compatibility with sortable.js library. * Change o variable to $table for consistency * Added data-topOffset and data-bgColor attributes for setting parameters on auto-setup tables. * Dynamically read data-topoffset when showing the fixed header. Removed bgcolor config, use class css instead. * Hide header if scrolled past bottom of table. * Implement data-topheader selector for dynamically setting top offset to selector element's bottom coordinate when visible. * Added "tableRefresh" custom event to recompute parameters. Helpful when table was invisible when initially setup. * Added "tableSetup" and "tableUnsetup" custom events to setup tables with fixed headers and to remove fixed headers. * Added window.TopOffset global for dynamically setting top offset. Can set by giving an element the class "top-header". */ (function($) { var defaults = { topOffset: 0, // offset from top of screen topHeader: null, // selector for fixed element at top of screen topHeaderClass: '.top-header', // selector of element where if found is used for topHeader className: 'table-header-fixed', // class name assigned to cloned thead }; $.fn.fixedHeader = function(arg) { var config; if (typeof arg === 'object') { config = $.extend({}, defaults, arg); } else if ($.isNumeric(arg)) { config = $.extend({}, defaults, {topOffset:arg}); } else { config = $.extend({}, defaults); } return this.each(function() { var $table = $(this) , $win = $(window) , $head = $('thead',$table).first() , isFixed = false , $copy // Dynamic table parameters , tableTopOffset , headTop , headHeight , tableHeight , tableBottomOffset; if (! $head.length) return; // no thead sections found in table if ($('.'+config.className,$table).length) return; // already has a fixed header // Store dynamic parameters with table element. if ($table.data('topheader') == null) { if (config['topHeader'] != null) { $table.data('topheader',config['topHeader']); } else if ($(config['topHeaderClass']).length > 0) { $table.data('topheader',config['topHeaderClass']); } } if ($table.data('topoffset') == null) $table.data('topoffset', config['topOffset']); function processScroll() { if (! $table.is(':visible')) return; var scrollTop = $win.scrollTop() + tableTopOffset; if (!isFixed && (scrollTop > headTop && scrollTop < (headTop + tableHeight))) { isFixed = true; } else if (isFixed && (scrollTop <= headTop || scrollTop >= (headTop + tableHeight))) { isFixed = false; } if (isFixed) { if (! $copy.is(':visible')) showHeaderCopy(); $copy.offset({ 'top': (tableBottomOffset < scrollTop ? tableBottomOffset : scrollTop), 'left': $head.offset().left }); } else { if ($copy.is(':visible')) hideHeaderCopy(); } } function processResize() { if (isFixed) { prepHeader(); // copy changes to hidden table header prepHeaderCopy(); // copy new table column widths back to fixed header getParam(); // recompute global variables for scroll processScroll(); } } function showHeaderCopy() { prepHeaderCopy(); $copy.show(); getParam(); } function hideHeaderCopy() { prepHeader(); getParam(); $copy.hide(); } function prepHeaderCopy() { // Transfer run-time changes made to table header to the cloned header copy. $copy.css('top',tableTopOffset).width($head.width()); $('tr>th',$head).each(function(i, h) { var w , $h = $(h) //##, $c = $("tr>th:eq("+i+")",$copy); , $c = $("tr>th:nth-child("+(i+1)+")",$copy); $c.attr('class', $h.attr('class')); // Make column widths the same. //$c.width($h.width()); // fixed width tables // Following is for compatibility with colResizable.js // For dynamic tables where their widths can grow or shrink, we must set // the min and max width too in order to force the table to grow and to allow // columns to be narrower than a word. // We should look at colResizable overflow option to determine whether table size // is dynamic or not. Here we just assume that all tables use the overflow option. w = $h.width() + 'px'; $c.css({'width':w, 'min-width':w, 'max-width':w}); // dynamic width tables // Following is for compatibility with sortable.js $c.attr('data-sorted', $h.attr('data-sorted')); $c.attr('data-sortable-type', $h.attr('data-sortable-type')); if ($h.attr('data-sorted-direction')) { $c.attr('data-sorted-direction',$h.attr('data-sorted-direction')); } else { $c.removeAttr('data-sorted-direction'); /* remove to clear possible css styling */ } }); } function prepHeader() { // Transfer run-time changes made to cloned header back to the table header. $('tr>th',$copy).each(function(i, c) { var $c = $(c) //##, $h = $("tr>th:eq("+i+")",$head); , $h = $("tr>th:nth-child("+(i+1)+")",$head); $h.attr('class', $c.attr('class')); // Following is for compatibility with sortable.js $h.attr('data-sorted', $c.attr('data-sorted')); $h.attr('data-sortable-type', $c.attr('data-sortable-type')); if ($c.attr('data-sorted-direction')) { $h.attr('data-sorted-direction',$c.attr('data-sorted-direction')); } else { $h.removeAttr('data-sorted-direction'); /* remove to clear possible css styling */ } }); } function getParam() { // Lookup and set global variables of table parameters used to trigger fixed header. headTop = $head.offset().top; headHeight = $head.height(); tableHeight = $table.height(); tableBottomOffset = headTop + tableHeight - headHeight; tableTopOffset = getTopOffset(); } function getTopOffset() { if (window.TopOffset != null) return window.TopOffset; var $topHeader = $($table.data('topheader')); if ($topHeader.length && $topHeader.css('position').match(/(fixed|stickey)/)) { return $topHeader.scrollTop()+$topHeader.height(); } return $table.data('topoffset') || 0; } if (! $copy || ! $table.data('fixedHeaderSetup')) { $copy = $head.clone(true) .addClass(config['className']) .css({ 'position': 'fixed', 'border-spacing': '0', 'display': 'none'}) .appendTo($table); $table.data('fixedHeaderSetup',true); } getParam(); $win.on('scroll.fixedHeader', processScroll); $win.on('resize.fixedHeader', processResize); //## Add custom event to recompute parameters. Helpful when table was invisible when initially setup. $(document).on('tableRefresh', function(){getParam();processResize();}); //## Define custom event for setting up dynamically generated tables. $(document).on('tableSetup',function(e){ $('.table-fixed-header').setupSimpleDataTable().fixedHeader() }); //## Define custom event for removing extra DOM elements added by $.fn.fixedHeader(). $(document).on('tableUnsetup',function(e){ $('.table-fixed-header').removeFixedHeader() }); //## Add touch horizontal scroll. if ('ontouchstart' in document.documentElement) $('.table-wrapper').on('scroll.fixedHeader',processScroll); //## trigger scroll to show table headers if page is initially positioned in middle of page. setTimeout(function(){$win.trigger('scroll.fixedHeader')},10); }); }; //## Added removeFixedHeader to remove added thead sections in tables. $.fn.removeFixedHeader = function(){ return this.each(function(){ var $table = $(this); $('thead',$table).each(function(i){ // Remove added thead sections. if (i > 0) $(this).remove(); }); $table.data('fixedHeaderSetup',false); }); }; //## Automatically setup tables having the table-fixed-header class. $(function(){ $('.table-fixed-header').setupSimpleDataTable().fixedHeader(); }); //## To enable fixedHeaders for touch, the table's container overflow css needs to be set. Helps horizontal scrolling. //## Note: the following clips off popup menus at bottom of table that are used in file-list. //## We can get by just by assigning overflow to any element such as .backdrop. //##if ('ontouchstart' in document.documentElement) { //## $('head').append('\n'); //##} })(jQuery); /*---------------- doubletap handler -----------------------------------------------------------*/ /* Provide a handler for touch devices to double-tap column grips in colResizable.js */ /* * jQuery Double Tap * Developer: Sergey Margaritov (sergey@margaritov.net) * Date: 22.10.2013 * Based on jquery documentation http://learn.jquery.com/events/event-extensions/ */ (function($){ $.event.special.doubletap = { bindType: 'touchend', delegateType: 'touchend', handle: function(event) { var handleObj = event.handleObj, targetData = jQuery.data(event.target), now = new Date().getTime(), delta = targetData.lastTouch ? now - targetData.lastTouch : 0, delay = delay == null ? 300 : delay; if (delta < delay && delta > 30) { targetData.lastTouch = null; event.type = handleObj.origType; ['clientX', 'clientY', 'pageX', 'pageY'].forEach(function(property) { event[property] = event.originalEvent.changedTouches[0][property]; }) // let jQuery handle the triggering of "doubletap" event handlers handleObj.handler.apply(this, arguments); } else { targetData.lastTouch = now; } } }; })(jQuery); /*---------------- colResizable.js -------------------------------------------------------------*/ /* Usage: http://www.bacubacu.com/colresizable/#usage /** _ _____ _ _ _ | | __ \ (_) | | | | ___ ___ | | |__) |___ ___ _ ______ _| |__ | | ___ / __/ _ \| | _ // _ \/ __| |_ / _` | '_ \| |/ _ \ | (_| (_) | | | \ \ __/\__ \ |/ / (_| | |_) | | __/ \___\___/|_|_| \_\___||___/_/___\__,_|_.__/|_|\___| v1.6 - jQuery plugin created by Alvaro Prieto Lauroba Licences: MIT & GPL Feel free to use or modify this plugin as far as my full name is kept If you are going to use this plug-in in production environments it is strongly recommended to use its minified version: colResizable.min.js */ /* * Changes: mack: * Changed style settings so grid lines z-index are above fixed header. * Replaced jQuery deprecated bind() function with on(). * Integrate colResizable with fixedHeader (copy settings, sync with other invisible header). * Added code automatically setting up tables with the class name "table-col-resizable". * Flush saved settings if the parameter "reset" is found in url. * Track which columns are changed by user. * On resize reset non-user specified column widths to auto to allow browser to resize widths. * Changed interpretation of overflow option to be more dynamic where table width can expand and contract. * Added double-click handler on grips to reset column width back to it's initial setting. * Saved original column width percentage of total width to use when resizing table. * Removed tracking of user changed columns above. Use saved original widths instead. * Added custom event tableRefresh to recompute grips and headers. * Removed need for marginLeft and marginRight options. * Added option touchBeforeDrag and onGripTouchStart handler to activate grips first before dragging. * Added custom event tableUnsetup to remove DOM elements added by colResizable to the document. * Added double-click handler on last table grip to reset all table columns to their original width. * Sync'ed grip visibility to column visibilty to allow dynamically displayed columns in responsive designs. * * Because browsers have latitude in adjusting tables on their own, resize was changed to first * set table parameters, let the browser render the results, and then read the resulting column * widths for accurate placement of grips and guidelines. */ (function($){ var d = $(document); //window object var h = $("head"); //head object var drag = null; //reference to the current grip that is being dragged var tables = {}; //object of the already processed tables (table.id as key) var count = 0; //internal count to create unique IDs when needed. //common strings for packing var ID = "id"; var PX = "px"; var SIGNATURE ="JColResizer"; var FLEX = "JCLRFlex"; //short-cuts var I = parseInt; var M = Math; var ie = navigator.userAgent.indexOf('Trident/4.0')>0; var S; try{S = sessionStorage;}catch(e){} //Firefox crashes when executed as local file system //append required CSS rules //##h.append(""); //## Change z-index to be one more than fixed header in table-fixed-header.js above. //## Removed table td and th padding settings. //## Removed JCLRFlex{width:auto!important} as width:100% preferred. //## Expanded width of grips to better facilitate touch devices //## Changed grip resizer's class to JCLResizer as JColResizer is used for the table class name. //## Changed JCLRgrip and JCLRResizer css to center the gridline over the cell borders. //## Changed e-resize to col-resize h.append('' + '\n' ); /** * Function to allow column resizing for table objects. It is the starting point to apply the plugin. * @param {DOM node} tb - reference to the DOM table object to be enhanced * @param {Object} options - some customization values */ var init = function( tb, options){ var t = $(tb); //the table object is wrapped t.opt = options; //each table has its own options available at anytime t.mode = options.resizeMode; //shortcuts t.dc = t.opt.disabledColumns; if(t.opt.disable) return destroy(t); //the user is asking to destroy a previously colResized table var id = t.id = t.attr(ID) || SIGNATURE+count++; //its id is obtained, if null new one is generated count++; //## always increase in case old ID's are reused (re-setup) t.p = t.opt.postbackSafe; //short-cut to detect postback safe t.tm = null; //## timer for setting grips after table resize t.uc = false; //## true if user changed column sizes if(!t.is("table") || tables[id] && !t.opt.partialRefresh) return; //if the object is not a table or if it was already processed then it is ignored. //##if(t.opt.hoverCursor !== 'e-resize') h.append(""); //if hoverCursor has been set, append the style if(t.opt.hoverCursor !== 'col-resize') h.append(""); //if hoverCursor has been set, append the style t.addClass(SIGNATURE).attr(ID, id).before('
'); //the grips container object is added. Signature class forces table rendering in fixed-layout mode to prevent column's min-width t.g = []; t.c = []; t.w = t.width(); t.gc = t.prev(); t.f=t.opt.fixed; //t.c and t.g are arrays of columns and grips respectively //## Following options not needed anymore as syncGC() used instead. //##if(options.marginLeft) t.gc.css("marginLeft", options.marginLeft); //if the table contains margins, it must be specified //##if(options.marginRight) t.gc.css("marginRight", options.marginRight); //since there is no (direct) way to obtain margin values in its original units (%, em, ...) t.cs = I(ie? tb.cellSpacing || tb.currentStyle.borderSpacing :t.css('border-spacing'))||2; //table cellspacing (not even jQuery is fully cross-browser) t.b = I(ie? tb.border || tb.currentStyle.borderLeftWidth :t.css('borderLeftWidth'))||1; //outer border width (again cross-browser issues) // if(!(tb.style.width || tb.width)) t.width(t.width()); //I am not an IE fan at all, but it is a pity that only IE has the currentStyle attribute working as expected. For this reason I can not check easily if the table has an explicit width or if it is rendered as "auto" tables[id] = t; //the table object is stored using its id as key syncGC(t); //## sync grip container createGrips(t); //grips are created }; /** * This function allows to remove any enhancements performed by this plugin on a previously processed table. * @param {jQuery ref} t - table object */ var destroy = function(t){ var id=t.attr(ID), t=tables[id]; //its table object is found if(!t||!t.is("table")) return; //if none, then it wasn't processed t.removeClass(SIGNATURE+" "+FLEX).gc.remove(); //class and grips are removed delete tables[id]; //clean up data }; /** * Function to create all the grips associated with the table given by parameters * @param {jQuery ref} t - table object */ var createGrips = function(t){ //##var th = t.find(">thead>tr:first>th,>thead>tr:first>td"); //table headers are obtained //##if(!th.length) th = t.find(">tbody>tr:first>th,>tr:first>th,>tbody>tr:first>td, >tr:first>td"); //but headers can also be included in different ways var th = t.find(">thead>tr:first-child>th,>thead>tr:first-child>td"); //table headers are obtained if(!th.length) th = t.find(">tbody>tr:first-child>th,>tr:first-child>th,>tbody>tr:first-child>td, >tr:first-child>td"); //but headers can also be included in different ways th = th.filter(":visible"); //filter invisible columns t.cg = t.find("col"); //a table can also contain a colgroup with col elements t.ln = th.length; //table length is stored t.owt = t.w; //## saved original table width t.ow = []; th.each(function(i){t.ow[i] = $(this).width();}); //## save original column widths if(t.p && S && S[t.id])memento(t,th); //if 'postbackSafe' is enabled and there is data for the current table, its coloumn layout is restored th.each(function(i){ //iterate through the table column headers var c = $(this); //jquery wrap for the current column var dc = t.dc.indexOf(i)!=-1; //is this a disabled column? var g = $(t.gc.append('
')[0].lastChild); //add the visual node to be used as grip //## SIGNATURE as a class name is also attached to the table element. Use JCLRResizer here instead. //##g.append(dc ? "": t.opt.gripInnerHtml).append('
'); g.append(dc ? "": t.opt.gripInnerHtml).append('
'); if(i == t.ln-1){ //if the current grip is the last one g.addClass("JCLRLastGrip"); //add a different css class to stlye it in a different way if needed if(t.f) g.html(""); //if the table resizing mode is set to fixed, the last grip is removed since table with can not change } //## following is duplicated below //##g.on('touchstart mousedown', onGripMouseDown); //bind the mousedown event to start dragging if(!dc){ //if normal column bind the mousedown event to start dragging, if disabled then apply its css class //##g.removeClass('JCLRdisabledGrip').on('touchstart mousedown', onGripMouseDown); g.removeClass('JCLRdisabledGrip') .on('mousedown',onGripMouseDown) .on('touchstart',onGripTouchStart) //## activate grip before dragging .on('dblclick doubletap',onGripDoubleClick); //## reset column width to default }else{ g.addClass('JCLRdisabledGrip'); } g.t = t; g.i = i; g.c = c; c.w =c.width(); //some values are stored in the grip's node data as shortcut t.g.push(g); t.c.push(c); //the current grip and column are added to its table object if(!dc) c.width(c.w).removeAttr("width"); //the width of the column is converted into pixel-based measurements c.pl = I(c.css('paddingLeft')); //## store data as shortcut c.pr = I(c.css('paddingRight')); //## store data as shortcut c.bl = I(c.css('borderLeftWidth')); //## store data as shortcut c.br = I(c.css('borderRightWidth')); //## store data as shortcut c.wp = 100*(c.w+c.pl+c.pr+c.bl+c.br)/t.w; //## compute column width percent for resize g.data(SIGNATURE, {i:i, t:t.attr(ID), last: i == t.ln-1}); //grip index and its table name are stored in the HTML }); t.cg.removeAttr("width"); //remove the width attribute from elements in the colgroup t.find('td, th').not(th).not('table th, table td').each(function(){ $(this).removeAttr('width'); //the width attribute is removed from all table cells which are not nested in other tables and dont belong to the header }); if(!t.f){ t.removeAttr('width').addClass(FLEX); //if not fixed, let the table grow as needed } syncGrips(t); //the grips are positioned according to the current table layout //there is a small problem, some cells in the table could contain dimension values interfering with the //width value set by this plugin. Those values are removed //## Note: original column width settings are now preserved and restored. }; /** * Function to allow the persistence of columns dimensions after a browser postback. It is based in * the HTML5 sessionStorage object, which can be emulated for older browsers using sessionstorage.js * @param {jQuery ref} t - table object * @param {jQuery ref} th - reference to the first row elements (only set in deserialization) */ var memento = function(t, th){ var w,m=0,i=0,aux =[],tw; if(th){ //in deserialization mode (after a postback) t.cg.removeAttr("width"); if(t.opt.flush){ S[t.id] =""; return;} //if flush is activated, stored data is removed w = S[t.id].split(";"); //column widths is obtained //## Unnamed tables or tables with same name share same storage. Ensure number of table columns are the same. if(w.length != t.ln+2){ S[t.id]=""; return;} //## flush if number of table columns are different tw = w[t.ln+1]; if(!t.f && tw){ //if not fixed and table width data available its size is restored t.width(tw*=1); if(t.opt.overflow) { //if overflow flag is set, restore table width also as table min-width t.css('min-width', tw + PX); } } //## For overflow tables, use actual pixel widths (not percentage) if(t.opt.overflow){ for(;i
data attributes modifying script behavior are: * data-sortable -- If false, do not sort column (sortable.js) * data-sortable-type -- Column type "numeric", "date", or "alpha" (sortable.js). Custom types also available. * data-resizable -- If false, do not allow user to resize the column. (colResizable.js) * * The optional data attribute is: * data-value -- value of column to use for sorting (sortable.js) * * To setup newly created tables trigger the custom event "tableSetup". To refresh the table settings with run-time changes, * trigger the custom event "tableRefresh". Both the table size and settings will be refreshed upon the window "resize" event. * * To remove DOM elements added to the tables, trigger the custom event "tableUnsetup". That can be useful before editing * a table after which the "tableSetup" event can be triggered to re-setup the table(s). * * @credits * Table sorting is from sortable.js by Adam Schwartz at https://github.com/HubSpot/sortable * The table-fixed-header.js script came from: http://github.com/oma/table-fixed-header * Column resizing is from colResizable.js by Alvaro Prieto Lauroba * The double-tap event handler for column resizing is by Sergey Margaritov (sergey@margaritov.net) * * @requires jQuery * * Patched sections are identified by comments having the string "##". */ "use strict"; /*----------------------------------------------------------------------------------------------*/ /* * setupSimpleDataTable - coerce tables into a simple data table pattern if needed. */ (function($) { $.fn.setupSimpleDataTable = function() { if (this.data('simpleDataTable') == true) return this; // Make thead table section if needed. if (! $('thead',this).length) { var $firstrow = $('tr',this).first(); var $thead = $('
tags to only those in