PageSourceSearch

https://www.gresb.com/wp-content/themes/framework/assets/js/components/_1_tooltip.js?ver=1790269062

js gresb.com collected 2026-09-24 17:14:22 UTC 7,751 bytes, 184 lines download raw bytes

1// File#: _1_tooltip
2// Usage: codyhouse.co/license
3(function() {
4	var Tooltip = function(element) {
5		this.element = element;
6		this.tooltip = false;
7		this.tooltipIntervalId = false;
8		this.tooltipContent = this.element.getAttribute('title');
9		this.tooltipPosition = (this.element.getAttribute('data-tooltip-position')) ? this.element.getAttribute('data-tooltip-position') : 'top';
10		this.tooltipClasses = (this.element.getAttribute('data-tooltip-class')) ? this.element.getAttribute('data-tooltip-class') : false;
11		this.tooltipId = 'js-tooltip-element'; // id of the tooltip element -> trigger will have the same aria-describedby attr
12		// there are cases where you only need the aria-label -> SR do not need to read the tooltip content (e.g., footnotes)
13		this.tooltipDescription = (this.element.getAttribute('data-tooltip-describedby') && this.element.getAttribute('data-tooltip-describedby') == 'false') ? false : true; 
14
15		this.tooltipDelay = 300; // show tooltip after a delay (in ms)
16		this.tooltipDelta = 10; // distance beetwen tooltip and trigger element (in px)
17		this.tooltipTriggerHover = false;
18		// tooltp sticky option
19		this.tooltipSticky = (this.tooltipClasses && this.tooltipClasses.indexOf('tooltip--sticky') > -1);
20		this.tooltipHover = false;
21		if(this.tooltipSticky) {
22			this.tooltipHoverInterval = false;
23		}
24		resetTooltipContent(this);
25		initTooltip(this);
26	};
27
28	function resetTooltipContent(tooltip) {
29		var htmlContent = tooltip.element.getAttribute('data-tooltip-title');
30		if(htmlContent) {
31			tooltip.tooltipContent = htmlContent;
32		}
33	};
34
35	function initTooltip(tooltipObj) {
36		// reset trigger element
37		tooltipObj.element.removeAttribute('title');
38		tooltipObj.element.setAttribute('tabindex', '0');
39		// add event listeners
40		tooltipObj.element.addEventListener('mouseenter', handleEvent.bind(tooltipObj));
41		tooltipObj.element.addEventListener('focus', handleEvent.bind(tooltipObj));
42	};
43
44	function removeTooltipEvents(tooltipObj) {
45		// remove event listeners
46		tooltipObj.element.removeEventListener('mouseleave',  handleEvent.bind(tooltipObj));
47		tooltipObj.element.removeEventListener('blur',  handleEvent.bind(tooltipObj));
48	};
49
50	function handleEvent(event) {
51		// handle events
52		switch(event.type) {
53			case 'mouseenter':
54			case 'focus':
55				showTooltip(this, event);
56				break;
57			case 'mouseleave':
58			case 'blur':
59				checkTooltip(this);
60				break;
61		}
62	};
63
64	function showTooltip(tooltipObj, event) {
65		// tooltip has already been triggered
66		if(tooltipObj.tooltipIntervalId) return;
67		tooltipObj.tooltipTriggerHover = true;
68		// listen to close events
69		tooltipObj.element.addEventListener('mouseleave', handleEvent.bind(tooltipObj));
70		tooltipObj.element.addEventListener('blur', handleEvent.bind(tooltipObj));
71		// show tooltip with a delay
72		tooltipObj.tooltipIntervalId = setTimeout(function(){
73			createTooltip(tooltipObj);
74		}, tooltipObj.tooltipDelay);
75	};
76
77	function createTooltip(tooltipObj) {
78		tooltipObj.tooltip = document.getElementById(tooltipObj.tooltipId);
79		
80		if( !tooltipObj.tooltip ) { // tooltip element does not yet exist
81			tooltipObj.tooltip = document.createElement('div');
82			document.body.appendChild(tooltipObj.tooltip);
83		} 
84		
85		// reset tooltip content/position
86		Util.setAttributes(tooltipObj.tooltip, {'id': tooltipObj.tooltipId, 'class': 'tooltip tooltip--is-hidden js-tooltip', 'role': 'tooltip'});
87		tooltipObj.tooltip.innerHTML = tooltipObj.tooltipContent;
88		if(tooltipObj.tooltipDescription) tooltipObj.element.setAttribute('aria-describedby', tooltipObj.tooltipId);
89		if(tooltipObj.tooltipClasses) Util.addClass(tooltipObj.tooltip, tooltipObj.tooltipClasses);
90		if(tooltipObj.tooltipSticky) Util.addClass(tooltipObj.tooltip, 'tooltip--sticky');
91		placeTooltip(tooltipObj);
92		Util.removeClass(tooltipObj.tooltip, 'tooltip--is-hidden');
93
94		// if tooltip is sticky, listen to mouse events
95		if(!tooltipObj.tooltipSticky) return;
96		tooltipObj.tooltip.addEventListener('mouseenter', function cb(){
97			tooltipObj.tooltipHover = true;
98			if(tooltipObj.tooltipHoverInterval) {
99				clearInterval(tooltipObj.tooltipHoverInterval);
100				tooltipObj.tooltipHoverInterval = false;
101			}
102			tooltipObj.tooltip.removeEventListener('mouseenter', cb);
103			tooltipLeaveEvent(tooltipObj);
104		});
105	};
106
107	function tooltipLeaveEvent(tooltipObj) {
108		tooltipObj.tooltip.addEventListener('mouseleave', function cb(){
109			tooltipObj.tooltipHover = false;
110			tooltipObj.tooltip.removeEventListener('mouseleave', cb);
111			hideTooltip(tooltipObj);
112		});
113	};
114
115	function placeTooltip(tooltipObj) {
116		// set top and left position of the tooltip according to the data-tooltip-position attr of the trigger
117		var dimention = [tooltipObj.tooltip.offsetHeight, tooltipObj.tooltip.offsetWidth],
118			positionTrigger = tooltipObj.element.getBoundingClientRect(),
119			position = [],
120			scrollY = window.scrollY || window.pageYOffset;
121		
122		position['top'] = [ (positionTrigger.top - dimention[0] - tooltipObj.tooltipDelta + scrollY), (positionTrigger.right/2 + positionTrigger.left/2 - dimention[1]/2)];
123		position['bottom'] = [ (positionTrigger.bottom + tooltipObj.tooltipDelta + scrollY), (positionTrigger.right/2 + positionTrigger.left/2 - dimention[1]/2)];
124		position['left'] = [(positionTrigger.top/2 + positionTrigger.bottom/2 - dimention[0]/2 + scrollY), positionTrigger.left - dimention[1] - tooltipObj.tooltipDelta];
125		position['right'] = [(positionTrigger.top/2 + positionTrigger.bottom/2 - dimention[0]/2 + scrollY), positionTrigger.right + tooltipObj.tooltipDelta];
126		
127		var direction = tooltipObj.tooltipPosition;
128		if( direction == 'top' && position['top'][0] < scrollY) direction = 'bottom';
129		else if( direction == 'bottom' && position['bottom'][0] + tooltipObj.tooltipDelta + dimention[0] > scrollY + window.innerHeight) direction = 'top';
130		else if( direction == 'left' && position['left'][1] < 0 )  direction = 'right';
131		else if( direction == 'right' && position['right'][1] + dimention[1] > window.innerWidth ) direction = 'left';
132		
133		if(direction == 'top' || direction == 'bottom') {
134			if(position[direction][1] < 0 ) position[direction][1] = 0;
135			if(position[direction][1] + dimention[1] > window.innerWidth ) position[direction][1] = window.innerWidth - dimention[1];
136		}
137		tooltipObj.tooltip.style.top = position[direction][0]+'px';
138		tooltipObj.tooltip.style.left = position[direction][1]+'px';
139		Util.addClass(tooltipObj.tooltip, 'tooltip--'+direction);
140	};
141
142	function checkTooltip(tooltipObj) {
143		tooltipObj.tooltipTriggerHover = false;
144		if(!tooltipObj.tooltipSticky) hideTooltip(tooltipObj);
145		else {
146			if(tooltipObj.tooltipHover) return;
147			if(tooltipObj.tooltipHoverInterval) return;
148			tooltipObj.tooltipHoverInterval = setTimeout(function(){
149				hideTooltip(tooltipObj); 
150				tooltipObj.tooltipHoverInterval = false;
151			}, 300);
152		}
153	};
154
155	function hideTooltip(tooltipObj) {
156		if(tooltipObj.tooltipHover || tooltipObj.tooltipTriggerHover) return;
157		clearInterval(tooltipObj.tooltipIntervalId);
158		if(tooltipObj.tooltipHoverInterval) {
159			clearInterval(tooltipObj.tooltipHoverInterval);
160			tooltipObj.tooltipHoverInterval = false;
161		}
162		tooltipObj.tooltipIntervalId = false;
163		if(!tooltipObj.tooltip) return;
164		// hide tooltip
165		removeTooltip(tooltipObj);
166		// remove events
167		removeTooltipEvents(tooltipObj);
168	};
169
170	function removeTooltip(tooltipObj) {
171		Util.addClass(tooltipObj.tooltip, 'tooltip--is-hidden');
172		if(tooltipObj.tooltipDescription) tooltipObj.element.removeAttribute('aria-describedby');
173	};
174
175	window.Tooltip = Tooltip;
176
177	//initialize the Tooltip objects
178	var tooltips = document.getElementsByClassName('js-tooltip-trigger');
179	if( tooltips.length > 0 ) {
180		for( var i = 0; i < tooltips.length; i++) {
181			(function(i){new Tooltip(tooltips[i]);})(i);
182		}
183	}
184}());

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.