diff --git a/Netdisco/Changes b/Netdisco/Changes index ee25c4f9..4e36acaf 100644 --- a/Netdisco/Changes +++ b/Netdisco/Changes @@ -22,6 +22,7 @@ * [#49] Allow device port searching with preference for port/name/vlan. This is to support some devices (HP?) which have plain numbers for port names and Netdisco defaults to assuming this is a VLAN number (R. Kerr) + * Upgrade floatThead JS plugin to improve performance for large tables [BUG FIXES] diff --git a/Netdisco/share/public/javascripts/jquery.floatThead.js b/Netdisco/share/public/javascripts/jquery.floatThead.js index 5fccc827..8b91a3bd 100644 --- a/Netdisco/share/public/javascripts/jquery.floatThead.js +++ b/Netdisco/share/public/javascripts/jquery.floatThead.js @@ -1,612 +1,19 @@ -/*! - * jQuery.floatThead - * Copyright (c) 2012 - 2013 Misha Koryak - https://github.com/mkoryak/floatThead - * Licensed under Creative Commons Attribution-NonCommercial 3.0 Unported - http://creativecommons.org/licenses/by-sa/3.0/ - * Date: 8/25/13 - * - * @projectDescription lock a table header in place while scrolling - without breaking styles or events bound to the header - * - * Dependencies: - * jquery 1.9.0 + [required] OR jquery 1.7.0 + jquery UI core - * underscore.js 1.3.0 + [required] - * - * http://notetodogself.blogspot.com - * http://programmingdrunk.com/floatThead/ - * - * Tested on FF13+, Chrome 21+, IE9, IE8 - * - * @author Misha Koryak - * @version 1.0.0 +/* + jQuery.floatThead 1.2.0 + Copyright (c) 2013 Misha Koryak - http://mkoryak.github.io/floatThead/ + Licensed under http://creativecommons.org/licenses/by-sa/4.0/ */ -// ==ClosureCompiler== -// @compilation_level SIMPLE_OPTIMIZATIONS -// @output_file_name jquery.floatThead.min.js -// ==/ClosureCompiler== -/** - * @preserve jQuery.floatThead 1.0.0 - * Copyright (c) 2013 Misha Koryak - https://github.com/mkoryak/floatThead - * Licensed under Creative Commons Attribution-NonCommercial 3.0 Unported - http://creativecommons.org/licenses/by-sa/3.0/ - */ -(function( $ ) { - -//browser stuff -var ieVersion = function(){for(var a=3,b=document.createElement("b"),c=b.all||[];b.innerHTML="",c[0];);return 4"); - $('body').append($table); - var width = $table.find('col').width(); - $table.remove(); - return width == 0; -}; - -/** - * provides a default config object. You can modify this after including this script if you want to change the init defaults - * @type {Object} - */ -$.floatThead = { - defaults: { - cellTag: 'th', - zIndex: 1001, //zindex of the floating thead (actually a container div) - debounceResizeMs: 1, - useAbsolutePositioning: true, //if set to NULL - defaults: has scrollContainer=true, doesnt have scrollContainer=false - scrollingTop: 0, //String or function($table) - offset from top of window where the header should not pass above - //TODO: this got lost somewhere - needs to be re-implemented - scrollingBottom: 0, //String or function($table) - offset from the bottom of the table where the header should stop scrolling - scrollContainer: function($table){ - return $([]); //if the table has horizontal scroll bars then this is the container that has overflow:auto and causes those scroll bars - }, - floatTableClass: 'floatThead-table' - } -}; - -var $window = $(window); -var floatTheadCreated = 0; - - -/** - * debounce and fix window resize event for ie7. ie7 is evil and will fire window resize event when ANY dom element is resized. - * @param debounceMs - * @param cb - */ - -function windowResize(debounceMs, cb){ - var winWidth = $window.width(); - var debouncedCb = _.debounce(function(){ - var winWidthNew = $window.width(); - if(winWidth != winWidthNew){ - winWidth = winWidthNew; - cb(); - } - }, debounceMs); - $window.bind('resize.floatTHead', debouncedCb); -} - -/** - * try to calculate the scrollbar width for your browser/os - * @return {Number} - */ -function scrollbarWidth() { - var $div = $('
') - .css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: -1000 }) - .prependTo('body').append('
').find('div') - .css({ width: '100%', height: 200 }); - var scrollbarWidth = 100 - $div.width(); - $div.parent().remove(); - return scrollbarWidth; -} - -/** - * Check if a given table has been datatableized (http://datatables.net) - * @param $table - * @return {Boolean} - */ -function isDatatable($table){ - if($table.dataTableSettings){ - for(var i = 0; i < $table.dataTableSettings.length; i++){ - var table = $table.dataTableSettings[i].nTable; - if($table[0] == table){ - return true; - } - } - } - return false; -} -$.fn.floatThead = function(map){ - if(ieVersion < 8){ - return this; //no more crappy browser support. - } - - isChrome = ifChrome(); //need to call this after dom ready, and now it is. - if(isChrome){ - //because chrome cant read width, these elements are used for sizing the table. Need to create new elements because they must be unstyled by user's css. - document.createElement('fthtr'); //tr - document.createElement('fthtd'); //td - document.createElement('fthfoot'); //tfoot - } - if(_.isString(map)){ - var command = map; - var ret = this; - this.filter('table').each(function(){ - var obj = $(this).data('floatThead-attached'); - if(obj && _.isFunction(obj[command])){ - r = obj[command](); - if(typeof r !== 'undefined'){ - ret = r; - } - } - }); - return ret; - } - var opts = $.extend({}, $.floatThead.defaults, map); - - - this.filter(':not(.'+opts.floatTableClass+')').each(function(){ - var $table = $(this); - if($table.data('floatThead-attached')){ - return true; //continue the each loop - } - if(!$table.is('table')){ - throw new Error('jQuery.floatThead must be run on a table element. ex: $("table").floatThead();'); - } - var $header = $table.find('thead:first'); - var $tbody = $table.find('tbody:first'); - if($header.length == 0){ - throw new Error('jQuery.floatThead must be run on a table that contains a element'); - } - var headerFloated = true; - var scrollingTop, scrollingBottom; - var scrollbarOffset = {vertical: 0, horizontal: 0}; - var scWidth = scrollbarWidth(); - var lastColumnCount = 0; //used by columnNum() - var $scrollContainer = opts.scrollContainer($table) || $([]); //guard against returned nulls - - var useAbsolutePositioning = opts.useAbsolutePositioning; - if(useAbsolutePositioning == null){ //defaults: locked=true, !locked=false - useAbsolutePositioning = opts.scrollContainer($table).length; - } - - var $fthGrp = $(''); - - var locked = $scrollContainer.length > 0; - var wrappedContainer = false; //used with absolute positioning enabled. did we need to wrap the scrollContainer/table with a relative div? - var absoluteToFixedOnScroll = ieVersion && !locked && useAbsolutePositioning; //on ie using absolute positioning doesnt look good with window scrolling, so we change positon to fixed on scroll, and then change it back to absolute when done. - var $floatTable = $(""); - var $floatColGroup = $(""); - var $tableColGroup = $(""); - var $fthRow = $(''); //created unstyled elements - var $floatContainer = $('
'); - var $newHeader = $("
"); - var $sizerRow = $(''); - var $sizerCells = $([]); - var $tableCells = $([]); //used for sizing - either $sizerCells or $tableColGroup cols. $tableColGroup cols are only created in chrome for borderCollapse:collapse because of a chrome bug. - var $headerCells = $([]); - var $fthCells = $([]); //created elements - - $newHeader.append($sizerRow); - $header.detach(); - - $table.prepend($newHeader); - $table.prepend($tableColGroup); - if(isChrome){ - $fthGrp.append($fthRow); - $table.append($fthGrp); - } - - $floatTable.append($floatColGroup); - $floatContainer.append($floatTable); - $floatTable.attr('class', $table.attr('class')); - $floatTable.addClass(opts.floatTableClass).css('margin', 0); //must have no margins or you wont be able to click on things under floating table - - if(useAbsolutePositioning){ - var makeRelative = function($container, alwaysWrap){ - var positionCss = $container.css('position'); - var relativeToScrollContainer = (positionCss == "relative" || positionCss == "absolute"); - if(!relativeToScrollContainer || alwaysWrap){ - var css = {"paddingLeft": $container.css('paddingLeft'), "paddingRight": $container.css('paddingRight')}; - $floatContainer.css(css); - $container = $container.wrap("
").parent(); - wrappedContainer = true; - } - return $container; - }; - if(locked){ - var $relative = makeRelative($scrollContainer, true); - $relative.append($floatContainer); - } else { - makeRelative($table); - $table.after($floatContainer); - } - } else { - $table.after($floatContainer); - } - - - $floatContainer.css({ - position: useAbsolutePositioning ? 'absolute' : 'fixed', - marginTop: 0, - top: useAbsolutePositioning ? 0 : 'auto', - zIndex: opts.zIndex - }); - updateScrollingOffsets(); - - var layoutFixed = {'table-layout': 'fixed'}; - var layoutAuto = {'table-layout': $table.css('tableLayout') || 'auto'}; - - function setHeaderHeight(){ - var headerHeight = $header.outerHeight(true); - $sizerRow.outerHeight(headerHeight); - $sizerCells.outerHeight(headerHeight); - } - - - function setFloatWidth(){ - var tableWidth = $table.outerWidth(); - var width = $scrollContainer.width() || tableWidth; - $floatContainer.width(width - scrollbarOffset.vertical); - if(locked){ - var percent = 100 * tableWidth / (width - scrollbarOffset.vertical); - $floatTable.css('width', percent+'%'); - } else { - $floatTable.outerWidth(tableWidth); - } - } - - function updateScrollingOffsets(){ - scrollingTop = (_.isFunction(opts.scrollingTop) ? opts.scrollingTop($table) : opts.scrollingTop) || 0; - scrollingBottom = (_.isFunction(opts.scrollingBottom) ? opts.scrollingBottom($table) : opts.scrollingBottom) || 0; - } - - /** - * get the number of columns and also rebuild resizer rows if the count is different then the last count - */ - function columnNum(){ - var $headerColumns = $header.find('tr:first>'+opts.cellTag); - - var count = _.reduce($headerColumns, function(sum, cell){ - var colspan = parseInt(($(cell).attr('colspan') || 1), 10); - return sum + colspan; - }, 0); - if(count != lastColumnCount){ - lastColumnCount = count; - var cells = [], cols = [], psuedo = []; - for(var x = 0; x < count; x++){ - cells.push('<'+opts.cellTag+' class="floatThead-col-'+x+'"/>'); - cols.push(''); - psuedo.push(""); - } - - cols = cols.join(''); - cells = cells.join(''); - - if(isChrome){ - psuedo = psuedo.join(''); - $fthRow.html(psuedo); - $fthCells = $fthRow.find('fthcell') - } - - $sizerRow.html(cells); - $tableColGroup.html(cols); - $tableCells = $tableColGroup.find('col'); - $floatColGroup.html(cols); - $headerCells = $floatColGroup.find("col"); - - } - return count; - } - - - function refloat(){ - if(!headerFloated){ - headerFloated = true; - $table.css(layoutFixed); - $floatTable.css(layoutFixed); - $floatTable.append($header); //append because colgroup must go first in chrome - $tbody.before($newHeader); - setHeaderHeight(); - } - } - function unfloat(){ - if(headerFloated){ - headerFloated = false; - $newHeader.detach(); - $table.prepend($header); - $table.css(layoutAuto); - $floatTable.css(layoutAuto); - } - } - function changePositioning(isAbsolute){ - if(useAbsolutePositioning != isAbsolute){ - useAbsolutePositioning = isAbsolute; - $floatContainer.css({ - position: useAbsolutePositioning ? 'absolute' : 'fixed' - }); - } - } - - /** - * returns a function that updates the floating header's cell widths. - * @return {Function} - */ - function reflow(){ - var numCols = columnNum(); //if the tables columns change dynamically since last time (datatables) we need to rebuild the sizer rows and get new count - var flow = function(){ - var badReflow = false; - var $rowCells = isChrome ? $fthCells : $tableCells; - if($rowCells.length == numCols && numCols > 0){ - unfloat(); - for(var i=0; i < numCols; i++){ - var $rowCell = $rowCells.eq(i); - var rowWidth = $rowCell.outerWidth(true); - $headerCells.eq(i).outerWidth(rowWidth); - $tableCells.eq(i).outerWidth(rowWidth); - } - refloat(); - for(var i=0; i < numCols; i++){ - var hw = $headerCells.eq(i).outerWidth(true); - var tw = $tableCells.eq(i).outerWidth(true); - if(hw != tw){ - badReflow = true; - break; - } - } - } else { - $floatTable.append($header); - $table.css(layoutAuto); - $floatTable.css(layoutAuto); - setHeaderHeight(); - } - return badReflow; - }; - return flow; - } - - /** - * first performs initial calculations that we expect to not change when the table, window, or scrolling container are scrolled. - * returns a function that calculates the floating container's top and left coords. takes into account if we are using page scrolling or inner scrolling - * @return {Function} - */ - function calculateFloatContainerPosFn(){ - var scrollingContainerTop = $scrollContainer.scrollTop(); - - //this floatEnd calc was moved out of the returned function because we assume the table height doesnt change (otherwise we must reinit by calling calculateFloatContainerPosFn) - var floatEnd; - var tableContainerGap = 0; - - var floatContainerHeight = $floatContainer.height(); - var tableOffset = $table.offset(); - if(locked){ - var containerOffset = $scrollContainer.offset(); - tableContainerGap = tableOffset.top - containerOffset.top + scrollingContainerTop; - } else { - floatEnd = tableOffset.top - scrollingTop - floatContainerHeight + scrollingBottom + scrollbarOffset.horizontal; - } - var windowTop = $window.scrollTop(); - var windowLeft = $window.scrollLeft(); - var scrollContainerLeft = $scrollContainer.scrollLeft(); - scrollingContainerTop = $scrollContainer.scrollTop(); - - - - var positionFn = function(eventType){ - - if(eventType == 'windowScroll'){ - windowTop = $window.scrollTop(); - windowLeft = $window.scrollLeft(); - } else if(eventType == 'containerScroll'){ - scrollingContainerTop = $scrollContainer.scrollTop(); - scrollContainerLeft = $scrollContainer.scrollLeft(); - } else if(eventType != 'init') { - windowTop = $window.scrollTop(); - windowLeft = $window.scrollLeft(); - scrollingContainerTop = $scrollContainer.scrollTop(); - scrollContainerLeft = $scrollContainer.scrollLeft(); - } - if(absoluteToFixedOnScroll){ - if(eventType == 'windowScrollDone'){ - changePositioning(true); //change to absolute - } else { - changePositioning(false); //change to fixed - } - } else if(eventType == 'windowScrollDone'){ - return null; //event is fired when they stop scrolling. ignore it if not 'absoluteToFixedOnScroll' - } - - tableOffset = $table.offset(); - var top, left, tableHeight; - - //absolute positioning - if(locked && useAbsolutePositioning){ //inner scrolling - if (tableContainerGap >= scrollingContainerTop) { - var gap = tableContainerGap - scrollingContainerTop; - gap = gap > 0 ? gap : 0; - top = gap; - // unfloat(); //more trouble than its worth - } else { - top = wrappedContainer ? 0 : scrollingContainerTop; - // refloat(); //more trouble than its worth - //headers stop at the top of the viewport - } - left = 0; - } else if(!locked && useAbsolutePositioning) { //window scrolling - tableHeight = $table.outerHeight(); - if(windowTop > floatEnd + tableHeight){ - top = tableHeight - floatContainerHeight; //scrolled past table - } else if (tableOffset.top > windowTop + scrollingTop) { - top = 0; //scrolling to table - unfloat(); - } else { - top = scrollingTop + windowTop - tableOffset.top + tableContainerGap; - refloat(); //scrolling within table. header floated - } - left = 0; - - //fixed positioning: - } else if(locked && !useAbsolutePositioning){ //inner scrolling - if (tableContainerGap > scrollingContainerTop) { - top = tableOffset.top - windowTop; - unfloat(); - } else { - top = tableOffset.top + scrollingContainerTop - windowTop - tableContainerGap; - refloat(); - //headers stop at the top of the viewport - } - left = tableOffset.left + scrollContainerLeft - windowLeft; - } else if(!locked && !useAbsolutePositioning) { //window scrolling - tableHeight = $table.outerHeight(); - if(windowTop > floatEnd + tableHeight){ - top = tableHeight + scrollingTop - windowTop + floatEnd; - unfloat(); - } else if (tableOffset.top > windowTop + scrollingTop) { - top = tableOffset.top - windowTop; - refloat(); - } else { - top = scrollingTop; - } - left = tableOffset.left - windowLeft; - } - - return {top: top, left: left}; - }; - return positionFn; - } - /** - * returns a function that caches old floating container position and only updates css when the position changes - * @return {Function} - */ - function repositionFloatContainerFn(){ - var oldTop = null; - var oldLeft = null; - var oldScrollLeft = null; - return function(pos, setWidth, setHeight){ - if(pos != null && (oldTop != pos.top || oldLeft != pos.left)){ - $floatContainer.css({ - top: pos.top, - left: pos.left - }); - oldTop = pos.top; - oldLeft = pos.left; - } - if(setWidth){ - setFloatWidth(); - } - if(setHeight){ - setHeaderHeight(); - } - var scrollLeft = $scrollContainer.scrollLeft(); - if(oldScrollLeft != scrollLeft){ - $floatContainer.scrollLeft(scrollLeft); - oldScrollLeft = scrollLeft; - } - } - } - - /** - * checks if THIS table has scrollbars, and finds their widths - */ - function calculateScrollBarSize(){ //this should happen after the floating table has been positioned - if($scrollContainer.length){ - scrollbarOffset.horizontal = $scrollContainer.width() < $table.width() ? scWidth : 0; - scrollbarOffset.vertical = $scrollContainer.height() < $table.height() ? scWidth: 0; - } - } - //finish up. create all calculation functions and bind them to events - calculateScrollBarSize(); - - var flow = reflow(); - flow(); - var calculateFloatContainerPos = calculateFloatContainerPosFn(); - var repositionFloatContainer = repositionFloatContainerFn(); - - repositionFloatContainer(calculateFloatContainerPos('init'), true, true); //this must come after reflow because reflow changes scrollLeft back to 0 when it rips out the thead - - var windowScrollDoneEvent = _.debounce(function(){ - repositionFloatContainer(calculateFloatContainerPos('windowScrollDone'), false); - }, 300); - - var windowScrollEvent = function(){ - repositionFloatContainer(calculateFloatContainerPos('windowScroll'), false); - windowScrollDoneEvent(); - }; - var containerScrollEvent = function(){ - repositionFloatContainer(calculateFloatContainerPos('containerScroll'), false); - }; - - var windowResizeEvent = function(){ - updateScrollingOffsets(); - calculateScrollBarSize(); - flow = reflow(); - var badReflow = flow(); - if(badReflow){ - flow(); - } - calculateFloatContainerPos = calculateFloatContainerPosFn(); - repositionFloatContainer = repositionFloatContainerFn(); - repositionFloatContainer(calculateFloatContainerPos('resize'), true, true); - }; - var reflowEvent = _.debounce(function(){ - calculateScrollBarSize(); - updateScrollingOffsets(); - flow = reflow(); - var badReflow = flow(); - if(badReflow){ - flow(); - } - calculateFloatContainerPos = calculateFloatContainerPosFn(); - repositionFloatContainer(calculateFloatContainerPos('reflow'), true); - }, 1); - if(locked){ //internal scrolling - if(useAbsolutePositioning){ - $scrollContainer.bind('scroll.floatTHead', containerScrollEvent); - } else { - $scrollContainer.bind('scroll.floatTHead', containerScrollEvent); - $window.bind('scroll.floatTHead', windowScrollEvent); - } - } else { //window scrolling - $window.bind('scroll.floatTHead', windowScrollEvent); - } - - $window.bind('load.floatTHead', reflowEvent); //for tables with images - - windowResize(opts.debounceResizeMs, windowResizeEvent); - $table.bind('reflow', reflowEvent); - if(isDatatable($table)){ - $table - .bind('filter', reflowEvent) - .bind('sort', reflowEvent) - .bind('page', reflowEvent); - } - - //attach some useful functions to the table. - $table.data('floatThead-attached', { - destroy: function(){ - $table.css(layoutAuto); - $tableColGroup.remove(); - $fthGrp.remove(); - $newHeader.replaceWith($header); - $table.unbind('reflow'); - reflowEvent = windowResizeEvent = containerScrollEvent = windowScrollEvent = function() {}; - $scrollContainer.unbind('scroll.floatTHead'); - $floatContainer.remove(); - $table.data('floatThead-attached', false); - floatTheadCreated--; - if(floatTheadCreated == 0){ - $window.unbind('scroll.floatTHead'); - $window.unbind('resize.floatTHead'); - $window.unbind('load.floatTHead'); - } - }, - reflow: function(){ - reflowEvent(); - }, - setHeaderHeight: function(){ - setHeaderHeight(); - }, - getFloatContainer: function(){ - return $floatContainer; - } - }); - floatTheadCreated++; - }); - return this; -}; -})(jQuery); +(function(a){function ha(a,d){var b=e.width(),ia=_.debounce(function(){var a=e.width();b!=a&&(b=a,d())},a);e.bind("resize.floatTHead",ia)}function ja(){var g=a('
');a("body").append(g);var d=g.innerWidth(),b=a("div",g).innerWidth();g.remove();return d-b}function ka(a){if(a.dataTableSettings)for(var d=0;dtd")},floatTableClass:"floatThead-table",debug:!1}};var D=function(){for(var a=3,d=document.createElement("b"),b=d.all||[];d.innerHTML="\x3c!--[if gt IE "+ ++a+"]>
");a("body").append(e);var d=e.find("col").width();e.remove();return 0==d},e=a(window),K=0;a.fn.floatThead=function(g){if(8>D)return this;null==v&&(v=J())&&(document.createElement("fthtr"),document.createElement("fthtd"),document.createElement("fthfoot"));if(_.isString(g)){var d=this;this.filter("table").each(function(){var b=a(this).data("floatThead-attached");b&&_.isFunction(b[g])&&(b=b[g](),"undefined"!== + typeof b&&(d=b))});return d}var b=a.extend({},a.floatThead.defaults,g);_.each(g,function(e,d){if(!(d in a.floatThead.defaults)&&b.debug){var g="jQuery.floatThead: used ["+d+"] key to init plugin, but that param is not an option for the plugin. Valid options are: "+_.keys(a.floatThead.defaults).join(", ");window.console&&window.console&&window.console.log&&window.console.log(g)}});this.filter(":not(."+b.floatTableClass+")").each(function(){function d(){var a=n.outerHeight(!0);L.outerHeight(a);la.outerHeight(a)} + function g(){w=(_.isFunction(b.scrollingTop)?b.scrollingTop(c):b.scrollingTop)||0;X=(_.isFunction(b.scrollingBottom)?b.scrollingBottom(c):b.scrollingBottom)||0}function J(){var c=n.find("tr:first>"+b.cellTag),c=_.reduce(c,function(c,b){var d=parseInt(a(b).attr("colspan")||1,10);return c+d},0);if(c!=Y){Y=c;for(var d=[],s=[],f=[],e=0;e'),s.push(""),f.push("");s=s.join("");d=d.join(""); + v&&(f=f.join(""),M.html(f),N=M.find("fthtd"));L.html(d);E.html(s);O=E.find("col");P.html(s);Z=P.find("col")}return c}function F(){G||(G=!0,c.css($),h.css($),h.append(n),ma.before(z),d())}function Q(){G&&(G=!1,z.detach(),c.prepend(n),c.css(A),h.css(A))}function aa(a){p!=a&&(p=a,l.css({position:p?"absolute":"fixed"}))}function R(){var a,e=J();return function(){var s;s=O;s=v?N:D?b.getSizingRow(c,s,N):s;if(s.length==e&&0r||0>n)){if(na)"windowScrollDone"== + q?aa(!0):aa(!1);else if("windowScrollDone"==q)return null;k=c.offset();H&&ba&&(k.top+=f);var h,l;u&&p?(d>=a?(q=d-a,h=0b+q+f?h=q-g+f:k.top>r+w?(h=0,Q()):(h=w+r-k.top+d+f,F()),l=0):u&&!p?(d>a?(h=k.top-r,Q()):(h=k.top+a-r-d,F()),l=k.left+t-n):u||p||(q=c.outerHeight(),r>b+q+f?h=q+w-r+b+f:k.top>r+w?(h=k.top-r,F()):h=w,l=k.left-n);return{top:h,left:l}}}}function da(){var a=null,b=null,e=null;return function(f,g,k){null==f||a==f.top&&b==f.left||(l.css({top:f.top, + left:f.left}),a=f.top,b=f.left);g&&(f=c.outerWidth(),g=m.width()||f,l.width(g-B.vertical),u?h.css("width",100*f/(g-B.vertical)+"%"):h.outerWidth(f));k&&d();k=m.scrollLeft();e!=k&&(l.scrollLeft(k),e=k)}}function T(){m.length&&(B.horizontal=m.width() element");var G=!0,w,X,B={vertical:0,horizontal:0},ea=ja(),Y=0,m=b.scrollContainer(c)||a([]),p=b.useAbsolutePositioning;null==p&&(p=b.scrollContainer(c).length);var I=c.find("caption"),H=1==I.length;if(H)var ba="top"===(I.css("caption-side")||I.attr("align")||"top");var U=a(''),u=0=D&&!u&&p,h=a(""),P=a(""), + E=a(""),M=a(''),l=a('
'),z=a("
"),L=a(''),la=a([]),O=a([]),Z=a([]),N=a([]);z.append(L);n.detach();c.prepend(z);c.prepend(E);v&&(U.append(M),c.append(U));h.append(P);l.append(h);h.attr("class",c.attr("class"));h.addClass(b.floatTableClass).css("margin",0);if(p){var fa=function(a,c){var b=a.css("position");if("relative"!=b&&"absolute"!=b||c)b={paddingLeft:a.css("paddingLeft"),paddingRight:a.css("paddingRight")}, + l.css(b),a=a.wrap("
").parent(),ca=!0;return a};u?fa(m,!0).append(l):(fa(c),c.after(l))}else c.after(l);l.css({position:p?"absolute":"fixed",marginTop:0,top:p?0:"auto",zIndex:b.zIndex});g();var $={"table-layout":"fixed"},A={"table-layout":c.css("tableLayout")||"auto"};T();var C=R();C();var t=S(),x=da();x(t("init"),!0);var oa=_.debounce(function(){x(t("windowScrollDone"),!1)},300),V=function(){x(t("windowScroll"),!1);oa()},W=function(){x(t("containerScroll"), + !1)},ga=function(){g();T();C=R();C();t=S();x=da();x(t("resize"),!0,!0)},y=_.debounce(function(){T();g();C=R();C();t=S();x(t("reflow"),!0)},1);u?p?m.bind("scroll.floatTHead",W):(m.bind("scroll.floatTHead",W),e.bind("scroll.floatTHead",V)):e.bind("scroll.floatTHead",V);e.bind("load.floatTHead",y);ha(b.debounceResizeMs,ga);c.bind("reflow",y);ka(c)&&c.bind("filter",y).bind("sort",y).bind("page",y);c.data("floatThead-attached",{destroy:function(){c.css(A);E.remove();v&&U.remove();z.parent().length&&z.replaceWith(n); + c.unbind("reflow");y=ga=W=V=function(){};m.unbind("scroll.floatTHead");l.remove();c.data("floatThead-attached",!1);K--;0==K&&(e.unbind("scroll.floatTHead"),e.unbind("resize.floatTHead"),e.unbind("load.floatTHead"))},reflow:function(){y()},setHeaderHeight:function(){d()},getFloatContainer:function(){return l}});K++});return this}})(jQuery); \ No newline at end of file