PageSourceSearch

https://www.knoleparkgolfclub.co.uk/javascript/jquery.fixTHead.js

js knoleparkgolfclub.co.uk collected 2026-10-07 18:00:11 UTC 8,149 bytes, 281 lines download raw bytes

1;(function ($, window, undefined) {
2	'use strict';
3
4	var name = 'fixTableHeaders',
5		id = 0,
6		defaults = {
7			fixedOffset: 0,
8			leftOffset: 0,
9			marginTop: 0,
10			objDocument: document,
11			objHead: 'head',
12			objWindow: window,
13			scrollableArea: window
14		};
15
16	function Plugin (el, options) {
17
18		var base = this;
19
20		base.$el = $(el);
21		base.el = el;
22		base.id = id++;
23
24		base.$el.bind('destroyed',
25			$.proxy(base.teardown, base));
26
27		base.$clonedHeader = null;
28		base.$originalHeader = null;
29
30		base.isSticky = false;
31		base.hasBeenSticky = false;
32		base.leftOffset = null;
33		base.topOffset = null;
34
35		base.init = function () {
36			base.setOptions(options);
37
38			base.$el.each(function () {
39				var $this = $(this);
40
41				$this.css('padding', 0);
42
43				base.$originalHeader = $('thead:first', this);
44				base.$clonedHeader = base.$originalHeader.clone();
45				$this.trigger('clonedHeader.' + name, [base.$clonedHeader]);
46
47				base.$clonedHeader.addClass('tableFloatingHeader');
48				base.$clonedHeader.css('display', 'none');
49
50				base.$originalHeader.addClass('tableFloatingHeaderOriginal');
51				base.$originalHeader.find('tr').attr('data-csv-ignore','ignore');
52
53				base.$originalHeader.after(base.$clonedHeader);
54
55				base.$printStyle = $('<style type="text/css" media="print">' +
56					'.tableFloatingHeader{display:none !important;}' +
57					'.tableFloatingHeaderOriginal{position:static !important;}' +
58					'</style>');
59				base.$head.append(base.$printStyle);
60			});
61
62			base.updateWidth();
63			base.toggleHeaders();
64			base.bind();
65		};
66
67		base.destroy = function (){
68			base.$el.unbind('destroyed', base.teardown);
69			base.teardown();
70		};
71
72		base.teardown = function(){
73			if (base.isSticky) {
74				base.$originalHeader.css('position', 'static');
75			}
76			$.removeData(base.el, 'plugin_' + name);
77			base.unbind();
78
79			base.$clonedHeader.remove();
80			base.$originalHeader.removeClass('tableFloatingHeaderOriginal');
81			base.$originalHeader.css('visibility', 'visible');
82			base.$printStyle.remove();
83
84			base.el = null;
85			base.$el = null;
86		};
87
88		base.bind = function(){
89			base.$scrollableArea.on('scroll.' + name, base.toggleHeaders);
90			if (!base.isWindowScrolling) {
91				base.$window.on('scroll.' + name + base.id, base.setPositionValues);
92				base.$window.on('resize.' + name + base.id, base.toggleHeaders);
93			}
94			base.$scrollableArea.on('resize.' + name, base.toggleHeaders);
95			base.$scrollableArea.on('resize.' + name, base.updateWidth);
96		};
97
98		base.unbind = function(){
99
100			base.$scrollableArea.off('.' + name, base.toggleHeaders);
101			if (!base.isWindowScrolling) {
102				base.$window.off('.' + name + base.id, base.setPositionValues);
103				base.$window.off('.' + name + base.id, base.toggleHeaders);
104			}
105			base.$scrollableArea.off('.' + name, base.updateWidth);
106		};
107
108		base.toggleHeaders = function () {
109			if (base.$el) {
110				base.$el.each(function () {
111					var $this = $(this),
112						newLeft,
113						newTopOffset = base.isWindowScrolling ? (
114									isNaN(base.options.fixedOffset) ?
115									base.options.fixedOffset.outerHeight() :
116									base.options.fixedOffset
117								) :
118								base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0),
119						offset = $this.offset(),
120
121						scrollTop = base.$scrollableArea.scrollTop() + newTopOffset,
122						scrollLeft = base.$scrollableArea.scrollLeft(),
123
124						scrolledPastTop = base.isWindowScrolling ?
125								scrollTop > offset.top :
126								newTopOffset > offset.top,
127						notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) <
128								(offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset));
129
130					if (scrolledPastTop && notScrolledPastBottom) {
131						newLeft = offset.left - scrollLeft + base.options.leftOffset;
132						base.$originalHeader.css({
133							'position': 'fixed',
134							'margin-top': base.options.marginTop,
135							'left': newLeft,
136							'z-index': 3
137						});
138						base.leftOffset = newLeft;
139						base.topOffset = newTopOffset;
140						base.$clonedHeader.css('display', '');
141						if (!base.isSticky) {
142							base.isSticky = true;
143							base.updateWidth();
144							$this.trigger('enabledStickiness.' + name);
145						}
146						base.setPositionValues();
147					} else if (base.isSticky) {
148						base.$originalHeader.css('position', 'static');
149						base.$clonedHeader.css('display', 'none');
150						base.isSticky = false;
151						base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader));
152						$this.trigger('disabledStickiness.' + name);
153					}
154				});
155			}
156		};
157
158		base.setPositionValues = function () {
159			var winScrollTop = base.$window.scrollTop(),
160				winScrollLeft = base.$window.scrollLeft();
161			if (!base.isSticky ||
162					winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() ||
163					winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) {
164				return;
165			}
166			base.$originalHeader.css({
167				'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop),
168				'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft)
169			});
170		};
171
172		base.updateWidth = function () {
173			if (!base.isSticky) {
174				return;
175			}
176
177			if (!base.$originalHeaderCells) {
178				base.$originalHeaderCells = $('th,td', base.$originalHeader);
179			}
180			if (!base.$clonedHeaderCells) {
181				base.$clonedHeaderCells = $('th,td', base.$clonedHeader);
182			}
183			var cellWidths = base.getWidth(base.$clonedHeaderCells);
184			base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells);
185
186			base.$originalHeader.css('width', base.$clonedHeader.width());
187		};
188
189		base.getWidth = function ($clonedHeaders) {
190			var widths = [];
191			$clonedHeaders.each(function (index) {
192				var width, $this = $(this);
193
194				if ($this.css('box-sizing') === 'border-box') {
195					var boundingClientRect = $this[0].getBoundingClientRect();
196					if(boundingClientRect.width) {
197						width = boundingClientRect.width; 
198					} else {
199						width = boundingClientRect.right - boundingClientRect.left; 
200					}
201				} else {
202					var $origTh = $('th', base.$originalHeader);
203					if ($origTh.css('border-collapse') === 'collapse') {
204						if (window.getComputedStyle) {
205							width = parseFloat(window.getComputedStyle(this, null).width);
206						} else {
207
208							var leftPadding = parseFloat($this.css('padding-left'));
209							var rightPadding = parseFloat($this.css('padding-right'));
210
211							var border = parseFloat($this.css('border-width'));
212							width = $this.outerWidth() - leftPadding - rightPadding - border;
213						}
214					} else {
215						width = $this.width();
216					}
217				}
218
219				widths[index] = width;
220			});
221			return widths;
222		};
223
224		base.setWidth = function (widths, $clonedHeaders, $origHeaders) {
225			$clonedHeaders.each(function (index) {
226				var width = widths[index];
227				$origHeaders.eq(index).css({
228					'min-width': width,
229					'max-width': width
230				});
231			});
232		};
233
234		base.resetWidth = function ($clonedHeaders, $origHeaders) {
235			$clonedHeaders.each(function (index) {
236				var $this = $(this);
237				$origHeaders.eq(index).css({
238					'min-width': $this.css('min-width'),
239					'max-width': $this.css('max-width')
240				});
241			});
242		};
243
244		base.setOptions = function (options) {
245			base.options = $.extend({}, defaults, options);
246			base.$window = $(base.options.objWindow);
247			base.$head = $(base.options.objHead);
248			base.$document = $(base.options.objDocument);
249			base.$scrollableArea = $(base.options.scrollableArea);
250			base.isWindowScrolling = base.$scrollableArea[0] === base.$window[0];
251		};
252
253		base.updateOptions = function (options) {
254			base.setOptions(options);
255
256			base.unbind();
257			base.bind();
258			base.updateWidth();
259			base.toggleHeaders();
260		};
261
262
263		base.init();
264	}
265
266	$.fn[name] = function ( options ) {
267		return this.each(function () {
268			var instance = $.data(this, 'plugin_' + name);
269			if (instance) {
270				if (typeof options === 'string') {
271					instance[options].apply(instance);
272				} else {
273					instance.updateOptions(options);
274				}
275			} else if(options !== 'destroy') {
276				$.data(this, 'plugin_' + name, new Plugin( this, options ));
277			}
278		});
279	};
280
281})(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.