Plugin Directory

Changeset 3359056


Ignore:
Timestamp:
09/10/2025 09:32:02 AM (7 months ago)
Author:
satindersingh
Message:

Update to version 4.2.3 from GitHub

Location:
mask-form-elementor
Files:
16 added
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • mask-form-elementor/tags/4.2.3/assets/js/custom-mask-script.js

    r3347851 r3359056  
    5656          let moneymaskFormat = input.dataset.moneymaskFormat
    5757          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         
    5967          if (input.value === newValue) return;
    6068     
     
    211219              var newCaret = mapDigitIndexToCaret(newVal, digitIndex);
    212220     
    213               input.value = newVal;
     221              if(newVal != '('){
     222
     223                input.value = newVal;
     224              }else{
     225                input.value = "";
     226              }
    214227             
    215228              setCaretPosition(input, newCaret || 0); // Keep caret in place
     
    333346          $(document).on("input", selector, function () {
    334347              var input = $(this);
     348              nextbtnVisibility(errorClass, input, validationFunction);
    335349              var errorElement = input.closest('.elementor-field-group').find("." + errorClass);
    336350     
     
    584598     
    585599        // ----------------- 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        }
    586694       
    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);
    594980          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
    662994     
    663995    });
  • mask-form-elementor/tags/4.2.3/includes/class-elementor-mask-control.php

    r3255318 r3359056  
    348348            }
    349349        }       
    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         }
    377350
    378351        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  
    5050
    5151           
    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' ) );
    5369
    5470            add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_plugin_settings_link' ) );
    5571
    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(){
    6872
    6973        if(!class_exists('CPFM_Feedback_Notice')){
    7074            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';
    7180        }
    7281
     
    332341        }
    333342
    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        }
    342351
    343352        return true;
  • mask-form-elementor/tags/4.2.3/index.php

    r3347851 r3359056  
    66 * Author: Rodrigo Bogdanowicz
    77 * Author URI: https://www.bogdanowicz.com.br
    8  * Version: 4.2.2
     8 * Version: 4.2.3
    99 * Text Domain: mask-form-elementor
    10  * Elementor tested up to: 3.31.2
    11  * Elementor Pro tested up to: 3.31.2
     10 * Elementor tested up to: 3.31.4
     11 * Elementor Pro tested up to: 3.31.3
    1212 */
    1313
     
    1515
    1616// Define plugin version and paths.
    17 define( 'MFE_VERSION', '4.2.2' );
     17define( 'MFE_VERSION', '4.2.3' );
    1818define('MFE_PHP_MINIMUM_VERSION','7.4');
    1919define('MFE_WP_MINIMUM_VERSION','5.5');
  • mask-form-elementor/tags/4.2.3/readme.txt

    r3352589 r3359056  
    66Tested up to: 6.8.2
    77Requires PHP: 7.2
    8 Stable tag: 4.2.2
     8Stable tag: 4.2.3
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    11 Elementor tested up to: 3.31.2
    12 Elementor Pro tested up to: 3.31.2
     11Elementor tested up to: 3.31.4
     12Elementor Pro tested up to: 3.31.3
    1313
    1414Apply input masks in Elementor form widget fields - phone, date, time, credit card, CPF, CNPJ, CEP & more for valid and error-free entries.
     
    152152- [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) 
    153153
    154 ---
    155 
    156154== 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.
    157160
    158161= 4.2.2 - Aug 21, 2025 = 
  • mask-form-elementor/trunk/assets/js/custom-mask-script.js

    r3347851 r3359056  
    5656          let moneymaskFormat = input.dataset.moneymaskFormat
    5757          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         
    5967          if (input.value === newValue) return;
    6068     
     
    211219              var newCaret = mapDigitIndexToCaret(newVal, digitIndex);
    212220     
    213               input.value = newVal;
     221              if(newVal != '('){
     222
     223                input.value = newVal;
     224              }else{
     225                input.value = "";
     226              }
    214227             
    215228              setCaretPosition(input, newCaret || 0); // Keep caret in place
     
    333346          $(document).on("input", selector, function () {
    334347              var input = $(this);
     348              nextbtnVisibility(errorClass, input, validationFunction);
    335349              var errorElement = input.closest('.elementor-field-group').find("." + errorClass);
    336350     
     
    584598     
    585599        // ----------------- 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        }
    586694       
    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);
    594980          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
    662994     
    663995    });
  • mask-form-elementor/trunk/includes/class-elementor-mask-control.php

    r3255318 r3359056  
    348348            }
    349349        }       
    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         }
    377350
    378351        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  
    5050
    5151           
    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' ) );
    5369
    5470            add_filter( 'plugin_action_links_' . plugin_basename( MFE_PLUGIN_FILE ), array( $this, 'mfe_plugin_settings_link' ) );
    5571
    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(){
    6872
    6973        if(!class_exists('CPFM_Feedback_Notice')){
    7074            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';
    7180        }
    7281
     
    332341        }
    333342
    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        }
    342351
    343352        return true;
  • mask-form-elementor/trunk/index.php

    r3347851 r3359056  
    66 * Author: Rodrigo Bogdanowicz
    77 * Author URI: https://www.bogdanowicz.com.br
    8  * Version: 4.2.2
     8 * Version: 4.2.3
    99 * Text Domain: mask-form-elementor
    10  * Elementor tested up to: 3.31.2
    11  * Elementor Pro tested up to: 3.31.2
     10 * Elementor tested up to: 3.31.4
     11 * Elementor Pro tested up to: 3.31.3
    1212 */
    1313
     
    1515
    1616// Define plugin version and paths.
    17 define( 'MFE_VERSION', '4.2.2' );
     17define( 'MFE_VERSION', '4.2.3' );
    1818define('MFE_PHP_MINIMUM_VERSION','7.4');
    1919define('MFE_WP_MINIMUM_VERSION','5.5');
  • mask-form-elementor/trunk/readme.txt

    r3352589 r3359056  
    66Tested up to: 6.8.2
    77Requires PHP: 7.2
    8 Stable tag: 4.2.2
     8Stable tag: 4.2.3
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    11 Elementor tested up to: 3.31.2
    12 Elementor Pro tested up to: 3.31.2
     11Elementor tested up to: 3.31.4
     12Elementor Pro tested up to: 3.31.3
    1313
    1414Apply input masks in Elementor form widget fields - phone, date, time, credit card, CPF, CNPJ, CEP & more for valid and error-free entries.
     
    152152- [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) 
    153153
    154 ---
    155 
    156154== 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.
    157160
    158161= 4.2.2 - Aug 21, 2025 = 
Note: See TracChangeset for help on using the changeset viewer.