PageSourceSearch

https://genarts.xyz/wp-content/themes/miyazaki/assets/js/construct.js?ver=2.2

js genarts.xyz collected 2026-10-09 02:53:29 UTC 20,779 bytes, 839 lines download raw bytes

1// ======================================================================= Namespace
2var miyazaki = miyazaki || {},
3	$ = jQuery;
4
5
6// ======================================================================= Helper Functions
7
8/* OUTPUT AJAX ERRORS */
9
10function miyazakiAjaxErrors( jqXHR, exception ) {
11	if ( jqXHR.status === 0 ) {
12		alert( 'Not connect.n Verify Network.' );
13	} else if ( jqXHR.status == 404 ) {
14		alert( 'Requested page not found. [404]' );
15	} else if ( jqXHR.status == 500 ) {
16		alert( 'Internal Server Error [500].' );
17	} else if ( exception === 'parsererror' ) {
18		alert( 'Requested JSON parse failed.' );
19	} else if ( exception === 'timeout' ) {
20		alert( 'Time out error.' );
21	} else if ( exception === 'abort' ) {
22		alert( 'Ajax request aborted.' );
23	} else {
24		alert( 'Uncaught Error.n' + jqXHR.responseText );
25	}
26}
27
28
29// ======================================================================= Interval Scroll
30miyazaki.intervalScroll = {
31
32	init: function() {
33
34		didScroll = false;
35
36		// Check for the scroll event
37		$( window ).on( 'scroll load', function() {
38			didScroll = true;
39		} );
40
41		// Once every 100ms, check if we have scrolled, and if we have, do the intensive stuff
42		setInterval( function() {
43			if ( didScroll ) {
44				didScroll = false;
45
46				// When this triggers, we know that we have scrolled
47				$( window ).triggerHandler( 'did-interval-scroll' );
48
49			}
50
51		}, 250 );
52
53	},
54
55} // miyazaki.intervalScroll
56
57
58// ======================================================================= Toggles
59miyazaki.toggles = {
60
61	init: function() {
62
63		// Do the toggle
64		miyazaki.toggles.toggle();
65
66	},
67
68	toggle: function() {
69
70		$( '*[data-toggle-target]' ).on( 'click toggle', function( e ) {
71
72			var $toggle = $( this );
73
74			// Get our targets
75			var targetString = $toggle.data( 'toggle-target' );
76
77			if ( targetString == 'next' ) {
78				var $target = $toggle.next();
79			} else {
80				var $target = $( targetString );
81			}
82
83			$target.trigger( 'will-be-toggled' );
84
85			// Get the class to toggle, if specified
86			var classToToggle = $toggle.data( 'class-to-toggle' ) ? $toggle.data( 'class-to-toggle' ) : 'active';
87
88			// Toggle the target of the clicked toggle
89			if ( $toggle.data( 'toggle-type' ) == 'slidetoggle' ) {
90				var duration = $toggle.data( 'toggle-duration' ) ? $toggle.data( 'toggle-duration' ) : '400';
91				$target.slideToggle( duration );
92			} else {
93				$target.toggleClass( classToToggle );
94			}
95
96			// Toggle the toggles
97			$( '*[data-toggle-target="' + targetString + '"]' ).each( function() {
98				$( this ).toggleClass( 'active' );
99			} );
100
101			// Check whether to set focus
102			if ( $toggle.is( '.active' ) && $toggle.data( 'set-focus' ) ) {
103				var $focusElement = $( $toggle.data( 'set-focus' ) );
104
105				if ( $focusElement.length ) {
106					$focusElement.focus();
107				}
108			}
109
110			// Check whether to lock the scroll
111			if ( $toggle.data( 'lock-scroll' ) ) {
112				miyazaki.scrollLock.setTo( true );
113			} else if ( $toggle.data( 'unlock-scroll' ) ) {
114				miyazaki.scrollLock.setTo( false );
115			} else if ( $toggle.data( 'toggle-scroll-lock' ) ) {
116				miyazaki.scrollLock.setTo();
117			}
118
119			$target.trigger( 'toggled' );
120
121			return false;
122
123		} );
124	}
125
126} // miyazaki.toggles
127
128
129// ======================================================================= Cover Modals
130miyazaki.coverModals = {
131
132	init: function() {
133
134		if ( $( '.cover-modal' ).length ) {
135
136			// Add body class when cover modals are active
137			miyazaki.coverModals.addBodyClassOnActive();
138
139			// Reset modal classes on resize
140			miyazaki.coverModals.hideModalOnResize();
141
142			// Close the search modal when the escape key is pressed
143			miyazaki.coverModals.closeSearchOnEscape();
144
145		}
146
147	},
148
149	addBodyClassOnActive: function() {
150
151		$( '.cover-modal' ).on( 'toggled', function() {
152
153			if ( $( this ).hasClass( 'active' ) ) {
154				$( 'body' ).addClass( 'showing-modal' );
155			} else {
156				$( 'body' ).removeClass( 'showing-modal' );
157			}
158
159		} );
160
161	},
162
163	hideModalOnResize: function() {
164
165		$( window ).on( 'resize', function() {
166
167			var $activeModal = $( '.cover-modal.active' );
168
169			if ( $activeModal.length ) {
170
171				var winWidth = $( window ).width(),
172					untoggleAbove = $activeModal.data( 'untoggle-above' ),
173					untoggleBelow = $activeModal.data( 'untoggle-below' );
174
175				if ( untoggleAbove && ( winWidth > untoggleAbove ) || untoggleBelow && ( winWidth < untoggleBelow ) ) {
176					miyazaki.coverModals.untoggleModal( $activeModal );
177				}
178			}
179
180		} );
181
182	},
183
184	closeSearchOnEscape: function() {
185
186		$( document ).keyup( function( e ) {
187			if ( e.keyCode == 27 && $( '.search-overlay' ).hasClass( 'active' ) ) {
188				$( '.search-toggle' ).trigger( 'click' );
189			}
190		} );
191
192	},
193
194	// Untoggle a modal
195	untoggleModal: function( $modal ) {
196
197		$modalToggle = false;
198
199		// If the modal has specified the string (ID or class) used by toggles to target it, untoggle the toggles with that target string.
200		// The modal-target-string must match the string toggles use to target the modal.
201		if ( $modal.data( 'modal-target-string' ) ) {
202			var modalTargetClass = $modal.data( 'modal-target-string' ),
203				$modalToggle = $( '*[data-toggle-target="' + modalTargetClass + '"]' ).first();
204		}
205
206		// If a modal toggle exists, trigger it so all of the toggle options are included
207		if ( $modalToggle && $modalToggle.length ) {
208			$modalToggle.trigger( 'click' );
209
210		// If one doesn't exist, just hide the modal
211		} else {
212			$modal.removeClass( 'active' );
213			$( 'body' ).removeClass( 'showing-modal' );
214		}
215
216	}
217
218} // miyazaki.coverModals
219
220
221// ======================================================================= Element in View
222miyazaki.elementInView = {
223
224	init: function() {
225
226		$targets = $( '.do-spot' );
227		miyazaki.elementInView.run( $targets );
228
229		// Rerun on AJAX content loaded
230		$( window ).on( 'ajax-content-loaded', function() {
231			$targets = $( '.do-spot' );
232			miyazaki.elementInView.run( $targets );
233		} );
234
235	},
236
237	run: function( $targets ) {
238
239		if ( $targets.length ) {
240
241			// Add class indicating the elements will be spotted
242			$targets.each( function() {
243				$( this ).addClass( 'will-be-spotted' );
244			} );
245
246			miyazaki.elementInView.handleFocus( $targets );
247		}
248
249	},
250
251	handleFocus: function( $targets ) {
252
253		winHeight = $( window ).height();
254
255		// Get dimensions of window outside of scroll for performance
256		$( window ).on( 'load resize orientationchange', function() {
257			winHeight = $( window ).height();
258		} );
259
260		$( window ).on( 'resize orientationchange did-interval-scroll', function() {
261
262			var winTop 		= $( window ).scrollTop();
263				winBottom 	= winTop + winHeight;
264
265			// Check for our targets
266			$targets.each( function() {
267
268				var $this = $( this );
269
270				if ( miyazaki.elementInView.isVisible( $this, checkAbove = true ) ) {
271					$this.addClass( 'spotted' ).triggerHandler( 'spotted' );
272				}
273
274			} );
275
276		} );
277
278	},
279
280	// Determine whether the element is in view
281	isVisible: function( $elem, checkAbove ) {
282
283		if ( typeof checkAbove === 'undefined' ) {
284			checkAbove = false;
285		}
286
287		var winHeight 				= $( window ).height();
288
289		var docViewTop 				= $( window ).scrollTop(),
290			docViewBottom			= docViewTop + winHeight,
291			docViewLimit 			= docViewBottom - 50;
292
293		var elemTop 				= $elem.offset().top,
294			elemBottom 				= $elem.offset().top + $elem.outerHeight();
295
296		// If checkAbove is set to true, which is default, return true if the browser has already scrolled past the element
297		if ( checkAbove && ( elemBottom <= docViewBottom ) ) {
298			return true;
299		}
300
301		// If not, check whether the scroll limit exceeds the element top
302		return ( docViewLimit >= elemTop );
303
304	}
305
306} // miyazaki.elementInView
307
308
309// =======================================================================  Mobile Menu
310miyazaki.mobileMenu = {
311
312	init: function() {
313
314		// On mobile menu toggle, scroll to the top
315		miyazaki.mobileMenu.onToggle();
316
317		// On screen resize, check whether to unlock scroll and match the mobile menu wrapper padding to the site header
318		miyazaki.mobileMenu.resizeChecks();
319
320	},
321
322	onToggle: function() {
323
324		$( '.mobile-menu-wrapper' ).on( 'will-be-toggled', function() {
325			window.scrollTo( 0, 0 );
326		} );
327
328	},
329
330	resizeChecks: function() {
331
332		$( window ).on( 'load resize orientationchange', function() {
333
334			// Update the mobile menu wrapper top padding to match the height of the header
335			var $siteHeader = $( '#site-header' ),
336				$mobileMenuWrapper = $( '.mobile-menu-wrapper' );
337				
338			var paddedHeaderHeight = $siteHeader.outerHeight() + 35;
339
340			$mobileMenuWrapper.css( { 'padding-top': paddedHeaderHeight + 'px' } );
341		} );
342
343	}
344
345} // miyazaki.mobileMenu
346
347
348// =======================================================================  Resize videos
349miyazaki.intrinsicRatioEmbeds = {
350
351	init: function() {
352
353		// Resize videos after their container
354		var vidSelector = 'iframe, object, video';
355		var resizeVideo = function( sSel ) {
356			$( sSel ).each( function() {
357				var $video = $( this ),
358					$container = $video.parent(),
359					iTargetWidth = $container.width();
360
361				if ( ! $video.attr( 'data-origwidth' ) ) {
362					$video.attr( 'data-origwidth', $video.attr( 'width' ) );
363					$video.attr( 'data-origheight', $video.attr( 'height' ) );
364				}
365
366				var ratio = iTargetWidth / $video.attr( 'data-origwidth' );
367
368				$video.css( 'width', iTargetWidth + 'px' );
369				$video.css( 'height', ( $video.attr( 'data-origheight' ) * ratio ) + 'px' );
370			});
371		};
372
373		resizeVideo( vidSelector );
374
375		$( window ).resize( function() {
376			resizeVideo( vidSelector );
377		} );
378
379	},
380
381} // miyazaki.intrinsicRatioEmbeds
382
383
384// ======================================================================= Masonry
385miyazaki.masonry = {
386
387	init: function() {
388
389		$wrapper = $( '.posts' );
390
391		if ( $wrapper.length ) {
392
393			$grid = $wrapper.imagesLoaded( function() {
394
395				$grid = $wrapper.masonry( {
396					columnWidth: 		'.grid-sizer',
397					itemSelector: 		'.preview',
398					percentPosition: 	true,
399					stagger: 			0,
400					transitionDuration: 0,
401				} );
402
403			} );
404
405			$grid.on( 'layoutComplete', function() {
406				$( '.posts' ).css( 'opacity', 1 );
407				$( window ).triggerHandler( 'scroll' );
408			} );
409
410		}
411
412	}
413
414} // miyazaki.masonry
415
416
417// =======================================================================  Smooth Scroll
418miyazaki.smoothScroll = {
419
420	init: function() {
421
422		// Scroll to on-page elements by hash.
423		$( 'a[href*="#"]' ).not( '[href="#"]' ).not( '[href="#0"]' ).not( '.disable-hash-scroll' ).on( 'click', function( e ) {
424			if ( location.pathname.replace(/^\//, '' ) == this.pathname.replace(/^\//, '' ) && location.hostname == this.hostname ) {
425				$target = $( this.hash ).length ? $( this.hash ) : $( '[name=' + this.hash.slice(1) + ']' );
426				miyazaki.smoothScroll.scrollToTarget( $target, $( this ) );
427				e.preventDefault();
428			}
429		} );
430
431		// Scroll to elements specified with a data attribute.
432		$( document ).on( 'click', '*[data-scroll-to]', function( e ) {
433			var $target = $( $( this ).data( 'scroll-to' ) );
434			miyazaki.smoothScroll.scrollToTarget( $target, $( this ) );
435			e.preventDefault();
436		} );
437
438	},
439
440	// Scroll to target.
441	scrollToTarget: function( $target, $clickElem ) {
442
443		if ( $target.length ) {
444
445			var additionalOffset 	= 0,
446				timeOutTime			= 0;
447
448			// Close any parent modal before calculating offset and scrolling.
449			// Also, set a timeout, to make sure elements have the correct offset before we scroll.
450			if ( $clickElem && $clickElem.closest( '.cover-modal' ) ) {
451				miyazaki.coverModals.untoggleModal( $clickElem.closest( '.cover-modal' ) );
452				timeOutTime = 5;
453			}
454
455			setTimeout( function() {
456
457				// Determine offset.
458				var scrollOffset = $target.offset().top + additionalOffset;
459
460				// Scroll to position.
461				miyazaki.smoothScroll.scrollToPosition( scrollOffset );
462
463			}, timeOutTime );
464
465		}
466
467	},
468
469	// Scroll to position.
470	scrollToPosition: function( scrollOffset ) {
471
472		// Animate.
473		$( 'html, body' ).animate( {
474			scrollTop: scrollOffset,
475		}, 500, function() {
476			$( window ).trigger( 'did-interval-scroll' );
477		} );
478
479	}
480
481} // miyazaki.smoothScroll
482
483
484// =======================================================================  Scroll Lock
485miyazaki.scrollLock = {
486
487	init: function() {
488
489		// Init variables
490		window.scrollLocked = false,
491		window.prevScroll = {
492			scrollLeft : $( window ).scrollLeft(),
493			scrollTop  : $( window ).scrollTop()
494		},
495		window.prevLockStyles = {},
496		window.lockStyles = {
497			'overflow-y' : 'scroll',
498			'position'   : 'fixed',
499			'width'      : '100%'
500		};
501
502		// Instantiate cache in case someone tries to unlock before locking
503		miyazaki.scrollLock.saveStyles();
504
505	},
506
507	// Save context's inline styles in cache
508	saveStyles: function() {
509
510		var styleAttr = $( 'html' ).attr( 'style' ),
511			styleStrs = [],
512			styleHash = {};
513
514		if ( ! styleAttr ) {
515			return;
516		}
517
518		styleStrs = styleAttr.split( /;\s/ );
519
520		$.each( styleStrs, function serializeStyleProp( styleString ) {
521			if ( ! styleString ) {
522				return;
523			}
524
525			var keyValue = styleString.split( /\s:\s/ );
526
527			if ( keyValue.length < 2 ) {
528				return;
529			}
530
531			styleHash[ keyValue[ 0 ] ] = keyValue[ 1 ];
532		} );
533
534		$.extend( prevLockStyles, styleHash );
535	},
536
537	// Lock the scroll (do not call this directly)
538	lock: function() {
539
540		var appliedLock = {};
541
542		if ( scrollLocked ) {
543			return;
544		}
545
546		// Save scroll state and styles
547		prevScroll = {
548			scrollLeft : $( window ).scrollLeft(),
549			scrollTop  : $( window ).scrollTop()
550		};
551
552		miyazaki.scrollLock.saveStyles();
553
554		// Compose our applied CSS, with scroll state as styles
555		$.extend( appliedLock, lockStyles, {
556			'left' : - prevScroll.scrollLeft + 'px',
557			'top'  : - prevScroll.scrollTop + 'px'
558		} );
559
560		// Then lock styles and state
561		$( 'html' ).css( appliedLock );
562		$( window ).scrollLeft( 0 ).scrollTop( 0 );
563
564		scrollLocked = true;
565	},
566
567	// Unlock the scroll (do not call this directly)
568	unlock: function() {
569
570		if ( ! scrollLocked ) {
571			return;
572		}
573
574		// Revert styles and state
575		$( 'html' ).attr( 'style', $( '<x>' ).css( prevLockStyles ).attr( 'style' ) || '' );
576		$( window ).scrollLeft( prevScroll.scrollLeft ).scrollTop( prevScroll.scrollTop );
577
578		scrollLocked = false;
579	},
580
581	// Call this to lock or unlock the scroll
582	setTo: function( on ) {
583
584		// If an argument is passed, lock or unlock accordingly
585		if ( arguments.length ) {
586			if ( on ) {
587				miyazaki.scrollLock.lock();
588			} else {
589				miyazaki.scrollLock.unlock();
590			}
591			// If not, toggle to the inverse state
592		} else {
593			if ( scrollLocked ) {
594				miyazaki.scrollLock.unlock();
595			} else {
596				miyazaki.scrollLock.lock();
597			}
598		}
599
600	},
601
602} // miyazaki.scrollLock
603
604
605// ==================================================================== Load More
606miyazaki.loadMore = {
607
608	init: function() {
609
610		var $pagination = $( '#pagination' );
611
612		// First, check that there's a pagination
613		if ( $pagination.length ) {
614
615			// Default values for variables
616			window.loading = false;
617			window.lastPage = false;
618
619			miyazaki.loadMore.prepare( $pagination );
620
621		}
622
623	},
624
625	prepare: function( $pagination ) {
626
627		// Get the query arguments from the pagination element
628		var query_args = JSON.parse( $pagination.attr( 'data-query-args' ) );
629
630		// If we're already at the last page, exit out here
631		if ( query_args.paged == query_args.max_num_pages ) {
632			$pagination.addClass( 'last-page' );
633		} else {
634			$pagination.removeClass( 'last-page' );
635		}
636
637		// Get the load more setting
638		var loadMoreType = 'button';
639		if ( $( 'body' ).hasClass( 'pagination-type-scroll' ) ) {
640			loadMoreType = 'scroll';
641		} else if ( $( 'body' ).hasClass( 'pagination-type-links' ) ) {
642			// No JS needed – exit out
643			return;
644		}
645
646		// Do the appropriate load more detection, depending on the type
647		if ( loadMoreType == 'scroll' ) {
648			miyazaki.loadMore.detectScroll( $pagination, query_args );
649		} else if ( loadMoreType == 'button' ) {
650			miyazaki.loadMore.detectButtonClick( $pagination, query_args );
651		}
652
653	},
654
655	// Load more on scroll
656	detectScroll: function( $pagination, query_args ) {
657
658		$( window ).on( 'did-interval-scroll', function() {
659
660			// If it's the last page, or we're already loading, we're done here
661			if ( lastPage || loading ) {
662				return;
663			}
664
665			var paginationOffset 	= $pagination.offset().top,
666				winOffset 			= $( window ).scrollTop() + $( window ).outerHeight();
667
668			// If the bottom of the window is below the top of the pagination, start loading
669			if ( ( winOffset > paginationOffset ) ) {
670				miyazaki.loadMore.loadPosts( $pagination, query_args );
671			}
672
673		} );
674
675	},
676
677	// Load more on click
678	detectButtonClick: function( $pagination, query_args ) {
679
680		// Load on click
681		$( '#load-more' ).on( 'click', function() {
682
683			// Make sure we aren't already loading
684			if ( loading ) {
685				return;
686			}
687
688			miyazaki.loadMore.loadPosts( $pagination, query_args );
689			return false;
690		} );
691
692	},
693
694	// Load the posts
695	loadPosts: function( $pagination, query_args ) {
696
697		// We're now loading
698		loading = true;
699		$pagination.addClass( 'loading' ).removeClass( 'last-page' );
700
701		// Increment paged to indicate another page has been loaded
702		query_args.paged++;
703
704		// Prepare the query args for submission
705		var json_query_args = JSON.stringify( query_args );
706
707		$.ajax({
708			url: miyazaki_ajax_load_more.ajaxurl,
709			type: 'post',
710			data: {
711				action: 'miyazaki_ajax_load_more',
712				json_data: json_query_args
713			},
714			success: function( result ) {
715
716				// Get the results
717				var $result = $( result ),
718					$articleWrapper = $( $pagination.data( 'load-more-target' ) );
719
720				// If there are no results, we're at the last page
721				if ( ! $result.length ) {
722					loading = false;
723					$articleWrapper.addClass( 'no-results' );
724					$pagination.addClass( 'last-page' ).removeClass( 'loading' );
725				}
726
727				if ( $result.length ) {
728
729					$articleWrapper.removeClass( 'no-results' );
730
731					// Wait for the images to load
732					$result.imagesLoaded( function() {
733
734						// Append the results
735						$articleWrapper.append( $result ).masonry( 'appended', $result ).masonry();
736
737						$( window ).triggerHandler( 'ajax-content-loaded' );
738						$( window ).triggerHandler( 'did-interval-scroll' );
739
740						// Update history
741						miyazaki.loadMore.updateHistory( query_args.paged );
742
743						// We're now finished with the loading
744						loading = false;
745						$pagination.removeClass( 'loading' );
746
747						// If that was the last page, make sure we don't check for any more
748						if ( query_args.paged == query_args.max_num_pages ) {
749							$pagination.addClass( 'last-page' );
750							lastPage = true;
751							return;
752						} else {
753							$pagination.removeClass( 'last-page' );
754							lastPage = false;
755						}
756
757						
758
759					} );
760
761				}
762
763			},
764
765			error: function( jqXHR, exception ) {
766				miyazakiAjaxErrors( jqXHR, exception );
767			}
768		} );
769
770	},
771
772	// Update browser history
773    updateHistory: function( paged ) {
774
775		var newUrl,
776			currentUrl = document.location.href;
777
778		// If currentUrl doesn't end with a slash, append one
779		if ( currentUrl.substr( currentUrl.length - 1 ) !== '/' ) {
780			currentUrl += '/';
781		}
782
783		var hasPaginationRegexp = new RegExp( '^(.*/page)/[0-9]*/(.*$)' );
784
785		if ( hasPaginationRegexp.test( currentUrl ) ) {
786			newUrl = currentUrl.replace( hasPaginationRegexp, '$1/' + paged + '/$2' );
787		} else {
788			var beforeSearchReplaceRegexp = new RegExp( '^([^?]*)(\\??.*$)' );
789			newUrl = currentUrl.replace( beforeSearchReplaceRegexp, '$1page/' + paged + '/$2' );
790		}
791
792		history.pushState( {}, '', newUrl );
793
794	}
795
796} // Load More
797
798
799
800
801/*	-----------------------------------------------------------------------------------------------
802	Focus Management
803--------------------------------------------------------------------------------------------------- */
804
805miyazaki.focusManagement = {
806
807	init: function() {
808
809		// Add and remove a class from dropdown menu items on focus
810		miyazaki.focusManagement.dropdownFocus();
811
812	},
813
814	// Add and remove a class from dropdown menu items on focus
815	dropdownFocus: function() {
816		$( '.main-menu a' ).on( 'blur focus', function( e ) {
817			$( this ).parents( 'li.menu-item-has-children' ).toggleClass( 'focus' );
818		} );
819	}
820
821} // miyazaki.focusManagement
822
823
824// ======================================================================= Function calls
825$( document ).ready( function( ) {
826
827	miyazaki.intervalScroll.init();						// Interval scroll
828	miyazaki.toggles.init();							// Toggles
829	miyazaki.coverModals.init();						// Cover modal specifics
830	miyazaki.elementInView.init();						// Check for element in view
831	miyazaki.mobileMenu.init();							// Mobile menu
832	miyazaki.intrinsicRatioEmbeds.init();				// Resize embeds
833	miyazaki.masonry.init();							// Masonry grid
834	miyazaki.smoothScroll.init();						// Smooth scrolls to anchor links
835	miyazaki.loadMore.init();							// Load more posts
836	miyazaki.scrollLock.init();							// Handle locking of the scroll
837	miyazaki.focusManagement.init();					// Focus functionality
838
839} );

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.