1

I'm working on a JForm with some fields with custom event handlers to do client side form validation as it is described in this document

The document says that "Joomla adds a blur handler to validate the form field when the user moves away from the field."

When I type something in the text field and press tab or click another field, my custom event handler is called and everything works fine. However when I enter the field and then leave the field without typing anything, or enter the field, type something, delete it and then leave the field: the event handler is not called at all, so I cannot display any warning for the user.

How could I make sure that my custom event handler is called even in these cases?

The sources: The form xml (not complete):

<form>
    <fields name="main">
        <fieldset name="basic" addfieldpath="/modules/mod_gngcontactmultiloc/models/fields">
            <field
                name="Email"
                type="text"
                label="MOD_GNGCONTACT_EMAIL"
                size="20"
                maxlenght="100"
                class="validate-myemail gngcontact"
            />

the template file (not complete):

    <?php 
    // No direct access
    defined('_JEXEC') or die;
    JHtml::_('behavior.formvalidator');
    JHtml::_('behavior.tooltip');
    ?>
    <script>

        jQuery(document).ready(function(){
           document.formvalidator.setHandler('myemail', function(value) {
              alert("hello");
              regex=/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
              var result = regex.test(value);
              if (result) {
                document.getElementById("msg-main[Email]").style.display = 'none';
              } 
              else 
              {
                document.getElementById("msg-main[Email]").style.display = 'block';
              };
              return result;
           });
        }); 

...

<form method="post" id="contactForm" name="contactForm" class="form-validate gngcontact">
... 

The alert in the above code is display if I leave the field after typing somthing, but not displayed in the scenarios described with bold above.

UPDATE: @Zollie 's final conclusion is right, using the "required" attribute the standard Joomla validation kicks in even in this special case and changes the field into red. Unfortunately this was not sufficient for me as I wanted to have a custom validation icon and message displayed by a custom event handler and it seems that the custom event handler is not called in this special case. Therefore I had to implement my client side validation from scratch not using the built in Joomla mechanism.

Thanks, W.

  • Are we still blurring on your question, or you got some focus now? – Zollie Jan 28 at 12:01
3

I deleted my earlier answer, since it was on some points true but not exactly answered the question. My mind was blurred by the question. :) The question is very tricky. Why?

Because in the question the linked Joomla document clearly states that in order to have the validation jQuery functions ignited on your Form, you have to add the form-validate class to your Form like:

<form class="form-validate"> ... </form>

Now, I do not see anything mentioned about this in the question. In the question you see a form Field but you do not see the whole Form itself. You see, it's tricky because this way 'you will never find out' what the real problem is and if the Form has the important class added or not finally. We now only know that the Blur event is not working on the Form field. And we concentrate on the field and on the script. But not on the From itself. Thus the blur effect starts to work on us.:)

It's true that something may happen on the field, some validation when you give the field validate-email class name for example, but according to the document you have to also give the class form-validate to the Form itself too.

And if the correct class is added to the Form then we could see if the script is wrong or not, or whether it is checking any field against emptiness. Since in the given script in the question, it does not look like that the function checks against empty Form fields anyway.

So the above might be the reason of not seeing the blur event happen on the Form.

And I just leave this short function below if anybody needs empty field checking on any Form field. :)

As an extra mile :) I wrote the blur ignited function in jQuery which could be also built in the original Joomla script above, but I just give it as standalone (I tested this too and it works on blur on input field if the field left empty)

.myformfieldclass should be changed to your input field class name.

<script>

    jQuery('.myformfieldclass').on("blur", function(){
        if(jQuery.trim($(this).val()) === ''){
            alert('Input field can not be left blank');
        }
    });

</script>

UPDATE - ON JOOMLA HANDLER AND BLUR FUNCTION

Now, we could just leave this subject for good, since I do not see any urgent reason to solve this question, which could be handled simply by few lines of code within minutes, but just for fun in coffee break, I checked the Form validation javascript of Joomla and I've found the valid script (thanks to @Lodder too for pointing to the file, I was lazy to search for that). This is a totally different script what was given in the question basically, so I still do not know where that script is coming from in the poster' question. This is how Joomla checks the validity of an email input field if validation is set:

// Default handlers
setHandler('email', function(value, element) {
            value = punycode.toASCII(value);
            var regex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
            return regex.test(value);
        });
        // Attach to forms with class 'form-validate'
        var forms = jQuery('form.form-validate');
        for (var i = 0, l = forms.length; i < l; i++) {
            attachToForm(forms[i]);
}

Now in the above script, you can see clearly two things. The function is attached to Forms which has the class form-validate. That is OK. You can also see that the default email field handler function does not check if the field is empty or not. I still do not see that in the above. Or can anybody confirm that this regex can filter an empty field? Not, but, before this check, there is an html5 validation too on the fields and after that the set Handler validates the field.

Now let's see where Joomla attaches the input fields to blur events:

In this function:

            // Attach validate method only to fields
            else if (tagName !== 'button' && !(tagName === 'input' && $el.attr('type') === 'button')) {
                if ($el.hasClass('required')) {
                    $el.attr('aria-required', 'true').attr('required', 'required');
                }
                if (tagName !== 'fieldset') {
                    $el.on('blur', function() {
                        return validate(this);
                    });
                    if ($el.hasClass('validate-email') && inputEmail) {
                        elements[i].setAttribute('type', 'email');
                    }
                }
                inputFields.push($el);
}

And if the input field class is set to validate:

