PageSourceSearch

https://www.lakehalliegolf.com/media/com_rsform/js/script.js?f0dc0d41e81e8711259f23e598419f9e

js lakehalliegolf.com collected 2026-10-04 15:26:47 UTC 94,118 bytes, 3,089 lines download raw bytes

1var RSFormProCalendars = {};
2var RSFormProPrices = {};
3var ajaxExtraValidationScript = {};
4var RSClickedSubmitElement = false;
5
6if (typeof RSFormPro != 'object') {
7	var RSFormPro = {};
8}
9
10RSFormPro.Forms = {};
11RSFormPro.Editors = {};
12RSFormPro.scrollToError = false;
13RSFormPro.usePositioning = false;
14RSFormPro.scrollPage = false;
15RSFormPro.scrollPageOffset = 0;
16RSFormPro.initialPage = false;
17
18/* Handle HTML5 form fields validation for the forms without AjaxValidation enabled */
19RSFormPro.setHTML5Validation = function (formId, isDisabledSubmit, errorClasses, totalPages) {
20	var parentErrorClass = errorClasses.parent;
21	var fieldErrorClass = errorClasses.field;
22	var submitElement = RSFormPro.getElementByType(formId, 'submit');
23	var i, j;
24	for (i = 0; i < submitElement.length; i++) {
25		if (RSFormProUtils.hasClass(submitElement[i],'rsform-submit-button')) {
26			RSFormProUtils.addEvent(submitElement[i], 'click', (function (event) {
27				var errorElements = RSFormPro.HTML5.validation(formId);
28				if (errorElements.length) {
29					var errorPagesFound = [];
30					for (j = 0; j < errorElements.length; j++) {
31						RSFormProUtils.addClass(errorElements[j], 'rsform-error');
32
33						if (document.getElementById('component' + errorElements[j].componentId)) {
34							document.getElementById('component' + errorElements[j].componentId).className = 'formError';
35						}
36						if (parentErrorClass) {
37							try {
38								var block = RSFormPro.getBlock(formId, RSFormProUtils.getAlias(errorElements[j].field.getAttribute('id')));
39
40								RSFormProUtils.addClass(block[0], parentErrorClass);
41							} catch (err) {}
42						}
43
44						if (totalPages > 0) {
45							errorPagesFound.push(errorElements[j].page);
46						}
47					}
48
49					if (totalPages > 0 && errorPagesFound.length) {
50						var firstErrorPage = Math.min.apply(null, errorPagesFound);
51						RSFormPro.Pages.change(formId, firstErrorPage, totalPages, false, errorClasses)
52					}
53
54					if (RSFormPro.scrollToError){
55						RSFormPro.gotoErrorElement(formId);
56					}
57
58					if (isDisabledSubmit) {
59						for (j = 0; j < submitElement.length; j++) {
60							submitElement[j].disabled = false;
61						}
62					}
63
64					event.preventDefault();
65				} else {
66					if (isDisabledSubmit) {
67						RSFormPro.submitForm(this.form);
68					}
69				}
70			}));
71		}
72	}
73};
74
75RSFormPro.formEvents = {};
76
77RSFormPro.addFormEvent = function(formId, func) {
78	if (typeof RSFormPro.formEvents[formId] !== 'object') {
79		RSFormPro.formEvents[formId] = [];
80	}
81
82	RSFormPro.formEvents[formId].push(func);
83};
84
85RSFormPro.submitFormCount = 0;
86
87RSFormPro.submitForm = function(form) {
88	var formId = form.elements['form[formId]'].value;
89	var func;
90
91	if (typeof RSFormPro.formEvents[formId] === 'object' && RSFormPro.formEvents[formId].length > 0) {
92		func = RSFormPro.formEvents[formId].shift()
93		if (typeof func === 'function') {
94			func();
95
96			return false;
97		}
98	}
99
100	// Need this to stop infinite loops on Chrome, for now
101	if (RSFormPro.submitFormCount > 0)
102	{
103		RSFormPro.submitFormCount = 0;
104		return;
105	}
106	RSFormPro.submitFormCount++;
107
108	// if the submit button or any other element has the id submit the form.submit() function is overwritten
109	RSFormPro.triggerEvent(form, 'submit');
110	if (typeof form.submit === 'function') {
111		form.submit();
112	} else {
113		document.createElement('form').submit.call(form)
114	}
115};
116
117/* Disable the submit button when form is submitted functions */
118RSFormPro.setDisabledSubmit = function(formId, ajaxValidation){
119	if (!ajaxValidation) {
120		var i, j;
121		var submitElement = RSFormPro.getElementByType(formId, 'submit');
122		for (i = 0; i < submitElement.length; i++) {
123			if (RSFormProUtils.hasClass(submitElement[i],'rsform-submit-button')) {
124				RSFormProUtils.addEvent(submitElement[i],'click', (function(event) {
125					event.preventDefault();
126					for (j = 0; j < submitElement.length; j++) {
127						submitElement[j].disabled = true;
128					}
129				}));
130			}
131		}
132	}
133};
134/* Thank You Message in Popup Window functions */
135
136RSFormPro.showThankYouPopup = function (thankYouContainer){
137	var content = thankYouContainer.innerHTML;
138	var gotoUrl = thankYouContainer.querySelector('#rsfp-thankyou-popup-return-link').value;
139
140	// remove the html part from the layout
141	thankYouContainer.parentNode.removeChild(thankYouContainer);
142
143	RSFormProUtils.addClass(document.body, 'rsfp_popup_activated');
144
145	var outer = document.createElement('div');
146	outer.setAttribute('class', 'rsfp_thankyou_popup_outer');
147	outer.onclick = function() {
148		if (event && event.target && (RSFormProUtils.hasClass(event.target, 'rsfp_thankyou_popup_outer') || RSFormProUtils.hasClass(event.target, 'rsfp_thankou_popup_close_btn'))) {
149            destroyPopup();
150            redirectUrl();
151		}
152	};
153
154	var inner = document.createElement('div');
155	inner.setAttribute('class', 'rsfp_thankyou_popup_inner');
156	inner.setAttribute('id', 'rsfp_thankyou_popup_inner');
157	inner.innerHTML = content;
158
159	var close = document.createElement('div');
160	close.setAttribute('class', 'rsfp_thankou_popup_close_btn');
161	close.innerHTML = '&times;';
162
163	outer.appendChild(inner);
164	inner.appendChild(close);
165
166	document.body.appendChild(outer);
167
168	document.getElementById('rsfp_thankyou_popup_inner').style.marginTop = (window.innerHeight - document.getElementById('rsfp_thankyou_popup_inner').offsetHeight) / 2 + 'px';
169
170	var continueButton = outer.querySelector('[name=continue]');
171	if (continueButton) {
172		continueButton.removeAttribute('onclick');
173		continueButton.onclick = function() {
174			destroyPopup();
175			redirectUrl();
176		}
177	}
178
179	var redirectUrl = function() {
180        if (gotoUrl.length > 0) {
181            document.location = gotoUrl;
182        } else {
183            document.location.reload(true);
184        }
185	};
186
187	var destroyPopup = function() {
188        RSFormProUtils.removeClass(document.body, 'rsfp_popup_activated');
189
190        document.body.removeChild(outer);
191	};
192};
193
194/* Scroll to first error element */
195RSFormPro.gotoErrorElement = function(formId){
196	var form = RSFormPro.getForm(formId);
197	var errorElements = form.getElementsByClassName('formError');
198	if (errorElements.length) {
199		var block = RSFormPro.findAncestor(errorElements[0], 'rsform-block');
200		if (block) {
201			RSFormPro.scrollToElement(block);
202		} else {
203			RSFormPro.scrollToElement(errorElements[0]);
204		}
205	}
206};
207
208RSFormPro.findAncestor = function(el, cls){
209	while(el = el.parentElement) {
210		var elementClasses = el.className;
211		elementClasses = elementClasses.split(' ');
212		if (elementClasses.indexOf(cls) > -1) {
213			return el;
214		}
215	}
216
217	return false;
218};
219
220/* Reset all values, used with reset button for the submit */
221RSFormPro.resetElements = function(formId) {
222	var form 	= RSFormPro.getForm(formId);
223
224	if (form && form.elements.length) {
225		RSFormPro.resetValues(form.elements);
226	}
227};
228
229/* ScrollTo functions */
230RSFormPro.scrollToElement = function(element){
231	var to = element.offsetTop;
232	var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
233	var documentView = window.innerHeight + scrollTop;
234
235	// this is more specific for the modern browsers
236	if (typeof element.getBoundingClientRect === 'function') {
237		to = element.getBoundingClientRect().top + scrollTop;
238	}
239
240	if (to < scrollTop || to > documentView) {
241		RSFormPro.scrollTo(to, 300);
242	}
243};
244
245RSFormPro.scrollTo = function(to, duration) {
246	if (duration <= 0) return;
247	var elementScrollTop = window.pageYOffset ?  window.pageYOffset : document.documentElement.scrollTop;
248	var difference = to - elementScrollTop;
249	var perTick = difference / duration * 10;
250	
251	window.setTimeout(function() {
252		var limitControl;
253		limitControl = window.pageYOffset ?  window.pageYOffset : document.documentElement.scrollTop;
254		limitControl = limitControl + perTick;
255		window.scrollTo(0, limitControl);
256		// if the element has been reached or the scroll is at the bottom of the page no need to continue
257		if (limitControl == to) return;
258
259		RSFormPro.scrollTo(to, duration - 10);
260	}, 10);
261};
262
263/* Field specific functions */
264
265RSFormPro.refreshCaptcha = function(componentId, captchaPath) {
266	if (!captchaPath) {
267		captchaPath = 'index.php?option=com_rsform&task=captcha&format=image&componentId=' + componentId;
268	}
269	document.getElementById('captcha' + componentId).src = captchaPath + '&' + Math.random();
270	document.getElementById('captchaTxt' + componentId).value = '';
271	document.getElementById('captchaTxt' + componentId).focus();
272};
273
274RSFormPro.geoLocationTimeouts = {};
275
276RSFormPro.initGeoLocation = function(term, id, mapid, map, marker, geocoder, type) {
277	var content = document.getElementById('rsform_geolocation'+id);
278	var address	= document.getElementById(mapid).clientWidth;
279
280	document.getElementById('rsform_geolocation'+id).style.width = address+'px';
281	document.getElementById('rsform_geolocation'+id).style.display = 'none';
282	document.getElementById('rsform_geolocation'+id).innerHTML = '';
283
284	if (typeof RSFormPro.geoLocationTimeouts[id] !== 'undefined')
285	{
286		window.clearTimeout(RSFormPro.geoLocationTimeouts[id]);
287	}
288
289	if (term != '') {
290		RSFormPro.geoLocationTimeouts[id] = window.setTimeout(function(){
291			geocoder.geocode( {'address': term }, function(results, status) {
292				if (status == 'OK') {
293					for (var i=0; i<results.length; i++) {
294						var item	= results[i];
295						var theli	= document.createElement('li');
296						var thea	= document.createElement('a');
297
298						thea.setAttribute('href','javascript:void(0)');
299						thea.innerHTML = item.formatted_address;
300
301						RSFormProUtils.addEvent(thea,'click', (function() {
302							var mapValue = type ? item.formatted_address : item.geometry.location.lat().toFixed(5) + ',' + item.geometry.location.lng().toFixed(5);
303							var mapId	 = mapid;
304							var location = new google.maps.LatLng(item.geometry.location.lat().toFixed(5), item.geometry.location.lng().toFixed(5));
305
306							return function() {
307								document.getElementById(mapId).value = mapValue;
308								marker.setPosition(location);
309								map.setCenter(location);
310								document.getElementById('rsform_geolocation'+id).style.display = 'none';
311							}
312						})());
313
314						theli.appendChild(thea);
315						content.appendChild(theli);
316					}
317
318					document.getElementById('rsform_geolocation'+id).style.display = '';
319				}
320			});
321		}, 500);
322	}
323};
324
325RSFormPro.initGoogleMaps = function() {
326
327}
328RSFormPro.googleMapIds = [];
329
330RSFormPro.requestLocation = function() {
331	if (navigator && navigator.geolocation && navigator.geolocation.getCurrentPosition) {
332		navigator.geolocation.getCurrentPosition(function(position){
333			var id, map, marker;
334
335			for (var i = 0; i < RSFormPro.googleMapIds.length; i++)
336			{
337				id = RSFormPro.googleMapIds[i];
338				map = window['rsformmap' + id];
339				marker = window['rsformmarker' + id];
340
341				map.setCenter({lat: position.coords.latitude, lng: position.coords.longitude});
342				marker.setPosition({lat: position.coords.latitude, lng: position.coords.longitude});
343				google.maps.event.trigger(marker, 'drag');
344			}
345		});
346	}
347};
348
349RSFormPro.disableInvalidDates = function() {
350    document.addEventListener('DOMContentLoaded', function(){
351        var fields = document.querySelectorAll('[data-rsfp-disable-invalid-dates]');
352        if (fields.length > 0) {
353            for (var i = 0; i < fields.length; i++) {
354                var field = fields[i];
355                (function (field) {
356                    field.addEventListener('change', function(){
357                        var fieldName = this.getAttribute('data-rsfp-disable-invalid-dates');
358
359                        var theDate = new Date(),
360                            day,
361                            index;
362
363                        for (day = 1; day <= 31; day++) {
364                            var year 	= parseInt(document.getElementById(fieldName + 'y').value);
365                            var month 	= parseInt(document.getElementById(fieldName + 'm').value) - 1;
366
367                            index = day - 1;
368                            if (document.getElementById(fieldName + 'd').options[0].value == '') {
369                                index++;
370                            }
371                            document.getElementById(fieldName + 'd').options[index].disabled = false;
372                            if (!isNaN(year) && !isNaN(month)) {
373                                theDate.setFullYear(year, month, day);
374
375                                if (theDate.getDate() != day || theDate.getMonth() != month) {
376                                    document.getElementById(fieldName + 'd').options[index].disabled = true;
377                                }
378                            }
379                        }
380                        if (document.getElementById(fieldName + 'd').options[document.getElementById(fieldName + 'd').selectedIndex].disabled == true) {
381                            for (day = 31; day >= 28; day--) {
382                                index = day - 1;
383                                if (document.getElementById(fieldName + 'd').options[0].value == '') {
384                                    index++;
385                                }
386                                if (document.getElementById(fieldName + 'd').options[index].disabled == false) {
387                                    document.getElementById(fieldName + 'd').value = day;
388                                    break;
389                                }
390                            }
391                        }
392                    });
393                }(field));
394            }
395        }
396    });
397};
398
399RSFormPro.addMoreFiles = function(button) {
400	var previousElement = button.previousElementSibling;
401	var previousInputs = previousElement.getElementsByTagName('input');
402	var originalInput;
403	if (previousInputs.length)
404	{
405		for (var k = 0; k < previousInputs.length; k++)
406		{
407			if (previousInputs[k].type && previousInputs[k].type.toUpperCase() === 'FILE')
408			{
409				originalInput = previousInputs[k];
410				break;
411			}
412		}
413	}
414
415	var clone = previousElement.cloneNode(true);
416	var inputs = clone.getElementsByTagName('input');
417	if (inputs.length)
418	{
419		for (var i = 0; i < inputs.length; i++)
420		{
421			if (inputs[i].type && inputs[i].type.toUpperCase() === 'FILE')
422			{
423				var fieldName = inputs[i].getAttribute('id');
424				inputs[i].value = '';
425
426				if (originalInput)
427				{
428					RSFormProUtils.addEvent(inputs[i], 'change', function() {
429						RSFormPro.triggerEvent(originalInput, 'change');
430					});
431				}
432			}
433		}
434	}
435
436	var images = clone.getElementsByTagName('img');
437	if (images.length)
438	{
439		for (var j = 0; j < images.length; j++)
440		{
441			if (RSFormProUtils.hasClass(images[j], 'rsfp-image-polaroid'))
442			{
443				images[j].parentNode.parentNode.removeChild(images[j].parentNode);
444			}
445		}
446	}
447
448	button.parentNode.appendChild(clone);
449
450	var maxFiles = parseInt(button.getAttribute('data-rsfp-maxfiles'));
451	if (maxFiles > 0)
452	{
453		if (RSFormPro.getFieldsByName(button.getAttribute('data-rsfp-formid'), fieldName).length / 2 >= maxFiles)
454		{
455			button.disabled = true;
456		}
457	}
458};
459
460RSFormPro.openImageModal = function(element) {
461	var modal = document.createElement('div');
462	modal.setAttribute('class', 'rsfp-modal');
463
464	var close = document.createElement('span');
465	close.innerHTML = '&times;';
466	close.setAttribute('class', 'rsfp-modal-close-button');
467	modal.onclick = close.onclick = function() {
468		modal.parentNode.removeChild(modal);
469	};
470
471	var img = document.createElement('img');
472	img.setAttribute('class', 'rsfp-modal-image');
473	img.setAttribute('src', element.getAttribute('src'));
474
475	var caption = document.createElement('div');
476	caption.setAttribute('class', 'rsfp-modal-caption');
477	caption.innerHTML = element.getAttribute('alt');
478
479	modal.appendChild(close);
480	modal.appendChild(img);
481	modal.appendChild(caption);
482
483	document.getElementsByTagName('body')[0].appendChild(modal);
484
485	modal.style.display = 'block';
486}
487
488RSFormPro.loadImage = function(input) {
489	if ('files' in input && typeof FileReader === 'function')
490	{
491		var file, reader;
492
493		var images = input.parentNode.querySelectorAll('.rsfp-image-container');
494
495		for (var j = 0; j < images.length; j++)
496		{
497			images[j].parentNode.removeChild(images[j]);
498		}
499
500		for (var i = 0; i < input.files.length; i++)
501		{
502			file = input.files[i];
503
504			reader = new FileReader();
505			reader.onload = function(e) {
506				var div = document.createElement('div');
507				div.setAttribute('class', 'rsfp-image-container');
508
509				var img = document.createElement('img');
510				img.setAttribute('src', e.target.result);
511				img.setAttribute('alt', file.name);
512				img.setAttribute('title', file.name);
513				img.setAttribute('class', 'rsfp-image-polaroid');
514				img.onerror = function() {
515					img.src = "data:image/svg+xml,%3Csvg role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 8C119.034 8 8 119.033 8 256s111.034 248 248 248 248-111.034 248-248S392.967 8 256 8zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676zM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676z'%3E%3C/path%3E%3C/svg%3E";
516					img.onclick = false;
517				};
518				img.onclick = function() {
519					RSFormPro.openImageModal(this);
520				};
521
522				div.appendChild(img);
523
524				input.parentNode.insertBefore(div, input.nextSibling);
525			};
526
527			reader.readAsDataURL(file);
528		}
529	}
530};
531
532/* Number functions */
533
534RSFormPro.formatNumber = function(number, decimals, dec_point, thousands_sep) {
535	var n = number, prec = decimals;
536	n = !isFinite(+n) ? 0 : +n;
537	prec = !isFinite(+prec) ? 0 : Math.abs(prec);
538	var sep = (typeof thousands_sep == "undefined") ? ',' : thousands_sep;
539	var dec = (typeof dec_point == "undefined") ? '.' : dec_point;
540
541	var s = (prec > 0) ? n.toFixed(prec) : Math.round(n).toFixed(prec); //fix for IE parseFloat(0.55).toFixed(0) = 0;
542
543	var abs = Math.abs(n).toFixed(prec);
544	var _, i;
545
546	if (abs >= 1000) {
547		_ = abs.split(/\D/);
548		i = _[0].length % 3 || 3;
549
550		_[0] = s.slice(0,i + (n < 0)) +
551			_[0].slice(i).replace(/(\d{3})/g, sep+'$1');
552
553		s = _.join(dec);
554	} else {
555		s = s.replace('.', dec);
556	}
557
558	return s;
559};
560
561RSFormPro.toNumber = function(number, decimal, thousands, decimals) {
562	// Remove decimals first
563	if (parseInt(decimals) > 0 && number.lastIndexOf(decimal) > -1) {
564		var index = number.lastIndexOf(decimal);
565		number = number.substring(0, index) + 'DECIMALS' + number.substring(index + 1);
566	}
567
568	// Remove thousands separator
569	if (number.indexOf(thousands) > -1) {
570		number = number.split(thousands).join('');
571	}
572
573	number = number.split('DECIMALS').join('.');
574	return parseFloat(number);
575};
576
577/* Form and element functions */
578
579RSFormPro.getForm = function(formId) {
580	if (typeof RSFormPro.Forms[formId] == 'undefined') {
581		var formIds = document.getElementsByName('form[formId]');
582		for (var i=0; i<formIds.length; i++)
583		{
584			if (parseInt(formIds[i].value) != parseInt(formId))
585				continue;
586
587			var form = formIds[i].parentNode;
588			if (form.tagName == 'FORM' || form.nodeName == 'FORM') {
589				RSFormPro.Forms[formId] = form;
590				return form;
591			}
592
593			while (form.parentNode)
594			{
595				form = form.parentNode;
596				if (form.tagName == 'FORM' || form.nodeName == 'FORM') {
597					RSFormPro.Forms[formId] = form;
598					return form;
599				}
600			}
601		}
602	}
603
604	return RSFormPro.Forms[formId];
605};
606
607RSFormPro.getValue = function(formId, name) {
608	var form	= RSFormPro.getForm(formId);
609	var values	= [];
610
611	if (typeof form != 'undefined')
612	{
613		for (var i = 0; i < form.elements.length; i++)
614		{
615			var element = form.elements[i];
616			var tagName = element.tagName || element.nodeName;
617
618			switch (tagName)
619			{
620				case 'INPUT':
621					if (element.type)
622						switch (element.type.toUpperCase())
623						{
624							case 'TEXT':
625							case 'NUMBER':
626							case 'HIDDEN':
627								if (!element.name || element.name != 'form[' + name + ']') continue;
628								
629								if (typeof RSFormPro.YUICalendar != 'undefined' &&
630									typeof RSFormPro.YUICalendar.calendars[formId] != 'undefined' &&
631									typeof RSFormPro.YUICalendar.calendars[formId][name] != 'undefined')
632									{
633										var selectedDate = new Date(RSFormPro.YUICalendar.calendars[formId][name].getSelectedDates()[0]);
634										return (selectedDate.getTime() / 1000).toString();
635									}
636								
637								if (typeof RSFormPro.jQueryCalendar != 'undefined' &&
638									typeof RSFormPro.jQueryCalendar.calendars[formId] != 'undefined' &&
639									typeof RSFormPro.jQueryCalendar.calendars[formId][name] != 'undefined')
640									{
641										var tmpDate = RSFormPro.jQueryCalendar.calendars[formId][name].calendarInstance.getValue();
642
643										if (RSFormPro.jQueryCalendar.calendars[formId][name].hiddenFormat.indexOf('HH:mm') === -1)
644										{
645											tmpDate.setHours(0, 0, 0, 0);
646										}
647
648										return parseInt(tmpDate.getTime() / 1000).toString();
649									}
650
651                                if (element.hasOwnProperty('rsfpGetValue'))
652                                {
653                                    return element.rsfpGetValue();
654                                }
655								
656								return element.value;
657								break;
658
659							case 'RADIO':
660								if (!element.name || (element.name !== 'form[' + name + ']' && element.name.substring(0, ('form[' + name + ']').length) !== 'form[' + name + ']')) continue;
661
662								if (element.checked) {
663									values.push(element.value);
664								}
665								break;
666
667							case 'CHECKBOX':
668								if (!element.name || element.name != 'form[' + name + '][]') continue;
669								if (element.checked == true) {
670									values.push(element.value);
671								}
672								break;
673						}
674					break;
675
676				case 'SELECT':
677					if (!element.name || element.name != 'form[' + name + '][]') continue;
678
679					if (element.options)
680						for (var o=0; o<element.options.length; o++)
681							if (element.options[o].selected)
682							{
683								values.push(element.options[o].value);
684							}
685					break;
686			}
687		}
688	}
689
690	return values;
691};
692
693RSFormPro.getElementByType = function(formId, type) {
694	var form	= RSFormPro.getForm(formId);
695	type = type.toUpperCase();
696	var elements	= [];
697
698	if (typeof form != 'undefined')
699	{
700		for (var i = 0; i < form.elements.length; i++)
701		{
702			var element = form.elements[i];
703			var tagName = element.tagName || element.nodeName;
704			switch (tagName)
705			{
706				case 'INPUT':
707				case 'BUTTON':
708					if (element.type.toUpperCase() == type) {
709						elements.push(element);
710					}
711					break;
712
713				case 'SELECT':
714				case 'TEXTAREA':
715					if (type == 'SELECT' || type == 'TEXTAREA') {
716						elements.push(element);
717					}
718					break;
719			}
720		}
721	}
722
723	return elements;
724};
725
726RSFormPro.resettingValues = false;
727
728RSFormPro.resetValues = function(items) {
729	if (RSFormPro.resettingValues)
730	{
731		return true;
732	}
733
734	var element, tagName;
735	try
736	{
737		for (var i = 0; i < items.length; i++)
738		{
739			element = items[i];
740			tagName = element.tagName || element.nodeName;
741
742			switch (tagName)
743			{
744				case 'INPUT':
745					if (element.type)
746					{
747						switch (element.type.toUpperCase())
748						{
749							case 'CHECKBOX':
750							case 'RADIO':
751								if (element.defaultChecked !== element.checked)
752								{
753									element.checked = element.defaultChecked;
754									RSFormPro.triggerEvent(element, 'change');
755								}
756							break;
757							
758							case 'NUMBER':
759							case 'TEXT':
760								if (element.defaultValue !== element.value)
761								{
762									element.value = element.defaultValue;
763
764									if (element.id)
765									{
766										// Range Slider
767										if (element.id.indexOf('rs-range-slider') === 0 && typeof jQuery !== 'undefined')
768										{
769											jQuery(element).data('ionRangeSlider').reset();
770										}
771
772										// Date and Time Picker
773										if (element.id.indexOf('txtjQcal') === 0 && typeof jQuery !== 'undefined' && typeof RSFormPro.jQueryCalendar !== 'undefined')
774										{
775											jQuery(element).datetimepicker('reset');
776										}
777
778										// Calendar
779										if (element.id.indexOf('txtcal') === 0 && typeof RSFormPro.YUICalendar !== 'undefined')
780										{
781											var match = element.id.match(/^txtcal([0-9]+)_[0-9]+$/);
782											if (match.length === 2)
783											{
784												var formId = match[1];
785												var calendarName = element.name.match(/^form\[(.*)\]$/)[1];
786
787												if (typeof RSFormPro.YUICalendar.calendars[formId][calendarName] !== 'undefined')
788												{
789													RSFormPro.YUICalendar.calendars[formId][calendarName].reset();
790												}
791											}
792										}
793									}
794
795									RSFormPro.triggerEvent(element, 'change');
796									RSFormPro.triggerEvent(element, 'input');
797								}
798							break;
799						}
800					}
801				break;
802				
803				case 'TEXTAREA':
804					if (element.defaultValue !== element.value)
805					{
806						element.value = element.defaultValue;
807
808						RSFormPro.triggerEvent(element, 'change');
809						RSFormPro.triggerEvent(element, 'input');
810					}
811				break;
812
813				case 'SELECT':
814					if (element.options)
815					{
816						var needsChange = false;
817						var unselected = [];
818						for (var o = 0; o < element.options.length; o++) {
819							if (element.options[o].defaultSelected !== element.options[o].selected)
820							{
821								needsChange = true;
822								element.options[o].selected = element.options[o].defaultSelected;
823							}
824
825							if (!element.options[o].defaultSelected) {
826								unselected.push(o);
827							}
828						}
829						
830						// in safari something must be selected
831						if (element.options.length === unselected.length) {
832							element.selectedIndex = 0;
833						}
834
835						if (needsChange)
836						{
837							RSFormPro.triggerEvent(element, 'change');
838						}
839					}
840				break;
841			}
842		}
843	}
844	catch (err) {}
845};
846
847RSFormPro.triggerEvent = function(element, type) {
848	try {
849		element.dispatchEvent(new Event(type));
850	} catch (e) {}
851};
852
853RSFormPro.isChecked = function(formId, name, value) {
854	var isChecked 	= false;
855	var form 		= RSFormPro.getForm(formId);
856
857	if (typeof form != 'undefined')
858	{
859		primary_loop:
860			for (var i=0; i<form.elements.length; i++)
861			{
862				var element = form.elements[i];
863				var tagName = element.tagName || element.nodeName;
864
865				switch (tagName)
866				{
867					case 'INPUT':
868						if (element.type)
869							switch (element.type.toUpperCase())
870							{
871								default:
872									if (!element.name || element.name != 'form[' + name + ']') continue;
873									if (!element.value) continue;
874
875									if (element.value == value)
876									{
877										isChecked = true;
878										break primary_loop;
879									}
880
881									break;
882								case 'RADIO':
883									if (!element.name || element.name != 'form[' + name + ']') continue;
884									if (element.checked == true && element.value == value)
885									{
886										isChecked = true;
887										break primary_loop;
888									}
889									break;
890
891								case 'CHECKBOX':
892									if (!element.name || element.name != 'form[' + name + '][]') continue;
893									if (element.checked == true && element.value == value)
894									{
895										isChecked = true;
896										break primary_loop;
897									}
898									break;
899							}
900						break;
901
902					case 'SELECT':
903						if (!element.name || element.name != 'form[' + name + '][]') continue;
904
905						if (element.options)
906							for (var o=0; o<element.options.length; o++)
907								if (element.options[o].selected && element.options[o].value == value)
908								{
909									isChecked = true;
910									break primary_loop;
911								}
912						break;
913				}
914			}
915	}
916
917	return isChecked;
918};
919
920RSFormPro.getBlock = function(formId, block) {
921	var form 	 = RSFormPro.getForm(formId);
922	var possible = false;
923	var blocks, current_block;
924
925	if (typeof form != 'undefined') {
926		if (blocks = getElementsByClassName('rsform-block')) {
927			for (i=0; i<blocks.length; i++) {
928				var classes = blocks[i].className.split(' ');
929				for (c=0; c<classes.length; c++) {
930					if (classes[c] == 'rsform-block-' + block) {
931						if (blocks[i].parentNode) {
932							current_block = blocks[i];
933							if (current_block == form)
934								return [ blocks[i] ];
935
936							while (current_block.parentNode) {
937								current_block = current_block.parentNode;
938								if (current_block == form)
939									return [ blocks[i] ];
940							}
941						}
942
943						possible = [ blocks[i] ];
944					}
945				}
946			}
947		}
948	}
949
950	return possible;
951};
952
953RSFormPro.getFieldsByName = function(formId, name) {
954	var form 	= RSFormPro.getForm(formId);
955	var results = [];
956	var pushed  = false;
957
958	if (typeof form != 'undefined') {
959		for (var i=0; i<form.elements.length; i++) {
960			var element = form.elements[i];
961			pushed = false;
962			if (element.name && (
963					// single fields
964					element.name == 'form[' + name + ']' ||
965					// multiple fields
966					element.name == 'form[' + name + '][]' ||
967					// new field - Birthday field
968					element.name == 'form[' + name + '][d]' ||
969					element.name == 'form[' + name + '][m]' ||
970					element.name == 'form[' + name + '][y]'
971				)) {
972				results.push(element);
973				pushed = true;
974			}
975
976			if (!pushed)
977			{
978				if (element.name && element.getAttribute('data-rsfpsurveytable-answer') && element.name.substring(0, ('form[' + name + ']').length) === 'form[' + name + ']')
979				{
980					results.push(element);
981				}
982			}
983
984			if (pushed) {
985				// for calendar
986				if (element.id && element.id.indexOf('txtcal') > -1) {
987					var suffix = element.id.replace('txtcal', '');
988					if (document.getElementById('btn' + suffix))
989					{
990						results.push(document.getElementById('btn' + suffix));
991					}
992				}
993				// for labels (radio, checkbox)
994				var labels = form.getElementsByTagName('label');
995				for (var l=0; l<labels.length; l++) {
996					if (labels[l].htmlFor && labels[l].htmlFor == element.id)
997						results.push(labels[l]);
998				}
999			}
1000		}
1001	}
1002
1003	return results;
1004};
1005
1006RSFormPro.showCounter = function(element, id) {
1007	var current = element.value.length;
1008	var result;
1009	if (element.maxLength > 0)
1010	{
1011		result = current + '/' + element.maxLength;
1012	}
1013	else
1014	{
1015		result = current;
1016	}
1017	
1018	document.getElementById('rsfp-counter-' + id).innerText = result;
1019};
1020
1021RSFormPro.limitSelections = function(formId, field, max) {
1022    RSFormProUtils.addEvent(window, 'load', function() {
1023        var fields = RSFormPro.getFieldsByName(formId, field);
1024        var objects = [];
1025        var i;
1026        var tagName;
1027
1028        if (!fields || !fields.length) {
1029            return;
1030        }
1031
1032        for (i = 0; i < fields.length; i++) {
1033            tagName = fields[i].tagName || fields[i].nodeName;
1034            tagName = tagName.toUpperCase();
1035
1036            if (tagName === 'INPUT' && fields[i].type && fields[i].type.toUpperCase() === 'CHECKBOX' && !fields[i].disabled) {
1037                objects.push(fields[i]);
1038            }
1039        }
1040
1041        if (!objects.length) {
1042            return;
1043        }
1044
1045        function limitSelections() {
1046            var values = RSFormProUtils.getChecked(objects);
1047            RSFormProUtils.remAttr(objects, 'disabled');
1048            if (values && values.length > 0 && values.length >= max) {
1049                RSFormProUtils.setAttr(RSFormProUtils.getUnchecked(objects), 'disabled', true);
1050            }
1051		}
1052
1053        for (i = 0; i < objects.length; i++) {
1054            RSFormProUtils.addEvent(objects[i], 'change', limitSelections);
1055        }
1056
1057        limitSelections();
1058    });
1059};
1060
1061/*HTML5 simulators*/
1062
1063RSFormPro.HTML5 = {
1064	validation: function(formId){
1065		var form = RSFormPro.getForm(formId);
1066		var errorElements = [];
1067		var html5types = ['number', 'email', 'range', 'url', 'tel'];
1068		var multipleTypes = ['radio'];
1069
1070		var checkValidityExists = true;
1071		var checkValidityFunction;
1072		var needsCheck;
1073		var options;
1074		var page = 0;
1075		var componentId;
1076		var elementId;
1077		var match;
1078
1079		if (form.elements.length) {
1080			for (var i = 0; i < form.elements.length; i++) {
1081				if (!checkValidityExists) {
1082					break;
1083				}
1084
1085				needsCheck = false;
1086				checkValidityFunction = false;
1087
1088				// if the multiple form is present and also validation we will need to find in which page the element is located
1089				if (form.elements[i].type === 'button') {
1090					var onclick = form.elements[i].getAttribute('onclick');
1091					if (typeof onclick == 'string' && (onclick.indexOf('rsfp_changePage') > -1 || onclick.indexOf('RSFormPro.Pages.change') > -1)) {
1092						var countCommas = 0;
1093						var pos = onclick.indexOf(',');
1094						while (pos > -1) {
1095							++countCommas;
1096							pos = onclick.indexOf(',', ++pos);
1097						}
1098
1099						if (countCommas > 2) {
1100							page++;
1101						}
1102					}
1103				}
1104				if (form.elements[i].getAttribute('data-rsfp-phonenumber'))
1105				{
1106					options = JSON.parse(form.elements[i].getAttribute('data-rsfp-phonenumber'));
1107					needsCheck = form.elements[i].value.length > 0;
1108					if (options['validation'] === 'precise')
1109					{
1110						checkValidityFunction = function(el) { return intlTelInput.getInstance(el).isValidNumberPrecise(); }
1111					}
1112					else
1113					{
1114						checkValidityFunction = function(el) { return intlTelInput.getInstance(el).isValidNumber(); }
1115					}
1116				}
1117				else
1118				{
1119					needsCheck = html5types.indexOf(form.elements[i].type) > -1;
1120					if (typeof(form.elements[i].checkValidity) === 'function')
1121					{
1122						checkValidityFunction = function(el) { return el.checkValidity() };
1123					}
1124				}
1125				if (needsCheck) {
1126					if (typeof(checkValidityFunction) === 'function' && checkValidityExists) {
1127						if (!checkValidityFunction(form.elements[i])) {
1128							var elementObj = {
1129								field: form.elements[i],
1130								page: page
1131							};
1132							// try to get the componentId
1133							elementId = form.elements[i].getAttribute('id');
1134							if (multipleTypes.indexOf(form.elements[i].type) > -1)
1135							{
1136								if (match = form.elements[i].getAttribute('name').match(/form\[(.*)\]/))
1137								{
1138									elementId = match[1];
1139								}
1140							}
1141							componentId = RSFormPro.HTML5.getComponentId(formId, elementId);
1142
1143							if (componentId) {
1144								elementObj.componentId = componentId;
1145							}
1146
1147							errorElements.push(elementObj);
1148						}
1149					} else {
1150						checkValidityExists = false;
1151					}
1152				}
1153			}
1154		}
1155		return errorElements;
1156	},
1157
1158	componentIds: {},
1159
1160	getComponentId: function(formId, elementAlias) {
1161		if (typeof RSFormPro.HTML5.componentIds[formId] == 'undefined') {
1162			RSFormPro.HTML5.componentIds[formId] = {};
1163		}
1164
1165		if (typeof RSFormPro.HTML5.componentIds[formId][elementAlias] == 'undefined') {
1166			RSFormPro.HTML5.componentIds[formId][elementAlias] = false;
1167			var block = RSFormPro.getBlock(formId, RSFormProUtils.getAlias(elementAlias));
1168
1169			if (typeof block[0] !== 'undefined') {
1170				var componentIdBlock;
1171
1172				componentIdBlock = RSFormProUtils.getElementsByClassName('formNoError', 'span', block[0]);
1173				if (componentIdBlock.length === 0) {
1174					componentIdBlock = RSFormProUtils.getElementsByClassName('formError', 'span', block[0]);
1175				}
1176
1177				if (componentIdBlock.length > 0) {
1178					var componentId = componentIdBlock[0].getAttribute('id');
1179					RSFormPro.HTML5.componentIds[formId][elementAlias] = componentId.replace('component', '');
1180				}
1181			}
1182		}
1183
1184		return RSFormPro.HTML5.componentIds[formId][elementAlias];
1185	}
1186};
1187
1188/* Pagination functions */
1189
1190RSFormPro.Pages = {
1191	change: function(formId, page, totalPages, validate, errorClasses) {
1192		// callback functions if next page is clicked
1193		var direction = RSFormPro.Pages.checkDirection(formId, page);
1194		if (direction == 'next') {
1195			RSFormPro.callbacks.runCallback(formId, 'nextPage');
1196		}
1197		RSFormPro.callbacks.runCallback(formId, 'changePage');
1198		
1199		var thePage;
1200
1201		if (validate) {
1202			var form = RSFormPro.getForm(formId);
1203			if (!RSFormPro.Ajax.validate(form, page, errorClasses, totalPages)) {
1204				return false;
1205			}
1206		}
1207
1208		for (var i = 0; i <= totalPages; i++) {
1209			thePage = document.getElementById('rsform_' + formId + '_page_' + i);
1210			if (thePage) {
1211				RSFormPro.Pages.hide(thePage);
1212			}
1213		}
1214
1215		thePage = document.getElementById('rsform_' + formId + '_page_' + page);
1216		if (thePage) {
1217			RSFormPro.Pages.show(thePage);
1218			try {
1219				var func = window["rsfp_showProgress_" + formId];
1220				if (typeof func == "function") {
1221					func(page);
1222				}
1223			}
1224			catch (err) {}
1225		}
1226	},
1227	hide: function(thePage) {
1228		RSFormProUtils.addClass(thePage, 'formHidden');
1229	},
1230	show: function(thePage) {
1231		RSFormProUtils.removeClass(thePage, 'formHidden');
1232        var rsform, formId, page, pageNumber;
1233
1234        [rsform, formId, page, pageNumber] = thePage.id.split('_');
1235
1236        if (RSFormPro.scrollPage && !RSFormPro.initialPage) {
1237            window.scrollTo(0, findPos(RSFormPro.getForm(formId)));
1238
1239            function findPos(obj) {
1240                var curtop = 0;
1241                if (obj.offsetParent) {
1242                    do {
1243                        curtop += obj.offsetTop;
1244                    } while (obj = obj.offsetParent);
1245                    return [curtop - RSFormPro.scrollPageOffset];
1246                }
1247            }
1248        }
1249	},
1250	
1251	checkDirection : function(formId, page) {
1252		var base = RSFormPro.Pages;
1253		if (typeof base.history[formId] == 'undefined') {
1254			base.history[formId] = page;
1255			return 'next';
1256		} else {
1257			var direction;
1258			if (base.history[formId] <= page ) { 
1259				direction = 'next';
1260			} else {
1261				direction = 'prev';
1262			}
1263			base.history[formId] = page;
1264			
1265			return direction;
1266		}
1267	},	
1268	history: {}
1269};
1270
1271/* Condition functions */
1272RSFormPro.Conditions = {
1273	add: function(formId, name, fnCondition) {
1274		var form = RSFormPro.getForm(formId);
1275
1276		if (typeof form != 'undefined') {
1277			for (var i = 0; i < form.elements.length; i++) {
1278				var element = form.elements[i];
1279				if (element.name && (element.name == 'form[' + name + ']' || element.name == 'form[' + name + '][]')) {
1280					RSFormProUtils.addEvent(element, 'change', function() {
1281						fnCondition();
1282					});
1283				}
1284			}
1285		}
1286	},
1287	run: function(condition) {
1288		var formId = condition.form_id,
1289            conditions = [],
1290            items = [],
1291			detail, isChecked, displayValue, match;
1292
1293		var i, c;
1294
1295		if (typeof condition.details === 'object')
1296		{
1297			for (i = 0; i < condition.details.length; i++)
1298			{
1299				detail = condition.details[i];
1300                isChecked = RSFormPro.isChecked(formId, detail.ComponentName, detail.value);
1301                conditions.push(isChecked === (detail.operator === 'is'));
1302			}
1303
1304			items = [];
1305
1306			if (condition.ComponentNames)
1307			{
1308				for (c = 0; c < condition.ComponentNames.length; c++)
1309				{
1310					if (parseInt(condition.block) === 1)
1311					{
1312						items = items.concat(RSFormPro.getBlock(formId, RSFormProUtils.getAlias(condition.ComponentNames[c])));
1313					}
1314					else
1315					{
1316						items = items.concat(RSFormPro.getFieldsByName(formId, condition.ComponentNames[c]));
1317					}
1318				}
1319			}
1320
1321			if (items.length > 0)
1322			{
1323				if (condition.condition === 'all')
1324				{
1325                    // && conditions need all elements of the Array to be true -> no false in Array
1326                    match = conditions.indexOf(false) === -1;
1327				}
1328				else
1329				{
1330                    // || conditions need only one element to be true -> one true in array
1331					match = conditions.indexOf(true) > -1;
1332				}
1333
1334                if (match)
1335                {
1336                    displayValue = condition.action === 'show' ? '' : 'none';
1337                }
1338                else
1339                {
1340                    displayValue = condition.action === 'show' ? 'none' : '';
1341                }
1342
1343				RSFormProUtils.setDisplay(items, displayValue);
1344                if (displayValue === 'none')
1345				{
1346					if (condition.ComponentNames && condition.ComponentNames.length > 0)
1347					{
1348						for (c = 0; c < condition.ComponentNames.length; c++)
1349						{
1350							RSFormPro.resetValues(RSFormPro.getFieldsByName(formId, condition.ComponentNames[c]));
1351						}
1352					}
1353				}
1354			}
1355		}
1356	},
1357	runAll: function(formId) {
1358		var func = window['rsfp_runAllConditions' + formId];
1359		if (typeof func === 'function') {
1360			func();
1361		}
1362	},
1363	addReset: function(formId) {
1364		var resetElements = RSFormPro.getElementByType(formId, 'reset');
1365		if (resetElements.length > 0)
1366		{
1367			for (var i = 0; i < resetElements.length; i++)
1368			{
1369				RSFormProUtils.addEvent(resetElements[i], 'click', function() {
1370					window.setTimeout(function() {
1371						RSFormPro.Conditions.runAll(formId);
1372					}, 1);
1373				});
1374			}
1375		}
1376	},
1377	delayRun: function(formId) {
1378		var func = window['rsfp_runAllConditions' + formId];
1379		if (typeof func === 'function') {
1380			RSFormProUtils.addEvent(window, 'load', func);
1381		}
1382	}
1383};
1384
1385/* Calculation functions */
1386
1387RSFormPro.Calculations = {
1388	toDays: function(seconds) {
1389		return Math.round(parseFloat(seconds) / 86400);
1390	},
1391	toHours: function(seconds) {
1392		return Math.round(parseFloat(seconds) / 86400 * 24);
1393	},
1394	toMinutes: function(seconds) {
1395        return Math.round(parseFloat(seconds) / 86400 * 24 * 60);
1396    },
1397	addEvents: function(formId, fields) {
1398		RSFormProUtils.addEvent(window, 'load', function(){
1399            window.setTimeout(function() {
1400                RSFormPro.Calculations._addEvents(formId, fields);
1401            })
1402		});
1403	},
1404	_addEvents: function(formId, fields) {
1405		var func 		= window['rsfp_Calculations' + formId];
1406		var thefields	= fields ? fields : RSFormProPrices;
1407		var event 		= 'change';
1408		var objects, tagName;
1409		
1410		var resetElements = RSFormPro.getElementByType(formId, 'reset');
1411		if (resetElements.length > 0)
1412		{
1413			for (var i = 0; i < resetElements.length; i++)
1414			{
1415				RSFormProUtils.addEvent(resetElements[i], 'click', function() {
1416					if (typeof func === 'function') {
1417						window.setTimeout(func, 1);
1418					}
1419				});
1420			}
1421		}
1422
1423		for (var field in thefields) {
1424			if (!thefields.hasOwnProperty(field)) {
1425				continue;
1426			}
1427			field = field.replace(formId+'_','');
1428			objects = RSFormPro.getFieldsByName(formId,field);
1429			for(i = 0; i < objects.length;i++) {
1430				tagName = objects[i].tagName || objects[i].nodeName;
1431
1432				if (tagName === 'INPUT' || tagName === 'SELECT') {
1433					event = 'change';
1434					if (tagName === 'INPUT' && typeof objects[i].type == 'string') {
1435						switch (objects[i].type.toUpperCase())
1436						{
1437							default:
1438								event = 'change';
1439							break;
1440							
1441							case 'NUMBER':
1442							case 'TEXT':
1443								event = 'input';
1444								if (typeof RSFormPro.jQueryCalendar !== 'undefined' &&
1445									typeof RSFormPro.jQueryCalendar.calendars[formId] !== 'undefined' &&
1446									typeof RSFormPro.jQueryCalendar.calendars[formId][field] !== 'undefined')
1447									{
1448										RSFormPro.jQueryCalendar.calendars[formId][field].calendarInstance.setOptions({onChangeDateTime: function() {
1449											if (typeof func === 'function') {
1450												func();
1451											}
1452										}});
1453									}
1454								
1455								if (typeof RSFormPro.YUICalendar !== 'undefined' &&
1456									typeof RSFormPro.YUICalendar.calendars[formId] !== 'undefined' &&
1457									typeof RSFormPro.YUICalendar.calendars[formId][field] !== 'undefined')
1458									{
1459										RSFormPro.YUICalendar.calendars[formId][field].selectEvent.subscribe(function() {
1460											if (typeof func === 'function') {
1461												func();
1462											}
1463										}, RSFormPro.YUICalendar.calendars[formId][field], true);
1464									}
1465
1466								if (objects[i].hasOwnProperty('rsfpOnChange'))
1467								{
1468									objects[i].rsfpOnChange(func);
1469								}
1470							break;
1471						}
1472					}
1473
1474					RSFormProUtils.addEvent(objects[i], event, function() {
1475						if (typeof func === 'function') {
1476							func();
1477						}
1478					});
1479				}
1480			}
1481		}
1482	}
1483};
1484
1485/* AJAX functions */
1486RSFormPro.Ajax = {
1487	Wait: false,
1488	URL: false,
1489	Params: {},
1490	getParamsObject: function() {
1491		return {
1492			vars: [],
1493			push: function(str) {
1494				return this.vars.push(str);
1495			},
1496			
1497			indexOf: function(str) {
1498				return this.vars.join('&').indexOf(str);
1499			},
1500			
1501			replace: function(r, w) {
1502				this.vars = this.vars.join('&').replace(r, w).split('&');
1503				
1504				return this.vars.join('&');
1505			},
1506			
1507			toString: function() {
1508				return this.vars.join('&');
1509			}
1510		};
1511	},
1512	getXHR: function() {
1513		try {
1514			return new window.XMLHttpRequest();
1515		} catch ( e ) {}
1516	},
1517	getXHRLegacy: function() {
1518		return {
1519			send: function(data)
1520			{
1521				if (data === RSFormPro.Ajax.Params)
1522				{
1523					data = data.toString();
1524				}
1525				
1526				return RSFormPro.Ajax.xhr.send(data);
1527			}
1528		}
1529	},
1530	displayValidationErrors: function(formComponents, task, formId, data) {
1531		if (task == 'afterSend') {
1532			var ids, i, j, id, formComponent, elementBlock;
1533			var parentErrorClass = typeof data.parentErrorClass !== 'undefined' && data.parentErrorClass.length > 0 ? data.parentErrorClass : false;
1534			var fieldErrorClass = typeof data.fieldErrorClass !== 'undefined' && data.fieldErrorClass.length > 0 ? data.fieldErrorClass : false;
1535
1536			ids = data.response[0].split(',');
1537			for (i = 0; i < ids.length; i++)
1538			{
1539				id = parseInt(ids[i]);
1540
1541				if (isNaN(id))
1542				{
1543					continue;
1544				}
1545
1546				if (typeof formComponents[id] === 'undefined')
1547				{
1548					continue;
1549				}
1550
1551				formComponent = RSFormPro.getFieldsByName(formId, formComponents[id]);
1552
1553				if (!formComponent || formComponent.length < 1)
1554				{
1555					continue;
1556				}
1557
1558				for (j = 0; j < formComponent.length; j++)
1559				{
1560					if (formComponent[j])
1561					{
1562						RSFormProUtils.removeClass(formComponent[j], 'rsform-error');
1563						formComponent[j].removeAttribute('aria-invalid');
1564						if (formComponent[j].getAttribute('aria-describedby') === 'component' + id) {
1565							formComponent[j].removeAttribute('aria-describedby');
1566						}
1567
1568						if (parentErrorClass)
1569						{
1570							try
1571							{
1572								if (elementBlock = RSFormPro.getBlock(formId, RSFormProUtils.getAlias(formComponents[id])))
1573								{
1574									RSFormProUtils.removeClass(elementBlock[0], parentErrorClass);
1575								}
1576							}
1577							catch (err) {}
1578						}
1579
1580						if (fieldErrorClass)
1581						{
1582							RSFormProUtils.removeClass(formComponent[j], fieldErrorClass);
1583						}
1584					}
1585				}
1586			}
1587
1588			ids = data.response[1].split(',');
1589			var doFocus = false;
1590			for (i = 0; i < ids.length; i++)
1591			{
1592				id = parseInt(ids[i]);
1593				
1594				if (isNaN(id))
1595				{
1596					continue;
1597				}
1598				
1599				if (typeof formComponents[id] === 'undefined')
1600				{
1601					continue;
1602				}
1603				
1604				formComponent = RSFormPro.getFieldsByName(formId, formComponents[id]);
1605
1606				if (!formComponent || formComponent.length < 1)
1607				{
1608					continue;
1609				}
1610				
1611				for (j = 0; j < formComponent.length; j++)
1612				{
1613					if (formComponent[j])
1614					{
1615						RSFormProUtils.addClass(formComponent[j], 'rsform-error');
1616						
1617						if (parentErrorClass)
1618						{
1619							try
1620							{
1621								if (elementBlock = RSFormPro.getBlock(formId, RSFormProUtils.getAlias(formComponents[id])))
1622								{
1623									RSFormProUtils.addClass(elementBlock[0], parentErrorClass);
1624								}
1625							}
1626							catch (err) {}
1627						}
1628
1629						if (fieldErrorClass)
1630						{
1631							RSFormProUtils.addClass(formComponent[j], fieldErrorClass);
1632						}
1633
1634						if (['INPUT', 'SELECT', 'TEXTAREA'].indexOf(formComponent[j].nodeName) > -1)
1635						{
1636							if (formComponent[j].getAttribute('type') !== 'button') {
1637								formComponent[j].setAttribute('aria-invalid', 'true');
1638								formComponent[j].setAttribute('aria-describedby', 'component' + id);
1639
1640								if (!doFocus && typeof formComponent[j].focus === 'function') {
1641									formComponent[j].focus();
1642									doFocus = true;
1643								}
1644							}
1645						}
1646					}
1647				}
1648			}
1649			
1650			// scroll to first error elment
1651			if (RSFormPro.scrollToError){
1652				RSFormPro.gotoErrorElement(formId);
1653			}
1654		}
1655	},
1656	validate: function(form, page, errorClasses, totalPages) {
1657		try {
1658			var el = form.elements.length;
1659		} catch (err) {
1660			form = this;
1661		}
1662
1663		RSFormPro.Ajax.xhr = RSFormPro.Ajax.getXHR();
1664		RSFormPro.Ajax.xmlHttp = RSFormPro.Ajax.getXHRLegacy();
1665		var url = 'index.php?option=com_rsform&task=ajaxValidate';
1666		if (typeof RSFormPro.Ajax.URL == 'string') {
1667			url = RSFormPro.Ajax.URL;
1668		}
1669		
1670		RSFormPro.Ajax.Params = RSFormPro.Ajax.getParamsObject();
1671
1672		var submits = [],
1673			errorFields = [],
1674			success = false,
1675			formId = form.elements['form[formId]'].value,
1676			totalJSDetectedPages = 0,
1677			i,
1678			j;
1679
1680		// File uploads AJAX validation variabiles
1681		var ajaxSkippedFileUploads = [],
1682			filesLength = 0,
1683			filesCollection = [],
1684			identicalFiles = [];
1685		
1686		if (typeof errorClasses != 'object')
1687		{
1688			errorClasses = {'parent': '', 'field': ''}
1689		}
1690
1691		for (i=0; i<form.elements.length; i++)
1692		{
1693			// try and detect total pages of the form
1694			if (form.elements[i].type == 'button') {
1695				var onclick = form.elements[i].getAttribute('onclick');
1696				if (typeof onclick === 'string' && (onclick.indexOf('rsfp_changePage') > -1 || onclick.indexOf('RSFormPro.Pages.change') > -1)) {
1697					var countCommas = 0;
1698					var pos = onclick.indexOf(',');
1699					while (pos > -1) {
1700						++countCommas;
1701						pos = onclick.indexOf(',', ++pos);
1702					}
1703
1704					if (countCommas > 2) {
1705						totalJSDetectedPages++;
1706					}
1707				}
1708			}
1709
1710			// don't send an empty value
1711			if (!form.elements[i].name) continue;
1712			if (form.elements[i].name.length == 0) continue;
1713			// check if the checkbox is checked
1714			if (form.elements[i].type == 'checkbox' && form.elements[i].checked == false) continue;
1715			// check if the radio is selected
1716			if (form.elements[i].type == 'radio' && form.elements[i].checked == false) continue;
1717
1718			if (form.elements[i].type == 'submit' && form.elements[i].getAttribute('data-disableonsubmit') == '1') {
1719				submits.push(form.elements[i]);
1720				form.elements[i].disabled = true;
1721			}
1722
1723			// check if form is a dropdown with multiple selections
1724			if (form.elements[i].type == 'select-multiple')
1725			{
1726				for (j = 0; j < form.elements[i].options.length; j++) {
1727					if (form.elements[i].options[j].selected) {
1728						RSFormPro.Ajax.Params.push(form.elements[i].name + '=' + encodeURIComponent(form.elements[i].options[j].value));
1729					}
1730				}
1731
1732				continue;
1733			}
1734
1735			if (form.elements[i].type == 'file')
1736			{
1737				if ('files' in form.elements[i])
1738				{
1739					try
1740					{
1741						if (RSFormPro.usePositioning)
1742						{
1743							if (form.elements[i].offsetParent !== document.getElementsByTagName('body')[0])
1744							{
1745								throw 'CONDITIONAL_HIDDEN';
1746							}
1747						}
1748						else
1749						{
1750							if (form.elements[i].offsetParent === null)
1751							{
1752								throw 'CONDITIONAL_HIDDEN';
1753							}
1754						}
1755
1756						if (form.elements[i].getAttribute('data-rsfp-skip-ajax') === 'true')
1757						{
1758							// Not already processed
1759							if (ajaxSkippedFileUploads.indexOf(form.elements[i].name) === -1)
1760							{
1761								// All fields are identical, make sure this code is only run once.
1762								ajaxSkippedFileUploads.push(form.elements[i].name);
1763
1764								// Get all identical fields
1765								identicalFiles = form.elements[form.elements[i].name];
1766
1767								filesLength = 0;
1768								filesCollection = [];
1769
1770								if (typeof identicalFiles === 'object')
1771								{
1772									// NodeList (multiple inputs)
1773									if (typeof identicalFiles.length !== 'undefined' && identicalFiles.length > 0)
1774									{
1775										for (var tmp = 0; tmp < identicalFiles.length; tmp++)
1776										{
1777											if (identicalFiles[tmp].files.length > 0)
1778											{
1779												filesLength += identicalFiles[tmp].files.length;
1780												filesCollection = filesCollection.concat(identicalFiles[tmp].files[0]);
1781											}
1782										}
1783									}
1784									else if (typeof identicalFiles.files !== 'undefined')
1785									{
1786										// Just one input
1787										filesLength += identicalFiles.files.length;
1788										filesCollection = filesCollection.concat(identicalFiles.files[0]);
1789									}
1790								}
1791							}
1792							else
1793							{
1794								throw 'AJAX_SKIPPED_FILE_UPLOAD';
1795							}
1796						}
1797						else
1798						{
1799							filesLength = form.elements[i].files.length;
1800							filesCollection = form.elements[i].files;
1801						}
1802
1803						if (filesLength === 0 && form.elements[i].getAttribute('data-rsfp-required') === 'true')
1804						{
1805							throw new RSFormPro.validationError('VALIDATION_ERROR', RSFormPro.Translations.translate(formId, form.elements[i].getAttribute('id'), 'VALIDATIONMESSAGE'));
1806						}
1807
1808						if (form.elements[i].getAttribute('data-rsfp-required') === 'true' || filesLength > 0)
1809						{
1810							if (form.elements[i].getAttribute('data-rsfp-minfiles'))
1811							{
1812								var minFiles = parseInt(form.elements[i].getAttribute('data-rsfp-minfiles'));
1813
1814								if (filesLength < minFiles)
1815								{
1816									throw new RSFormPro.validationError('VALIDATION_ERROR', RSFormProUtils.sprintf(RSFormPro.Translations.commonTranslate('COM_RSFORM_MIN
1816FILES_REQUIRED'), minFiles));
1817								}
1818							}
1819
1820							if (form.elements[i].getAttribute('data-rsfp-maxfiles'))
1821							{
1822								var maxFiles = parseInt(form.elements[i].getAttribute('data-rsfp-maxfiles'));
1823
1824								if (filesLength > maxFiles)
1825								{
1826									throw new RSFormPro.validationError('VALIDATION_ERROR', RSFormProUtils.sprintf(RSFormPro.Translations.commonTranslate('COM_RSFORM_MAXFILES_REQUIRED'), maxFiles));
1827								}
1828							}
1829						}
1830
1831						for (var f = 0; f < filesLength; f++)
1832						{
1833							var file = filesCollection[f];
1834							var maxSize = parseInt(form.elements[i].getAttribute('data-rsfp-size'));
1835							if ('size' in file && maxSize > 0)
1836							{
1837								if (file.size > maxSize)
1838								{
1839									throw new RSFormPro.validationError('VALIDATION_ERROR', RSFormProUtils.sprintf(RSFormPro.Translations.commonTranslate('COM_RSFORM_FILE_EXCEEDS_LIMIT'), file.name, maxSize / 1024));
1840								}
1841							}
1842							if ('name' in file)
1843							{
1844								var exts = form.elements[i].getAttribute('data-rsfp-exts');
1845								if (exts)
1846								{
1847									exts = JSON.parse(exts);
1848
1849									var ext = file.name.slice((file.name.lastIndexOf(".") - 1 >>> 0) + 2);
1850									if (exts.indexOf(ext.toLowerCase()) === -1)
1851									{
1852										throw new RSFormPro.validationError('VALIDATION_ERROR', RSFormProUtils.sprintf(RSFormPro.Translations.commonTranslate('COM_RSFORM_FILE_EXTENSION_NOT_ALLOWED'), file.name));
1853									}
1854								}
1855							}
1856						}
1857					}
1858					catch (error)
1859					{
1860						if (typeof error === 'object')
1861						{
1862							if (error.toString() === 'VALIDATION_ERROR')
1863							{
1864								var parents = RSFormProUtils.getParents(form.elements[i]),
1865									page_number,
1866									parent;
1867								if (parents.length > 0)
1868								{
1869									for (var p = 0; p < parents.length; p++)
1870									{
1871										parent = parents[p];
1872
1873										if ('getAttribute' in parent)
1874										{
1875											var hasId = parents[p].getAttribute('id');
1876											var pageId = 'rsform_' + formId + '_page_';
1877											if (hasId && hasId.indexOf(pageId) === 0)
1878											{
1879												page_number = hasId.slice(pageId.length);
1880												break;
1881											}
1882										}
1883									}
1884								}
1885
1886								var elementObj = {
1887									field: form.elements[i],
1888									page: page_number
1889								};
1890
1891								// try to get the componentId
1892								var componentId = RSFormPro.HTML5.getComponentId(formId, form.elements[i].getAttribute('id'));
1893								if (componentId)
1894								{
1895									elementObj.componentId = componentId;
1896
1897									if (document.getElementById('component' + componentId) && error.message.length > 0)
1898									{
1899										document.getElementById('component' + componentId).innerText = error.message;
1900									}
1901								}
1902
1903								errorFields.push(elementObj);
1904							}
1905						}
1906					}
1907				}
1908			}
1909
1910			if (form.elements[i].type !== 'file')
1911			{
1912				if (typeof RSFormPro.Editors[form.elements[i].name] === 'function' && RSFormPro.Editors[form.elements[i].name]() !== null)
1913				{
1914					RSFormPro.Ajax.Params.push(form.elements[i].name + '=' + encodeURIComponent(RSFormPro.Editors[form.elements[i].name]()));
1915				}
1916				else
1917				{
1918					RSFormPro.Ajax.Params.push(form.elements[i].name + '=' + encodeURIComponent(form.elements[i].value));
1919				}
1920			}
1921		}
1922
1923		errorFields = errorFields.concat(RSFormPro.HTML5.validation(formId));
1924
1925		if (page) {
1926			RSFormPro.Ajax.Params.push('page=' + page);
1927		}
1928
1929		RSFormPro.Ajax.xhr.open("POST", url, true);
1930
1931		//Send the proper header information along with the request
1932		RSFormPro.Ajax.xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
1933		
1934		if (typeof ajaxExtraValidationScript[formId] == 'function') {
1935			ajaxExtraValidationScript[formId]('beforeSend', formId, {'url': url, 'params': RSFormPro.Ajax.Params});
1936		}
1937
1938		if (!RSFormPro.Ajax.Wait)
1939		{
1940			// B/C layer
1941			RSFormPro.Ajax.xmlHttp.send(RSFormPro.Ajax.Params);
1942		}
1943		success = true;
1944		
1945		RSFormPro.Ajax.xhr.onreadystatechange = function() {
1946			if (RSFormPro.Ajax.xhr.readyState === 4 && RSFormPro.Ajax.xhr.status === 200) {
1947				try
1948				{
1949					var RSFormProResponse = JSON.parse(RSFormPro.Ajax.xhr.responseText);
1950				}
1951				catch (error)
1952				{
1953					// Parse invalid data
1954					if (typeof RSFormProResponse !== 'object')
1955					{
1956						var match = RSFormPro.Ajax.xhr.responseText.match(/{.*}/);
1957
1958						if (match.length > 0)
1959						{
1960							RSFormProResponse = JSON.parse(match[0]);
1961						}
1962					}
1963				}
1964
1965				var response = [];
1966				var ids;
1967				var i;
1968
1969				if (typeof RSFormProResponse.formComponents !== 'undefined')
1970				{
1971					// All spans set to no error
1972					ids = RSFormProResponse.formComponents;
1973
1974					for (i = 0; i < ids.length; i++)
1975					{
1976						if (!isNaN(parseInt(ids[i])) && document.getElementById('component'+ids[i]))
1977						{
1978							document.getElementById('component'+ids[i]).className = 'formNoError';
1979						}
1980					}
1981
1982					// Legacy
1983					response.push(RSFormProResponse.formComponents.join(','));
1984				}
1985
1986				if (typeof RSFormProResponse.invalidComponents === 'undefined')
1987				{
1988					RSFormProResponse.invalidComponents = [];
1989				}
1990
1991				// add the HTML5 elements with errors
1992				var errorOnPage;
1993				if (errorFields.length)
1994				{
1995					for (i = 0; i < errorFields.length; i++)
1996					{
1997						if (typeof errorFields[i].componentId !== 'undefined')
1998						{
1999							if (typeof page === 'undefined' || (page - 1) == errorFields[i].page)
2000							{
2001								RSFormProResponse.invalidComponents.push(errorFields[i].componentId);
2002								if (typeof errorOnPage !== 'undefined')
2003								{
2004									errorOnPage = errorFields[i].page < errorOnPage ? errorFields[i].page : errorOnPage;
2005								}
2006								else 
2007								{
2008									errorOnPage = errorFields[i].page;
2009								}
2010							}
2011						}
2012					}
2013				}
2014
2015				// Show errors
2016				var errorComponents = [];
2017
2018				var errorMessageContainer;
2019
2020				for (i = 0; i < RSFormProResponse.invalidComponents.length; i++)
2021				{
2022					if (!isNaN(parseInt(RSFormProResponse.invalidComponents[i])))
2023					{
2024						errorMessageContainer = document.getElementById('component' + RSFormProResponse.invalidComponents[i]);
2025
2026						if (errorMessageContainer)
2027						{
2028							errorMessageContainer.className = 'formError';
2029
2030							if (RSFormProResponse.validationMessages && typeof RSFormProResponse.validationMessages[RSFormProResponse.invalidComponents[i]] !== 'undefined')
2031							{
2032								errorMessageContainer.innerHTML = RSFormProResponse.validationMessages[RSFormProResponse.invalidComponents[i]];
2033							}
2034						}
2035
2036						errorComponents.push(RSFormProResponse.invalidComponents[i]);
2037						success = false;
2038					}
2039				}
2040
2041				// lets detect if the multiple page form is submitted
2042				var changePageHTML5Errors = false;
2043				if (totalJSDetectedPages > 0 && RSClickedSubmitElement && submits.indexOf(RSClickedSubmitElement) >= 0 && typeof errorOnPage !== 'undefined') {
2044					changePageHTML5Errors = true;
2045				}
2046
2047				// Legacy
2048				response.push(RSFormProResponse.invalidComponents.join(','));
2049
2050				if (typeof RSFormProResponse.allPages !== 'undefined' || changePageHTML5Errors)
2051				{
2052					// Legacy
2053					response.push(RSFormProResponse.currentPage);
2054					response.push(RSFormProResponse.allPages);
2055
2056					if (typeof RSFormProResponse.allPages !== 'undefined')
2057					{
2058						page = parseInt(RSFormProResponse.currentPage) - 1;
2059						totalPages = parseInt(RSFormProResponse.allPages);
2060						if (changePageHTML5Errors)
2061						{
2062							page = page > errorOnPage ? errorOnPage : page;
2063						}
2064					}
2065					else
2066					{
2067						if (changePageHTML5Errors)
2068						{
2069							page = errorOnPage;
2070							totalPages = totalJSDetectedPages;
2071						}
2072					}
2073
2074					RSFormPro.Pages.change(formId, page, totalPages, false);
2075				}
2076
2077				if (typeof ajaxExtraValidationScript[formId] === 'function')
2078				{
2079					// rewrite the response so that all the error components are added (that includes HTML5 fields)
2080					if (errorComponents.length)
2081					{
2082						response[1] = errorComponents.join();
2083					}
2084
2085					ajaxExtraValidationScript[formId]('afterSend', formId, {'url': url, 'params': RSFormPro.Ajax.Params, 'response': response, 'parentErrorClass': errorClasses.parent, 'fieldErrorClass': errorClasses.field, 'json': RSFormProResponse});
2086				}
2087				
2088				if (success === false)
2089				{
2090					// The submits must be clickable again
2091					for (i = 0; i < submits.length; i++)
2092					{
2093						submits[i].disabled = false;
2094					}
2095
2096					try
2097					{
2098						if (typeof page === 'undefined' || page == 0)
2099						{
2100							RSFormPro.callbacks.runCallback(formId, 'afterValidationFailed'); // callback functions if validation fails when form is submitted
2101						}
2102						else
2103						{
2104							RSFormPro.callbacks.runCallback(formId, 'nextPageFailed'); // callback functions if validation fails when a specific page of the form is checked
2105						}
2106
2107						if (document.getElementById('rsform_error_' + formId))
2108						{
2109							document.getElementById('rsform_error_' + formId).style.display = 'block';
2110
2111                            if (document.getElementById('rsform_error_count_' + formId))
2112                            {
2113                                document.getElementById('rsform_error_count_' + formId).innerText = errorComponents.length;
2114                            }
2115						}
2116					}
2117					catch (err) { }
2118				}
2119				else
2120				{
2121					// Change the page if the validation passes
2122					if (page)
2123					{
2124						RSFormPro.Pages.change(formId, page, totalPages, false);
2125						// The submits must be clickable again
2126						for (i = 0; i < submits.length; i++)
2127						{
2128							submits[i].disabled = false;
2129						}
2130					}
2131					else
2132					{
2133						// the submit button has been pressed so we need to submit the form
2134						// if the submit button or any other element has the id submit the form.submit() function is overwritten
2135						RSFormPro.submitForm(form);
2136					}
2137
2138					try
2139					{
2140						if (typeof page === 'undefined' || page == 0)
2141						{
2142							RSFormPro.callbacks.runCallback(formId, 'afterValidationSuccess'); // callback functions if validation succeeds
2143						}
2144						else
2145						{
2146							RSFormPro.callbacks.runCallback(formId, 'nextPageSuccess'); // callback functions if validation succeeds when a specific page of the form is checked
2147						}
2148
2149						if (document.getElementById('rsform_error_' + formId))
2150						{
2151							document.getElementById('rsform_error_' + formId).style.display = 'none';
2152						}
2153					}
2154					catch (err) { }
2155				}
2156
2157				return success;
2158			}
2159		};
2160
2161		return false;
2162	},
2163	overrideSubmit: function(formId, validationParams, disableSubmitButton) {
2164        var form = RSFormPro.getForm(formId);
2165        var submitElement = RSFormPro.getElementByType(formId, 'submit');
2166		var i, j;
2167        for (i = 0; i < submitElement.length; i++) {
2168			if (RSFormProUtils.hasClass(submitElement[i],'rsform-submit-button')) {
2169				RSFormProUtils.addEvent(submitElement[i],'click', (function(event) {
2170					event.preventDefault();
2171					RSClickedSubmitElement = this;
2172					if (disableSubmitButton) {
2173						for (j = 0; j < submitElement.length; j++) {
2174							submitElement[j].setAttribute('data-disableonsubmit','1');
2175						}
2176					}
2177
2178					RSFormPro.Ajax.validate(form, undefined, validationParams);
2179				}));
2180			}
2181		}
2182	}
2183};
2184
2185RSFormPro.validationError = function(type, message) {
2186	this.type = type;
2187	this.message = message;
2188};
2189
2190RSFormPro.validationError.prototype.toString = function() {
2191	return this.type;
2192};
2193
2194RSFormPro.callbacks = {
2195	allCallbacks: {},
2196	
2197	addCallback: function(formId, callbackName, args) {
2198		var base = RSFormPro.callbacks;
2199		
2200		if (typeof base.allCallbacks[formId] == 'undefined') {
2201			base.allCallbacks[formId] = {}
2202		}
2203		
2204		if (typeof base.allCallbacks[formId][callbackName] == 'undefined') {
2205			base.allCallbacks[formId][callbackName] = [];
2206		}
2207		
2208		base.allCallbacks[formId][callbackName].push(args);
2209	},
2210	
2211	runCallback: function(formId, callbackName) {
2212		var base = RSFormPro.callbacks;
2213		if (typeof base.allCallbacks[formId] != 'undefined' && typeof base.allCallbacks[formId][callbackName] != 'undefined' && base.allCallbacks[formId][callbackName].length > 0) {
2214			for (var i = 0; i < base.allCallbacks[formId][callbackName].length; i++) {
2215				var args = base.allCallbacks[formId][callbackName][i];
2216				var functionName = args[0];
2217				
2218				var functionArgs =  [];
2219				for (var j = 1; j < args.length; j++) {
2220					functionArgs.push(args[j]);
2221				}
2222				
2223				// execute the callback function set for this trigger
2224				functionName.apply(self, functionArgs);
2225			}
2226		}
2227	}
2228};
2229
2230/* Translations */
2231
2232RSFormPro.Translations = {
2233	translations: {},
2234	commonTranslations: {},
2235
2236	add: function(formId, name, key, translation) {
2237		if (typeof this.translations[formId + '-' + name] !== 'object')
2238		{
2239			this.translations[formId + '-' + name] = {};
2240		}
2241
2242		this.translations[formId + '-' + name][key] = translation;
2243	},
2244
2245	translate: function(formId, name, key) {
2246		if (typeof this.translations[formId + '-' + name][key] == 'string')
2247		{
2248			return this.translations[formId + '-' + name][key];
2249		}
2250
2251		return key;
2252	},
2253
2254	addCommonTranslation: function(key, translation) {
2255		this.commonTranslations[key] = translation;
2256	},
2257
2258	addCommonTranslations: function(translations) {
2259		var self = this;
2260		translations.forEach(function(el){
2261			self.commonTranslations[el[0]] = el[1];
2262		})
2263	},
2264
2265	commonTranslate: function(key) {
2266		if (typeof this.commonTranslations[key] == 'string')
2267		{
2268			return this.commonTranslations[key];
2269		}
2270
2271		return key;
2272	}
2273};
2274
2275RSFormPro.previewFields = {
2276	'elements': [],
2277	'delimiter': ', ',
2278	escapeValue: function(str) {
2279		var textAreaDiv = document.createElement('textarea');
2280		textAreaDiv.textContent = str;
2281		return textAreaDiv.innerHTML;
2282	},
2283	attachEvents: function() {
2284		if (RSFormPro.previewFields.elements.length > 0) {
2285			var element, results, i, j, tagName;
2286			var form;
2287			for (i = 0; i < RSFormPro.previewFields.elements.length; i++) {
2288				element = RSFormPro.previewFields.elements[i];
2289				results = RSFormPro.getFieldsByName(element.formId, element.fieldName);
2290				form = RSFormPro.getForm(element.formId)
2291
2292				if (results.length > 0) {
2293					for (j = 0; j < results.length; j++) {
2294						(function(element, field, formId, form){
2295							var funcValue = function () {
2296								if (document.getElementById('preview-' + element.previewId)) {
2297									if (field.hasOwnProperty('rsfpGetPreviewValue')) {
2298										document.getElementById('preview-' + element.previewId).innerHTML = field.rsfpGetPreviewValue();
2299									} else {
2300										document.getElementById('preview-' + element.previewId).innerText = field.value;
2301									}
2302								}
2303							}
2304							var funcMultiple = function () {
2305								if (document.getElementById('preview-' + element.previewId)) {
2306									var theValue = [];
2307									if (form.elements[field.name]) {
2308										if (form.elements[field.name].forEach) {
2309											form.elements[field.name].forEach(function (el) {
2310												if (el.checked) {
2311													if (document.querySelector('[for="' + el.id + '"]')) {
2312														theValue.push(RSFormPro.previewFields.escapeValue(document.querySelector('[for="' + el.id + '"]').innerText));
2313													} else {
2314														if (el.hasOwnProperty('rsfpGetPreviewValue')) {
2315															theValue.push(RSFormPro.previewFields.escapeValue(el.rsfpGetPreviewValue()));
2316														} else {
2317															theValue.push(RSFormPro.previewFields.escapeValue(el.value));
2318														}
2319													}
2320												}
2321											})
2322										} else {
2323											if (form.elements[field.name].checked) {
2324												if (form.elements[field.name].hasOwnProperty('rsfpGetPreviewValue')) {
2325													theValue.push(RSFormPro.previewFields.escapeValue(form.elements[field.name].rsfpGetPreviewValue()));
2326												} else {
2327													theValue.push(RSFormPro.previewFields.escapeValue(form.elements[field.name].value));
2328												}
2329											}
2330										}
2331									}
2332									document.getElementById('preview-' + element.previewId).innerHTML = theValue.join(element.separator || RSF
2332ormPro.previewFields.delimiter);
2333								}
2334							}
2335							var funcSurveyTable = function() {
2336								if (document.getElementById('preview-' + element.previewId)) {
2337									var theValue = [];
2338									var theQuestions = [];
2339									var theAnswers = [];
2340									var questions = parseInt(field.getAttribute('data-rsfpsurveytable-questions'));
2341									if (!isNaN(questions)) {
2342										var match = field.name.match(/^form\[(.*)]\[[0-9]+]$/);
2343										if (match)
2344										{
2345											var name = match[1];
2346											var firstPart = 'form[' + name + ']';
2347											for (var i = 0; i < questions; i ++) {
2348												if (form.elements[firstPart + '[' + i + ']'])
2349												{
2350													if (form.elements[firstPart + '[' + i + ']'].forEach)
2351													{
2352														form.elements[firstPart + '[' + i + ']'].forEach(function(el){
2353															if (el.checked)
2354															{
2355																theAnswers.push(el.parentNode.getAttribute('data-th'));
2356
2357																if (document.getElementById(el.getAttribute('aria-labelledby')))
2358																{
2359																	theQuestions.push(document.getElementById(el.getAttribute('aria-labelledby')).innerText);
2360																}
2361																else
2362																{
2363																	theQuestions.push(el.parentNode.parentNode.firstChild.innerText);
2364																}
2365															}
2366														});
2367													}
2368													else
2369													{
2370														if (form.elements[firstPart + '[' + i + ']'].checked)
2371														{
2372															theAnswers.push(form.elements[firstPart + '[' + i + ']'].parentNode.getAttribute('data-th'));
2373
2374															if (document.getElementById(form.elements[firstPart + '[' + i + ']'].getAttribute('aria-labelledby')))
2375															{
2376																theQuestions.push(document.getElementById(form.elements[firstPart + '[' + i + ']'].getAttribute('aria-labelledby')).innerText);
2377															}
2378															else
2379															{
2380																theQuestions.push(form.elements[firstPart + '[' + i + ']'].parentNode.parentNode.firstChild.innerText);
2381															}
2382														}
2383													}
2384												}
2385											}
2386
2387											for (var j = 0; j < theAnswers.length; j++) {
2388												theValue.push(element.template.replace('{question}', theQuestions[j]).replace('{answer}', theAnswers[j]));
2389											}
2390										}
2391									}
2392
2393									document.getElementById('preview-' + element.previewId).innerHTML = theValue.join(element.separator || RSF
2393ormPro.previewFields.delimiter);
2394								}
2395							}
2396							var funcSelect = function () {
2397								if (document.getElementById('preview-' + element.previewId)) {
2398									var theValue = [];
2399									if (field.options.length > 0) {
2400										for (var i = 0; i < field.options.length; i++) {
2401											if (field.options[i].selected) {
2402												theValue.push(RSFormPro.previewFields.escapeValue(field.options[i].text));
2403											}
2404										}
2405									}
2406									document.getElementById('preview-' + element.previewId).innerHTML = theValue.join(element.separator || RSFormPro.previewFields.delimiter);
2407								}
2408							}
2409							var funcBirthday = function () {
2410								if (document.getElementById('preview-' + element.previewId)) {
2411									var theValue = [];
2412									var theRoot = field.name.replace(/\[[dmy]]$/, '');
2413									var theElements = [theRoot + '[d]', theRoot + '[m]', theRoot + '[y]'];
2414									theElements.forEach(function(el){
2415										if (form.elements[el] && form.elements[el].value !== '') {
2416											theValue.push(form.elements[el].options[form.elements[el].selectedIndex].text);
2417										}
2418									})
2419									document.getElementById('preview-' + element.previewId).innerHTML = theValue.join(element.separator || '-');
2420								}
2421							}
2422							var funcFiles = function () {
2423								if (document.getElementById('preview-' + element.previewId)) {
2424									var f;
2425									var theValue = [];
2426									if (form.elements[field.name]) {
2427										if (form.elements[field.name].forEach) {
2428											form.elements[field.name].forEach(function (el) {
2429												if (el.files && el.files.length > 0) {
2430													for (f = 0; f < el.files.length; f++) {
2431														theValue.push(RSFormPro.previewFields.escapeValue(el.files[f].name));
2432													}
2433												}
2434											})
2435										} else {
2436											if (form.elements[field.name].files && form.elements[field.name].files.length > 0) {
2437												for (f = 0; f < form.elements[field.name].files.length; f++) {
2438													theValue.push(RSFormPro.previewFields.escapeValue(form.elements[field.name].files[f].name));
2439												}
2440											}
2441										}
2442									}
2443									document.getElementById('preview-' + element.previewId).innerHTML = theValue.join(element.separator || RSF
2443ormPro.previewFields.delimiter);
2444								}
2445							}
2446							tagName = field.tagName || field.nodeName;
2447
2448							if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
2449								var attachEvent = 'change';
2450								if (tagName === 'INPUT' && typeof field.type == 'string') {
2451									switch (field.type.toUpperCase()) {
2452										case 'FILE':
2453											funcValue = funcFiles;
2454											break;
2455
2456										case 'CHECKBOX':
2457										case 'RADIO':
2458											if (field.getAttribute('data-rsfpsurveytable-answer'))
2459											{
2460												funcValue = funcSurveyTable;
2461											}
2462											else
2463											{
2464												funcValue = funcMultiple;
2465											}
2466
2467											break;
2468
2469										case 'NUMBER':
2470										case 'TEXT':
2471										case 'PASSWORD':
2472										case 'EMAIL':
2473										case 'TEL':
2474										case 'URL':
2475										case 'RANGE':
2476											attachEvent = 'input';
2477											if (typeof RSFormPro.jQueryCalendar !== 'undefined' &&
2478												typeof RSFormPro.jQueryCalendar.calendars[formId] !== 'undefined' &&
2479												typeof RSFormPro.jQueryCalendar.calendars[formId][element.fieldName] !== 'undefined') {
2480												RSFormPro.jQueryCalendar.calendars[formId][element.fieldName].calendarInstance.setOptions({
2481													onChangeDateTime: function () {
2482														if (typeof funcValue === 'function') {
2483															funcValue();
2484														}
2485													}
2486												});
2487											}
2488
2489											if (typeof RSFormPro.YUICalendar !== 'undefined' &&
2490												typeof RSFormPro.YUICalendar.calendars[formId] !== 'undefined' &&
2491												typeof RSFormPro.YUICalendar.calendars[formId][element.fieldName] !== 'undefined') {
2492												RSFormPro.YUICalendar.calendars[formId][element.fieldName].selectEvent.subscribe(function () {
2493													if (typeof funcValue === 'function') {
2494														funcValue();
2495													}
2496												}, RSFormPro.YUICalendar.calendars[formId][element.fieldName], true);
2497											}
2498
2499											if (field.hasOwnProperty('rsfpOnChange')) {
2500												field.rsfpOnChange(funcValue);
2501											}
2502											break;
2503									}
2504								} else if (tagName === 'SELECT' && field.multiple === false && field.name.match(/form\[.*?]\[[dmy]]/)) {
2505									funcValue = funcBirthday;
2506								} else if (tagName === 'SELECT') {
2507									funcValue = funcSelect;
2508								} else if (tagName === 'TEXTAREA') {
2509									attachEvent = 'input';
2510								}
2511
2512								RSFormProUtils.addEvent(field, attachEvent, function () {
2513									if (typeof funcValue === 'function') {
2514										funcValue();
2515									}
2516								});
2517
2518								funcValue();
2519							}
2520						})(element, results[j], element.formId, form);
2521					}
2522				}
2523			}
2524		}
2525	}
2526};
2527
2528/* Helper functions */
2529var RSFormProUtils = {
2530	addEvent: function(obj, evType, fn) {
2531		if (obj.addEventListener)
2532		{
2533			obj.addEventListener(evType, fn, false);
2534			return true;
2535		}
2536		else if (obj.attachEvent)
2537		{
2538			var r = obj.attachEvent("on"+evType, fn);
2539			return r;
2540		}
2541		else
2542		{
2543			return false;
2544		}
2545	},
2546	hasClass: function (el, name) {
2547		return new RegExp('(\\s|^)' + name + '(\\s|$)').test(el.className);
2548	},
2549	addClass: function(el, name) {
2550		if (!RSFormProUtils.hasClass(el, name)) {
2551			el.className += (el.className ? ' ' : '') + name;
2552		}
2553	},
2554	removeClass: function(el, name) {
2555		if (RSFormProUtils.hasClass(el, name)) {
2556			el.className = el.className.replace(new RegExp('(\\s|^)' + name + '(\\s|$)'),' ').replace(/^\s+|\s+$/g, '');
2557		}
2558	},
2559	setDisplay: function (items, value) {
2560		if (!items || !items.length) {
2561			return false;
2562		}
2563
2564		for (var i = 0; i < items.length; i++) {
2565			if (!items[i]) {
2566				continue;
2567			}
2568
2569			if (!RSFormPro.usePositioning) {
2570				items[i].style.display = value;
2571			} else {
2572				value === 'none' ? RSFormProUtils.addClass(items[i], 'formHidden') : RSFormProUtils.removeClass(items[i], 'formHidden');
2573			}
2574		}
2575	},
2576	setAttr: function (items, attr, value) {
2577        for (var i = 0; i < items.length; i++) {
2578            items[i].setAttribute(attr, value);
2579        }
2580	},
2581    remAttr: function (items, attr) {
2582        for (var i = 0; i < items.length; i++) {
2583            items[i].removeAttribute(attr);
2584        }
2585    },
2586	getChecked: function (items) {
2587		var elements = [];
2588		var element, tagName;
2589        for (var i = 0; i < items.length; i++) {
2590        	element = items[i];
2591            tagName = element.tagName || element.nodeName;
2592
2593            if (tagName == 'INPUT' && element.type && element.type.toUpperCase() == 'CHECKBOX' && element.checked == true) {
2594				elements.push(element);
2595			}
2596        }
2597
2598        return elements;
2599	},
2600    getUnchecked: function (items) {
2601        var elements = [];
2602        var element, tagName;
2603        for (var i = 0; i < items.length; i++) {
2604            element = items[i];
2605            tagName = element.tagName || element.nodeName;
2606
2607            if (tagName == 'INPUT' && element.type && element.type.toUpperCase() == 'CHECKBOX' && !element.checked) {
2608                elements.push(element);
2609            }
2610        }
2611
2612        return elements;
2613    },
2614	getAlias: function(str) {
2615		str = str.replace(/\-/g, ' ');
2616
2617		if (!String.prototype.trim) {
2618			str = str.replace(/^\s+|\s+$/g, '');
2619		} else {
2620			str = str.trim();
2621		}
2622
2623		str = str.toLowerCase();
2624		str = str.replace(/(\s|[^A-Za-z0-9\-])+/g, '-');
2625		str = str.replace(/^\-+|\-+$/g, '');
2626
2627		return str;
2628	},
2629	getParents: function(a) {
2630		var els = [];
2631		while (a) {
2632			els.push(a);
2633			a = a.parentNode;
2634		}
2635		// Remove our own element
2636		if (els.length > 0)
2637		{
2638			els.shift()
2639		}
2640
2641		return els;
2642	},
2643	getElementsByClassName: function (className, tag, elm) {
2644		if (document.getElementsByClassName) {
2645			getElementsByClassName = function (className, tag, elm) {
2646				elm = elm || document;
2647				var elements = elm.getElementsByClassName(className),
2648					nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
2649					returnElements = [],
2650					current;
2651				for(var i=0, il=elements.length; i<il; i+=1){
2652					current = elements[i];
2653					if(!nodeName || nodeName.test(current.nodeName)) {
2654						returnElements.push(current);
2655					}
2656				}
2657				return returnElements;
2658			};
2659		} else if (document.evaluate) {
2660			getElementsByClassName = function (className, tag, elm) {
2661				tag = tag || "*";
2662				elm = elm || document;
2663				var classes = className.split(" "),
2664					classesToCheck = "",
2665					xhtmlNamespace = "http://www.w3.org/1999/xhtml",
2666					namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
2667					returnElements = [],
2668					elements,
2669					node;
2670				for(var j=0, jl=classes.length; j<jl; j+=1){
2671					classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
2672				}
2673				try	{
2674					elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
2675				}
2676				catch (e) {
2677					elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
2678				}
2679				while ((node = elements.iterateNext())) {
2680					returnElements.push(node);
2681				}
2682				return returnElements;
2683			};
2684		} else {
2685			getElementsByClassName = function (className, tag, elm) {
2686				tag = tag || "*";
2687				elm = elm || document;
2688				var classes = className.split(" "),
2689					classesToCheck = [],
2690					elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
2691					current,
2692					returnElements = [],
2693					match;
2694				for(var k=0, kl=classes.length; k<kl; k+=1){
2695					classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
2696				}
2697				for(var l=0, ll=elements.length; l<ll; l+=1){
2698					current = elements[l];
2699					match = false;
2700					for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
2701						match = classesToCheck[m].test(current.className);
2702						if (!match) {
2703							break;
2704						}
2705					}
2706					if (match) {
2707						returnElements.push(current);
2708					}
2709				}
2710				return returnElements;
2711			};
2712		}
2713
2714		return getElementsByClassName(className, tag, elm);
2715	},
2716
2717	/*!
2718	**  sprintf.js -- POSIX sprintf(3)-style String Formatting for JavaScript
2719	**  Copyright (c) 2006-2019 Dr. Ralf S. Engelschall <[email protected]>
2720	**  Partly based on Public Domain code by Jan Moesen <http://jan.moesen.nu/>
2721	**
2722	**  Permission is hereby granted, free of charge, to any person obtaining
2723	**  a copy of this software and associated documentation files (the
2724	**  "Software"), to deal in the Software without restriction, including
2725	**  without limitation the rights to use, copy, modify, merge, publish,
2726	**  distribute, sublicense, and/or sell copies of the Software, and to
2727	**  permit persons to whom the Software is furnished to do so, subject to
2728	**  the following conditions:
2729	**
2730	**  The above copyright notice and this permission notice shall be included
2731	**  in all copies or substantial portions of the Software.
2732	**
2733	**  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2734	**  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2735	**  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2736	**  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2737	**  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2738	**  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2739	**  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2740	*/
2741	sprintf: function () {
2742		/*  argument sanity checking  */
2743		if (!arguments || arguments.length < 1)
2744			throw new Error("sprintf: ERROR: not enough arguments");
2745
2746		/*  initialize processing queue  */
2747		var argumentnum = 0;
2748		var done = "", todo = arguments[argumentnum++];
2749
2750		/*  parse still to be done format string  */
2751		var m;
2752		while ((m = /^([^%]*)%(?:(\d+)\$|\((.*?)\))?([#0 +'-]+)?(\*|\d+)?(\.\*|\.\d+)?([%diouxXfFeEcs])((?:.|[\r\n])*)$/.exec(todo))) {
2753			var pProlog    = m[1],
2754				pAccessD   = m[2],
2755				pAccessN   = m[3],
2756				pFlags     = m[4],
2757				pMinLength = m[5],
2758				pPrecision = m[6],
2759				pType      = m[7],
2760				pEpilog    = m[8];
2761
2762			/*  determine substitution  */
2763			var subst;
2764			if (pType === "%")
2765			/*  special case: escaped percent character  */
2766				subst = "%";
2767			else {
2768				/*  parse padding and justify aspects of flags  */
2769				var padWith = " ";
2770				var justifyRight = true;
2771				if (pFlags) {
2772					if (pFlags.indexOf("0") >= 0)
2773						padWith = "0";
2774					if (pFlags.indexOf("-") >= 0) {
2775						padWith = " ";
2776						justifyRight = false;
2777					}
2778				}
2779				else
2780					pFlags = "";
2781
2782				/*  determine minimum length  */
2783				var access;
2784				var minLength = -1;
2785				if (pMinLength) {
2786					if (pMinLength === "*") {
2787						access = argumentnum++;
2788						if (access >= arguments.length)
2789							throw new Error("sprintf: ERROR: not enough arguments");
2790						minLength = arguments[access];
2791					}
2792					else
2793						minLength = parseInt(pMinLength, 10);
2794				}
2795
2796				/*  determine precision  */
2797				var precision = -1;
2798				if (pPrecision) {
2799					if (pPrecision === ".*") {
2800						access = argumentnum++;
2801						if (access >= arguments.length)
2802							throw new Error("sprintf: ERROR: not enough arguments");
2803						precision = arguments[access];
2804					}
2805					else
2806						precision = parseInt(pPrecision.substring(1), 10);
2807				}
2808
2809				/*  determine how to fetch argument  */
2810				access = argumentnum++;
2811				if (pAccessD) {
2812					access = parseInt(pAccessD, 10);
2813					if (access >= arguments.length)
2814						throw new Error("sprintf: ERROR: not enough arguments");
2815					subst = arguments[access];
2816				}
2817				else if (pAccessN) {
2818					if (typeof arguments[1] !== "object")
2819						throw new Error("sprintf: ERROR: invalid non-object arguments for named argument");
2820					subst = arguments[1][pAccessN];
2821					if (typeof subst === "undefined")
2822						throw new Error("sprintf: ERROR: invalid undefined value for named argument");
2823				}
2824				else {
2825					if (access >= arguments.length)
2826						throw new Error("sprintf: ERROR: not enough arguments");
2827					subst = arguments[access];
2828				}
2829
2830				/*  dispatch into expansions according to type  */
2831				var prefix = "";
2832				switch (pType) {
2833					/*  decimal number  */
2834					case "d":
2835					case "i":
2836						if (typeof subst !== "number")
2837							subst = 0;
2838						subst = subst.toString(10);
2839						if (pFlags.indexOf("#") >= 0 && subst >= 0)
2840							subst = "+" + subst;
2841						if (pFlags.indexOf(" ") >= 0 && subst >= 0)
2842							subst = " " + subst;
2843						break;
2844
2845					/*  binary number  */
2846					case "b":
2847						if (typeof subst !== "number")
2848							subst = 0;
2849						subst = subst.toString(2);
2850						break;
2851
2852					/*  octal number  */
2853					case "o":
2854						if (typeof subst !== "number")
2855							subst = 0;
2856						subst = subst.toString(8);
2857						break;
2858
2859					/*  unsigned decimal number  */
2860					case "u":
2861						if (typeof subst !== "number")
2862							subst = 0;
2863						subst = Math.abs(subst);
2864						subst = subst.toString(10);
2865						break;
2866
2867					/*  (lower-case) hexadecimal number  */
2868					case "x":
2869						if (typeof subst !== "number")
2870							subst = 0;
2871						subst = subst.toString(16).toLowerCase();
2872						if (pFlags.indexOf("#") >= 0)
2873							prefix = "0x";
2874						break;
2875
2876					/*  (upper-case) hexadecimal number  */
2877					case "X":
2878						if (typeof subst !== "number")
2879							subst = 0;
2880						subst = subst.toString(16).toUpperCase();
2881						if (pFlags.indexOf("#") >= 0)
2882							prefix = "0X";
2883						break;
2884
2885					/*  (lower/upper-case) floating point number (fixed precision)  */
2886					case "f":
2887					case "F":
2888						if (typeof subst !== "number")
2889							subst = 0.0;
2890						subst = 0.0 + subst;
2891						if (precision > -1) {
2892							if (subst.toFixed)
2893								subst = subst.toFixed(precision);
2894							else {
2895								subst = (Math.round(subst * Math.pow(10, precision)) / Math.pow(10, precision));
2896								subst += "0000000000";
2897								subst = subst.substr(0, subst.indexOf(".") + precision + 1);
2898							}
2899						}
2900						subst = "" + subst;
2901						if (pFlags.indexOf("'") >= 0) {
2902							var k = 0;
2903							for (var i = (subst.length - 1) - 3; i >= 0; i -= 3) {
2904								subst = subst.substring(0, i) + (k === 0 ? "." : ",") + subst.substring(i);
2905								k = (k + 1) % 2;
2906							}
2907						}
2908						break;
2909
2910					/*  (lower/upper-case) floating point number (exponential-based precision)  */
2911					case "e":
2912					case "E":
2913						if (typeof subst !== "number")
2914							subst = 0.0;
2915						subst = 0.0 + subst;
2916						if (precision > -1) {
2917							if (subst.toExponential)
2918								subst = subst.toExponential(precision);
2919							else
2920								throw new Error("sprintf: ERROR: toExponential() method not supported");
2921						}
2922						subst = "" + subst;
2923						if (pType === "E")
2924							subst = subst.replace(/e\+/, "E+");
2925						break;
2926
2927					/*  single character  */
2928					case "c":
2929						if (typeof subst !== "number")
2930							subst = 0;
2931						subst = String.fromCharCode(subst);
2932						break;
2933
2934					/*  string  */
2935					case "s":
2936						if (typeof subst !== "string")
2937							subst = String(subst);
2938						if (precision > -1)
2939							subst = subst.substr(0, precision);
2940						break;
2941					default:
2942						throw new Error("sprintf: ERROR: invalid conversion character \"" + pType + "\"");
2943				}
2944
2945				/*  apply optional padding  */
2946				var padding = minLength - subst.toString().length - prefix.toString().length;
2947				if (padding > 0) {
2948					var arrTmp = new Array(padding + 1);
2949					if (justifyRight)
2950						subst = arrTmp.join(padWith) + subst;
2951					else
2952						subst = subst + arrTmp.join(padWith);
2953				}
2954
2955				/*  add optional prefix  */
2956				subst = prefix + subst;
2957			}
2958
2959			/*  update the processing queue  */
2960			done = done + pProlog + subst;
2961			todo = pEpilog;
2962		}
2963
2964		/*  return finally formatted string  */
2965		return (done + todo);
2966	}
2967};
2968
2969function isset() {
2970  // http://kevin.vanzonneveld.net
2971  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2972  // +   improved by: FremyCompany
2973  // +   improved by: Onno Marsman
2974  // +   improved by: Rafał Kukawski
2975  // *     example 1: isset( undefined, true);
2976  // *     returns 1: false
2977  // *     example 2: isset( 'Kevin van Zonneveld' );
2978  // *     returns 2: true
2979  var a = arguments,
2980    l = a.length,
2981    i = 0,
2982    undef;
2983
2984  if (l === 0) {
2985    throw new Error('Empty isset');
2986  }
2987
2988  while (i !== l) {
2989    if (a[i] === undef || a[i] === null) {
2990      return false;
2991    }
2992    i++;
2993  }
2994  return true;
2995}
2996
2997/* Legacy functions */
2998
2999function rsfp_geolocation(term, id, mapid,  map, marker, geocoder, type) {
3000	return RSFormPro.initGeoLocation(term, id, mapid, map, marker, geocoder, type);
3001}
3002
3003function refreshCaptcha(componentId, captchaPath) {
3004	return RSFormPro.refreshCaptcha(componentId, captchaPath);
3005}
3006
3007function number_format(number, decimals, dec_point, thousands_sep) {
3008	return RSFormPro.formatNumber(number, decimals, dec_point, thousands_sep);
3009}
3010
3011function rsfp_toNumber(number, decimal, thousands, decimals) {
3012	return RSFormPro.toNumber(number, decimal, thousands, decimals);
3013}
3014
3015function rsfp_getForm(formId) {
3016	return RSFormPro.getForm(formId);
3017}
3018
3019function rsfp_getValue(formId, name) {
3020	return RSFormPro.getValue(formId, name);
3021}
3022
3023function rsfp_verifyChecked(formId, name, value) {
3024	return RSFormPro.isChecked(formId, name, value);
3025}
3026
3027function rsfp_getBlock(formId, block) {
3028	return RSFormPro.getBlock(formId, block);
3029}
3030
3031function rsfp_getFieldsByName(formId, name) {
3032	return RSFormPro.getFieldsByName(formId, name);
3033}
3034
3035function rsfp_addEvent(obj, evType, fn) {
3036	return RSFormProUtils.addEvent(obj, evType, fn);
3037}
3038
3039function rsfp_setDisplay(items, value) {
3040	return RSFormProUtils.setDisplay(items, value);
3041}
3042
3043function stringURLSafe(str) {
3044	return RSFormProUtils.getAlias(str);
3045}
3046
3047function rsfp_changePage(formId, page, totalPages, validate, errorClasses) {
3048	return RSFormPro.Pages.change(formId, page, totalPages, validate, errorClasses);
3049}
3050
3051function rsfp_hidePage(thePage) {
3052	return RSFormPro.Pages.hide(thePage);
3053}
3054
3055function rsfp_showPage(thePage) {
3056	return RSFormPro.Pages.show(thePage);
3057}
3058
3059function rsfp_checkValidDate(fieldName) {
3060	return RSFormPro.disableInvalidDates(fieldName);
3061}
3062
3063function rsfp_addCondition(formId, name, fnCondition) {
3064	return RSFormPro.Conditions.add(formId, name, fnCondition);
3065}
3066
3067function rsfp_runAllConditions(formId) {
3068	return RSFormPro.Conditions.runAll(formId);
3069}
3070
3071function rsfp_setCalculationsEvents(formId, fields) {
3072	return RSFormPro.Calculations.addEvents(formId, fields);
3073}
3074
3075function getElementsByClassName(className, tag, elm) {
3076	return RSFormProUtils.getElementsByClassName(className, tag, elm);
3077}
3078
3079function buildXmlHttp() {
3080	return RSFormPro.Ajax.getXHR();
3081}
3082
3083function ajaxDisplayValidationErrors(formComponents, task, formId, data) {
3084	return RSFormPro.Ajax.displayValidationErrors(formComponents, task, formId, data);
3085}
3086
3087function ajaxValidation(form, page, errorClasses) {
3088	return RSFormPro.Ajax.validate(form, page, errorClasses);
3089}

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.