| @@ -153,9 +153,17 @@ | ||
| 153 | 153 | //jQuery(".gform-datepicker").datepicker('destroy'); |
| 154 | 154 | get_repeater_data_name(); |
| 155 | 155 | }); |
| 156 | 156 | gform.addFilter('gform_file_upload_markup', function (html, file, up, strings, imagesUrl, response) { |
| 157 | - var repeater = $('#' + file.id).closest(".container-repeater-field").find(".gform_multifile_upload") | |
| 157 | + var formId = up.settings.multipart_params.form_id; | |
| 158 | + var fieldId = up.settings.multipart_params.field_id; | |
| 159 | + var container = $('#' + file.id).closest(".container-repeater-field"); | |
| 160 | + var id_rand = container.data("id"); | |
| 161 | + var nameAttr = 'gform_multifile_upload_' + formId + '_' + fieldId + '__' + id_rand; | |
| 162 | + var repeater = container.find('input[name="' + nameAttr + '"]'); | |
| 163 | + if (repeater.length === 0) { | |
| 164 | + repeater = container.find(".gform_multifile_upload"); | |
| 165 | + } | |
| 158 | 166 | var val_repeater = repeater.val(); |
| 159 | 167 | var link = response.data.uploaded_filename; |
| 160 | 168 | if (val_repeater == "") { |
| 161 | 169 | repeater.val(link) |
| @@ -163,8 +171,17 @@ | ||
| 163 | 171 | repeater.val(val_repeater + ", " + link); |
| 164 | 172 | } |
| 165 | 173 | return html.replace("onclick", "data-onclick");; |
| 166 | 174 | }); |
| 175 | + if (window.gform && typeof window.gform.addFilter === 'function') { | |
| 176 | + window.gform.addFilter('gform_datepicker_options_pre_init', function (options, formId, fieldId) { | |
| 177 | + if (typeof fieldId === 'string' && fieldId.indexOf('-') > -1) { | |
| 178 | + var originalFieldId = fieldId.split('-')[0]; | |
| 179 | + return window.gform.applyFilters('gform_datepicker_options_pre_init', options, formId, originalFieldId); | |
| 180 | + } | |
| 181 | + return options; | |
| 182 | + }, 9); | |
| 183 | + } | |
| 167 | 184 | var repeater_fields_htmls = {}; |
| 168 | 185 | //condition out repeater out |
| 169 | 186 | gform.addAction('gform_post_conditional_logic_field_action1', function (formId, action, targetId, defaultValues, isInit) { |
| 170 | 187 | if (targetId != "") { |
| @@ -205,9 +222,12 @@ | ||
| 205 | 222 | function gformDeleteUploadedFileRepeater(formId, fieldId, deleteButton) { |
| 206 | 223 | if (deleteButton.closest(".repeater-field-warp-item-data").length > 0) { |
| 207 | 224 | var rand_id = deleteButton.closest(".container-repeater-field").data("id"); |
| 208 | 225 | var fileIndex = jQuery(deleteButton).parent().index(); |
| 209 | - var parent = jQuery("#field_" + formId + "_" + fieldId); | |
| 226 | + var parent = deleteButton.closest(".container-repeater-field").find("#field_" + formId + "_" + fieldId + "-" + rand_id); | |
| 227 | + if (parent.length === 0) { | |
| 228 | + parent = jQuery("#field_" + formId + "_" + fieldId); | |
| 229 | + } | |
| 210 | 230 | parent.find('input[type="file"],.validation_message,#extensions_message_' + formId + '_' + fieldId).removeClass("gform_hidden"); |
| 211 | 231 | parent.find(".ginput_post_image_file").show(); |
| 212 | 232 | //parent.find("input[type=\"text\"]").val(''); |
| 213 | 233 | var filesJson = jQuery('#gform_uploaded_files_' + formId).val(); |
| @@ -214,9 +234,9 @@ | ||
| 214 | 234 | if (filesJson) { |
| 215 | 235 | var files = jQuery.secureEvalJSON(filesJson); |
| 216 | 236 | if (files) { |
| 217 | 237 | var inputName = "input_" + fieldId; |
| 218 | - var full_name = deleteButton.closest(".repeater-field-warp-item-data").find('input[name="gform_multifile_upload_' + formId + '_' + fieldId + '__' + rand_id + '"]').val(); | |
| 238 | + var full_name = deleteButton.closest(".container-repeater-field").find('input[name="gform_multifile_upload_' + formId + '_' + fieldId + '__' + rand_id + '"]').val(); | |
| 219 | 239 | if (full_name == "") { |
| 220 | 240 | full_name = []; |
| 221 | 241 | } else { |
| 222 | 242 | full_name = full_name.split(","); |
| @@ -226,9 +246,9 @@ | ||
| 226 | 246 | var index1 = full_name.indexOf(remove_name); |
| 227 | 247 | if (index1 !== -1) { |
| 228 | 248 | full_name.splice(index1, 1); |
| 229 | 249 | } |
| 230 | - deleteButton.closest(".repeater-field-warp-item-data").find('input[name="gform_multifile_upload_' + formId + '_' + fieldId + '__' + rand_id + '"]').val(full_name.join(",")); | |
| 250 | + deleteButton.closest(".container-repeater-field").find('input[name="gform_multifile_upload_' + formId + '_' + fieldId + '__' + rand_id + '"]').val(full_name.join(",")); | |
| 231 | 251 | deleteButton.closest(".ginput_preview").remove(); |
| 232 | 252 | if ($multfile.length > 0) { |
| 233 | 253 | files[inputName].splice(fileIndex, 1); |
| 234 | 254 | var settings = $multfile.data('settings'); |
| @@ -331,13 +351,35 @@ | ||
| 331 | 351 | } else { |
| 332 | 352 | $(this).attr("name", name + "__" + id_rand); |
| 333 | 353 | } |
| 334 | 354 | $(this).attr("id", id + "-" + id_rand); |
| 355 | + if ($(this).hasClass('gform-datepicker') || $(this).hasClass('datepicker')) { | |
| 356 | + $(this).removeAttr('data-initialized').removeData('initialized').removeClass('hasDatepicker'); | |
| 357 | + if (this.dataset) { | |
| 358 | + delete this.dataset.initialized; | |
| 359 | + delete this.dataset.toggleClickedBeforeInit; | |
| 360 | + } | |
| 361 | + var $toggleBtn = $(this).siblings('.gform-datepicker-toggle'); | |
| 362 | + if (!$toggleBtn.length) { | |
| 363 | + $toggleBtn = $(this).closest('.ginput_container_date').find('.gform-datepicker-toggle'); | |
| 364 | + } | |
| 365 | + if ($toggleBtn.length) { | |
| 366 | + $toggleBtn.attr('id', 'datepicker_toggle_' + id + '-' + id_rand); | |
| 367 | + $toggleBtn.attr('aria-controls', id + '-' + id_rand); | |
| 368 | + } | |
| 369 | + var $kbd = $(this).siblings('#keyboardHint_' + id); | |
| 370 | + if (!$kbd.length) { | |
| 371 | + $kbd = $(this).closest('.ginput_container_date').find('#keyboardHint_' + id); | |
| 372 | + } | |
| 373 | + if ($kbd.length) { | |
| 374 | + $kbd.attr('id', 'keyboardHint_' + id + '-' + id_rand); | |
| 375 | + } | |
| 376 | + } | |
| 335 | 377 | var value_check = localStorage.getItem(id + "-" + id_rand); |
| 336 | 378 | if (type == "checkbox") { |
| 337 | 379 | $(this).closest("div").find("label").attr("for", id + "-" + id_rand); |
| 338 | 380 | if (value_check != null) { |
| 339 | - $(this).attr("checked", "checked"); | |
| 381 | + $(this).prop("checked", true).attr("checked", "checked"); | |
| 340 | 382 | } |
| 341 | 383 | } else if (type == "file") { |
| 342 | 384 | $(this).attr("id", id + "-" + id_rand); |
| 343 | 385 | } else if (type == "radio") { |
| @@ -346,9 +388,9 @@ | ||
| 346 | 388 | var value_check = localStorage.getItem(name + "__" + id_rand); |
| 347 | 389 | if (value_check != null) { |
| 348 | 390 | var old_check = $(this).val(); |
| 349 | 391 | if (old_check == value_check) { |
| 350 | - $(this).attr("checked", true); | |
| 392 | + $(this).prop("checked", true).attr("checked", "checked"); | |
| 351 | 393 | } |
| 352 | 394 | } |
| 353 | 395 | } |
| 354 | 396 | else { |
| @@ -407,8 +449,9 @@ | ||
| 407 | 449 | var header = get_repeater_data_header(start_field); |
| 408 | 450 | item.find(".repeater-field-header").append(header); |
| 409 | 451 | item.find(".repeater-field-content").append(html_field); |
| 410 | 452 | button.find(".repeater-field-warp-item").append(item); |
| 453 | + item.find("input[type=radio][checked], input[type=checkbox][checked]").prop("checked", true); | |
| 411 | 454 | update_repeater_count_header(); |
| 412 | 455 | $("input").trigger("done_load_repeater"); |
| 413 | 456 | var form_ids = button.attr("id").split("_"); |
| 414 | 457 | if (yeeaddons_gf_repeater_data.pro == "ok") { |
| @@ -459,14 +502,15 @@ | ||
| 459 | 502 | } |
| 460 | 503 | } |
| 461 | 504 | } |
| 462 | 505 | //end logic |
| 463 | - var j = 0; | |
| 506 | + | |
| 464 | 507 | $.each(names_upload, function (key_1, value) { |
| 465 | - gfMultiFileUploader.setup("#" + value); | |
| 466 | - names_upload.splice(j, 1); | |
| 467 | - j++; | |
| 508 | + if ($("#" + value).length > 0) { | |
| 509 | + gfMultiFileUploader.setup("#" + value); | |
| 510 | + } | |
| 468 | 511 | }); |
| 512 | + names_upload = []; | |
| 469 | 513 | var input_mask = yeeaddons_gf_repeater_data.input_mask; |
| 470 | 514 | $.each(input_ids, function (key_1, value_1) { |
| 471 | 515 | if (value_1 in input_mask) { |
| 472 | 516 | $('#' + value_1 + "-" + key).mask(input_mask[value_1]).bind('keypress', function (e) { if (e.which == 13) { jQuery(this).blur(); } }) |
| @@ -475,15 +519,48 @@ | ||
| 475 | 519 | conditional_logic_custom(key); |
| 476 | 520 | input_ids = []; |
| 477 | 521 | $('.gform-datepicker').each(function () { |
| 478 | 522 | var $element = $(this); |
| 479 | - initSingleDatepicker($element); | |
| 480 | - $element.addClass('initialized'); | |
| 523 | + if (typeof $.fn.datepicker === 'function') { | |
| 524 | + // Legacy GF < 3.0: jQuery UI datepicker available | |
| 525 | + if (!$element.hasClass('hasDatepicker')) { | |
| 526 | + initSingleDatepicker($element); | |
| 527 | + $element.addClass('initialized'); | |
| 528 | + } | |
| 529 | + } | |
| 481 | 530 | }); |
| 531 | + // GF 3.0+: Re-trigger datepicker initialization for the form | |
| 532 | + // so GF's theme script loads the datepicker chunk and sets up delegation | |
| 533 | + reinitGF3Datepicker(button); | |
| 482 | 534 | } |
| 535 | + /** | |
| 536 | + * Re-trigger GF 3.0 datepicker initialization. | |
| 537 | + * GF 3.0 uses lazy-loading: the datepicker chunk is only loaded when | |
| 538 | + * gform/post_render fires and .gform-datepicker elements exist in the DOM. | |
| 539 | + * Since the repeater removes original fields before GF checks for them, | |
| 540 | + * we need to re-dispatch the event after creating new rows. | |
| 541 | + */ | |
| 542 | + var _gf3DatepickerTriggered = {}; | |
| 543 | + function reinitGF3Datepicker(el) { | |
| 544 | + if (typeof $.fn.datepicker === 'function') { | |
| 545 | + return; // Legacy jQuery UI datepicker is available, no need for GF 3.0 re-init | |
| 546 | + } | |
| 547 | + var $wrapper = el.closest('.gform_wrapper'); | |
| 548 | + if (!$wrapper.length) return; | |
| 549 | + var formId = parseInt($wrapper.attr('id').replace('gform_wrapper_', '')); | |
| 550 | + if (!formId || isNaN(formId)) return; | |
| 551 | + // Only trigger once per form per page load to avoid duplicate event listeners | |
| 552 | + if (_gf3DatepickerTriggered[formId]) return; | |
| 553 | + _gf3DatepickerTriggered[formId] = true; | |
| 554 | + // Dispatch gform/post_render so GF's theme script detects datepicker fields | |
| 555 | + // and lazy-loads the accessible datepicker chunk | |
| 556 | + document.dispatchEvent(new CustomEvent('gform/post_render', { | |
| 557 | + detail: { formId: formId, currentPage: 1 } | |
| 558 | + })); | |
| 559 | + } | |
| 483 | 560 | function yeeaddons_change_id_logic(value, key) { |
| 484 | 561 | var field_rules_inner = []; |
| 485 | - if (value && Array.isArray(value.field.rules)) { // added this line to fix js issue in add more to autofill multiple data | |
| 562 | + if (value && value.field && Array.isArray(value.field.rules)) { // added this line to fix js issue in add more to autofill multiple data | |
| 486 | 563 | $.each(value.field.rules, function (key_2, value_2) { |
| 487 | 564 | if (value_2.fieldId.search("-") < 0) { |
| 488 | 565 | var field_id_1 = value_2.fieldId + "-" + key; |
| 489 | 566 | } |
| @@ -865,15 +942,17 @@ | ||
| 865 | 942 | } |
| 866 | 943 | inputId = inputId.split('_'); |
| 867 | 944 | // allow the user to override the datepicker options object |
| 868 | 945 | optionsObj = gform.applyFilters('gform_datepicker_options_pre_init', optionsObj, inputId[1], inputId[2], $element); |
| 869 | - $element.datepicker(optionsObj); | |
| 870 | - // We give the input focus after selecting a date which differs from default Datepicker behavior; this prevents | |
| 871 | - // users from clicking on the input again to open the datepicker. Let's add a manual click event to handle this. | |
| 872 | - if ($element.is(':input')) { | |
| 873 | - $element.click(function () { | |
| 874 | - $element.datepicker('show'); | |
| 875 | - }); | |
| 946 | + if (typeof $element.datepicker === 'function') { | |
| 947 | + $element.datepicker(optionsObj); | |
| 948 | + // We give the input focus after selecting a date which differs from default Datepicker behavior; this prevents | |
| 949 | + // users from clicking on the input again to open the datepicker. Let's add a manual click event to handle this. | |
| 950 | + if ($element.is(':input')) { | |
| 951 | + $element.click(function () { | |
| 952 | + $element.datepicker('show'); | |
| 953 | + }); | |
| 954 | + } | |
| 876 | 955 | } |
| 877 | 956 | } |
| 878 | 957 | }) |
| 879 | 958 | $(document).on("change", ".gfield--type-repeater_end input,.gfield--type-repeater_end textarea,.gfield--type-repeater_end select", function (event) { |