jQuery(function($){ $.fn.freezeTable = function (options) { return this.each(function () { var $this = $(this); if( $this.hasClass('frzTbl-clone-table') ){ return; } // destroy if( options == 'destroy' ){ if( $this.data('freezeTable') ) { $this.data('freezeTable').destroy(); } return true; } // create if( ! $this.data('freezeTable') ){ $this.data('freezeTable', new $.FreezeTable(this, options)); return true; } // resize if( options == 'resize' ){ $this.data('freezeTable').resize(); return true; } // cell resize if( options == 'cell_resize' ){ $this.data('freezeTable').cell_resize(); return true; } // reload $this.data('freezeTable').reload(options); }); }; $.FreezeTable = FreezeTable; function FreezeTable (table, options) { var $table = $(table); this.el = { $table: $table } this.ev = { touchstart: false } this.options = $.extend(true, {}, this.default_options, typeof options === 'object' ? options : {} ); this.namespace = Math.floor((Math.random() * 100000) + 1); if( this.options.height && ! this.options.force_sticky_outer_heading ){ this.options._sticky_outer_heading = false; }else if( this.options.force_sticky_outer_heading ){ this.options._sticky_outer_heading = true; } $table.trigger('before_freeze_table_build', this); this.build(); $table.trigger('after_freeze_table_build', this); }; FreezeTable.prototype.default_options = { left: 0, right: 0, heading: 0, offset: 0, wrapperWidth: 0, wrapperHeight: 0, tableWidth: 0, grab_and_scroll: 0, grab_and_scroll_click_selectors: false, captureScroll: false, force_sticky_outer_heading: false, _sticky_outer_heading: true }; // unwrap if FT not required at this window size FreezeTable.prototype.maybe_disable = function() { var settings = this.get_breakpoint_options(), $table = this.el.$table, $container = $table.closest('.frzTbl').length ? $table.closest('.frzTbl') : $table.parent(), container_width = settings.wrapperWidth ? settings.wrapperWidth : $container.width(), table_original_width = $table[0].style.width, table_compressed_width = $table.outerWidth(container_width).outerWidth(); $table[0].style.width = table_original_width; $(window).off('resize.ft' + this.namespace); if( ! settings.tableWidth && table_compressed_width <= container_width && ! settings.left && ! settings.right && ! settings.heading ){ this.unwrap(); // register event handler to check if FT required upon future resize $(window).on('resize.ft' + this.namespace, $.proxy(this, 'try_enable')); return true; } } // throttles event handler, attempts 'build' every 200 ms FreezeTable.prototype.try_enable = function() { var _build = $.proxy(this, 'build'); clearTimeout(this.try_enable_clear); this.try_enable_clear = setTimeout(_build, 200); }; FreezeTable.prototype.get_overflow_permission = function(){ var $table = this.el.$table, $table_parent = $table.parent(), settings = this.get_breakpoint_options(), table_overflows = false; // no need for ov flow if columns not fixed if( ! settings.left && ! settings.right ){ return false; } if( $table_parent.hasClass('frzTbl-table-wrapper__inner') ){ $table_parent.addClass('frzTbl-table-wrapper__inner--overflow-check'); table_overflows = $table.outerWidth() > $table_parent.width(); $table_parent.removeClass('frzTbl-table-wrapper__inner--overflow-check'); }else{ table_overflows = $table.outerWidth() > $table_parent.width(); } return table_overflows || settings.left || settings.right; } FreezeTable.prototype.build = function() { if( this.maybe_disable() ){ return; } var $table = this.el.$table, $temp_wrapper = $('
').insertBefore($table), tpl_master = $('#frzTbl-tpl').html(); $table.css({ width : '', minWidth : '', height : '', }); $temp_wrapper[0].innerHTML = '
'+ $table[0].outerHTML +'
'; var $temp_table = $('>div>table', $temp_wrapper), table_width = Math.max( $temp_table.outerWidth(), $temp_wrapper.width() ), table_height = $temp_table.outerHeight(); if( table_width > $temp_wrapper.width() ){ ++table_width; } // table cannot be narrower than FT container this.el.$table.css( 'min-width', $temp_wrapper.innerWidth() ); var wrapper_width = this.options.wrapperWidth ? this.options.wrapperWidth : '', wrapper_height = this.options.wrapperHeight ? this.options.wrapperHeight : table_height; $temp_wrapper.remove(); this.tpl = tpl_master .replace(/{{wrapper_height}}/g,'height:' + wrapper_height + 'px; ') .replace(/{{wrapper_width}}/g, wrapper_width ? 'width:' + wrapper_width + 'px; ' : '') .replace(/{{table_height}}/g, 'height:' + table_height + 'px; ') .replace(/{{table_width}}/g, 'width:' + table_width + 'px; '); this.build_heading(); this.build_left(); this.build_right(); $table.addClass('frzTbl-table'); var $wrapper = this.el.$wrapper = $(this.tpl).insertBefore($table); $wrapper.find('.frzTbl-table-placeholder').replaceWith($table); var $window = $(window); // record components this.el.$firstCell = this.el.$table.find('.wcpt-cell:first'); this.el.$scrollOverlay = this.el.$wrapper.children('.frzTbl-scroll-overlay'); this.el.$scrollOverlayInner = this.el.$scrollOverlay.children('.frzTbl-scroll-overlay__inner'); this.el.$contentWrapper = this.el.$wrapper.children('.frzTbl-content-wrapper'); this.el.$frozenColumnsWrapper = this.el.$contentWrapper.children('.frzTbl-frozen-columns-wrapper'); this.el.$frozenColumnsInner = this.el.$frozenColumnsWrapper.children('.frzTbl-frozen-columns-wrapper__inner'); this.el.$frozenColumnsLeft = this.el.$frozenColumnsInner.children('.frzTbl-frozen-columns-wrapper__columns--left'); this.el.$frozenColumnsLeftSticky = this.el.$frozenColumnsLeft.children('.frzTbl-top-sticky'); this.el.$frozenColumnsRight = this.el.$frozenColumnsInner.children('.frzTbl-frozen-columns-wrapper__columns--right'); this.el.$frozenColumnsRightSticky = this.el.$frozenColumnsRight.children('.frzTbl-top-sticky'); this.el.$fixedHeadingWrapperOuter = this.el.$contentWrapper.children('.frzTbl-fixed-heading-wrapper-outer'); this.el.$fixedHeadingWrapper = this.el.$fixedHeadingWrapperOuter.children('.frzTbl-fixed-heading-wrapper'); this.el.$fixedHeadingLeftColumn = this.el.$fixedHeadingWrapperOuter.children('.frzTbl-fixed-heading-wrapper__columns--left'); this.el.$fixedHeadingRightColumn = this.el.$fixedHeadingWrapperOuter.children('.frzTbl-fixed-heading-wrapper__columns--right'); this.el.$fixedHeadingInner = this.el.$fixedHeadingWrapper.children('.frzTbl-fixed-heading-wrapper__inner'); this.el.$tableWrapper = this.el.$contentWrapper.children('.frzTbl-table-wrapper'); this.el.$tableInner = this.el.$tableWrapper.children('.frzTbl-table-wrapper__inner'); this.el.$tableWrapperSticky = this.el.$tableInner.children('.frzTbl-top-sticky'); this.sticky_heading(); this.resize_clone_cells(); this.grab_and_scroll(); // if( this.get_overflow_permission() ){ this.antiscroll(); // wheel/scroll $(window).on('scroll', $.proxy(this, 'page_scroll')); this.page_scroll({target: document}); this.el.$wrapper.on('wheel', $.proxy(this, 'wrapper_wheel')); this.el.$wrapper.on('touchstart touchmove touchend', $.proxy(this, 'wrapper_touch')); this.el.$scrollOverlay.on('wheel scroll', $.proxy(this, 'scrollOverlay_wheel')); var affected = [ this.el.$scrollOverlay, this.el.$tableWrapper, this.el.$fixedHeadingWrapper, this.el.$frozenColumnsWrapper, ]; $.each(affected, function(i, $elm){ $elm[0].scrollTop = 0; $elm[0].scrollLeft = 0; }) // } if( 1 > Math.abs( this.el.$wrapper.innerWidth() - this.el.$table.outerWidth() ) ){ this.el.$wrapper.addClass('frzTbl--scrolled-to-left-edge frzTbl--scrolled-to-right-edge'); } // window resize handler $window.on('resize.ft' + this.namespace , $.proxy(this, 'resize')); // image load handler $table[0].addEventListener('load', this.load_image, true); this.recordEnv(); }; FreezeTable.prototype.load_image = function(e){ var ft = $(this).data('freezeTable'), cell_resize = $.proxy(ft, 'cell_resize'); if( e.target.tagName === 'IMG' ){ cell_resize(e.target); } } FreezeTable.prototype.grab_and_scroll = function() { var _ = this, $wrapper = _.el.$wrapper, $body = $('body'); $wrapper.off('mousedown.freeze_table.grab_and_scroll'); $body.off('mousemove.freeze_table.grab_and_scroll_' + _.namespace); $body.off('mousemove.freeze_table.grab_and_scroll_' + _.namespace); $('img, a', $wrapper).off('dragstart.freeze_table.grab_and_scroll_' + _.namespace); $wrapper.removeClass('frzTbl--grab-and-scroll frzTbl--grab-and-scroll--grabbing'); if( this.get_breakpoint_options().grab_and_scroll ){ _.grab_and_scroll__grabbed = false; _.grab_and_scroll__last_clientX = false; _.grab_and_scroll__last_pos_x = false; _.grab_and_scroll__last_clientY = false; _.grab_and_scroll__last_pos_y = false; _.grab_and_scroll__$el = false; $wrapper.addClass('frzTbl--grab-and-scroll'); $wrapper.on('mousedown.freeze_table.grab_and_scroll', function(e){ if( e.which === 3 ){ // right click return; } if( e.target.tagName == 'SELECT' ){ return; } _.grab_and_scroll__grabbed = true; _.grab_and_scroll__first_clientX = e.clientX; _.grab_and_scroll__first_clientY = e.clientY; _.grab_and_scroll__last_clientX = e.clientX; _.grab_and_scroll__last_clientY = e.clientY; _.grab_and_scroll__$el = $(e.target).parentsUntil( $wrapper ); _.grab_and_scroll__$el__ev_handler_attached = false; $wrapper.addClass('frzTbl--grab-and-scroll--grabbing'); _.el.$table.trigger('freeze_table__grab_and_scroll__start'); $body.one('mouseup', function(){ _.grab_and_scroll__grabbed = false; $wrapper.removeClass('frzTbl--grab-and-scroll--grabbing'); _.el.$table.trigger('freeze_table__grab_and_scroll__stop'); setTimeout(function(){ // async else click ev will fire now _.grab_and_scroll__$el.off('click.freeze_table.grab_and_scroll_' + _.namespace); }, 1); }) }) $body.on('mousemove.freeze_table.grab_and_scroll_' + _.namespace, function(e){ if( _.grab_and_scroll__grabbed ){ var diff_x = e.clientX - _.grab_and_scroll__last_clientX; _.grab_and_scroll__last_pos_x += parseFloat(diff_x); _.horizontal_scroll( -diff_x ); _.grab_and_scroll__last_clientX = e.clientX; var diff_y = e.clientY - _.grab_and_scroll__last_clientY; _.grab_and_scroll__last_pos_y += parseFloat(diff_y); _.vertical_scroll( -diff_y ); _.grab_and_scroll__last_clientY = e.clientY; if( ( Math.abs( _.grab_and_scroll__last_clientX - _.grab_and_scroll__first_clientX ) > 2 || Math.abs( _.grab_and_scroll__last_clientY - _.grab_and_scroll__first_clientY ) > 2 ) && ! _.grab_and_scroll__$el__ev_handler_attached ){ _.grab_and_scroll__$el.one('click.freeze_table.grab_and_scroll_' + _.namespace, function(e){ e.preventDefault(); e.stopPropagation(); }) _.grab_and_scroll__$el__ev_handler_attached = true; } _.el.$table.trigger('freeze_table__grab_and_scroll__dragging'); } }) $('img, a', $wrapper).on('dragstart.freeze_table.grab_and_scroll_' + _.namespace, function(e){ e.preventDefault(); }); } }; FreezeTable.prototype.build_heading = function() { if( this.get_breakpoint_options().heading ){ var $heading = this.clone_table(); $heading.find('tbody').remove(); this.tpl = this.tpl.replace(/{{heading}}/g, $heading[0].outerHTML); } else { this.tpl = this.tpl.replace(/{{heading}}/g, ''); } }; FreezeTable.prototype.sticky_heading = function() { var settings = this.get_breakpoint_options(), offset = settings.offset ? settings.offset : 0, $heading = this.el.$table.children('thead'), heading_height = $heading[0].getBoundingClientRect().height, gap_top = parseInt( this.el.$table.css('border-top-width') ), heading_border = parseInt( this.el.$table.find('> thead > tr').css('border-bottom-width') ); if( isNaN(offset) ){ if( typeof offset === 'string' ){ // selector offset = $(offset).height(); }else if( typeof offset === 'object' ){ // jQuery object offset = offset.height(); } } if( gap_top % 2 ){ --gap_top; } gap_top *= .5; this.el.$fixedHeadingWrapperOuter.css({ height: heading_height + gap_top + heading_border, top: parseFloat( offset ) + 'px', }); if( ! settings._sticky_outer_heading ){ this.el.$fixedHeadingWrapperOuter.hide(); }else{ this.el.$fixedHeadingWrapperOuter.show(); } $('> div > table', this.el.$frozenColumnsInner).each(function(){ var $this = $(this); $('> thead', $this).remove(); $this.css('margin-top', (heading_height + gap_top) + 'px'); }) if( ! settings.heading ){ this.el.$fixedHeadingWrapperOuter.css({ position: 'relative', top: 0 }); } this.el.$wrapper.parents().each(function(){ var $this = $(this), overflow = $this.css('overflow'); if( ! $this.is('html') && ! $this.is('body') && overflow && overflow !== 'visible' ){ $this.addClass('frzTbl-force-parent-overlow-visible'); } }); }; FreezeTable.prototype.build_left = function() { var settings = this.get_breakpoint_options(); if( ! settings.left ){ this.tpl = this.tpl.replace( /{{left-columns}}/g, '' ); this.tpl = this.tpl.replace( /{{left-columns-heading}}/g, '' ); this.tpl = this.tpl.replace( /{{hide-left-columns-heading}}/g, 'frzTbl-fixed-heading-wrapper__columns--empty' ); this.tpl = this.tpl.replace( /{{hide-left-column}}/g, 'frzTbl-frozen-columns-wrapper__columns--empty' ); return; } var $left = this.clone_table(); $left.find('td, th').each(function(){ var $this = $(this); if( $this.index() >= settings.left ){ $this.remove(); } }) this.tpl = this.tpl.replace( /{{left-columns}}/g, ($left[0].outerHTML || '') ); $left_heading = $left.clone(); $left_heading.find('tbody').remove(); this.tpl = this.tpl.replace( /{{left-columns-heading}}/g, ($left_heading[0].outerHTML || '') ); this.tpl = this.tpl.replace( /{{hide-left-column}}/g, '' ); if( $('> thead > tr.wcpt-heading-row.wcpt-hide', this.el.$table).length ){ this.tpl = this.tpl.replace( /{{hide-top-sticky}}/g, ' frzTbl-top-sticky--empty ' ); }else{ this.tpl = this.tpl.replace( /{{hide-top-sticky}}/g, '' ); } }; FreezeTable.prototype.build_right = function() { var settings = this.get_breakpoint_options(); if( ! settings.right ){ this.tpl = this.tpl.replace( /{{right-columns}}/g, '' ); this.tpl = this.tpl.replace( /{{right-columns-heading}}/g, '' ); this.tpl = this.tpl.replace( /{{hide-right-columns-heading}}/g, 'frzTbl-fixed-heading-wrapper__columns--empty' ); this.tpl = this.tpl.replace( /{{hide-right-column}}/g, 'frzTbl-frozen-columns-wrapper__columns--empty' ); return; } var $right = this.clone_table(); $right.find('td, th').each(function(){ var $this = $(this); if( $this.siblings().length - $this.index() >= settings.right ){ $this.remove(); } }) this.tpl = this.tpl.replace( /{{right-columns}}/g, ($right[0].outerHTML || '') ); $right_heading = $right.clone(); $right_heading.find('tbody').remove(); this.tpl = this.tpl.replace( /{{right-columns-heading}}/g, ($right_heading[0].outerHTML || '') ); this.tpl = this.tpl.replace( /{{hide-right-column}}/g, '' ); if( $('> thead > tr.wcpt-heading-row.wcpt-hide', this.el.$table).length ){ this.tpl = this.tpl.replace( /{{hide-top-sticky}}/g, ' frzTbl-top-sticky--empty ' ); }else{ this.tpl = this.tpl.replace( /{{hide-top-sticky}}/g, '' ); } }; FreezeTable.prototype.clone_table = function() { var $table = this.el.$table, $cloneTable = this.el.$table.clone(); $cloneTable .css({ 'width': '', 'min-width': '', }) .addClass('frzTbl-clone-table'); $( '> tbody > tr > td, > thead > tr > th', $cloneTable ).each(function(){ var $this = $(this); $this.attr({ 'data-index': $this.index(), }); }); return $cloneTable; }; FreezeTable.prototype.resize_clone_cells = function() { var $table = this.el.$table, $cloneTables = this.get_clone_tables(), $cloneCells = $( '> tbody > tr > td, > thead > tr > th', $cloneTables ), dimensions = []; // read styles $cloneCells.each(function(){ var $this = $(this), $row = $this.parent(), wrapper = $row.parent().is('thead') ? 'thead' : 'tbody', selector = '> '+ wrapper +' > tr:nth-child('+ ($row.index() + 1) +') > *:nth-child('+ (parseInt($this.attr('data-index')) + 1) +')', $original = $(selector, $table); dimensions.push({ width: $original[0].getBoundingClientRect().width, rowOuterHeight: $original.parent()[0].getBoundingClientRect().height }); }); // write styles $cloneCells.each(function(i){ var $this = $(this); $this.css({ width: dimensions[i].width, minWidth: dimensions[i].width, }); $this.parent().outerHeight(dimensions[i].rowOuterHeight); }); // frozen columns header gap var $heading = this.el.$table.children('thead'), heading_height = $heading[0].getBoundingClientRect().height, gap_top = parseInt( this.el.$table.css('border-top-width') ); if( gap_top % 2 ){ --gap_top; } gap_top *= .5; $('> div > table', this.el.$frozenColumnsInner).each(function(){ var $this = $(this); $this.css('margin-top', (heading_height + gap_top) + 'px'); }) }; FreezeTable.prototype.get_clone_tables = function() { var $table = this.el.$table, $cloneTables = $(); $.each(this.el, function(name, $el){ var $childTables = $el.children().filter(function(){ return $(this).is('table') && this !== $table[0] }); $cloneTables = $cloneTables.add($childTables); }); return $cloneTables; }; FreezeTable.prototype.page_scroll = function(e) { if(e.target !== document ){ return; } var heading_rect = this.el.$fixedHeadingWrapperOuter[0].getBoundingClientRect(), table_rect = this.el.$table[0].getBoundingClientRect(); if( heading_rect.top == table_rect.top ){ this.el.$wrapper.addClass('frzTbl--scrolled-to-top'); }else{ this.el.$wrapper.removeClass('frzTbl--scrolled-to-top'); } }; FreezeTable.prototype.wrapper_wheel = function(e) { if( e.originalEvent.deltaY && ( ! e.originalEvent.deltaX || Math.abs( e.originalEvent.deltaY / e.originalEvent.deltaX ) > .1 ) && ! this.get_breakpoint_options().wrapperHeight ){ return true; } var $wrapper = this.el.$wrapper, scrolling = 'frzTbl--scrolling'; $wrapper.addClass(scrolling); clearTimeout(this.scroll_clear); this.scroll_clear = setTimeout( function(){ $wrapper.removeClass(scrolling); }, 300 ); e.preventDefault(); if( ! this.options.captureScroll || ! this.options.wrapperHeight ){ if( // no scroll this.el.$scrollOverlay[0].scrollHeight == this.el.$scrollOverlay.height() || // scroll down ( e.originalEvent.deltaY > 0 && this.el.$scrollOverlay[0].scrollTop + this.el.$scrollOverlay.height() == this.el.$scrollOverlayInner.height() ) || // scroll up ( e.originalEvent.deltaY < 0 && ! this.el.$scrollOverlay[0].scrollTop ) ){ $('html')[0].scrollTop += e.originalEvent.deltaY; $('body')[0].scrollTop += e.originalEvent.deltaY; } } }; FreezeTable.prototype.wrapper_touch = function(e) { if( e.type == 'touchstart' ){ this.el.$scrollOverlay.stop(true); } if( e.type == 'touchmove' && this.ev.prevClientX !== false ){ var diffX = this.ev.prevClientX - e.originalEvent.touches[0].clientX, diffY = this.ev.prevClientY - e.originalEvent.touches[0].clientY; var e2 = { originalEvent: { deltaX: diffX, deltaY: diffY } }; this.scrollOverlay_wheel(e2); // prep animate scroll if( Math.abs(diffX) > 5 ){ this.ev.animScroll = 20 * diffX + this.el.$scrollOverlay[0].scrollLeft; }else{ this.ev.animScroll = false; } } if( e.type == 'touchend' ){ if( this.ev.animScroll ){ this.el.$scrollOverlay.animate({scrollLeft: this.ev.animScroll}, { specialEasing: { scrollLeft : 'FreezeTable_easeOutQuad', } }); this.ev.animScroll = false; } this.ev.prevClientX = false; this.ev.prevClientY = false; }else{ this.ev.prevClientX = e.originalEvent.touches[0].clientX, this.ev.prevClientY = e.originalEvent.touches[0].clientY; } }; FreezeTable.prototype.scrollOverlay_wheel = function(e) { var deltaX = e.originalEvent.deltaX || 0, deltaY = e.originalEvent.deltaY || 0; this.horizontal_scroll( deltaX ); }; FreezeTable.prototype.horizontal_scroll = function( deltaX, deltaY ){ var $scrollOverlay = this.el.$scrollOverlay, scrollTop = this.layout_memory.scrollTop, scrollLeft = this.layout_memory.scrollLeft, scrollOverlayWidth = this.layout_memory.scrollOverlayWidth, scrollOverlayInnerWidth = this.layout_memory.scrollOverlayInnerWidth, // mode = 'scroll'; mode = 'transform'; if( ! deltaX ){ deltaX = 0; } if( ! deltaY ){ deltaY = 0; } if( deltaX == 0 && deltaY == 0 ){ // antiscroll deltaX = $scrollOverlay[0].scrollLeft - this.layout_memory.scrollLeft; } scrollTop += deltaY; scrollLeft += deltaX; // scrollLeft bounds if( scrollLeft < 0 ){ scrollLeft = 0; } if( scrollLeft + scrollOverlayWidth + 1 > scrollOverlayInnerWidth ){ scrollLeft = scrollOverlayInnerWidth - scrollOverlayWidth; } this.layout_memory.scrollTop = scrollTop; this.layout_memory.scrollLeft = scrollLeft; $scrollOverlay[0].scrollTop = scrollTop; $scrollOverlay[0].scrollLeft = scrollLeft; // scroll if( mode == 'scroll' ){ // -- table // this.el.$tableWrapper[0].scrollTop = scrollTop; this.el.$tableWrapper[0].scrollLeft = scrollLeft; // -- fixed heading this.el.$fixedHeadingWrapper[0].scrollLeft = scrollLeft; // -- fixed columns // this.el.$frozenColumnsWrapper[0].scrollTop = scrollTop; } // transform if( mode == 'transform' ){ // -- table this.el.$tableInner[0].style.transform = 'translate3d(-' + scrollLeft + 'px, 0, 0)'; // -- fixed heading this.el.$fixedHeadingInner[0].style.transform = 'translate3d(-' + scrollLeft + 'px, 0, 0)'; // -- fixed columns // this.el.$frozenColumnsInner[0].style.transform = 'translate3d(0, -' + scrollTop + 'px, 0)'; } // scrolled to edge class this.el.$wrapper.removeClass('frzTbl--scrolled-to-left-edge frzTbl--scrolled-to-right-edge'); if( ! scrollLeft ){ this.el.$wrapper.addClass('frzTbl--scrolled-to-left-edge'); } if( scrollLeft + scrollOverlayWidth >= scrollOverlayInnerWidth ){ this.el.$wrapper.addClass('frzTbl--scrolled-to-right-edge'); } } FreezeTable.prototype.vertical_scroll = function( deltaY ){ $('html')[0].scrollTop += deltaY; $('body')[0].scrollTop += deltaY; } FreezeTable.prototype.get_breakpoint_options = function() { var settings = this.get_options(), current_bp = this.current_breakpoint(); if( current_bp ){ var ops = $.extend(true, {}, this.default_options, settings.breakpoint[current_bp]); return ops; } return settings; }; FreezeTable.prototype.get_options = function() { return $.extend(true, {}, this.options); }; FreezeTable.prototype.resize = function() { var _resize = $.proxy(this, '_resize'); clearTimeout(this.resize_clear); this.resize_clear = setTimeout(_resize, 200); }; FreezeTable.prototype._resize = function() { var wrapperWidth = this.el.$wrapper.width(); if( this.env.wrapperWidth !== wrapperWidth ){ if( this.crossed_breakpoint() ){ this.reload(this.get_options()); return; } this.antiscroll(); this.recordEnv(); } }; // throttles event handler, attempts '_cell_resize' every 300 ms FreezeTable.prototype.cell_resize = function() { var _cell_resize = $.proxy(this, '_cell_resize'); clearTimeout(this.cell_resize_timeout); this.cell_resize_timeout = setTimeout(_cell_resize, 200); }; FreezeTable.prototype._cell_resize = function(cell) { if( ! this.el.$table.hasClass('frzTbl-table') ){ return; } if( typeof this.el.$scrollOverlay == 'undefined' ){ return; } var scrollLeft = this.el.$scrollOverlay[0].scrollLeft; var $table = this.el.$table; // manage overflow if( ! this.get_overflow_permission() ){ this.el.$tableInner.addClass('frzTbl-table-wrapper__inner--deflate'); }else{ this.el.$tableInner.removeClass('frzTbl-table-wrapper__inner--deflate'); } $table.css({ width : '', minWidth : '', height : '', }); this.el.$tableInner.addClass('frzTbl-table-wrapper__inner--unrestrict-table-wrapper'); var table_width = Math.max( this.el.$table.outerWidth(), this.el.$wrapper.innerWidth() ); table_height = this.el.$table.outerHeight(); if( table_width > this.el.$wrapper.width() ){ ++table_width; } this.el.$tableInner.removeClass('frzTbl-table-wrapper__inner--unrestrict-table-wrapper'); // table cannot be narrower than FT container this.el.$table.css( 'min-width', table_width ); var $affected = [ this.el.$scrollOverlayInner, // this.el.$tableInner, this.el.$frozenColumnsInner ]; if( ! this.get_breakpoint_options.wrapperHeight ){ $affected.push( this.el.$wrapper ); } $.each($affected, function(key, $elm){ $elm.css({ height: table_height, width: table_width, }); }); this.resize_clone_cells(); this.antiscroll(); this.el.$scrollOverlay[0].scrollLeft = scrollLeft; this.recordEnv(); }; FreezeTable.prototype.antiscroll = function() { var $table = this.el.$table, $scrollOverlay = this.el.$scrollOverlay; // rebuild layout memory this.layout_memory = { scrollTop: $scrollOverlay[0].scrollTop = 0, scrollLeft: $scrollOverlay[0].scrollLeft = 0, scrollOverlayWidth: $scrollOverlay.width(), scrollOverlayInnerWidth: this.el.$scrollOverlayInner.width(), } // reposition scrollbar var overflow = this.el.$table.width() - this.el.$wrapper.width(); if( overflow > 5 ){ this.el.$wrapper.antiscroll(); } this.el.$wrapper .children('> .frzTbl-antiscroll-wrap').remove().end() .children('.antiscroll-scrollbar-horizontal').wrap('
'); }; FreezeTable.prototype.crossed_breakpoint = function() { return this.current_breakpoint() !== this.env.breakpoint }; FreezeTable.prototype.recordEnv = function() { var _ = this; _.env = { // window windowWidth: $(window).width(), windowHeight: $(window).height(), // wrapper wrapperWidth: this.el.$wrapper.width(), wrapperHeight: this.el.$wrapper.height(), // table tableWidth: _.el.$table.width(), tableHeight: _.el.$table.height(), // first cell firstCellWidth: _.el.$firstCell.width(), firstCellHeight: _.el.$firstCell.height(), // breakpoint breakpoint: _.current_breakpoint(), } }; FreezeTable.prototype.current_breakpoint = function() { var settings = this.get_options(), breakpoint = false, windowWidth = $(window).width(); if( ! settings.breakpoint ){ return false; } $.each(settings.breakpoint, function(bp, bp_settings){ var bp = parseInt( bp ); if( bp < windowWidth ){ return true; } if( ! breakpoint || bp < breakpoint ){ breakpoint = bp; } }) return breakpoint; }; FreezeTable.prototype.destroy = function() { this.clear_handlers(); this.unwrap(); this.el.$table.removeData('freezeTable'); }; FreezeTable.prototype.clear_handlers = function() { $(window).off('resize.ft' + this.namespace); }; FreezeTable.prototype.unwrap = function() { var $table = this.el.$table, $wrapper = this.el.$wrapper; $table .removeClass('frzTbl-table') .css({ 'width': '', 'min-width': '' }); if( ! $wrapper || ! $wrapper.length ){ return; } $table.insertBefore($wrapper); $wrapper.remove(); }; FreezeTable.prototype.reload = function(options) { var $table = this.el.$table; this.destroy(); $table.data('freezeTable', new $.FreezeTable($table[0], options)); }; $.extend($.easing, { FreezeTable_easeOutQuad: function (x, t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, } ); });