PageSourceSearch

https://www.omnidian.com/wp-content/plugins/plethora-tabs-accordions/js/accordion.jquery-plugin.js?ver=1.1.3

js omnidian.com collected 2026-10-03 19:31:37 UTC 10,765 bytes, 378 lines download raw bytes

1(function($) {
2	'use strict';
3	
4	const dataNS = 'pds-tabs--';
5	/**
6	 * Accordion plugin function
7	 *
8	 * @param object options Plugin settings to override the defaults
9	 */
10	$.fn.pdsAccordionItem = function(options) {
11		const defaultAccordionIcon = '<span class="pds-accordion__icon" role="presentation" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 12 7.4099998" ><path d="M12 1.41 10.59 0 6 4.58 1.41 0 0 1.41l6 6z" fill="currentColor"></path></svg></span>';
12		const iconClass = 'pds-accordion__icon';
13
14		var settings = $.extend({
15			// Set default settings
16			initiallyOpen: false,
17			autoClose:     true,
18			clickToClose:  true,
19			scroll:        false,
20			scrollOffset:  false,
21			icon: true, /*
22				true: default icon. 
23				false: hide the icon 
24				'<svg>...</svg>': custom markup for a single-state icon. 180 degree rotation will be applied when the state of the accordion item is open.
25				{closed: '<b>+</b>', open:'<b>-</b>'}: custom markup for a two-state icon
26				*/
27			iconSize: '', 
28		}, options);
29
30		var duration = 250;
31		var hashID = window.location.hash.replace('#', '');
32
33		var item = {};
34
35		item.self       = $(this);
36		item.id         = $(this).attr('id');
37		item.controller = $(this).find('.pds-js-accordion-controller');
38		item.uuid       = getAccordionItemUUID(item.self);
39		item.content    = $('#ac-' + item.uuid);
40		item.accordionGroupItems = [item.uuid];
41		item.accordionAncestorItems = [];
42		initialSetup();
43		
44
45
46		/**
47		 * Initial setup
48		 * Set the scroll offset, and figure out which items should be open by
49		 * default.
50		 */
51		function initialSetup() {
52			// Remove the 'pds-no-js' class since JavaScript is enabled
53			item.self.removeClass('pds-no-js');
54			/**
55			 * Set up some defaults for this controller
56			 */
57			item.controller.attr({
58				'tabindex': 0,
59				'aria-controls': 'ac-' + item.uuid,
60				'role': 'button'
61			});
62			
63			if(!item.controller.attr('id')) item.controller.id(item.uuid + '_acc_header');
64			item.content.attr({
65				'role':'region',
66				'aria-labelledby':item.controller.attr('id')
67			});
68
69			settings.scrollOffset = Math.floor(parseInt(settings.scrollOffset, 10)) || 0;
70
71			/**
72			 * Add any sibling accordion items to the accordionGroupItems array.
73			 */
74			$.each(item.self.siblings('.pds-js-accordion-item'), function(index, ele) {
75				var uuid = getAccordionItemUUID(ele);
76
77				item.accordionGroupItems.push(uuid);
78			});
79
80			/**
81			 * Add any parent accordion items to the accordionAncestorItems array.
82			 */
83			$.each(item.self.parents('.pds-js-accordion-item'), function(index, ele) {
84				var uuid = getAccordionItemUUID(ele);
85
86				item.accordionAncestorItems.push(uuid);
87			});
88
89			// If this item has `initially-open prop` set to true, open it
90			if (settings.initiallyOpen) {
91				/**
92				 * We aren't opening the item here (only setting open attributes)
93				 * because the openItem() function fires the `pds-openAccordionItem`
94				 * event which, if `autoClose` is set, would override the users
95				 * defined initiallyOpen settings.
96				 *
97				 * Only setting open attributes is fine since the item's content
98				 * display (`display: none|block`) is already set by the plugin.
99				 */
100				setOpenItemAttributes();
101			}
102			// If the hash matches this item, open it
103			else if (item.id === hashID) {
104				/**
105				 * Unlike the `initiallyOpen` case above, if a hash is detected
106				 * that matches one of the accordion items, we probably _want_
107				 * the other items to close so the user can focus on this item.
108				 */
109				openItem();
110
111				// Open ancestors if necessary
112				$.each(item.accordionAncestorItems, function(index, uuid) {
113					$(document).trigger('pds-openAncestorAccordionItem', uuid);
114				});
115			}
116			// Otherwise, close the item
117			else {
118				/**
119				 * Don't use closeItem() function call since it animates the
120				 * closing. Instead, we only need to set the closed attributes.
121				 */
122				setCloseItemAttributes();
123			}
124			adjustIcon();
125		}
126
127		function adjustIcon(){
128			if(!settings.icon) {
129				item.controller.find('.' + iconClass).remove();
130				return;
131			}
132			var $icon = item.controller.find('.' + iconClass);
133			if(!$icon.length)  {
134				$icon = $(defaultAccordionIcon);
135				item.controller.append($icon);
136			}
137			$icon.css('width', settings.iconSize).css('height', settings.iconSize)
138			if(settings.icon !== true){
139				if (typeof settings.icon === 'string') {
140					$icon.addClass(iconClass + '--custom').empty().append(settings.icon);
141				}
142				else if (typeof settings.icon === 'object' && settings.icon.open && settings.icon.closed){
143					//must be a two-state icon definition
144					var $closed = $('<span/>').addClass(iconClass + '--closed').append(settings.icon.closed);
145					var $open = $('<span/>
145').addClass(iconClass + '--open').append(settings.icon.open);
146					$icon.addClass(iconClass + '--two-state').empty().append($closed).append($open)
147				}
148			}
149		}
150
151
152		/**
153		 * Default click function
154		 * Called when an accordion controller is clicked.
155		 */
156		function clickHandler() {
157			// Only open the item if item isn't already open
158			if (!item.self.hasClass('is-open')) {
159				// Open clicked item
160				openItem();
161			}
162			// If item is open, and click to close is set, close it
163			else if (settings.clickToClose) {
164				closeItem();
165			}
166
167			return false;
168		}
169
170
171
172		/**
173		 * Get the accordion item UUID for a given accordion item DOM element.
174		 */
175		function getAccordionItemUUID(ele) {
176			return $(ele).find('.pds-js-accordion-controller').attr('id').replace('at-', '');
177		}
178
179
180
181		/**
182		 * Opens an accordion item
183		 * Also handles accessibility attribute settings.
184		 */
185		function openItem(doNotPushState) {
186			setOpenItemAttributes();
187
188			// Clear/stop any previous animations before revealing content
189			item.content.clearQueue().stop().slideDown(duration, function() {
190				// Scroll page to the title
191				if (settings.scroll) {
192					// Pause scrolling until other items have closed
193					setTimeout(function() {
194						$('html, body').animate({
195							scrollTop: item.self.offset().top - settings.scrollOffset
196						}, duration);
197					}, duration);
198				}
199			});
200
201			$(document).trigger('pds-openAccordionItem', item);
202			
203			if(!doNotPushState) {
204				const newHash = '#' + item.id;
205				if(newHash !== window.location.hash) history.pushState(undefined, undefined, newHash);
206			}
207		}
208
209
210
211		/**
212		 * Set open item attributes
213		 * Mark accordion item as open and read and set aria attributes.
214		 */
215		function setOpenItemAttributes() {
216			item.self.addClass('is-open is-read');
217			item.controller.attr('aria-expanded', true);
218			item.content.prop('hidden', false);
219		}
220
221
222
223		/**
224		 * Closes an accordion item
225		 * Also handles accessibility attribute settings.
226		 */
227		function closeItem() {
228			// Close the item
229			item.content.slideUp(duration, function() {
230				setCloseItemAttributes();
231			});
232		}
233
234
235
236		/**
237		 * Set closed item attributes
238		 * Mark accordion item as closed and set aria attributes.
239		 */
240		function setCloseItemAttributes() {
241			item.self.removeClass('is-open');
242			item.controller.attr('aria-expanded', false);
243			item.content.attr('hidden', true);
244		}
245
246
247
248		/**
249		 * Close all items if auto close is enabled
250		 */
251		function maybeCloseItem() {
252			if (settings.autoClose && item.self.hasClass('is-open')) {
253				closeItem();
254			}
255		}
256
257
258
259		/**
260		 * Add event listeners
261		 */
262		item.controller.on('click', clickHandler);
263
264
265
266		/**
267		 * Listen for other accordion items opening
268		 *
269		 * The `pds-openAccordionItem` event is fired whenever an accordion item is
270		 * opened after initial plugin setup.
271		 */
272		$(document).on('pds-openAccordionItem', function(event, ele) {
273			/**
274			 * Only trigger potential close these conditions are met:
275			 *
276			 * 1. This isn't the item the user just clicked to open.
277			 * 2. This accordion is in the same group of accordions as the one
278			 *    that was just clicked to open.
279			 * 3. This accordion is not an ancestor of the item that was just
280			 *    clicked to open.
281			 *
282			 * This serves two purposes:
283			 *
284			 * 1. It allows nesting of accordions to work.
285			 * 2. It allows users to group accordions to control independently
286			 *    of other groups of accordions.
287			 * 3. It allows child accordions to be opened via hash change
288			 *    without automatically closing the parent accordion, therefore
289			 *    hiding the accordion the user just indicated they wanted open.
290			 */
291			if (
292				ele !== item &&
293				ele.accordionGroupItems.indexOf(item.uuid) > 0 &&
294				ele.accordionAncestorItems.indexOf(item.uuid) === -1
295			) {
296				maybeCloseItem();
297			}
298		});
299
300
301
302		/**
303		 * Listen for ancestor opening requests
304		 *
305		 * The `pds-openAncestorAccordionItem` event is fired whenever a nested
306		 * accordion item is opened, but the ancestors may also need to be
307		 * opened.
308		 */
309		$(document).on('pds-openAncestorAccordionItem', function(event, uuid) {
310			if (uuid === item.uuid) {
311				openItem(true);
312			}
313		});
314
315
316
317		item.controller.on('keydown', function(event) {
318			var code = event.which;
319
320			if (item.controller.prop('tagName') !== 'BUTTON') {
321				// 13 = Return, 32 = Space
322				if ((code === 13) || (code === 32)) {
323					// Simulate click on the controller
324					$(this).click();
325				}
326			}
327
328			// 27 = Esc
329			if (code === 27) {
330				maybeCloseItem();
331			}
332		});
333
334		// Listen for hash changes (in page jump links for accordions)
335		$(window).on('hashchange', function() {
336			hashID = window.location.hash.replace('#', '');
337
338			// Only open this item if the has matches the ID
339			if (hashID === item.id) {
340				var ele = $('#' + hashID);
341
342				// If there is a hash and the hash is on an accordion item
343				if (ele.length && ele.hasClass('pds-js-accordion-item')) {
344					// Open clicked item
345					openItem(true);
346
347					// Open ancestors if necessary
348					$.each(item.accordionAncestorItems, function(index, uuid) {
349						$(document).trigger('pds-openAncestorAccordionItem', uuid);
350					});
351				}
352			}
353		});
354
355		return this;
356	};
357
358
359	function initializeNewAccordions(){
360		$('.pds-js-accordion-item.pds-no-js').each(function() {
361			var fromData = {
362				// Set default settings
363				initiallyOpen: $(this).data(dataNS + 'initially-open'),
364				autoClose:     $(this).data(dataNS + 'auto-close'),
365				clickToClose:  $(this).data(dataNS + 'click-to-close'),
366				scroll:        $(this).data(dataNS + 'scroll'),
367				scrollOffset:  $(this).data(dataNS + 'scroll-offset'),
368				icon:  		   $(this).data(dataNS + 'icon'),
369				iconSize:  	   $(this).data(dataNS + 'iconSize'),
370			};
371			$(this).pdsAccordionItem(fromData);
372		});
373	}
374	// Loop through accordion settings objects
375	// Wait for the entire page to load before loading the accordion
376	$(window).on('load', initializeNewAccordions);
377	$(document).on('pds--apply-widgets pds-accordion--apply-widgets', initializeNewAccordions);
378}(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.