PageSourceSearch

https://www.tealive.com.my/media/com_rsform/js/script.js?eae6cb12c70c2368b42a969178714f78

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

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.