├── jquery.tablebodyscroll.css ├── README.md └── jquery.tablebodyscroll.js /jquery.tablebodyscroll.css: -------------------------------------------------------------------------------- 1 | .tablebodyscroll-head { margin-bottom: 0 !important; border-bottom: none !important; } 2 | 3 | /* Hide the scrollbar on most platforms. Post-load Javascript adjusts the inner box a bit. */ 4 | .tablebodyscroll-scroller { position: relative; overflow: hidden; } 5 | .tablebodyscroll-scroller2 { position: absolute; overflow: scroll; top: 0; bottom: -17px; left: 0; right: -17px; } 6 | [dir="rtl"] .tablebodyscroll-scroller2 { left: -17px; right: 0; } 7 | .tablebodyscroll-scroller2::-webkit-scrollbar { display: none; } 8 | 9 | .tablebodyscroll-scroller3 { position: relative; } 10 | 11 | .tablebodyscroll-shadow-top .tablebodyscroll-scroller-shadow-top, .tablebodyscroll-shadow-both .tablebodyscroll-scroller-shadow-top { position: absolute; left: 0; right: 0; top: 0; height: 10px; background: rgba(0, 0, 0, 0.4); background: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0)); } 12 | .tablebodyscroll-shadow-bottom .tablebodyscroll-scroller-shadow-bottom, .tablebodyscroll-shadow-both .tablebodyscroll-scroller-shadow-bottom { position: absolute; left: 0; right: 0; bottom: 0; height: 10px; background: rgba(0, 0, 0, 0); background: linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 1)); } 13 | 14 | .tablebodyscroll-scroller-indicator { position: absolute; right: 0; height: 25px; width: 3px; background: #CCCCCC; transition: top .25s; } 15 | [dir="rtl"] .tablebodyscroll-scroller-indicator { right: auto; left: 0; } 16 | .tablebodyscroll-scroller-indicator-hide { opacity: 0; transition: opacity .5s linear; } 17 | .tablebodyscroll-scroller-indicator-show { opacity: 1; } 18 | 19 | .tablebodyscroll-has-head .tablebodyscroll-scroller3 > table { margin-top: 0 !important; border-top: none !important; } 20 | .tablebodyscroll-scroller3 > table > thead > tr { height: 0; } 21 | .tablebodyscroll-has-foot .tablebodyscroll-scroller3 > table { margin-bottom: 0 !important; border-bottom: none !important; } 22 | .tablebodyscroll-scroller3 > table > tfoot > tr { height: 0; } 23 | 24 | .tablebodyscroll-scroller3 th.tablebodyscroll-body-hide-cell, .tablebodyscroll-scroller3 td.tablebodyscroll-body-hide-cell { padding-top: 0 !important; padding-bottom: 0 !important; } 25 | .tablebodyscroll-scroller3 div.tablebodyscroll-body-hide-cell { height: 0; overflow: hidden; } 26 | 27 | .tablebodyscroll-foot { margin-top: 0 !important; border-top: none !important; } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQuery Table Body Scroll 2 | ======================== 3 | 4 | This jQuery plugin heavily modifies table bodies into slick vertical scrolling solutions. Ugly scrollbars are hidden out of sight, relying on visual indicators. Native keyboard, scroll wheel, and touch support. 5 | 6 | Combined with [TableCards](https://github.com/cubiclesoft/jquery-tablecards), traditional tables can be displayed on all devices in a neat, compact format. 7 | 8 | [](https://cubiclesoft.com/donate/) [](https://cubiclesoft.com/product-support/github/) 9 | 10 | Usage 11 | ----- 12 | 13 | ```html 14 | 15 | 16 | 40 | ``` 41 | 42 | There are several live examples under "Add Entry" in the [Admin Pack Demo](http://barebonescms.com/demos/admin_pack/admin.php). 43 | 44 | Options 45 | ------- 46 | 47 | The following options may be passed to TableBodyScroll: 48 | 49 | * height - An integer containing the height (Default is 60). 50 | * heightunit - A string containing one of the standard CSS units of measurement (Default is '%'). 51 | * percentelem - An object to reference for the height measurement when heightunit is '%' (Default is window). 52 | * postinit - A callback function to run after each TableCards initialization is run (Default is null). 53 | 54 | To destroy the instance and restore the table to its initial state, simply call: `$('#mytable').TableBodyScroll('destroy');` 55 | 56 | Events 57 | ------ 58 | 59 | The following custom events may be listened for: 60 | 61 | * tablebodyscroll:sizechanged - Notifies after resizing the table's most immediate parent. 62 | 63 | The following custom events may be manually triggered: 64 | 65 | * tablebodyscroll:resize - Notifies TableBodyScroll that the table has been resized. 66 | * tablebodyscroll:columnschanged - Notifies TableBodyScroll that the table columns have changed and to rebuild any headers and footers. 67 | -------------------------------------------------------------------------------- /jquery.tablebodyscroll.js: -------------------------------------------------------------------------------- 1 | // jQuery plugin to scroll the body of long tables so the table fits on a single screen. 2 | // (C) 2017 CubicleSoft. All Rights Reserved. 3 | 4 | (function($) { 5 | var debounce = function(func, wait) { 6 | var timeout = null; 7 | 8 | return function() { 9 | var context = this, args = arguments; 10 | var later = function() { 11 | timeout = null; 12 | 13 | func.apply(context, args); 14 | }; 15 | 16 | if (timeout) clearTimeout(timeout); 17 | timeout = setTimeout(later, wait); 18 | }; 19 | }; 20 | 21 | var debounce2 = function(func, wait, wait2) { 22 | var timeout = null, timeout2 = null; 23 | 24 | return function() { 25 | var context = this, args = arguments; 26 | var later = function() { 27 | clearTimeout(timeout); 28 | timeout = null; 29 | 30 | clearTimeout(timeout2); 31 | timeout2 = null; 32 | 33 | func.apply(context, args); 34 | }; 35 | 36 | if (timeout) clearTimeout(timeout); 37 | timeout = setTimeout(later, wait); 38 | 39 | if (!timeout2) timeout2 = setTimeout(later, wait2); 40 | }; 41 | }; 42 | 43 | $.fn.TableBodyScroll = function(options) { 44 | this.each(function() { 45 | var $this = $(this); 46 | 47 | if ($this.parent().hasClass('tablebodyscroll-scroller3')) 48 | { 49 | var scroller3 = $this.parent(); 50 | var scroller2 = scroller3.parent(); 51 | var scroller = scroller2.parent(); 52 | var wrapper = scroller.parent(); 53 | var origparent = wrapper.parent(); 54 | 55 | // Remove event handlers. 56 | scroller2.off('scroll.tablebodyscroll'); 57 | scroller2.off('mousemove.tablebodyscroll'); 58 | scroller2.off('keypress.tablebodyscroll'); 59 | $this.off('tablebodyscroll:resize'); 60 | $this.off('tablebodyscroll:columnschanged'); 61 | 62 | // Move the table back to its original parent in the DOM. 63 | wrapper.insertBefore($this); 64 | wrapper.remove(); 65 | 66 | // Clean up modified header/footer cells. 67 | $this.children('thead, tfoot').children('tr').children('th, td').each(function() { 68 | if ($(this).hasClass('tablebodyscroll-body-hide-cell')) 69 | { 70 | $(this).removeClass('tablebodyscroll-body-hide-cell'); 71 | 72 | var div = $(this).children('.tablebodyscroll-body-hide-cell'); 73 | div.insertBefore(div.contents()).remove(); 74 | } 75 | }); 76 | } 77 | }); 78 | 79 | if (typeof(options) === 'string' && options === 'destroy') return this; 80 | 81 | var settings = $.extend({}, $.fn.TableBodyScroll.defaults, options); 82 | 83 | return this.each(function() { 84 | var $this = $(this); 85 | 86 | // Wrap the table. 87 | var origparent = $this.parent(); 88 | var scrollerindicator = $('
').addClass('tablebodyscroll-scroller-indicator').addClass('tablebodyscroll-scroller-indicator-hide'); 89 | var scrollershadowtop = $('').addClass('tablebodyscroll-scroller-shadow-top'); 90 | var scrollershadowbottom = $('').addClass('tablebodyscroll-scroller-shadow-bottom'); 91 | var scroller3 = $('').addClass('tablebodyscroll-scroller3').insertBefore($this).append($this); 92 | var scroller2 = $('').addClass('tablebodyscroll-scroller2').insertBefore(scroller3).append(scroller3); 93 | var scroller = $('').addClass('tablebodyscroll-scroller').insertBefore(scroller2).append(scroller2).append(scrollerindicator).append(scrollershadowtop).append(scrollershadowbottom); 94 | var wrapper = $('').addClass('tablebodyscroll').insertBefore(scroller).append(scroller); 95 | 96 | // Generate header and footer tables. 97 | // Cloning has several mostly minor unresolveable issues but there is no other way to accurately make just the body of the table scroll. 98 | var origtheads = null; 99 | var newheadtable = null, newtheadcells = null, origtheadcells = null; 100 | 101 | var origtfoots = null; 102 | var newfoottable = null, newtfootcells = null, origtfootcells = null; 103 | 104 | var CloneHeadFoot = function() { 105 | origtheads = $this.children('thead'); 106 | origtheadcells = origtheads.children('tr').children('th, td'); 107 | if (origtheads.length) 108 | { 109 | origtheadcells.each(function() { 110 | if (!$(this).hasClass('tablebodyscroll-body-hide-cell')) 111 | { 112 | $(this).addClass('tablebodyscroll-body-hide-cell').append($('').append($(this).contents())); 113 | } 114 | }); 115 | 116 | if (newheadtable) newheadtable.remove(); 117 | var newtheads = origtheads.clone(true, true); 118 | newtheads.find('id').removeAttr('id'); 119 | newheadtable = $('