1/** 2 * Centralized field initialization for WPUF Pro 3 * Handles initialization of fields that require JavaScript plugins 4 * Compatible with repeat fields and dynamic field instances 5 */ 6(function($) { 7 'use strict'; 8 9 var WPUF_Field_Initializer = { 10 11 isInitializing: false, 12 13 init: function() { 14 this.initDateFields(); 15 this.initCountryFields(); 16 this.initPhoneFields(); 17 this.initRatingFields(); 18 this.initFileFields(); 19 this.bindEvents(); 20 }, 21 22 /** 23 * Initialize date fields 24 */ 25 initDateFields: function() { 26 if (this.isInitializing) { 27 return; 28 } 29 30 var dateFields = $('.wpuf-date-field:not(.wpuf-initialized)'); 31 32 // Clean up any existing date field initializations that might be orphaned 33 $('.wpuf-date-field.hasDatepicker').each(function() { 34 var $field = $(this); 35 if (!$field.hasClass('wpuf-initialized')) { 36 try { 37 $field.datepicker('destroy'); 38 } catch (error) { 39 $field.removeClass('hasDatepicker'); 40 } 41 } 42 }); 43 44 if (dateFields.length === 0) { 45 return; 46 } 47 48 this.isInitializing = true; 49 50 dateFields.each(function(index) { 51 var $field = $(this); 52 53 // Remove any existing datepicker/datetimepicker initialization 54 if ($field.hasClass('hasDatepicker')) { 55 try { 56 $field.datepicker('destroy'); 57 } catch (error) { 58 $field.removeClass('hasDatepicker'); 59 } 60 } 61 if ($field.hasClass('hasTimepicker')) { 62 try { 63 $field.datetimepicker('destroy'); 64 } catch (error) { 65 $field.removeClass('hasTimepicker'); 66 } 67 } 68 69 var format = $field.data('format') || 'dd/mm/yy'; 70 var timeEnabled = $field.data('time') === 'yes'; 71 var mintime = $field.data('mintime'); 72 var maxtime = $field.data('maxtime'); 73 74 var dateConfig = { 75 dateFormat: format, 76 changeMonth: true, 77 changeYear: true, 78 yearRange: '-100:+20' 79 }; 80 81 // Add min/max date constraints if set 82 if (mintime || maxtime) { 83 if (mintime) { 84 var mintimeParts = mintime.split('-'); 85 dateConfig.minDate = new Date(mintimeParts[2], mintimeParts[1] - 1, mintimeParts[0]); 86 } 87 if (maxtime) { 88 var maxtimeParts = maxtime.split('-'); 89 dateConfig.maxDate = new Date(maxtimeParts[2], maxtimeParts[1] - 1, maxtimeParts[0]); 90 } 91 } 92 93 // Initialize based on time setting 94 try { 95 if (timeEnabled) { 96 $field.datetimepicker(dateConfig); 97 } else { 98 $field.datepicker(dateConfig); 99 } 100 101 // Mark as initialized 102 $field.addClass('wpuf-initialized'); 103 } catch (error) { 104 // Error initializing date field 105 } 106 }); 107 108 this.isInitializing = false; 109 }, 110 111 /** 112 * Initialize country fields 113 */ 114 initCountryFields: function() { 115 if (this.isInitializing) { 116 return; 117 } 118 119 var countryFields = $('select[data-countries]:not(.wpuf-initialized)'); 120 121 if (countryFields.length === 0) { 122 return; 123 } 124 125 // Check if selectize is available globally 126 if (typeof $.fn.selectize === 'undefined') { 127 return; 128 } 129 130 this.isInitializing = true; 131 132 countryFields.each(function(index) { 133 var $field = $(this); 134 135 // Remove any existing selectize initialization 136 if ($field.hasClass('selectized')) { 137 try { 138 $field[0].selectize.destroy(); 139 } catch (error) { 140 $field.removeClass('selectized'); 141 } 142 } 143 144 try { 145 // Safely parse JSON data with fallbacks 146 var countriesData = $field.data('countries'); 147 var bannedCountriesData = $field.data('banned-countries'); 148 var allowedCountriesData = $field.data('allowed-countries'); 149 150 var countries = []; 151 var bannedCountries = []; 152 var allowedCountries = []; 153 154 // Parse countries data 155 if (countriesData) { 156 if (typeof countriesData === 'string') { 157 try { 158 countries = JSON.parse(countriesData); 159 } catch (e) { 160 countries = []; 161 } 162 } else if (Array.isArray(countriesData)) { 163 countries = countriesData; 164 } else { 165 countries = []; 166 } 167 } 168 169 // Parse banned countries data 170 if (bannedCountriesData) { 171 if (typeof bannedCountriesData === 'string') { 172 try { 173 bannedCountries = JSON.parse(bannedCountriesData); 174 } catch (e) { 175 bannedCountries = []; 176 } 177 } else if (Array.isArray(bannedCountriesData)) { 178 bannedCountries = bannedCountriesData; 179 } 180 } 181 182 // Parse allowed countries data 183 if (allowedCountriesData) { 184 if (typeof allowedCountriesData === 'string') { 185 try { 186 allowedCountries = JSON.parse(allowedCountriesData); 187 } catch (e) { 188 allowedCountries = []; 189 } 190 } else if (Array.isArray(allowedCountriesData)) { 191 allowedCountries = allowedCountriesData; 192 } 193 } 194 195 var listVisibilityOption = $field.data('list-visibility-option') || 'all'; 196 var selectedCountry = $field.data('selected-country') || ''; 197 198 // Build options based on visibility settings 199 var options = []; 200 201 // Ensure countries is an array 202 if (!Array.isArray(countries)) { 203 if (typeof countries === 'object' && countries !== null) { 204 // Convert object to array if needed 205 var countriesArray = []; 206 for (var code in countries) { 207 if (countries.hasOwnProperty(code)) { 208 countriesArray.push({ 209 code: code, 210 name: countries[code] 211 }); 212 } 213 } 214 countries = countriesArray; 215 } else { 216 countries = []; 217 } 218 } 219 220 if (listVisibilityOption === 'hide') { 221 // Show all countries except banned ones
222 countries.forEach(function(country) { 223 if (bannedCountries.indexOf(country.code) === -1) { 224 options.push({ 225 value: country.code, 226 text: country.name 227 }); 228 } 229 }); 230 } else if (listVisibilityOption === 'show') { 231 // Show only allowed countries 232 allowedCountries.forEach(function(countryCode) { 233 var country = countries.find(function(c) { return c.code === countryCode; }); 234 if (country) { 235 options.push({ 236 value: country.code, 237 text: country.name 238 }); 239 } 240 }); 241 } else { 242 // Show all countries 243 countries.forEach(function(country) { 244 options.push({ 245 value: country.code, 246 text: country.name 247 }); 248 }); 249 } 250 251 // Check if selectize is available 252 if (typeof $.fn.selectize !== 'undefined') { 253 // Initialize selectize 254 $field.selectize({ 255 options: options, 256 items: selectedCountry ? [selectedCountry] : [], 257 placeholder: 'Select a country', 258 allowEmptyOption: true 259 }); 260 261 // Mark as initialized 262 $field.addClass('wpuf-initialized'); 263 } else { 264 // Fallback to regular select if selectize is not available 265 // Clear existing options 266 $field.empty(); 267 268 // Add placeholder option 269 $field.append('<option value="">Select a country</option>'); 270 271 // Add country options 272 options.forEach(function(option) { 273 var selected = option.value === selectedCountry ? 'selected' : ''; 274 $field.append('<option value="' + option.value + '" ' + selected + '>' + option.text + '</option>'); 275 }); 276 277 // Mark as initialized 278 $field.addClass('wpuf-initialized'); 279 } 280 281 } catch (error) { 282 // Error initializing country field 283 } 284 }); 285 286 this.isInitializing = false; 287 }, 288 289 /** 290 * Initialize phone fields 291 */ 292 initPhoneFields: function() { 293 if (this.isInitializing) { 294 return; 295 } 296 297 // Find all phone fields first for debugging 298 var allPhoneFields = $('input[type="tel"], input.wpuf_telephone'); 299 300 // Debug: Log state of all phone fields 301 allPhoneFields.each(function() { 302 var $field = $(this); 303 var fieldId = $field.attr('id') || 'no-id'; 304 var $wrapper = $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code'); 305 var hasWrapper = $wrapper.length && $wrapper[0] !== $field[0]; 306 var hasInitClass = $field.hasClass('wpuf-initialized'); 307 var hasInstance = false; 308 309 try { 310 var instance = window.intlTelInput && window.intlTelInput.getInstance($field[0]); 311 hasInstance = !!instance; 312 } catch (e) { 313 hasInstance = false; 314 } 315 }); 316 317 // Find phone fields that need initialization 318 // Include fields that are marked as initialized but missing the wrapper (broken state) 319 var phoneFields = allPhoneFields.filter(function() { 320 var $field = $(this); 321 var $wrapper = $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code'); 322 var hasWrapper = $wrapper.length && $wrapper[0] !== $field[0]; 323 324 // If already properly wrapped, skip 325 if (hasWrapper && $field.hasClass('wpuf-initialized')) { 326 return false; 327 } 328 329 // If marked as initialized but missing wrapper, remove the class to re-initialize 330 if ($field.hasClass('wpuf-initialized') && !hasWrapper) { 331 $field.removeClass('wpuf-initialized'); 332 } 333 334 return true; 335 }); 336 337 // Clean up any existing phone field initializations that might be orphaned
338 $('input.wpuf_telephone').each(function() { 339 var $field = $(this); 340 if (!$field.hasClass('wpuf-initialized')) { 341 // Check if wrapped 342 var $wrapper = $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code'); 343 if ($wrapper.length && $wrapper[0] !== $field[0]) { 344 // Unwrap it 345 $field.detach(); 346 $wrapper.replaceWith($field); 347 } 348 // Try to destroy if has intlTelInput instance 349 if ($field.data('intlTelInput')) { 350 try { 351 $field.intlTelInput('destroy'); 352 } catch (error) { 353 $field.removeClass('iti'); 354 } 355 } 356 } 357 }); 358 359 if (phoneFields.length === 0) { 360 return; 361 } 362 363 // Check if intlTelInput is available 364 if (typeof window.intlTelInput === 'undefined') { 365 return; 366 } 367 368 this.isInitializing = true; 369 370 phoneFields.each(function(index) { 371 var $field = $(this); 372 var fieldId = $field.attr('id') || 'no-id'; 373 374 // Check if already wrapped in intlTelInput container 375 var $existingWrapper = $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code'); 376 if ($existingWrapper.length && $existingWrapper[0] !== $field[0]) { 377 // Already wrapped, verify it's properly initialized 378 try { 379 var instance = window.intlTelInput.getInstance($field[0]); 380 if (instance) { 381 $field.addClass('wpuf-initialized'); 382 return; 383 } else {} 384 } catch (e) {} 385 } 386 387 // Check for existing instance before destroying 388 var existingInstance = null; 389 try { 390 existingInstance = window.intlTelInput.getInstance($field[0]); 391 if (existingInstance) { 392 existingInstance.destroy(); 393 } else { 394 } 395 } catch (e) {} 396 397 // Remove any wrapper that might exist 398 var $wrapper = $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code'); 399 if ($wrapper.length && $wrapper[0] !== $field[0]) { 400 $field.detach(); 401 $wrapper.replaceWith($field); 402 } 403 404 // Clean up classes and data 405 $field.removeClass('iti wpuf-initialized'); 406 $field.removeAttr('data-intl-tel-input-id'); 407 $field.removeData('intlTelInput'); 408 409 try { 410 // Get field-specific settings 411 var showList = $field.data('show-list') || 'yes'; 412 var defaultCountry = $field.data('default-country') || ''; 413 var autoPlaceholder = $field.data('auto-placeholder') || 'yes'; 414 var utilsScript = $field.data('utils-script') || ''; 415 416 // Parse JSON data attributes 417 var onlyCountries = []; 418 var excludeCountries = []; 419 420 try { 421 var onlyCountriesData = $field.data('only-countries'); 422 if (onlyCountriesData && typeof onlyCountriesData === 'string') { 423 onlyCountries = JSON.parse(onlyCountriesData); 424 } else if (Array.isArray(onlyCountriesData)) { 425 onlyCountries = onlyCountriesData; 426 } 427 } catch (e) { 428 // Error parsing only-countries data 429 } 430 431 try { 432 var excludeCountriesData = $field.data('exclude-countries'); 433 if (excludeCountriesData && typeof excludeCountriesData === 'string') { 434 excludeCountries = JSON.parse(excludeCountriesData); 435 } else if (Array.isArray(excludeCountriesData)) { 436 excludeCountries = excludeCountriesData; 437 } 438 } catch (e) { 439 // Error parsing exclude-countries data 440 } 441 442 // Only initialize if show_list is 'yes' 443 if (showList === 'yes') { 444 // Check if intlTelInput is available 445 if (typeof window.intlTelInput !== 'undefined') { 446 var config = {}; 447 448 if (utilsScript) { 449 config.utilsScript = utilsScript; 450 } 451 452 if (defaultCountry) { 453 config.initialCountry = defaultCountry; 454 } 455 456 if (onlyCountries && onlyCountries.length > 0) { 457 config.onlyCountries = onlyCountries; 458 } 459 460 if (excludeCountries && excludeCountries.length > 0) { 461 config.excludeCountries = excludeCountries; 462 } 463 464 if (autoPlaceholder === 'no') { 465 config.autoPlaceholder = 'off'; 466 } 467 468 // Initialize international telephone input using the global function 469 try { 470 window.intlTelInput($field[0], config); 471 472 // Verify the wrapper was created immediately 473 // intlTelInput wraps the input synchronously 474 var $wrapper = $field.parent(); 475 var hasWrapper = $wrapper.length && 476 ($wrapper.hasClass('iti') || 477 $wrapper.hasClass('iti--allow-dropdown') || 478 $wrapper.hasClass('iti--separate-dial-code')); 479 480 if (hasWrapper) { 481 // Wrapper was created successfully - mark as initialized 482 $field.addClass('wpuf-initialized'); 483 } else { 484 // Wrapper not found - initialization may have failed 485 // Try to get instance to verify 486 try { 487 var instance = window.intlTelInput.getInstance($field[0]); 488 if (instance) { 489 // Instance exists, check parent one more time 490 $wrapper = $field.parent(); 491 if ($wrapper.hasClass('iti') || 492 $wrapper.hasClass('iti--allow-dropdown') || 493 $wrapper.hasClass('iti--separate-dial-code')) { 494 $field.addClass('wpuf-initialized'); 495 } else {} 496 } else {} 497 } catch (e) {} 498 } 499 } catch (error) { 500 // Initialization failed, don't mark as initialized 501 $field.removeClass('wpuf-initialized'); 502 // Add a simple placeholder as fallback 503 if (!$field.attr('placeholder')) { 504 $field.attr('placeholder', 'Enter phone number'); 505 } 506 } 507 } else { 508 // show_list is 'no', mark as initialized without wrapper 509 $field.addClass('wpuf-initialized'); 510 } 511 } else { 512 // show_list is 'no', mark as initialized without wrapper 513 $field.addClass('wpuf-initialized'); 514 } 515 } catch (error) {} 516 }); 517 518 this.isInitializing = false; 519 }, 520 521 /** 522 * Initialize rating fields 523 */ 524 initRatingFields: function() { 525 $('.wpuf-ratings:not(.wpuf-initialized)').each(function() { 526 var $field = $(this); 527 528 // Remove any existing barrating initialization 529 if ($field.hasClass('br-theme-css-stars')) { 530 $field.barrating('destroy'); 531 } 532 533 try { 534 $field.barrating({ 535 theme: 'css-stars' 536 }); 537 538 // Mark as initialized 539 $field.addClass('wpuf-initialized'); 540 } catch (error) { 541 // Error initializing rating field 542 } 543 }); 544 }, 545 546 /** 547 * Initialize file upload fields 548 */ 549 initFileFields: function() { 550 $('.wpuf-file-upload:not(.wpuf-initialized)').each(function() { 551 var $field = $(this); 552 var uniqueId = $field.data('unique-id'); 553 var fieldName = $field.data('field-name'); 554 var count = $field.data('count') || 1; 555 var allowedExt = $field.data('allowed-ext') || ''; 556 var maxSize = $field.data('max-size') || 1024; 557 558 if (uniqueId && fieldName) { 559 try { 560 var uploader = new WPUF_Uploader( 561 'wpuf-' + uniqueId + '-pickfiles', 562 'wpuf-' + uniqueId + '-upload-container', 563 count, 564 fieldName, 565 allowedExt, 566 maxSize 567 ); 568 569 if (typeof wpuf_plupload_items !== 'undefined') { 570 wpuf_plupload_items.push(uploader); 571 } 572 573 // Mark as initialized 574 $field.addClass('wpuf-initialized'); 575 } catch (error) { 576 // Error initializing file upload field 577 } 578 } 579 }); 580 }, 581 582 /** 583 * Clean up initialized fields (for cloned elements) 584 */ 585 cleanupInitializedFields: function($container) { 586 if (!$container) { 587 $container = $('body'); 588 } 589 590 // Remove initialization classes and destroy plugins 591 var initializedFields = $container.find('.wpuf-initialized'); 592 593 initializedFields.each(function() { 594 var $field = $(this); 595 $field.removeClass('wpuf-initialized'); 596 597 // Destroy datepicker if exists - handle safely 598 if ($field.hasClass('hasDatepicker')) { 599 try { 600 $field.datepicker('destroy'); 601 } catch (error) { 602 // Remove the hasDatepicker class manually 603 $field.removeClass('hasDatepicker'); 604 // Remove any datepicker-related elements 605 $field.siblings('.ui-datepicker').remove(); 606 } 607 } 608 if ($field.hasClass('hasTimepicker')) { 609 try { 610 $field.datetimepicker('destroy'); 611 } catch (error) { 612 // Remove the hasTimepicker class manually 613 $field.removeClass('hasTimepicker'); 614 // Remove any datetimepicker-related elements 615 $field.siblings('.ui-datetimepicker').remove(); 616 } 617 } 618 619 // Destroy barrating if exists 620 if ($field.hasClass('br-theme-css-stars')) { 621 try { 622 $field.barrating('destroy'); 623 } catch (error) { 624 // Remove barrating-related classes manually 625 $field.removeClass('br-theme-css-stars'); 626 $field.siblings('.br-wrapper').remove(); 627 } 628 } 629 630 // Destroy selectize if exists 631 if ($field.hasClass('selectized') && $field[0].selectize) { 632 try { 633 $field[0].selectize.destroy(); 634 } catch (error) { 635 // Remove selectize-related classes manually 636 $field.removeClass('selectized'); 637 $field.siblings('.selectize-control').remove(); 638 } 639 } 640 641 // Destroy intlTelInput if exists 642 if ($field.hasClass('iti') || $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code').length) { 643 try { 644 // Try to get the intlTelInput instance and destroy it 645 if ($field.data('intlTelInput')) { 646 $field.intlTelInput('destroy'); 647 } 648 } catch (error) {
649 // If destroy fails, manually unwrap 650 } 651 652 // Unwrap the input from intlTelInput container 653 var $wrapper = $field.closest('.iti, .iti--allow-dropdown, .iti--separate-dial-code'); 654 if ($wrapper.length && $wrapper[0] !== $field[0]) { 655 $field.detach(); 656 $wrapper.replaceWith($field); 657 } 658 659 // Remove intlTelInput-related classes and data 660 $field.removeClass('iti wpuf-initialized'); 661 $field.removeAttr('data-intl-tel-input-id'); 662 } 663 }); 664 }, 665 666 /** 667 * Bind events for dynamic content 668 */ 669 bindEvents: function() { 670 // Re-initialize fields when new content is added (for repeat fields) 671 $(document).on('wpuf-repeat-instance-added', function(event, $newInstance) { 672 // Clean up any existing initializations in the new instance 673 WPUF_Field_Initializer.cleanupInitializedFields($newInstance); 674 675 // Re-initialize fields in the new instance with a longer delay 676 setTimeout(function() { 677 WPUF_Field_Initializer.initDateFields(); 678 WPUF_Field_Initializer.initCountryFields(); 679 WPUF_Field_Initializer.initPhoneFields(); 680 WPUF_Field_Initializer.initRatingFields(); 681 WPUF_Field_Initializer.initFileFields(); 682 }, 200); 683 }); 684 685 // Handle conditional logic updates 686 $(document).on('wpuf-conditional-logic-updated', function() { 687 WPUF_Field_Initializer.initDateFields(); 688 WPUF_Field_Initializer.initCountryFields(); 689 WPUF_Field_Initializer.initPhoneFields(); 690 WPUF_Field_Initializer.initRatingFields(); 691 WPUF_Field_Initializer.initFileFields(); 692 }); 693 }, 694 695 /** 696 * Re-initialize all fields (useful for repeat field instances) 697 */ 698 reinitialize: function() { 699 this.initDateFields(); 700 this.initCountryFields(); 701 this.initPhoneFields(); 702 this.initRatingFields(); 703 this.initFileFields(); 704 } 705 }; 706 707 // Initialize on document ready 708 $(document).ready(function() { 709 if (typeof WPUF_Field_Initializer !== 'undefined' && typeof WPUF_Field_Initializer.init === 'function') { 710 WPUF_Field_Initializer.init(); 711 } 712 }); 713 714 // Make available globally 715 window.WPUF_Field_Initializer = WPUF_Field_Initializer; 716 717})(jQuery);
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.