// Only validate the field if the validate class is set
handler = ($el.attr('class') && $el.attr('class').match(/validate-([a-zA-Z0-9\_\-]+)/)) ? $el.attr('class').match(/validate-([a-zA-Z0-9\_\-]+)/)[1] : "";

From the above short two scripts you can also see quite clearly that all of the input fields which is set to required (and if validate is set in class name and not button and fieldset), so all of these input fields, are sent to validate on blur! Bound to the Blur event. So there is no question about whether blur ignites or not on these fields. These input fields are bound to blur event, no escape.

So, I still do not understand where the problem is coming from which is explained in the original question. However it can happen that I overlooked on something in this file. I did not have too much time.

But if anybody can find something interesting, please be my guest: :)

https://github.com/joomla/joomla-cms/blob/staging/media/system/js/validate-uncompressed.js

FINALLY

The only way I could have checked the whole thing is with creating an email field and check whether the Joomla blur kicks in or not if I click in the field and leave it empty then, without typing anything in the field. What I've found is that Joomla validation on blur only kicks in (if the field is left empty) when the field is set to required validate-email. So this is the only solution on this question. Joomla validation on blur kicks in on empty without problem if the field is required, but only then.

Here is my short recorded image on how it works:

enter image description here

You can see that on blur the validation kicks in on empty field, no exception (if the field is required). If the field is not set to required, on blur nothing happens on empty.

That's the final verdict on this subject. :) Joomla blur works.

  • Thanks for the quick response! However I'm not sure if this is completely true. If I click the field (my cursor blinks in the field) and leave it without typing anything or type something and then delete it before leaving the field, I would think that it gets the focus and looses it again when I click elsewhere. This is also how examples on blur work, e.g. this one: w3schools.com/jquery/… I don't see why this is different with a Joomla generated field. – wanderlusted Jan 27 at 14:21
  • @wanderlusted - since you did not copy here the function which should be ignited by blur, that was the only thing came to my mind. Until I do not see the script I cannot answer, only bet. – Zollie Jan 27 at 14:27
  • My more general problem is that I'd like to use this custom event hander to check any problems with the input, if it is correctly filled in, or empty, or anything else and then display a custom error message. Unfortunately I can't this now for the empty case as the handler is not called... – wanderlusted Jan 27 at 14:27
  • @wanderlusted - edit your question and add the event handler script to it. I’d like to see what that is exactly. – Zollie Jan 27 at 14:31
  • 1
    @Zollie, I truly appreciate the amount of time you put into this investigation. I agree that final conclusion is right, using the "required" attribute the standard Joomla validation kicks even in this special case and changes the field into red. Unfortunately this was not sufficient for me as I wanted to have a custom validation icon and message displayed by a custom event handler and the custom event handler is not called in this special case. Therefore I had to implement my client side validation from scratch not using the built in Joomla mechanism. Kudos for the results! – wanderlusted Jan 29 at 20:01
1

Would you not have joy with adding required as an additional class on the field? On the https://docs.joomla.org/Special:MyLanguage/Client-side_form_validation doc page, <field name="email" type="text" class="required validate-email" size="30" /> suggests that you could just add required to the end of class="validate-myemail gngcontact".

As for your javascript, I just have a couple of notes to follow my snippet:

<script>
  jQuery(document).ready(function() {
    document.formvalidator.setHandler('myemail', function(value) {
      alert("Validating value: " + value);
      let regex=/^(?:"[^"]+"|[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)@(?:\[\d{1,3}(?:\.\d{1,3}){3}]|(?:[a-z\d-]+\.)+[a-z]{2,})$/i;
      let result = regex.test(value);
      if (result) {
          JQuery("input[name='email']").hide();
      } else {
          JQuery("input[name='email']").show();
      }
      return result;
    });
  });
</script>
  • You had a few extra capture groups that were not necessary to maintain the regex pattern logic -- so I removed them
  • I converted capturing groups to non-capturing groups to convey that there is no intention of returning any of the substrings in the output. This is more of a matter of personal preference; it doesn't improve efficiency and it actually makes the pattern longer by adding ?: after each ( -- so you can ignore this adjustment if you wish
  • Opening square braces inside of a character class do not need to be escaped. Hyphens don't need to be escaped if they are the first or last character in the declaration or if they follow a "range of characters"
  • \d is the same as 0-9
  • You can use [a-z] to cover all alphabetical characters if you append the i modifier to the end of your pattern
  • Probably the best piece of advice is for you to use a negated character class with " and a greedy quantifier to enable best efficiency. This may not have much impact on this script, but it is a best practice that not everyone knows about. ".+" is not the same as "[^"]+". The former, in some scenarios, will "overmatch". The latter behaves like ".+?" but is more efficient.

Here is a pattern demo, if you want to see the official breakdown or test any input strings: https://regex101.com/r/sua8lS/1/

I am not sure if I have your selectors right, but jQuery affords you to implement the literal show() and hide() actions -- which is very easy on the eyes.

  • thanks for the suggestion! I already tried adding required="true" as an attribute of the field and now I also tried adding "required" to the class attribute as you proposed. Unfortunately none of these are triggering my custom event handler in case I enter something, then delete it and finally leave the field. What they do is highlighting the field caption with red, but what I want is to display a custom error message. Thanks for the other suggestion, I will take a look as soon as I fixed the problem of my custom event handler not being called. – wanderlusted Jan 28 at 12:16
  • Okay, that's all I got. I don't have something to test with. This was just shooting from the hip from my mobile. Keep engaging with Zollie, I feel like he might be able to see you through. – mickmackusa Jan 28 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.