PageSourceSearch

https://ipic.ca/_scripts/_hi5/hi5-form.js?v=322.43

js ipic.ca collected 2026-10-02 07:53:35 UTC 70,410 bytes, 2,467 lines download raw bytes

1var HI5_PING_TIME = 5; // minutes
2var HI5_LOCK_RELEASE = 60; // seconds
3
4var objFormInputError = null;
5
6$(document).ready(function() {
7	
8	initFormControls("");
9	
10});	
11
12function autoPing() {
13	
14	var urlAjax = urlAjaxBase + 'signin/ajax/?comaction=keep-alive';
15
16	$.ajax({
17		url:  urlAjax
18		, success: function() { console.log("Pinged server to keep session alive"); }
19		, error: function() { console.log('User session was not found'); }
20	});	
21	
22	setTimeout(function(){ autoPing(); }, HI5_PING_TIME * 60000);
23	
24}
25
26function releaseLock(strFormID) {
27	
28	$("#" + strFormID + " button[type='submit']").each(function() {
29		
30		var strButtonTextID = strFormID + '-submit-text' + ($(this).val() ? '-' + $(this).val() : '');
31
32		$(this).html($('#' + strButtonTextID).html());
33		$('#' + strButtonTextID).remove();
34		
35	});
36
37	$("#" + strFormID + " fieldset").removeClass('submitting');
38	$("#" + strFormID + " button[type='submit'] .ripple-container").empty();
39	
40}
41
42function initFormControls(strID) {
43	
44	var strBaseSelector = strID ? "#" + strID : ".Hi5Form";
45	
46	strSelector = strBaseSelector + ":not(.Hi5-init)";
47	
48	var arrForms = document.querySelectorAll(strSelector);
49	
50	for(var iForm = 0; iForm<arrForms.length; iForm++) {
51	
52		var objForm = arrForms[iForm];
53		var strFormID = $(objForm).attr('id');
54		
55		$(objForm).find('.g-recaptcha-response').attr('aria-hidden', true).attr('aria-label', 'Google Recaptcha').attr('aria-readonly', true);
56		$(objForm).find('label[aria-hidden="true"]').remove();
57		
58		// ================ SET AUTO-PING =========================
59		
60		if($("#" + strFormID).hasClass("keep-session-alive")) {
61			
62			setTimeout(function(){ autoPing(strFormID); },  HI5_PING_TIME * 60000);
63			
64		}
65		
66		// ================ SET SUBMIT-LOCK =========================
67
68		$("#" + strFormID + " input, #" + strFormID + " select, #" + strFormID + " textarea").bind('invalid', function(e){
69			
70			if($(this).closest('.modal-content').length) return; // this is inside a modal - do not scroll in this case
71
72			if (objFormInputError==this) {
73				
74				return true;
75				
76			} else if(objFormInputError!=null) {
77				
78				e.preventDefault();
79				return false;
80				
81			}
82
83			objFormInputError = this;
84
85			setTimeout(function (){
86				
87				objFormInputError = null;
88				
89			}, 1000);		
90		
91			var intDiff = ($(this).offset().top - $(window).scrollTop());
92
93			if(intDiff<100) {
94				
95				$('html, body').animate({scrollTop: $(this).offset().top - 200 }, 'slow');
96				e.preventDefault();
97				setTimeout(function (){
98					
99					objFormInputError.reportValidity();
100					
101				}, 600);
102				
103			} else {
104
105				e.preventDefault();
106				objFormInputError.reportValidity();
107
108			}
109
110		});		
111		
112		$("#" + strFormID).on('submit', function(e) { 
113			
114			var strFormID = this.id;
115			
116			if($("#" + strFormID + " fieldset").hasClass('invalid')) { // invalid, don't submit
117				
118				$("#" + strFormID + " fieldset").removeClass('invalid');
119				e.preventDefault();
120
121			} else if($("#" + strFormID + " fieldset").hasClass('submitting')) { // already submitted
122				
123				e.preventDefault();
124				
125			} else {
126				
127				$("#" + strFormID + " fieldset").addClass('submitting');
128				setTimeout(function(){ releaseLock(strFormID); }, HI5_LOCK_RELEASE * 1000);
129				
130			}
131			
132		});
133		
134		// ================ clear checked "file remove" checkboxes ================
135		
136		setTimeout(function(){
137			$('input[type="checkbox"][name^="hi5_file_remove"]').prop('checked', false);
138		}, 100);
139		
140		// ================= SET REQUIRED =====================
141		
142		if(typeof arrRequired !== 'undefined' && typeof arrRequired[strFormID] !== 'undefined' && Array.isArray(arrRequired[strFormID])) for(var i=0; i<arrRequired[strFormID].length; i++) {
143			
144			var objCtrl = document.querySelector("#" + strFormID + " #" + arrRequired[strFormID][i]);	
145			
146			if(objCtrl) {
147
148				$(objCtrl).prop('required', true);
149				$(objCtrl).attr('data-required', 'true');
150
151				if(objCtrl.type=="password") {
152					
153					var objCtrlConfirm = document.querySelector("#CONFIRM-" + arrRequired[strFormID][i]);
154					
155					if(objCtrlConfirm) {
156						
157						objCtrlConfirm.required = true;
158					
159					}
160					
161				}
162				
163				if(objCtrl.type=="radio") {
164		
165					var objCtrlLabel = document.querySelector("#" + strFormID + " #field-" + arrRequired[strFormID][i].substr(0, arrRequired[strFormID][i].lastIndexOf("-")));				
166					
167				} else {
168
169					var objCtrlLabel = document.querySelector("#" + strFormID + " #field-" + arrRequired[strFormID][i]);
170					
171				}
172				
173				if(objCtrlLabel) objCtrlLabel.className+= " required";
174				
175			} else {
176				
177				objCtrl = document.querySelector("#" + strFormID + " #" + arrRequired[strFormID][i] + "-hi5_date");	
178				
179				if(objCtrl) {
180						
181					objCtrl.required = true;
182					objCtrl.dataset.required = true;				
183					objCtrl = document.querySelector("#" + strFormID + " #" + arrRequired[strFormID][i] + "-hi5_time");	
184					objCtrl.required = true;
185					objCtrl.dataset.required = true;
186					
187				}
188				
189				var objCtrlLabel = document.querySelector("#" + strFormID + " #field-" + arrRequired[strFormID][i]);
190				if(objCtrlLabel) objCtrlLabel.className+= " required";
191				
192			}
193			
194			if($("#" + strFormID).hasClass("show-missing")) {
195			
196				let $formGroup = $(objCtrl).closest(".form-group");
197				var isValid = true;
198				
199				if ($formGroup.length) {
200	                
201	                if ($(objCtrl).val() === "") {
202	                	
203	                    isValid = false;
204	                    
205	                }
206
207	                if (!isValid) {
208	                	
209				        $formGroup.addClass("has-error");
210				        
211				        if($(objCtrl).attr('type')=='password' && objCtrl.required) $('#field-CONFIRM-' + objCtrl.id).addClass("has-error");
212				        
213				    } else {
214				    	
215				        $formGroup.removeClass("has-error");
216				        
217				    }
218				}
219				
220			}
221			
222		}	
223		
224		if(typeof arrRequiredAdminExempt !== 'undefined' && typeof arrRequiredAdminExempt[strFormID] !== 'undefined' && Array.isArray(arrRequiredAdminExempt[strFormID])) for(var i=0; i<arrRequiredAdminExempt[strFormID].length; i++) {
225			
226			var objCtrl = document.querySelector("#" + strFormID + " #" + arrRequiredAdminExempt[strFormID][i]);	
227			
228			if(objCtrl) {
229				
230				if(objCtrl.type=="radio") {
231					var objCtrlLabel = document.querySelector("#" + strFormID + " #field-" + arrRequiredAdminExempt[strFormID][i].substr(0, arrRequiredAdminExempt[strFormID][i].lastIndexOf("-")));				
232				} else {
233					var objCtrlLabel = document.querySelector("#" + strFormID + " #field-" + arrRequiredAdminExempt[strFormID][i]);
234				}
235				
236				if(objCtrlLabel) objCtrlLabel.className+= " required-exempt";
237				
238			} else {
239				
240				var objCtrlLabel = document.querySelector("#" + strFormID + " #field-" + arrRequiredAdminExempt[strFormID][i]);
241				if(objCtrlLabel) objCtrlLabel.className+= " required-exempt";
242				
243			}
244			
245		}		
246	
247	}
248	
249	// ================= SET PASSWORD CONFIRM =====================
250	
251	$(strSelector + ' input[type="password"].password-confirm:not(.no-hide)').on("blur", function(e) {
252		
253		var strPwd = $('#' + $(this).data('match')).val();
254		var strPwdConfirm = $(this).val();
255		
256		var strMsg = "";
257		var strClass = "";
258		
259		if(strPwd.length && strPwd==strPwdConfirm) {
260			
261			strMsg = strLang_Matches;
262			strClass = "success";
263			this.setCustomValidity('');
264			
265		} else if(!strPwdConfirm.length) {
266			
267			strMsg = strLang_PleaseConfirm;
268			strClass = "caution";	
269			this.setCustomValidity(strMsg);		
270			
271		} else {
272			
273			strMsg = strLang_DoesNotMatch;
274			strClass = "danger";
275			this.setCustomValidity(strMsg);
276			
277		}
278				
279		$('#' + this.id + '-result').removeClass('success caution danger').addClass(strClass).html(strMsg);
280
281	});
282	
283	$(strSelector + ' .form-group:not(.required) input[type="password"]:not(.password-confirm)').on("change keyup blur", function(e) {
284		
285		var strFieldId = $(this).attr('id');
286		
287		$('#field-CONFIRM-' + strFieldId + ".hidden").css('display', 'none').removeClass('hidden');
288		
289		if($(this).val() && isValidPassword($(this).val()) && $('#field-CONFIRM-' + strFieldId).css('display')=='none') {
290			
291			$('#field-CONFIRM-' + strFieldId).slideDown().addClass('required');
292			$('#CONFIRM-' + strFieldId).prop('required', true);
293			$('#' + strFieldId).prop('required', true);
294
295		} else if(!$('#field-CONFIRM-' + strFieldId).hasClass('no-hide') && (!$(this).val() || !isValidPassword($(this).val())) && $('#field-CONFIRM-' + strFieldId).css('display')!='none') {
296			
297			$('#CONFIRM-' + strFieldId).val("").prop('required', false);
298			$('#field-CONFIRM-' + strFieldId).slideUp().removeClass('required');
299			
300		}
301		
302		if(!$(this).val()) $('#' + strFieldId).prop('required', false);
303		
304	});	
305	
306	$(strSelector + ' input[type="password"]').on("change keyup blur", function(e) {
307		
308		if(this.id.substr(0, 8)=="CONFIRM-") {
309			
310			var ctrlPwdId = this.id.substr(8);
311			
312			var strPwd = $('#' + ctrlPwdId).val();
313			var ctrlPwd = $('#' + ctrlPwdId)[0];
314			var ctrlConfirm = $(this)[0];
315			var strPwdConfirm = $(this).val();
316
317		} else {
318			
319			var strPwd = $(this).val();
320			var ctrlPwd = $('#' + this.id)[0];
321			var ctrlConfirm = document.getElementById("CONFIRM-" + this.id);
322			if(!ctrlConfirm) return;
323			var strPwdConfirm = $('#' + ctrlConfirm.id).val();
324			
325		}
326		
327		var strClass = "";
328		
329		if(strPwd.length && !isValidPassword(strPwd)) {
330			
331			strMsg = "";
332			strClass = "caution";	
333			ctrlPwd.setCustomValidity(strMsg);	
334			ctrlConfirm.removeAttribute("required");
335			ctrlPwd.setAttribute("required", "required");
336			$('#field-' + ctrlPwd.id + ' .help-block').html(strLang_InvalidPassword);
337			
338		}
338 else if(strPwd.length && strPwd==strPwdConfirm) {
339			
340			strMsg = strLang_Matches;
341			strClass = "success";
342			ctrlConfirm.setCustomValidity('');
343			ctrlPwd.setCustomValidity('');
344			ctrlConfirm.setAttribute("required", "required");
345			ctrlPwd.setAttribute("required", "required");
346
347		} else if (!strPwd.length && !ctrlPwd.required) {
348
349			strMsg = "";
350			strClass = "";
351			ctrlConfirm.setCustomValidity('');
352			ctrlPwd.setCustomValidity('');
353			ctrlConfirm.removeAttribute("required");
354			ctrlPwd.removeAttribute("required");
355			$('#field-' + ctrlPwd.id + ' .help-block').html(strLang_KeepPassword);
356			
357		} else if(strPwd.length && strPwd.length == strPwdConfirm.length) {
358			
359			strMsg = strLang_DoesNotMatch;
360			strClass = "danger";
361			ctrlConfirm.setCustomValidity(strMsg);
362			ctrlPwd.setCustomValidity('');
363			ctrlConfirm.setAttribute("required", "required");
364			ctrlPwd.setAttribute("required", "required");
365			
366		} else if(strPwd.length) {
367			
368			strMsg = strLang_PleaseConfirm;
369			strClass = "caution";	
370			ctrlConfirm.setCustomValidity(strMsg);	
371			ctrlConfirm.setAttribute("required", "required");
372			ctrlPwd.setAttribute("required", "required");
373			
374		}
375		
376		$('#' + ctrlConfirm.id + '-result').removeClass('success caution danger').addClass(strClass).html(strMsg);
377		
378	});
379	
380	// ================= ENTER KEY BEHAVIOUR =====================
381	
382	/*$(document).keydown(function(e) {
383		
384		return;
385	
386		var self = $(':focus'), form = self.parents('form:eq(0)'), focusable; // Set self as the current item in focus // Set the form by the current item in focus		
387		
388		focusable = form.find('input,a,select,button,textarea,div[contenteditable=true]').filter(':visible'); // Array of Indexable/Tab-able items
389		
390		function enterKey() {
391			
392			if (e.which === 13 && !self.is('button,input[type="submit"],input[type="button"],input[type="file"],input[type="radio"],input[type="checkbox"],textarea,div[contenteditable=true]')) { // [Enter] key
393			
394				if ($.inArray(self, focusable) && (!self.is('a,button'))) { // If not a regular hyperlink/button/textarea
395				
396					e.preventDefault(); // Then prevent the default [Enter] key behaviour from submitting the form
397					
398				} // Otherwise follow the link/button as by design, or put new line in textarea		
399				
400				focusable.eq(focusable.index(self) + (e.shiftKey ? -1 : 1)).focus(); // Focus on the next item (either previous or next depending on shift)
401				
402				return false;
403				
404			}
405			
406		}
407		
408		if (e.shiftKey) { enterKey() } else { enterKey() } // We need to capture the [Shift] key and check the [Enter] key either way.
409		
410	});	*/	
411	
412	// ================= DATE =====================
413
414	if (!DatePickerSupported()) {
415			  
416		$(strSelector + ' input[type="date"]').datetimepicker({
417			format: 'YYYY-MM-DD'
418			, useCurrent: false
419		});	  
420		
421	}
422
423	// ================= FILE / IMAGE =====================
424	
425	if(typeof intMaxFileSize == 'undefined') var intMaxFileSize = 0;
426	
427	$(strSelector + ' input[type="file"]').each(function() {
428		
429		var blnImageOnly = $(this).attr('accept')=='image/*';
430		var blnMediaOnly = $(this).attr('accept')=='video/*,image/*';
431		
432		var intCustomMaxFileSize = $(this).attr('data-max-kb');
433		
434		var arrAllowedFileTypes = null;
435		var arrAllowedFileExt = null;
436		
437		if(blnMediaOnly) {
438
439			arrAllowedFileTypes = ["image", "video"];
440			arrAllowedFileExt = ['gif', 'ico', 'jpeg', 'jpg', 'png', 'svg', 'webp', 'mp4', 'ogg', 'webm'];
441			
442		} else if (blnImageOnly) {
443			
444			arrAllowedFileTypes = ["image"];
445			arrAllowedFileExt = ['gif', 'ico', 'jpeg', 'jpg', 'png', 'svg', 'webp'];
446			
447		}
448		
449		if(!intCustomMaxFileSize) intCustomMaxFileSize = intMaxFileSize;
450	
451		$(this).fileinput({
452			'showUpload':false
453			, 'previewFileType': blnImageOnly ? 'image' : 'any'
454			, 'cancelClass':'btn btn-link'
455			, 'removeClass':'btn btn-link'
456			, 'dropZoneTitle': strLang_DropZone
457			, 'browseLabel': strLang_Browse
458			, 'maxFileSize': intCustomMaxFileSize
459			//, 'allowedFileTypes': arrAllowedFileTypes
460			, 'allowedFileExtensions': arrAllowedFileExt
461		});
462		
463	});
464	
465	$(strSelector + " .hi5-image-preview input[type='checkbox']").on('change', function(event) {
466							
467		strCtrlId = $(this).attr("data-parent");														 
468		strDivId = "field-" + strCtrlId;
469		strFormId = $(this).closest("form").attr('id');
470		
471		$("#" + strFormId + " #" + strDivId + " .hi5-image-replace.hidden, #" + strFormId + " #" + strDivId + ".hi5-image-replace.hidden").css('display', 'none').removeClass('hidden');
472				
473		if($(this).is(':checked')) {
474
475			$("#" + strFormId + " #" + strDivId + " .hi5-image-replace, #" + strFormId + " #" + strDivId + ".hi5-image-replace").slideDown(100);
476			if($("#" + strFormId + " #" + strDivId).hasClass("required")) $("#" + strFormId + " #" + strDivId + " .hi5-image-replace input[type='file'], #" + strFormId + " #" + strDivId + ".hi5-image-replace input[type='file'], " + strSelector + " #" + strDivId + ".hi5-image-replace textarea").prop('required',true);
477			if($(this).attr("data-type")=="signature") $('#'+strCtrlId).resize()
478
479		} else {
480			
481			if($(this).attr("data-type")=="signature") ResetSignature($(this).attr("data-parent"));
482			$("#" + strFormId + " #" + strDivId + " .hi5-image-replace, #" + strFormId + " #" + strDivId + ".hi5-image-replace").slideUp(100);
483			$("#" + strFormId + " #" + strDivId + " .hi5-image-replace input[type='file'], #" + strFormId + " #" + strDivId + ".hi5-image-replace input[type='file'], #" + strFormId + " #" + strDivId + ".hi5-image-replace textarea").prop('required',false);
484			
485		}
486
487	});
488	
489	$('.grid_input .file-caption-name').attr('placeholder', strLang_SelectFile);
490
491	$(strSelector + " .hi5-image-replace input[type='file'], .hi5-image-replace textarea").prop('required',false);
492
493	// ============================== SIGNATURE ===============================
494
495	$(strSelector + " .signature-ctrl").each(function() {
496	
497		var $ctrl = $(this);
498		var $target = $('#' + $ctrl.attr('data-target'));
499	
500		$ctrl.jSignature();
501	
502		$ctrl.bind('change', function() {
503	
504			var arrNative = $ctrl.jSignature('getData', 'native');
505	
506			if(arrNative && arrNative.length > 0) {
507				$target.val($ctrl.jSignature('getData'));
508			} else if($target.val() == '0') {
509				$target.val('');
510			}
511	
512		});
513	
514	});
515	
516	// ============================== CONTENT =================================
517
518	var urlCleanStyleBase = (typeof urlStyleBase === 'undefined') ? "" : urlStyleBase;
519	var urlCleanDocBase = (typeof urlDocBase === 'undefined') ? "" : urlDocBase;
520	var strCleanAppVersion = (typeof strAppVersion === 'undefined') ? "" : strAppVersion;
521	var urlCleanContentCSS =  '/' + urlCleanStyleBase + ((typeof urlContentCSS === 'undefined') ? "tinymce" : urlContentCSS) + ".css?v=" + strCleanAppVersion;
522	
523	var strLang = $('html').attr('lang') == 'fr' ? 'fr_FR' : 'en_CA';
524	
525	// full version
526	
527	$(strBaseSelector + ' textarea.tinymce:not([aria-hidden="true"]):not([style="visibility: hidden;"])').each(function(){
528	
529		var objElement = this;
530		
531		tinymce.editors.forEach(function(editor) {
532			
533			if (objElement.id==editor.targetElm.id && objElement.form.id == editor.targetElm.form.id) {
534
535				if($(editor.targetElm).hasClass('tinymce-basic')) {
536					$(objElement).addClass('tinymce-basic').removeClass('tinymce');
537				}
538				editor.remove();
539			
540			}
541		
542		});	
543			
544	});
545	
546	$(strBaseSelector + ' .form-group.basic-editor').each(function() {
547		
548		$(this).find('.tinymce').addClass('tinymce-basic').removeClass('tinymce');
549		
550	});
551	
552	tinymce.init({
553		branding: false,
554		selector: strBaseSelector + ' textarea.tinymce:not([aria-hidden="true"])',
555		language: strLang,
556		plugins: "advlist anchor autolink autoresize autosave contextmenu cms code emoticons fullscreen hr image link lists media nonbreaking paste searchreplace table textcolor visualchars", // cms",
557		menubar: false,	
558		toolbar: [ "undo redo | bullist numlist | nonbreaking hr table cmsimage media emoticons anchor quote | cmslink cmsbutton | searchreplace | code visualchars fullscreen",
559				"removeformat bold italic styleselect fontsizeselect forecolor backcolor | alignleft aligncenter alignright al
559ignjustify | outdent indent" ],
560		/*content_css : [urlCleanContentCSS, '/_styles/_hi5/hi5-tinymce.css?v=' + strCleanAppVersion],*/
561		content_css: '/_styles/_hi5/hi5-tinymce.css?v=' + strCleanAppVersion,
562		width: '100%',
563		height: 450,
564		autoresize_min_height: 350,
565		autoresize_max_height: 450,
566		nonbreaking_force_tab: true,
567		save_enablewhendirty: false,
568		document_base_url : urlCleanDocBase,
569		entity_encoding : "raw",
570		browser_spellcheck: true,
571		extended_valid_elements : "script[type|src|id],i[id|class|style],em,link[href|rel|type],style[type]",
572		relative_urls : false,
573		convert_urls : false,
574		/*paste_as_text: true,*/
575		paste_data_images: true,
576		paste_word_valid_elements: "p,b,strong,i,em,h1,h2,h3,h4,h5,ul,ol,li,img,table,thead,tbody,tfoot,th,td",
577		visualchars_default_state: true,
578		
579		formats: {
580        	quote: {title: 'Quote', inline: 'q', classes: 'citation'}
581    	},
582		style_formats: [
583			{title: 'Headers', items: [
584				{title: 'h1', block: 'h1'},
585				{title: 'h2', block: 'h2'},
586				{title: 'h3', block: 'h3'},
587				{title: 'h4', block: 'h4'},
588			]},
589			{title: 'Inline', items: [
590				{title: 'Bold', inline: 'b', icon: 'bold'},
591				{title: 'Italic', inline: 'i', icon: 'italic'},
592				{title: 'Quote', inline: 'q', icon: 'blockquote', classes: 'citation'},
593				{title: 'Underline', inline: 'span', styles : {textDecoration : 'underline'}, icon: 'underline'},
594				{title: 'Strikethrough', inline: 'span', styles : {textDecoration : 'line-through'}, icon: 'strikethrough'},
595				{title: 'Superscript', inline: 'sup', icon: 'superscript'},
596				{title: 'Subscript', inline: 'sub', icon: 'subscript'},
597				{title: 'Code', inline: 'code', icon: 'code'},
598			]},
599			{title: 'Blocks', items: [
600				{title: 'Paragraph', block: 'p'},
601				{title: 'Address', block: 'address'},
602				{title: 'Blockquote', block: 'blockquote'},
603				{title: 'Div', block: 'div'},
604				{title: 'Pre', block: 'pre'}
605			]},
606			{title: 'Alignment', items: [
607				{title: 'Left', block: 'div', styles : {textAlign : 'left'}, icon: 'alignleft'},
608				{title: 'Center', block: 'div', styles : {textAlign : 'center'}, icon: 'aligncenter'},
609				{title: 'Right', block: 'div', styles : {textAlign : 'right'}, icon: 'alignright'},
610				{title: 'Justify', block: 'div', styles : {textAlign : 'justify'}, icon: 'alignjustify'}
611			]}
612		],
613		table_class_list: [
614		    {title: 'None', value: ''},
615		    {title: 'Table', value: 'table'},
616		    {title: 'Striped', value: 'table table-striped table-hover'},
617		    {title: 'Bordered', value: 'table table-bordered table-hover'}
618		],
619		contextmenu: "cut copy paste pastetext | cms | formats | alignment tableprops deletetable | cell row column",
620	    setup: function(editor) {
621	    	
622	        editor.addButton('quote', {
623	            icon: 'blockquote',
624	            onClick: function() { editor.formatter.toggle('quote'); }
625	        });
626	        editor.on('change', function () {
627				if(typeof window.tinyMCEupdate === "function") window.tinyMCEupdate(this.id);
628	        });
629   	        editor.on('blur', function () {
630				if(typeof window.tinyMCEblur === "function") window.tinyMCEblur(this.id);
631	        });	 
632	        
633	    }
634	});
635
636	// basic version
637	
638	tinymce.init({
639		branding: false,
640		selector: strBaseSelector + ' textarea.tinymce-basic:not([aria-hidden="true"])',
641		language: strLang,
642		plugins: "advlist autolink autoresize autosave contextmenu cms image link lists media paste visualchars",
643		menubar: false,	
644		toolbar: [ "bold italic | alignleft aligncenter alignright alignjustify | bullist numlist blockquote | cmsimage media cmslink" ],
645		content_css: '/_styles/_hi5/hi5-tinymce.css?v=' + strCleanAppVersion,
646		width: '100%',
647		height: 300,
648		autoresize_min_height: 200,
649		autoresize_max_height: 300,
650		nonbreaking_force_tab: true,
651		save_enablewhendirty: false,
652		document_base_url : urlCleanDocBase,
653		entity_encoding : "raw",
654		browser_spellcheck: true,
655		extended_valid_elements : "i[id|class|style],em",
656		relative_urls : false,
657		convert_urls : false,
658		paste_data_images: true,
659		paste_word_valid_elements: "p,b,strong,i,em,h1,h2,h3,h4,h5,ul,ol,li,img,table,thead,tbody,tfoot,th,td",
660		visualchars_default_state: true,
661		contextmenu: "cut copy paste pastetext | alignment | cms",
662	    setup: function(editor) {
663	        editor.on('change', function () {
664				if(typeof window.tinyMCEupdate === "function") window.tinyMCEupdate(this.id);
665	        });
666   	        editor.on('blur', function () {
667				if(typeof window.tinyMCEblur === "function") window.tinyMCEblur(this.id);
668	        });	 
669	    }		
670	});
671	
672	// scientific version
673	
674	tinymce.init({
675		branding: false
676		, selector: "textarea.tinymce-scientific"
677		, language: strLang
678		, height: 400
679		, menubar: false
680		, plugins: "advlist autolink autoresize autosave contextmenu cms image link lists media paste visualchars wordcount tiny_mce_wiris"
681		, toolbar: "bold italic | alignleft aligncenter alignright alignjustify | bullist numlist blockquote | cmsimage media link | tiny_mce_wiris_formulaEditor tiny_mce_wiris_formulaEditorChemistry"
682		, min_word: 1
683		, max_word: null
684        , setup: function (ed) {
685        	
686        	ed.on('init', function(e) {
687        		var intMaxWords = parseInt($(this.targetElm).attr('data-maxwords'));
688        		if(intMaxWords) ed.settings.max_word = intMaxWords;
689        		setTimeout(function(){ UpdateWordCounter(ed); }, 500);
690
691        	});
692        	
693            ed.on('NodeChange keyup', function (e) {
694            	setTimeout(function(){ UpdateWordCounter(ed); }, 500);
695            });
696
697        }
698		, statusbar: true
699		/*, content_css : [urlCleanContentCSS, '/_styles/_hi5/hi5-tinymce.css?v=' + strCleanAppVersion]*/
700		, content_css: '/_styles/_hi5/hi5-tinymce.css?v=' + strCleanAppVersion
701		, width: '100%'
702		, height: 450
703		, autoresize_min_height: 350
704		, autoresize_max_height: 450
705		, nonbreaking_force_tab: true
706		, save_enablewhendirt
706y: false
707		, document_base_url : urlCleanDocBase
708		, entity_encoding : "raw"
709		, browser_spellcheck: true
710		, extended_valid_elements : "i[id|class|style],em"
711		, relative_urls : false
712		, convert_urls : false
713		, paste_data_images: true
714		, paste_word_valid_elements: "p,b,strong,i,em,h1,h2,h3,h4,h5,ul,ol,li,img,table,thead,tbody,tfoot,th,td"
715		, visualchars_default_state: true
716		, contextmenu: "cut copy paste pastetext | alignment | cms"		
717	});
718
719	// ================= GROUP EXPAND =================
720	
721	$(strSelector + " .form-group-expand").off("click");
722	
723	$(strSelector + " .form-group-expand").on("click", function(e) {
724		
725		var target = e.target || e.srcElement;
726
727		if(target.nodeName=="SPAN") {
728			
729			var selector = "#" + target.parentNode.parentNode.parentNode.id;
730			
731		} else {
732			
733			var selector = "#" + target.parentNode.parentNode.id;
734			
735		}
736		
737		if($(selector).hasClass("expanded")) {
738			
739			$(selector).removeClass("expanded");
740			
741			$(selector + " span").addClass("glyphicon-fullscreen");
742			
743			$(selector + " span").removeClass("glyphicon-remove-circle");
744			
745		} else {	
746
747			$(selector).addClass("expanded");
748			
749			$(selector + " span").addClass("glyphicon-remove-circle");
750			
751			$(selector + " span").removeClass("glyphicon-fullscreen");
752			
753		}
754		
755		
756	});
757	
758	// ======= YES / NO SWITCH
759	
760	$(strSelector + " .switch:not(.switch-init)").each(function() {
761		
762		$(this).addClass('switch-init');
763		
764		var objCheck = $(this).find('input')[0];
765		
766		if($(objCheck).prop('readonly')) {
767			
768			$(objCheck).after('<input type="hidden" name="' + objCheck.name + '" value="' + objCheck.value + '" />')
769			
770		} else {
771		
772			$(objCheck).off('click').click(function() {
773	
774				var blnChecked = $(this).val()=="1";
775				
776				$(this).val(blnChecked ? "0" : "1");
777				this.checked = true;
778				
779			});
780	
781		}		
782		
783	});
784	
785	// ============ TEXTAREAS =========================
786			
787	$(strSelector + ' textarea:not(.tinymce)').each(function () {
788	
789	    const $t = $(this);
790	
791	    //
792	    // STEP 1: Reset any inline height (important)
793	    //
794	    $t.css('height', 'auto');
795	
796	    //
797	    // STEP 2: Compute height components
798	    //
799	    const lineHeight    = parseFloat($t.css('line-height'));
800	    const paddingTop    = parseFloat($t.css('padding-top'));
801	    const paddingBottom = parseFloat($t.css('padding-bottom'));
802	
803	    const extras = paddingTop + paddingBottom;
804
805	    //
806	    // STEP 3: Min/max heights based on rows
807	    //
808	    const minHeight = (lineHeight * 2);   // 2 lines
809	    const maxHeight = (lineHeight * 10) + extras;   // 10 lines
810	
811	    //
812	    // Apply min/max rules
813	    //
814	    $t.css({
815	        minHeight: minHeight + 'px',
816	        maxHeight: maxHeight + 'px',
817		    'scroll-padding-top':    paddingTop    + 'px',
818		    'scroll-padding-bottom': paddingBottom + 'px'
819	    });
820	
821	    //
822	    // STEP 4: Initial sizing (clamp + overshoot correction)
823	    //
824	    const initialHeight = Math.min(this.scrollHeight - extras, maxHeight /*-extras*/);
825	    $t.height(initialHeight);
826	
827	    // Show scrollbar on load if needed
828	    $t.css('overflow-y', this.scrollHeight - extras > maxHeight ? 'auto' : 'hidden');
829
830	    //
831	    // Store for input handler
832	    //
833	    $t.data('minHeight', minHeight);
834	    $t.data('maxHeight', maxHeight);
835	    //$t.data('lineHeight', lineHeight);
836	
837	    //
838	    // STEP 5: Input handler (expand + shrink + clamp + correct overshoot)
839	    //
840	    $t.on('input focus blur', function (e) {
841	    	
842	        const $self = $(this);
843	        const t = this;
844	        //const lineHeight = $self.data('lineHeight');
845
846	        const minH = $self.data('minHeight');
847	        const maxH = $self.data('maxHeight');
848	        
849	        // Allow shrinking
850	        $self.height('auto');
851	        
852	        var calcH = t.scrollHeight - extras;
853
854			/*if($self.is(':focus')) {
855				calcH+= lineHeight;
856			}*/
857	
858	        // Clamp to min/max
859	        const newHeight = Math.max(minH, Math.min(calcH, maxH));
860	
861	        // Set the height
862	        $self.height(newHeight);
863	
864	        // Scroll when over max
865	        $self.css('overflow-y', t.scrollHeight - extras > maxH ? 'auto' : 'hidden');
866	        
867	    });
868	    
869	});
870
871	// ================= MULTIROW =====================
872	
873	/*$(strSelector + " button.Hi5GridDeleteRow").off('click').on('click', function() {
874
875		deletGridRow($(this).attr('data-row'));	
876	
877	}).each(function( key, value ) {
878		
879		$(value).attr('data-row', $(value).parent().parent().attr('id') );
880	  
881	});*/
882	
883	/*$(strBaseSelector + " button.Hi5GridDeleteRow:not([data-original-title])").popConfirm({
884		
885		placement: 'bottom',
886		yesBtn: strLang_Yes,
887        noBtn: strLang_No		
888		
889	});*/
890
891	$(strSelector + " button.Hi5GridDeleteRow")
892	    .off('click') // Remove old handlers
893	    .on('click', function() {
894	        deletGridRow($(this).attr('data-row'));
895	    })
896	    .each(function(key, value) {
897	        $(value).attr('data-row', $(value).parent().parent().attr('id'));
898	    })
899	    .popConfirm({
900	        placement: 'bottom',
901	        yesBtn: strLang_Yes,
902	        noBtn: strLang_No
903	    });	
904	
905	// ======= AUTO URL PREFIX =======
906	
907	$(strSelector + ' input[type="url"]').blur(function(e) {
908	
909		fixHttpPrefix(this);
910		
911	});	
912
913	// ========= ENABLE FORM  =======
914	
915	$(strSelector + ' fieldset').prop("disabled", false);
916
917	// ======== TREE-SELECT ========================
918	
919	$(strBaseSelector + ' .hierarchy-select').each(function() {
920
921		var data = top.treeData[this.dataset.target];
922		var selected = $('#' + $(this).attr('data-target')).val();
923		$(this).comboTree({
924			source: data
925			, isMultiple: false
926			, selected: [selected]
927		});	
928		
929	});
930	
931	// ========= DROPDOWN / MULTISELECT / SEARCH-SELECT / SEARCH-MULTISELECT  =======
932	
933	$(strBaseSelector + ' select[data-selected]:not(.selectized)').each(function() {
934		
935		var str = $(this).attr('data-selected');
936		var arr = str.split(" ");
937		
938		for(var i=0; i<arr.length;i++) {
939			
940			$(this).find('option[value="' + parseInt(arr[i]) + '"]').prop('selected', true);
941			
942		}
943		
944	});
945
946	$(strBaseSelector + ' select.static:not(.selectized)').selectize({
947		placeholder: strLang_SelectPlaceHolder
948		, create: false
949		, onBlur: function(value) {					
950			if(document.createEventObject) {
951				this.$input[0].fireEvent("onblur");
952			} else {
953				var evt = document.createEvent("HTMLEvents");
954				evt.initEvent("blur", false, true);
955				this.$input[0].dispatchEvent(evt);
956			}						
957		}		
958		/*, onChange: function(value) {					
959			if(document.createEventObject) {
960				this.$input[0].fireEvent("onchange");
961			} else {
962				var evt = document.createEvent("HTMLEvents");
963				evt.initEvent("change", false, true);
964				this.$input[0].dispatchEvent(evt);
965			}						
966		}*/
967	    , onInitialize: function () {
968	    	
969	    	var strPlaceholder = $(this.$input[0]).attr('placeholder');
970	    	
971	    	if(strPlaceholder) {
972	    		this.settings.placeholder = strPlaceholder;
973	    		this.updatePlaceholder();
974	    	}
975
976	    	this.hiddenOptions = [];
977        	var s = this;
978        	this.revertSettings.$children.each(function () {
979	            $.extend(s.options[this.value], $(this).data());
980        	});
981    	}
982	});	
983
984	$(strBaseSelector + ' select.dynamic:not(.selectized)').selectize({
985		placeholder: strLang_SearchSelectPlaceHolder,
986		/*onChange: function(value) {					
987			if(document.createEventObject) {
988				this.$input[0].fireEvent("onchange");
989			} else {
990				var evt = document.createEvent("HTMLEvents");
991				evt.initEvent("change", false, true);
992				this.$input[0].dispatchEvent(evt);
993			}						
994		},*/
995		valueField: 'id',
996		labelField: 'caption',
997		searchField: 'caption',
998		create: false,
999		closeAfterSelect: true,
1000		load: function(query, callback) {
1001			
1002			var pkColumn = this.$input[0].dataset.column;
1003			var correlationArgs = (this.correlationValue ? "&correlateVal=" + this.correlationValue : "");
1004			
1005			var urlAjax = urlAjaxBase + 'ajax/search-select/?pkTable='+this.$input[0].dataset.table+'&pkColumn='+ pkColumn + correlationArgs;
1006			var baseHref = document.getElementsByTagName('base')[0].href;
1007			
1008			query = query.trim();
1009			if (!query.length) return callback();
1010			
1011			console.log("AJAX request: " + baseHref + urlAjax + "&caption=" + query);
1012			
1013			$.ajax({
1014				url:  urlAjax,
1015				type: 'GET',
1016				dataType: 'json',
1017				data: {
1018					caption: query,
1019				},
1020				error: function() {
1021					callback();
1022				},
1023				success: function(res) {
1024					callback(res);
1025				}
1026			});
1027		}					
1028		
1029	});
1030	
1031	$(strSelector + ' select.selectized').each(function() {
1032
1033		this.selectize.correlationValue = 0;
1034
1035	});	
1036	
1037	$(strSelector + ' .selectize-control input').keydown(function(e) {
1038		
1039		if (e.which === 13) {
1040		
1041			e.preventDefault();
1042			return false;	
1043			
1044		}
1045		
1046	});
1047	
1048	setTimeout(function(){ 
1049
1050		$('.selectize-control input').each(function() {
1051
1052			$(this).attr('aria-labelledby', $(this).closest('.form-group').find('label.control-label').attr('id'));
1053			
1054		});
1055	
1056	}, 500);
1057	
1058	// =============== COLOR PICKER ============================
1059	
1060	$(strSelector + ' .form-color-picker').on('change', function() {
1061		$(this).next().val(this.value);
1062	});
1063	$(strSelector + ' .form-color-value').on('update keyup', function() {
1064		if(this.value.length==7) $(this).prev().val(this.value);
1065		else $(this).prev().val(null);
1066	});
1067	
1068	initColorPicker(); // this is for the new color picker
1069	
1070	// ======== DISABLE MOUSE WHEEL NUMBER SPINNING ==================
1071	
1072	$('input[type=number]').on('mousewheel', function(e) {
1073		$(e.target).blur();
1074	});
1075
1076	// ================= HTML 5 VALIDATION =====================
1077	
1078	$(strSelector + " input[required]:checkbox").click(function() {
1079		
1080		var strElemName = $(this).attr('data-parent');
1081		
1082		if(!strElemName || $('input[data-parent="' + strElemName + '"]:checked').length) {
1083			$('input[data-parent="' + strElemName + '"]').prop('required', false);
1084		} else {
1085			$('input[data-parent="' + strElemName + '"]').prop('required', true);
1086		}
1087
1088	});	
1089	
1090	$(strSelector + ' button[type="submit"]').on('click', function() { // Reveal native selects for HTML 5 validaton
1091											
1092		tinymce.triggerSave();
1093
1094		revealNativeControls(this.form);
1095		
1096		// for validating yes-no 
1097
1098		$(strBaseSelector + ' .switch input:required[value="0"]').prop("checked", false);
1099		
1100		// for validating checklists
1101		
1102		$(strBaseSelector + ' .checklist input:required:checked').each(function(){
1103
1104			var strElemName = $(this).attr('data-parent');
1105			if(strElemName) $('input[data-parent="' + strElemName + '"]').prop('required', false);
1106			
1107		});
1108
1109		var fd = new FormData(this.form);
1110		var size = 0;
1111		for(var pair of fd.entries()) {
1112		if (pair[1] instanceof Blob) 
1113		  size += pair[1].size;
1114		else
1115		  size += pair[1].length;
1116		}
1117
1118		if(typeof intMaxFormData !== 'undefined' && size > intMaxFormData) {
1119			alert(strLang_ErrorTooMuchData + ' ' + Math.round(intMaxFormData/1024/1024) + 'MB');
1120			return false;
1121		}
1122		
1123		
1124	});	
1125
1126	// conditional triggers and consequences
1127	
1128	$(strSelector + " .hi5-form-trigger input, " + strSelector + " .hi5-form-trigger select").each(function() {
1129		
1130		ConditionalTrigger(this.form.id);	
1131		
1132	});	
1133	
1134	$(strSelector + " .hi5-form-trigger input, " + strSelector + " .hi5-form-trigger select").on('change', function(e) {
1135		
1136		ConditionalTrigger(this.form.id);	
1137		
1138	});
1139	
1140	//ConditionalTrigger(strFormID);
1141	
1142	// correlated columns
1143
1144
1145/*	
1146	$(strSelector + ' [data-correlation-parent] select').change(function() {
1147		
1148		var strParent = $(this).closest('[data-correlation-parent]').attr('data-correlation-parent');
1149		var objParent = $('#' + strParent)[0];
1150		
1151		var pkChildSelected = $(this).val();
1152		
1153		if(!Array.isArray(pkChildSelected) && pkChildSelected > 0) {
1154
1155			if(typeof objParent.selectize.hiddenOptions !== 'undefined') { // parent is static dropdown
1156		
1157				var pkSelected = this.selectize.options[pkChildSelected].correlation;
1158				objParent.selectize.setValue(pkSelected, false);
1159				
1160			} else { // parent is dynamic dropdown
1161			
1162				var OptionKeys = Object.keys(this.selectize.options);
1163				var pkSelectedCorrelation = this.selectize.options[OptionKeys[OptionKeys.indexOf(pkChildSelected)]].correlation;
1164		
1165				var urlAjax = urlAjaxBase + 'ajax/search-select/?pkTable='+$(objParent).attr('data-table')+'&pkColumn='+$(objParent).attr('data-column') + '&get=item' + '&correlateVal=' + pkSelectedCorrelation;
1166				var baseHref = document.getElementsByTagName('base')[0].href;
1167				console.log("AJAX request: " + baseHref + urlAjax);	
1168				
1169				$.ajax({
1170					url:  urlAjax
1171					, success: function(jsonOption) {
1172
1173						jsonOption = JSON.parse(jsonOption);
1174
1175						objParent.selectize.addOption(jsonOption);
1176						objParent.selectize.refreshOptions(false);
1177						objParent.selectize.setValue(pkSelectedCorrelation, false);
1178
1179					}
1180				});
1181				
1182			}
1183			
1184		}
1185
1186	});
1187	
1188	$(strSelector + ' [data-correlation-parent] select.static').change();
1189	
1190	$(strSelector + ' [data-correlation-child] select.static').change(function() {
1191		
1192		var strChild = $(this).closest('[data-correlation-child]').attr('data-correlation-child');
1193		var pkSelected = $(this).val();
1194		var objChild = $('#' + strChild)[0];
1195		var objChildCtrl = $(objChild).closest('[data-correlation-parent]');
1196		
1197		if(!objChild) return;
1198
1199		if(typeof objChild.selectize !== 'undefined' && typeof objChild.selectize.hiddenOptions !== 'undefined') { // child is static dropdown
1200		
1201			var OptionKeys = Object.keys(objChild.selectize.options);
1202			
1203			var pkChildSelected = $(objChild).val();
1204			
1205			if(!Array.isArray(pkChildSelected) && pkChildSelected > 0) {
1206			
1207				var pkSelectedCorrelation = objChild.selectize.options[OptionKeys[OptionKeys.indexOf(pkChildSelected)]].correlation;
1208				if(pkSelectedCorrelation!=pkSelected) objChild.selectize.clearOptions();
1209				
1210			} else for(i=0; i<OptionKeys.length; i++) {
1211				
1212				objChild.selectize.hiddenOptions.push(objChild.selectize.options[OptionKeys[i]]);
1213	
1214				if(pkSelected && pkSelected!=objChild.selectize.options[OptionKeys[i]].correlation) {
1215					
1216					objChild.selectize.hiddenOptions.push(objChild.selectize.options[OptionKeys[i]]);
1217					objChild.selectize.removeOption(OptionKeys[i]);
1218					
1219				}
1220				
1221			}
1222			
1223			for(i=0; i<objChild.selectize.hiddenOptions.length; i++) {
1224				
1225				if((!pkSelected && !$(objChild).prop('multiple')) || pkSelected==objChild.selectize.hiddenOptions[i].correlation) {
1226					
1227					objChild.selectize.addOption(objChild.selectize.hiddenOptions[i]);
1228					
1229				}
1230			
1231			}
1232			
1233			var intOptionCount = Object.keys(objChild.selectize.options).length;
1234			
1235			var objCtrl = $(objChild).closest();
1236			var strCtrlHidden = $(objChildCtrl).attr('aria-hidden');
1237			
1238			if(intOptionCount==0 && strCtrlHidden!='true') {
1239				
1240				toggleFormSection(objChildCtrl, false);
1241				
1242			} else if (intOptionCount > 0 && strCtrlHidden=='true') {
1243				
1244				toggleFormSection(objChildCtrl, true);
1245				
1246			}
1247			
1248		} else if(typeof objChild.selectize !== 'undefined') { // child is dynamic dropdown
1249		
1250			var OptionKeys = Object.keys(objChild.selectize.options);
1251
1252			var pkChildSelected = $(objChild).val();
1253			
1254			if(pkChildSelected > 0) {
1255			
1256				var pkSelectedCorrelation = objChild.selectize.options[OptionKeys[OptionKeys.indexOf(pkChildSelected)]].correlation;
1257				if(pkSelectedCorrelation!=pkSelected) objChild.selectize.clearOptions();
1258				
1259			} else for(i=0; i<OptionKeys.length; i++) {
1260	
1261				if(pkSelected && pkSelected!=objChild.selectize.options[OptionKeys[i]].correlation) {
1262					
1263					objChild.selectize.removeOption(OptionKeys[i]);
1264					
1265				}
1266				
1267			}
1268			
1269			objChild.selectize.correlationValue = pkSelected;
1270			var strCtrlHidden = $(objChildCtrl).attr('aria-hidden');
1271			
1272			if(pkSelected) {
1273			
1274				var urlAjax = urlAjaxBase + 'ajax/search-select/?pkTable='+$(objChild).attr('data-table')+'&pkColumn='+$(objChild).attr('data-column') + '&get=count' + '&correlateVal=' + pkSelected;
1275				var baseHref = document.getElementsByTagName('base')[0].href;
1276				console.log("AJAX request: " + baseHref + urlAjax);	
1277				
1278				$.ajax({
1279					url:  urlAjax
1280					, success: function(intOptionCount) {
1281						
1282						if(intOptionCount==0 && strCtrlHidden!='true') {
1283							
1284							toggleFormSection(objChildCtrl, false);
1285							
1286						} else if (intOptionCount > 0 && strCtrlHidden=='true') {
1287							
1288							toggleFormSection(objChildCtrl, true);
1289							
1290						}
1291						
1292					}
1293				});
1294				
1295			} else if (strCtrlHidden=='true') {
1296							
1297				toggleFormSection(objChildCtrl, true);
1298				
1299			}
1300		
1301		}
1302
1303	});	
1304	
1305	$(strSelector + ' [data-correlation-child] select').change();
1306*/
1307
1308	$(strSelector + ' [data-correlation-parent] select').change(function() {
1309		
1310		var strParent = $(this).closest('[data-correlation-parent]').attr('data-correlation-parent');
1311		var objParent = $('#' + strParent)[0];
1312		
1313		if(!objParent || typeof this.selectize === 'undefined' || typeof objParent.selectize === 'undefined') return;
1314		
1315		var pkChildSelected = $(this).val();
1316		
1317		if(!Array.isArray(pkChildSelected) && pkChildSelected > 0) {
1318	
1319			if(typeof objParent.selectize.hiddenOptions !== 'undefined') { // parent is static dropdown
1320		
1321				if(typeof this.selectize.options[pkChildSelected] !== 'undefined') {
1322					
1323					var pkSelected = this.selectize.options[pkChildSelected].correlation;
1324					objParent.selectize.setValue(pkSelected, false);
1325					
1326				}
1327				
1328			} else { // parent is dynamic dropdown
1329			
1330				if(typeof this.selectize.options[pkChildSelected] !== 'undefined') {
1331					
1332					var pkSelectedCorrelation = this.selectize.options[pkChildSelected].correlation;
1333			
1334					var urlAjax = urlAjaxBase + 'ajax/search-select/?pkTable=' + $(objParent).attr('data-table') + '&pkColumn=' + $(objParent).attr('data-column') + '&get=item' + '&correlateVal=' + pkSelectedCorrelation;
1335					var baseHref = document.getElementsByTagName('base')[0].href;
1336					console.log("AJAX request: " + baseHref + urlAjax);	
1337					
1338					$.ajax({
1339						url: urlAjax,
1340						success: function(jsonOption) {
1341	
1342							jsonOption = JSON.parse(jsonOption);
1343	
1344							objParent.selectize.addOption(jsonOption);
1345							objParent.selectize.refreshOptions(false);
1346							objParent.selectize.setValue(pkSelectedCorrelation, false);
1347	
1348						}
1349					});
1350					
1351				}
1352				
1353			}
1354			
1355		}
1356	
1357	});
1358	
1359	$(strSelector + ' [data-correlation-parent] select.static').change();
1360	
1361	$(strSelector + ' [data-correlation-child] select.static').change(function() {
1362		
1363		var strChild = $(this).closest('[data-correlation-child]').attr('data-correlation-child');
1364		var pkSelected = $(this).val();
1365		var objChild = $('#' + strChild)[0];
1366		
1367		if(!objChild || typeof objChild.selectize === 'undefined') return;
1368		
1369		var objChildCtrl = $(objChild).closest('[data-correlation-parent]');
1370		var selectize = objChild.selectize;
1371		
1372		// Ensure hiddenOptions exists for static dropdowns.
1373		if(typeof selectize.hiddenOptions === 'undefined') {
1374			selectize.hiddenOptions = [];
1375		}
1376		
1377		// If the current selected child no longer belongs to the selected parent,
1378		// clear the selected value only. Do not clear the option list.
1379		var pkChildSelected = $(objChild).val();
1380		
1381		if(!Array.isArray(pkChildSelected) && pkChildSelected > 0 && typeof selectize.options[pkChildSelected] !== 'undefined') {
1382			
1383			var pkSelectedCorrelation = selectize.options[pkChildSelected].correlation;
1384			
1385			if(pkSelectedCorrelation != pkSelected) {
1386				selectize.clear(false);
1387			}
1388			
1389		}
1390		
1391		// Move mismatched visible options into hiddenOptions.
1392		var OptionKeys = Object.keys(selectize.options);
1393		
1394		for(var i = 0; i < OptionKeys.length; i++) {
1395			
1396			var key = OptionKeys[i];
1397			var option = selectize.options[key];
1398			
1399			if(pkSelected && option.correlation != pkSelected) {
1400				
1401				var blnAlreadyHidden = false;
1402				
1403				for(var h = 0; h < selectize.hiddenOptions.length; h++) {
1404					
1405					if(selectize.hiddenOptions[h].value == option.value) {
1406						blnAlreadyHidden = true;
1407						break;
1408					}
1409					
1410				}
1411				
1412				if(!blnAlreadyHidden) {
1413					selectize.hiddenOptions.push(option);
1414				}
1415				
1416				selectize.removeOption(key);
1417				
1418			}
1419			
1420		}
1421		
1422		// Restore matching hidden options.
1423		for(var j = 0; j < selectize.hiddenOptions.length; j++) {
1424			
1425			var hiddenOption = selectize.hiddenOptions[j];
1426			
1427			if((!pkSelected && !$(objChild).prop('multiple')) || hiddenOption.correlation == pkSelected) {
1428				selectize.addOption(hiddenOption);
1429			}
1430			
1431		}
1432		
1433		selectize.refreshOptions(false);
1434		
1435		var intOptionCount = Object.keys(selectize.options).length;
1436		var strCtrlHidden = $(objChildCtrl).attr('aria-hidden');
1437		
1438		if(intOptionCount == 0 && strCtrlHidden != 'true') {
1439			
1440			toggleFormSection(objChildCtrl, false);
1441			
1442		} else if(intOptionCount > 0 && strCtrlHidden == 'true') {
1443			
1444			toggleFormSection(objChildCtrl, true);
1445			
1446		}
1447	
1448	});	
1449	
1450	$(strSelector + ' [data-correlation-child] select').change();
1451	// consent fields
1452	
1453	$(strSelector + " .form-group.consent-field input").change(function(e) {
1454		
1455		if($(this).is(":checked")) {
1456			
1457			$('#' + $(this).attr('data-consent')).html($('#hi5_consent_content_' + $(this).attr('data-consent')).html());
1458			
1459		} else {
1460			
1461			$('#' + $(this).attr('data-consent')).empty();
1462			
1463		}
1464		
1465	});
1466	
1467	// confirmation popup
1468	
1469	//initConfirmation();
1470	
1471	/*$(strSelector + " [data-toggle='confirmation'][data-href]").each(function(){
1472		$(this).attr('href', $(this).attr('data-href')).removeAttr('data-href');
1473	});
1474
1475	$(strSelector + "[data-toggle='confirmation']:not([data-original-title])").each(function() { 
1476		
1477		$(this).removeClass('loading').popConfirm({
1478			placement: $(this).attr('data-placement') ? $(this).attr('data-placement') : 'top',
1479			yesBtn: strLang_Yes,
1480	        noBtn: strLang_No
1481		});
1482		
1483	});*/
1484	
1485	// lov adder
1486	
1487	$(strSelector + ' .hi5-lov-adder').each(function() {
1488	
1489		var objButton = $(this).find('button');
1490		var objSelect = $(this).find('select');
1491		
1492		var pkTable = $(this).attr('data-table');
1493		var pkColumn = $(this).attr('data-column');
1494		
1495		var urlAjax = urlAjaxBase + 'ajax/lov-adder/?pkTable=' + pkTable + '&pkColumn=' + pkColumn;
1496		var baseHref = document.getElementsByTagName('base')[0].href;
1497		console.log("AJAX request: " + baseHref + urlAjax);	
1498		
1499		$(objButton).on('click', function() {
1500
1501			$.ajax({
1502				url:  urlAjax
1503				, success: function(result) {
1504					
1505			        // Remove existing modals to prevent duplicates
1506			        $('#lov-adder-modal').remove();
1507			
1508			        // Append the new modal HTML to the body
1509			        $('body').append(result);
1510			        
1511			        initFormControls('lov-adder-form');
1512			        
1513					$('#lov-adder-form').on('submit', function(e) {
1514				
1515						e.preventDefault();
1516						
1517						var objForm = this;
1518						
1519						setTimeout(function(){ 
1520						
1521							var formData = new FormData(objForm);
1522							var urlAjax = $(objForm).attr('action')
1523							var baseHref = document.getElementsByTagName('base')[0].href;
1524							console.log("AJAX request: " + baseHref + urlAjax);
1525							
1526							$.ajax({
1527								url:  urlAjax
1528								, type: $(objForm).attr('method')
1529								, data: formData
1530					        	, async: false
1531					        	, cache: false
1532					        	, contentType: false
1533					        	, enctype: 'multipart/form-data'
1534					        	, processData: false
1535					        	, dataType: 'json'
1536								, success: function(result) {
1537									
1538									if(result.success) {
1539									
1540										$('#lov-adder-modal').modal('hide');
1541
1542										let objSelectize = $(objSelect)[0].selectize;
1543										
1544										if(objSelectize) {
1545										
1546										    if (objSelectize.isDisabled) {
1547										        objSelectize.enable();
1548										    }											
1549											
1550											objSelectize.addOption({ id: result.value, value: result.value, text: result.label, caption: result.label});
1551											objSelectize.refreshOptions(false);
1552											objSelectize.refreshItems();
1553							                objSelectize.addItem(result.value);
1554
1555										} else { // If Selectize is NOT active (native <select>)
1556								            
1557								            let $option = $('<option>', { value: result.value, text: result.label });
1558								            $(objSelect).append($option).val(result.value).trigger('change');
1559								            
1560								        }
1561										
1562									} else {
1563										
1564										$(objForm).append('<div style="display:none;" id="hi5-popper">' + result.reason + '</div>');
1565										initPopper();
1566										releaseLock('lov-adder-form');
1567										
1568									}
1569	
1570								}, error: function(result) {
1571								
1572									alert("An error occurred: " + $(result.responseText).text().replace(/[\r\n\t]/g, ''));
1573									releaseLock('lov-adder-form');
1574									
1575								}		
1576							});
1577							
1578						}, 100);	
1579						
1580					});	
1581					
1582			        // Show the modal
1583			        $('#lov-adder-modal').modal('show');
1584			        
1585				}, error: function(result) {
1586							
1587					alert("An error occurred: " + $(result.responseText).text().replace(/[\r\n\t]/g, ''));
1588
1589				}
1590				
1591			});
1592			
1593		}).prop('disabled', false);
1594		
1595	});	
1596	
1597	// ajax submit
1598	
1599	$(strSelector + '.ajax-submit').each(function() {
1600		
1601		var submitButtonName = '';
1602		var submitButtonValue = '';
1603		
1604		$(this).find('button[type="submit"]').click(function() {
1605			submitButtonName = $(this).attr('name');
1606			submitButtonValue = $(this).val();
1607		});
1608	
1609		$(this).off('submit').on('submit', function(e) {
1610	
1611		e.preventDefault();
1612		
1613		var objForm = this;
1614		var $form = $(objForm);
1615		var $fieldset = $form.find('fieldset');
1616		var $target = $($form.attr('data-target'));
1617		
1618		if($fieldset.hasClass('invalid')) {
1619			
1620			$fieldset.removeClass('invalid');
1621			alert('invalid');
1622			return;
1623	
1624		} else if($fieldset.hasClass('submitting')) {
1625			
1626			alert('already submitted');
1627			return;
1628			
1629		} else {
1630			
1631			$fieldset.addClass('submitting');
1632			
1633		}
1634		
1635		if(objForm.checkValidity() == false) {
1636			objForm.reportValidity();
1637			$fieldset.removeClass('submitting');
1638			return;
1639		}
1640		
1641		if(typeof tinymce !== 'undefined') {
1642			tinymce.triggerSave();
1643		}
1644		
1645		$form.find('textarea').each(function() {
1646			$(this).text($(this).val());
1647		});
1648		
1649		$target.find('textarea').each(function() {
1650			$(this).text($(this).val());
1651		});
1652		
1653		var formData = new FormData(objForm);
1654		if(submitButtonName.length && submitButtonValue.length) {
1655			formData.append(submitButtonName, submitButtonValue);
1656		}
1657		
1658		var strOriginalTargetHtml = $target.html();
1659		var urlAjax = urlAjaxBase + $form.attr('action');
1660		var baseHref = document.getElementsByTagName('base')[0].href;
1661		
1662		console.log("AJAX request: " + baseHref + urlAjax);
1663		
1664		if($target.is('tr')) {
1665		
1666			$target.html(
1667				'<td colspan="' + $target.children('td').length + '" class="text-center">' +
1668					'<i class="glyphicon glyphicon-hourglass icon-spinner"></i>' +
1669				'</td>'
1670			);
1671		
1672		} else {
1673		
1674			$target.html(
1675				'<div id="loading-icon" class="d-block text-center p-5" style="font-size:60px;opacity:0.25;height:100%;padding:25px;">' +
1676					'<i class="glyphicon glyphicon-hourglass icon-spinner"></i>' +
1677				'</div>'
1678			);
1679		
1680		}
1681
1682		setTimeout(function() {
1683			var targetEl = $target[0];
1684			if(targetEl) {
1685				targetEl.scrollIntoView({ behavior: "smooth", block: "center" });
1686			}
1687		}, 250);
1688			
1689			setTimeout(function() {
1690	
1691				$.ajax({
1692					url: urlAjax,
1693					type: $(objForm).attr('method'),
1694					data: formData,
1695		        	async: false,
1696		        	cache: false,
1697		        	contentType: false,
1698		        	enctype: 'multipart/form-data',
1699		        	processData: false,
1700					success: function(result) {
1701						
1702						var strFormID = $(objForm).attr('id');
1703						releaseLock(strFormID);
1704						$($(objForm).attr('data-target')).replaceWith(result);
1705						
1706						if($form.hasClass('close-modal-on-success')) $form.closest('.modal').modal('hide');						
1707						
1708						initAJAXLinks();
1709						initFormControls(strFormID);
1710						initCommentButtons();
1711						CSPInit();
1712						initConfirmation();
1713						
1714						$(objForm).find('[type="search"]').select();
1715						
1716					},
1717					error: function(xhr) {
1718						
1719						var strErrorMsg = '';
1720
1721						if(xhr.responseText) {
1722							var $response = $(xhr.responseText);
1723							strErrorMsg = $response.filter('#error-msg').add($response.find('#error-msg')).first().html();
1724						}
1725						
1726						if(!strErrorMsg) {
1727							strErrorMsg = 'Sorry, the form could not be submitted.';
1728						}
1729						
1730						$target.html(strOriginalTargetHtml);
1731						
1732						$target.find('form.Hi5-init').removeClass('Hi5-init');
1733						$target.find('select.selectized').removeClass('selectized');
1734						$target.find('.selectize-control').remove();
1735						
1736						// reset Krajee fileinput back to raw file inputs
1737						$target.find('.file-input').each(function() {
1738							
1739							var $wrapper = $(this);
1740							var $input = $wrapper.find('input[type="file"]').first();
1741							
1742							if($input.length) {
1743								$wrapper.replaceWith($input);
1744							}
1745							
1746						});
1747						
1748						$target.find('input[type="file"]').each(function() {
1749							$(this).removeData('fileinput');
1750						});						
1751						
1752						// reset TinyMCE
1753						$target.find('.tox-tinymce, .mce-tinymce, .mce-container, .mce-panel').remove();
1754						$target.find('textarea').each(function() {
1755							$(this).show().removeAttr('aria-hidden');
1756						});					
1757						
1758						// legacy class fix
1759						$target.find('textarea.tinymce-basic').each(function() {
1760							$(this)
1761								.removeClass('tinymce-basic')
1762								.addClass('tinymce');
1763						});						
1764						
1765						initAJAXLinks();
1766						initFormControls($(objForm).attr('id'));
1767						initCommentButtons();
1768						CSPInit();
1769						initConfirmation();			
1770						
1771						$target.find('.grid_input > div > .btn-primary')
1772							.off('click.addGridRow')
1773							.on('click.addGridRow', function(e) {
1774								e.preventDefault();
1775								var strTableId = $(this).closest('.grid_input').find('table[id]').first().attr('id');
1776								if(strTableId) addGridRow(strTableId);
1777							});
1778						
1779						$('#hi5-popper').remove();
1780						$('body').append('<div style="display:none;" id="hi5-popper">' + strErrorMsg + '</div>');
1781						initPopper();
1782						
1783						releaseLock($(objForm).attr('id'));
1784						$(objForm).find('[type="search"]').select();
1785						
1786					}
1787				});
1788			}, 500);
1789			
1790		});
1791		
1792	});	
1793	
1794	if($(strSelector + ' input[type="search"]').length) $(strSelector + ' input[type="search"]').first().focus().select();
1795	
1796	// add init class
1797	$(strSelector).addClass('Hi5-init');
1798
1799}
1800
1801function ConditionalTrigger(strFormID) {
1802	
1803	$('#' + strFormID + ' [data-show-conditions]').each(function(i) {
1804		
1805		checkCondition(this, $(this).attr('data-show-conditions'), 'show');
1806
1807	});
1808
1809	$('#' + strFormID + ' [data-required-conditions]').each(function(i) {
1810	
1811		checkCondition(this, $(this).attr('data-required-conditions'), 'required');
1812		
1813	});
1814	
1815	$('#' + strFormID + ' [data-hide-conditions]').each(function(i) {
1816	
1817		checkCondition(this, $(this).attr('data-hide-conditions'), 'hide');
1818		
1819	});
1820		
1821}
1822
1823function checkCondition(obj, strCondition, enumAction) {
1824
1825	if(strCondition.length==0) return;
1826
1827	var arrConditions = strCondition.split(',');
1828	
1829	var blnConditionMet = false;
1830	var intConditionsMet = 0;
1831	
1832	for(var i=0; i<arrConditions.length; i++) {
1833		
1834		var arrConditionParts = arrConditions[i].split('|');
1835		var strTriggerCol = arrConditionParts[0];
1836		var arrSelected = getSelected(strTriggerCol);
1837
1838		if($('#field-' + strTriggerCol).attr('aria-hidden')=='true') {
1839			
1840			intConditionsMet++;
1841			blnConditionMet = intConditionsMet==arrConditions.length;
1842			
1843		} else {
1844
1845			for(var j=1; !blnConditionMet && j<arrConditionParts.length; j++) for(var k=0; !blnConditionMet && k<arrSelected.length; k++) if(arrConditionParts[j]==arrSelected[k]) {
1846				
1847				intConditionsMet++;
1848				blnConditionMet = intConditionsMet==arrConditions.length;
1849				
1850			}
1851			
1852			if(blnConditionMet) {
1853				
1854				if(enumAction=='required') {
1855				
1856					toggleConditionalRequiredFields(obj, true);
1857					
1858				} else {
1859
1860					toggleFormSection(obj, enumAction=='show');
1861
1862					if(enumAction=='show' && $(obj).find(".signature-ctrl").length) {
1863						
1864						$(obj).find(".signature-ctrl").each(function(){
1865						
1866							//$(this).jSignature('reset'); 
1867							$(this).off();
1868							$(this).empty();	
1869							$(this).jSignature();
1870							$(this).jSignature('reset'); 
1871							
1872							$(this).bind('change', function(){ 
1873								
1874								$('#' + $(this).attr('data-target')).val($(this).jSignature("getData"));
1875								
1876							});							
1877							
1878						});
1879
1880					}
1881
1882				}
1883				
1884				//blnConditionMet = true;
1885				
1886			}
1887			
1888		}
1889
1890	}
1891
1892	if(!blnConditionMet) {
1893		
1894		if(enumAction=='required') {
1895			
1896			toggleConditionalRequiredFields(obj, false);
1897			
1898		} else {		
1899		
1900			toggleFormSection(obj, enumAction=='hide');
1901			
1902		}
1903		
1904	}
1905
1906}
1907
1908function toggleConditionalRequiredFields(obj, blnRequired) {
1909	
1910	if(obj.tagName!='DIV') return;
1911
1912	if(blnRequired) {
1913		
1914		$(obj).addClass('required');
1915		$(obj).find('.form-control').prop('required', true);
1916		$(obj).find('.control-label span.mark_optional').remove();
1917		$(obj).find('.control-label span.mark_required').remove();
1918		$(obj).find('.control-label > span').append('<span class="mark_required">(' + strLang_Required + ')</span>');
1919		
1920	} else {
1921		
1922		$(obj).removeClass('required');
1923		$(obj).find('.form-control').prop('required', false);
1924		$(obj).find('.control-label span.mark_optional').remove();
1925		$(obj).find('.control-label span.mark_required').remove();
1926		$(obj).find('.control-label > span').append('<span class="mark_optional">(' + strLang_Optional + ')</span>');
1927		
1928	}
1929	
1930}
1931
1932function toggleFormSection(obj, blnShow) {
1933	
1934	if(blnShow) {
1935		
1936		if($(obj).find('[data-required="true"]').length) toggleConditionalRequiredFields(obj, true);
1937		$(obj).attr('aria-hidden', 'false').slideDown();
1938		
1939	} else {
1940		
1941		if($(obj).hasClass('required')) toggleConditionalRequiredFields(obj, false);
1942		$(obj).attr('aria-hidden', 'true').slideUp();
1943		
1944	}
1945	
1946}
1947
1948function getSelected(strCol) {
1949	
1950	var arrSelected = [];
1951	
1952	$('select#' + strCol + ' > option:selected, .switch input#' + strCol + '[type="checkbox"], #' + strCol + '.checklist input[type="checkbox"]:checked, #' + strCol + '.checklist input[type="radio"]:checked').each(function(i) {
1953		
1954		arrSelected.push(this.value);
1955		
1956	});
1957	
1958	if(arrSelected.length==0) arrSelected.push(0);
1959	
1960	return arrSelected;
1961	
1962}
1963
1964function revealNativeControls(objForm) {
1965	
1966	$(objForm).find('.signature textarea, select.selectized, select.hierarchy-select-ctrl, textarea.tinymce, textarea.tinymce-basic, textarea.tinymce-scientific, .radio input[type=radio] , .checkbox input[type=checkbox], .switch input[type=checkbox]').each(function() {
1967		
1968		if($(this).css('opacity')==0 || $(this).css('display')=='none') {
1969		
1970			$(this).addClass('validation-display').css("position", "absolution").css("bottom", "0").css("left", "10%").css("transform", "translateX(-50%)").css("padding", "0").css("border", "0").css("min-width", "1px").css("min-height", "1px").css("max-height", "1px").css("max-width", "1px").css("display", "block").css("opacity", "0");
1971			
1972		}
1973		
1974	});
1975	
1976}
1977
1978function hideSelects() {
1979	
1980	$('select').css("display", "none");
1981	
1982}
1983
1984
1985function addGridRow(strTableId) {
1986	
1987	if (typeof addGridRowCustom == 'function') { 
1988		addGridRowCustom(strTableId);
1989		return;
1990	}
1991		
1992	var table = document.getElementById(strTableId);		
1993	var rowTemplate = document.getElementById("template_" + strTableId);
1994	var intMaxRow = 0;
1995	
1996	$('#' + strTableId + ' input[data-row], #' + strTableId + ' select[data-row]').each(function() {
1997		if($(this).attr('data-row')>intMaxRow) intMaxRow = parseInt($(this).attr('data-row'));
1998	});
1999
2000	var node = rowTemplate.cloneNode(true);
2001	node.id = strTableId + "-row-" + (intMaxRow+1);
2002	var strNode = $(node).get(0).outerHTML;
2003	strNode = strNode.replaceAll('{$rownum}', intMaxRow+1);
2004	
2005	$('#' + strTableId + ' tbody').append(strNode);
2006	
2007	if (typeof GridRowAdded === 'function') { 
2008		GridRowAdded(node.id);
2009	}
2010
2011	initFormControls(node.id);
2012
2013}
2014
2015String.prototype.replaceAll = function (stringToFind, stringToReplace) {
2016    if (stringToFind === stringToReplace) return this;
2017    var temp = this;
2018    var index = temp.indexOf(stringToFind);
2019    while (index != -1) {
2020        temp = temp.replace(stringToFind, stringToReplace);
2021        index = temp.indexOf(stringToFind);
2022    }
2023    return temp;
2024};
2025    
2026function deletGridRow(strRowID) {
2027
2028	$('.popover').remove();
2029	
2030	var strTableId = $('#' + strRowID).parent().parent().attr('id');
2031	
2032	//$('#' + strRowID).remove();
2033	
2034	$('#' + strRowID + ' td.id_column').empty();
2035	$('#' + strRowID + ' :required').prop('required', false);
2036	$('#' + strRowID).css('display', 'none').addClass('hidden d-none');	
2037	
2038	/*if(document.getElementById(strTableId).getElementsByTagName("tbody")[0].getElementsByTagName("tr").length==0) {
2039		
2040		addGridRow(strTableId);
2041		
2042	}*/
2043		
2044	if (typeof GridRowRemoved === 'function') {
2045		
2046		GridRowRemoved();
2047		
2048	}
2049	
2050}
2051
2052function fixHttpPrefix(objUrlInput) {
2053
2054	var s = objUrlInput.value.trim();
2055
2056	if(s.length) {
2057		
2058		if (!s.match(/^[a-zA-Z]+:\/\//)) {
2059			
2060			objUrlInput.value = "http://" + s;
2061			
2062		}
2063		
2064	}
2065	
2066}	
2067
2068function ValidURL(str) {
2069		
2070  var pattern = new RegExp('((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name
2071  '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
2072  '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
2073  '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
2074  '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
2075  
2076  return pattern.test(str);
2077}
2078
2079function doSubmit(obj) {
2080	
2081	$(obj).closest('form').submit();
2082	
2083}
2084
2085function doCancel() {
2086
2087	if(history.length<=1 && document.referrer!=window.location.href) {
2088		window.location.replace(document.referrer);	
2089	} else {
2090		history.back();
2091	}	
2092	
2093}
2094
2095function DatePickerSupported() {
2096
2097	var elem = document.createElement('input');
2098	
2099	elem.setAttribute('type', 'date');
2100	
2101	elem.value = '2000-01-01';
2102
2103	if (typeof elem.valueAsDate == 'undefined') {
2104		
2105		return false;
2106		
2107	} else {
2108		
2109		return true;
2110		
2111	}	
2112	
2113}
2114
2115function DateTimePickerSupported() {
2116
2117	var elem = document.createElement('input');
2118	
2119	elem.setAttribute('type', 'datetime-local');
2120	
2121	elem.value = '2000-01-01T12:00:00';
2122
2123	if (isNaN(elem.valueAsNumber)) {
2124		
2125		return false;
2126		
2127	} else {
2128		
2129		return true;
2130		
2131	}	
2132	
2133}
2134
2135function UpdateSelectOptions(strCtrlId, arrOptions, pkSelected) {
2136
2137	if(pkSelected==-1) {
2138		
2139		var currentVal = arrOptions[0].id;
2140		
2141	} else /*if(pkSelected)*/ {
2142		
2143		var currentVal = pkSelected;
2144		
2145	/*} else {
2146		
2147		//var currentVal = Number($('#' + strCtrlId).val());
2148		
2149		currentVal = $('#' + strCtrlId).val();
2150		*/
2151	}
2152
2153	var newOptions = Array();
2154	
2155	$.each(arrOptions, function(id, obj) {
2156			
2157		var option = document.createElement("option");
2158		option.text = obj.caption;
2159		option.value = obj.id;
2160		newOptions.push(option);
2161			
2162    });
2163	
2164	var selectize = $('#' + strCtrlId)[0].selectize;
2165	
2166	selectize.clearOptions();
2167	selectize.addOption(newOptions);
2168	
2169	//if(currentVal > 0) {
2170		
2171		if(newOptions.length==1) {
2172			
2173			selectize.setValue(newOptions[0].value);
2174			
2175		} else {
2176			
2177			selectize.setValue(currentVal);
2178			
2179		}
2180		
2181	//}
2182	selectize.refreshOptions(false);
2183	
2184}
2185function ResetSignature(strCol) {
2186
2187	$("#hi5_sig-" + strCol).jSignature("reset");
2188	$('#'+strCol).val('');
2189	
2190}
2191function isValidPassword(str) {
2192
2193	return regExValidPwd.test(str);
2194
2195}
2196
2197/* color picker */
2198
2199function initColorPicker() {
2200	
2201	$('.color-picker:not(.color-picker-init)').each(function() {
2202		
2203		var objInput = this;
2204
2205		$(this).find('.dropdown  > input').each(function() {
2206			
2207			$(this).prop('readonly', true);
2208			UpdateColorPicker(this);
2209			
2210		});
2211		
2212		$(this).find('.dropdown > input').click(function(e) {
2213			
2214			if($(this).parent().hasClass('open')) return;
2215			
2216			$('.color-picker .dropdown.open .dropdown-toggle').each(function() {
2217				
2218				CloseColorPicker(this);
2219
2220				/*$(this).removeClass('open');
2221				var htmlDropdown = $(this).closest('.color-picker').find('.dropdown-menu').html();
2222				$(this).closest('.color-picker').find('.dropdown-menu > div').remove();
2223				$('#color-picker-dropdown').html(htmlDropdown);*/
2224				
2225			});
2226			
2227		
2228			//$('#color-picker-dropdown > div').detach().appendTo($(this).parent().find('.dropdown-menu'));
2229			var htmlDropdown = $('#color-picker-dropdown').html();
2230			$('#color-picker-dropdown > div').remove();
2231			$(this).parent().find('.dropdown-menu').html(htmlDropdown);
2232			initColorPickerDropdown(objInput);
2233			$(this).parent().addClass('open');
2234		
2235		});
2236		
2237		$(this).addClass('color-picker-init');
2238	
2239	});	
2240	
2241}
2242
2243function initColorPickerDropdown(objInput) {
2244	
2245	var strHex = $(objInput).find('.dropdown-toggle').attr('data-hex');
2246	var intOpacity = $(objInput).find('.dropdown-toggle').attr('data-opacity');	
2247	
2248	$(objInput).parent().find('input[name="color-picker-hexcode"]').val(strHex);
2249	$(objInput).parent().find('input[name="color-picker-opacity"]').attr('placeholder', "opacity: " + intOpacity + "%");	
2250
2251	$(objInput).find('.dropdown > .dropdown-menu input[type="text"]').on('input', function() { 
2252		
2253		this.setCustomValidity(" ");
2254	
2255	});
2256	
2257	$(objInput).find('.dropdown > .dropdown-menu input[name="color-picker-opacity"]').on('change', function() { 
2258		
2259		if(this.validity.patternMismatch) {
2260			
2261			this.setCustomValidity("Please enter a number between 0 and 100");
2262			this.reportValidity();
2263			
2264		} else {
2265		
2266			var intOpacity = $(this).val();
2267			
2268			var objInput = $(this).closest('.color-picker').find('.dropdown-toggle')[0];
2269			$(objInput).attr('data-opacity', intOpacity);
2270			
2271			$(this).attr('placeholder', "opacity: " + intOpacity + "%");
2272			$(this).val('');
2273			
2274		}
2275		
2276	});	
2277	
2278	$(objInput).find('input[name="color-picker-hexcode"]').on('keyup', function(e) {
2279		if (e.key == "Escape") {
2280			var strHex = $(objInput).closest('.color-picker').find('.dropdown-toggle').attr('data-hex');
2281			$(this).val(strHex);
2282		}
2283	});
2284	
2285	$(objInput).find('input[name="color-picker-hexcode"]').on('input', function() {
2286        // Get the current value of the input field
2287        var value = $(this).val();
2288
2289        // Check if the input has a value and the first character isn't '#'
2290        if (value && value.charAt(0) !== '#') {
2291            // Prepend '#' to the value
2292            $(this).val('#' + value);
2293        }
2294        
2295        // if there is a value, and the opacity is zero, then set opacity to 100
2296        if(value) {
2297        	
2298        	var intOpacity = $(objInput).find('[data-opacity]').attr('data-opacity');
2299
2300			if(intOpacity==0) {
2301			
2302				intOpacity = 100;
2303				$(objInput).find('[data-opacity]').attr('data-opacity', intOpacity);
2304				$(objInput).find('input[name="color-picker-opacity"]').attr('placeholder', "opacity: " + intOpacity + "%");		
2305				
2306			}
2307			
2308        }
2309        
2310    });
2311	
2312	$(objInput).find('.dropdown > .dropdown-menu button').click(function() {
2313		
2314		var objInputHex = $(this).closest('.dropdown-menu').find('input[name="color-picker-hexcode"]')[0];
2315		var objInputOpacity = $(this).closest('.dropdown-menu').find('input[name="color-picker-opacity"]')[0];
2316
2317		if(objInputHex.validity.patternMismatch || objInputHex.validity.valueMissing) {
2318			
2319			objInputHex.setCustomValidity("Please enter a valid hexadecimal color code");
2320			objInputHex.reportValidity();
2321			
2322		} else if(objInputOpacity.validity.patternMismatch) {
2323			
2324			objInputOpacity.setCustomValidity("Please enter a number between 0 and 100");
2325			objInputOpacity.reportValidity();
2326			
2327		} else {
2328		
2329			var objInput = $(this).closest('.color-picker').find('.dropdown-toggle')[0];
2330			
2331			CloseColorPicker(objInput);
2332			
2333		}
2334		
2335	});
2336	
2337	$(objInput).find('.radio-option').click(function(e) {
2338		
2339		var strHexCode = $(this).find('input[name="color-option"]').val();
2340		var objInput = $(this).closest('.color-picker').find('.dropdown-toggle')[0];
2341		var objInputOpacity = $(this).closest('.dropdown-menu').find('input[name="color-picker-opacity"]')[0];
2342		
2343		var intOpacity = $(objInput).attr('data-opacity');
2344
2345		if(intOpacity==0) {
2346		
2347			intOpacity = 100;
2348			$(objInput).attr('data-opacity', intOpacity);
2349			$(objInputOpacity).attr('placeholder', "opacity: " + intOpacity + "%");		
2350			
2351		}
2352
2353		$(this).closest('.dropdown-menu').find('input[name="color-picker-hexcode"]').val(strHexCode);
2354		CloseColorPicker(objInput);
2355		
2356	});	
2357
2358}
2359
2360function CloseColorPicker(objInput) {
2361	
2362	var strHexCode = $(objInput).closest('.color-picker').find('input[name="color-picker-hexcode"]').val();
2363	var intOpacity = $(objInput).attr('data-opacity');
2364
2365	$(objInput).attr('data-hex', strHexCode);
2366	$(objInput).closest('.dropdown').removeClass('open');
2367	UpdateColorPicker(objInput);
2368	
2369	var htmlDropdown = $(objInput).closest('.color-picker').find('.dropdown-menu').html();
2370	$(objInput).closest('.color-picker').find('.dropdown-menu > div').remove();
2371	$('#color-picker-dropdown').html(htmlDropdown);
2372	
2373	//$(objInput).find('.dropdown-menu > div').detach().appendTo('#color-picker-dropdown');
2374	
2375}
2376	
2377function UpdateColorPicker(objInput) {
2378	
2379	var strHex = $(objInput).attr('data-hex');
2380	var intOpacity = $(objInput).attr('data-opacity');
2381	
2382	if(isDarkColor(strHex, intOpacity)) {
2383		$(objInput).css('color', 'white');
2384	} else {
2385		$(objInput).css('color', 'black');
2386	}
2387	
2388	strRGBA = hexToRGB(strHex, intOpacity);
2389	
2390	$(objInput).val(strHex + ' (' + intOpacity + '%)');
2391	$(objInput).css('background-color', strRGBA);
2392	
2393}
2394
2395function DisableColorPicker(objInput) {
2396	
2397	$(objInput).prop('disabled', true);
2398	
2399}
2400
2401/**
2402 * Retrieves the value of a CSS variable defined within an iframe.
2403 *
2404 * @param {Element} elementInIframe - An element located inside the iframe, used to access the iframe's document.
2405 * @param {string} varName - The name of the CSS variable to retrieve (e.g., '--color-primary').
2406 * @returns {string} The value of the specified CSS variable, with whitespace trimmed.
2407 */
2408
2409function getCSSVariable(elementInIframe, varName) {
2410    // Use getComputedStyle on the document element of the iframe's content
2411    return getComputedStyle(elementInIframe.ownerDocument.documentElement)
2412        .getPropertyValue(varName)
2413        .trim();
2414}
2415
2416/**
2417 * Expands a short hex color code (e.g., '#666') to its full form (e.g., '#666666').
2418 * If the color is already in full hex format (e.g., '#123456'), it returns the color unaltered.
2419 *
2420 * @param {string} color - The hex color code to expand, either short (e.g., '#abc') or full (e.g., '#aabbcc').
2421 * @returns {string} The expanded full-form hex color code, or the original if already in full format.
2422 */
2423 
2424function expandHexColor(color) {
2425    // Check if the color is in short format (e.g., #abc)
2426    if (/^#([0-9a-fA-F]{3})$/.test(color)) {
2427        // Expand it by repeating each character
2428        return color.replace(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/, '#$1$1$2$2$3$3');
2429    }
2430    // Return the color unaltered if it is already in full format
2431    return color;
2432}
2433
2434function hexToRGB(hex, alpha) {
2435
2436	alpha = alpha / 100;
2437	
2438    var r = parseInt(hex.slice(1, 3), 16),
2439        g = parseInt(hex.slice(3, 5), 16),
2440        b = parseInt(hex.slice(5, 7), 16);
2441
2442    if (alpha) {
2443        return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
2444    } else {
2445        return "rgb(" + r + ", " + g + ", " + b + ")";
2446    }
2447 
2448}
2449
2450function isDarkColor(color, alpha) {
2451
2452	alpha = alpha / 100;
2453	
2454    color = +("0x" + color.slice(1).replace( 
2455    color.length < 5 && /./g, '$&$&'));
2456    
2457    var r, g, b
2458
2459    r = color >> 16;
2460    g = color >> 8 & 255;
2461    b = color & 255;	
2462    
2463    const brightness = r * 0.299 + g * 0.587 + b * 0.114 + (1 - alpha) * 255;
2464    
2465    return brightness > 186 ? false : true;
2466
2467}

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.