PageSourceSearch

https://nantohome.com/wp-content/plugins/still-be-combine-social-photos/asset/js/class.js?ver=1721052654

js nantohome.com collected 2026-10-05 02:06:35 UTC 18,943 bytes, 576 lines download raw bytes

1(function(){
2
3
4	"use strict";
5
6
7	// Slider Class
8	const Slider = class {
9
10		constructor($target, $rootClass){
11			this.isDoneInitialize = false;
12			// Main Elements
13			this.target = $target;
14			if(this.target.children.length < 1){
15				return;
16			}
17			this.parent = this.target.parentNode;
18			this.root   = (($p, $r) => {
19				let p = $p;
20				while(p && !p.classList?.contains($r)){
21					p = p.parentNode;
22				}
23				return p;
24			})(this.parent, $rootClass);
25			if(!this.root){
26				console.error(`Root element of Simple Slider is not found.... Element className is '${$rootClass}'.`);
27				return;
28			}
29			this.target.dataset.role = "target";
30			// Constance Values
31			this.setConstanceValues();
32			// Set Elements
33			this.setElements();
34			// Set Scroll Operation
35			this.setScroll();
36			// Set Resize Operation
37			this.resize();
38			//
39			this.isDoneInitialize = true;
40		}
41
42		setConstanceValues(){
43			if(this.isDoneInitialize){
44				return;
45			}
46			// Image Size
47			this.widthImage = Number(this.root?.style.getPropertyValue("--sb-csp-width-base").trim().replace(/(\d+(?:\.\d+)?)px/, "$1")) || 300;   // Initial Value is Base Width
48			Object.defineProperty(this, "widthBase", { value: this.widthImage });
49			Object.defineProperty(this, "widthMin",  { value: Number(this.root?.style.getPropertyValue("--sb-csp-width-min" ).trim().replace(/(\d+(?:\.\d+)?)px/, "$1")) || 200 });
50			Object.defineProperty(this, "colsMin",   { value: Number(this.root?.style.getPropertyValue("--sb-csp-columns-min")) || 2 });
51			// Is Touch Device
52			Object.defineProperty(this, "isTouchDevice", { value: "ontouchstart" in window || "ontouchstart" in document.body });
53			// Transition Time
54			const duration = this.root?.style.getPropertyValue("--sb-csp-scroll-duration").trim().replace(/(\d+(?:\.\d+)?)([um]?s)/i, ($m, $num, $unit) => {
55				if($unit === "us"){
56					return Number($num / 1000);
57				}
58				if($unit === "ms"){
59					return Number($num);
60				}
61				return Number($num * 1000);
62			});
63			Object.defineProperty(this, "duration", { value: duration || 300 });
64			// Numerical accuracy of cubic-bezier
65			Object.defineProperty(this, "cubicBezierAccuracy", { value: Number(this.root?.style.getPropertyValue("--sb-csp-cubix-bezier-acc")) || 5e-2 });   // Default: 5%
66			// Easing Function
67			const easingFunction = ((_this, $m) => {
68				switch($m){
69					case "1":
70						return _this.easeLinear;
71					break;
72					case "2":
73						return _this.easeInOutSine;
74					break;
75					case "3":
76						return _this.easeInOutQuad;
77					break;
78					case "4":
79						return _this.easeOutBounce;
80					break;
81					case "5":
82						return _this.easeInOutCubic;
83					break;
84					
85					case "99":
86						// Default: cubic-bezier(0.46, 0, 0.36, 1.44)
87						const x1 = _this.clamp(0, Number(_this.root?.style.getPropertyValue("--sb-csp-cubix-bezier-x1").trim() || 0.46), 1);
88						const y1 = Number(_this.root?.style.getPropertyValue("--sb-csp-cubix-bezier-y1").trim() || 0   );
89						const x2 = _this.clamp(0, Number(_this.root?.style.getPropertyValue("--sb-csp-cubix-bezier-x2").trim() || 0.36), 1);
90						const y2 = Number(_this.root?.style.getPropertyValue("--sb-csp-cubix-bezier-y2").trim() || 1.44);
91						return _this.cubicBezier(x1, y1, x2, y2);
92					break;
93				}
94				return _this.easeInOutQuad;
95			})(this, this.root?.style.getPropertyValue("--sb-csp-easing-function").trim());
96			Object.defineProperty(this, "easingFunction", { value: easingFunction || this.easeInOutQuad });
97		}
98
99		setElements(){
100			if(this.isDoneInitialize){
101				return;
102			}
103			// Add Styles at Attribute
104			this.target.style.overflow = "hidden";
105			if(window.getComputedStyle(this.parent).position === "static"){
106				this.parent.style.position = "relative";
107			}
108			// Fit to Container
109			this.adjustImageWidth();
110			// Scroll Buttons
111			if(!this.isTouchDevice){
112				this.buttonMoveLeft  = this.parent.appendChild(document.createElement("button"));
113				this.buttonMoveRight = this.parent.appendChild(document.createElement("button"));
114				this.buttonMoveLeft .className = "ig-scroll-move-left";
115				this.buttonMoveRight.className = "ig-scroll-move-right";
116				this.buttonMoveLeft .type      = "button";
117				this.buttonMoveRight.type      = "button";
118				this.buttonMoveLeft .ariaLabel = "Slide to Left";
119				this.buttonMoveRight.ariaLabel = "Slide to Right";
120			}
121			// Show Navigation
122			this.setNavigationElements();
123		}
124
125		setNavigationElements(){
126			if(this.nav){
127				this.nav.remove();
128				delete this.nav;
129			}
130			this.nav = this.parent.insertBefore(document.createElement("ul"), this.target.nextElementSibling);
131			this.nav.className = "ig-scroll-nav";
132			this.navs = [];
133			const widthClient = this.getBoxWidthClient();
134			const widthScroll = this.getBoxWidthScroll();
135			if(widthScroll === widthClient){
136				this.nav.remove();
137				this.buttonMoveLeft?.remove();
138				this.buttonMoveRight?.remove();
139				delete this.nav, this.buttonMoveLeft, this.buttonMoveRight;
140			}
141			const nums = Math.ceil( widthScroll / this.imagePlusGap );
142			for(let i = 0; i < nums; ++i){
143				this.navs.push(this.nav.appendChild(document.createElement("li")));
144				const _nav = this.navs[i].appendChild(document.createElement("button"));
145				_nav.addEventListener("click", this.scrollToIndex.bind(this, i), false);
146				_nav.type      = "button";
147				_nav.ariaLabel = `Slide to Index ${i + 1}`;
148			}
149			const _this = this;
150			this.navPos = new Proxy({ current: 0 }, {
151				set(_obj, _prop, _newVal){
152					const _oldVal = _obj[_prop];
153					if(_prop === "current"){
154						if(_this.navs[_oldVal]){
155							_this.navs[_oldVal].classList.remove("current");
156						}
157						if(_this.navs[_newVal]){
158							_this.navs[_newVal].classList.add("current");
159						}
160					}
161					_obj[_prop] = _newVal;
162					return true;
163				}
164			});
165			const right = this.getCurrentRight();
166			this.showNavCurrent(right);
167			// Arrow Buttons
168			if(!this.isTouchDevice){
169				const rectTarget     = this.target.getBoundingClientRect();
170				const rectParent     = this.parent.getBoundingClientRect();
171				const positionTop    = rectTarget.top    - rectParent.top;
172				const positionBottom = rectParent.bottom - rectTarget.bottom;
173				this.buttonMoveLeft .style.top    = positionTop + "px";
174				this.buttonMoveRight.style.top    = positionTop + "px";
175				this.buttonMoveLeft .style.bottom = positionBottom + "px";
176				this.buttonMoveRight.style.bottom = positionBottom + "px";
177				this.buttonMoveLeft .style.width  = `clamp(3em, ${this.widthImage * 0.2}px, 6em)`;
178				this.buttonMoveRight.style.width  = `clamp(3em, ${this.widthImage * 0.2}px, 6em)`;
179			}
180		}
181
182		showNavCurrent($right, $index){
183			if($index !== undefined){
184				this.navPos.current = $index;
185				this.toggleDisplayButtonMove($index);
186				return;
187			}
188			const scrollMax = this.getBoxWidthScroll() - this.getBoxWidthClient();
189			const navsNum   = this.navs.length;
190			const divisions = Math.max(1, (navsNum - 1) * 2);
191			const divBase   = scrollMax / divisions;
192			if(divBase < 1){
193				return;
194			}
195			let x = 0;
196			while($right >= x++ * divBase){
197				if($right < x * divBase){
198					break;
199				}
200			}
201			const index = ~~(x / 2);
202			this.navPos.current = index;
203			this.toggleDisplayButtonMove(index)
204		}
205
206		toggleDisplayButtonMove($index){
207			if($index === undefined){
208				return;
209			}
210			const indexMax = this.navs.length - 1;
211			if(!this.isTouchDevice){
212				this.buttonMoveLeft .style.display = $index > 0        ? "" : "none";
213				this.buttonMoveRight.style.display = $index < indexMax ? "" : "none";
214			}
215		}
216
217		getBoxWidthClient(){
218			return this.target.clientWidth;
219		}
220
221		getBoxWidthScroll(){
222			return this.target.scrollWidth;
223		}
224
225		getCurrentRight(){
226			return this.target.getBoundingClientRect().left - this.target.firstElementChild.getBoundingClientRect().left;
227		}
228
229		easeLinear($t){
230			return $t;
231		}
232
233		easeInOutSine($t){
234			return -(Math.cos(Math.PI * $t) - 1) / 2;
235		}
236
237		easeInOutQuad($t){
238			return $t < 0.5 ? (2 * $t * $t) : (-1 + (4 - 2 * $t) * $t);
239		}
240
241		easeInOutCubic($t){
242			return $t < 0.5 ? 4 * ($t ** 3) : 1 - (-2 * $t + 2 ) ** 3 / 2;
243		}
244
245		easeOutBounce($t){
246			const n1 = 7.5625;
247			const d1 = 2.75;
248			if($t < 1 / d1){
249				return n1 * $t * $t;
250			} else if($t < 2 / d1){
251				return n1 * ($t -= 1.5 / d1) * $t + 0.75;
252			} else if($t < 2.5 / d1){
253				return n1 * ($t -= 2.25 / d1) * $t + 0.9375;
254			} else{
255				return n1 * ($t -= 2.625 / d1) * $t + 0.984375;
256			}
257		}
258
259		cubicBezier($x1, $y1, $x2, $y2){
260			// Refer: http://www.moshplant.com/direct-or/bezier/math.html
261			const cx = 3 * $x1,
262			      bx = 3 * ($x2 - $x1) - cx,
263			      ax = 1 - cx - bx;
264			const cy = 3 * $y1,
265			      by = 3 * ($y2 - $y1) - cy,
266			      ay = 1 - cy - by;
267			// X-coordinate with mediate variable displayed
268			var bezierX = $t => {
269				return $t * (cx + $t * (bx + $t * ax));
270			};
271			// t-diff of X coordinate
272			var bezierDX = $t => {
273				return cx + $t * (2 * bx + 3 * ax * $t);
274			};
275			// Numerical analysis by Newton's method
276			var newtonRaphson = $x => {
277				if($x <= 0){
278					return 0;
279				}
280				if($x >= 1){
281					return 1;
282				}
283				let prev, t = $x;
284				do{
285					prev = t;
286					t = t - ((bezierX(t) - $x) / bezierDX(t));
287				} while(Math.abs(t - prev) > this.cubicBezierAccuracy);
288				return t;
289			};
290			return function($t){
291				// Obtain the value of the mediator variable t corresponding to the X coordinate (time)
292				const t = newtonRaphson($t);
293				// Calculate Y-coordinate (Easing amount)
294				return t * (cy + t * (by + t * ay));
295			};
296		}
297
298		clamp($min, $value, $max){
299			const value = Number($value) || 0;
300			return Math.min($max, Math.max($min, value));
301		}
302
303		getGap(){
304			const _this = this;
305			const gap = Number(window.getComputedStyle(this.target).columnGap.replace(/(\d+(?:\.\d+)?)(px|%)/, ($m, $num, $unit) => {
306				if($unit === "px"){
307					return Number($num);
308				}
309				if($unit === "%"){
310					return Number($num) / 100 * _this.parent.clientWidth;
311				}
312				return 0;
313			}));
314			if(!Number.isFinite(gap)){
315				return 0;
316			}
317			return gap;
318		}
319
320		adjustImageWidth(){
321			this.parent.style.removeProperty("width");
322			const widthClient = this.getBoxWidthClient();
323			const widthScroll = this.getBoxWidthScroll();
324			if(widthClient === widthScroll){
325				this.parent.style.width = widthClient + "px";
326				this.root.style.removeProperty("--sb-csp-width-fit");
327				return true;
328			}
329			if(!this.root){
330				return false;
331			}
332			//
333			const gap = this.getGap();
334			let columns    = Math.max( this.colsMin, Math.ceil( ( widthClient + gap ) / ( this.widthBase + gap ) ) );
335			let widthGuess = ( widthClient + gap ) / columns - gap;
336			while(widthGuess < this.widthMin && columns > this.colsMin){
337				widthGuess = ( widthClient + gap ) / --columns - gap;
338			}
339			if(this.parent.dataset.size !== "fit-container"){
340				widthGuess = Math.min(widthGuess, this.widthBase);
341				this.parent.style.setProperty("width", `${( this.widthImage + gap ) * this.columns - gap}px`);
342			//	this.root.style.removeProperty("--sb-csp-width-fit");
343			}
344			this.widthImage = widthGuess;
345			this.root.style.setProperty("--sb-csp-width-fit", this.widthImage + "px");
346			this.columns   = columns;
347			this.isColsMin = this.columns <= this.colsMin;
348			this.imagePlusGap = ( this.widthImage + gap ) * this.columns;
349			return true;
350		}
351
352		setScroll(){
353			if(this.isTouchDevice){
354				this.setScrollSP();
355			} else{
356				this.setScrollPC();
357			}
358		}
359
360		setScrollSP(){
361			if(this.isDoneInitialize){
362				return;
363			}
364			// Touch Vars
365			const touch = {
366				startX: 0,
367				movedX: 0,
368				currentRight: 0,
369				startTime: 0,
370			};
371			// Self Instance
372			const _this = this;
373			// Touch Start
374			this.target.addEventListener("touchstart", $event => {
375				touch.startX = touch.movedX = $event.changedTouches[0].pageX;
376				touch.currentRight = _this.getCurrentRight();
377				touch.startTime    = (new Date()).getTime();
378			}, {passive : false});
379			// Touch Moving
380			this.target.addEventListener("touchmove", $event => {
381				touch.movedX  = $event.changedTouches[0].pageX;
382				// Box Width
383				const widthClient = _this.getBoxWidthClient();
384				const widthScroll = _this.getBoxWidthScroll();
385				// Scroll Position Follows Swiping
386				const max   = widthScroll - widthClient;
387				const move  = touch.currentRight + (touch.startX - touch.movedX);
388				const right = Math.max(0, Math.min(move, max));
389				// Scroll
390				_this.target.scrollTo(right, 0);
391				// Show Current Nav
392				_this.showNavCurrent(right);
393			}, {passive : false});
394			// Touch End
395			this.target.addEventListener("touchend", $event => {
396				if(!this.isColsMin){
397					// Box Width
398					const widthClient = _this.getBoxWidthClient();
399					const widthScroll = _this.getBoxWidthScroll();
400					// Scroll Position Follows Swiping
401					const max   = widthScroll - widthClient;
402					const move  = touch.startX - touch.movedX;
403					const time  = (new Date()).getTime() - touch.startTime;
404					let accelerate = move / time * 17;
405					// Momentum Scrolling
406					let timestamp = null;
407					window.requestAnimationFrame(function momentumScrolling($timestamp){
408						timestamp = timestamp || $timestamp;
409						accelerate = accelerate / Math.pow(1.06, ($timestamp - timestamp) / 17);
410						timestamp = $timestamp;
411						const targetLeft = _this.target.getBoundingClientRect().left;
412						const scrollLeft = _this.target.firstElementChild.getBoundingClientRect().left;
413						const right = _this.clamp(0, targetLeft - scrollLeft + accelerate, max);
414						if(right <= 0 || right >= max){
415							accelerate = 0;
416						}
417						// Scroll
418						_this.target.scrollTo(right, 0);
419						// Show Current Nav
420						_this.showNavCurrent(right);
421						// Render a Next Frame
422						if(Math.abs(accelerate) > 1){
423							window.requestAnimationFrame(momentumScrolling);
424						}
425					});
426				} else{
427					// Box Width
428					const widthClient = _this.getBoxWidthClient();
429					const widthScroll = _this.getBoxWidthScroll();
430					// Box Scrolled Position
431					const right = _this.getCurrentRight();
432					// Gap
433					const gap = _this.getGap();
434					// The Min Columns are Scrolled Together
435					const goal = ($right => {
436						let goal = 0;
437						if(Math.abs(touch.currentRight - $right) / widthClient < 0.2){
438							goal = touch.currentRight;
439						} else{
440							if(touch.currentRight > $right){
441								goal = Math.max(0, touch.currentRight - widthClient - gap)
442							} else{
443							//	goal = Math.min(touch.currentRight + _this.imagePlusGap, widthScroll - widthClient);
444								goal = touch.currentRight + _this.imagePlusGap;
445							}
446						}
447						goal = ~~( goal / _this.imagePlusGap + 0.5 ) * _this.imagePlusGap;
448						return goal;
449					})(right);
450					// Scrolling
451					_this.scrollTo({
452						right : right,
453						goal  : goal,
454					});
455				}
456			}, false);
457		}
458
459		setScrollPC(){
460			if(this.isDoneInitialize){
461				return;
462			}
463			/**
464			 * Calcurate the Next Position
465			 * 
466			 * @param     $direction: -1 or +1
467			 * @required  Bind a Class Instance to 'this'
468			 */
469			const calcGoal = function($direction){
470				this.scrollToIndex(this.navPos.current + $direction);
471			};
472			// Set Event
473			this.buttonMoveLeft .addEventListener("click", calcGoal.bind(this, -1), false);
474			this.buttonMoveRight.addEventListener("click", calcGoal.bind(this, +1), false);
475		}
476
477		scrollToIndex($index){
478			const index = ~~(this.clamp(0, $index, this.navs.length - 1));
479			const goal  = this.imagePlusGap * index;
480			const right = this.getCurrentRight();
481			this.scrollTo({
482				right : right,
483				goal  : goal,
484				index : index,
485			});
486		}
487
488		scrollTo($scrollParams){
489			const _this     = this;
490			let   _duration = Number(this.duration);
491			// Max Scroll Width
492			const scrollMax = this.getBoxWidthScroll() - this.getBoxWidthClient();
493			// Previous Position
494			const startRelativePos   = ($scrollParams.goal < $scrollParams.right ? +1 : -1) * this.imagePlusGap;
495			$scrollParams.rightStart = $scrollParams.goal + startRelativePos;
496			// Halfway Scrolling
497			if(scrollMax < $scrollParams.goal){
498				_duration          = ~~(_duration * Math.sqrt( Math.abs( (scrollMax - $scrollParams.rightStart) / ($scrollParams.goal - $scrollParams.rightStart) ) ) );
499				$scrollParams.goal = scrollMax;
500			}
501			if($scrollParams.right > $scrollParams.goal && this.imagePlusGap > $scrollParams.right){
502				_duration          = ~~(_duration * Math.sqrt( $scrollParams.right / this.imagePlusGap ) );
503				$scrollParams.goal = 0;
504			}
505			// Run Animation
506			window.requestAnimationFrame(function easeScrolling($microTimestamp){
507				const now = $microTimestamp;
508				// Start Time
509				$scrollParams.timeStart = $scrollParams.timeStart || now;
510				// 
511				const spentTime = now - $scrollParams.timeStart;
512				const process   = spentTime / _duration;
513				// Scroll
514				const right = $scrollParams.right + ($scrollParams.goal - $scrollParams.right) * _this.easingFunction(process);
515				_this.target.scrollTo(right, 0);
516				if(right < 0){
517					_this.target.style.setProperty("--sb-csp-scroll-right", `${right}px`);
518				}
519				if(right > scrollMax){
520					_this.target.style.setProperty("--sb-csp-scroll-right", `${right - scrollMax}px`);
521				}
522				// Show Current Nav
523				_this.showNavCurrent(right, $scrollParams.index);
524				// Render a Next Frame
525				if(Math.abs(process) < 1){
526					window.requestAnimationFrame(easeScrolling);
527				}
528			});
529		}
530
531		resize(){
532			if(this.isDoneInitialize){
533				return;
534			}
535			// Global
536			window.__stillbe = window.__stillbe || {};
537			window.__stillbe.resizeObserver = window.__stillbe.resizeObserver || new ResizeObserver(entries => {
538				let instance = null;
539				for(const entry of entries){
540					instance = null;
541					for(const slider of (window.__stillbe?.vars?.sliders || [])){
542						if(entry.target.querySelector("[data-role='target']") === slider.target){
543							instance = slider.instance;
544							break;
545						}
546					}
547					if(instance){
548						instance.adjustImageWidth();
549						instance.target.scrollTo(0, 0);
550						instance.setNavigationElements();
551					}
552				}
553			});
554			// Observe Slider Target Element
555			window.__stillbe.resizeObserver.observe(this.root);
556		/*
557			// 
558			const _this = this;
559			window.addEventListener("resize", () => {
560				_this.adjustImageWidth();
561				_this.target.scrollTo(0, 0);
562				_this.setNavigationElements();
563			}, false);
564		*/
565		}
566
567	}
568
569
570	// Global for Editor
571	window.__stillbe              = window.__stillbe || {};
572	window.__stillbe.class        = window.__stillbe.class || {};
573	window.__stillbe.class.Slider = window.__stillbe.class.Slider || Slider;
574
575
576})();

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.