1/** 2* @package BaForms 3* @author Balbooa http://www.balbooa.com/ 4* @copyright Copyright @ Balbooa 5* @license http://www.gnu.org/licenses/gpl.html GNU/GPL 6*/ 7 8var $f = jQuery, 9 formsApp = { 10 loaded: {} 11 }; 12 13!function($){ 14 class formsModal { 15 constructor(element) { 16 this.element = $(element).on('mousedown.formsModal', $.proxy(this.hide, this)); 17 this.position = element.dataset.position ? element.dataset.position : ''; 18 if (element.parentNode != document.body) { 19 $('body').append(this.element); 20 } 21 } 22 show() { 23 this.element.css({ 24 'opacity': '', 25 'pointer-events': '' 26 }); 27 this.setScroll(); 28 this.element.addClass('visible-forms-modal'); 29 let scroll = this.element[0].offsetWidth - this.element[0].clientWidth; 30 this.element[0].style.setProperty('--forms-modal-scroll-width', scroll + 'px'); 31 } 32 setScroll() { 33 document.body.classList.add('forms-modal-position-' + this.position); 34 if (!document.body.classList.contains('forms-modal-opened')) { 35 let scroll = window.innerWidth - document.documentElement.clientWidth; 36 document.body.classList.add('forms-modal-opened'); 37 document.body.style.setProperty('--forms-body-scroll-width', scroll + 'px'); 38 } 39 } 40 hide(event) { 41 if (!event || event.target.dataset.dismiss == 'formsModal' && event.button == 0) { 42 let $this = this; 43 this.element.removeClass('visible-forms-modal'); 44 setTimeout(function () { 45 $this.hideScroll(); 46 }, 300); 47 } 48 } 49 hideScroll() { 50 document.body.classList.remove('forms-modal-position-' + this.position); 51 if (!document.querySelector('.visible-forms-modal')) { 52 document.body.classList.remove('forms-modal-opened'); 53 document.body.style.removeProperty('--forms-body-scroll-width'); 54 } 55 } 56 } 57 $.fn.formsModal = function(option){ 58 return this.each(function() { 59 var data = $(this).data('formsModal'); 60 if (!data) { 61 $(this).data('formsModal', (data = new formsModal(this))); 62 } 63 if (typeof option == 'string') { 64 data[option](); 65 } else { 66 data.show(); 67 } 68 }); 69 } 70 $.fn.formsModal.Constructor = formsModal; 71}(window.$f); 72 73formsApp.renderFormsCalendar = function(input){ 74 if (input) { 75 formsApp.calendar.formInput = input; 76 } 77 formsApp.fetch.request(JUri+'index.php?option=com_baforms&task=form.renderFormsCalendar', { 78 start: formsApp.calendar.start, 79 year: formsApp.calendar.year, 80 month: formsApp.calendar.month * 1 + 1 81 }).then(function(text){ 82 let data = JSON.parse(text), 83 disable = formsApp.calendar.disable, 84 input = formsApp.calendar.formInput, 85 div = document.createElement('div'); 86 div.innerHTML = data.body; 87 for (let i = 0; i < disable.days.length; i++) { 88 div.querySelectorAll('.ba-date-cell[data-day-number="'+disable.days[i]+'"]').forEach((cell) => { 89 cell.classList.add('disabled-date'); 90 }); 91 } 92 for (let i = 0; i < disable.dates.length; i++) { 93 div.querySelectorAll('.ba-date-cell[data-day-date="'+disable.dates[i]+'"]').forEach((cell) => { 94 cell.classList.add('disabled-date'); 95 }) 96 } 97 for (let i = 0; i < disable.range.length; i++) { 98 let minMax = disable.range[i].split(' - '); 99 div.querySelectorAll('.ba-date-cell:not(.disabled-date)').forEach((cell) => { 100 if (cell.dataset.dayDate >= minMax[0] && cell.dataset.dayDate <= minMax[1]) { 101 cell.classList.add('disabled-date'); 102 } 103 }); 104 } 105 div.querySelectorAll('.ba-curent-date').forEach(($this) => { 106 let today = formsApp.calendar.querySelector('.ba-forms-today-btn'), 107 action = $this.classList.contains('disabled-date') ? 'add' : 'remove'; 108 today.dataset.date = $this.dataset.date; 109 today.dataset.dayDate = $this.dataset.dayDate; 110 today.classList[action]('disabled-date'); 111 }); 112 if (input.rangeBtn && input.dataset.index == 1) { 113 let date = input.rangeBtn.dataset.value; 114 div.querySelectorAll('.ba-date-cell:not(.disabled-date)').forEach((cell) => { 115 if (cell.dataset.dayDate <= date) { 116 cell.classList.add('disabled-date'); 117 } 118 }); 119 } 120 formsApp.calendar.querySelector('.ba-forms-calendar-title').textContent = data.title; 121 formsApp.calendar.querySelector('.ba-forms-calendar-header').innerHTML = data.header; 122 formsApp.calendar.querySelector('.ba-forms-calendar-body').innerHTML = div.innerHTML; 123 if (!formsApp.calendar.classList.contains('visible-forms-calendar')) { 124 formsApp.calendar.classList.add('visible-forms-calendar'); 125 } 126 }); 127} 128 129formsApp.setFormsCalendarEvents = function(){ 130 let $calendar = $f(formsApp.calendar); 131 $calendar.find('.ba-forms-today-btn').on('click', function(){ 132 if (!this.classList.contains('disabled-date')) { 133 formsApp.calendar.formInput.value = this.dataset.date; 134 formsApp.calendar.formInput.dataset.value = this.dataset.dayDate; 135 $f(formsApp.calendar.formInput).trigger('input');
136 formsApp.hideCalendar(); 137 } 138 }); 139 $calendar.find('i[data-action]').on('click', function(){ 140 let year = formsApp.calendar.year * 1, 141 month = formsApp.calendar.month * 1; 142 if (this.dataset.action == 'next') { 143 year = (month === 11) ? year + 1 : year; 144 month = (month + 1) % 12; 145 } else if (this.dataset.action == 'prev') { 146 year = (month === 0) ? year - 1 : year; 147 month = (month === 0) ? 11 : month - 1; 148 } else if (this.dataset.action == 'next-year') { 149 year = year + 1; 150 } else if (this.dataset.action == 'prev-year') { 151 year = year - 1; 152 } 153 formsApp.calendar.year = year; 154 formsApp.calendar.month = month; 155 formsApp.renderFormsCalendar(); 156 }); 157 $calendar.on('click', '.ba-date-cell', function(){ 158 if (!(formsApp.calendar.classList.contains('disable-previous-date') && this.classList.contains('ba-previous-date')) 159 && !this.classList.contains('disabled-date')) { 160 formsApp.calendar.formInput.value = this.dataset.date; 161 formsApp.calendar.formInput.dataset.value = this.dataset.dayDate; 162 $f(formsApp.calendar.formInput).trigger('input'); 163 formsApp.hideCalendar(); 164 } 165 }); 166 $calendar.find('.ba-close-calendar').on('click', function(){ 167 formsApp.hideCalendar(); 168 }); 169} 170 171formsApp.hideCalendar = function(){ 172 formsApp.calendar.classList.add('forms-calendar-out'); 173 setTimeout(function(){ 174 formsApp.calendar.classList.remove('visible-forms-calendar'); 175 formsApp.calendar.classList.remove('forms-calendar-out'); 176 }, 600); 177} 178 179formsApp.createCalendar = function($this){ 180 formsApp.calendar = document.createElement('div'); 181 formsApp.calendar.className = 'forms-calendar-wrapper'; 182 formsApp.calendar.innerHTML = '<div class="ba-forms-calendar"><div class="ba-forms-calendar-title-wrapper">'+ 183 '<span class="forms-calendar-btn"><i class="ba-form-icons ba-icon-chevron-left" data-action="prev-year"></i>'+ 184 '<span class="ba-tooltip ba-bottom ba-hide-element">'+formsApp._('YEAR')+'</span></span>'+ 185 '<span class="forms-calendar-btn"><i class="ba-form-icons ba-icon-chevron-left" data-action="prev"></i>'+ 186 '<span class="ba-tooltip ba-bottom ba-hide-element">'+formsApp._('MONTH')+'</span></span>'+ 187 '<span class="ba-forms-calendar-title"></span>'+ 188 '<span class="forms-calendar-btn"><i class="ba-form-icons ba-icon-chevron-right" data-action="next"></i>'+ 189 '<span class="ba-tooltip ba-bottom ba-hide-element">'+formsApp._('MONTH')+'</span></span>'+ 190 '<span class="forms-calendar-btn"><i class="ba-form-icons ba-icon-chevron-right" data-action="next-year"></i>'+ 191 '<span class="ba-tooltip ba-bottom ba-hide-element">'+formsApp._('YEAR')+'</span></span>'+ 192 '</div><div class="ba-forms-calendar-header"></div>'+ 193 '<div class="ba-forms-calendar-body"></div>'+ 194 '<div class="ba-forms-calendar-footer"><span class="ba-forms-today-btn">'+formsApp._('TODAY')+'</span></div>'+ 195 '</div><div class="ba-close-calendar"></div>'; 196 document.body.appendChild(formsApp.calendar); 197 formsApp.calendar.year = $this.dataset.year; 198 formsApp.calendar.month = $this.dataset.month; 199 formsApp.setFormsCalendarEvents(); 200} 201 202formsApp.hideNotice = function(){ 203 this.notification.classList.remove('notification-in'); 204 this.notification.classList.add('animation-out'); 205} 206 207formsApp.showNotice = function(message, className = ''){ 208 if (!this.notification) { 209 this.notification = document.createElement('div'); 210 this.notification.id = 'ba-forms-notification'; 211 this.notification.innerHTML = '<i class="ba-form-icons ba-icon-close"></i><h4>'+this._('ERROR')+'</h4><p></p>'; 212 this.notification.querySelector('.ba-icon-close').addEventListener('click', function(){ 213 formsApp.hideNotice(); 214 }); 215 document.body.append(this.notification); 216 } 217 this.notification.showCallback = function(){}; 218 if (this.notification.classList.contains('notification-in')) { 219 this.notification.showCallback = function(){ 220 formsApp.notification.showCallback = function(){}; 221 formsApp.addNoticeText(message, className); 222 }; 223 } else { 224 this.addNoticeText(message, className); 225 } 226} 227 228formsApp.addNoticeText = function(message, className){ 229 $f(this.notification).find(' > p').html(message); 230 if (className) { 231 this.notification.classList.add(className); 232 } else { 233 this.notification.classList.remove('ba-alert'); 234 } 235 this.notification.classList.remove('animation-out') 236 this.notification.classList.add('notification-in'); 237 clearTimeout(this.notification.hideDelay); 238 this.notification.hideDelay = setTimeout(function(){ 239 formsApp.hideNotice(); 240 setTimeout(function(){ 241 if (className) { 242 formsApp.notification.classList.remove(className); 243 } 244 formsApp.notification.showCallback(); 245 }, 400); 246 }, 6000); 247} 248 249formsApp.getLocalStorage = function(){ 250 let storage = localStorage.getItem('forms-progress'), 251 date = +new Date(), 252 expire = false;
253 if (!storage) { 254 storage = '{}'; 255 } 256 formsApp.storage = JSON.parse(storage); 257 for (let ind in formsApp.storage) { 258 let page = formsApp.storage[ind]; 259 for (let key in page) { 260 let data = page[key]; 261 if (Math.floor((date - data.date) / (1000 * 60 * 60 * 24)) > 30) { 262 expire = true; 263 delete formsApp.storage[ind][key]; 264 } 265 } 266 } 267 if (expire) { 268 localStorage.setItem('forms-progress', JSON.stringify(formsApp.storage)); 269 } 270} 271 272formsApp.fetch = { 273 getErrorText: function(text){ 274 let div = document.createElement('div'); 275 div.innerHTML = text; 276 if (div.querySelector('title')) { 277 text = div.querySelector('title').textContent; 278 } 279 280 return text; 281 }, 282 request: async function(url, data){ 283 let request = await fetch(url, { 284 method: 'POST', 285 cache: 'no-cache', 286 body: this.getFormData(data) 287 }), 288 response = null; 289 if (request.ok) { 290 response = await request.text(); 291 } else { 292 let utf8Decoder = new TextDecoder("utf-8"), 293 reader = request.body.getReader(), 294 textData = await reader.read(), 295 text = utf8Decoder.decode(textData.value); 296 console.info(this.getErrorText(text)); 297 } 298 299 return response; 300 }, 301 getFormData: function(data){ 302 let formData = new FormData(); 303 if (data) { 304 for (let ind in data) { 305 formData.append(ind, data[ind]); 306 } 307 } 308 309 return formData; 310 }, 311 312} 313 314formsApp.countries = { 315 append: function(){ 316 document.querySelectorAll('.ba-form-phone-field .ba-phone-countries-list').forEach(function(ul){ 317 if (!ul.querySelector('li')) { 318 ul.innerHTML = formsApp.countries.html; 319 } 320 }) 321 }, 322 check: function(){ 323 if (this.data) { 324 this.append() 325 } else if (document.querySelector('.ba-form-phone-field') && !this.loading) { 326 this.load(); 327 } 328 }, 329 readCountries: function(){ 330 return new Promise(function(resolve, reject) { 331 fetch(JUri+'index.php?option=com_baforms&task=form.readCountries').then(function(response){ 332 if (response.ok) { 333 response.json().then(function(json){ 334 resolve(json); 335 }); 336 } else { 337 console.info(response) 338 } 339 }); 340 }); 341 }, 342 load: function(){ 343 this.loading = true; 344 fetch(JUri+'components/com_baforms/libraries/countries/countries.json').then(function(response){ 345 if (!response.ok) { 346 return formsApp.countries.readCountries() 347 } else { 348 return response.json(); 349 } 350 }).then(function(json){ 351 formsApp.countries.set(json); 352 }); 353 }, 354 set: function(data){ 355 let html = ''; 356 for (let ind in data) { 357 html += '<li class="ba-phone-country-item" data-prefix="+'+data[ind].prefix+'" data-flag="'+ind+ 358 '" data-title="'+data[ind].title+'" data-placeholder="'+data[ind].placeholder.replace(/X/g, '_')+ 359 '"><span class="ba-phone-flag ba-phone-flag-'+ind+'"></span><span class="ba-phone-country-title">'+ 360 data[ind].title+'</span><span class="ba-phone-country-prefix">+'+data[ind].prefix+'</span></li>'; 361 } 362 this.html = html; 363 this.data = data; 364 this.append(); 365 } 366} 367 368formsApp.createForms = function(){ 369 formsApp.signature.check(); 370 formsApp.checkGoogleMaps(); 371 formsApp.checkLanguage(); 372 formsApp.countries.check(); 373 if (!formsApp.recaptcha && document.querySelector('.ba-form-submit-recaptcha-wrapper')) { 374 formsApp.getRecaptchaData(); 375 } 376 formsApp.getLocalStorage(); 377 $f('.com-baforms-wrapper').each(formsApp.createForm).closest('.ba-form-lightbox-layout').each(formsApp.renderLightbox); 378} 379 380formsApp.renderLightbox = function(){ 381 if (!this.trigger) { 382 this.trigger = JSON.parse(this.dataset.trigger); 383 this.session = JSON.parse(this.dataset.session);
384 $f(this).removeAttr('data-trigger').removeAttr('data-session') 385 } 386 if (!this.session.enable) { 387 formsApp.initLightbox(this); 388 } else if (this.session.enable && this.trigger.type != '') { 389 var flag = true; 390 if (localStorage['formsModal-'+this.dataset.id]) { 391 var date = new Date().getTime(), 392 expires = new Date(localStorage[this.dataset.id]); 393 expires.getTime(); 394 if (date >= expires) { 395 flag = true; 396 localStorage.removeItem(this.dataset.id); 397 } else { 398 flag = false; 399 } 400 } 401 if (flag) { 402 formsApp.initLightbox(this); 403 } 404 } 405} 406 407formsApp.showLightbox = function($this){ 408 if ($this.session.enable) { 409 var expiration = new Date(); 410 expiration.setDate(expiration.getDate()+$this.session.duration); 411 localStorage.setItem('formsModal-'+$this.dataset.id, expiration); 412 } 413 $f($this).formsModal().find('.ba-form-submit-field').each(function(){ 414 formsApp.initFormsRecaptcha(this); 415 }); 416} 417 418formsApp.initLightbox = function($this){ 419 if ($this.trigger.type == 'time-delay') { 420 setTimeout(function(){ 421 formsApp.showLightbox($this); 422 }, $this.trigger.time); 423 } else if ($this.trigger.type == 'scrolling') { 424 formsApp.lightboxScroll($this, $this.trigger.scroll * 1); 425 } else if ($this.trigger.type == 'exit-intent') { 426 $f(document).one('mouseleave', function(){ 427 formsApp.showLightbox($this); 428 }); 429 } else if ($this.trigger.type == 'bottom-of-page') { 430 formsApp.lightboxScroll($this, 100); 431 } 432} 433 434formsApp.lightboxScroll = function($this, scroll){ 435 var top, 436 docHeight, 437 htmlHeight; 438 $f(window).on('scroll.ba-lightbox'+$this.dataset.id+' load.ba-lightbox'+$this.dataset.id, function(){ 439 top = $f(window).scrollTop(); 440 docHeight = document.documentElement.clientHeight 441 htmlHeight = Math.max( 442 document.body.scrollHeight, document.documentElement.scrollHeight, 443 document.body.offsetHeight, document.documentElement.offsetHeight, 444 document.body.clientHeight, document.documentElement.clientHeight 445 ); 446 var x = (docHeight + top) * 100 / htmlHeight; 447 if (x >= scroll || (scroll > 97 && x >= 97)) { 448 $f(window).off('scroll.ba-lightbox'+$this.dataset.id+' load.ba-lightbox'+$this.dataset.id); 449 formsApp.showLightbox($this) 450 } 451 }); 452} 453 454formsApp.executeRecaptcha = (btn) => { 455 let visible = true; 456 $f(btn).closest('.ba-form-submit-wrapper').find('.forms-recaptcha').each(function(){ 457 let widgetID = formsApp.recaptcha.data[this.id], 458 response = formsApp.getRecaptchaResponse(this); 459 if (this.dataset.captcha == 'recaptcha_invisible' && !response) { 460 grecaptcha.execute(widgetID); 461 visible = false; 462 } else if (this.dataset.captcha == 'hcaptcha' && formsApp.recaptcha.hcaptcha.invisible && !response) { 463 hcaptcha.execute(widgetID) 464 visible = false; 465 } 466 }); 467 468 return visible; 469} 470 471formsApp.getRecaptchaResponse = function(elem){ 472 let response = '', 473 widgetId = formsApp.recaptcha.data[elem.id]; 474 try { 475 if (elem.dataset.captcha == 'recaptcha_invisible') { 476 response = grecaptcha.getResponse(); 477 } else if (elem.dataset.captcha == 'hcaptcha') { 478 response = hcaptcha.getResponse(widgetId); 479 } else if (elem.dataset.captcha == 'turnstile') { 480 response = !turnstile.isExpired(widgetId) ? turnstile.getResponse(widgetId) : ''; 481 } else { 482 response = grecaptcha.getResponse(widgetId); 483 } 484 } catch (err) { 485 console.info(err) 486 } 487 488 return response != ''; 489} 490 491formsApp.checkAlert = function(form){ 492 form.find('.confirm-email-wrapper').find('input').each(function(){ 493 let alert = !this.value.trim(), 494 key = 'THIS_FIELD_REQUIRED'; 495 if (this.value) { 496 alert = !(/@/g.test(this.value) && this.value.match(/@/g).length == 1); 497 key = 'ENTER_VALID_VALUE'; 498 if (!alert) { 499 let email = this.closest('.ba-form-field-item').querySelector('.ba-input-wrapper input').value.trim(); 500 alert = !(email == this.value.trim()); 501 key = 'EMAIL_ADDRESSES_NOT_MATCH'; 502 } 503 } 504 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-field-container'), key); 505 }); 506 form.find('.ba-form-signature-field').each(function(){ 507 if (this.dataset.required) { 508 let alert = this.signature.isEmpty(), 509 container = this.querySelector('.ba-field-container'); 510 formsApp.toggleAlertTooltip(alert, container, container, 'THIS_FIELD_REQUIRED'); 511 } 512 }) 513 form.find('.confirm-password-wrapper').find('input').each(function(){ 514 let password = this.closest('.ba-form-field-item').querySelector('.ba-input-wrapper input').value.trim(), 515 alert = this.required && !this.value.trim(), 516 key = 'THIS_FIELD_REQUIRED'; 517 if (password) { 518 alert = !(password == this.value.trim()); 519 key = 'PASSWORDS_NOT_MATCH'; 520 } 521 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-field-container'), key); 522 }); 523 form.find('.ba-form-input-field, .ba-form-address-field').find(' > .ba-input-wrapper').find('input, textarea').each(function(){ 524 let alert = this.required && !this.value.trim(), 525 key = 'THIS_FIELD_REQUIRED'; 526 if (this.formsInputMask) { 527 alert = this.required && this.value == this.formsInputMask; 528 } 529 if (this.value && this.characters && this.characters.key == 'min') { 530 alert = !(this.value.length >= this.characters.length); 531 key = 'ENTER_VALID_VALUE'; 532 } else if (this.value && this.dataset.validation == 'email') { 533 alert = !(/@/g.test(this.value) && this.value.match(/@/g).length == 1); 534 key = 'ENTER_VALID_VALUE'; 535 } else if (this.value && this.dataset.validation == 'numbers') { 536 alert = !(/\d+\.{0,1}\d{0,}/.test(this.value)); 537 key = 'ENTER_VALID_VALUE'; 538 } else if (this.value && this.dataset.validation == 'url') { 539 alert = !(/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i.test(this.value)); 540 key = 'ENTER_VALID_VALUE'; 541 } else if (!alert && this.value && this.formsInputMask) { 542 alert = this.value != this.formsInputMask && this.value.indexOf('_') != -1; 543 key = 'ENTER_VALID_VALUE'; 544 } 545 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-field-container'), key); 546 }); 547 form.find('.ba-form-phone-field input.ba-phone-number-input').each(function(){ 548 let alert = this.required && this.value == this.formsInputMask, 549 key = 'THIS_FIELD_REQUIRED'; 550 if (!alert && this.value) { 551 alert = this.value != this.formsInputMask && this.value.indexOf('_') != -1; 552 key = 'ENTER_VALID_VALUE'; 553 } 554 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-field-container'), key); 555 }); 556 form.find('.ba-form-upload-field').find('input[type="file"]').each(function(){ 557 let alert = this.required && this.uploads.count == 0; 558 formsApp.toggleAlertTooltip(alert, this, this.closest('.upload-file-input'), 'THIS_FIELD_REQUIRED'); 559 }); 560 form.find('.ba-form-field-item').find('.ba-form-rating-group-wrapper').each(function(){ 561 if (this.dataset.required) { 562 let alert = false;
563 $f(this).find('input').each(function(){ 564 alert = !this.checked; 565 if (this.checked) { 566 return false; 567 } 568 }) 569 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-form-rating-group-wrapper'), 'THIS_FIELD_REQUIRED'); 570 } 571 }); 572 form.find('.ba-form-field-item').find('.ba-form-checkbox-group-wrapper').each(function(){ 573 if (this.dataset.required) { 574 let alert = false; 575 $f(this).find('input').each(function(){ 576 alert = !this.checked; 577 if (this.checked) { 578 return false; 579 } 580 }) 581 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-form-checkbox-group-wrapper'),'THIS_FIELD_REQUIRED'); 582 } 583 }); 584 form.find('.ba-form-dropdown-field, .ba-form-select-multiple-field').find('select').each(function(){ 585 let alert = this.required && !this.value.trim(); 586 formsApp.toggleAlertTooltip(alert, this, this.closest('.ba-field-container'), 'THIS_FIELD_REQUIRED'); 587 }); 588 form.find('.ba-form-acceptance-field').find('.ba-field-container').each(function(){ 589 if (this.dataset.required) { 590 let alert = false; 591 $f(this).find('input').each(function(){ 592 alert = !this.checked; 593 if (this.checked) { 594 return false; 595 } 596 }) 597 formsApp.toggleAlertTooltip(alert, this, this, 'THIS_FIELD_REQUIRED'); 598 } 599 }); 600 form.find('.ba-form-calendar-field input[required]').each(function(){ 601 formsApp.toggleAlertTooltip(!this.value.trim(), this, this.closest('.calendar-field-wrapper'), 'THIS_FIELD_REQUIRED'); 602 }) 603 let tooltip = form.find('.ba-form-field-item').find('.ba-alert-tooltip'); 604 if (tooltip.length) { 605 tooltip[0].closest('.ba-form-field-item').scrollIntoView({ 606 block: 'center' 607 }); 608 return false; 609 } 610} 611 612formsApp.toggleAlertTooltip = function(alert, $this, parent, key){ 613 if (alert && !$this.alertTooltip && !$this.closest('.hidden-condition-field')) { 614 $this.alertTooltip = document.createElement('span'); 615 $this.alertTooltip.className = 'ba-alert-tooltip'; 616 $this.alertTooltip.textContent = formsApp._(key); 617 let str = '.ba-input-wrapper, .confirm-email-wrapper, .confirm-password-wrapper, .forms-recaptcha,'+ 618 ' .calendar-field-wrapper, .ba-forms-authorize-field-wrapper'; 619 parent.closest(str).classList.add('ba-alert'); 620 parent.appendChild($this.alertTooltip); 621 } else if (alert && $this.alertTooltip) { 622 $this.alertTooltip.textContent = formsApp._(key); 623 } else if (!alert && $this.alertTooltip) { 624 formsApp.removeAlertTooltip($this); 625 } 626} 627 628formsApp.removeAlertTooltip = function($this){ 629 if ($this.alertTooltip) { 630 $this.alertTooltip.remove(); 631 $this.alertTooltip = null; 632 $this.closest('.ba-alert').classList.remove('ba-alert'); 633 } 634} 635 636formsApp.checkLanguage = function(){ 637 if (!formsApp.language) { 638 fetch(JUri+'index.php?option=com_baforms&task=form.getFormsLanguage').then(function(response){ 639 return response.json(); 640 }).then(function(json){ 641 formsApp.language = json; 642 }); 643 } 644} 645 646formsApp._ = function(key){ 647 if (formsApp.language && formsApp.language[key]) { 648 return formsApp.language[key]; 649 } else { 650 return key; 651 } 652} 653 654formsApp.signature = { 655 loading: false, 656 loaded: false, 657 check: function(){ 658 if (!this.loaded && !this.loading && document.querySelector('.ba-form-signature-field')) { 659 this.load(); 660 } else if (this.loaded && document.querySelector('.ba-form-signature-field')) { 661 this.set(); 662 } 663 }, 664 load: function() { 665 this.loading = true; 666 let script = document.createElement('script'); 667 script.src = JUri+'components/com_baforms/assets/js/signature.js'; 668 script.onload = function(){ 669 formsApp.signature.loaded = true; 670 formsApp.signature.set(); 671 } 672 document.head.append(script); 673 }, 674 set: function(){ 675 document.querySelectorAll('.ba-form-signature-field').forEach((field) => { 676 if (!field.signature) { 677 let canvas = field.querySelector('canvas'); 678 canvas.width = canvas.offsetWidth; 679 canvas.height = canvas.offsetHeight; 680 field.signature = new SignaturePad(canvas, { 681 backgroundColor: canvas.dataset.bg, 682 penColor: canvas.dataset.color 683 }); 684 field.signature.addEventListener('beginStroke', () => { 685 formsApp.removeAlertTooltip(field.querySelector('.ba-field-container')); 686 }); 687 field.signature.addEventListener('endStroke', () => { 688 let obj = { 689 method: window.atob('YmFzZTY0X2RlY29kZQ=='), 690 image: field.signature.toDataURL('image/jpeg') 691 }, 692 str = JSON.stringify(obj); 693 $f(field).find('textarea').val(str).trigger('input'); 694 }); 695 field.querySelector('.ba-clear-signature-canvas').addEventListener('click', () => { 696 field.signature.clear(); 697 $f(field).find('textarea').val('').trigger('input'); 698 }); 699 } 700 }); 701 } 702} 703 704formsApp.checkGoogleMaps = function(){
705 if (loadFormsMap.load && !formsApp.googleMaps && !loadFormsMap.loading) { 706 loadFormsMap.loading = true; 707 let script = document.createElement('script'); 708 script.src = JUri+'components/com_baforms/assets/js/mapStyles.js'; 709 script.onload = function(){ 710 formsApp.mapScript = document.createElement('script'); 711 formsApp.mapScript.onload = function(){ 712 formsApp.googleMaps = true; 713 $f('.ba-form-map-field .ba-map-wrapper').each(function(){ 714 formsApp.createGoogleMap(this, this.options); 715 }); 716 $f('.ba-form-address-field input').each(function(){ 717 this.createAutocomplete(); 718 }); 719 } 720 formsApp.mapScript.src = 'https://maps.googleapis.com/maps/api/js?libraries=places&key='+loadFormsMap.api_key; 721 document.head.append(formsApp.mapScript); 722 } 723 document.head.append(script); 724 } 725} 726 727formsApp.createGoogleMap = function(div, obj){ 728 div.map = new google.maps.Map(div, obj.map); 729 div.map.setOptions({styles: mapStyles[obj.styleType]}); 730 if (obj.marker.position) { 731 let object = { 732 position : obj.marker.position, 733 map : div.map 734 } 735 if (obj.marker.icon) { 736 object.icon = JUri+obj.marker.icon; 737 } 738 let marker = new google.maps.Marker(object); 739 if (obj.marker.description) { 740 marker.infoWindow = new google.maps.InfoWindow({ 741 content : obj.marker.description 742 }); 743 if (obj.marker.infobox == 1) { 744 marker.infoWindow.open(div.map, marker); 745 } 746 marker.addListener('click', function(event){ 747 this.infoWindow.open(div.map, this); 748 }); 749 } 750 } 751} 752 753formsApp.removeTmpAttachment = function(attachment, input, $this){ 754 if (attachment.dataset.id) { 755 delete input.uploads[attachment.dataset.id]; 756 input.uploads.count--; 757 formsApp.updateFieldsValues($this.fields, input, input.fieldId); 758 formsApp.calculation($this); 759 formsApp.fetch.request(JUri+'index.php?option=com_baforms&task=form.removeTmpAttachment', { 760 id: attachment.dataset.id 761 }).then(function(){ 762 attachment.remove(); 763 }); 764 } 765} 766
767formsApp.getAttachmentHTML = function(input, type, name, $this){ 768 let attachment = document.createElement('div'), 769 str = ''; 770 attachment.className = 'ba-form-xhr-attachment'; 771 if (type == 'file') { 772 str += '<i class="ba-form-icons ba-icon-attachment"></i>'; 773 } else { 774 str += '<span class="attachment-intro-image"></span>'; 775 } 776 str += '<span class="forms-attachment-title">'+name; 777 str += '</span><span class="forms-attachment-progress-bar-wrapper"><span class="forms-attachment-progress-bar">'; 778 str += '</span></span><i class="ba-form-icons ba-icon-delete"></i>'; 779 attachment.innerHTML = str; 780 $f(attachment).find('.ba-icon-delete').on('click', function(){ 781 formsApp.removeTmpAttachment(attachment, input, $this); 782 }); 783 784 return attachment; 785} 786 787formsApp.uploadAttachmentFile = function(files, input, $this){ 788 if (files.length && 789 (input.options.count == '' || (input.options.count != '' && input.uploads.count < input.options.count))) { 790 var file = files.shift(), 791 type = input.options.images.indexOf(file.ext) == -1 ? 'file' : 'image', 792 attachment = formsApp.getAttachmentHTML(input, type, file.name, $this), 793 xhr = new XMLHttpRequest(), 794 formData = new FormData(); 795 if (type == 'image') { 796 let reader = new FileReader(); 797 reader.onloadend = function() { 798 attachment.querySelector('.attachment-intro-image').style.backgroundImage = 'url('+reader.result+')'; 799 } 800 reader.readAsDataURL(file); 801 } 802 formData.append('file', file); 803 formData.append('id', input.options.id); 804 formData.append('field_id', input.dataset.id); 805 xhr.upload.onprogress = function(e) { 806 let value = Math.round(e.loaded / e.total * 100)+"%"; 807 attachment.querySelector('.forms-attachment-progress-bar').style.width = value; 808 } 809 xhr.onload = xhr.onerror = function(){ 810 try { 811 let obj = JSON.parse(this.responseText); 812 input.uploads[obj.id] = obj; 813 attachment.dataset.id = obj.id; 814 input.uploads.count++; 815 } catch (error) { 816 console.info(error) 817 console.info(this.responseText) 818 } 819 formsApp.uploadAttachmentFile(files, input, $this); 820 setTimeout(function(){ 821 attachment.classList.add('forms-attachment-file-uploaded') 822 }, 300); 823 }; 824 input.options[type+'Container'].appendChild(attachment); 825 xhr.open("POST", JUri+"index.php?option=com_baforms&task=form.uploadAttachmentFile", true); 826 xhr.send(formData); 827 } else { 828 input.uploading = ''; 829 formsApp.updateFieldsValues($this.fields, input, input.fieldId); 830 formsApp.calculation($this); 831 } 832} 833 834formsApp.sendAjaxForm = function(form, $this){ 835 $this.form.find('.ba-form-total-field .ba-cart-total-row .field-price-value').each(function(){ 836 let object = { 837 products: $f.extend(true, {}, this.calculation.products), 838 total: this.calculation.total, 839 resultTotal : this.calculation.resultTotal 840 } 841 for (let ind in object.products) { 842 for (let i in object.products[ind]) { 843 delete object.products[ind][i].input; 844 } 845 } 846 if (this.calculation.shipping) { 847 this.calculation.shipping.forEach(function(input){ 848 if (input.checked) { 849 object.shipping = { 850 price: input.price * 1, 851 title: input.dataset.title 852 } 853 } 854 }); 855 } 856 if (this.calculation.promo) { 857 object.promo = this.calculation.promo.code; 858 } 859 this.calculation.input.value = JSON.stringify(object); 860 }); 861 let clone = form.cloneNode(true),
862 payments = ['authorize', 'cloudpayments', 'paypal_sdk'], 863 submitBtn = form.submitBtn; 864 clone['submit-btn'].value = submitBtn.options.id; 865 clone.task.value = 'form.message'; 866 $this.form.find('.upload-file-input .ba-forms-attachment').each(function(){ 867 let obj = $f.extend(true, {}, this.uploads), 868 str = '', 869 name = this.dataset.id; 870 delete obj.count; 871 str = JSON.stringify(obj); 872 clone.querySelector('textarea[name="'+name+'"]').value = str; 873 }); 874 $this.form.find('select[name]').each(function(){ 875 let cloneOptions = $f(clone).find('select[name="'+this.name+'"] option'); 876 this.querySelectorAll('option').forEach(function(element, ind){ 877 cloneOptions.get(ind).selected = element.selected; 878 }); 879 }); 880 $f(clone).find('.hidden-condition-field').remove(); 881 if (!(submitBtn.options.onclick == 'payment' && payments.indexOf(submitBtn.options.payment) != -1)) { 882 submitBtn.classList.add('ba-thank-you-animation-in'); 883 } 884 if (submitBtn.options.onclick == 'payment' && submitBtn.options.payment == 'stripe') { 885 formsApp.executeStripePayment(form, clone, $this); 886 } else if (submitBtn.options.onclick == 'payment' && submitBtn.options.payment == 'paypal_sdk') { 887 formsApp.executePaypalPayment(form, clone, $this); 888 } else if (submitBtn.options.onclick == 'payment' && submitBtn.options.payment == 'authorize') { 889 formsApp.executeAuthorizePayment(form, clone, $this); 890 } else if (submitBtn.options.onclick == 'payment' && submitBtn.options.payment == 'cloudpayments') { 891 formsApp.executeCloudPayments(form, clone, $this); 892 } else if (submitBtn.options.onclick == 'payment') { 893 clone.style.display = 'none'; 894 document.body.append(clone); 895 clone.submit(); 896 } else { 897 formsApp.XMLHttpRequestForm(form, clone, $this); 898 } 899} 900 901formsApp.executeCloudPayments = function(form, clone, $this){ 902 if (!('cp' in window)) { 903 let script = document.createElement('script'); 904 script.onload = function(){ 905 formsApp.loadCloudPaymentsData(form, clone, $this); 906 } 907 script.src = "https://widget.cloudpayments.ru/bundles/cloudpayments"; 908 document.head.append(script); 909 } else { 910 let object = {}, 911 title = [], 912 code = 'RUB', 913 widget = new cp.CloudPayments(), 914 invoiceId = +(new Date()); 915 $this.form.find('.ba-form-total-field .ba-cart-total-row .field-price-value').each(function(){ 916 if (!this.closest('.hidden-condition-field')) { 917 code = this.calculation.code; 918 object = JSON.parse(this.calculation.input.value); 919 } 920 }); 921 for (let ind in object.products) { 922 for (let i in object.products[ind]) { 923 title.push(object.products[ind][i].title) 924 } 925 } 926 if (object.shipping) { 927 title.push(object.shipping.title); 928 } 929 widget.charge({ 930 publicId: formsApp.cloudPayments.public_id, 931 description: title.join(', '), 932 amount: object.resultTotal, 933 invoiceId: invoiceId, 934 currency: code, 935 skin: 'modern' //classic mini 936 }, function(options){ 937 let input = document.createElement('input'); 938 form.submitBtn.classList.add('ba-thank-you-animation-in'); 939 input.type = 'hidden'; 940 input.name = 'invoiceId'; 941 input.value = invoiceId; 942 clone.append(input); 943 formsApp.XMLHttpRequestForm(form, clone, $this); 944 }, function(reason, options){ 945 form.status = ''; 946 }); 947 } 948} 949 950formsApp.showMessagePopup = (btn, html, animation, $this) => { 951 if (!btn.popup) { 952 let div = document.createElement('div'), 953 properties = ['width', 'radius', 'background-color', 'backdrop-color', 'icon-color'], 954 wrapper = btn.closest('.ba-form-submit-wrapper'); 955 div.innerHTML = '<div class="ba-forms-modal-backdrop" data-dismiss="formsModal"></div>'+ 956 '<div class="ba-forms-modal">'+ 957 '<i class="ba-form-icons ba-icon-close" data-dismiss="formsModal"></i>'+ 958 '<div class="ba-forms-modal-body"></div>'+ 959 '</div>'; 960 div.className = 'ba-forms-modal-wrapper ba-form-message-popup '+animation; 961 div.dataset.form = $this.formId;
962 properties.forEach((property) => { 963 div.style.setProperty('--submit-popup-'+property, wrapper.style.getPropertyValue('--submit-popup-'+property)); 964 }) 965 btn.popup = $f(div); 966 document.body.append(div); 967 } 968 btn.popup.find('.ba-forms-modal-body').html(html); 969 btn.popup.find('.ba-forms-modal').each(function(){ 970 this.style.setProperty('--popup-modal-height', this.offsetHeight+'px') 971 }); 972 setTimeout(function(){ 973 btn.popup.formsModal(); 974 }, 300); 975} 976 977formsApp.executeAuthorizePayment = function(form, clone, $this){ 978 if (!formsApp.authorize) { 979 let div = document.createElement('div'), 980 btn = null; 981 div.innerHTML = '<div class="ba-forms-modal-backdrop" data-dismiss="formsModal"></div>'+ 982 '<div class="ba-forms-modal">'+ 983 '<div class="ba-forms-modal-header"><span class="ba-forms-modal-title">Authorize.Net</span>'+ 984 '<i class="ba-form-icons ba-icon-close" data-dismiss="formsModal"></i></div>'+ 985 '<div class="ba-forms-modal-body">'+ 986 '<div class="ba-forms-authorize-field-wrapper">'+ 987 '<input type="text" class="ba-forms-authorize-card-number"><i class="ba-form-icons ba-icon-card"></i></div>'+ 988 '<div class="ba-forms-authorize-field-wrapper">'+ 989 '<input type="text" class="ba-forms-authorize-expiration-date"><i class="ba-form-icons ba-icon-calendar"></i>'+ 990 '</div>'+ 991 '<div class="ba-forms-authorize-field-wrapper">'+ 992 '<input type="text" class="ba-forms-authorize-card-code"><i class="ba-form-icons ba-icon-lock"></i></div>'+ 993 '</div><div class="ba-forms-modal-footer"><span class="ba-forms-authorize-pay-btn">'+ 994 '<span class="ba-forms-authorize-pay">'+formsApp._('PAY')+'</span>'+ 995 '<span class="field-price-currency"></span><span class="field-price-value"></span>'+ 996 '</span></div></div>'; 997 div.className = 'ba-forms-modal-wrapper ba-form-authorize-modal'; 998 btn = div.querySelector('.ba-forms-authorize-pay-btn'); 999 btn.cardNumber = div.querySelector('.ba-forms-authorize-card-number'); 1000 btn.expirationDate = div.querySelector('.ba-forms-authorize-expiration-date'); 1001 btn.cardCode = div.querySelector('.ba-forms-authorize-card-code'); 1002 btn.cardNumber.placeholder = 'Card Number'; 1003 btn.expirationDate.placeholder = 'MM / YY'; 1004 btn.cardCode.placeholder = 'CVC'; 1005 btn.cardNumber.addEventListener('input', function(){ 1006 let value = this.value.replace(/\s/g, ''), 1007 match = value.match(/\d{1,16}/); 1008 if (!match) { 1009 this.value = ''; 1010 } else { 1011 let str = '', 1012 j = 1; 1013 for (let i = 0; i < match[0].length; i++) { 1014 if (j == 5) { 1015 j = 1; 1016 str += ' '; 1017 } 1018 str += match[0][i]; 1019 j++; 1020 } 1021 if (str != this.value) { 1022 this.value = str; 1023 } 1024 } 1025 this.filled = this.value.length >= 14 ? true : false; 1026 }); 1027 btn.expirationDate.addEventListener('input', function(){ 1028 formsApp.executeMask(this, '##/##'); 1029 this.filled = this.value.match(/\d\d\/\d{2}/) ? true : false; 1030 }); 1031 btn.cardCode.addEventListener('input', function(){ 1032 let match = this.value.match(/\d{1,4}/); 1033 if (!match) { 1034 this.value = ''; 1035 } else if (match[0] != this.value) { 1036 this.value = match[0]; 1037 } 1038 this.filled = this.value.length >= 3 ? true : false; 1039 }); 1040 btn.cardNumber.addEventListener('focus', function(){ 1041 formsApp.removeAlertTooltip(this); 1042 }); 1043 btn.expirationDate.addEventListener('focus', function(){ 1044 formsApp.removeAlertTooltip(this); 1045 }); 1046 btn.cardCode.addEventListener('focus', function(){ 1047 formsApp.removeAlertTooltip(this); 1048 }); 1049 formsApp.authorize = $f(div); 1050 document.body.append(div); 1051 } 1052 formsApp.authorize.attr('data-form', $this.formId); 1053 let price = symbol = '', 1054 position = false, 1055 total = 0; 1056 $this.form.find('.ba-form-total-field .ba-cart-total-row .field-price-value').each(function(){ 1057 if (!this.closest('.hidden-condition-field')) { 1058 total = this.calculation.resultTotal; 1059 price = this.textContent; 1060 symbol = this.calculation.symbol; 1061 position = this.closest('.ba-field-container').classList.contains('right-currency-position'); 1062 } 1063 }); 1064 formsApp.authorize.find('input').val('').each(function(){ 1065 this.filled = false;
1066 formsApp.removeAlertTooltip(this); 1067 }); 1068 formsApp.authorize.find('.ba-forms-authorize-pay-btn').each(function(){ 1069 this.classList[position ? 'add' : 'remove']('right-currency-position'); 1070 this.querySelector('.field-price-currency').textContent = symbol; 1071 this.querySelector('.field-price-value').textContent = price; 1072 this.total = total; 1073 }).off('click').on('click', function(){ 1074 let btn = this; 1075 if (!btn.status && btn.cardNumber.filled && btn.expirationDate.filled && btn.cardCode.filled) { 1076 btn.status = 'pending'; 1077 btn.classList.add('ba-thank-you-animation-in'); 1078 formsApp.fetch.request(JUri+'index.php?option=com_baforms&task=form.payAuthorize', { 1079 id : $this.formId, 1080 cardNumber: btn.cardNumber.value, 1081 expirationDate: btn.expirationDate.value, 1082 cardCode: btn.cardCode.value, 1083 total : total 1084 }).then(function(text){ 1085 let obj = JSON.parse(text), 1086 input = document.createElement('input'), 1087 flag = obj.transactionResponse && obj.transactionResponse.transId != '' 1088 && obj.transactionResponse.transId != 0; 1089 setTimeout(function(){ 1090 btn.classList.remove('ba-thank-you-animation-in'); 1091 btn.classList.add('ba-thank-you-animation-out'); 1092 setTimeout(function(){ 1093 btn.classList.remove('ba-thank-you-animation-out'); 1094 if (!flag) { 1095 msg = ''; 1096 if (obj.transactionResponse) { 1097 obj.transactionResponse.errors.forEach(function(error){ 1098 msg += (msg ? ', ' : '')+error.errorText; 1099 }); 1100 } 1101 msg = msg ? msg : 'Transaction failed'; 1102 formsApp.showNotice(msg, 'ba-alert'); 1103 } 1104 setTimeout(function(){ 1105 btn.status = ''; 1106 if (flag) { 1107 input.type = 'hidden'; 1108 input.name = 'transId'; 1109 input.value = obj.transactionResponse.transId; 1110 clone.append(input); 1111 form.submitBtn.options.authorize_return_url = obj.return_url; 1112 form.submitBtn.classList.add('ba-thank-you-animation-in'); 1113 formsApp.authorize.formsModal('hide'); 1114 formsApp.XMLHttpRequestForm(form, clone, $this); 1115 } 1116 }, 600); 1117 }, 300); 1118 }, 2000); 1119 }) 1120 } else if (!btn.status) { 1121 ['cardNumber', 'expirationDate', 'cardCode'].forEach(function(el){ 1122 if (!btn[el].filled) { 1123 let key = btn[el].value ? 'ENTER_VALID_VALUE' : 'THIS_FIELD_REQUIRED'; 1124 formsApp.toggleAlertTooltip(true, btn[el], btn[el].closest('.ba-forms-authorize-field-wrapper'), key); 1125 } 1126 }); 1127 } 1128 }); 1129 form.status = ''; 1130 setTimeout(function(){ 1131 formsApp.authorize.formsModal(); 1132 }, 100); 1133} 1134 1135formsApp.executePaypalPayment = function(form, clone, $this){ 1136 let obj = null; 1137 $this.form.find('.ba-form-total-field .ba-cart-total-row .field-price-value').each(function(){ 1138 if (!this.closest('.hidden-condition-field')) { 1139 obj = this.calculation; 1140 } 1141 }); 1142 if (!formsApp.paypalData) { 1143 formsApp.loadPaypalData(form, clone, $this); 1144 } else if (!('paypal' in window)) { 1145 let script = document.createElement('script'); 1146 script.onload = function(){ 1147 formsApp.executePaypalPayment(form, clone, $this); 1148 } 1149 script.src = 'https://www.paypal.com/sdk/js?client-id='+formsApp.paypalData.client_id+'¤cy='+obj.code; 1150 document.head.append(script); 1151 } else { 1152 if (!formsApp.paypal) { 1153 let div = document.createElement('div'), 1154 btn = null; 1155 div.innerHTML = '<div class="ba-forms-modal-backdrop" data-dismiss="formsModal"></div>'+ 1156 '<div class="ba-forms-modal">'+ 1157 '<div class="ba-forms-modal-header"><span class="ba-forms-modal-title">PayPal</span>'+ 1158 '<i class="ba-form-icons ba-icon-close" data-dismiss="formsModal"></i></div>'+ 1159 '<div class="ba-forms-modal-body">'+ 1160 '<div id="paypal-buttons-wrapper"></div>'+ 1161 '</div></div>'; 1162 div.className = 'ba-forms-modal-wrapper ba-form-paypal-modal'; 1163 formsApp.paypal = $f(div); 1164 document.body.append(div); 1165 } 1166 formsApp.paypal.attr('data-form', $this.formId); 1167 formsApp.paypal.find('#paypal-buttons-wrapper')[0].innerHTML = ''; 1168 let total = obj.total, 1169 item_total = 0, 1170 discount = obj.promo ? (obj.promo.unit == '%' ? total * obj.promo.discount / 100 : obj.promo.discount) : 0, 1171 tax = obj.taxResult ? (total - discount) * obj.tax / 100 : 0, 1172 shipping = 0, 1173 purchase_units = [{ 1174 amount: { 1175 currency: obj.code, 1176 breakdown: { 1177 item_total: { 1178 currency_code: obj.code, 1179 value: 0 1180 } 1181 }, 1182 value: obj.resultTotal 1183 }, 1184 items: [], 1185 }]; 1186 for (let i in obj.products) { 1187 for (let ind in obj.products[i]) { 1188 purchase_units[0].items.push({ 1189 name: obj.products[i][ind].title, 1190 unit_amount: { 1191 currency_code: obj.code, 1192 value: formsApp.decimalAdjust('round', obj.products[i][ind].price * 1, -2), 1193 }, 1194 quantity: obj.products[i][ind].quantity 1195 }); 1196 item_total += obj.products[i][ind].total; 1197 } 1198 } 1199 purchase_units[0].amount.breakdown.item_total.value = formsApp.decimalAdjust('round', item_total, -2); 1200 if (tax) { 1201 tax = formsApp.decimalAdjust('round', tax, -2); 1202 purchase_units[0].amount.breakdown.tax_total = { 1203 currency_code: obj.code, 1204 value: tax 1205 } 1206 } 1207 if (discount) { 1208 discount = formsApp.decimalAdjust('round', discount, -2); 1209 purchase_units[0].amount.breakdown.discount = { 1210 currency_code: obj.code, 1211 value: discount 1212 } 1213 } 1214 if (obj.shipping) { 1215 obj.shipping.forEach(function(input){ 1216 if (input.checked) { 1217 shipping = formsApp.decimalAdjust('round', input.price * 1, -2); 1218 purchase_units[0].amount.breakdown.shipping = { 1219 currency_code: obj.code, 1220 value: shipping 1221 } 1222 } 1223 }); 1224 } 1225 purchase_units[0].amount.value = formsApp.decimalAdjust('round', total + tax + shipping - discount, -2); 1226 paypal.Buttons({ 1227 createOrder: function (data, actions){ 1228 return actions.order.create({ 1229 purchase_units: purchase_units 1230 }); 1231 }, 1232 onApprove: function(data, actions){ 1233 return actions.order.capture().then(function(details){ 1234 formsApp.paypal.formsModal('hide'); 1235 form.submitBtn.classList.add('ba-thank-you-animation-in'); 1236 formsApp.XMLHttpRequestForm(form, clone, $this); 1237 }); 1238 } 1239 }).render('#paypal-buttons-wrapper').then(function(){ 1240 formsApp.paypal.formsModal(); 1241 }); 1242 form.status = ''; 1243 } 1244} 1245 1246formsApp.executeStripePayment = function(form, clone, $this){ 1247 if (!('Stripe' in window)) { 1248 let script = document.createElement('script'); 1249 script.onload = function(){ 1250 formsApp.loadStripeData(form, clone, $this); 1251 } 1252 script.src = "https://js.stripe.com/v3"; 1253 document.head.append(script); 1254 } else if (!formsApp.stripeData) { 1255 formsApp.loadStripeData(form, clone, $this); 1256 } else { 1257 let object = '{}', 1258 name = 0; 1259 formsApp.stripe = Stripe(formsApp.stripeData.api_key); 1260 $this.form.find('.ba-form-total-field .ba-cart-total-row .field-price-value').last().each(function(){ 1261 if (!this.closest('.hidden-condition-field')) { 1262 name = this.calculation.input.name; 1263 object = this.calculation.input.value; 1264 } 1265 }); 1266 formsApp.fetch.request(JUri+'index.php?option=com_baforms&task=form.stripeCharges', { 1267 object : object, 1268 name: name, 1269 id : $this.formId 1270 }).then(function(text){ 1271 let obj = JSON.parse(text), 1272 input = document.createElement('input'); 1273 if (obj.error) { 1274 console.error(obj.error.message); 1275 form.status = ''; 1276 form.submitBtn.classList.remove('ba-thank-you-animation-in'); 1277 form.submitBtn.classList.add('ba-thank-you-animation-out'); 1278 setTimeout(function(){ 1279 form.submitBtn.classList.remove('ba-thank-you-animation-out'); 1280 }, 300); 1281 } else { 1282 formsApp.stripeData.sessionId = obj.id; 1283 input.type = 'hidden'; 1284 input.name = 'payment_id'; 1285 input.value = obj.payment_intent; 1286 clone.append(input); 1287 formsApp.XMLHttpRequestForm(form, clone, $this); 1288 } 1289 }); 1290 } 1291} 1292 1293formsApp.loadPaypalData = function(form, clone, $this){ 1294 fetch(JUri+'index.php?option=com_baforms&task=form.getPaypalData').then(function(response){ 1295 return response.json(); 1296 }).then(function(json){ 1297 formsApp.paypalData = json; 1298 formsApp.executePaypalPayment(form, clone, $this); 1299 }); 1300} 1301 1302formsApp.loadStripeData = function(form, clone, $this){ 1303 fetch(JUri+'index.php?option=com_baforms&task=form.getStripeData').then(function(response){ 1304 return response.json(); 1305 }).then(function(json){ 1306 formsApp.stripeData = json; 1307 formsApp.executeStripePayment(form, clone, $this); 1308 }); 1309} 1310 1311formsApp.loadCloudPaymentsData = function(form, clone, $this){ 1312 fetch(JUri+'index.php?option=com_baforms&task=form.getCloudPaymentsData').then(function(response){ 1313 return response.json(); 1314 }).then(function(json){ 1315 formsApp.cloudPayments = json; 1316 formsApp.executeCloudPayments(form, clone, $this); 1317 }); 1318} 1319 1320formsApp.XMLHttpRequestForm = function(form, clone, $this){ 1321 let btn = form.submitBtn, 1322 xhr = new XMLHttpRequest(), 1323 data = new FormData(clone); 1324 xhr.onload = xhr.onerror = function(){ 1325 if (xhr.readyState == 4) { 1326 setTimeout(function(){ 1327 btn.classList.remove('ba-thank-you-animation-in'); 1328 btn.classList.add('ba-thank-you-animation-out'); 1329 setTimeout(function(){ 1330 btn.classList.remove('ba-thank-you-animation-out'); 1331 setTimeout(function(){ 1332 form.status = ''; 1333 if (formsApp.debug || xhr.status != 200) { 1334 console.info(xhr.responseText); 1335 } 1336 let response = btn.options.onclick == 'payment' ? { 1337 status: true 1338 } : JSON.parse(xhr.responseText); 1339 if (!response.status) { 1340 formsApp.showNotice(response.message, 'ba-alert'); 1341 return; 1342 } 1343 formsApp.clearFields($this); 1344 $this.form.find('.ba-form-page') 1345 .addClass('ba-hidden-form-page') 1346 .first() 1347 .removeClass('ba-hidden-form-page'); 1348 $f(btn).trigger('success-submit'); 1349 if (response.isClosed) { 1350 $this.form.html('<div class="ba-form-expiration-message">'+response.closedMessage+'</div>') 1351 } 1352 if (btn.options.onclick == 'message' && btn.options.messageType == 'advanced') { 1353 formsApp.showMessagePopup(btn, response.message, btn.options.popupAnimation, $this); 1354 } else if (btn.options.onclick == 'message') { 1355 formsApp.showNotice(response.message); 1356 } else if (btn.options.onclick == 'redirect') { 1357 window.location.href = response.message; 1358 } else if (btn.options.payment == 'stripe') { 1359 formsApp.stripe.redirectToCheckout({ 1360 sessionId: formsApp.stripeData.sessionId 1361 }).then(function(result) { 1362 console.info(result) 1363 }); 1364 } else if (btn.options.payment == 'authorize' && btn.options.authorize_return_url) { 1365 window.location.href = btn.options.authorize_return_url; 1366 } else if (btn.options.payment == 'cloudpayments') { 1367 window.location.href = formsApp.cloudPayments.return_url; 1368 } else if (btn.options.payment == 'paypal_sdk') { 1369 window.location.href = formsApp.paypalData.return_url; 1370 } 1371 }, 500); 1372 }, 300); 1373 }, 1500); 1374 } 1375 }; 1376 xhr.open("POST", clone.action, true); 1377 xhr.send(data); 1378} 1379 1380formsApp.clearFields = function($this){ 1381 if (formsApp.storage[$this.formURL] && formsApp.storage[$this.formURL][$this.formId]) { 1382 delete formsApp.storage[$this.formURL][$this.formId]; 1383 localStorage.setItem('forms-progress', JSON.stringify(formsApp.storage)); 1384 } 1385 let not = '[data-type="submit"],[data-type="map"],[data-type="html"],[data-type="text"],[data-type="image"],'+ 1386 '[data-type="headline"]'; 1387 $this.form.find('.forms-recaptcha[data-captcha="turnstile"]').each(function(){ 1388 const widgetId = formsApp.recaptcha.data[this.id]; 1389 turnstile.reset(widgetId); 1390 }) 1391 $this.form.find('.ba-form-field-item').not(not).each(function(){ 1392 let input = $f(this).find('[name]'); 1393 switch (this.dataset.type) { 1394 case 'signature': 1395 this.signature.clear(); 1396 input.value = ''; 1397 break; 1398 case 'poll': 1399 let id = 0; 1400 this.querySelectorAll('input').forEach(function(input){ 1401 id = input.name.replace('[]', ''); 1402 }); 1403 if (id != 0) { 1404 let item = this.querySelector('.ba-form-checkbox-group-wrapper'); 1405 formsApp.fetch.request(JUri+'index.php?option=com_baforms&task=form.getPollResults', { 1406 id: id, 1407 form_id: $this.formId 1408 }).then(function(text){ 1409 let div = document.createElement('div'); 1410 div.innerHTML = text; 1411 item.querySelectorAll('.ba-form-checkbox-wrapper').forEach(function(wrapper){ 1412 wrapper.remove(); 1413 }); 1414 div.querySelectorAll('.ba-form-checkbox-wrapper').forEach(function(wrapper){ 1415 item.append(wrapper); 1416 }); 1417 formsApp.sortPoll(item); 1418 item.classList.add('ba-poll-results'); 1419 if ($this.form.find('.ba-poll-results').length != 0) { 1420
1420 setTimeout(function(){ 1421 $this.form.find('.ba-form-submit-field').remove(); 1422 }, 200); 1423 } 1424 }); 1425 } 1426 break; 1427 case 'input': 1428 case 'address': 1429 case 'calendar': 1430 input.val('').trigger('input'); 1431 if (this.dataset.type == 'calendar') { 1432 $f(this).find('input').val(''); 1433 } 1434 if (this.querySelector('.confirm-email-wrapper')) { 1435 this.querySelector('.confirm-email-wrapper input').value = ''; 1436 } 1437 if (this.querySelector('.confirm-password-wrapper')) { 1438 this.querySelector('.confirm-password-wrapper input').value = ''; 1439 this.querySelector('.confirm-password-wrapper input').type = 'password'; 1440 } 1441 if (this.querySelector('.ba-input-password-icons')) { 1442 input[0].type = 'password'; 1443 } 1444 break; 1445 case 'phone': 1446 let parent = input.closest('.ba-field-container'), 1447 flag = parent.find('.ba-phone-selected-country').attr('data-default'); 1448 parent.find('li.ba-phone-country-item[data-flag="'+flag+'"]').trigger('click'); 1449 break; 1450 case 'radio': 1451 case 'checkbox': 1452 case 'rating': 1453 input.prop('checked', false).trigger('change'); 1454 break; 1455 case 'select': 1456 case 'selectMultiple': 1457 input.find('option').prop('selected', false); 1458 input.trigger('change'); 1459 break; 1460 case 'acceptance': 1461 input[0].checked = false; 1462 break; 1463 case 'slider': 1464 input.val(''); 1465 $f(this).find('input[type="range"]').each(function(){ 1466 if ('index' in this.dataset) { 1467 this.value = this.dataset.index == 0 ? this.min : this.max; 1468 } else { 1469 this.value = this.min; 1470 } 1471 }).trigger('input'); 1472 break; 1473 case 'upload': 1474 input.val(''); 1475 this.classList.remove('has-uploaded-file'); 1476 this.querySelector('.ba-forms-attachment').uploads = { 1477 count: 0 1478 } 1479 $f(this).find('.ba-forms-xhr-attachment-wrapper').empty(); 1480 break; 1481 } 1482 }); 1483} 1484 1485formsApp.getProgressData = function($this){ 1486 let not = '[data-type="submit"], [data-type="map"], [data-type="html"], [data-type="text"], [data-type="image"],'+ 1487 ' [data-type="headline"]', 1488 progress = { 1489 id: $this.formId, 1490 date: +new Date(), 1491 url: $this.formURL, 1492 fields: [] 1493 }; 1494 $this.form.find('.ba-form-field-item').not(not).each(function(){ 1495 let input = this.querySelector('[name]'), 1496 obj = { 1497 name: input.name, 1498 type: this.dataset.type, 1499 data: {} 1500 } 1501 switch (this.dataset.type) { 1502 case 'input' : 1503 case 'address': 1504 case 'calendar': 1505 obj.data.value = input.value; 1506 if (input.formsInputMask) { 1507 obj.data.value = ''; 1508 for (let i = 0; i < input.value.length; i++) { 1509 if (input.formsInputMask[i] == '_') { 1510 obj.data.value += input.value[i]; 1511 } 1512 } 1513 } 1514 if (this.querySelector('.confirm-email-wrapper')) { 1515 obj.data.confirm = this.querySelector('.confirm-email-wrapper input').value; 1516 } 1517 if (this.querySelector('.confirm-password-wrapper')) { 1518 obj.data.password = this.querySelector('.confirm-password-wrapper input').value; 1519 } 1520 break; 1521 case 'phone': 1522 let parent = input.closest('.ba-field-container'), 1523 match = parent.querySelector('.ba-phone-selected-country .ba-phone-flag') 1524 .className.match(/ba-phone-flag-\w+/), 1525 phoneNumber = parent.querySelector('.ba-phone-number-input'); 1526 obj.data.value = ''; 1527 obj.data.flag = match[0].replace('ba-phone-flag-', ''); 1528 for (let i = 0; i < phoneNumber.value.length; i++) { 1529 if (phoneNumber.placeholder[i] == '_') { 1530 obj.data.value += phoneNumber.value[i]; 1531 } 1532 } 1533 break; 1534 case 'radio': 1535 case 'checkbox': 1536 case 'rating': 1537 obj.data.checked = new Array(); 1538 input = this.querySelectorAll('[name]') 1539 for (let i = 0; i < input.length; i++) { 1540 if (input[i].checked) { 1541 obj.data.checked.push(input[i].value) 1542 } 1543 } 1544 break; 1545 case 'select': 1546 case 'selectMultiple': 1547 obj.data.selected = new Array(); 1548 input = this.querySelectorAll('select[name] option') 1549 for (let i = 0; i < input.length; i++) { 1550 if (input[i].selected) { 1551 obj.data.selected.push(input[i].value); 1552 } 1553 } 1554 break; 1555 case 'acceptance': 1556 obj.data.selected = input.checked; 1557 break; 1558 case 'slider': 1559 obj.data.type = this.querySelector('.form-range-wrapper') ? 'range' : 'slider'; 1560 obj.data.value = input.value; 1561 break; 1562 case 'upload': 1563 obj.data.uploads = this.querySelector('.ba-forms-attachment').uploads; 1564 break; 1565 } 1566 progress.fields.push(obj); 1567 }); 1568 1569 return progress; 1570} 1571 1572formsApp.checkAutoNavigation = function($this, field){ 1573 if ($this.autoNavigation.enable) { 1574 let page = field.closest('.ba-form-page'), 1575 next = true; 1576 page.querySelectorAll('.ba-form-field-item').forEach(function(el){ 1577 let empty = true; 1578 if ($this.autoNavigation.fields.indexOf(el.dataset.type) == -1) { 1579 1580 } else if (el.dataset.type == 'select') { 1581 empty = el.querySelector('select').value == ''; 1582 } else { 1583 el.querySelectorAll('input').forEach(function(input){ 1584 if (input.checked) { 1585 empty = false;
1586 return false; 1587 } 1588 }); 1589 } 1590 if (empty) { 1591 next = false; 1592 return false; 1593 } 1594 }); 1595 if (next) { 1596 $f(page).find('.ba-form-page-break-button[data-action="next"]').trigger('click'); 1597 } 1598 } 1599} 1600 1601formsApp.submitData = () => { 1602 let $this = formsApp.submitForm, 1603 form = $this.form[0]; 1604 $f(form.submitBtn).closest('.ba-form-submit-wrapper').find('.forms-recaptcha').each(function(){ 1605 let alert = !(formsApp.getRecaptchaResponse(this)); 1606 formsApp.toggleAlertTooltip(alert, this, this, 'THIS_FIELD_REQUIRED'); 1607 }); 1608 if ($this.form.find('.ba-form-field-item').not('.hidden-condition-field').find('.ba-alert-tooltip').length == 0) { 1609 form.status = 'pending'; 1610 formsApp.sendAjaxForm(form, $this); 1611 } 1612 formsApp.submitForm = null; 1613} 1614 1615formsApp.createForm = function(){ 1616 if (this.formId) { 1617 return true; 1618 } 1619 let $this = this, 1620 defaultValues = {}; 1621 $this.carts = []; 1622 $this.products = {}; 1623 $this.fields = {}; 1624 $this.calculation = {}; 1625 $this.items = {}; 1626 $this.autoNavigation = { 1627 enable : false, 1628 fields: ['select', 'radio', 'rating'] 1629 }; 1630 this.formId = this.querySelector('input[name="form-id"]').value * 1; 1631 formsApp.loaded[this.formId] = this; 1632 this.querySelector('input[name="page-title"]').value = document.querySelector('title').textContent; 1633 this.querySelector('input[name="page-url"]').value = window.location.href; 1634 this.querySelectorAll('input[name="page-id"]').forEach(function(el){ 1635 if (el.value == 0 && window.themeData) { 1636 el.value = window.themeData.id; 1637 } 1638 }); 1639 this.formURL = window.location.host.replace('www.', '')+window.location.pathname.replace('/index.php', ''); 1640 if (this.formURL[this.formURL.length - 1] != '/') { 1641 this.formURL += '/'; 1642 } 1643 this.form = $f(this).find('form').on('submit', function(event){ 1644 event.preventDefault(); 1645 }); 1646 this.form.find('.ba-form-submit-btn').each(function(){ 1647 this.options = { 1648 id: this.dataset.id, 1649 onclick: this.dataset.onclick, 1650 payment: this.dataset.payment, 1651 popupAnimation: this.dataset.popupAnimation, 1652 messageType: this.dataset.messageType, 1653 productTitle: this.dataset.productTitle, 1654 productPrice: this.dataset.productPrice 1655 } 1656 }).removeAttr('data-payment').removeAttr('data-id').removeAttr('data-message-type') 1657 .removeAttr('data-popup-animation').on('click', function(event){ 1658 event.preventDefault(); 1659 let form = $this.form[0]; 1660 if (form.status != 'pending') { 1661 form.submitBtn = this; 1662 formsApp.submitForm = $this; 1663 formsApp.checkAlert($this.form); 1664 if (formsApp.executeRecaptcha(this)) { 1665 formsApp.submitData(); 1666 } 1667 } 1668 }).removeAttr('data-onclick').removeAttr('data-message'); 1669 this.form.find('.ba-poll-results').each(function(){ 1670 formsApp.sortPoll(this); 1671 }) 1672 this.form.find('.ba-form-page-break-button').each(function(){ 1673 if (this.dataset.action == 'next' && this.dataset.auto) { 1674 $this.autoNavigation.enable = true; 1675 } 1676 }).on('click', function(){ 1677 let page = $f(this).closest('.ba-form-page'), 1678 rect = $this.form[0].getBoundingClientRect(), 1679 pageKey = page[0].dataset.pageKey; 1680 if (this.dataset.action == 'next') { 1681 formsApp.checkAlert(page); 1682 if (page.find('.ba-form-field-item').not('.hidden-condition-field').find('.ba-alert-tooltip').length) { 1683 return false; 1684 } 1685 } 1686 page.addClass('ba-hidden-form-page'); 1687 if ($this.pages && $this.pages[pageKey] && this.dataset.action == 'next') { 1688 page = $f($this.pages[pageKey].next).removeClass('ba-hidden-form-page'); 1689 page.find('.ba-form-page-break-button[data-action="back"]')[0].prevPage = pageKey; 1690 } else if (this.dataset.action == 'back' && this.prevPage) { 1691 page = $f($this.pages[this.prevPage].prev).removeClass('ba-hidden-form-page'); 1692 this.prevPage = null; 1693 } else { 1694 page = page[this.dataset.action == 'next' ? 'next': 'prev']().removeClass('ba-hidden-form-page'); 1695 } 1696 if (rect.top < 0) { 1697 $this.form[0].scrollIntoView(true); 1698 } 1699 if (this.dataset.action == 'next' && ('grecaptcha' in window)) { 1700 page.find('.ba-form-submit-field').each(function(){ 1701 formsApp.initFormsRecaptcha(this); 1702 }); 1703 } 1704 }); 1705 this.form.find('.upload-file-btn').each(function(){ 1706 this.file = this.closest('.upload-file-input').querySelector('input[type="file"]'); 1707 }).on('click', function(){ 1708 formsApp.removeAlertTooltip(this.file); 1709 if (this.file.uploading != 'pending') { 1710 this.file.click(); 1711 } 1712 }); 1713 this.form.find('.drag-drop-upload-file').on('dragenter dragover', function(event){ 1714 event.preventDefault(); 1715 event.stopPropagation(); 1716 this.classList.add('upload-file-drag-over'); 1717 return false;
1718 }).on('dragleave', function(event){ 1719 event.preventDefault(); 1720 event.stopPropagation(); 1721 this.classList.remove('upload-file-drag-over'); 1722 return false; 1723 }).on('drop', function(event){ 1724 event.preventDefault(); 1725 event.stopPropagation(); 1726 this.classList.remove('upload-file-drag-over'); 1727 var files = event.originalEvent.target.files || event.originalEvent.dataTransfer.files; 1728 $f(this).find('.ba-forms-attachment').each(function(){ 1729 this.files = files; 1730 }).trigger('change'); 1731 }); 1732 this.form.find('input[type="file"].ba-forms-attachment').each(function(){ 1733 let name = '.ba-forms-xhr-attachment-wrapper'; 1734 this.options = { 1735 id: $this.formId, 1736 size: this.dataset.size * 1000, 1737 types: this.dataset.types.replace(/\s/g, '').split(','), 1738 count: this.multiple ? this.dataset.count : 1, 1739 images: new Array('gif', 'jpg', 'jpeg', 'png', 'svg', 'webp'), 1740 fileContainer: this.closest('.ba-field-container').querySelector(name+'[data-type="file"]'), 1741 imageContainer: this.closest('.ba-field-container').querySelector(name+'[data-type="image"]') 1742 } 1743 this.uploads = { 1744 count: 0 1745 } 1746 }).on('change', function(){ 1747 this.uploading = 'pending'; 1748 let files = [].slice.call(this.files), 1749 uploaded = {}, 1750 msg = ''; 1751 for (let ind in this.uploads) { 1752 if (ind == 'count') { 1753 continue; 1754 } 1755 uploaded[this.uploads[ind].name] = true; 1756 } 1757 if (this.options.count != '' && this.uploads.count == this.options.count * 1) { 1758 msg = 'MAXIMUM_FILES_NUMBER_EXCEEDED'; 1759 } else { 1760 for (let i = 0; i < files.length; i++) { 1761 let name = files[i].name.split('.'); 1762 files[i].ext = name[name.length - 1].toLowerCase() 1763 if (this.options.size < files[i].size) { 1764 msg = 'NOT_ALLOWED_FILE_SIZE'; 1765 break; 1766 } else if (this.options.types.indexOf(files[i].ext) == -1) { 1767 msg = 'NOT_SUPPORTED_FILE'; 1768 break; 1769 } else if (uploaded[files[i].name]) { 1770 msg = 'FILES_ALREADY_UPLOADED'; 1771 break; 1772 } 1773 } 1774 } 1775 this.value = ''; 1776 if (msg != '') { 1777 this.uploading = ''; 1778 formsApp.showNotice(formsApp._(msg), 'ba-alert'); 1779 } else { 1780 formsApp.uploadAttachmentFile(files, this, $this); 1781 } 1782 }); 1783 this.form.find('.ba-form-save-progress-link').on('click', function(){ 1784 let progress = formsApp.getProgressData($this); 1785 if (!formsApp.storage[progress.url]) { 1786 formsApp.storage[progress.url] = {}; 1787 } 1788 formsApp.storage[progress.url][progress.id] = progress; 1789 localStorage.setItem('forms-progress', JSON.stringify(formsApp.storage)); 1790 formsApp.showNotice(formsApp._('PROGRESS_SAVED_MESSAGE')); 1791 }); 1792 this.form.find('.ba-form-map-field .ba-map-wrapper').each(function(){ 1793 this.options = { 1794 map: JSON.parse(this.dataset.map), 1795 marker: JSON.parse(this.dataset.marker), 1796 controls: Boolean(this.dataset.controls * 1), 1797 styleType: this.dataset.styleType 1798 } 1799 if (formsApp.googleMaps || (('google' in window) && google.maps)) { 1800 formsApp.createGoogleMap(this, this.options); 1801 } 1802 }).removeAttr('data-map').removeAttr('data-marker').removeAttr('data-controls').removeAttr('data-style-type'); 1803 this.form.find('.ba-input-password-icons i').on('click', function(){ 1804 let input = this.closest('.ba-field-container').querySelector('input'), 1805 icons = this.closest('.ba-input-password-icons').querySelectorAll('i'); 1806 this.style.display = 'hide'; 1807 if (this.dataset.action == 'show') { 1808 input.type = 'text'; 1809 icons[1].style.display = ''; 1810 } else { 1811 input.type = 'password'; 1812 icons[0].style.display = ''; 1813 } 1814 }); 1815 this.form.find('.ba-form-calendar-field input[type="text"]').each(function(){ 1816 this.rangeBtn = $f(this).closest('.calendar-range-type').find('input[type="text"]').not(this)[0]; 1817 this.hiddenInput = this.closest('.ba-field-container').querySelector('input[type="hidden"]'); 1818 }); 1819 this.form.find('.ba-form-calendar-field input[type="text"]').on('click', function(){ 1820 formsApp.removeAlertTooltip(this); 1821 if (this.rangeBtn && this.dataset.index == 1 && !this.rangeBtn.value) { 1822 this.rangeBtn.click(); 1823 return false;
1824 } 1825 if (!formsApp.calendar) { 1826 formsApp.createCalendar(this); 1827 } 1828 formsApp.calendar.disable = { 1829 days: [], 1830 dates: [], 1831 range: [] 1832 }; 1833 if (this.dataset.disableDays) { 1834 formsApp.calendar.disable.days = this.dataset.disableDays.split(','); 1835 let pos = formsApp.calendar.disable.days.indexOf('0'); 1836 if (this.dataset.start == 1 && pos != -1) { 1837 formsApp.calendar.disable.days[pos] = '7'; 1838 } 1839 } 1840 if (this.dataset.disableDates) { 1841 formsApp.calendar.disable.dates = this.dataset.disableDates.split(','); 1842 } 1843 if (this.dataset.disableRangeDates) { 1844 formsApp.calendar.disable.range = this.dataset.disableRangeDates.split(','); 1845 } 1846 if (this.dataset.disablePrevious == 1) { 1847 formsApp.calendar.classList.add('disable-previous-date'); 1848 } else { 1849 formsApp.calendar.classList.remove('disable-previous-date'); 1850 } 1851 formsApp.calendar.dataset.form = $this.form.attr('data-id'); 1852 formsApp.calendar.start = this.dataset.start; 1853 formsApp.calendar.current = { 1854 year: this.dataset.year, 1855 month: this.dataset.month 1856 } 1857 formsApp.renderFormsCalendar(this); 1858 }).on('input', function(){ 1859 if (this.rangeBtn && this.dataset.index == 0) { 1860 this.rangeBtn.value = ''; 1861 } 1862 this.hiddenInput.price = 0; 1863 if (!this.rangeBtn) { 1864 this.hiddenInput.value = this.value; 1865 } else if (this.rangeBtn && this.dataset.index == 0) { 1866 this.hiddenInput.value = this.value+' - '+this.rangeBtn.value; 1867 } else { 1868 this.hiddenInput.value = this.rangeBtn.value+' - '+this.value; 1869 var date1 = new Date(this.rangeBtn.dataset.value), 1870 date2 = new Date(this.dataset.value); 1871 this.hiddenInput.price = Math.ceil(Math.abs(date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)) 1872 } 1873 formsApp.updateFieldsValues($this.fields, this.hiddenInput, this.hiddenInput.fieldId); 1874 formsApp.checkConditionLogic($this); 1875 formsApp.calculation($this); 1876 }); 1877 this.form.find('.ba-form-address-field input').each(function(){ 1878 this.createAutocomplete = function(){ 1879 let autocomplete = new google.maps.places.Autocomplete(this), 1880 input = this; 1881 autocomplete.addListener('place_changed', function(){ 1882 formsApp.updateFieldsValues($this.fields, input, input.fieldId); 1883 formsApp.checkConditionLogic($this); 1884 }); 1885 } 1886 if (formsApp.googleMaps || (('google' in window) && google.maps)) { 1887 this.createAutocomplete(); 1888 } 1889 }).on('input', function(){ 1890 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 1891 formsApp.checkConditionLogic($this); 1892 }).on('focus', function(){ 1893 formsApp.removeAlertTooltip(this); 1894 }); 1895 this.form.find('.ba-form-slider-field .form-range-wrapper input').each(function(){ 1896 let parent = this.closest('.ba-field-container'); 1897 this.linear = parent.querySelector('.ba-form-range-liner'); 1898 this.number = parent.querySelector('.form-slider-input-wrapper input[data-type="range"]'); 1899 this.input = parent.querySelector('.form-slider-input-wrapper input[type="hidden"][name]'); 1900 this.number.range = this; 1901 }).on('input', function(){ 1902 var max = this.max * 1, 1903 min = this.min * 1, 1904 value = this.value * 1, 1905 sx = (value - min) * 100 / (max - min); 1906 this.input.value = value; 1907 this.number.value = this.value; 1908 this.linear.style.width = sx+'%'; 1909 formsApp.updateFieldsValues($this.fields, this.input, this.input.fieldId); 1910 formsApp.checkConditionLogic($this); 1911 formsApp.calculation($this); 1912 }); 1913 this.form.find('.ba-form-slider-field .form-slider-input-wrapper input[data-type="range"]').on('input', function(){ 1914 var max = this.range.max * 1, 1915 min = this.range.min * 1, 1916 value = this.value * 1; 1917 if (value > max) { 1918 this.value = value = max; 1919 } 1920 if (value >= min) { 1921 this.range.value = value; 1922 $f(this.range).trigger('input'); 1923 } 1924 }); 1925 this.form.find('.ba-form-slider-field .form-slider-wrapper input[type="range"]').each(function(){ 1926 let parent = this.closest('.ba-field-container'); 1927 this.linear = parent.querySelector('.ba-form-range-liner'); 1928 this.slides = parent.querySelectorAll('input[type="range"]'); 1929 this.numbers = parent.querySelectorAll('.form-slider-input-wrapper input[data-type="slider"]');
1930 this.numbers[0].slides = this.slides; 1931 this.numbers[1].slides = this.slides; 1932 this.input = parent.querySelector('.form-slider-input-wrapper input[type="hidden"][name]'); 1933 if (!this.input.values) { 1934 this.input.values = new Array(); 1935 } 1936 this.input.values.push(this.value); 1937 }).on('input', function(){ 1938 var max = this.max * 1, 1939 min = this.min * 1, 1940 ind = this.dataset.index * 1, 1941 index = ind == 0 ? 1 : 0, 1942 value = this.value * 1, 1943 value2 = this.slides[index].value * 1, 1944 sx = left = 0; 1945 if (this.slides[0].value * 1 > this.slides[1].value * 1) { 1946 ind = ind == 0 ? 1 : 0; 1947 index = index == 0 ? 1 : 0; 1948 } 1949 this.input.values[index] = value2; 1950 this.numbers[index].value = value2; 1951 this.numbers[ind].value = value; 1952 this.input.values[ind] = value; 1953 this.input.value = this.input.values[0]+' '+this.input.values[1]; 1954 sx = (this.input.values[1] * 1 - this.input.values[0] * 1) * 100 / (max - min) 1955 left = (max - this.input.values[1] * 1) * 100 / (max - min); 1956 this.linear.style.width = sx+'%'; 1957 this.linear.style.marginLeft = (100 - sx - left)+'%'; 1958 formsApp.updateFieldsValues($this.fields, this.input, this.input.fieldId); 1959 formsApp.checkConditionLogic($this); 1960 }); 1961 this.form.find('.ba-form-slider-field .form-slider-input-wrapper input[data-type="slider"]').on('input', function(){ 1962 let $this = this 1963 clearTimeout(this.delay); 1964 this.delay = setTimeout(function(){ 1965 if ($this.value) { 1966 let value = $this.value * 1, 1967 values = $this.slides[0].input.values, 1968 index = $this.dataset.index * 1; 1969 if (index == 0 && value > values[1] * 1) { 1970 index = 1; 1971 $this.slides[1].numbers[1].focus(); 1972 $this.value = values[1]; 1973 $this.slides[0].input.values[0] = $this.value; 1974 $f($this.slides[0]).val($this.value); 1975 } else if (index == 1 && value < values[0] * 1) { 1976 index = 0; 1977 $this.slides[0].numbers[0].focus(); 1978 $this.value = values[0]; 1979 $this.slides[0].input.values[1] = $this.value; 1980 $f($this.slides[1]).val($this.value); 1981 } 1982 $this.slides[index].value = value; 1983 $f($this.slides[index]).trigger('input'); 1984 } 1985 }, 500); 1986 }); 1987 this.form.find('.ba-form-phone-field').on('click', function(){ 1988 formsApp.removeAlertTooltip(this.querySelector('input.ba-phone-number-input')); 1989 }).on('click', '.ba-phone-selected-country', function(){ 1990 let wrapper = this.closest('.ba-phone-countries-wrapper'), 1991 search = wrapper.querySelector('.ba-phone-countries-search'); 1992 setTimeout(function(){ 1993 wrapper.querySelectorAll('li').forEach(function(el){ 1994 el.style.display = ''; 1995 }); 1996 wrapper.classList.remove('top-countries-list'); 1997 wrapper.classList.add('visible-countries-list'); 1998 let rect = wrapper.querySelector('ul').getBoundingClientRect(); 1999 if (window.innerHeight < rect.bottom) { 2000 wrapper.classList.add('top-countries-list'); 2001 } 2002 search.value = ''; 2003 search.focus(); 2004 $f('body').off('click.selected-country').one('click.selected-country', function(){ 2005 $f('.visible-countries-list').removeClass('visible-countries-list'); 2006 }); 2007 }, 100); 2008 }).on('input', '.ba-phone-countries-search', function(){ 2009 var li = this.closest('.ba-phone-countries-wrapper').querySelectorAll('li'), 2010 search = this.value.toLowerCase(); 2011 clearTimeout(this.delay); 2012 this.delay = setTimeout(function(){ 2013 li.forEach(function(el){ 2014 let title = el.dataset.title.toLowerCase(); 2015 el.style.display = !search || title.indexOf(search) != -1 ? '' : 'none'; 2016 }); 2017 }, 300); 2018 }).on('click', '.ba-phone-countries-search', function(event){ 2019 event.stopPropagation(); 2020 }).on('click', '.ba-phone-countries-list li.ba-phone-country-item', function(){ 2021 let wrapper = this.closest('.ba-field-container'); 2022 if (!wrapper.phoneInput) { 2023 wrapper.countryFlag = wrapper.querySelector('.ba-phone-selected-country .ba-phone-flag'); 2024 wrapper.countryPrefix = wrapper.querySelector('.ba-phone-selected-country .ba-phone-prefix'); 2025 wrapper.phoneInput = wrapper.querySelector('input.ba-phone-number-input'); 2026 } 2027 wrapper.countryFlag.className = 'ba-phone-flag ba-phone-flag-'+this.dataset.flag; 2028 wrapper.countryPrefix.textContent = this.dataset.prefix; 2029 wrapper.phoneInput.placeholder = this.dataset.placeholder; 2030 wrapper.phoneInput.value = ''; 2031 wrapper.phoneInput.formsInputMask = this.dataset.placeholder; 2032 wrapper.phoneInput.dataset.prefix = this.dataset.prefix; 2033 wrapper.phoneInput.dispatchEvent(wrapper.phoneInput.inputEvent); 2034 formsApp.prepareInputMask(wrapper.phoneInput, wrapper.phoneInput.formsInputMask); 2035 }).on('keydown', 'input.ba-phone-number-input', function(event){ 2036 formsApp.prepareInputMask(this, this.formsInputMask, event); 2037 }).on('input', 'input.ba-phone-number-input', function(){ 2038 formsApp.executeInputMask(this, this.formsInputMask); 2039 let value = this.dataset.prefix+' '+this.value, 2040 placeholder = this.dataset.prefix+' '+this.placeholder; 2041 this.hiddenInput.value = this.value && value != placeholder ? value : ''; 2042 this.hiddenInput.dispatchEvent(this.inputEvent); 2043 }).find('input.ba-phone-number-input').each(function(){ 2044 this.prefix = this.dataset.prefix; 2045 this.formsInputMask = this.placeholder; 2046 formsApp.prepareInputMask(this, this.formsInputMask); 2047 this.hiddenInput = this.closest('.ba-field-container').querySelector('input[type="hidden"]'); 2048 this.hiddenInput.addEventListener('input', function(){ 2049 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 2050 formsApp.checkConditionLogic($this); 2051 formsApp.calculation($this); 2052 }); 2053 this.inputEvent = new Event('input'); 2054 }); 2055 this.form.find('.ba-form-input-field > .ba-input-wrapper').find('[data-mask]').each(function(){ 2056 this.formsInputMask = this.dataset.mask.replace(/#/g, '_'); 2057 formsApp.prepareInputMask(this, this.formsInputMask); 2058 }).on('keydown', function(event){ 2059 formsApp.prepareInputMask(this, this.formsInputMask, event); 2060 }).on('input', function(event){ 2061 formsApp.executeInputMask(this, this.formsInputMask); 2062 }); 2063 this.form.find('.characters-wrapper').each(function(){ 2064 let input = this.closest('.ba-field-container').querySelector('input, textarea'); 2065 input.characters = { 2066 div: this, 2067 key: this.dataset.direction, 2068 length: this.dataset.length 2069 } 2070 }); 2071 this.form.find('.ba-form-input-field > .ba-input-wrapper').find('input, textarea').on('input', function(){ 2072 if (this.dataset.validation == 'numbers') { 2073 let match = this.value.match(/\d+\.{0,1}\d{0,}/); 2074 if (!match) { 2075 this.value = ''; 2076 } else if (match[0] != this.value) { 2077 this.value = match[0]; 2078 } 2079 } 2080 if (this.characters) { 2081 let length = this.value.length; 2082 this.characters.div.querySelector('.current-characters').textContent = length; 2083 } 2084 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 2085 formsApp.checkConditionLogic($this); 2086 formsApp.calculation($this); 2087 }).on('focus', function(){ 2088 formsApp.removeAlertTooltip(this); 2089 }); 2090 this.form.find('.ba-form-signature-field textarea').on('input', function(){ 2091 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 2092 formsApp.checkConditionLogic($this); 2093 }); 2094 this.form.find('.confirm-email-wrapper, .confirm-password-wrapper').find('input').on('focus', function(){ 2095 formsApp.removeAlertTooltip(this); 2096 }); 2097 this.form.find('.ba-form-dropdown-field, .ba-form-select-multiple-field').find('select').on('focus', function(){ 2098 formsApp.removeAlertTooltip(this); 2099 }).on('change', function(){ 2100 $this.fields[this.fieldId] = { 2101 value: '', 2102 price: 0 2103 } 2104 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 2105 formsApp.checkConditionLogic($this); 2106 formsApp.calculation($this); 2107 formsApp.checkAutoNavigation($this, this); 2108 if (this.product) { 2109 formsApp.productChange($this, this.name); 2110 } 2111 }); 2112 this.form.find('.ba-form-rating-group-wrapper').on('change', function(){ 2113 formsApp.removeAlertTooltip(this); 2114 let input = this.querySelectorAll('input'); 2115 $this.fields[input[0].fieldId] = { 2116 value: '', 2117 price: 0 2118 } 2119 this.classList.remove('active'); 2120 $f(this).find('label.active').removeClass('active'); 2121 for (let i = 0; i < input.length; i++) { 2122 formsApp.updateFieldsValues($this.fields, input[i], input[i].fieldId); 2123 if (input[i].checked) { 2124 this.classList.add('active'); 2125 input[i].closest('label').classList.add('active'); 2126 } 2127 } 2128 formsApp.checkConditionLogic($this); 2129 formsApp.calculation($this); 2130 formsApp.checkAutoNavigation($this, this); 2131 }); 2132 this.form.find('.ba-form-checkbox-group-wrapper').each(function(){ 2133 if (this.querySelector('.ba-checkbox-image')) { 2134 this.classList.add('checkbox-image-group-wrapper'); 2135 } 2136 let checkbox = this.querySelector('.ba-form-checkbox-wrapper:last-child'); 2137 if (checkbox && !checkbox.classList.contains('last-row-checkbox-wrapper')) { 2138 checkbox.classList.add('last-row-checkbox-wrapper') 2139 } 2140 }).on('change', function(){ 2141 formsApp.removeAlertTooltip(this); 2142 let input = this.querySelectorAll('input'), 2143 name = product = null, 2144 image = this.classList.contains('checkbox-image-group-wrapper'); 2145 $this.fields[input[0].fieldId] = { 2146 value: '', 2147 price: 0 2148 } 2149 if (image) { 2150 $f(this).find('.checked-image-container').removeClass('checked-image-container'); 2151 } 2152 for (let i = 0; i < input.length; i++) { 2153 formsApp.updateFieldsValues($this.fields, input[i], input[i].fieldId);
2154 name = input[i].name; 2155 product = input[i].product; 2156 if (input[i].checked) { 2157 input[i].closest('.ba-form-checkbox-wrapper').classList.add('checked-image-container'); 2158 } 2159 } 2160 formsApp.checkConditionLogic($this); 2161 formsApp.calculation($this); 2162 formsApp.checkAutoNavigation($this, this); 2163 if (product && name) { 2164 formsApp.productChange($this, name); 2165 } 2166 }).find('.ba-form-checkbox-wrapper').on('click', function(event){ 2167 if (!event.target.classList.contains('ba-form-checkbox') && !event.target.closest('.ba-form-checkbox') && 2168 !event.target.closest('.ba-form-radio')) { 2169 $f(this).find('> .ba-checkbox-wrapper input').each(function(){ 2170 if (this.type == 'radio' && !this.checked) { 2171 this.checked = true; 2172 } else if (this.type == 'checkbox') { 2173 this.checked = !this.checked; 2174 } 2175 }).trigger('change'); 2176 } 2177 }); 2178 this.form.find('.ba-form-acceptance-field .ba-field-container').on('change', function(){ 2179 formsApp.removeAlertTooltip(this); 2180 let input = this.querySelector('input'); 2181 $this.fields[input.fieldId] = { 2182 value: '', 2183 price: 0 2184 } 2185 formsApp.updateFieldsValues($this.fields, input, input.fieldId); 2186 formsApp.checkConditionLogic($this); 2187 }); 2188 this.form.find('[data-price]').each(function(){ 2189 this.price = this.dataset.price; 2190 }).removeAttr('data-price'); 2191 this.form.find('[data-field-id]').each(function(){ 2192 this.fieldId = this.dataset.fieldId; 2193 $this.items[this.fieldId] = this.closest('.ba-form-field-item'); 2194 if (this.classList.contains('ba-form-submit-btn')) { 2195 return true; 2196 } 2197 if (!$this.fields[this.fieldId]) { 2198 $this.fields[this.fieldId] = { 2199 value: '', 2200 price: 0 2201 } 2202 } 2203 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 2204 }).removeAttr('data-field-id'); 2205 this.form.find('[data-default]').each(function(){ 2206 let match = this.dataset.default.match(/\[Field ID=\d+\]/) || this.dataset.default.match(/\[Page Title\]/); 2207 match = match || this.dataset.default.match(/\[Page URL\]/); 2208 if (this.dataset.default && match) { 2209 let key = this.fieldId ? this.fieldId : +new Date(), 2210 obj = { 2211 item: this, 2212 value: this.dataset.default 2213 } 2214 defaultValues[key] = obj; 2215 } 2216 }); 2217 this.form.find('.ba-form-calculation-field .field-price-value').each(function(){ 2218 let name = '.ba-form-calculation-price-wrapper'; 2219 this.calculation = $f.extend({}, this.dataset); 2220 this.calculation.result = this; 2221 this.calculation.input = this.closest('.ba-field-container').querySelector('input'); 2222 this.calculation.product = this.closest(name).querySelector('input').dataset.product == 'product'; 2223 for (ind in this.dataset) { 2224 $f(this).removeAttr('data-'+ind) 2225 } 2226 $this.calculation[this.calculation.input.fieldId] = this.calculation; 2227 }); 2228 this.form.find('.ba-form-calculation-field input[type="hidden"]').on('change', function(){ 2229 formsApp.updateFieldsValues($this.fields, this, this.fieldId); 2230 formsApp.checkConditionLogic($this); 2231 if (this.product) { 2232 formsApp.productChange($this, this.name); 2233 } 2234 }); 2235 this.form.find('.ba-form-total-field .ba-cart-total-row .field-price-value').each(function(){ 2236 this.calculation = $f.extend({}, this.dataset); 2237 let calculation = this.calculation, 2238 name = '.ba-cart-subtotal-row .field-price-value'; 2239 calculation.subtotal = this.closest('.ba-cart-total-container').querySelector(name); 2240 calculation.result = this; 2241 calculation.input = this.closest('.ba-form-calculation-price-wrapper').querySelector('textarea'); 2242 calculation.cart = this.closest('.ba-input-wrapper').querySelector('.ba-form-products-cart'); 2243 calculation.products = {}; 2244 calculation.total = 0; 2245 calculation.resultTotal = 0; 2246 name = '.ba-cart-discount-row .field-price-value';
2247 calculation.discount = this.closest('.ba-cart-total-container').querySelector(name); 2248 name = '.ba-cart-tax-row .field-price-value'; 2249 calculation.taxResult = this.closest('.ba-cart-total-container').querySelector(name); 2250 name = '.ba-cart-shipping-row input[type="radio"]'; 2251 calculation.shipping = this.closest('.ba-cart-total-container').querySelectorAll(name); 2252 calculation.shipping.forEach(function(el){ 2253 el.addEventListener('change', function(){ 2254 formsApp.calculateCartTotal(calculation); 2255 }) 2256 }); 2257 $this.carts.push(this); 2258 for (ind in this.dataset) { 2259 $f(this).removeAttr('data-'+ind) 2260 } 2261 }); 2262 this.form.find('.ba-form-total-field textarea').on('change', function(){ 2263 let calc = this.closest('.ba-form-calculation-price-wrapper').querySelector('.field-price-value').calculation; 2264 if ($this.fields[this.fieldId].price != calc.resultTotal) { 2265 $this.fields[this.fieldId] = { 2266 value: calc.resultTotal, 2267 price: calc.resultTotal 2268 } 2269 formsApp.calculation($this, true); 2270 } 2271 }); 2272 2273 this.form.find('.ba-cart-promo-code-btn').each(function(){ 2274 this.promo = { 2275 input: this.closest('.ba-cart-promo-code-container').querySelector('.ba-cart-promo-code-input'), 2276 total: this.closest('.ba-field-container').querySelector('.ba-cart-total-row .field-price-value'), 2277 discount: this.closest('.ba-field-container').querySelector('.ba-cart-discount-row') 2278 } 2279 }).on('click', function(){ 2280 if (this.status != 'pending') { 2281 this.status = 'pending'; 2282 let btn = this; 2283 formsApp.fetch.request(JUri+'index.php?option=com_baforms&task=form.checkCoupon', { 2284 coupon: btn.promo.input.value.trim(), 2285 id: btn.dataset.name 2286 }).then(function(text){ 2287 btn.status = ''; 2288 if (!text || !btn.promo.input.value.trim()) { 2289 formsApp.showNotice(formsApp._('PROMO_CODE_NOT_VALID'), 'ba-alert'); 2290 btn.promo.total.calculation.promo = null; 2291 btn.promo.discount.style.display = 'none'; 2292 } else { 2293 btn.promo.total.calculation.promo = JSON.parse(text); 2294 btn.promo.discount.style.display = ''; 2295 } 2296 formsApp.calculateCartTotal(btn.promo.total.calculation); 2297 }); 2298 } 2299 }) 2300 this.form.find('[data-product]').each(function(){ 2301 if (this.dataset.product) { 2302 this.product = this.dataset.product; 2303 let name = this.name; 2304 if (!$this.products[name]) { 2305 $this.products[name] = new Array(); 2306 } 2307 if (this.localName == 'select') { 2308 this.querySelectorAll('option').forEach(function(option){ 2309 $this.products[name].push(option); 2310 }); 2311 } else { 2312 $this.products[name].push(this); 2313 } 2314 } 2315 }).removeAttr('data-product'); 2316 formsApp.updateFieldsDefaultValues($this, defaultValues); 2317 formsApp.getProgress($this); 2318 formsApp.checkConditionLogic($this); 2319 formsApp.calculation($this); 2320 formsApp.updateCarts($this); 2321} 2322 2323formsApp.productChange = function($this, name){ 2324 for (let i = 0; i < $this.carts.length; i++) { 2325 if (!$this.carts[i].calculation.products[name]) { 2326 continue; 2327 } 2328 let calculation = $this.carts[i].calculation; 2329 formsApp.updateProducts($this, calculation, name); 2330 } 2331} 2332 2333formsApp.updateCarts = function($this){ 2334 for (let i = 0; i < $this.carts.length; i++) { 2335 let calculation = $this.carts[i].calculation; 2336 for (let name in $this.products) { 2337 if (!calculation.products[name]) { 2338 calculation.products[name] = {}; 2339 } 2340 formsApp.updateProducts($this, calculation, name); 2341 } 2342 } 2343} 2344 2345formsApp.updateProducts = function($this, calculation, name){ 2346 let products = $this.products[name], 2347 object = {}; 2348 for (let i = 0; i < products.length; i++) { 2349 if (products[i].closest('.hidden-condition-field')) { 2350 continue; 2351 } 2352 if (products[i].price != '' && 2353 (((products[i].type == 'radio' || products[i].type == 'checkbox') && products[i].checked) 2354 || (products[i].localName == 'option' && products[i].selected) || products[i].type == 'hidden')) { 2355 let obj = { 2356 input: products[i], 2357 quantity:1, 2358 title: products[i].dataset.title ? products[i].dataset.title : products[i].value, 2359 price: products[i].price 2360 } 2361 obj.total = obj.price * obj.quantity; 2362 object[i] = obj; 2363 } 2364 } 2365 for (let ind in calculation.products[name]) { 2366 if (!object[ind] || calculation.products[name][ind].input.type == 'hidden') { 2367 calculation.total -= calculation.products[name][ind].total; 2368 if (calculation.cart) { 2369 calculation.cart.querySelector('.ba-form-product-row[data-name="'+name+'"][data-ind="'+ind+'"]').remove(); 2370 } 2371 delete calculation.products[name][ind]; 2372 } 2373 } 2374 for (let ind in object) { 2375 if (!calculation.products[name][ind]) { 2376 if (Number.isNaN(object[ind].total)) { 2377 object[ind].total = 0; 2378 } 2379 calculation.total += object[ind].total; 2380 if (calculation.cart) { 2381 let div = formsApp.getProductCartHTML(object[ind], name, ind, calculation); 2382 calculation.cart.append(div); 2383 } 2384 calculation.products[name][ind] = object[ind]; 2385 } 2386 } 2387 calculation.total = formsApp.decimalAdjust('round', calculation.total, calculation.decimals * -1); 2388 formsApp.calculateCartTotal(calculation); 2389 2390} 2391 2392formsApp.calculateCartTotal = function(calculation){ 2393 let decimals = calculation.decimals, 2394 price = formsApp.renderPrice(String(calculation.total), calculation.thousand, calculation.separator, decimals), 2395 total = calculation.total, 2396 tax = 0, 2397 discount = calculation.promo ? calculation.promo.discount * 1 : 0; 2398 if (calculation.subtotal) { 2399 calculation.subtotal.textContent = price; 2400 } 2401 if (calculation.promo && calculation.promo.unit == '%') { 2402 discount = total * discount / 100; 2403 } 2404 total -= discount; 2405 if (calculation.taxResult) { 2406 tax = total * calculation.tax / 100 2407 price = formsApp.renderPrice(String(tax), calculation.thousand, calculation.separator, decimals) 2408 calculation.taxResult.textContent = price; 2409 } 2410 total += tax; 2411 if (calculation.discount) { 2412 price = formsApp.renderPrice(String(discount), calculation.thousand, calculation.separator, decimals); 2413 calculation.discount.textContent = '-'+price; 2414 } 2415 if (calculation.shipping) { 2416 calculation.shipping.forEach(function(input){ 2417 if (input.checked) { 2418 total += input.price * 1; 2419 } 2420 }); 2421 } 2422 calculation.resultTotal = total; 2423 price = formsApp.renderPrice(String(total), calculation.thousand, calculation.separator, decimals) 2424 calculation.result.textContent = price; 2425 $f(calculation.input).trigger('change'); 2426} 2427 2428formsApp.getProductCartHTML = function(product, name, ind, calculation){ 2429 let div = document.createElement('div'), 2430 decimals = calculation.decimals, 2431 price = formsApp.renderPrice(String(product.total), calculation.thousand, calculation.separator, decimals), 2432 image = product.input.closest('.checkbox-image-wrapper'); 2433 div.className = 'ba-form-product-row'; 2434 div.dataset.name = name; 2435 div.dataset.ind = ind; 2436 div.innerHTML = '<div class="ba-form-product-title-cell">'+product.title+'</div>'+ 2437 '<div class="ba-form-product-quantity-cell"><i class="ba-form-icons ba-icon-minus-circle '+ 2438 (product.quantity == 1 ? 'ba-disabled' : '')+'" data-action="-"></i>'+ 2439 '<input type="number" value="'+product.quantity+'" min="1" step="1">'+ 2440 '<i class="ba-form-icons ba-icon-plus-circle" data-action="+"></i></div>'+ 2441 '<div class="ba-form-product-total-cell"><div class="ba-form-calculation-price-wrapper">'+ 2442 '<span class="field-price-currency">'+calculation.symbol+'</span><span class="field-price-value">'+price+ 2443 '</span></div>'+ 2444 '</div><div class="ba-form-product-remove-cell"><i class="ba-form-icons ba-icon-delete"></i></div>'; 2445 if (image) { 2446 let img = document.createElement('div'); 2447 img.className = 'ba-form-product-image-cell'; 2448 img.append(image.querySelector('img').cloneNode()); 2449 div.insertBefore(img, div.querySelector('.ba-form-product-title-cell')); 2450 } 2451 let input = div.querySelector('.ba-form-product-quantity-cell input'), 2452 trash = div.querySelector('.ba-form-product-remove-cell i'), 2453 quantityBtns = div.querySelectorAll('.ba-form-product-quantity-cell i[data-action]'); 2454 quantityBtns.forEach(function(element){ 2455 element.addEventListener('click', function(){ 2456 if (this.classList.contains('ba-disabled')) { 2457 return false;
2458 } 2459 if (this.dataset.action == '+') { 2460 input.value = input.value * 1 + 1; 2461 } else { 2462 input.value = input.value * 1 - 1; 2463 } 2464 let event = new Event('input'); 2465 input.dispatchEvent(event); 2466 }); 2467 }); 2468 input.addEventListener('input', function(){ 2469 if (this.value != '') { 2470 quantityBtns[0].classList[this.value == 1 ? 'add' : 'remove']('ba-disabled'); 2471 let match = this.value.match(/\d+/), 2472 decimals = calculation.decimals; 2473 if (!match || match[0] == 0) { 2474 this.value = 1; 2475 } else if (match[0] != this.value) { 2476 this.value = match[0]; 2477 } 2478 if (this.value * 1 > 0) { 2479 calculation.total -= product.total; 2480 product.quantity = this.value * 1; 2481 product.total = product.price * product.quantity; 2482 price = formsApp.renderPrice(String(product.total), calculation.thousand, calculation.separator, decimals); 2483 div.querySelector('.field-price-value').textContent = price; 2484 calculation.total += product.total; 2485 formsApp.calculateCartTotal(calculation); 2486 } 2487 } 2488 }); 2489 trash.addEventListener('click', function(){ 2490 if (product.input.type == 'hidden') { 2491 calculation.total -= product.total; 2492 delete calculation.products[name][ind]; 2493 div.remove(); 2494 let decimals = calculation.decimals; 2495 price = formsApp.renderPrice(String(calculation.total), calculation.thousand, calculation.separator, decimals); 2496 calculation.result.textContent = price; 2497 } else { 2498 product.input[product.input.localName == 'option' ? 'selected' : 'checked'] = false; 2499 $f(product.input).trigger('change'); 2500 } 2501 }); 2502 2503 return div; 2504} 2505 2506formsApp.decimalAdjust = function(type, value, exp){ 2507 if (typeof exp === 'undefined' || +exp === 0) { 2508 return Math[type](value); 2509 } 2510 value = +value; 2511 exp = +exp; 2512 if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) { 2513 return NaN; 2514 } 2515 value = value.toString().split('e'); 2516 value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))); 2517 value = value.toString().split('e'); 2518 2519 return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)); 2520} 2521 2522formsApp.calculation = function($this, fromCart){ 2523 formsApp.calculated = {}; 2524 for (let i in $this.calculation) { 2525 if (fromCart && $this.calculation[i].product) { 2526 continue; 2527 } 2528 let calc = $this.calculation[i], 2529 total = formsApp.calculate(calc.formula, $this), 2530 price = String(total); 2531 total = formsApp.decimalAdjust('round', total, calc.decimals * -1); 2532 price = String(total); 2533 calc.input.price = total; 2534 formsApp.calculated[i] = total; 2535 if (total != calc.input.value * 1) { 2536 price = formsApp.renderPrice(price, calc.thousand, calc.separator, calc.decimals); 2537 calc.input.value = total; 2538 calc.result.textContent = price; 2539 $f(calc.input).trigger('change'); 2540 } 2541 } 2542} 2543 2544formsApp.calculate = function(formula, $this){ 2545 if (formula == '') { 2546 return 0; 2547 } 2548 formula = formula.replace(/\s/g, '').replace(/elseif/g, 'else if'); 2549 let matches = formula.match(/\[FieldID=\d+\]/g), 2550 total = 0; 2551 if (matches) { 2552 for (let i = 0; i < matches.length; i++) { 2553 let match = matches[i].match(/\d+/g), 2554 price = $this.fields['baform-'+match[0]] ? $this.fields['baform-'+match[0]].price : 0; 2555 if (!$this.items['baform-'+match[0]] || $this.items['baform-'+match[0]].closest('.hidden-condition-field')) { 2556 price = 0; 2557 } else if ('baform-'+match[0] in formsApp.calculated) { 2558 price = formsApp.calculated['baform-'+match[0]]; 2559 } else if ($this.calculation['baform-'+match[0]]) { 2560 price = formsApp.calculate($this.calculation['baform-'+match[0]].formula, $this) 2561 formsApp.calculated['baform-'+match[0]] = price; 2562 } 2563 formula = formula.replace(matches[i], price); 2564 } 2565 } 2566 try { 2567 total = eval(formula); 2568 } catch (error) { 2569 console.error(error) 2570 } 2571 if (total == -Infinity || total == Infinity || Number.isNaN(total)) { 2572 total = 0; 2573 } 2574 2575 return total; 2576} 2577 2578formsApp.getProgress = function($this){ 2579 if (formsApp.storage[$this.formURL] && formsApp.storage[$this.formURL][$this.formId]) { 2580 let data = formsApp.storage[$this.formURL][$this.formId]; 2581 for (let i = 0; i < data.fields.length; i++) { 2582 let input = $this.form.find('[name="'+data.fields[i].name+'"]'), 2583 obj = data.fields[i]; 2584 if (!input.length) { 2585 continue; 2586 } 2587 switch (obj.type) { 2588 case 'input' : 2589 case 'address': 2590 if (input[0].formsInputMask) { 2591 input[0].setSelectionRange(0, 0); 2592 input[0].setRangeText(obj.data.value); 2593 } else { 2594 input.val(obj.data.value); 2595 } 2596 input.trigger('input');
2597 if ('confirm' in obj.data) { 2598 input.closest('.ba-form-field-item').find('.confirm-email-wrapper input').val(obj.data.confirm); 2599 } 2600 if ('password' in obj.data) { 2601 input.closest('.ba-form-field-item').find('.confirm-password-wrapper input').val(obj.data.password); 2602 } 2603 break; 2604 case 'phone': 2605 let parent = input.closest('.ba-field-container'); 2606 parent.find('.ba-phone-country-item[data-flag="'+obj.data.flag+'"]').trigger('click'); 2607 parent.find('.ba-phone-number-input').each(function(){ 2608 this.setSelectionRange(0, 0); 2609 this.setRangeText(obj.data.value); 2610 }).trigger('input'); 2611 break; 2612 case 'calendar': 2613 let value = obj.data.value.split(' - '); 2614 input.closest('.ba-field-container').find('input[type="text"]').each(function(i){ 2615 this.value = value[i]; 2616 }).trigger('input'); 2617 break; 2618 case 'radio': 2619 case 'checkbox': 2620 case 'rating': 2621 input.each(function(){ 2622 if (obj.data.checked.indexOf(this.value) != -1) { 2623 this.checked = true; 2624 $f(this).trigger('change'); 2625 } 2626 }); 2627 break; 2628 case 'select': 2629 case 'selectMultiple': 2630 input.find('option').each(function(){ 2631 if (obj.data.selected.indexOf(this.value) != -1) { 2632 this.selected = true; 2633 input.trigger('change'); 2634 } 2635 }); 2636 break; 2637 case 'acceptance': 2638 if (obj.data.selected) { 2639 input.prop('checked', obj.data.selected); 2640 } 2641 break; 2642 case 'slider': 2643 let range = input.closest('.ba-field-container').find('input[type="range"]'); 2644 input.value = obj.data.value; 2645 if (obj.data.type == 'range') { 2646 range.val(obj.data.value).trigger('input'); 2647 } else { 2648 let array = obj.data.value.split(' '); 2649 range.first().val(array[0]).trigger('input'); 2650 range.last().val(array[1]).trigger('input'); 2651 } 2652 break; 2653 case 'upload': 2654 let file = input.closest('.upload-file-input').find('.ba-forms-attachment')[0]; 2655 file.uploads = obj.data.uploads; 2656 for (let ind in file.uploads) { 2657 if (ind == 'count') { 2658 continue; 2659 } 2660 let name = file.uploads[ind].name.split('.'), 2661 ext = name[name.length - 1].toLowerCase(), 2662 type = file.options.images.indexOf(ext) == -1 ? 'file' : 'image', 2663 attachment = formsApp.getAttachmentHTML(file, type, file.uploads[ind].name); 2664 attachment.dataset.id = ind; 2665 attachment.classList.add('forms-attachment-file-uploaded'); 2666 if (type == 'image') { 2667 let img = JUri+uploads_storage+'/form-'+$this.formId+'/'+file.uploads[ind].filename; 2668 attachment.querySelector('.attachment-intro-image').style.backgroundImage = 'url('+img+')'; 2669 } 2670 file.options[type+'Container'].appendChild(attachment); 2671 } 2672 break; 2673 } 2674 } 2675 } 2676} 2677 2678formsApp.updateFieldsDefaultValues = function($this, defaultValues){ 2679 let object = {}; 2680 for (let ind in defaultValues) { 2681 object[ind] = ''; 2682 object[ind] = formsApp.updateFieldsDefaultValue($this, defaultValues, defaultValues[ind].value, object); 2683 defaultValues[ind].item.value = object[ind]; 2684 } 2685} 2686 2687formsApp.updateFieldsDefaultValue = function($this, defaultValues, value, object){ 2688 let matches = value.match(/\[Field ID=\d+\]/g), 2689 title = $this.querySelector('input[name="page-title"]').value, 2690 url = $this.querySelector('input[name="page-url"]').value; 2691 if (matches) { 2692 for (let i = 0; i < matches.length; i++) { 2693 let match = matches[i].match(/\d+/g), 2694 key = 'baform-'+match[0], 2695 val = $this.fields[key].value; 2696 if (key in object) { 2697 val = object[match[0]]; 2698 } else if (key in defaultValues) { 2699 object[key] = ''; 2700 val = formsApp.updateFieldsDefaultValue($this, defaultValues, defaultValues[key].value, object); 2701 object[key] = val; 2702 } 2703 } 2704 } 2705 value = value.replace(/\[Page Title\]/g, title); 2706 value = value.replace(/\[Page URL\]/g, url); 2707 2708 2709 return value; 2710} 2711 2712formsApp.updateFieldsValues = function(fields, $this, id){ 2713 if ($this.type == 'radio' && $this.checked) { 2714 fields[id] = { 2715 value: $this.value, 2716 price: $this.price * 1 2717 } 2718 } else if ($this.type == 'checkbox' && $this.checked) { 2719 fields[id].value += fields[id].value != '' ? ' '+$this.value : $this.value; 2720 fields[id].price += $this.price * 1; 2721 } else if ($this.localName == 'select') { 2722 $f($this).find('option').each(function(){ 2723 if (this.selected) { 2724 fields[id].value += fields[id].value != '' ? ' '+this.value : this.value; 2725 fields[id].price += this.price * 1; 2726 } 2727 }); 2728 } else if ($this.dataset.calendar) { 2729 fields[id].value = $this.value; 2730 fields[id].price = $this.price * 1; 2731 } else if ($this.type == 'hidden' || $this.type == 'text' || $this.type == 'number' 2732 || $this.localName == 'textarea' || $this.type == 'email') { 2733 fields[id].value = $this.value; 2734 fields[id].price = $this.value.replace(/,/g, '.') * 1; 2735 } else if ($this.type == 'file') { 2736 fields[id].value = ''; 2737 fields[id].price = $this.uploads.count; 2738 $this.closest('.ba-form-upload-field').classList[$this.uploads.count > 0 ? 'add' : 'remove']('has-uploaded-file'); 2739 } 2740 if (String(fields[id].price) == 'NaN') { 2741 fields[id].price = 0; 2742 } 2743} 2744 2745formsApp.checkConditionLogic = function($this){ 2746 $this.pages = {}; 2747 $this.querySelectorAll('.hidden-condition-field').forEach((div) => { 2748 div.classList.remove('hidden-condition-field'); 2749 });
2750 conditionLogic[$this.formId].forEach(function(el){ 2751 if (!el.publish) { 2752 return true; 2753 } 2754 let flags = new Array(), 2755 page = null, 2756 value; 2757 el.when.forEach(function(obj){ 2758 if (!obj.field || !obj.state) { 2759 return true; 2760 } 2761 if (!$this.fields['baform-'+obj.field]) { 2762 return true; 2763 } 2764 page = $this.items['baform-'+obj.field].closest('.ba-form-page'); 2765 if ($this.items['baform-'+obj.field].classList.contains('hidden-condition-field') 2766 || $this.items['baform-'+obj.field].closest('.hidden-condition-field')) { 2767 flags.push(false); 2768 return true; 2769 } 2770 value = $this.fields['baform-'+obj.field].value; 2771 if ($this.items['baform-'+obj.field].dataset.type == 'checkbox' 2772 || $this.items['baform-'+obj.field].dataset.type == 'selectMultiple') { 2773 value = []; 2774 $this.items['baform-'+obj.field].querySelectorAll('input[name], option').forEach(function(input){ 2775 input.checked || input.selected ? value.push(input.value) : ''; 2776 }); 2777 } 2778 switch (obj.state) { 2779 case 'equal': 2780 if (typeof value == 'string') { 2781 flags.push(value == obj.value); 2782 } else { 2783 flags.push(value.indexOf(obj.value) != -1); 2784 } 2785 break; 2786 case 'not-equal': 2787 if (typeof value == 'string') { 2788 flags.push(value != obj.value); 2789 } else { 2790 flags.push(value.indexOf(obj.value) == -1); 2791 } 2792 break; 2793 case 'not-empty': 2794 if (typeof value == 'string') { 2795 flags.push(value != ''); 2796 } else { 2797 flags.push(value.length != 0); 2798 } 2799 break; 2800 case 'empty': 2801 if (typeof value == 'string') { 2802 flags.push(value == ''); 2803 } else { 2804 flags.push(value.length == 0); 2805 } 2806 break; 2807 case 'greater': 2808 flags.push((!isNaN(value) ? value * 1 : value) > (!isNaN(obj.value) ? obj.value * 1 : obj.value)); 2809 break; 2810 case 'less': 2811 flags.push((!isNaN(value) ? value * 1 : value) < (!isNaN(obj.value) ? obj.value * 1 : obj.value)); 2812 break; 2813 case 'contain': 2814 flags.push(value.indexOf(obj.value) != -1); 2815 break; 2816 case 'not-contain': 2817 flags.push(value.indexOf(obj.value) == -1); 2818 break; 2819 } 2820 }); 2821 if (!flags.length) { 2822 return true; 2823 } 2824 let method = el.operation == 'OR' ? 'some' : 'every', 2825 flag = flags[method](function(state){return state}); 2826 el.do.forEach(function(obj){ 2827 if (obj.field && obj.action) { 2828 let item = $this.items['baform-'+obj.field] 2829 || $this.form[0].querySelector('.ba-form-page[data-page-key="'+obj.field+'"]'); 2830 if (!item) { 2831 return true; 2832 } 2833 if (obj.action == 'show' || obj.action == 'hide') { 2834 let method = (obj.action == 'show' && flag) || (obj.action == 'hide' && !flag) ? 'remove' : 'add'; 2835 item.classList[method]('hidden-condition-field'); 2836 item.querySelectorAll('input[name], select[name], textarea[name]').forEach(function(itm){ 2837 if (itm.product) { 2838 formsApp.productChange($this, itm.name); 2839 } 2840 }); 2841 if (item.classList.contains('ba-form-submit-field') && method == 'remove') { 2842 formsApp.initFormsRecaptcha(item); 2843 } 2844 } else if (obj.action == 'move' && flag) { 2845 $this.pages[page.dataset.pageKey] = { 2846 prev: page, 2847 next: item 2848 } 2849 let hidden = []; 2850 $f(page).nextAll('.ba-form-page').each(function(){ 2851 if (this == item) { 2852 this.classList.remove('hidden-condition-field'); 2853 return false;
2854 } 2855 this.classList.add('hidden-condition-field'); 2856 hidden.push(this.dataset.pageKey); 2857 }); 2858 $this.pages[page.dataset.pageKey].hidden = hidden; 2859 } 2860 } 2861 }); 2862 $f(window).trigger('scroll'); 2863 }); 2864} 2865 2866formsApp.strrev = function(string){ 2867 var ret = '', i = 0; 2868 for (i = string.length - 1; i >= 0; i--) { 2869 ret += string[i]; 2870 } 2871 2872 return ret; 2873} 2874 2875formsApp.renderPrice = function(value, thousand, separator, decimals){ 2876 let delta = value < 0 ? '-' : '', 2877 priceArray = value.replace('-', '').trim().split('.'), 2878 priceThousand = priceArray[0], 2879 priceDecimal = priceArray[1] ? priceArray[1] : '', 2880 price = ''; 2881 if (priceThousand.length > 3 && thousand != '') { 2882 for (let i = 0; i < priceThousand.length; i++) { 2883 if (i % 3 == 0 && i != 0) { 2884 price += thousand; 2885 } 2886 price += priceThousand[priceThousand.length - 1 - i]; 2887 } 2888 price = formsApp.strrev(price); 2889 } else { 2890 price += priceThousand; 2891 } 2892 if (decimals != 0) { 2893 price += separator; 2894 for (let i = 0; i < decimals; i++) { 2895 price += priceDecimal[i] ? priceDecimal[i] : '0'; 2896 } 2897 } 2898 2899 return delta+price; 2900} 2901 2902 2903 2904function formsCaptchaOnload(service, captcha) 2905{ 2906 formsApp[service].captcha = captcha; 2907 formsApp[service].loaded = true; 2908 formsApp[service].init(); 2909} 2910 2911function formsRecaptchaOnload() 2912{ 2913 formsCaptchaOnload('grecaptcha', grecaptcha); 2914} 2915 2916function formshCaptchaOnload() 2917{ 2918 formsCaptchaOnload('hcaptcha', hcaptcha); 2919} 2920 2921function formsTurnstileOnload() 2922{ 2923 formsCaptchaOnload('turnstile', turnstile); 2924} 2925 2926 2927formsApp.captcha = { 2928 configurate: function(settings) { 2929 this.settings = settings; 2930 }, 2931 get: function(key) { 2932 return formsApp.recaptcha[this.type][key]; 2933 }, 2934 init: function(){ 2935 $f('.ba-form-submit-field').each(function(){ 2936 formsApp.initFormsRecaptcha(this); 2937 }); 2938 }, 2939 load: function() { 2940 if (this.loaded) { 2941 this.init(); 2942 } else if (!this.loaded && !this.loading) { 2943 let script = document.createElement('script'); 2944 this.loading = true; 2945 script.src = this.src; 2946 document.head.appendChild(script); 2947 } 2948 }, 2949 set: function(element) { 2950 let div = document.createElement('div'), 2951 parent = $f(element).find('.ba-form-submit-recaptcha-wrapper'); 2952 div.id = 'forms-recaptcha-'+(+new Date()); 2953 div.className = 'forms-recaptcha'; 2954 div.dataset.captcha = this.type; 2955 parent.append(div); 2956 this.render(div); 2957 element.rendered = true; 2958 } 2959} 2960 2961formsApp.turnstile = { 2962 src: 'https://challenges.cloudflare.com/turnstile/v0/api.js?onload=formsTurnstileOnload', 2963 type: 'turnstile', 2964 __proto__: formsApp.captcha, 2965 render: function(div){ 2966 formsApp.recaptcha.data[div.id] = this.captcha.render(div, { 2967 sitekey: this.get('site_key'), 2968 theme: this.get('theme'), 2969 size: this.get('size'), 2970 callback: formsVerifyCaptcha 2971 }); 2972 } 2973} 2974 2975formsApp.hcaptcha = { 2976 src: 'https://js.hcaptcha.com/1/api.js?onload=formshCaptchaOnload', 2977 type: 'hcaptcha', 2978 __proto__: formsApp.captcha, 2979 render: function(div){ 2980 div.dataset.size = this.get('invisible') ? 'invisible' : 'normal'; 2981 formsApp.recaptcha.data[div.id] = this.captcha.render(div, { 2982 sitekey: this.get('site_key'), 2983 theme: this.get('theme'), 2984 size: this.get('invisible') ? 'invisible' : 'normal', 2985 callback: formsVerifyCaptcha 2986 }); 2987 } 2988} 2989 2990formsApp.grecaptcha = { 2991 init: () => { 2992 $f('.ba-form-submit-field').each(function(){ 2993 formsApp.initFormsRecaptcha(this); 2994 }); 2995 }, 2996 load: () => { 2997 if ('grecaptcha' in window) { 2998 formsRecaptchaOnload() 2999 } else if (!formsApp.grecaptcha.loaded && !formsApp.grecaptcha.loading) { 3000 formsApp.grecaptcha.loading = true; 3001 let script = document.createElement('script'); 3002 script.src = 'https://www.google.com/recaptcha/api.js?onload=formsRecaptchaOnload&render=explicit'; 3003 script.onload = () => { 3004 formsApp.grecaptcha.loaded = true; 3005 } 3006 document.head.appendChild(script); 3007 } 3008 } 3009} 3010 3011formsApp.loadRecaptcha = function(){ 3012 $f('.ba-form-submit-field').each(function(){ 3013 let captcha = this.querySelector('.ba-form-submit-btn').dataset.captcha;
3014 if (captcha == 'hcaptcha' && formsApp.recaptcha[captcha]) { 3015 formsApp.hcaptcha.load(); 3016 } else if (captcha == 'turnstile' && formsApp.recaptcha[captcha]) { 3017 formsApp.turnstile.load(); 3018 } else if (captcha && formsApp.recaptcha[captcha]) { 3019 formsApp.grecaptcha.load(); 3020 } 3021 }); 3022} 3023 3024formsApp.getRecaptchaData = function(){ 3025 fetch(JUri+'index.php?option=com_baforms&task=form.getRecaptchaData').then(function(response){ 3026 return response.json(); 3027 }).then(function(json){ 3028 formsApp.recaptcha = json; 3029 formsApp.loadRecaptcha(); 3030 }); 3031} 3032 3033formsApp.initFormsRecaptcha = function(element){ 3034 let captcha = element.querySelector('.ba-form-submit-btn').dataset.captcha; 3035 if (formsApp.recaptcha && captcha == 'hcaptcha' && formsApp.recaptcha[captcha] && !element.rendered) { 3036 formsApp.hcaptcha.set(element); 3037 } else if (formsApp.recaptcha && captcha == 'turnstile' && formsApp.recaptcha[captcha] && !element.rendered) { 3038 formsApp.turnstile.set(element); 3039 } else if (formsApp.recaptcha && captcha && formsApp.recaptcha[captcha] && ('grecaptcha' in window) && !element.rendered) { 3040 let div = document.createElement('div'), 3041 parent = element.querySelector('.ba-form-submit-recaptcha-wrapper'), 3042 options = { 3043 sitekey : formsApp.recaptcha[captcha].public_key 3044 }; 3045 if (captcha == 'recaptcha') { 3046 options.theme = formsApp.recaptcha[captcha].theme; 3047 options.size = formsApp.recaptcha[captcha].size; 3048 } else { 3049 options.badge = formsApp.recaptcha[captcha].badge; 3050 options.size = 'invisible'; 3051 } 3052 div.id = 'forms-recaptcha-'+(+new Date()); 3053 div.className = 'forms-recaptcha'; 3054 div.dataset.captcha = captcha; 3055 div.dataset.size = options.size; 3056 parent.append(div); 3057 options.callback = formsVerifyCaptcha 3058 formsApp.recaptcha.data[div.id] = grecaptcha.render(div, options); 3059 element.rendered = true; 3060 } 3061} 3062 3063function formsVerifyCaptcha(){ 3064 $f('.forms-recaptcha').each(function(){ 3065 formsApp.removeAlertTooltip(this); 3066 }); 3067 if (formsApp.submitForm) { 3068 formsApp.submitData(); 3069 } 3070} 3071 3072formsApp.executeInputMask = function(input, mask){ 3073 let n = input.beforeData.start + Math.abs(input.beforeData.value.length - input.value.length), 3074 pos = mask.indexOf('_'), 3075 text = [], 3076 delData = [], 3077 start = updateStart = null, 3078 value = mask; 3079 if (input.value.length > input.beforeData.value.length || input.value.length == input.beforeData.value.length) { 3080 let i = 0; 3081 for (i; i < input.beforeData.start; i++) { 3082 if (mask[i] == '_' && /\d/.test(input.beforeData.value[i])) { 3083 text.push(input.beforeData.value[i]); 3084 } 3085 } 3086 i = input.beforeData.start; 3087 n = input.value.length > input.beforeData.value.length ? n : input.beforeData.end; 3088 for (i; i < n; i++) { 3089 if (/\d/.test(input.value[i])) { 3090 text.push(input.value[i]); 3091 } 3092 } 3093 start = pos; 3094 for (i = 0; i < text.length; i++) { 3095 start = mask.indexOf('_', start + 1); 3096 if (start == -1) { 3097 start = mask.length; 3098 } 3099 } 3100 for (i = input.beforeData.end; i < input.beforeData.value.length; i++) { 3101 if (mask[i] == '_' && /\d/.test(input.beforeData.value[i])) { 3102 text.push(input.beforeData.value[i]); 3103 } 3104 } 3105 } else if (input.beforeData.start == 0 && input.beforeData.end == mask.length) { 3106 for (let i = 0; i < input.value.length; i++) { 3107 if (/\d/.test(input.value[i])) { 3108 text.push(input.value[i]); 3109 } 3110 } 3111 updateStart = true; 3112 } else if (input.beforeData.start < input.selectionStart) { 3113 let i = 0; 3114 for (i; i < input.selectionStart; i++) { 3115 if (mask[i] == '_' && /\d/.test(input.value[i])) { 3116 text.push(input.value[i]); 3117 } 3118 } 3119 start = i; 3120 for (let j = input.beforeData.end; j < input.beforeData.value.length; j++) { 3121 if (mask[j] == '_' && /\d/.test(input.beforeData.value[j])) { 3122 text.push(input.beforeData.value[j]); 3123 } 3124 } 3125 } else { 3126 let i = input.selectionStart < input.beforeData.start ? input.selectionStart : input.beforeData.start; 3127 n = input.selectionStart < input.beforeData.start ? input.beforeData.start : n; 3128 for (i; i < n; i++) { 3129 delData.push(i); 3130 } 3131 } 3132 if (delData.length == 1 && mask[delData[0]] != '_' && input.selectionStart < input.beforeData.start) { 3133 for (let i = input.selectionStart; i >= 0; i--) { 3134 if (mask[i] == '_') { 3135 delData[0] = i; 3136 break; 3137 } 3138 } 3139 } else if (delData.length == 1 && mask[delData[0]] != '_') { 3140 for (let i = input.selectionStart; i < mask.length; i++) { 3141 if (mask[i] == '_') { 3142 delData[0] = i; 3143 break; 3144 } 3145 } 3146 } 3147 if (delData.length) { 3148 start = delData[0]; 3149 for (let i = 0; i < input.beforeData.value.length; i++) { 3150 if (delData.indexOf(i) == -1 && mask[i] == '_') { 3151 text.push(input.beforeData.value[i]); 3152 } 3153 } 3154 } 3155 input.value = value; 3156 text.forEach(function(el){ 3157 if (pos != -1) { 3158 input.setSelectionRange(pos, ++pos); 3159 input.setRangeText(el); 3160 if (updateStart) { 3161 start = pos; 3162 } 3163 } 3164 pos = input.value.indexOf('_'); 3165 }); 3166 if (start !== null) { 3167 input.setSelectionRange(start, start); 3168 } 3169} 3170 3171formsApp.prepareInputMask = function(input, mask, event){ 3172 let value = input.value ? input.value : mask; 3173 if (event) { 3174 input.beforeData = { 3175 start: input.selectionStart, 3176 end: input.selectionEnd, 3177 value: value 3178 }; 3179 } else { 3180 input.beforeData = { 3181 start: 0, 3182 end: 0, 3183 value: value 3184 }; 3185 input.value = value; 3186 } 3187} 3188 3189formsApp.executeMask = function(input, mask){ 3190 let i = 0, 3191 flag = true, 3192 value = ''; 3193 for (i = 0; i < input.value.length; i++) { 3194 flag = input.value[i] == mask[i] || mask[i] == '#' && /\d/.test(input.value[i]) 3195 if (flag) { 3196 value += input.value[i]; 3197 } else { 3198 break; 3199 } 3200 } 3201 if (!flag) { 3202 let subValue = input.value.substr(i), 3203 match = subValue.match(/\d+/), 3204 ind = 0; 3205 for (i; i < mask.length; i++) { 3206 if (mask[i] != '#') { 3207 value += mask[i]; 3208 } else if (match && match[0][ind]) { 3209 value += match[0][ind++]; 3210 } else { 3211 break; 3212 } 3213 } 3214 input.value = value; 3215 } 3216} 3217 3218formsApp.sortPoll = function(field){ 3219 let array = Array.apply(null, field.querySelectorAll('.ba-form-checkbox-wrapper')), 3220 last = null, 3221 count = field.style.getPropertyValue('--checkbox-field-count') * 1, 3222 index = 1; 3223 array.sort(function(a, b){ 3224 if (a.style.getPropertyValue('--poll-order') * 1 > b.style.getPropertyValue('--poll-order') * 1) { 3225 return 1; 3226 } else if (a.style.getPropertyValue('--poll-order') * 1 < b.style.getPropertyValue('--poll-order') * 1) { 3227 return -1; 3228 } else { 3229 return 0; 3230 } 3231 }); 3232 array.forEach(function(div){ 3233 if (index == count) { 3234 div.classList.add('last-row-checkbox-wrapper'); 3235 index = 0; 3236 } else { 3237 div.classList.remove('last-row-checkbox-wrapper'); 3238 } 3239 index++; 3240 }); 3241 last = array.pop(); 3242 last ? last.classList.add('last-row-checkbox-wrapper') : ''; 3243} 3244 3245document.addEventListener('DOMContentLoaded', formsApp.createForms); 3246if (document.readyState == 'complete') { 3247 formsApp.createForms(); 3248}
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.