1$(window).scroll(function(){ 2 $('.th_heure').css({ 3 'left': $(this).scrollLeft() //Why this 15, because in the CSS, we have set left 15, so as we scroll, we would want this to remain at 15px left 4 }); 5}); 6/*var leftOffset = parseInt($(".th_heure").css("left")); //Grab the left position left first 7$(window).scroll(function(){ 8 $(".th_heure").css({ 9 'left': $(this).scrollLeft() + leftOffset //Use it later 10 }); 11});*/ 12 13;(function ($, window, undefined) { 14 'use strict'; 15 16 var name = 'stickyTableHeaders', 17 id = 0, 18 defaults = { 19 fixedOffset: 0, 20 leftOffset: 0, 21 marginTop: 0, 22 objDocument: document, 23 objHead: 'head', 24 objWindow: window, 25 scrollableArea: window, 26 cacheHeaderHeight: false, 27 zIndex: 3 28 }; 29 30 function Plugin (el, options) { 31 // To avoid scope issues, use 'base' instead of 'this' 32 // to reference this class from internal events and functions. 33 var base = this; 34 35 // Access to jQuery and DOM versions of element 36 base.$el = $(el); 37 base.el = el; 38 base.id = id++; 39 40 // Listen for destroyed, call teardown 41 base.$el.bind('destroyed', 42 $.proxy(base.teardown, base)); 43 44 // Cache DOM refs for performance reasons 45 base.$clonedHeader = null; 46 base.$originalHeader = null; 47 48 // Cache header height for performance reasons 49 base.cachedHeaderHeight = null; 50 51 // Keep track of state 52 base.isSticky = false; 53 base.hasBeenSticky = false; 54 base.leftOffset = null; 55 base.topOffset = null; 56 57 base.init = function () { 58 base.setOptions(options); 59 60 base.$el.each(function () { 61 var $this = $(this); 62 63 // remove padding on <table> to fix issue #7 64 $this.css('padding', 0); 65 66 base.$originalHeader = $('thead:first', this); 67 base.$clonedHeader = base.$originalHeader.clone(); 68 $this.trigger('clonedHeader.' + name, [base.$clonedHeader]); 69 70 base.$clonedHeader.addClass('tableFloatingHeader'); 71 base.$clonedHeader.css({display: 'none', opacity: 0.0}); 72 73 base.$originalHeader.addClass('tableFloatingHeaderOriginal'); 74 75 base.$originalHeader.after(base.$clonedHeader); 76 77 base.$printStyle = $('<style type="text/css" media="print">' + 78 '.tableFloatingHeader{display:none !important;}' + 79 '.tableFloatingHeaderOriginal{position:static !important;}' + 80 '</style>'); 81 base.$head.append(base.$printStyle); 82 }); 83 84 base.$clonedHeader.find("input, select").attr("disabled", true); 85 86 base.updateWidth(); 87 base.toggleHeaders(); 88 base.bind(); 89 }; 90 91 base.destroy = function (){ 92 base.$el.unbind('destroyed', base.teardown); 93 base.teardown(); 94 }; 95 96 base.teardown = function(){ 97 if (base.isSticky) { 98 base.$originalHeader.css('position', 'static'); 99 } 100 $.removeData(base.el, 'plugin_' + name); 101 base.unbind(); 102 103 base.$clonedHeader.remove(); 104 base.$originalHeader.removeClass('tableFloatingHeaderOriginal'); 105 base.$originalHeader.css('visibility', 'visible'); 106 base.$printStyle.remove(); 107 108 base.el = null; 109 base.$el = null; 110 }; 111 112 base.bind = function(){ 113 base.$scrollableArea.on('scroll.' + name, base.toggleHeaders); 114 if (!base.isWindowScrolling) { 115 base.$window.on('scroll.' + name + base.id, base.setPositionValues); 116 base.$window.on('resize.' + name + base.id, base.toggleHeaders); 117 } 118 base.$scrollableArea.on('resize.' + name, base.toggleHeaders); 119 base.$scrollableArea.on('resize.' + name, base.updateWidth); 120 }; 121 122 base.unbind = function(){ 123 // unbind window events by specifying handle so we don't remove too much 124 base.$scrollableArea.off('.' + name, base.toggleHeaders); 125 if (!base.isWindowScrolling) { 126 base.$window.off('.' + name + base.id, base.setPositionValues); 127 base.$window.off('.' + name + base.id, base.toggleHeaders); 128 } 129 base.$scrollableArea.off('.' + name, base.updateWidth); 130 }; 131 132 // We debounce the functions bound to the scroll and resize events 133 base.debounce = function (fn, delay) { 134 var timer = null; 135 return function () { 136 var context = this, args = arguments; 137 clearTimeout(timer); 138 timer = setTimeout(function () { 139 fn.apply(context, args); 140 }, delay); 141 }; 142 }; 143 144 base.toggleHeaders = base.debounce(function () { 145 if (base.$el) { 146 base.$el.each(function () { 147 var $this = $(this), 148 newLeft, 149 newTopOffset = base.isWindowScrolling ? ( 150 isNaN(base.options.fixedOffset) ? 151 base.options.fixedOffset.outerHeight() : 152 base.options.fixedOffset 153 ) : 154 base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0), 155 offset = $this.offset(), 156 157 scrollTop = base.$scrollableArea.scrollTop() + newTopOffset, 158 scrollLeft = base.$scrollableArea.scrollLeft(), 159 160 headerHeight, 161 162 scrolledPastTop = base.isWindowScrolling ? 163 scrollTop > offset.top : 164 newTopOffset > offset.top, 165 notScrolledPastBottom; 166 167 if (scrolledPastTop) { 168 headerHeight = base.options.cacheHeaderHeight ? base.cachedHeaderHeight : base.$clonedHeader.height(); 169 notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < 170 (offset.top + $this.height() - headerHeight - (base.isWindowScrolling ? 0 : newTopOffset)); 171 } 172 173 if (scrolledPastTop && notScrolledPastBottom) { 174 newLeft = offset.left - scrollLeft + base.options.leftOffset; 175 base.$originalHeader.css({ 176 'position': 'fixed', 177 'margin-top': base.options.marginTop, 178 'top': 0, 179 'left': newLeft, 180 'z-index': base.options.zIndex 181 }); 182 base.leftOffset = newLeft; 183 base.topOffset = newTopOffset; 184 base.$clonedHeader.css('display', ''); 185 if (!base.isSticky) { 186 base.isSticky = true; 187 // make sure the width is correct: the user might have resized the browser while in static mode 188 base.updateWidth(); 189 $this.trigger('enabledStickiness.' + name); 190 } 191 base.setPositionValues(); 192 } else if (base.isSticky) { 193 base.$originalHeader.css('position', 'static'); 194 base.$clonedHeader.css('display', 'none'); 195 base.isSticky = false;
196 base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader)); 197 $this.trigger('disabledStickiness.' + name); 198 } 199 }); 200 } 201 }, 0); 202 203 base.setPositionValues = base.debounce(function () { 204 var winScrollTop = base.$window.scrollTop(), 205 winScrollLeft = base.$window.scrollLeft(); 206 if (!base.isSticky || 207 winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() || 208 winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) { 209 return; 210 } 211 base.$originalHeader.css({ 212 'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop), 213 'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft) 214 }); 215 }, 0); 216 217 base.updateWidth = base.debounce(function () { 218 if (!base.isSticky) { 219 return; 220 } 221 // Copy cell widths from clone 222 if (!base.$originalHeaderCells) { 223 base.$originalHeaderCells = $('th,td', base.$originalHeader); 224 } 225 if (!base.$clonedHeaderCells) { 226 base.$clonedHeaderCells = $('th,td', base.$clonedHeader); 227 } 228 var cellWidths = base.getWidth(base.$clonedHeaderCells); 229 base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells); 230 231 // Copy row width from whole table 232 base.$originalHeader.css('width', base.$clonedHeader.width()); 233 234 // If we're caching the height, we need to update the cached value when the width changes 235 if (base.options.cacheHeaderHeight) { 236 base.cachedHeaderHeight = base.$clonedHeader.height(); 237 } 238 }, 0); 239 240 base.getWidth = function ($clonedHeaders) { 241 var widths = []; 242 $clonedHeaders.each(function (index) { 243 var width, $this = $(this); 244 245 if ($this.css('box-sizing') === 'border-box') { 246 var boundingClientRect = $this[0].getBoundingClientRect(); 247 if(boundingClientRect.width) { 248 width = boundingClientRect.width; // #39: border-box bug 249 } else { 250 width = boundingClientRect.right - boundingClientRect.left; // ie8 bug: getBoundingClientRect() does not have a width property 251 } 252 } else { 253 var $origTh = $('th', base.$originalHeader); 254 if ($origTh.css('border-collapse') === 'collapse') { 255 if (window.getComputedStyle) { 256 width = parseFloat(window.getComputedStyle(this, null).width); 257 } else { 258 // ie8 only 259 var leftPadding = parseFloat($this.css('padding-left')); 260 var rightPadding = parseFloat($this.css('padding-right')); 261 // Needs more investigation - this is assuming constant border around this cell and it's neighbours. 262 var border = parseFloat($this.css('border-width')); 263 width = $this.outerWidth() - leftPadding - rightPadding - border; 264 } 265 } else { 266 width = $this.width(); 267 } 268 } 269 270 widths[index] = width; 271 }); 272 return widths; 273 }; 274 275 base.setWidth = function (widths, $clonedHeaders, $origHeaders) { 276 $clonedHeaders.each(function (index) { 277 var width = widths[index]; 278 $origHeaders.eq(index).css({ 279 'min-width': width, 280 'max-width': width 281 }); 282 }); 283 }; 284 285 base.resetWidth = function ($clonedHeaders, $origHeaders) { 286 $clonedHeaders.each(function (index) { 287 var $this = $(this); 288 $origHeaders.eq(index).css({ 289 'min-width': $this.css('min-width'), 290 'max-width': $this.css('max-width') 291 }); 292 }); 293 }; 294 295 base.setOptions = function (options) { 296 base.options = $.extend({}, defaults, options); 297 base.$window = $(base.options.objWindow); 298 base.$head = $(base.options.objHead); 299 base.$document = $(base.options.objDocument); 300 base.$scrollableArea = $(base.options.scrollableArea); 301 base.isWindowScrolling = base.$scrollableArea[0] === base.$window[0]; 302 }; 303 304 base.updateOptions = function (options) { 305 base.setOptions(options); 306 // scrollableArea might have changed 307 base.unbind(); 308 base.bind(); 309 base.updateWidth(); 310 base.toggleHeaders(); 311 }; 312 313 // Run initializer 314 base.init(); 315 } 316 317 // A plugin wrapper around the constructor, 318 // preventing against multiple instantiations 319 $.fn[name] = function ( options ) { 320 return this.each(function () {
321 var instance = $.data(this, 'plugin_' + name); 322 if (instance) { 323 if (typeof options === 'string') { 324 instance[options].apply(instance); 325 } else { 326 instance.updateOptions(options); 327 } 328 } else if(options !== 'destroy') { 329 $.data(this, 'plugin_' + name, new Plugin( this, options )); 330 } 331 }); 332 }; 333 334})(jQuery, window);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.