PageSourceSearch

https://www.onpointcu.com/wp-content/themes/onpointcu-theme/js/lib/productComparison.js?ver=20260423.6

js onpointcu.com collected 2026-09-24 09:14:07 UTC 17,560 bytes, 517 lines download raw bytes

1(function($) {
2	$(document).ready(function() {
3		//
4		// Comparison Table
5		//
6		var $compTables = $('.js-comp_table'),
7				$compTablesLength = $compTables.length,
8				$compMoreButtons = $('.js-comp_table_more'),
9				allTableRows = [],
10			initTableRowLevel = function() {
11				if ( layoutView != 'small' && layoutView != 'medium' ) {
12					$compTables.imagesLoaded(function() {
13						for ( var i = 0; i < $compTablesLength; i++ ) {
14							var $curTable = $($compTables[i]);
15									$tableHeaders = $curTable.find('.js-comp_table_title'),
16									tableRows = [],
17									$tableLists = $curTable.find('.js-comp_table_list'),
18									tableListsLength = $tableLists.length;
19							for ( curListKey = 0; curListKey < tableListsLength; curListKey++ ) {
20								var $curList = $($tableLists[curListKey]),
21										$curListItems = $curList.find('.js-comp_table_cell'),
22										curListItemsLength = $curListItems.length;
23								for ( curCellKey = 0; curCellKey < curListItemsLength; curCellKey++ ) {
24									var $curListItem = $($curListItems[curCellKey]);
25									if ( typeof tableRows[curCellKey] == 'undefined' ) tableRows[curCellKey] = [];
26									tableRows[curCellKey].push($curListItem[0]);
27								}
28							}
29							tableRows.push($tableHeaders);
30							allTableRows = allTableRows.concat(tableRows);
31							var tableRowsLength = tableRows.length;
32							for ( var curTableRowKey = 0; curTableRowKey < tableRowsLength; curTableRowKey++ ) {
33								var $curRow = $(tableRows[curTableRowKey]);
34								levelHeight($curRow);
35								if ( $($curRow[0]).hasClass('js-comp_table_more_cell') ) {
36									$curRow.each(function() {
37										$(this).addClass('closed');
38									});
39								}
40							}
41						}
42						setMoreButtonPosition();
43					});
44				}
45			},
46			setMoreButtonPosition = function() {
47				if ( layoutView == 'large' || layoutView == 'xlarge') {
48					for ( var i = 0; i < $compTablesLength; i++ ) {
49						var $curTable = $($compTables[i]),
50								$moreButtons = $curTable.find('.js-comp_table_more');
51						if ( $moreButtons.length > 0 ) {
52							var $curLargeButton = $($moreButtons[0]),
53									$buttonLocation = $($moreButtons[1]),
54									buttonLocationOffset = $buttonLocation.offset(),
55									tableOffset = $curTable.find('.co-comp_table_box').offset(),
56									buttonTop = buttonLocationOffset.top - tableOffset.top;
57							$curLargeButton.css({top: buttonTop});
58						}
59					}
60				}
61			},
62			tableHeightSetting;
63		resetTabelRowLevels = function() {
64			setMoreButtonPosition();
65			if ( layoutView == 'large' || layoutView == 'xlarge' ) {
66				tableHeightSetting = levelHeight;
67			} else {
68				tableHeightSetting = resetHeights;
69			}
70			var tableRowsLength = allTableRows.length;
71			for ( var i = 0; i < tableRowsLength; i++ ) {
72				tableHeightSetting(allTableRows[i]);
73			}
74		}
75		var toggleCompMore = function(x) {
76				var $x = $(x),
77						parentSelector = '';
78				if ( layoutView == 'large' || layoutView == 'xlarge') {
79					// if at the larger layout toggle all of the rows
80					parentSelector = '.co-comp_table_box';
81				} else {
82					// if at smaller layout toggle just this column
83					parentSelector = '.co-comp_table';
84				}
85				var $itemsToToggle = $x.parents(parentSelector).find('.js-comp_table_more_cell');
86				if ( $x.hasClass('closed') ) {
87					$itemsToToggle.removeClass('closed');
88					$x.removeClass('closed');
89				} else {
90					$itemsToToggle.addClass('closed');
91					$x.addClass('closed');
92				}
93			},
94			redrawComparisonSlider = function($tabPanel) {
95				var $childSlider = $tabPanel.find('.bx-wrapper .co-comp_table_wrap');
96				if ( $childSlider.length ) {
97					$childSlider = $childSlider.data('slider');
98					$childSlider.redrawSlider();
99				}
100			},
101			getCompTableSliderFromNav = function(x) {
102				return $(x)
103					.parents('.co-flex_row')
104					.find('.bx-wrapper .co-comp_table_wrap')
105					.data('slider');
106			},
107			prevCompTableSlide = function(x) {
108				var curSlider = getCompTableSliderFromNav(x);
109				curSlider.goToPrevSlide();
110			},
111			nextCompTableSlide = function(x) {
112				var curSlider = getCompTableSliderFromNav(x);
113				curSlider.goToNextSlide();
114			}
115		initCompTableCarousel = function() {
116			checkLayout();
117			if ( layoutView == 'small' || layoutView == 'medium' ) {
118				var $compTableSliders = $('.js-comp_table'),
119						compTableSlidersLength = $compTableSliders.length;
120				for ( var i = 0; i < compTableSlidersLength; i++ ) {
121					var $curTable = $($compTableSliders[i]),
122							sliderSettings = {
123								useCSS: false,
124								pager: false,
125								infiniteLoop: false,
126								adaptiveHeight: true,
127								slideSelector: '.co-comp_table:not(.co-comp_table__key_0)',
128								controls: false,
129								preventDefaultSwipeY: false,
130								onSliderLoad: function() {
131									$(this[0]).data('slider', this);
132								}
133							},
134							curSlider = $curTable
135								.find('.co-comp_table_wrap')
136								.bxSlider(sliderSettings);
137				}
138			}
139		};
140		$compMoreButtons.click(function() {
141			if ( layoutView == 'large' || layoutView == 'xlarge' ) {
142				toggleCompMore(this);
143			}
144		});
145		$compMoreButtons.on('touchstart', function(){
146			if ( layoutView == 'small' || layoutView == 'medium' ) {
147				toggleCompMore(this);
148			}
149		});
150		$('.js-comp_table_prev').click(function() {
151			prevCompTableSlide(this);
152		});
153		$('.js-comp_table_next').click(function() {
154			nextCompTableSlide(this);
155		});
156		initTableRowLevel();
157		initCompTableCarousel();
158	});
159
160	//
161	// Scroll Button and Dot Navigation and Accordion functionality
162	//
163	$('.co-comp_table-mobile-section').each(function() {
164		const $table_scroll_section = $(this);
165		const $table_scroll_container = $table_scroll_section.find('.scrollContainer');
166		const $table_scroll_button = $table_scroll_section.find('.scrollBtn');
167		const $dot_navs = $table_scroll_section.find('.table-mobile-dot-nav');
168		var scrollRight = true;
169		
170		// Check if two-columns class is present and hide navigation elements
171		const $mobileTable = $table_scroll_section.find('.co-comp_table-mobile');
172		if ($mobileTable.hasClass('co-comp_table-mobile-two-columns')) {
173			$table_scroll_section.find('.co-comp_table-mobile--scroll_button').hide();
174			$table_scroll_section.find('.co-comp_table-mobile--dots').hide();
175		}
176		
177		// Calculate scrollStep based on accordion column width
178		function getScrollStep() {
179			const $firstAccordionColumn = $table_scroll_section.find('.co-comp_table-mobile--accordion_column').first();
180			if ($firstAccordionColumn.length > 0) {
181				return $firstAccordionColumn.outerWidth(true) + 20; // Include margin and padding
182			}
183			return 150; // Fallback to original value if no columns found
184		}
185
186		// Function to update scroll button state
187		function updateScrollButtonState() {
188			const scrollLeft = $table_scroll_container.scrollLeft();
189			const containerWidth = $table_scroll_container.outerWidth();
190			const scrollWidth = $table_scroll_container[0].scrollWidth;
191			//const maxScroll = scrollWidth - containerWidth;
192
193			const atEnd = scrollLeft + containerWidth >= scrollWidth - 1;
194			const atStart = scrollLeft <= 0;
195
196			// Update scroll button state
197			if (atEnd) {
198				scrollRight = false;
199				$table_scroll_button.css('transform', 'scaleX(-1)');
200			} else if (atStart) {
201				scrollRight = true;
202				$table_scroll_button.css('transform', 'scaleX(1)');
203			}
204
205			// Update dot navigation state
206			$dot_navs.removeClass('active');
207			if (atStart) {
208				$dot_navs.filter('[data-position="start"]').addClass('active');
209			} else if (atEnd) {
210				$dot_navs.filter('[data-position="end"]').addClass('active');
211			} else {
212				$dot_navs.filter('[data-position="middle"]').addClass('active');
213			}
214		}
215
216		// Function to scroll to position
217		function scrollToPosition(position) {
218			const containerWidth = $table_scroll_container.outerWidth();
219			const scrollWidth = $table_scroll_container[0].scrollWidth;
220			const maxScroll = scrollWidth - containerWidth;
221			let targetScroll;
222
223			switch(position) {
224				case 'start':
225					targetScroll = 0;
226					break;
227				case 'end':
228					targetScroll = maxScroll;
229					break;
230				case 'middle':
231					targetScroll = maxScroll / 2;
232					break;
233			}
234
235			$table_scroll_container.animate({
236				scrollLeft: targetScroll
237			}, 300, function() {
238				updateScrollButtonState();
239			});
240		}
241
242		// Listen for manual scrolling
243		$table_scroll_container.on('scroll', function() {
244			updateScrollButtonState();
245		});
246
247		// Handle dot navigation clicks
248		$dot_navs.on('click', function() {
249			const position = $(this).data('position');
250			scrollToPosition(position);
251		});
252
253		$table_scroll_button.on('click', function (e) {
254			e.preventDefault();
255			const scrollStep = getScrollStep();
256			const newScroll = scrollRight ? scrollStep : -scrollStep;
257
258			$table_scroll_container.animate({
259				scrollLeft: $table_scroll_container.scrollLeft() + newScroll
260			}, 300, function () {
261				updateScrollButtonState();
262			});
263		});
264		
265		//
266		// Accordion functionality
267		//
268		const $accordionItems = $table_scroll_section.find('.co-comp_table-mobile--accordion_item');
269
270		// Add click handler to accordion titles
271		$accordionItems.each(function() {
272			const $item = $(this);
273			const $title = $item.find('.co-comp_table-mobile--accordion_title');
274			const $title_wrap = $item.find('.co-comp_table-mobile--accordion_title-text-wrap');
275			const $content = $item.find('.co-comp_table-mobile--accordion_columns_wrap');
276			
277			// Add indicator span
278			$title_wrap.append('<span class="accordion-indicator">-</span>');
279			
280			// Add click handler to title
281			$title.on('click', function() {
282				const isExpanded = $item.hasClass('expanded');
283				
284				// Toggle current item
285				$item.toggleClass('expanded');
286				$content.slideToggle(300);
287				
288				// Update indicator
289				$title.find('.accordion-indicator').text(isExpanded ? '+' : '-');
290				
291				// Update aria attributes
292				$title.attr('aria-expanded', !isExpanded);
293			});
294			
295			// Set initial state
296			$item.addClass('expanded');
297			$title.attr('aria-expanded', 'true');
298			$title.attr('role', 'button');
299			$title.attr('tabindex', '0');
300		});
301
302		//
303		// Handle hide more button visibility
304		//
305		const $allAccordionItems = $table_scroll_section.find('.co-comp_table-mobile--accordion_item');
306		const $itemsWithMoreButton = $allAccordionItems.filter(function() {
307			return $(this).find('.co-comp_table--more_button').length > 0;
308		});
309		if ($itemsWithMoreButton.length > 0) {
310			$itemsWithMoreButton.hide();
311		}
312
313		//
314		// Handle show differences checkbox
315		//
316		const $showDifferencesCheckbox = $table_scroll_section.find('.co-comp_table-mobile-show-differences');
317		
318		// Function to get content hash for a single column
319		function getColumnContentHash($column) {
320			// Get the exact HTML content of the column
321			return $column.html().trim();
322		}
323
324		// Function to check if all columns in an accordion have identical content
325		function allColumnsIdentical($accordionItem) {
326			const $columns = $accordionItem.find('.co-comp_table-mobile--accordion_column');
327			if ($columns.length <= 1) {
328				return false; // Don't collapse if there's only one column
329			}
330			
331			const firstColumnContent = getColumnContentHash($columns.first());
332			
333			// Check if all columns have the same content as the first column
334			return $columns.toArray().every(function(column) {
335				return getColumnContentHash($(column)) === firstColumnContent;
336			});
337		}
338		
339		// Function to find accordions where all columns have identical content
340		function findAccordionsWithIdenticalColumns() {
341			const accordionsToCollapse = [];
342			
343			$accordionItems.each(function() {
344				const $item = $(this);
345				if (allColumnsIdentical($item)) {
346					accordionsToCollapse.push($item);
347				}
348			});
349			
350			return accordionsToCollapse;
351		}
352		
353		$showDifferencesCheckbox.on('change', function() {
354			const isChecked = $(this).is(':checked');
355			
356			if (isChecked) {
357				// Find and collapse accordions where all columns have identical content
358				const accordionsToCollapse = findAccordionsWithIdenticalColumns();
359				
360				accordionsToCollapse.forEach($item => {
361					const $title = $item.find('.co-comp_table-mobile--accordion_title');
362					const $content = $item.find('.co-comp_table-mobile--accordion_columns_wrap');
363					const $indicator = $title.find('.accordion-indicator');
364					
365					$item.removeClass('expanded');
366					$content.slideUp(300);
367					$indicator.text('+');
368					$title.attr('aria-expanded', 'false');
369				});
370			} else {
371				// Expand all accordions
372				$accordionItems.each(function() {
373					const $item = $(this);
374					const $title = $item.find('.co-comp_table-mobile--accordion_title');
375					const $content = $item.find('.co-comp_table-mobile--accordion_columns_wrap');
376					const $indicator = $title.find('.accordion-indicator');
377					
378					$item.addClass('expanded');
379					$content.slideDown(300);
380					$indicator.text('-');
381					$title.attr('aria-expanded', 'true');
382				});
383			}
384		});
385
386		//
387		// Handle pin-to-compare select functionality
388		//
389		const $pinToCompareSelect = $table_scroll_section.find('.co-comp_table-mobile-pin-to-compare');
390		
391		// Function to reorder columns based on selected value
392		function reorderColumns(selectedValue) {
393			const $titlesContainer = $table_scroll_section.find('.co-comp_table-mobile--titles');
394			const $allTitles = $titlesContainer.find('.co-comp_table-mobile--title');
395			
396			if (selectedValue === 'all') {
397				// Reset to original order - sort titles by their key number
398				const titlesArray = $allTitles.toArray();
399				titlesArray.sort(function(a, b) {
400					const aKey = parseInt($(a).attr('class').match(/comp_table-mobile--title__key_(\d+)/)?.[1] || 0);
401					const bKey = parseInt($(b).attr('class').match(/comp_table-mobile--title__key_(\d+)/)?.[1] || 0);
402					return aKey - bKey;
403				});
404				
405				// Clear container and append in sorted order
406				$titlesContainer.empty();
407				titlesArray.forEach(function(title) {
408					$titlesContainer.append(title);
409				});
410				
411				// Remove sticky class when showing all
412				$table_scroll_section.removeClass('has-pinned-column');
413			} else {
414				// Find the selected column and move it to the first position
415				const $selectedTitle = $titlesContainer.find('.comp_table-mobile--title__key_' + selectedValue);
416				
417				if ($selectedTitle.length > 0) {
418					// Move the selected title to the beginning
419					$titlesContainer.prepend($selectedTitle);
420					
421					// Add sticky class when a specific column is pinned
422					$table_scroll_section.addClass('has-pinned-column');
423				}
424			}
425			
426			// Also reorder the accordion columns to match
427			reorderAccordionColumns(selectedValue);
428			
429			// Reset horizontal scroll to the left after reordering
430			$table_scroll_container.animate({
431				scrollLeft: 0
432			}, 300, function() {
433				updateScrollButtonState();
434			});
435		}
436		
437		// Function to reorder accordion columns to match the title order
438		function reorderAccordionColumns(selectedValue) {
439			$accordionItems.each(function() {
440				const $item = $(this);
441				const $columnsWrap = $item.find('.co-comp_table-mobile--accordion_columns_wrap');
442				const $allColumns = $columnsWrap.find('.co-comp_table-mobile--accordion_column');
443				
444				if (selectedValue === 'all') {
445					// Reset to original order - sort columns by their key number
446					const columnsArray = $allColumns.toArray();
447					columnsArray.sort(function(a, b) {
448						const aKey = parseInt($(a).attr('class').match(/comp_table-mobile--accordion_column__key_(\d+)/)?.[1] || 0);
449						const bKey = parseInt($(b).attr('class').match(/comp_table-mobile--accordion_column__key_(\d+)/)?.[1] || 0);
450						return aKey - bKey;
451					});
452					
453					// Clear container and append in sorted order
454					$columnsWrap.empty();
455					columnsArray.forEach(function(column) {
456						$columnsWrap.append(column);
457					});
458				} else {
459					// Find the selected column and move it to the first position
460					const $selectedColumn = $columnsWrap.find('.comp_table-mobile--accordion_column__key_' + selectedValue);
461					
462					if ($selectedColumn.length > 0) {
463						// Move the selected column to the beginning
464						$columnsWrap.prepend($selectedColumn);
465					}
466				}
467			});
468		}
469		
470		// Handle select change event
471		$pinToCompareSelect.on('change', function() {
472			const selectedValue = $(this).val();
473			reorderColumns(selectedValue);
474		});
475	});
476
477	function syncAutoLoanRatesPills($root, $snap) {
478		const w = $snap.outerWidth();
479		if (!w) {
480			return;
481		}
482		const idx = Math.round($snap.scrollLeft() / w);
483		const $pills = $root.find('.co-auto_loan_rates-mobile--pill_tablist [role="tab"]');
484		$pills.removeClass('is-active').attr('aria-selected', 'false').attr('tabindex', '-1');
485		const $active = $pills.filter('[data-panel-index="' + idx + '"]');
486		if ($active.length) {
487			$active.addClass('is-active').attr('aria-selected', 'true').attr('tabindex', '0');
488		}
489	}
490
491	$('.js-auto_loan_rates_root').each(function() {
492		const $root = $(this);
493		const $snap = $root.find('.js-auto_loan_panels_snap');
494		if (!$snap.length) {
495			return;
496		}
497		const $pills = $root.find('.co-auto_loan_rates-mobile--pill_tablist [role="tab"]');
498		$pills.on('click', function() {
499			const idx = parseInt($(this).data('panel-index'), 10);
500			const w = $snap.outerWidth();
501			$snap.animate({ scrollLeft: idx * w }, 300, function() {
502				syncAutoLoanRatesPills($root, $snap);
503			});
504		});
505		let scrollTimer;
506		$snap.on('scroll', function() {
507			clearTimeout(scrollTimer);
508			scrollTimer = setTimeout(function() {
509				syncAutoLoanRatesPills($root, $snap);
510			}, 80);
511		});
512		$(window).on('resize', function() {
513			syncAutoLoanRatesPills($root, $snap);
514		});
515		syncAutoLoanRatesPills($root, $snap);
516	});
517})(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.