PluginProbe
Repeater Fields for Gravity Forms / 3.2.0
Repeater Fields for Gravity Forms v3.2.0
3.2.0 3.1.1 3.1.0 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 2.5.1 2.5.0 2.4.6 trunk 2.0.5 2.0.9 2.1.0 2.3.2 2.3.7 2.4.1 2.4.3 2.4.4 2.4.5
← All changes | libs/wp_repeater.js +99 -20 2.4.5 → 3.2.0 View file →
@@ -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) {