PageSourceSearch

https://thaihealthacademy.com/js/custom.js?v=25690608

js thaihealthacademy.com collected 2026-09-29 00:16:14 UTC 35,311 bytes, 1,406 lines download raw bytes

1
2var _baseUriApi;
3var _serverSite;
4var _currentCulture;
5
6document.addEventListener('DOMContentLoaded', function () {
7	var clipboard = new ClipboardJS('.btn-clipboard');
8
9	clipboard.on('success', function (e) {
10		SuccessAlert("Copy successfully")
11		e.clearSelection();
12	});
13
14	clipboard.on('error', function (e) {
15		console.error('Error copying text: ', e);
16	});
17
18	// ป้องกัน Enter submit form ใน input/select
19	document.addEventListener('keydown', function (e) {
20		//console.log('e.key', e.key)
21		if (e.key === 'Enter' &&
22			(e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') &&
23			e.target.type !== 'submit' &&
24			e.target.type !== 'button' &&
25			e.target.type !== 'textarea') {
26			e.preventDefault();
27			return false;
28		}
29	});
30});
31
32window.blazorBookingModalBridge = function (dotNetHelper) {
33	setTimeout(function () {
34		window.callBlazorOpenModal = function (startDate, endDate) {
35			dotNetHelper.invokeMethodAsync('OpenModalSpaceBookingFromJS', startDate, endDate);
36		}
37	}, 500)
38}
39
40window.checkFunctionExists = function (functionName) {
41	//console.log(typeof window[functionName] === 'function')	
42	return typeof window[functionName] === 'function';
43}
44
45window.trackGoogleAdsConversion = function (sendTo, value, currency) {
46	if (typeof gtag !== 'function') {
47		return;
48	}
49
50	gtag('event', 'conversion', {
51		'send_to': sendTo,
52		'value': value || 1.0,
53		'currency': currency || 'THB'
54	});
55}
56
57window.initializeHomeLayout = () => {
58	var elem = document.getElementsByClassName('main_cookie')[0];
59	if (elem) {
60		elem.style.marginTop = '0';
61	}
62
63	_baseUriApi = $('#hid_baseUriApi').val()
64	_serverSite = $('#hid_serverSite').val()
65	_currentCulture = $('#hid_currentCulture').val()
66	InitScrollTop()
67	//filterHtml()
68}
69
70window.initializeMainLayout = () => {
71	if (window.location.pathname != '/') {
72		var elem = document.getElementById("fv-dots");
73		if (elem != null && elem != undefined) {
74			elem.parentElement.removeChild(elem);
75		}
76	}
77	_baseUriApi = $('#hid_baseUriApi').val()
78
79	InitScrollTop()
80	//filterHtml()
81}
82
83window.multiSelectHelper = {
84	registerOutsideClick: function (dotnetRef, elementId) {
85		function handler(e) {
86			const el = document.getElementById(elementId);
87			if (el && !el.contains(e.target)) {
88				dotnetRef.invokeMethodAsync("CloseFromOutside");
89			}
90		}
91		document.addEventListener("mousedown", handler);
92		return { dispose: () => document.removeEventListener("mousedown", handler) };
93	}
94};
95
96window.initializeBootSelect = () => {
97	console.log('initializeBootSelect...')
98	$('.selectpicker').selectpicker('setStyle', 'btn_white');
99}
100
101window.BootSelectClass = (elm_id) => {
102	$(`.${elm_id}`).selectpicker('setStyle', 'btn_white');
103}
104
105window.BootSelectID = (elm_id) => {
106	$(`#${elm_id}`).selectpicker('setStyle', 'btn_white');
107}
108
109window.BootSelectRefreshID = (elm_id, time = 10) => {
110	setTimeout(function () {
111		$(`#${elm_id}`).selectpicker('refresh');
112	}, time)
113}
114
115window.BootSelectVal = (elm_id, value = '') => {
116	$(`#${elm_id}`).selectpicker('val', `#${value}`);
117}
118
119window.BootSelectRender = (elm_id) => {
120	$(`#${elm_id}`).selectpicker('render');
121}
122
123window.BootSelectClassDestroy = (elm_id) => {
124	$(`.${elm_id}`).selectpicker('destroy');
125}
126
127window.BootSelectDestroy = (elm_id) => {
128	$(`#${elm_id}`).selectpicker('destroy');
129}
130
131window.BootSelectEmptyID = (elm_id) => {
132	$(`#${elm_id}`).selectpicker('destroy');
133	$(`#${elm_id}`).selectpicker('setStyle', 'btn_white');
134	$(`#${elm_id}`).selectpicker('refresh');
135}
136
137window.deselectAllSelectPicker = (id) => {
138	let $select = $(`#${id}`);
139	$select.selectpicker('deselectAll');
140	$select.selectpicker('render');
141}
142
143//รอจนกว่า <select> มี <option> อยู่ในนั้นก่อนที่จะเรียก selectpicker
144window.BootSelectWaitForHaveOptions = (id, _liveSearch = true) => {
145	return new Promise((resolve) => {
146		const timeout = 10000; // 10 วินาที (ในหน่วยมิลลิวินาที)
147		const startTime = Date.now(); // เวลาเริ่มต้น
148
149		const checkOptions = () => {
150			const selectElement = document.getElementById(id);
151			const elapsedTime = Date.now() - startTime; // เวลาที่ผ่านไป
152
153			// ถ้าเกิน 10 วินาทีให้หยุดและ resolve โดยไม่ทำอะไรเพิ่ม
154			if (elapsedTime >= timeout) {
155				console.warn(`Timeout: No options found for select with id "${id}" after 10 seconds.`);
156				resolve(); // หยุดการทำงานโดยไม่ reject
157				return;
158			}
159
160			// ถ้ามี <option> ใน <select>
161			//console.log(selectElement)
162			//console.log(selectElement.options.length)
163			if (selectElement && selectElement.options.length > 0) {
164				$(`#${id}`)
165					.selectpicker('destroy')  // รีเซ็ตอย่างสมบูรณ์
166					.selectpicker({  // กำหนดค่าใหม่อย่างครบถ้วน
167						liveSearch: _liveSearch,
168						actionsBox: true,
169						width: '100%',
170						style: 'select_btn_set'
171					});
172				resolve();
173			} else {
174				// ถ้ายังไม่มี <option> ให้ตรวจสอบอีกครั้ง
175				requestAnimationFrame(checkOptions);
176			}
177		};
178
179		checkOptions();
180	});
181};
182
183
184//window.InitSelectPicker = (dotnetHelper, callbackMethodName, pickerElementName) => {
185//	$(pickerElementName).selectpicker('setStyle', 'btn_white');
186//	$(pickerElementName).on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) {
187//		console.log('Select picker changed');
188//		dotnetHelper.invokeMethodAsync(callbackMethodName, $(pickerElementName).val(), $(pickerElementName + ' option:selected').text())
189//			.then(data => {
190
191//			});
192//	});
193//}
194
195// debouncing ช่วยป้องกันการทริกเกอร์ซ้ำได้ **ตัวอย่างที่ขึ้นซ้ำ ( --เลือก-- --เลือก-- )
196let debounceTimeout;
197window.InitSelectPicker = (dotnetHelper, callbackMethodName, pickerElementName) => {
198	$(pickerElementName).selectpicker('setStyle', 'btn_white');
199
200	//console.log('Event triggered');
201	$(pickerElementName).on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) {
202		clearTimeout(debounceTimeout);
203		debounceTimeout = setTimeout(() => {
204			//console.log('Select picker changed');
205			dotnetHelper.invokeMethodAsync(callbackMethodName, $(pickerElementName).val(), $(pickerElementName + ' option:selected').text())
206				.then(data => {
207					console.log('InitSelectPicker...then')
208				})
209				.catch(error => {
210					console.error('InitSelectPicker', error);
211				});
212		}, 300);
213	});
214}
215
216
217
218window.initializeCarousel = () => {
219	$('#carouselBannerControls3').carousel({ interval: 10000 });
220	playVideo();
221
222}
223
224window.carouselBannerHome = () => {
225	$('#carouselBannerHome').carousel({ interval: 100000 });
226	playVideo();
227
228}
229
230window.PopupShow = () => {
231	var popupModalEL = document.getElementById('PopupMasterModal');
232	if (popupModalEL instanceof HTMLElement) {
233		var popupModal = new bootstrap.Modal(popupModalEL, {})
234		popupModal.show()
235	}
236}
237
238window.slick_home_trainingel = () => {
239
240	$('#slick_home_trainingel').slick({
241		infinite: true,
242		slidesToShow: 2,
243		slidesToScroll: 2,
244		autoplaySpeed: 3000,
245		//autoplay: true,
246		dots: true,
247		arrows: false,
248		rows: 2, // แสดง 2 แถวในแต่ละ slide
249		responsive: [
250			{
251				breakpoint: 768,
252				settings: {
253					dots: true,
254					arrows: false,
255					slidesToShow: 1,
256					slidesToScroll: 1,
257					//vertical: true, // ทำให้การเลื่อนเป็นแนวตั้ง
258					slidesPerRow: 1 // แสดง 1 กล่องต่อแถว
259				}
260			},
261			{
262				breakpoint: 480,
263				settings: {
264					dots: true,
265					arrows: false,
266					slidesToShow: 1,
267					slidesToScroll: 1,
268				}
269			}
270		]
271	});
272}
273
274window.slick_home_space = () => {
275
276	$('#slick_home_space').slick({
277		infinite: true,
278		slidesToShow: 3,
279		autoplaySpeed: 3000,
280		//autoplay: true,
281		dots: false,
282		arrows: true,
283		responsive: [
284			{
285				breakpoint: 992,
286				settings: {
287					dots: false,
288					arrows: true,
289					slidesToShow: 3
290				}
291			},
292			{
293				breakpoint: 768,
294				settings: {
295					dots: false,
296					arrows: true,
297					slidesToShow: 2
298				}
299			},
300			{
301				breakpoint: 480,
302				settings: {
303					dots: true,
304					arrows: false,
305					slidesToShow: 1
306				}
307			}
308		]
309	});
310}
311
312window.slick_home_credit = () => {
313
314	$('#slick_home_credit').slick({
315		infinite: true,
316		centerPadding: '10px',
317		slidesToShow: 6,
318		autoplaySpeed: 3000,
319		autoplay: true,
320		dots: false,
321		arrows: true,
322		responsive: [
323			{
324				breakpoint: 992,
325				settings: {
326					dots: false,
327					arrows: true,
328					centerPadding: '10px',
329					slidesToShow: 3
330				}
331			},
332			{
333				breakpoint: 768,
334				settings: {
335					dots: true,
336					arrows: false,
337					centerPadding: '10px',
338					slidesToShow: 2
339				}
340			},
341			{
342				breakpoint: 480,
343				settings: {
344					dots: true,
345					arrows: false,
346					centerPadding: '10px',
347					slidesToShow: 1
348				}
349			}
350		]
351	}).on('afterChange', function (event, slick, currentSlide) {
352		// โค้ดที่ต้องการให้ทำงานหลังจาก Slick เปลี่ยน slide แรก
353		//if (currentSlide === 1) {
354		//	$('.slick_main').css('visibility', 'visible');
355		//}
356	});
357}
358
359window.slick_result_el = () => {
360
361	$('#slick_result_el').slick({
362		infinite: true,
363		centerMode: true,
364		centerPadding: '10px',
365		slidesToShow: 3,
366		autoplaySpeed: 3000,
367		autoplay: true,
368		dots: false,
369		arrows: true,
370		responsive: [
371			{
372				breakpoint: 992,
373				settings: {
374					dots: false,
375					arrows: true,
376					centerMode: false,
377					centerPadding: '10px',
378					slidesToShow: 1
379				}
380			},
381			{
382				breakpoint: 768,
383				settings: {
384					dots: false,
385					arrows: true,
386					centerMode: true,
387					centerPadding: '10px',
388					slidesToShow: 1
389				}
390			},
391			{
392				breakpoint: 480,
393				settings: {
394					dots: true,
395					arrows: false,
396					centerMode: true,
397					centerPadding: '10px',
398					slidesToShow: 1
399				}
400			}
401		]
402	});
403}
404
405window.slick_tn_promo = () => {
406
407	$('#slick_tn_promo').slick({
408		infinite: true,
409		centerPadding: '10px',
410		slidesToShow: 3,
411		autoplaySpeed: 3000,
412		//autoplay: true,
413		dots: false,
414		arrows: true,
415		responsive: [
416			{
417				breakpoint: 992,
418				settings: {
419					dots: false,
420					arrows: true,
421					centerMode: false,
422					centerPadding: '10px',
423					slidesToShow: 1
424				}
425			},
426			{
427				breakpoint: 768,
428				settings: {
429					dots: false,
430					arrows: true,
431					centerMode: true,
432					centerPadding: '10px',
433					slidesToShow: 1
434				}
435			},
436			{
437				breakpoint: 480,
438				settings: {
439					dots: true,
440					arrows: false,
441					centerMode: true,
442					centerPadding: '10px',
443					slidesToShow: 1
444				}
445			}
446		]
447	});
448}
449
450window.slick_about_credit = () => {
451
452	$('#slick_about_credit').slick({
453		infinite: true,
454		centerPadding: '10px',
455		slidesToShow: 6,
456		autoplaySpeed: 3000,
457		autoplay: true,
458		dots: false,
459		arrows: true,
460		responsive: [
461			{
462				breakpoint: 992,
463				settings: {
464					dots: false,
465					arrows: true,
466					centerPadding: '10px',
467					slidesToShow: 3
468				}
469			},
470			{
471				breakpoint: 768,
472				settings: {
473					dots: true,
474					arrows: false,
475					centerPadding: '10px',
476					slidesToShow: 2
477				}
478			},
479			{
480				breakpoint: 480,
481				settings: {
482					dots: true,
483					arrows: false,
484					centerPadding: '10px',
485					slidesToShow: 1
486				}
487			}
488		]
489	}).on('afterChange', function (event, slick, currentSlide) {
490		// โค้ดที่ต้องการให้ทำงานหลังจาก Slick เปลี่ยน slide แรก
491		//if (currentSlide === 1) {
492		//	$('.slick_main').css('visibility', 'visible');
493		//}
494	});
495}
496
497
498window.triggerFileDownload = (fileName, url, target = null) => {
499	const anchorElement = document.createElement('a');
500	anchorElement.href = url;
501	if (target != null) {
502		anchorElement.target = target;
503	}
504	anchorElement.download = fileName ?? '';
505	anchorElement.click();
506	anchorElement.remove();
507}
508
509window.onScrollTopoEvent = () => {
510	document.documentElement.scrollTop = 0;
511}
512
513window.onScrollBottomEvent = () => {
514	setTimeout(function () {
515		window.scrollTo(0, document.body.scrollHeight);
516	}, 100)
517
518}
519
520window.scrollToElement = (elm) => {
521	var elem = document.getElementById(elm);
522	//console.log(elem)
523	if (elem != null && elem != undefined) {
524		elem.scrollIntoView();
525	}
526}
527
528window.scrollToElementSmooth = (id) => {
529	var element = document.getElementsByClassName(id);
530	if (element != null && element.length > 0) {
531		var requiredElement = element[0];
532		var elementPosition = requiredElement.offsetTop;
533		window.scrollTo({
534			top: elementPosition - 40, //add your necessary value
535			behavior: "smooth"  //Smooth transition to roll
536		});
537	}
538}
539
540window.scrollToValidation = (id) => {
541	var element = document.getElementsByClassName(id);
542	if (element != null && element.length > 0) {
543		var requiredElement = element[0];
544		var elementPosition = requiredElement.offsetTop;
545		window.scrollTo({
546			top: elementPosition - 155, //add your necessary value
547			behavior: "smooth"  //Smooth transition to roll
548		});
549	}
550}
551
552window.sidebarToggleAdmin = () => {
553	const checkSidebarToggle = setInterval(function () {
554		const sidebarToggle = document.getElementById('sidebarToggle');
555		if (sidebarToggle) {
556			// เมื่อเจอ sidebarToggle แล้วให้หยุด interval
557			clearInterval(checkSidebarToggle);
558
559			sidebarToggle.addEventListener('click', event => {
560				event.preventDefault();
561				document.body.classList.toggle('sb-sidenav-toggled');
562				localStorage.setItem('sb|sidebar-toggle', document.body.classList.contains('sb-sidenav-toggled'));
563			});
564		}
565	}, 1000);
566}
567
568window.loadVideo = () => {
569	//console.log('loadVideo...')
570	document.getElementById("video_elm").load();
571}
572
573window.playVideo = () => {
574	//console.log('playVideo...')
575	//var vid = document.getElementById('elm_video');
576	//console.log(vid)
577	//if (vid != null && vid != undefined) {
578	//	setTimeout(function () {
579	//		console.log('load...')
580	//		vid.load();
581	//	}, 3000)
582
583	//}
584	//document.querySelector('video').play();
585}
586
587window.videoContent = (fileAddress) => {
588	console.log(fileAddress)
589	if (fileAddress != null && fileAddress != undefined) {
590		var sourceMP4 = document.createElement("source");
591		sourceMP4.type = "video/mp4";
592
593		//sourceMP4.src = `/files/videos/ep${id}.mp4`;
594		//sourceMP4.src = `/files/resource/video/files/2022/06/ep1.mp4`;
595		sourceMP4.src = `${fileAddress}`;
596
597		var videlem = document.createElement("video");
598		//videlem.height = 400; // 👈️ in px
599		//videlem.width = 600; // 👈️ in pxeds
600		videlem.id = `MediaId`;
601		videlem.muted = true;
602		videlem.autoplay = true;
603		videlem.controls = false;
604		videlem.appendChild(sourceMP4);
605		const box = document.getElementById(`video_elm`);
606		//console.log('box', box)
607		if (box != null && box != undefined) {
608			box.innerHTML = "";
609			box.appendChild(videlem);
610		}
611
612		//var v = document.querySelector('video#MediaId');
613		//var sources = v.querySelectorAll('source');
614		//console.log(sources)
615		//if (sources.length !== 0) {
616		//var lastSource = sources[sources.length - 1];
617
618		//lastSource.addEventListener('error', function () {
619		//	alert('Video Not Found');
620		//});
621		//}
622	}
623}
624
625window.anchorLink = {
626	scrollIntoView: function (elementId) {
627		console.log('anchorLink')
628		//console.log('elementId', elementId)
629		// This function is called from the AnchorLink component using JavaScript interop.
630		// It will try to find an element using the ID given to the function, and scroll that
631		// element into view, if an element is found.
632		var elem = document.getElementById(elementId);
633		if (elem) {
634			//elem.scrollIntoView();
635			//window.location.hash = elementId;
636
637			window.scrollTo({
638				behavior: 'smooth',
639				top:
640					elem.getBoundingClientRect().top -
641					document.body.getBoundingClientRect().top -
642					150,
643			})
644		}
645	}
646}
647
648window.ScrollList = {
649	Init: function (ele, ref) {
650		console.log('ScrollList')
651		window.ScrollList.ifs = new InfiniteScroll(ele, ref);
652	},
653	RemoveListener: function () {
654		window.ScrollList.ifs.RemoveListener();
655	}
656}
657
658//window.clipboardCopy = {
659//	copyText: function (text) {
660//		navigator.clipboard.writeText(text).then(function () {
661//			SuccessAlert("Copy successfully")
662//			//shareOverrideOGMeta('https://uat.thaihealthacademy.com', 'overrideTitle..', 'overrideDescription..', 'https://uat.thaihealthacademy.com/image/logo/tha_logo_fb.jpg')
663//		})
664//			.catch(function (error) {
665//				alert(error);
666//			});
667//	}
668//}
669
670window.clipboardCopy_backup = {
671	copyText: function (text) {
672		let textarea;
673		let result;
674
675		try {
676			textarea = document.createElement('textarea');
677			textarea.setAttribute('readonly', true);
678			textarea.setAttribute('contenteditable', true);
679			textarea.style.position = 'fixed'; // prevent scroll from jumping to the bottom when focus is set.
680			textarea.value = text;
681
682			document.body.appendChild(textarea);
683
684			textarea.focus();
685			textarea.select();
686
687			const range = document.createRange();
688			range.selectNodeContents(textarea);
689
690			const sel = window.getSelection();
691			sel.removeAllRanges();
692			sel.addRange(range);
693
694			textarea.setSelectionRange(0, textarea.value.length);
695			result = document.execCommand('copy');
696			SuccessAlert("Copy successfully")
697		} catch (err) {
698			console.error(err);
699			result = null;
700		} finally {
701			document.body.removeChild(textarea);
702		}
703
704	}
705}
706
707window.clipboardCopy = {
708	copyText: function (text) {
709		//if (navigator.clipboard && window.isSecureContext) {
710		//	console.log('windows')
711		//	// navigator.clipboard API method
712		//	return navigator.clipboard.writeText(text).then(function () {
713		//		SuccessAlert("Copy successfully")
714		//	}, function (err) {
715		//		WarningAlert(`Could not copy text`)
716		//		console.error('Could not copy text: ', err);
717		//	});
718		//} else {
719		console.log('ios')
720		// Fallback method
721		let textArea = document.createElement("textarea");
722		textArea.value = text;
723		textArea.style.position = "fixed";  // Avoid scrolling to bottom
724		document.body.appendChild(textArea);
725		textArea.focus();
726		textArea.select();
727		try {
728			document.execCommand('copy');
729			SuccessAlert("Copy successfully.")
730		} catch (err) {
731			WarningAlert(`Fallback: Oops, unable to copy`)
732			console.error('Fallback: Oops, unable to copy', err);
733		}
734		document.body.removeChild(textArea);
735		//}
736	}
737}
738
739window.PDPATH_Consent = (data) => {
740	setTimeout(async function () {
741		//console.log(data)
742
743		var consentIds = [];
744		for (const property in data.consentIds) {
745			consentIds.push(data.consentIds[property])
746		}
747
748		var new_data = {
749			SiteKey: data.siteKey,
750			UniqueId: data.uniqueId,
751			Email: data.email,
752			PersonName: data.personName,
753			ConsentIds: consentIds
754		};
755		console.log(new_data)
756		await th_consent_get(new_data);
757
758		th_consent_callback = function (callback_data) {
759			console.log(callback_data);
760		};
761	}, 100)
762}
763
764function copyToClipboardEL(el) {
765	//console.log(el)
766	// resolve the element
767	el = (typeof el === 'string') ? document.querySelector(el) : el;
768
769	// handle iOS as a special case
770	//console.log(navigator.userAgent)
771	if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
772		console.log('iOS dev.....')
773		// save current contentEditable/readOnly status
774		var editable = el.contentEditable;
775		var readOnly = el.readOnly;
776
777		// convert to editable with readonly to stop iOS keyboard opening
778		el.contentEditable = true;
779		el.readOnly = true;
780
781		// create a selectable range
782		var range = document.createRange();
783		range.selectNodeContents(el);
784
785		// select the range
786		var selection = window.getSelection();
787		selection.removeAllRanges();
788		selection.addRange(range);
789		el.setSelectionRange(0, 999999);
790
791		// restore contentEditable/readOnly to original state
792		el.contentEditable = editable;
793		el.readOnly = readOnly;
794		console.log('end iOS dev.....')
795	}
796	else {
797		console.log('other dev.....')
798		el.select();
799	}
800
801	// execute copy command
802	//console.log('execCommand.....')
803	document.execCommand('copy');
804	SuccessAlert("Copy successfully")
805	console.log('end execCommand.....')
806}
807
808function copyToClipboardGPT(text) {
809	console.log(text)
810	if (navigator.clipboard && window.isSecureContext) {
811		// navigator.clipboard API method
812		return navigator.clipboard.writeText(text).then(function () {
813			SuccessAlert("Copy successfully")
814		}, function (err) {
815			WarningAlert(`Could not copy text`)
816			console.error('Could not copy text: ', err);
817		});
818	} else {
819		// Fallback method
820		let textArea = document.createElement("textarea");
821		textArea.value = text;
822		textArea.style.position = "fixed";  // Avoid scrolling to bottom
823		document.body.appendChild(textArea);
824		textArea.focus();
825		textArea.select();
826		try {
827			document.execCommand('copy');
828			SuccessAlert("Copy successfully.")
829		} catch (err) {
830			WarningAlert(`Fallback: Oops, unable to copy`)
831			console.error('Fallback: Oops, unable to copy', err);
832		}
833		document.body.removeChild(textArea);
834	}
835}
836
837
838window.saveAsFile = function (fileName, byteBase64) {
839	var link = this.document.createElement('a');
840	link.download = fileName;
841	link.href = "data:application/octet-stream;base64," + byteBase64;
842	this.document.body.appendChild(link);
843	link.click();
844	this.document.body.removeChild(link);
845}
846
847////****ใช้ตัวนี้ทำให้ IOS Error
848//$(document).on("change click keyup input paste", ".moneyformat", function (event) {
849//	$(this).val(function (index, value) {
850//		return value.replace(/(?!\.)\D/g, "").replace(/(?<=\..*)\./g, "").replace(/(?<=\.\d\d).*/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
851//	});
852//});
853
854function isDevice() {
855	let portWidth = window.innerWidth;
856	if (portWidth <= 576) {
857		return true;
858	} else {
859		return false;
860	}
861}
862
863function InitScrollTop() {
864	// Scroll to top button appear
865	$(document).on('scroll', function () {
866		var scrollDistance = $(this).scrollTop();
867		if (scrollDistance > 100) {
868			$('.scroll-to-top').fadeIn();
869		} else {
870			$('.scroll-to-top').fadeOut();
871		}
872	});
873
874}
875
876function toArray(a) {
877	var result = [];
878	var i = a.length;
879	while (i--) {
880		result[i] = a[i];
881	}
882	return result;
883}
884
885function openInNewTab(url, target) {
886	//console.log(url, target)
887	const a = document.createElement("a");
888	a.setAttribute('href', url);
889	a.setAttribute('target', target);
890	a.click();
891
892	//window.open(url, target).focus();
893}
894
895function shareOverrideOGMeta(overrideLink, overrideTitle, overrideDescription, overrideImage) {
896	//console.log('shareOverrideOGMeta...')
897
898	FB.ui({
899		method: 'share_open_graph',
900		action_type: 'og.shares',
901		action_properties: JSON.stringify({
902			object: {
903				'og:url': overrideLink,
904				'og:title': overrideTitle,
905				'og:description': overrideDescription,
906				'og:image': overrideImage
907			}
908		})
909	},
910		function (response) {
911			// Action after response
912		});
913
914	//FB.ui({
915	//	method: 'feed',
916	//	name: 'บริษัท โค๊ดบี จำกัด',
917	//	link: 'https://uat.thaihealthacademy.com',
918	//	picture: 'https://uat.thaihealthacademy.com/image/logo/tha_logo_fb.jpg',
919	//	caption: 'บริษัทรับทำเว็บไซต์และโมบายแอพพลิเคชั่น',
920	//	description: 'บริษัทรับทำเว็บไซต์และโมบายแอพพลิเคชั่น'
921	//});
922
923}
924
925function GetCurrentDate() {
926	const today = new Date();
927	const yyyy = today.getFullYear();
928	let mm = today.getMonth() + 1; // Months start at 0!
929	let dd = today.getDate();
930
931	if (dd < 10) dd = '0' + dd;
932	if (mm < 10) mm = '0' + mm;
933
934	let fullday = yyyy + '-' + mm + '-' + dd;
935
936	return fullday;
937}
938
939function GetDateFormat(date) {
940	const yyyy = date.getFullYear();
941	let mm = date.getMonth() + 1; // Months start at 0!
942	let dd = date.getDate();
943
944	if (dd < 10) dd = '0' + dd;
945	if (mm < 10) mm = '0' + mm;
946
947	let fullday = yyyy + '-' + mm + '-' + dd;
948
949	//console.log(yyyy)
950	//console.log(mm)
951	//console.log(dd)
952	//console.log(fullday)
953	return fullday;
954}
955
956function hover_home() {
957	var element = document.getElementById("icon_home");
958	if (element) {
959		element.setAttribute('src', '/image/icon/home_2x.png');
960	}
961}
962
963function unhover_home(element, src) {
964	var element = document.getElementById("icon_home");
965	if (element) {
966		if (window.location.pathname == '/') {
967			element.setAttribute('src', '/image/icon/home_2x.png');
968		} else {
969			element.setAttribute('src', '/image/icon/home2_2x.png');
970		}
971	}
972}
973
974
975$(function () {
976	//document.body.style.msTouchAction = "none";
977	//Prevent pull to refresh chrome
978	var lastTouchY = 0;
979	var preventPullToRefresh = false;
980
981	//$('body').on('touchstart', function (e) {
982	//	if (e.originalEvent.touches.length != 1) {
983	//		return;
984	//	}
985	//	lastTouchY = e.originalEvent.touches[0].clientY;
986	//	preventPullToRefresh = window.pageYOffset == 0;
987	//});
988
989	//$('body').on('touchmove', function (e) {
990	//	var touchY = e.originalEvent.touches[0].clientY;
991	//	var touchYDelta = touchY - lastTouchY;
992	//	lastTouchY = touchY;
993	//	if (preventPullToRefresh) {
994	//		// To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
995	//		preventPullToRefresh = false;
996	//		if (touchYDelta > 0) {
997	//			e.preventDefault();
998	//			return;
999	//		}
1000	//	}
1001	//});
1002
1003})
1004
1005function enforceMinMax(el) {
1006	if (el.value != "") {
1007		if (parseInt(el.value) < parseInt(el.min)) {
1008			el.value = el.min;
1009		}
1010		if (parseInt(el.value) > parseInt(el.max)) {
1011			el.value = el.max;
1012		}
1013	}
1014}
1015
1016function enforceMinMaxFloat(el) {
1017	console.log('enforceMinMaxFloat..')
1018	if (el.value != "") {
1019		console.log(el.value);
1020		// แปลงค่าที่มี "," เป็นค่าตัวเลข
1021		let numericValue = parseFloat(el.value.replace(/,/g, ''));
1022		console.log(numericValue);
1023
1024		if (numericValue < parseFloat(el.min)) {
1025			el.value = el.min;
1026		}
1027		if (numericValue > parseFloat(el.max)) {
1028			el.value = el.max;
1029		}
1030	}
1031}
1032
1033
1034function isPhoneNumber(evt) {
1035	var charCode = (evt.which) ? evt.which : event.keyCode;
1036	//console.log(charCode);
1037	//45="-" ขีด
1038	if (charCode != 46 /*&& charCode != 45*/ && charCode > 31
1039		&& (charCode < 48 || charCode > 57))
1040		return false;
1041
1042	return true;
1043}
1044
1045function isNumber(evt) {
1046	//minus 45
1047	var charCode = (evt.which) ? evt.which : event.keyCode;
1048	//console.log(charCode);
1049	if (charCode != 46 /*&& charCode != 45*/ && charCode > 31
1050		&& (charCode < 48 || charCode > 57))
1051		return false;
1052
1053	return true;
1054}
1055
1056$(document).on("input", ".az09", function (e) {
1057	var regexp = /[^a-zA-Z0-9]/g;
1058	if ($(this).val().match(regexp)) {
1059		$(this).val($(this).val().replace(regexp, ''));
1060	}
1061});
1062
1063function SuccessAlert(text = 'Success.') {
1064	alertify.set('notifier', 'delay', 4);
1065	alertify.set('notifier', 'position', 'top-right');
1066	alertify.success(text);
1067}
1068
1069function WarningAlert(text = 'Warning.') {
1070	alertify.set('notifier', 'delay', 4);
1071	alertify.set('notifier', 'position', 'top-right');
1072	alertify.warning(text);
1073}
1074
1075function ConfirmAlert(message) {
1076	//console.log('ConfirmAlert', message)
1077	return new Promise(resolve => {
1078		alertify.confirm(message,
1079			function () { resolve(true) },
1080			function () { resolve(false) }
1081		).set({ title: "Confirm" }).set({ labels: { cancel: 'ยกเลิก', ok: 'ตกลง' } });
1082	});
1083}
1084
1085function AlertClose() {
1086	//console.log('AlertClose...')
1087	//alertify.alert().close();
1088	var dialog = alertify.confirm().set({});  // get current dialog instance
1089	if (dialog) {
1090		dialog.close();
1091	}
1092}
1093
1094function CloseModal(modalId) {
1095	$(modalId).modal('hide');
1096}
1097
1098
1099function setCookie(cname, cvalue, exdays, type = 'd') {
1100	var d = new Date();
1101	if (type == 's') {
1102		d.setTime(d.getTime() + (exdays * 1000));  // วินาที
1103	} else if (type == 'm') {
1104		d.setTime(d.getTime() + (exdays * 60 * 1000));  // นาที
1105	} else {
1106		d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));  // วัน
1107	}
1108	var expires = "expires=" + d.toUTCString();
1109	document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
1110}
1111
1112function getCookie(cname) {
1113	var name = cname + "=";
1114	var decodedCookie = decodeURIComponent(document.cookie);
1115	var ca = decodedCookie.split(';');
1116	for (var i = 0; i < ca.length; i++) {
1117		var c = ca[i];
1118		while (c.charAt(0) == ' ') {
1119			c = c.substring(1);
1120		}
1121		if (c.indexOf(name) == 0) {
1122			return c.substring(name.length, c.length);
1123		}
1124	}
1125	return "";
1126}
1127
1128function cookie_accept() {
1129	setCookie("cookie_accept", "accept", 365);
1130}
1131
1132function CutterNormal() {
1133	setCookie("CutterBackWhihe", "0", 365);
1134	setCookie("CutterBackYello", "0", 365);
1135	$("body").removeClass("color_cutter_bg").removeClass("color_cutter_by");
1136}
1137
1138function CutterBackWhihe() {
1139	setCookie("CutterBackYello", "0", 365);
1140	setCookie("CutterBackWhihe", "1", 365);
1141	$("body").removeClass("color_cutter_by").addClass("color_cutter_bg");
1142}
1143
1144function CutterBackYello() {
1145	setCookie("CutterBackWhihe", "0", 365);
1146	setCookie("CutterBackYello", "1", 365);
1147	$("body").removeClass("color_cutter_bg").addClass("color_cutter_by");
1148}
1149
1150window.focusInput = function (elementId) {
1151	var element = document.getElementById(elementId);
1152	if (element) {
1153		element.focus();
1154	} else {
1155		console.log("Element not found: " + elementId);
1156	}
1157};
1158
1159window.addClickOutsideListener = function (inputId, callback) {
1160	document.addEventListener('click', function (e) {
1161		var input = document.getElementById(inputId);
1162		// ค้นหา .search-dropdown ภายใน .modal-search
1163		var modalSearch = input ? input.closest('.modal-search') : null;
1164		var dropdown = modalSearch ? modalSearch.querySelector('.search-dropdown') : null;
1165
1166		if (input && dropdown && !input.contains(e.target) && !dropdown.contains(e.target)) {
1167			//console.log("Click outside detected, closing dropdown");
1168			callback.invokeMethodAsync('CloseDropdown');
1169		}
1170	});
1171};
1172
1173window.initializePanorama = (img_url) => {
1174	setTimeout(function () {
1175		const panoImage = document.querySelector('#pano-image');
1176		const panorama = new PANOLENS.ImagePanorama(img_url);
1177		//console.log(panoImage)
1178		//console.log(panorama)
1179		if (panoImage != null) {
1180			viewer = new PANOLENS.Viewer({
1181				container: panoImage,
1182				controlBar: true,
1183				controlButtons: ['fullscreen']
1184			});
1185			viewer.add(panorama);
1186			panoImage.addEventListener('wheel', zoomPanorama);
1187		}
1188
1189	}, 500)
1190}
1191
1192function zoomPanorama(event) {
1193	event.preventDefault();
1194
1195	if (event.deltaY < 0) {
1196		// เลื่อนขึ้น -> ซูมเข้า
1197		viewer.camera.fov -= 1;
1198	} else {
1199		// เลื่อนลง -> ซูมออก
1200		viewer.camera.fov += 1;
1201	}
1202	viewer.camera.updateProjectionMatrix();
1203}
1204
1205window.updateUrlWithoutNavigation = (url) => {
1206	window.history.pushState(null, '', url);
1207}
1208
1209//function downloadFileFromStream(fileName, base64String) {
1210//	const link = document.createElement('a');
1211//	link.download = fileName;
1212//	link.href = "data:application/zip;base64," + base64String;
1213//	document.body.appendChild(link);
1214//	link.click();
1215//	document.body.removeChild(link);
1216//}
1217
1218let currentDownloadLink = null;
1219
1220window.downloadFileFromStream = (fileName, base64String, dotNetHelper) => {
1221	if (currentDownloadLink) {
1222		document.body.removeChild(currentDownloadLink);
1223	}
1224
1225	const link = document.createElement('a');
1226	link.download = fileName;
1227	link.href = "data:application/zip;base64," + base64String;
1228	document.body.appendChild(link);
1229	currentDownloadLink = link;
1230	link.click();
1231
1232	dotNetHelper.invokeMethodAsync('OnDownloadComplete');
1233};
1234
1235window.cancelCurrentDownload = () => {
1236	if (currentDownloadLink) {
1237		document.body.removeChild(currentDownloadLink);
1238		currentDownloadLink = null;
1239	}
1240};
1241
1242function triggerCMSInputFile(inputfile) {
1243	//console.log('triggerInputFilePro...')
1244	const fileInput = document.getElementById(`${inputfile}`);
1245	if (fileInput) {
1246		fileInput.click(); // trigger the file input click
1247	} else {
1248		console.error("File input element not found.");
1249	}
1250}
1251
1252function getDomain() {
1253	var domain_curr = window.location.hostname;
1254	//console.log(domain_curr)
1255	return domain_curr;
1256}
1257
1258
1259
1260//window.initializeSortable = (containerId, dotnetHelper) => {
1261//	const container = document.getElementById(containerId);
1262//	Sortable.create(container, {
1263//		animation: 150,
1264//		draggable: ".image-item",
1265//		onEnd: function (evt) {
1266//			dotnetHelper.invokeMethodAsync('UpdateImageOrder', evt.oldIndex, evt.newIndex);
1267//		}
1268//	});
1269//};
1270
1271window.initializeSortable = (containerId, dotnetHelper) => {
1272	const container = document.getElementById(containerId);
1273	Sortable.create(container, {
1274		animation: 150,
1275		onEnd: function (evt) {
1276			const newOrder = Array.from(container.children).map(item => item.getAttribute('data-id'));
1277			//console.log(newOrder)
1278			dotnetHelper.invokeMethodAsync('UpdateImageOrder', newOrder);
1279		}
1280	});
1281};
1282
1283// Add to your JS file or script tag
1284window.getInputValue = (element) => element.value;
1285
1286window.focusElement = (element) => {
1287	element.focus();
1288}
1289
1290window.selectpicker_new = () => {
1291	console.log('selectpicker_new...')
1292	$('.selectpicker').selectpicker({
1293		liveSearch: true,
1294		size: 10
1295	});
1296}
1297
1298window.formStorage = {
1299	saveData: function (key, value) {
1300		sessionStorage.setItem(key, value);
1301	},
1302	getData: function (key) {
1303		return sessionStorage.getItem(key);
1304	},
1305	removeData: function (key) {
1306		sessionStorage.removeItem(key);
1307	}
1308};
1309
1310window.localStorageHelper = {
1311	setItem: function (key, value) {
1312		localStorage.setItem(key, value);
1313	},
1314	getItem: function (key) {
1315		return localStorage.getItem(key);
1316	},
1317	removeItem: function (key) {
1318		localStorage.removeItem(key);
1319	}
1320};
1321
1322
1323function refreshSelectPicker() {
1324	//console.log('refreshSelectPicker..')
1325	$('.selectpicker').selectpicker('refresh');
1326}
1327
1328function initializeSelects() {
1329	//console.log('initializeSelects...')
1330	$('.selectpicker').each(function () {
1331		$(this).selectpicker({
1332			liveSearch: true,
1333			size: 10
1334		});
1335	});
1336}
1337
1338// Refresh select ตามที่ระบุ
1339function refreshSelect(selectId) {
1340	//console.log('refreshSelect... ' + selectId);
1341	try {
1342		// Destroy selectpicker ก่อน
1343		$('#' + selectId).selectpicker('destroy');
1344
1345		// Initialize ใหม่
1346		$('#' + selectId).selectpicker({
1347			liveSearch: true,
1348			size: 10
1349		});
1350	} catch (error) {
1351		console.error('Error refreshing select:', error);
1352	}
1353}
1354
1355// Destroy และ reinitialize select เมื่อต้องการ
1356function reinitializeSelect(selectId) {
1357	//console.log('reinitializing... ' + selectId);
1358	try {
1359		var $select = $('#' + selectId);
1360		$select.selectpicker('destroy');
1361		// รอให้ DOM อัพเดท
1362		setTimeout(() => {
1363			$select.selectpicker({
1364				liveSearch: true,
1365				size: 10
1366			});
1367		}, 0);
1368	} catch (error) {
1369		console.error('Error reinitializing select:', error);
1370	}
1371}
1372
1373function destroySelects() {
1374	$('.selectpicker').selectpicker('destroy');
1375}
1376
1377
1378function resetSelect(id) {
1379	try {
1380		if (document.getElementById(id)) {
1381			document.getElementById(id).selectedIndex = 0;
1382		}
1383
1384	} catch (error) {
1385		console.error('Error resetSelect:', error);
1386	}
1387}
1388
1389function addClickOutsideHandler(dotNetObject) {
1390	document.addEventListener('click', function (e) {
1391		if (!e.target.closest('.relative')) {
1392			dotNetObject.invokeMethodAsync('CloseDropdown');
1393		}
1394	});
1395}
1396
1397function filterHtml() {
1398
1399	const path = window.location.pathname.toLowerCase();
1400	if (!path.startsWith('/backoffice')) {
1401		document.documentElement.style.filter = 'grayscale(0.7)';
1402		document.documentElement.style.setProperty('filter', 'grayscale(0.7)', 'important');
1403	} else {
1404		document.documentElement.style.filter = 'none';
1405	}
1406}

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.