PageSourceSearch

https://compton.edu/_resources/js/main-menu-onkeydown.js

js compton.edu collected 2026-10-01 12:28:51 UTC 4,266 bytes, 150 lines download raw bytes

1// desktop tab menu Marianne E. 06/23/23
2; (function ($) {
3	'use strict';
4
5	function DesktopTabMenu(options) {
6
7		this.options = $.extend({
8			holder: null,
9			items: '.menu-item',
10			links: '>a',
11			delay: 10,
12			activeClass: 'hover',
13			focusAttr: 'data-focused',
14			hasChildrenClass: 'menu-item-has-children',
15			altClass: 'right-position',
16			drop: '> .drop-holder',
17			mainItemClass: 'main-item',
18		}, options);
19		this.init();
20	}
21
22	DesktopTabMenu.prototype = {
23		init: function () {
24			if (this.options.holder) {
25				this.findElements();
26				this.attachEvents();
27				this.makeCallback('onInit', this);
28			}
29		},
30		findElements: function () {
31			this.holder = $(this.options.holder);
32			this.holder.find('> ' + this.options.items).addClass(this.options.mainItemClass);
33			this.menuItems = this.holder.find(this.options.items);
34			this.menuLinks = this.holder.find(this.options.items + ' ' + this.options.links);
35			this.timer;
36			this.win = jQuery(window);
37		},
38		openDrop: function (item) {
39			item.addClass(this.options.activeClass);
40			this.makeCallback('onDropOpen', this);
41		},
42		closeItem: function (menuItem) {
43			menuItem.removeClass(this.options.activeClass);
44			this.makeCallback('onDropClose', this);
45		},
46		closeDrop: function () {
47			var self = this;
48
49			setTimeout(() => {
50				var opened = self.menuItems
51				.filter('.' + self.options.activeClass)
52				.filter(':not(:has([' + self.options.focusAttr + ']))')
53				.removeClass(self.options.activeClass);
54
55				if (opened.length) {
56					this.makeCallback('onDropClose', this);
57				}
58
59				var menuFocus = self.holder.find('[' + self.options.focusAttr + ']');
60				if (menuFocus.length === 0) self.menuItems.removeClass(self.options.activeClass);
61			}, 0);
62		},
63		attachEvents: function () {
64			var self = this;
65
66			this.tabDirectionHandler = function (e) {
67				if (e.which === 9 && e.shiftKey) {
68					self.tabDirection = -1;
69				} else if (e.which === 9) {
70					self.tabDirection = 1;
71				}
72			};
73
74			this.focusHandler = function (e) {
75				var link = jQuery(e.target).attr(self.options.focusAttr, true);
76				var parent = link.closest(self.options.items);
77
78				if (parent.hasClass(self.options.hasChildrenClass) && parent.hasClass(self.options.mainItemClass)) {
79					self.openDrop(parent);
80				}
81			};
82
83			this.enterHandler = function (e) {
84				var link = jQuery(this);
85				var parent = link.closest(self.options.items);
86
87				if (e.keyCode === 13 && parent.hasClass(self.options.hasChildrenClass) && !parent.hasClass(self.options.mainItemClass)) {
88
89					e.preventDefault();
90					e.stopPropagation();
91					e.returnValue = false;
92					e.cancelBubble = true;
93					self.openDrop(parent);
94					return false;
95				}
96			};
97
98			this.blurHandler = function (e) {
99				jQuery(this).removeAttr(self.options.focusAttr);
100
101				self.closeDrop();
102			};
103
104			this.resizeHandler = function () {
105				clearTimeout(self.timer);
106				self.timer = setTimeout(function () {
107					self.menuItems.filter('.' + self.options.hasChildrenClass).each(function () {
108						var item = jQuery(this);
109						var drop = item.find(self.options.drop);
110						if (!drop.length) return;
111
112						item.removeClass(self.options.altClass);
113						drop.offset().left + drop.outerWidth() > self.win.width() && item.addClass(self.options.altClass);
114					}, 100);
115				});
116			};
117
118			this.resizeHandler();
119			this.menuLinks
120				.on('keyup keydown', this.enterHandler);
121
122			this.win.on('resize orientationchange', this.resizeHandler);
123		},
124		destroy: function () {
125			this.menuItems
126				.removeClass(this.options.activeClass)
127				.removeClass(this.options.altClass);
128			this.holder.find('[' + this.options.focusAttr + ']').removeAttr(this.options.focusAttr);
129
130			this.menuLinks
131				.off('focus', this.focusHandler)
132				.off('blur', this.blurHandler);
133			this.win.off('resize orientationchange', this.resizeHandler);
134			this.makeCallback('onDestroy', this);
135		},
136		makeCallback: function (name) {
137			if (typeof this.options[name] === 'function') {
138				var args = Array.prototype.slice.call(arguments);
139				args.shift();
140				this.options[name].apply(this, args);
141			}
142		}
143	};
144
145	$.fn.desktopTabMenu = function (options) {
146		return this.each(function () {
147			$(this).data('DesktopTabMenu', new DesktopTabMenu($.extend(options, { holder: this })));
148		});
149	};
150}(jQuery));

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.