Changeset 3359056
- Timestamp:
- 09/10/2025 09:32:02 AM (7 months ago)
- Location:
- mask-form-elementor
- Files:
-
- 16 added
- 10 edited
- 1 copied
-
tags/4.2.3 (copied) (copied from mask-form-elementor/trunk)
-
tags/4.2.3/admin/marketing (added)
-
tags/4.2.3/admin/marketing/css (added)
-
tags/4.2.3/admin/marketing/css/mfe-mkt.css (added)
-
tags/4.2.3/admin/marketing/images (added)
-
tags/4.2.3/admin/marketing/images/mfe-highlight-icon.svg (added)
-
tags/4.2.3/admin/marketing/js (added)
-
tags/4.2.3/admin/marketing/js/mfe-form-marketing.js (added)
-
tags/4.2.3/admin/marketing/mfe-marketing-common.php (added)
-
tags/4.2.3/assets/js/custom-mask-script.js (modified) (4 diffs)
-
tags/4.2.3/includes/class-elementor-mask-control.php (modified) (1 diff)
-
tags/4.2.3/includes/class-main-mask-form-elementor.php (modified) (2 diffs)
-
tags/4.2.3/index.php (modified) (2 diffs)
-
tags/4.2.3/readme.txt (modified) (2 diffs)
-
trunk/admin/marketing (added)
-
trunk/admin/marketing/css (added)
-
trunk/admin/marketing/css/mfe-mkt.css (added)
-
trunk/admin/marketing/images (added)
-
trunk/admin/marketing/images/mfe-highlight-icon.svg (added)
-
trunk/admin/marketing/js (added)
-
trunk/admin/marketing/js/mfe-form-marketing.js (added)
-
trunk/admin/marketing/mfe-marketing-common.php (added)
-
trunk/assets/js/custom-mask-script.js (modified) (4 diffs)
-
trunk/includes/class-elementor-mask-control.php (modified) (1 diff)
-
trunk/includes/class-main-mask-form-elementor.php (modified) (2 diffs)
-
trunk/index.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
mask-form-elementor/tags/4.2.3/assets/js/custom-mask-script.js
r3347851 r3359056 56 56 let moneymaskFormat = input.dataset.moneymaskFormat 57 57 let type = (moneymaskFormat === 'dot' ? 'D' : 'C') 58 let newValue = formatMoneyInput(input.value, type,moneyPrefix,input); 58 let newValue = ''; 59 60 if(input.value != '$0,00'){ 61 62 newValue = formatMoneyInput(input.value, type, moneyPrefix, input); 63 }else{ 64 newValue = ""; 65 } 66 59 67 if (input.value === newValue) return; 60 68 … … 211 219 var newCaret = mapDigitIndexToCaret(newVal, digitIndex); 212 220 213 input.value = newVal; 221 if(newVal != '('){ 222 223 input.value = newVal; 224 }else{ 225 input.value = ""; 226 } 214 227 215 228 setCaretPosition(input, newCaret || 0); // Keep caret in place … … 333 346 $(document).on("input", selector, function () { 334 347 var input = $(this); 348 nextbtnVisibility(errorClass, input, validationFunction); 335 349 var errorElement = input.closest('.elementor-field-group').find("." + errorClass); 336 350 … … 584 598 585 599 // ----------------- Form Submit ----------------- 600 601 602 // start - step field mask error handling 603 604 let maskErrorArr = {}; 605 let nextBtnOriginalClicks = {}; 606 let clickStatus={}; 607 let recaptchaEvent = {}; 608 let submitBtnEvent = {}; 609 610 611 const nextbtnVisibility = (errorClass, input, validationFunction) => { 612 613 const closesWidget = input.closest(".elementor-widget-form"); 614 const widgetId = closesWidget.data('id'); 615 const inuptId = input.attr('id'); 616 const fieldStep=input.closest(".elementor-field-type-step"); 617 const form = input.closest(".elementor-form"); 618 619 const currectStepFields = form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)").find('input, textarea, select'); 620 621 const submtBtnTag = form.find("button[type='submit']"); 622 623 if (!closesWidget.length || !fieldStep.length) { 624 return; 625 } 626 627 const nextBtn = fieldStep.find(".e-form__buttons__wrapper__button[data-direction='next']"); 628 629 630 631 if ((nextBtn.length == 0 && submtBtnTag.length > 0 ) && (submtBtnTag.length == 0 && nextBtn.length == 0) ) { 632 return; 633 } 634 635 636 637 let val = input.val(); 638 639 if (val.length === 1 && !/\d/.test(val)) { 640 val = ''; 641 } 642 643 // Show error message if validation fails 644 if ( val !== "" && !validationFunction(val)) { 645 646 647 if (closesWidget.length > 0) { 648 649 650 if (!maskErrorArr[widgetId]) { 651 maskErrorArr[widgetId] = []; 652 } 653 654 if (!maskErrorArr[widgetId].includes(inuptId)) { 655 maskErrorArr[widgetId].push(inuptId); 656 } 657 } 658 659 if (!nextBtnOriginalClicks[widgetId] || !nextBtnOriginalClicks[widgetId].length) { 660 661 662 663 if(nextBtn.length > 0){ 664 665 const origninalClicks = jQuery._data(nextBtn[0], "events"); 666 667 if (origninalClicks && (!nextBtnOriginalClicks[widgetId] || !nextBtnOriginalClicks[widgetId].length === 0)) { 668 nextBtnOriginalClicks[widgetId] = origninalClicks && origninalClicks.click ? origninalClicks.click.map(h => h.handler) : []; 669 670 } 671 } 672 673 674 } 675 } else { 676 if (maskErrorArr[widgetId] && maskErrorArr[widgetId].includes(inuptId)) { 677 maskErrorArr[widgetId] = maskErrorArr[widgetId].filter(item => item !== inuptId); 678 } 679 } 680 681 682 if (maskErrorArr[widgetId] && maskErrorArr[widgetId].length > 0) { 683 684 if(nextBtn.length > 0){ 685 686 const origninalClicks = jQuery._data(nextBtn[0], "events"); 687 688 if (origninalClicks && (!nextBtnOriginalClicks[widgetId] || !nextBtnOriginalClicks[widgetId].length)) { 689 690 691 nextBtnOriginalClicks[widgetId] = origninalClicks && origninalClicks.click ? origninalClicks.click.map(h => h.handler) : []; 692 693 } 586 694 587 588 $(document).on("click", ".elementor-field-type-submit", function (e) { 589 var $submitBtn = $(this); 590 var $form = $submitBtn.closest("form"); 591 592 // Prevent double-clicks 593 if ($submitBtn.data("clicked")) { 695 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 696 nextBtn.off("click"); 697 } 698 699 700 } 701 702 703 704 } else { 705 706 707 // when no error in mask validation 708 709 if(recaptchaEvent[widgetId]){ 710 711 recaptchaEvent[widgetId].forEach(fn => { 712 submtBtnTag.one("click", fn); // use .one instead of .on 713 }); 714 } 715 716 if(submitBtnEvent[widgetId]){ 717 form.on("submit", submitBtnEvent[widgetId]); 718 } 719 720 721 722 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 723 724 725 726 727 let isfieldsValid = true 728 729 for (let i = 0; i < currectStepFields.length; i++) { 730 731 732 if (currectStepFields[i].checkValidity() == false) { 733 734 isfieldsValid = false; 735 break; 736 737 } 738 739 } 740 741 if (isfieldsValid) { 742 743 744 745 746 747 if(nextBtn.length > 0){ 748 749 // 2️⃣ First, clear existing handlers to avoid duplication 750 nextBtn.off("click"); 751 752 // Re-attach original click handlers only once 753 nextBtnOriginalClicks[widgetId].forEach(fn => { 754 nextBtn.one("click", fn); // use .one instead of .on 755 }); 756 } 757 758 759 } 760 761 } 762 763 } 764 } 765 766 767 768 769 // handle next button event before click 770 771 $(document).on("mousedown", ".e-form__buttons__wrapper__button[data-direction='next']", function(e){ 772 773 const form = $(this).closest(".elementor-form"); 774 775 const mask_error_div = form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)").find('div.mask-error'); 776 777 const closesWidget = $(this).closest(".elementor-widget-form"); 778 const widgetId = closesWidget.data('id'); 779 780 let mask_error = false; 781 782 // finding mask error 783 for(let i=0; i<mask_error_div.length; i++){ 784 if(mask_error_div[i].value != "" && mask_error_div[i].style.display == 'flex'){ 785 mask_error = true; 786 break; 787 } 788 } 789 790 // reattcach next button event when no mask error 791 792 if (maskErrorArr[widgetId] && !maskErrorArr[widgetId].length > 0 && !mask_error) { 793 // Re-attach original click handlers only once 794 795 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 796 $(this).off("click"); 797 798 nextBtnOriginalClicks[widgetId].forEach(fn => { 799 $(this).one("click", fn); // use .one instead of .on 800 }); 801 } 802 803 804 } 805 806 }) 807 808 809 // handling next button event when previous button click 810 811 $(document).on("click", ".e-form__buttons__wrapper__button[data-direction='previous']", function(e){ 812 813 const form = $(this).closest(".elementor-form"); 814 815 const closesWidget = form.closest(".elementor-widget-form"); 816 const widgetId = closesWidget.data('id'); 817 maskErrorArr[widgetId] = []; 818 819 const currectStepFields = form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)") 820 821 const nextBtn = currectStepFields.find(".e-form__buttons__wrapper__button[data-direction='next']"); 822 823 // attaching events to next button 824 825 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 826 nextBtn.off("click"); 827 828 nextBtnOriginalClicks[widgetId].forEach(fn => { 829 nextBtn.one("click", fn); // use .one instead of .on 830 }); 831 832 } 833 834 }) 835 836 // handle mask validation on submit button of step field form 837 $(document).on("mousedown", ".elementor-field-type-submit", function (e){ 838 839 var $submitBtn = $(this); 840 841 var $form = $submitBtn.closest("form"); 842 843 const closesWidget = $form.closest(".elementor-widget-form"); 844 const widgetId = closesWidget.data('id'); 845 846 const currectStepFields = $form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)") 847 848 const previousBtn = currectStepFields.find(".e-form__buttons__wrapper__button[data-direction='previous']"); 849 850 const inputMaskFields = currectStepFields.find("input.fme-mask-input"); 851 852 // run only first time when click on submit button 853 // if maskerror found in the form widget this will remove submit button and form events to prevent submit 854 855 856 if(previousBtn.length && inputMaskFields.length && maskErrorArr[widgetId].length){ 857 858 var $subBtnTag = $submitBtn.find("button"); 859 860 861 // getting submit button recaptcha and click events 862 863 var $form = $submitBtn.closest("form"); 864 865 const origninalclick = jQuery._data($subBtnTag[0], "events"); 866 867 868 if(!recaptchaEvent[widgetId]){ 869 870 recaptchaEvent[widgetId] = origninalclick && origninalclick.click ? origninalclick.click.map(h => h.handler) : []; 871 } 872 873 874 875 876 // getting form apply step events 877 878 const origninalSubmit = jQuery._data($form[0], "events"); 879 880 origninalSubmit.submit.forEach((ele) => { 881 if(ele.handler.toString().trim().includes("resetForm")){ 882 883 if(!submitBtnEvent[widgetId]){ 884 885 submitBtnEvent[widgetId] = ele.handler; 886 887 } 888 889 } 890 }) 891 892 893 894 // removing form apply step event 895 $form.off("submit", submitBtnEvent[widgetId]); 896 897 // removing submit button click events 898 $subBtnTag.off("click"); 899 900 901 } 902 }) 903 904 // end - step field mask error handling 905 906 907 // handling form submit of mask field in elementor form 908 909 $(document).on("click", ".elementor-field-type-submit", function (e) { 910 911 var $submitBtn = $(this); 912 913 var $subBtnTag = $submitBtn.find("button"); 914 915 916 if ($submitBtn.find('button').hasClass('cfkef-prevent-submit') || $submitBtn.find('button').hasClass('confirmation-pending') 917 ) { 918 return 919 } 920 921 var $submitBtn = $(this); 922 var $form = $submitBtn.closest("form"); 923 924 925 // Prevent double-clicks 926 if ($submitBtn.data("clicked")) { 927 e.preventDefault(); 928 return; 929 } 930 $submitBtn.data("clicked", true); // Mark as clicked 931 932 // Trigger blur on inputs to ensure validation runs 933 $form.find("input").trigger("blur"); 934 935 // Add Elementor waiting class 936 $form[0].classList.add("elementor-form-waiting"); 937 938 // e.preventDefault(); // Prevent default form submission 939 940 // Wait for mask errors or blur logic to complete 941 setTimeout(() => { 942 943 944 let hasVisibleMaskError = false; 945 946 // Check for visible mask error messages 947 const $errors = $form.find(".mask-error").filter(function () { 948 return $(this).text().trim() !== "" && $(this).css("display") == "flex"; 949 }); 950 951 if ($errors.length > 0) { 952 hasVisibleMaskError = true; 953 const $firstError = $errors.first(); 954 $("html, body").animate({ 955 scrollTop: $firstError.offset().top - 200 956 }, 300); 957 } 958 959 // ✅ Check for empty required masked fields 960 const $emptyRequiredMasked = $form.find("input[required]").filter(function () { 961 const val = $(this).val().trim(); 962 const isVisible = $(this).css("display") == "flex"; 963 return (val === "" || /^[\s_\-\(\)\.:/]+$/.test(val)); 964 }); 965 966 967 if ($emptyRequiredMasked.length > 0) { 968 hasVisibleMaskError = true; 969 const $firstEmpty = $emptyRequiredMasked.first(); 970 $("html, body").animate({ 971 scrollTop: $firstEmpty.offset().top - 200 972 }, 300); 973 $firstEmpty.focus(); 974 } 975 976 // ❌ Validation failed 977 if (hasVisibleMaskError) { 978 // $form[0].classList.remove("elementor-form-waiting"); 979 $submitBtn.data("clicked", false); 594 980 e.preventDefault(); 595 return; 596 } 597 $submitBtn.data("clicked", true); // Mark as clicked 598 599 // Trigger blur on inputs to ensure validation runs 600 $form.find("input").trigger("blur"); 601 602 // Add Elementor waiting class 603 $form[0].classList.add("elementor-form-waiting"); 604 605 // Wait for mask errors or blur logic to complete 606 setTimeout(() => { 607 608 609 610 let hasVisibleMaskError = false; 611 612 // Check for visible mask error messages 613 const $errors = $form.find(".mask-error").filter(function () { 614 return $(this).text().trim() !== "" && $(this).is(":visible"); 615 }); 616 617 if ($errors.length > 0) { 618 hasVisibleMaskError = true; 619 const $firstError = $errors.first(); 620 $("html, body").animate({ 621 scrollTop: $firstError.offset().top - 200 622 }, 300); 623 } 624 625 // ✅ Check for empty required masked fields 626 const $emptyRequiredMasked = $form.find("input[required]").filter(function () { 627 const val = $(this).val().trim(); 628 const isVisible = $(this).is(":visible"); 629 return isVisible && (val === "" || /^[\s_\-\(\)\.:/]+$/.test(val)); 630 }); 631 632 633 if ($emptyRequiredMasked.length > 0) { 634 hasVisibleMaskError = true; 635 const $firstEmpty = $emptyRequiredMasked.first(); 636 $("html, body").animate({ 637 scrollTop: $firstEmpty.offset().top - 200 638 }, 300); 639 $firstEmpty.focus(); 640 } 641 642 // ❌ Validation failed 643 if (hasVisibleMaskError || !$form[0].checkValidity()) { 644 // $form[0].classList.remove("elementor-form-waiting"); 645 $submitBtn.data("clicked", false); 646 e.preventDefault(); 647 return; 648 } 649 650 651 if(!hasVisibleMaskError && !(!$form[0].checkValidity())){ 652 653 // ✅ All good — submit the form 654 $form[0].classList.remove("elementor-form-waiting"); 655 $form[0].requestSubmit(); 656 $submitBtn.data("clicked", false); 657 $submitBtn.trigger("submit"); 658 } 659 660 }, 500); 661 }); 981 return; 982 } 983 984 if (!hasVisibleMaskError) { 985 // ✅ All good — submit the form 986 $form[0].classList.remove("elementor-form-waiting"); 987 $submitBtn.data("clicked", false); 988 $submitBtn.trigger("submit"); 989 } 990 991 }, 500); 992 }); 993 662 994 663 995 }); -
mask-form-elementor/tags/4.2.3/includes/class-elementor-mask-control.php
r3255318 r3359056 348 348 } 349 349 } 350 351 if ( !is_plugin_active( 'country-code-field-for-elementor-form/country-code-field-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form/class-conditional-fields-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form-pro/class-conditional-fields-for-elementor-form-pro.php' )) {352 $controls_to_register['fme_country_code_toggle'] = array(353 'name' => 'fme_country_code_toggle',354 'label' => esc_html__( 'Enable Country Code', 'mask-form-elementor' ),355 'type' => Controls_Manager::SWITCHER,356 'tab' => 'content',357 'condition' => array(358 'field_type' => 'tel',359 ),360 'inner_tab' => 'form_fields_content_tab',361 'tabs_wrapper' => 'form_fields_tabs',362 );363 364 $controls_to_register['fme_country_code_link_button'] = array(365 'name' => 'fme_country_code_link_button',366 'type' => Controls_Manager::RAW_HTML,367 'raw' => "<p>To Add country code to Elementor form fields <a href='plugin-install.php?s=Country%2520Code%2520For%2520Elementor%2520Form%2520Telephone%2520Field%2520by%2520coolplugins&tab=search&type=term' target='_blank' >Activate Plugin</a></p>",368 'content_classes' => 'get_ccfef_link',369 'condition' => array(370 'fme_country_code_toggle' => 'yes',371 'field_type' => 'tel'372 ),373 'inner_tab' => 'form_fields_content_tab',374 'tabs_wrapper' => 'form_fields_tabs',375 );376 }377 350 378 351 if ( !is_plugin_active( 'country-code-field-for-elementor-form/country-code-field-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form/class-conditional-fields-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form-pro/class-conditional-fields-for-elementor-form-pro.php' ) ) { -
mask-form-elementor/tags/4.2.3/includes/class-main-mask-form-elementor.php
r3347851 r3359056 50 50 51 51 52 add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_pro_plugin_demo_link' ) ); 52 53 54 add_filter( 'plugin_row_meta', array( $this, 'mfe_plugin_row_meta' ), 10, 2 ); 55 56 add_action( 'plugins_loaded',array($this,'plugin_loads')); 57 58 59 $this->includes(); 60 61 62 } 63 } 64 65 public function plugin_loads(){ 66 67 68 add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_pro_plugin_demo_link' ) ); 53 69 54 70 add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_plugin_settings_link' ) ); 55 71 56 add_filter( 'plugin_row_meta', array( $this, 'mfe_plugin_row_meta' ), 10, 2 );57 58 add_action( 'plugins_loaded',array($this,'plugin_loads'));59 60 61 $this->includes();62 63 64 }65 }66 67 public function plugin_loads(){68 72 69 73 if(!class_exists('CPFM_Feedback_Notice')){ 70 74 require_once MFE_PLUGIN_PATH . 'admin/feedback/cpfm-common-notice.php'; 75 } 76 77 if ( did_action( 'elementor/loaded' ) && class_exists( '\Elementor\Plugin' ) ) { 78 79 require_once MFE_PLUGIN_PATH . '/admin/marketing/mfe-marketing-common.php'; 71 80 } 72 81 … … 332 341 } 333 342 334 //if ( is_plugin_active( 'cool-formkit-for-elementor-forms/cool-formkit-for-elementor-forms.php' ) ) {335 //return false;336 //}337 338 //if ( ! is_plugin_active( 'elementor-pro/elementor-pro.php' ) ) {339 //add_action('admin_notices', array($this, 'admin_notice_missing_main_plugin'));340 //return false;341 //}343 if ( is_plugin_active( 'cool-formkit-for-elementor-forms/cool-formkit-for-elementor-forms.php' ) ) { 344 return false; 345 } 346 347 if ( ! is_plugin_active( 'elementor-pro/elementor-pro.php' ) ) { 348 add_action('admin_notices', array($this, 'admin_notice_missing_main_plugin')); 349 return false; 350 } 342 351 343 352 return true; -
mask-form-elementor/tags/4.2.3/index.php
r3347851 r3359056 6 6 * Author: Rodrigo Bogdanowicz 7 7 * Author URI: https://www.bogdanowicz.com.br 8 * Version: 4.2. 28 * Version: 4.2.3 9 9 * Text Domain: mask-form-elementor 10 * Elementor tested up to: 3.31. 211 * Elementor Pro tested up to: 3.31. 210 * Elementor tested up to: 3.31.4 11 * Elementor Pro tested up to: 3.31.3 12 12 */ 13 13 … … 15 15 16 16 // Define plugin version and paths. 17 define( 'MFE_VERSION', '4.2. 2' );17 define( 'MFE_VERSION', '4.2.3' ); 18 18 define('MFE_PHP_MINIMUM_VERSION','7.4'); 19 19 define('MFE_WP_MINIMUM_VERSION','5.5'); -
mask-form-elementor/tags/4.2.3/readme.txt
r3352589 r3359056 6 6 Tested up to: 6.8.2 7 7 Requires PHP: 7.2 8 Stable tag: 4.2. 28 Stable tag: 4.2.3 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html 11 Elementor tested up to: 3.31. 212 Elementor Pro tested up to: 3.31. 211 Elementor tested up to: 3.31.4 12 Elementor Pro tested up to: 3.31.3 13 13 14 14 Apply input masks in Elementor form widget fields - phone, date, time, credit card, CPF, CNPJ, CEP & more for valid and error-free entries. … … 152 152 - [Live Demo](https://coolplugins.net/add-input-masks-elementor-form/?ref=mask&utm_source=mfe_plugin&utm_medium=readme&utm_campaign=demo&utm_content=installation) 153 153 154 ---155 156 154 == Changelog == 155 156 = 4.2.3 - Sep 10, 2025 = 157 - Added: - Added other plugin recommendations for Elementor users. 158 - Fixed: - Mask validation issue with step field form. 159 - Fixed: - Conflict between mask validation and reCaptcha v3. 157 160 158 161 = 4.2.2 - Aug 21, 2025 = -
mask-form-elementor/trunk/assets/js/custom-mask-script.js
r3347851 r3359056 56 56 let moneymaskFormat = input.dataset.moneymaskFormat 57 57 let type = (moneymaskFormat === 'dot' ? 'D' : 'C') 58 let newValue = formatMoneyInput(input.value, type,moneyPrefix,input); 58 let newValue = ''; 59 60 if(input.value != '$0,00'){ 61 62 newValue = formatMoneyInput(input.value, type, moneyPrefix, input); 63 }else{ 64 newValue = ""; 65 } 66 59 67 if (input.value === newValue) return; 60 68 … … 211 219 var newCaret = mapDigitIndexToCaret(newVal, digitIndex); 212 220 213 input.value = newVal; 221 if(newVal != '('){ 222 223 input.value = newVal; 224 }else{ 225 input.value = ""; 226 } 214 227 215 228 setCaretPosition(input, newCaret || 0); // Keep caret in place … … 333 346 $(document).on("input", selector, function () { 334 347 var input = $(this); 348 nextbtnVisibility(errorClass, input, validationFunction); 335 349 var errorElement = input.closest('.elementor-field-group').find("." + errorClass); 336 350 … … 584 598 585 599 // ----------------- Form Submit ----------------- 600 601 602 // start - step field mask error handling 603 604 let maskErrorArr = {}; 605 let nextBtnOriginalClicks = {}; 606 let clickStatus={}; 607 let recaptchaEvent = {}; 608 let submitBtnEvent = {}; 609 610 611 const nextbtnVisibility = (errorClass, input, validationFunction) => { 612 613 const closesWidget = input.closest(".elementor-widget-form"); 614 const widgetId = closesWidget.data('id'); 615 const inuptId = input.attr('id'); 616 const fieldStep=input.closest(".elementor-field-type-step"); 617 const form = input.closest(".elementor-form"); 618 619 const currectStepFields = form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)").find('input, textarea, select'); 620 621 const submtBtnTag = form.find("button[type='submit']"); 622 623 if (!closesWidget.length || !fieldStep.length) { 624 return; 625 } 626 627 const nextBtn = fieldStep.find(".e-form__buttons__wrapper__button[data-direction='next']"); 628 629 630 631 if ((nextBtn.length == 0 && submtBtnTag.length > 0 ) && (submtBtnTag.length == 0 && nextBtn.length == 0) ) { 632 return; 633 } 634 635 636 637 let val = input.val(); 638 639 if (val.length === 1 && !/\d/.test(val)) { 640 val = ''; 641 } 642 643 // Show error message if validation fails 644 if ( val !== "" && !validationFunction(val)) { 645 646 647 if (closesWidget.length > 0) { 648 649 650 if (!maskErrorArr[widgetId]) { 651 maskErrorArr[widgetId] = []; 652 } 653 654 if (!maskErrorArr[widgetId].includes(inuptId)) { 655 maskErrorArr[widgetId].push(inuptId); 656 } 657 } 658 659 if (!nextBtnOriginalClicks[widgetId] || !nextBtnOriginalClicks[widgetId].length) { 660 661 662 663 if(nextBtn.length > 0){ 664 665 const origninalClicks = jQuery._data(nextBtn[0], "events"); 666 667 if (origninalClicks && (!nextBtnOriginalClicks[widgetId] || !nextBtnOriginalClicks[widgetId].length === 0)) { 668 nextBtnOriginalClicks[widgetId] = origninalClicks && origninalClicks.click ? origninalClicks.click.map(h => h.handler) : []; 669 670 } 671 } 672 673 674 } 675 } else { 676 if (maskErrorArr[widgetId] && maskErrorArr[widgetId].includes(inuptId)) { 677 maskErrorArr[widgetId] = maskErrorArr[widgetId].filter(item => item !== inuptId); 678 } 679 } 680 681 682 if (maskErrorArr[widgetId] && maskErrorArr[widgetId].length > 0) { 683 684 if(nextBtn.length > 0){ 685 686 const origninalClicks = jQuery._data(nextBtn[0], "events"); 687 688 if (origninalClicks && (!nextBtnOriginalClicks[widgetId] || !nextBtnOriginalClicks[widgetId].length)) { 689 690 691 nextBtnOriginalClicks[widgetId] = origninalClicks && origninalClicks.click ? origninalClicks.click.map(h => h.handler) : []; 692 693 } 586 694 587 588 $(document).on("click", ".elementor-field-type-submit", function (e) { 589 var $submitBtn = $(this); 590 var $form = $submitBtn.closest("form"); 591 592 // Prevent double-clicks 593 if ($submitBtn.data("clicked")) { 695 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 696 nextBtn.off("click"); 697 } 698 699 700 } 701 702 703 704 } else { 705 706 707 // when no error in mask validation 708 709 if(recaptchaEvent[widgetId]){ 710 711 recaptchaEvent[widgetId].forEach(fn => { 712 submtBtnTag.one("click", fn); // use .one instead of .on 713 }); 714 } 715 716 if(submitBtnEvent[widgetId]){ 717 form.on("submit", submitBtnEvent[widgetId]); 718 } 719 720 721 722 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 723 724 725 726 727 let isfieldsValid = true 728 729 for (let i = 0; i < currectStepFields.length; i++) { 730 731 732 if (currectStepFields[i].checkValidity() == false) { 733 734 isfieldsValid = false; 735 break; 736 737 } 738 739 } 740 741 if (isfieldsValid) { 742 743 744 745 746 747 if(nextBtn.length > 0){ 748 749 // 2️⃣ First, clear existing handlers to avoid duplication 750 nextBtn.off("click"); 751 752 // Re-attach original click handlers only once 753 nextBtnOriginalClicks[widgetId].forEach(fn => { 754 nextBtn.one("click", fn); // use .one instead of .on 755 }); 756 } 757 758 759 } 760 761 } 762 763 } 764 } 765 766 767 768 769 // handle next button event before click 770 771 $(document).on("mousedown", ".e-form__buttons__wrapper__button[data-direction='next']", function(e){ 772 773 const form = $(this).closest(".elementor-form"); 774 775 const mask_error_div = form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)").find('div.mask-error'); 776 777 const closesWidget = $(this).closest(".elementor-widget-form"); 778 const widgetId = closesWidget.data('id'); 779 780 let mask_error = false; 781 782 // finding mask error 783 for(let i=0; i<mask_error_div.length; i++){ 784 if(mask_error_div[i].value != "" && mask_error_div[i].style.display == 'flex'){ 785 mask_error = true; 786 break; 787 } 788 } 789 790 // reattcach next button event when no mask error 791 792 if (maskErrorArr[widgetId] && !maskErrorArr[widgetId].length > 0 && !mask_error) { 793 // Re-attach original click handlers only once 794 795 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 796 $(this).off("click"); 797 798 nextBtnOriginalClicks[widgetId].forEach(fn => { 799 $(this).one("click", fn); // use .one instead of .on 800 }); 801 } 802 803 804 } 805 806 }) 807 808 809 // handling next button event when previous button click 810 811 $(document).on("click", ".e-form__buttons__wrapper__button[data-direction='previous']", function(e){ 812 813 const form = $(this).closest(".elementor-form"); 814 815 const closesWidget = form.closest(".elementor-widget-form"); 816 const widgetId = closesWidget.data('id'); 817 maskErrorArr[widgetId] = []; 818 819 const currectStepFields = form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)") 820 821 const nextBtn = currectStepFields.find(".e-form__buttons__wrapper__button[data-direction='next']"); 822 823 // attaching events to next button 824 825 if (nextBtnOriginalClicks[widgetId] && nextBtnOriginalClicks[widgetId].length > 0) { 826 nextBtn.off("click"); 827 828 nextBtnOriginalClicks[widgetId].forEach(fn => { 829 nextBtn.one("click", fn); // use .one instead of .on 830 }); 831 832 } 833 834 }) 835 836 // handle mask validation on submit button of step field form 837 $(document).on("mousedown", ".elementor-field-type-submit", function (e){ 838 839 var $submitBtn = $(this); 840 841 var $form = $submitBtn.closest("form"); 842 843 const closesWidget = $form.closest(".elementor-widget-form"); 844 const widgetId = closesWidget.data('id'); 845 846 const currectStepFields = $form.find(".elementor-form-fields-wrapper.elementor-labels-above").children("div:not(.elementor-hidden)") 847 848 const previousBtn = currectStepFields.find(".e-form__buttons__wrapper__button[data-direction='previous']"); 849 850 const inputMaskFields = currectStepFields.find("input.fme-mask-input"); 851 852 // run only first time when click on submit button 853 // if maskerror found in the form widget this will remove submit button and form events to prevent submit 854 855 856 if(previousBtn.length && inputMaskFields.length && maskErrorArr[widgetId].length){ 857 858 var $subBtnTag = $submitBtn.find("button"); 859 860 861 // getting submit button recaptcha and click events 862 863 var $form = $submitBtn.closest("form"); 864 865 const origninalclick = jQuery._data($subBtnTag[0], "events"); 866 867 868 if(!recaptchaEvent[widgetId]){ 869 870 recaptchaEvent[widgetId] = origninalclick && origninalclick.click ? origninalclick.click.map(h => h.handler) : []; 871 } 872 873 874 875 876 // getting form apply step events 877 878 const origninalSubmit = jQuery._data($form[0], "events"); 879 880 origninalSubmit.submit.forEach((ele) => { 881 if(ele.handler.toString().trim().includes("resetForm")){ 882 883 if(!submitBtnEvent[widgetId]){ 884 885 submitBtnEvent[widgetId] = ele.handler; 886 887 } 888 889 } 890 }) 891 892 893 894 // removing form apply step event 895 $form.off("submit", submitBtnEvent[widgetId]); 896 897 // removing submit button click events 898 $subBtnTag.off("click"); 899 900 901 } 902 }) 903 904 // end - step field mask error handling 905 906 907 // handling form submit of mask field in elementor form 908 909 $(document).on("click", ".elementor-field-type-submit", function (e) { 910 911 var $submitBtn = $(this); 912 913 var $subBtnTag = $submitBtn.find("button"); 914 915 916 if ($submitBtn.find('button').hasClass('cfkef-prevent-submit') || $submitBtn.find('button').hasClass('confirmation-pending') 917 ) { 918 return 919 } 920 921 var $submitBtn = $(this); 922 var $form = $submitBtn.closest("form"); 923 924 925 // Prevent double-clicks 926 if ($submitBtn.data("clicked")) { 927 e.preventDefault(); 928 return; 929 } 930 $submitBtn.data("clicked", true); // Mark as clicked 931 932 // Trigger blur on inputs to ensure validation runs 933 $form.find("input").trigger("blur"); 934 935 // Add Elementor waiting class 936 $form[0].classList.add("elementor-form-waiting"); 937 938 // e.preventDefault(); // Prevent default form submission 939 940 // Wait for mask errors or blur logic to complete 941 setTimeout(() => { 942 943 944 let hasVisibleMaskError = false; 945 946 // Check for visible mask error messages 947 const $errors = $form.find(".mask-error").filter(function () { 948 return $(this).text().trim() !== "" && $(this).css("display") == "flex"; 949 }); 950 951 if ($errors.length > 0) { 952 hasVisibleMaskError = true; 953 const $firstError = $errors.first(); 954 $("html, body").animate({ 955 scrollTop: $firstError.offset().top - 200 956 }, 300); 957 } 958 959 // ✅ Check for empty required masked fields 960 const $emptyRequiredMasked = $form.find("input[required]").filter(function () { 961 const val = $(this).val().trim(); 962 const isVisible = $(this).css("display") == "flex"; 963 return (val === "" || /^[\s_\-\(\)\.:/]+$/.test(val)); 964 }); 965 966 967 if ($emptyRequiredMasked.length > 0) { 968 hasVisibleMaskError = true; 969 const $firstEmpty = $emptyRequiredMasked.first(); 970 $("html, body").animate({ 971 scrollTop: $firstEmpty.offset().top - 200 972 }, 300); 973 $firstEmpty.focus(); 974 } 975 976 // ❌ Validation failed 977 if (hasVisibleMaskError) { 978 // $form[0].classList.remove("elementor-form-waiting"); 979 $submitBtn.data("clicked", false); 594 980 e.preventDefault(); 595 return; 596 } 597 $submitBtn.data("clicked", true); // Mark as clicked 598 599 // Trigger blur on inputs to ensure validation runs 600 $form.find("input").trigger("blur"); 601 602 // Add Elementor waiting class 603 $form[0].classList.add("elementor-form-waiting"); 604 605 // Wait for mask errors or blur logic to complete 606 setTimeout(() => { 607 608 609 610 let hasVisibleMaskError = false; 611 612 // Check for visible mask error messages 613 const $errors = $form.find(".mask-error").filter(function () { 614 return $(this).text().trim() !== "" && $(this).is(":visible"); 615 }); 616 617 if ($errors.length > 0) { 618 hasVisibleMaskError = true; 619 const $firstError = $errors.first(); 620 $("html, body").animate({ 621 scrollTop: $firstError.offset().top - 200 622 }, 300); 623 } 624 625 // ✅ Check for empty required masked fields 626 const $emptyRequiredMasked = $form.find("input[required]").filter(function () { 627 const val = $(this).val().trim(); 628 const isVisible = $(this).is(":visible"); 629 return isVisible && (val === "" || /^[\s_\-\(\)\.:/]+$/.test(val)); 630 }); 631 632 633 if ($emptyRequiredMasked.length > 0) { 634 hasVisibleMaskError = true; 635 const $firstEmpty = $emptyRequiredMasked.first(); 636 $("html, body").animate({ 637 scrollTop: $firstEmpty.offset().top - 200 638 }, 300); 639 $firstEmpty.focus(); 640 } 641 642 // ❌ Validation failed 643 if (hasVisibleMaskError || !$form[0].checkValidity()) { 644 // $form[0].classList.remove("elementor-form-waiting"); 645 $submitBtn.data("clicked", false); 646 e.preventDefault(); 647 return; 648 } 649 650 651 if(!hasVisibleMaskError && !(!$form[0].checkValidity())){ 652 653 // ✅ All good — submit the form 654 $form[0].classList.remove("elementor-form-waiting"); 655 $form[0].requestSubmit(); 656 $submitBtn.data("clicked", false); 657 $submitBtn.trigger("submit"); 658 } 659 660 }, 500); 661 }); 981 return; 982 } 983 984 if (!hasVisibleMaskError) { 985 // ✅ All good — submit the form 986 $form[0].classList.remove("elementor-form-waiting"); 987 $submitBtn.data("clicked", false); 988 $submitBtn.trigger("submit"); 989 } 990 991 }, 500); 992 }); 993 662 994 663 995 }); -
mask-form-elementor/trunk/includes/class-elementor-mask-control.php
r3255318 r3359056 348 348 } 349 349 } 350 351 if ( !is_plugin_active( 'country-code-field-for-elementor-form/country-code-field-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form/class-conditional-fields-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form-pro/class-conditional-fields-for-elementor-form-pro.php' )) {352 $controls_to_register['fme_country_code_toggle'] = array(353 'name' => 'fme_country_code_toggle',354 'label' => esc_html__( 'Enable Country Code', 'mask-form-elementor' ),355 'type' => Controls_Manager::SWITCHER,356 'tab' => 'content',357 'condition' => array(358 'field_type' => 'tel',359 ),360 'inner_tab' => 'form_fields_content_tab',361 'tabs_wrapper' => 'form_fields_tabs',362 );363 364 $controls_to_register['fme_country_code_link_button'] = array(365 'name' => 'fme_country_code_link_button',366 'type' => Controls_Manager::RAW_HTML,367 'raw' => "<p>To Add country code to Elementor form fields <a href='plugin-install.php?s=Country%2520Code%2520For%2520Elementor%2520Form%2520Telephone%2520Field%2520by%2520coolplugins&tab=search&type=term' target='_blank' >Activate Plugin</a></p>",368 'content_classes' => 'get_ccfef_link',369 'condition' => array(370 'fme_country_code_toggle' => 'yes',371 'field_type' => 'tel'372 ),373 'inner_tab' => 'form_fields_content_tab',374 'tabs_wrapper' => 'form_fields_tabs',375 );376 }377 350 378 351 if ( !is_plugin_active( 'country-code-field-for-elementor-form/country-code-field-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form/class-conditional-fields-for-elementor-form.php' ) && !is_plugin_active( 'conditional-fields-for-elementor-form-pro/class-conditional-fields-for-elementor-form-pro.php' ) ) { -
mask-form-elementor/trunk/includes/class-main-mask-form-elementor.php
r3347851 r3359056 50 50 51 51 52 add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_pro_plugin_demo_link' ) ); 52 53 54 add_filter( 'plugin_row_meta', array( $this, 'mfe_plugin_row_meta' ), 10, 2 ); 55 56 add_action( 'plugins_loaded',array($this,'plugin_loads')); 57 58 59 $this->includes(); 60 61 62 } 63 } 64 65 public function plugin_loads(){ 66 67 68 add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_pro_plugin_demo_link' ) ); 53 69 54 70 add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_plugin_settings_link' ) ); 55 71 56 add_filter( 'plugin_row_meta', array( $this, 'mfe_plugin_row_meta' ), 10, 2 );57 58 add_action( 'plugins_loaded',array($this,'plugin_loads'));59 60 61 $this->includes();62 63 64 }65 }66 67 public function plugin_loads(){68 72 69 73 if(!class_exists('CPFM_Feedback_Notice')){ 70 74 require_once MFE_PLUGIN_PATH . 'admin/feedback/cpfm-common-notice.php'; 75 } 76 77 if ( did_action( 'elementor/loaded' ) && class_exists( '\Elementor\Plugin' ) ) { 78 79 require_once MFE_PLUGIN_PATH . '/admin/marketing/mfe-marketing-common.php'; 71 80 } 72 81 … … 332 341 } 333 342 334 //if ( is_plugin_active( 'cool-formkit-for-elementor-forms/cool-formkit-for-elementor-forms.php' ) ) {335 //return false;336 //}337 338 //if ( ! is_plugin_active( 'elementor-pro/elementor-pro.php' ) ) {339 //add_action('admin_notices', array($this, 'admin_notice_missing_main_plugin'));340 //return false;341 //}343 if ( is_plugin_active( 'cool-formkit-for-elementor-forms/cool-formkit-for-elementor-forms.php' ) ) { 344 return false; 345 } 346 347 if ( ! is_plugin_active( 'elementor-pro/elementor-pro.php' ) ) { 348 add_action('admin_notices', array($this, 'admin_notice_missing_main_plugin')); 349 return false; 350 } 342 351 343 352 return true; -
mask-form-elementor/trunk/index.php
r3347851 r3359056 6 6 * Author: Rodrigo Bogdanowicz 7 7 * Author URI: https://www.bogdanowicz.com.br 8 * Version: 4.2. 28 * Version: 4.2.3 9 9 * Text Domain: mask-form-elementor 10 * Elementor tested up to: 3.31. 211 * Elementor Pro tested up to: 3.31. 210 * Elementor tested up to: 3.31.4 11 * Elementor Pro tested up to: 3.31.3 12 12 */ 13 13 … … 15 15 16 16 // Define plugin version and paths. 17 define( 'MFE_VERSION', '4.2. 2' );17 define( 'MFE_VERSION', '4.2.3' ); 18 18 define('MFE_PHP_MINIMUM_VERSION','7.4'); 19 19 define('MFE_WP_MINIMUM_VERSION','5.5'); -
mask-form-elementor/trunk/readme.txt
r3352589 r3359056 6 6 Tested up to: 6.8.2 7 7 Requires PHP: 7.2 8 Stable tag: 4.2. 28 Stable tag: 4.2.3 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html 11 Elementor tested up to: 3.31. 212 Elementor Pro tested up to: 3.31. 211 Elementor tested up to: 3.31.4 12 Elementor Pro tested up to: 3.31.3 13 13 14 14 Apply input masks in Elementor form widget fields - phone, date, time, credit card, CPF, CNPJ, CEP & more for valid and error-free entries. … … 152 152 - [Live Demo](https://coolplugins.net/add-input-masks-elementor-form/?ref=mask&utm_source=mfe_plugin&utm_medium=readme&utm_campaign=demo&utm_content=installation) 153 153 154 ---155 156 154 == Changelog == 155 156 = 4.2.3 - Sep 10, 2025 = 157 - Added: - Added other plugin recommendations for Elementor users. 158 - Fixed: - Mask validation issue with step field form. 159 - Fixed: - Conflict between mask validation and reCaptcha v3. 157 160 158 161 = 4.2.2 - Aug 21, 2025 =
Note: See TracChangeset
for help on using the changeset viewer.