PageSourceSearch

https://nobokepz.com/wp-content/themes/kingtube/assets/js/main.js?ver=1.10.0

js nobokepz.com collected 2026-10-09 22:58:50 UTC 36,884 bytes, 1,490 lines download raw bytes

1jQuery(window).on('load', function () {
2	jQuery('.prev-photo i').show();
3	jQuery('.next-photo i').show();
4});
5
6jQuery(document).ready(function () {
7	/** PHOTOS GALLERY */
8	jQuery('.wp-block-gallery a').attr('data-fancybox', 'gallery');
9	if (jQuery('.wp-block-gallery').length > 0) {
10		// var imgs = document.images,
11		var imgs = jQuery('.wp-block-gallery img'),
12			len = imgs.length,
13			counter = 0;
14		[].forEach.call(imgs, function (img) {
15			if (img.complete) {
16				incrementCounter();
17			} else {
18				img.addEventListener('load', incrementCounter, false);
19			}
20		});
21		function incrementCounter() {
22			counter++;
23			jQuery('.loading-photos span').text(counter + '/' + len);
24			if (counter === len) {
25				waterfall('.wp-block-gallery');
26				setTimeout(function () {
27					jQuery('.wp-block-gallery').css('opacity', 1);
28					jQuery('.loading-photos').hide();
29				}, 1000);
30			}
31		}
32		jQuery(window).resize(function () {
33			waterfall('.wp-block-gallery');
34		});
35	}
36	jQuery('.gallery a').attr('data-fancybox', 'gallery');
37	if (jQuery('.gallery').length > 0) {
38		// var imgs = document.images,
39		var imgs = jQuery('.gallery img'),
40			len = imgs.length,
41			counter = 0;
42		[].forEach.call(imgs, function (img) {
43			if (img.complete) {
44				incrementCounter();
45			} else {
46				img.addEventListener('load', incrementCounter, false);
47			}
48		});
49		function incrementCounter() {
50			counter++;
51			jQuery('.loading-photos span').text(counter + '/' + len);
52			if (counter === len) {
53				waterfall('.gallery');
54				setTimeout(function () {
55					jQuery('.gallery').css('opacity', 1);
56					jQuery('.loading-photos').hide();
57				}, 1000);
58			}
59		}
60		jQuery(window).resize(function () {
61			waterfall('.gallery');
62		});
63		jQuery(window).load(function () {
64			waterfall('.wp-block-gallery');
65		});
66	}
67
68	/** VideoJS loading **/
69	if (jQuery('#wpst-video').length > 0 && !wpst_ajax_var.ctpl_installed) {
70		var playerOptions = {
71			controlBar: {
72				children: [
73					'playToggle',
74					'progressControl',
75					'durationDisplay',
76					'volumePanel',
77					'qualitySelector',
78					'fullscreenToggle',
79				],
80			},
81		};
82		videojs('wpst-video', playerOptions);
83	}
84
85	/** Lazy load **/
86	var imgDefer = document.getElementsByTagName('img');
87	for (var i = 0; i < imgDefer.length; i++) {
88		var dataSrc = imgDefer[i].getAttribute('data-src');
89		if (dataSrc) {
90			imgDefer[i].setAttribute('src', dataSrc);
91			imgDefer[i].classList.add('display-img');
92		}
93	}
94
95	/** In-video Ad Close button **/
96	// if(wpst_ajax_var.ctpl_installed == ''){
97	jQuery('body').on('click', '.happy-inside-player .close', function (e) {
98		jQuery(this).parent('.happy-inside-player').hide();
99	});
100	// }
101
102	/** IIFE Set Post views with ajax request for cache compatibility */
103	(function () {
104		var is_post = jQuery('body.single-post').length > 0;
105		if (!is_post) return;
106		var post_id = jQuery('article.post').attr('id').replace('post-', '');
107		jQuery
108			.ajax({
109				type: 'post',
110				url: wpst_ajax_var.url,
111				dataType: 'json',
112				data: {
113					action: 'post-views',
114					nonce: wpst_ajax_var.nonce,
115					post_id: post_id,
116				},
117			})
118			.done(function (doneData) {
119				// done stuff
120			})
121			.fail(function (errorData) {
122				console.error(errorData);
123			})
124			.always(function (alwaysData) {
125				//get post views & rating data
126				jQuery
127					.ajax({
128						type: 'post',
129						url: wpst_ajax_var.url,
130						dataType: 'json',
131						data: {
132							action: 'get-post-data',
133							nonce: wpst_ajax_var.nonce,
134							post_id: post_id,
135						},
136					})
137					.done(function (doneData) {
138						if (doneData.views) {
139							jQuery('.video-views span').text(doneData.views);
140						}
141						if (doneData.likes) {
142							jQuery('.likes_count').text(doneData.likes);
143						}
144					})
145					.fail(function (errorData) {
146						console.error(errorData);
147					})
148					.always(function () {
149						// always stuff
150					});
151			});
152	})();
153
154	/** Post like **/
155	jQuery('.post-like a').on('click', function (e) {
156		e.preventDefault();
157
158		var heart = jQuery(this);
159		var post_id = heart.data('post_id');
160		var post_like = heart.data('post_like');
161
162		jQuery.ajax({
163			type: 'post',
164			url: wpst_ajax_var.url,
165			dataType: 'json',
166			data:
167				'action=post-like&nonce=' +
168				wpst_ajax_var.nonce +
169				'&post_like=' +
170				post_like +
171				'&post_id=' +
172				post_id,
173			success: function (data, textStatus, jqXHR) {
174				if (data.alreadyrate !== true) {
175					jQuery('.rating-result .percentage').text(
176						Math.floor(data.percentage) + '%',
177					);
178					jQuery('.rating-result .percentage').show();
179					jQuery('.likes .likes_count').text(data.likes);
180					jQuery('.post-like').html(data.button);
181				}
182			},
183		});
184		return false;
185	});
186
187	//Main thumbs
188	main_setThumbsHeight();
189
190	function ratio_format() {
191		var width = options.thumbnails_ratio.split('/')[0];
192		var height = options.thumbnails_ratio.split('/')[1];
193		return height / width;
194	}
195
196	jQuery(window).resize(function () {
197		main_setThumbsHeight();
198	});
199
200	function main_setThumbsHeight() {
201		var eltWidthMain = jQuery(jQuery('.post-thumbnail')[0]).width();
202		jQuery('.post-thumbnail img').height(eltWidthMain * ratio_format());
203		jQuery('.post-thumbnail .wpst-trailer').height(
204			eltWidthMain * ratio_format(),
205		);
206		jQuery('.photos-thumb').height(eltWidthMain);
207		jQuery('.photos .post-thumbnail .photo-bg').height(eltWidthMain);
208		jQuery('.post-thumbnail .no-thumb').height(eltWidthMain * ratio_format());
209	}
210
211	//Footer thumbs
212	footer_setThumbsHeight();
213
214	jQuery(window).resize(function () {
215		footer_setThumbsHeight();
216	});
217	function footer_setThumbsHeight() {
218		var eltWidthFooter = jQuery(
219			jQuery('.site-footer .post-thumbnail')[0],
220		).width();
221		jQuery('.site-footer .post-thumbnail img').height(
222			eltWidthFooter * ratio_format(),
223		);
224		jQuery('.site-footer .post-thumbnail .wpst-trailer').height(
225			eltWidthFooter * ratio_format(),
226		);
227		jQuery('.site-footer .no-thumb').height(eltWidthFooter * ratio_format());
228	}
229
230	//Hide title hover thumb
231	jQuery('.thumb-block a').hover(
232		function (e) {
233			jQuery(this).attr('data-title', jQuery(this).attr('title'));
234			jQuery(this).removeAttr('title');
235		},
236		function (e) {
237			jQuery(this).attr('title', jQuery(this).attr('data-title'));
238		},
239	);
240
241	jQuery(function ($) {
242		const thumbsInterval = 750;
243		const thumbsTimers = {};
244		const trailersState = {};
245
246		function debounce(fn, wait, immediate = false) {
247			let timer;
248			return function (...args) {
249				const callNow = immediate && !timer;
250				clearTimeout(timer);
251				timer = setTimeout(() => {
252					timer = null;
253					if (!immediate) fn.apply(this, args);
254				}, wait);
255				if (callNow) fn.apply(this, args);
256			};
257		}
258
259		function initVideoPreviews() {
260			$('.video-preview-item').each(function () {
261				const $item = $(this);
262				const videoId = $item.data('video-id');
263				const thumbsData = $item.data('thumbs');
264				const trailerSrc = $item.data('trailer');
265				const $postThumb = $item.find('.post-thumbnail');
266				const $mainImg = $item.find('.video-main-thumb');
267				const $overlay = $item.find('.video-overlay');
268
269				let thumbs = thumbsData
270					? thumbsData.split(',').map((s) => s.trim())
271					: [];
272
273				const hasThumbs = thumbs.length > 0;
274				const isVideoTrailer =
275					trailerSrc && trailerSrc.match(/\.(mp4|webm)(\?.*)?$/i);
276				const isImageTrailer =
277					trailerSrc && trailerSrc.match(/\.(gif|webp)(\?.*)?$/i);
278
279				$postThumb.on(
280					'mouseenter touchstart',
281					debounce(
282						function () {
283							stopPreview($postThumb);
284
285							if (hasThumbs) {
286								startThumbs(videoId, $mainImg, thumbs);
287							} else if (isVideoTrailer || isImageTrailer) {
288								startTrailer(
289									videoId,
290									$overlay,
291									trailerSrc,
292									$mainImg,
293									isVideoTrailer,
294								);
295							}
296						},
297						100,
298						true,
299					), // Debounce to avoid flickering,
300				);
301
302				$postThumb.on('mouseleave touchend touchcancel', function () {
303					stopPreview($postThumb);
304				});
305			});
306		}
307
308		function startThumbs(id, $img, thumbs) {
309			if (!thumbs.length) return;
310
311			let index = 1; // on commence à 1 car la 0 est déjà affichée
312			const initialDelay = 150; // délai pour la 1ʳᵉ rotation
313			const regularDelay = thumbsInterval;
314
315			function cycle() {
316				if (!thumbsTimers[id]) return;
317				$img.attr('src', thumbs[index]);
318				index = (index + 1) % thumbs.length;
319				thumbsTimers[id] = setTimeout(cycle, regularDelay);
320			}
321
322			// Lance la 1ère rotation plus vite
323			thumbsTimers[id] = setTimeout(cycle, initialDelay);
324		}
325
326		function stopThumbs(id, $img, mainSrc) {
327			clearTimeout(thumbsTimers[id]);
328			delete thumbsTimers[id];
329			$img.attr('src', mainSrc);
330		}
331
332		function startTrailer(id, $overlay, src, $mainImg, isVideo) {
333			stopTrailer(id);
334			$overlay.empty();
335
336			if (isVideo) {
337				const $video = $('<video muted autoplay loop playsinline></video>')
338					.attr('src', src)
339					.css({ width: '100%', height: 'auto' });
340
341				$overlay.append($video).fadeIn(200);
342				$mainImg.fadeOut(200);
343
344				trailersState[id] = { type: 'video', $video, $mainImg, $overlay };
345			} else {
346				const $img = $('<img class="preview-thumb" />').attr('src', src);
347				$overlay.append($img).fadeIn(200);
348				$mainImg.fadeOut(200);
349
350				trailersState[id] = { type: 'image', $img, $mainImg, $overlay };
351			}
352		}
353
354		function stopTrailer(id) {
355			if (!trailersState[id]) return;
356
357			const { $mainImg, $overlay } = trailersState[id];
358			$overlay.fadeOut(200, function () {
359				// $overlay.empty();
360			});
361			$mainImg.fadeIn(200);
362			delete trailersState[id];
363		}
364
365		function stopPreview($trigger) {
366			if ($trigger) {
367				const $item = $trigger.parents('.video-preview-item');
368				const id = $item.data('video-id');
369				const $mainImg = $item.find('.video-main-thumb');
370				const mainThumb = $item.data('main-thumb');
371				stopThumbs(id, $mainImg, mainThumb);
372				stopTrailer(id);
373			}
374			return;
375		}
376
377		initVideoPreviews();
378	});
379
380	jQuery('.video-description .more').readmore({
381		speed: 75,
382		collapsedHeight: 50,
383		moreLink:
384			'<a class="morelink" href="#">Read More <i class="fa fa-chevron-down"></i></a>',
385		lessLink:
386			'<a class="morelink" href="#">Read Less <i class="fa fa-chevron-up"></i></a>',
387	});
388
389	/** Back to top */
390	if (jQuery('#back-to-top').length) {
391		var scrollTrigger = 100, // px
392			backToTop = function () {
393				var scrollTop = jQuery(window).scrollTop();
394				if (scrollTop > scrollTrigger) {
395					jQuery('#back-to-top').addClass('show');
396				} else {
397					jQuery('#back-to-top').removeClass('show');
398				}
399			};
400		backToTop();
401		jQuery(window).on('scroll', function () {
402			backToTop();
403		});
404		jQuery('#back-to-top').on('click', function (e) {
405			e.preventDefault();
406			jQuery('html,body').animate(
407				{
408					scrollTop: 0,
409				},
410				700,
411			);
412		});
413	}
414});
415
416/** TRAILER */
417function hoverVideo(i) {
418	var playPromise = jQuery('.wpst-trailer')[i].play();
419	if (playPromise !== undefined) {
420		playPromise
421			.then((_) => {
422				// Automatic playback started!
423				// Show playing UI.
424			})
425			.catch((error) => {
426				// Auto-play was prevented
427				// Show paused UI.
428			});
429	}
430}
431
432function hideVideo(i) {
433	//jQuery('.wpst-trailer')[i].currentTime = 0;
434	jQuery('.wpst-trailer')[i].load();
435}
436
437/** LOGIN / REGISTER POPUP */
438function wpst_open_login_dialog(href) {
439	jQuery('#wpst-user-modal .modal-dialog').removeClass('registration-complete');
440	var modal_dialog = jQuery('#wpst-user-modal .modal-dialog');
441	modal_dialog.attr('data-active-tab', '');
442	switch (href) {
443		case '#wpst-register':
444			modal_dialog.attr('data-active-tab', '#wpst-register');
445			break;
446		case '#wpst-login':
447		default:
448			modal_dialog.attr('data-active-tab', '#wpst-login');
449			break;
450	}
451	jQuery('#wpst-user-modal').modal('show');
452}
453function wpst_close_login_dialog() {
454	jQuery('#wpst-user-modal').modal('hide');
455}
456
457jQuery(function ($) {
458	'use strict';
459	/***************************
460	 **  LOGIN / REGISTER DIALOG
461	 ***************************/
462
463	// Open login/register modal
464	$('[href="#wpst-login"], [href="#wpst-register"]').click(function (e) {
465		e.preventDefault();
466
467		wpst_open_login_dialog($(this).attr('href'));
468	});
469
470	// Switch forms login/register
471	$('.modal-footer a, a[href="#wpst-reset-password"]').click(function (e) {
472		e.preventDefault();
473		$('#wpst-user-modal .modal-dialog').attr(
474			'data-active-tab',
475			$(this).attr('href'),
476		);
477	});
478
479	// Post login form
480	$('#wpst_login_form').on('submit', function (e) {
481		e.preventDefault();
482
483		var button = $(this).find('button');
484		button.button('loading');
485
486		$.post(
487			wpst_ajax_var.url,
488			$('#wpst_login_form').serialize(),
489			function (data) {
490				var obj = $.parseJSON(data);
491
492				$('.wpst-login .wpst-errors').html(obj.message);
493
494				if (obj.error == false) {
495					$('#wpst-user-modal .modal-dialog').addClass('loading');
496					window.location.reload(true);
497					button.hide();
498				}
499
500				button.button('reset');
501			},
502		);
503	});
504
505	// Post register form
506	$('#wpst_registration_form').on('submit', function (e) {
507		e.preventDefault();
508
509		var button = $(this).find('button');
510		button.button('loading');
511
512		$.post(
513			wpst_ajax_var.url,
514			$('#wpst_registration_form').serialize(),
515			function (data) {
516				var obj = $.parseJSON(data);
517
518				$('.wpst-register .wpst-errors').html(obj.message);
519
520				if (obj.error == false) {
521					$('#wpst-user-modal .modal-dialog').addClass('registration-complete');
522					// window.location.reload(true);
523					button.hide();
524				}
525
526				button.button('reset');
527			},
528		);
529	});
530
531	// Reset Password
532	$('#wpst_reset_password_form').on('submit', function (e) {
533		e.preventDefault();
534
535		var button = $(this).find('button');
536		button.button('loading');
537
538		$.post(
539			wpst_ajax_var.url,
540			$('#wpst_reset_password_form').serialize(),
541			function (data) {
542				var obj = $.parseJSON(data);
543
544				$('.wpst-reset-password .wpst-errors').html(obj.message);
545
546				// if(obj.error == false){
547				// $('#wpst-user-modal .modal-dialog').addClass('loading');
548				// $('#wpst-user-modal').modal('hide');
549				// }
550
551				button.button('reset');
552			},
553		);
554	});
555
556	if (window.location.hash == '#login') {
557		wpst_open_login_dialog('#wpst-login');
558	}
559});
560
561/*!
562 * @preserve
563 *
564 * Readmore.js jQuery plugin
565 * Author: @jed_foster
566 * Project home: http://jedfoster.github.io/Readmore.js
567 * Licensed under the MIT license
568 *
569 * Debounce function from http://davidwalsh.name/javascript-debounce-function
570 */
571
572/* global jQuery */
573
574(function (factory) {
575	if (typeof define === 'function' && define.amd) {
576		// AMD
577		define(['jquery'], factory);
578	} else if (typeof exports === 'object') {
579		// CommonJS
580		module.exports = factory(require('jquery'));
581	} else {
582		// Browser globals
583		factory(jQuery);
584	}
585})(function ($) {
586	'use strict';
587
588	var readmore = 'readmore',
589		defaults = {
590			speed: 100,
591			collapsedHeight: 200,
592			heightMargin: 16,
593			moreLink: '<a href="#">Read More</a>',
594			lessLink: '<a href="#">Close</a>',
595			embedCSS: true,
596			blockCSS: 'display: block; width: 100%;',
597			startOpen: false,
598
599			// callbacks
600			blockProcessed: function () {},
601			beforeToggle: function () {},
602			afterToggle: function () {},
603		},
604		cssEmbedded = {},
605		uniqueIdCounter = 0;
606
607	function debounce(func, wait, immediate) {
608		var timeout;
609
610		return function () {
611			var context = this,
612				args = arguments;
613			var later = function () {
614				timeout = null;
615				if (!immediate) {
616					func.apply(context, args);
617				}
618			};
619			var callNow = immediate && !timeout;
620
621			clearTimeout(timeout);
622			timeout = setTimeout(later, wait);
623
624			if (callNow) {
625				func.apply(context, args);
626			}
627		};
628	}
629
630	function uniqueId(prefix) {
631		var id = ++uniqueIdCounter;
632
633		return String(prefix == null ? 'rmjs-' : prefix) + id;
634	}
635
636	function setBoxHeights(element) {
637		var el = element
638				.clone()
639				.css({
640					height: 'auto',
641					width: element.width(),
642					maxHeight: 'none',
643					overflow: 'hidden',
644				})
645				.insertAfter(element),
646			expandedHeight = el.outerHeight(),
647			cssMaxHeight = parseInt(
648				el
649					.css({ maxHeight: '' })
650					.css('max-height')
651					.replace(/[^-\d\.]/g, ''),
652				10,
653			),
654			defaultHeight = element.data('defaultHeight');
655
656		el.remove();
657
658		var collapsedHeight =
659			cssMaxHeight || element.data('collapsedHeight') || defaultHeight;
660
661		// Store our measurements.
662		element
663			.data({
664				expandedHeight: expandedHeight,
665				maxHeight: cssMaxHeight,
666				collapsedHeight: collapsedHeight,
667			})
668			// and disable any `max-height` property set in CSS
669			.css({
670				maxHeight: 'none',
671			});
672	}
673
674	var resizeBoxes = debounce(function () {
675		$('[data-readmore]').each(function () {
676			var current = $(this),
677				isExpanded = current.attr('aria-expanded') === 'true';
678
679			setBoxHeights(current);
680
681			current.css({
682				height: current.data(isExpanded ? 'expandedHeight' : 'collapsedHeight'),
683			});
684		});
685	}, 100);
686
687	function embedCSS(options) {
688		if (!cssEmbedded[options.selector]) {
689			var styles = ' ';
690
691			if (options.embedCSS && options.blockCSS !== '') {
692				styles +=
693					options.selector +
694					' + [data-readmore-toggle], ' +
695					options.selector +
696					'[data-readmore]{' +
697					options.blockCSS +
698					'}';
699			}
700
701			// Include the transition CSS even if embedCSS is false
702			styles +=
703				options.selector +
704				'[data-readmore]{' +
705				'transition: height ' +
706				options.speed +
707				'ms;' +
708				'overflow: hidden;' +
709				'}';
710
711			(function (d, u) {
712				var css = d.createElement('style');
713				css.type = 'text/css';
714
715				if (css.styleSheet) {
716					css.styleSheet.cssText = u;
717				} else {
718					css.appendChild(d.createTextNode(u));
719				}
720
721				d.getElementsByTagName('head')[0].appendChild(css);
722			})(document, styles);
723
724			cssEmbedded[options.selector] = true;
725		}
726	}
727
728	function Readmore(element, options) {
729		this.element = element;
730
731		this.options = $.extend({}, defaults, options);
732
733		embedCSS(this.options);
734
735		this._defaults = defaults;
736		this._name = readmore;
737
738		this.init();
739
740		// IE8 chokes on `window.addEventListener`, so need to test for support.
741		if (window.addEventListener) {
742			// Need to resize boxes when the page has fully loaded.
743			window.addEventListener('load', resizeBoxes);
744			window.addEventListener('resize', resizeBoxes);
745		} else {
746			window.attachEvent('load', resizeBoxes);
747			window.attachEvent('resize', resizeBoxes);
748		}
749	}
750
751	Readmore.prototype = {
752		init: function () {
753			var current = $(this.element);
754
755			current.data({
756				defaultHeight: this.options.collapsedHeight,
757				heightMargin: this.options.heightMargin,
758			});
759
760			setBoxHeights(current);
761
762			var collapsedHeight = current.data('collapsedHeight'),
763				heightMargin = current.data('heightMargin');
764
765			if (current.outerHeight(true) <= collapsedHeight + heightMargin) {
766				// The block is shorter than the limit, so there's no need to truncate it.
767				if (
768					this.options.blockProcessed &&
769					typeof this.options.blockProcessed === 'function'
770				) {
771					this.options.blockProcessed(current, false);
772				}
773				return true;
774			} else {
775				var id = current.attr('id') || uniqueId(),
776					useLink = this.options.startOpen
777						? this.options.lessLink
778						: this.options.moreLink;
779
780				current.attr({
781					'data-readmore': '',
782					'aria-expanded': this.options.startOpen,
783					id: id,
784				});
785
786				current.after(
787					$(useLink)
788						.on(
789							'click',
790							(function (_this) {
791								return function (event) {
792									_this.toggle(this, current[0], event);
793								};
794							})(this),
795						)
796						.attr({
797							'data-readmore-toggle': id,
798							'aria-controls': id,
799						}),
800				);
801
802				if (!this.options.startOpen) {
803					current.css({
804						height: collapsedHeight,
805					});
806				}
807
808				if (
809					this.options.blockProcessed &&
810					typeof this.options.blockProcessed === 'function'
811				) {
812					this.options.blockProcessed(current, true);
813				}
814			}
815		},
816
817		toggle: function (trigger, element, event) {
818			if (event) {
819				event.preventDefault();
820			}
821
822			if (!trigger) {
823				trigger = $('[aria-controls="' + this.element.id + '"]')[0];
824			}
825
826			if (!element) {
827				element = this.element;
828			}
829
830			var $element = $(element),
831				newHeight = '',
832				newLink = '',
833				expanded = false,
834				collapsedHeight = $element.data('collapsedHeight');
835
836			if ($element.height() <= collapsedHeight) {
837				newHeight = $element.data('expandedHeight') + 'px';
838				newLink = 'lessLink';
839				expanded = true;
840			} else {
841				newHeight = collapsedHeight;
842				newLink = 'moreLink';
843			}
844
845			// Fire beforeToggle callback
846			// Since we determined the new "expanded" state above we're now out of sync
847			// with our true current state, so we need to flip the value of `expanded`
848			if (
849				this.options.beforeToggle &&
850				typeof this.options.beforeToggle === 'function'
851			) {
852				this.options.beforeToggle(trigger, $element, !expanded);
853			}
854
855			$element.css({ height: newHeight });
856
857			// Fire afterToggle callback
858			$element.on(
859				'transitionend',
860				(function (_this) {
861					return function () {
862						if (
863							_this.options.afterToggle &&
864							typeof _this.options.afterToggle === 'function'
865						) {
866							_this.options.afterToggle(trigger, $element, expanded);
867						}
868
869						$(this)
870							.attr({
871								'aria-expanded': expanded,
872							})
873							.off('transitionend');
874					};
875				})(this),
876			);
877
878			$(trigger).replaceWith(
879				$(this.options[newLink])
880					.on(
881						'click',
882						(function (_this) {
883							return function (event) {
884								_this.toggle(this, element, event);
885							};
886						})(this),
887					)
888					.attr({
889						'data-readmore-toggle': $element.attr('id'),
890						'aria-controls': $element.attr('id'),
891					}),
892			);
893		},
894
895		destroy: function () {
896			$(this.element).each(function () {
897				var current = $(this);
898
899				current
900					.attr({
901						'data-readmore': null,
902						'aria-expanded': null,
903					})
904					.css({
905						maxHeight: '',
906						height: '',
907					})
908					.next('[data-readmore-toggle]')
909					.remove();
910
911				current.removeData();
912			});
913		},
914	};
915
916	$.fn.readmore = function (options) {
917		var args = arguments,
918			selector = this.selector;
919
920		options = options || {};
921
922		if (typeof options === 'object') {
923			return this.each(function () {
924				if ($.data(this, 'plugin_' + readmore)) {
925					var instance = $.data(this, 'plugin_' + readmore);
926					instance.destroy.apply(instance);
927				}
928
929				options.selector = selector;
930
931				$.data(this, 'plugin_' + readmore, new Readmore(this, options));
932			});
933		} else if (
934			typeof options === 'string' &&
935			options[0] !== '_' &&
936			options !== 'init'
937		) {
938			return this.each(function () {
939				var instance = $.data(this, 'plugin_' + readmore);
940				if (
941					instance instanceof Readmore &&
942					typeof instance[options] === 'function'
943				) {
944					instance[options].apply(
945						instance,
946						Array.prototype.slice.call(args, 1),
947					);
948				}
949			});
950		}
951	};
952});
953
954/********************/
955/** Bootstrap modal */
956/********************/
957/*!
958 * Bootstrap v3.3.7 (http://getbootstrap.com)
959 * Copyright 2011-2017 Twitter, Inc.
960 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
961 */
962
963/*!
964 * Generated using the Bootstrap Customizer (http://getbootstrap.com/docs/3.3/customize/?id=2df80e69d208c504c2a17d0146de73bb)
965 * Config saved to config.json and https://gist.github.com/2df80e69d208c504c2a17d0146de73bb
966 */
967if (typeof jQuery === 'undefined') {
968	throw new Error("Bootstrap's JavaScript requires jQuery");
969}
970+(function ($) {
971	'use strict';
972	var version = $.fn.jquery.split(' ')[0].split('.');
973	if (
974		(version[0] < 2 && version[1] < 9) ||
975		(version[0] == 1 && version[1] == 9 && version[2] < 1) ||
976		version[0] > 3
977	) {
978		throw new Error(
979			"Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4",
980		);
981	}
982})(jQuery);
983
984/* ========================================================================
985 * Bootstrap: button.js v3.3.7
986 * http://getbootstrap.com/javascript/#buttons
987 * ========================================================================
988 * Copyright 2011-2016 Twitter, Inc.
989 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
990 * ======================================================================== */
991
992+(function ($) {
993	'use strict';
994
995	// BUTTON PUBLIC CLASS DEFINITION
996	// ==============================
997
998	var Button = function (element, options) {
999		this.$element = $(element);
1000		this.options = $.extend({}, Button.DEFAULTS, options);
1001		this.isLoading = false;
1002	};
1003
1004	Button.VERSION = '3.3.7';
1005
1006	Button.DEFAULTS = {
1007		loadingText: 'loading...',
1008	};
1009
1010	Button.prototype.setState = function (state) {
1011		var d = 'disabled';
1012		var $el = this.$element;
1013		var val = $el.is('input') ? 'val' : 'html';
1014		var data = $el.data();
1015
1016		state += 'Text';
1017
1018		if (data.resetText == null) $el.data('resetText', $el[val]());
1019
1020		// push to event loop to allow forms to submit
1021		setTimeout(
1022			$.proxy(function () {
1023				$el[val](data[state] == null ? this.options[state] : data[state]);
1024
1025				if (state == 'loadingText') {
1026					this.isLoading = true;
1027					$el.addClass(d).attr(d, d).prop(d, true);
1028				} else if (this.isLoading) {
1029					this.isLoading = false;
1030					$el.removeClass(d).removeAttr(d).prop(d, false);
1031				}
1032			}, this),
1033			0,
1034		);
1035	};
1036
1037	Button.prototype.toggle = function () {
1038		var changed = true;
1039		var $parent = this.$element.closest('[data-toggle="buttons"]');
1040
1041		if ($parent.length) {
1042			var $input = this.$element.find('input');
1043			if ($input.prop('type') == 'radio') {
1044				if ($input.prop('checked')) changed = false;
1045				$parent.find('.active').removeClass('active');
1046				this.$element.addClass('active');
1047			} else if ($input.prop('type') == 'checkbox') {
1048				if ($input.prop('checked') !== this.$element.hasClass('active'))
1049					changed = false;
1050				this.$element.toggleClass('active');
1051			}
1052			$input.prop('checked', this.$element.hasClass('active'));
1053			if (changed) $input.trigger('change');
1054		} else {
1055			this.$element.attr('aria-pressed', !this.$element.hasClass('active'));
1056			this.$element.toggleClass('active');
1057		}
1058	};
1059
1060	// BUTTON PLUGIN DEFINITION
1061	// ========================
1062
1063	function Plugin(option) {
1064		return this.each(function () {
1065			var $this = $(this);
1066			var data = $this.data('bs.button');
1067			var options = typeof option == 'object' && option;
1068
1069			if (!data) $this.data('bs.button', (data = new Button(this, options)));
1070
1071			if (option == 'toggle') data.toggle();
1072			else if (option) data.setState(option);
1073		});
1074	}
1075
1076	var old = $.fn.button;
1077
1078	$.fn.button = Plugin;
1079	$.fn.button.Constructor = Button;
1080
1081	// BUTTON NO CONFLICT
1082	// ==================
1083
1084	$.fn.button.noConflict = function () {
1085		$.fn.button = old;
1086		return this;
1087	};
1088
1089	// BUTTON DATA-API
1090	// ===============
1091
1092	$(document)
1093		.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
1094			var $btn = $(e.target).closest('.btn');
1095			Plugin.call($btn, 'toggle');
1096			if (!$(e.target).is('input[type="radio"], input[type="checkbox"]')) {
1097				// Prevent double click on radios, and the double selections (so cancellation) on checkboxes
1098				e.preventDefault();
1099				// The target component still receive the focus
1100				if ($btn.is('input,button')) $btn.trigger('focus');
1101				else $btn.find('input:visible,button:visible').first().trigger('focus');
1102			}
1103		})
1104		.on(
1105			'focus.bs.button.data-api blur.bs.button.data-api',
1106			'[data-toggle^="button"]',
1107			function (e) {
1108				$(e.target)
1109					.closest('.btn')
1110					.toggleClass('focus', /^focus(in)?$/.test(e.type));
1111			},
1112		);
1113})(jQuery);
1114
1115/* ========================================================================
1116 * Bootstrap: modal.js v3.3.7
1117 * http://getbootstrap.com/javascript/#modals
1118 * ========================================================================
1119 * Copyright 2011-2016 Twitter, Inc.
1120 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1121 * ======================================================================== */
1122
1123+(function ($) {
1124	'use strict';
1125
1126	// MODAL CLASS DEFINITION
1127	// ======================
1128
1129	var Modal = function (element, options) {
1130		this.options = options;
1131		this.$body = $(document.body);
1132		this.$element = $(element);
1133		this.$dialog = this.$element.find('.modal-dialog');
1134		this.$backdrop = null;
1135		this.isShown = null;
1136		this.originalBodyPad = null;
1137		this.scrollbarWidth = 0;
1138		this.ignoreBackdropClick = false;
1139
1140		if (this.options.remote) {
1141			this.$element.find('.modal-content').load(
1142				this.options.remote,
1143				$.proxy(function () {
1144					this.$element.trigger('loaded.bs.modal');
1145				}, this),
1146			);
1147		}
1148	};
1149
1150	Modal.VERSION = '3.3.7';
1151
1152	Modal.TRANSITION_DURATION = 300;
1153	Modal.BACKDROP_TRANSITION_DURATION = 150;
1154
1155	Modal.DEFAULTS = {
1156		backdrop: true,
1157		keyboard: true,
1158		show: true,
1159	};
1160
1161	Modal.prototype.toggle = function (_relatedTarget) {
1162		return this.isShown ? this.hide() : this.show(_relatedTarget);
1163	};
1164
1165	Modal.prototype.show = function (_relatedTarget) {
1166		var that = this;
1167		var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget });
1168
1169		this.$element.trigger(e);
1170
1171		if (this.isShown || e.isDefaultPrevented()) return;
1172
1173		this.isShown = true;
1174
1175		this.checkScrollbar();
1176		this.setScrollbar();
1177		this.$body.addClass('modal-open');
1178
1179		this.escape();
1180		this.resize();
1181
1182		this.$element.on(
1183			'click.dismiss.bs.modal',
1184			'[data-dismiss="modal"]',
1185			$.proxy(this.hide, this),
1186		);
1187
1188		this.$dialog.on('mousedown.dismiss.bs.modal', function () {
1189			that.$element.one('mouseup.dismiss.bs.modal', function (e) {
1190				if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true;
1191			});
1192		});
1193
1194		this.backdrop(function () {
1195			var transition = $.support.transition && that.$element.hasClass('fade');
1196
1197			if (!that.$element.parent().length) {
1198				that.$element.appendTo(that.$body); // don't move modals dom position
1199			}
1200
1201			that.$element.show().scrollTop(0);
1202
1203			that.adjustDialog();
1204
1205			if (transition) {
1206				that.$element[0].offsetWidth; // force reflow
1207			}
1208
1209			that.$element.addClass('in');
1210
1211			that.enforceFocus();
1212
1213			var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget });
1214
1215			transition
1216				? that.$dialog // wait for modal to slide in
1217						.one('bsTransitionEnd', function () {
1218							that.$element.trigger('focus').trigger(e);
1219						})
1220						.emulateTransitionEnd(Modal.TRANSITION_DURATION)
1221				: that.$element.trigger('focus').trigger(e);
1222		});
1223	};
1224
1225	Modal.prototype.hide = function (e) {
1226		if (e) e.preventDefault();
1227
1228		e = $.Event('hide.bs.modal');
1229
1230		this.$element.trigger(e);
1231
1232		if (!this.isShown || e.isDefaultPrevented()) return;
1233
1234		this.isShown = false;
1235
1236		this.escape();
1237		this.resize();
1238
1239		$(document).off('focusin.bs.modal');
1240
1241		this.$element
1242			.removeClass('in')
1243			.off('click.dismiss.bs.modal')
1244			.off('mouseup.dismiss.bs.modal');
1245
1246		this.$dialog.off('mousedown.dismiss.bs.modal');
1247
1248		$.support.transition && this.$element.hasClass('fade')
1249			? this.$element
1250					.one('bsTransitionEnd', $.proxy(this.hideModal, this))
1251					.emulateTransitionEnd(Modal.TRANSITION_DURATION)
1252			: this.hideModal();
1253	};
1254
1255	Modal.prototype.enforceFocus = function () {
1256		$(document)
1257			.off('focusin.bs.modal') // guard against infinite focus loop
1258			.on(
1259				'focusin.bs.modal',
1260				$.proxy(function (e) {
1261					if (
1262						document !== e.target &&
1263						this.$element[0] !== e.target &&
1264						!this.$element.has(e.target).length
1265					) {
1266						this.$element.trigger('focus');
1267					}
1268				}, this),
1269			);
1270	};
1271
1272	Modal.prototype.escape = function () {
1273		if (this.isShown && this.options.keyboard) {
1274			this.$element.on(
1275				'keydown.dismiss.bs.modal',
1276				$.proxy(function (e) {
1277					e.which == 27 && this.hide();
1278				}, this),
1279			);
1280		} else if (!this.isShown) {
1281			this.$element.off('keydown.dismiss.bs.modal');
1282		}
1283	};
1284
1285	Modal.prototype.resize = function () {
1286		if (this.isShown) {
1287			$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this));
1288		} else {
1289			$(window).off('resize.bs.modal');
1290		}
1291	};
1292
1293	Modal.prototype.hideModal = function () {
1294		var that = this;
1295		this.$element.hide();
1296		this.backdrop(function () {
1297			that.$body.removeClass('modal-open');
1298			that.resetAdjustments();
1299			that.resetScrollbar();
1300			that.$element.trigger('hidden.bs.modal');
1301		});
1302	};
1303
1304	Modal.prototype.removeBackdrop = function () {
1305		this.$backdrop && this.$backdrop.remove();
1306		this.$backdrop = null;
1307	};
1308
1309	Modal.prototype.backdrop = function (callback) {
1310		var that = this;
1311		var animate = this.$element.hasClass('fade') ? 'fade' : '';
1312
1313		if (this.isShown && this.options.backdrop) {
1314			var doAnimate = $.support.transition && animate;
1315
1316			this.$backdrop = $(document.createElement('div'))
1317				.addClass('modal-backdrop ' + animate)
1318				.appendTo(this.$body);
1319
1320			this.$element.on(
1321				'click.dismiss.bs.modal',
1322				$.proxy(function (e) {
1323					if (this.ignoreBackdropClick) {
1324						this.ignoreBackdropClick = false;
1325						return;
1326					}
1327					if (e.target !== e.currentTarget) return;
1328					this.options.backdrop == 'static'
1329						? this.$element[0].focus()
1330						: this.hide();
1331				}, this),
1332			);
1333
1334			if (doAnimate) this.$backdrop[0].offsetWidth; // force reflow
1335
1336			this.$backdrop.addClass('in');
1337
1338			if (!callback) return;
1339
1340			doAnimate
1341				? this.$backdrop
1342						.one('bsTransitionEnd', callback)
1343						.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION)
1344				: callback();
1345		} else if (!this.isShown && this.$backdrop) {
1346			this.$backdrop.removeClass('in');
1347
1348			var callbackRemove = function () {
1349				that.removeBackdrop();
1350				callback && callback();
1351			};
1352			$.support.transition && this.$element.hasClass('fade')
1353				? this.$backdrop
1354						.one('bsTransitionEnd', callbackRemove)
1355						.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION)
1356				: callbackRemove();
1357		} else if (callback) {
1358			callback();
1359		}
1360	};
1361
1362	// these following methods are used to handle overflowing modals
1363
1364	Modal.prototype.handleUpdate = function () {
1365		this.adjustDialog();
1366	};
1367
1368	Modal.prototype.adjustDialog = function () {
1369		var modalIsOverflowing =
1370			this.$element[0].scrollHeight > document.documentElement.clientHeight;
1371
1372		this.$element.css({
1373			paddingLeft:
1374				!this.bodyIsOverflowing && modalIsOverflowing
1375					? this.scrollbarWidth
1376					: '',
1377			paddingRight:
1378				this.bodyIsOverflowing && !modalIsOverflowing
1379					? this.scrollbarWidth
1380					: '',
1381		});
1382	};
1383
1384	Modal.prototype.resetAdjustments = function () {
1385		this.$element.css({
1386			paddingLeft: '',
1387			paddingRight: '',
1388		});
1389	};
1390
1391	Modal.prototype.checkScrollbar = function () {
1392		var fullWindowWidth = window.innerWidth;
1393		if (!fullWindowWidth) {
1394			// workaround for missing window.innerWidth in IE8
1395			var documentElementRect =
1396				document.documentElement.getBoundingClientRect();
1397			fullWindowWidth =
1398				documentElementRect.right - Math.abs(documentElementRect.left);
1399		}
1400		this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
1401		this.scrollbarWidth = this.measureScrollbar();
1402	};
1403
1404	Modal.prototype.setScrollbar = function () {
1405		var bodyPad = parseInt(this.$body.css('padding-right') || 0, 10);
1406		this.originalBodyPad = document.body.style.paddingRight || '';
1407		if (this.bodyIsOverflowing)
1408			this.$body.css('padding-right', bodyPad + this.scrollbarWidth);
1409	};
1410
1411	Modal.prototype.resetScrollbar = function () {
1412		this.$body.css('padding-right', this.originalBodyPad);
1413	};
1414
1415	Modal.prototype.measureScrollbar = function () {
1416		// thx walsh
1417		var scrollDiv = document.createElement('div');
1418		scrollDiv.className = 'modal-scrollbar-measure';
1419		this.$body.append(scrollDiv);
1420		var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
1421		this.$body[0].removeChild(scrollDiv);
1422		return scrollbarWidth;
1423	};
1424
1425	// MODAL PLUGIN DEFINITION
1426	// =======================
1427
1428	function Plugin(option, _relatedTarget) {
1429		return this.each(function () {
1430			var $this = $(this);
1431			var data = $this.data('bs.modal');
1432			var options = $.extend(
1433				{},
1434				Modal.DEFAULTS,
1435				$this.data(),
1436				typeof option == 'object' && option,
1437			);
1438
1439			if (!data) $this.data('bs.modal', (data = new Modal(this, options)));
1440			if (typeof option == 'string') data[option](_relatedTarget);
1441			else if (options.show) data.show(_relatedTarget);
1442		});
1443	}
1444
1445	var old = $.fn.modal;
1446
1447	$.fn.modal = Plugin;
1448	$.fn.modal.Constructor = Modal;
1449
1450	// MODAL NO CONFLICT
1451	// =================
1452
1453	$.fn.modal.noConflict = function () {
1454		$.fn.modal = old;
1455		return this;
1456	};
1457
1458	// MODAL DATA-API
1459	// ==============
1460
1461	$(document).on(
1462		'click.bs.modal.data-api',
1463		'[data-toggle="modal"]',
1464		function (e) {
1465			var $this = $(this);
1466			var href = $this.attr('href');
1467			var $target = $(
1468				$this.attr('data-target') ||
1469					(href && href.replace(/.*(?=#[^\s]+$)/, '')),
1470			); // strip for ie7
1471			var option = $target.data('bs.modal')
1472				? 'toggle'
1473				: $.extend(
1474						{ remote: !/#/.test(href) && href },
1475						$target.data(),
1476						$this.data(),
1477					);
1478
1479			if ($this.is('a')) e.preventDefault();
1480
1481			$target.one('show.bs.modal', function (showEvent) {
1482				if (showEvent.isDefaultPrevented()) return; // only register focus restorer if modal will actually get shown
1483				$target.one('hidden.bs.modal', function () {
1484					$this.is(':visible') && $this.trigger('focus');
1485				});
1486			});
1487			Plugin.call($target, option, this);
1488		},
1489	);
1490})(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.