How to validate format and compare two dates to enable buttons

Asked

Viewed 1,761 times

6

I am using a script* to enable a button when two validations are made. The first one checks the format, and the second one if the initial date is lower than the final one, but I’m having some problems to include more fields with the same functionality, and correct some inconsistencies.

I created a FIDDLE to demonstrate the operation in practice, and follows below the code with verifiable example. The script already does the validation (both formatting and comparison) before opening the button, but:

  • It only works when you lose focus, I wish it was as with onkeyup (when to release the key), but if there’s no way it can only be when you lose focus yourself;
  • If the user, after the button has been opened, changes the date to an invalid format (or is shorter than another that should be larger), the button nay is disabled (and I need it to be). I need it is not possible for the user to "screen pass" (trade in div, see fiddle) without the format being correct, and observe the initial date condition < final date;
  • The last date, which makes the comparison with the second, arrives to open the div with the error message (when the date is shorter or is in the wrong format), but still sends the form (what wasn’t supposed to happen);
  • The field accepts letters, and only after that loses focus it gives the message that the format is wrong. I wanted the field do not accept letters, only numbers (it is possible to do with Regexp not? ) not even the / which causes problems because the user sometimes tries to type it.

I am open to other solutions, including with plugins other than that I’m wearing To check the formatting, but I already know that I went a long way looking for another solution and did not find. Either the plugin/script validates the formatting, or validates the comparison of the dates, and I need both.

Follows the code:

    // VALIDAÇÃO DO FORMATO PELO FORM.VALIDATOR

// Chama o form.validator

    $.validate({
        modules: 'date'
    });

    // Cria uma classe que verifica se o form.validator foi true, e abre o botão.

    $('.checar')

            .on('validation', function (evt, valid) {
                var validou =  document.getElementById('validou').value = valid ? "true" : "false";

                /* Verifica SE a data está OK */

                if (validou === "true") {
                    verificar(); // chama o script abaixo antes de abrir o botão se o formato está correto
                }
            });


    //VALIDA DATAS EM COMPARAÇÕES 

    var primeiradata = document.getElementById('Cinsem');
    var segundadata = document.getElementById('Cdesl22');
    var terceiradata = document.getElementById('Cinsem2');
    var quartadata = document.getElementById ('Cdesl223');
    var quintadata = document.getElementById('Cdatapgtos');

    function gerarData(str) {
        var partes = str.split("/");
        return new Date(partes[2], partes[1] - 1, partes[0]);
    }

    function verificar() {
        var primeira = primeiradata.value;
        var segunda = segundadata.value;
        var terceira = terceiradata.value;
        var quarta = quartadata.value;
        var quinta = quintadata.value;

        // PRIMEIRA DATA X SEGUNDA DATA

        if (primeira.length != 10 || segunda.length != 10) {
            return;
        }
        if (gerarData(segunda) >= gerarData(primeira)) {
            $('#startBtnseg').removeAttr('disabled', 'disabled');
            $('#message1').hide();
        }
        else {
            $('#startBtnseg').attr('disabled', 'disabled');
            $('#message1').fadeIn('slow');
        }
        // TERCEIRA DATA X QUARTA DATA

        if (terceira.length != 10 || quarta.length != 10) {
            return;
        }
        if (gerarData(quarta) >= gerarData(terceira)) {
            $('#startBtnseg2').removeAttr('disabled', 'disabled');
            $('#message2').hide();
        }
        else {
            $('#startBtnseg2').attr('disabled', 'disabled');
            $('#message2').fadeIn('slow');
        }

        //QUINTA DATA X SEGUNDA DATA

        if (quinta.length != 10 || segunda.length != 10){
            return;
        }
        if (gerarData(quinta) < gerarData(segunda)){
            $('#startBtnseg3').attr('disabled', 'disabled');
            $('#message3').fadeIn('slow');
        }
        else {
            $('#startBtnseg3').removeAttr('disabled', 'disabled');
            $('#message3').hide();
        }
    }

  
    <style>
        .message1 {

            font-size: 10pt;
            color: red;
        }
    </style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-form-validator/2.1.47/jquery.form-validator.min.js"></script>
<form>
    <div class="container textWord_about"  data-link="first">
    <label class="btn" for="Cinsem">
    <i class="glyphicon glyphicon-calendar"></i>Primeira data
    <input class="form-control checar" type="text" maxlength="10" placeholder="dd/mm/aaaa"
           onkeyup="formatar('##/##/####', this, event)" name="Tinsem3" id="Cinsem"
           data-validation="birthdate" data-validation-error-msg="Insira uma data válida"
           data-validation-format="dd/mm/yyyy"></label>
<br><br>
<label class="btn" for="Cdesl22">
    <i class="glyphicon glyphicon-calendar"></i>Segunda data
    <input type="text" class="form-control checar" name="Tdesl"  maxlength="10" data-validation="date"
           data-validation-format="dd/mm/yyyy" data-validation-error-msg="Insira uma data válida" placeholder="dd/mm/aaaa"
           onkeyup="formatar('##/##/####', this, event)" id="Cdesl22"></label>

<!-- Espelho de #aniv1,porém do tipo "date" -->
<label for="Cdesl222"></label>
<input type="date" id="Cdesl222" name="Cdesl22" class="checar" hidden="hidden" />

<!-- Auxilia na validação. Pode ser um DIV também mas precisará alterar o código -->
<label for="validou"></label>
<input type="text" id="validou" name="validou" hidden="hidden" class ="checar" value="false" />

<div class="message1 " id="message1" style="display:none;"><br><br>A segunda data deve ser igual ou posterior à primeira data.</div>
    <br><br>

<button type="button" class="btn btn-primary btn-sm link" id="startBtnseg"  name="TstartBtnseg"
        data-link="dois" onkeyup="verificar()" disabled="disabled">
    <i class="glyphicon glyphicon-ok"> Ir para próximas datas</i></button>
       <br><br>
        A segunda data deve ser <b>igual ou maior</b> que a primeira, e ambas devem estar
        no formato correto (ou seja, não pode aceitar letras, nem mês acima de 13 etc) para abrir o botão.
        Caso o usuário, antes de submeter o formulário (ou depois, se ele voltar) faça qualquer alteração
        que torne o formato inválido, ou torne a data final menor que a inicial, o botão deve ser desabilitado.
        O ideal é que a habilitação/desabilitação do botão seja feita com onkeyup (assim que o usuário
        tirar a pressão da tecla), mas se não tiver jeito pode ser só quando perder o foco mesmo (e eu criaria uma botão
        "falso" para "Checar data", onde o usuário clicaria apenas para o campo perder o foco e realziar a validação).
    <br><br>
</div>
    <div class="container textWord_about"  data-link="dois">
        <label class="btn" for="Cinsem2">
            <i class="glyphicon glyphicon-calendar"></i>Terceira data
            <input class="form-control checar" type="text" maxlength="10" placeholder="dd/mm/aaaa"
                   onkeyup="formatar('##/##/####', this, event)" name="Tinsem3" id="Cinsem2"
                   data-validation="birthdate" data-validation-error-msg="Insira uma data válida"
                   data-validation-format="dd/mm/yyyy"></label>
        <br><br>
        <label class="btn" for="Cdesl223">
            <i class="glyphicon glyphicon-calendar"></i>Quarta data
            <input type="text" class="form-control checar" name="Tdesl"  maxlength="10" data-validation="date"
                   data-validation-format="dd/mm/yyyy" data-validation-error-msg="Insira uma data válida" placeholder="dd/mm/aaaa"
                   onkeyup="formatar('##/##/####', this, event)" id="Cdesl223"></label>

        <!-- Espelho de #aniv1,porém do tipo "date" -->
        <label for="Cdesl222"></label>
        <input type="date" id="Cdesl2223" name="Cdesl223" class="checar" hidden="hidden" />

        <!-- Auxilia na validação. Pode ser um DIV também mas precisará alterar o código -->
        <label for="validou"></label>
        <input type="text" id="validou3" name="validou" hidden="hidden" class ="checar" value="false" />

        <div class="message1" id="message2" style="display:none;"><br><br>A data quarta data deve ser posterior à terceira data.</div>
        <br><br>

        <button type="button" class="btn btn-primary btn-sm link" id="startBtnseg2"
                data-link="tres" onkeyup="verificar()" disabled="disabled">
            <i class="glyphicon glyphicon-ok"> Próximas!</i></button>
        <br><br>
        Igual a primeira tela, considerando entre a terceira e a quarta datas.
    </div>

    <div class="container textWord_about" id="menu_about" data-link="tres">
<label class="btn" for="Cdatapgtos">
    <i class="glyphicon glyphicon-calendar"></i> Quinta data
    <input type="text"  id="Cdatapgtos" name="Tdatapagtos" class="form-control checar" maxlength="10"
           placeholder="dd/mm/aaaa" onkeyup="formatar('##/##/####', this, event)"></label>
<div class="message1 " id="message3" style="display:none;">A quinta data deve ser igual ou posterior à segunda data.</div>
    <br><br>
<button type="submit" id="startBtnseg3" class="btn btn-primary btn-sm" onkeyup="verificar()">
    <i class="glyphicon glyphicon-ok">Submeter formulário</i></button>
        <br><br>
        A quinta data deve ser <b>IGUAL OU POSTERIOR</b> à <b>SEGUNDA DATA</b>, e ambas devem
        estar no formato correto para que o formulário seja submetido. O botão de submeter
        o formulário precisa estar habilitado, e será desabilitado caso as validações não ocorram (formato de data e comparação
        com segunda data). Da mesma forma seria interessante com onkeyup, mas pode ser quando clicar no botão.
        O campo não é obrigatório, mas caso seja preenchido é feita a validação, e habilitado/desabilitado.
        </div>
</form>
        
        <script>      // ALTERNA AS DIV's

  $('.textWord_about').not(':first').hide();
    $('.link').click(function() {
        $('.textWord_about').hide();
        $('.textWord_about[data-link=' + $(this).data('link') + ']').fadeIn('slow');
    });</script>
        
        <script>
            
// MÁSCARA DOS CAMPOS

function formatar(mascara, documento, e) {
        var code = e.keyCode || e.code;
        if (code == 8 || code == 46 || code == 37 || code == 39) return;
        var i = documento.value.length;
        var saida = mascara.substring(0, 1);
        var texto = mascara.substring(i);
        if (texto.substring(0, 1) != saida) {
            documento.value += texto.substring(0, 1);
        }
    }

            
        </script>

Several users here of Sopt helped me to implement this script. See the series of questions:

1 answer

6


I ended up removing some parts of your code that I didn’t find necessary and added some <p> to get better presented, and remove HTML5 validation.

.message1 {
    font-size: 10pt;
    color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="http://pastebin.com/raw.php?i=gE1SbXKA"></script>
<script type="text/javascript" src="http://pastebin.com/raw.php?i=8xvHJBJf" ></script>
<script type="text/javascript" src="http://pastebin.com/raw.php?i=YRhQfUJs"></script>

<form onsubmit="return verifica('data2', 'data5', false, 3);">
    <div class="container textWord_about"  data-link="first">
	
        <p>
            <label class="btn" for="Cinsem">
                <i class="glyphicon glyphicon-calendar"></i>Primeira data
                <input class="form-control checar" id="data1" type="text" maxlength="10"
				       data-funcao="verifica('data1', 'data2', true, 1);">
            </label>
        </p>
        <p>
            <label class="btn" for="Cinsem">
                <i class="glyphicon glyphicon-calendar"></i>Segunda data
                <input class="form-control checar" id="data2" type="text" maxlength="10"
				       data-funcao="verifica('data1', 'data2', false, 1);">
            </label>
        </p>

        <button type="button" class="btn btn-primary btn-sm link" id="botao1" 
		        data-link="dois" disabled="disabled">
            <i class="glyphicon glyphicon-ok"> OK, vamos continuar!</i>
        </button>
		   
        <p>
            A segunda data deve ser <b>igual ou maior</b> que a primeira, e ambas devem estar
            no formato correto (ou seja, não pode aceitar letras, nem mês acima de 13 etc) para abrir o botão.
            Caso o usuário, antes de submeter o formulário (ou depois, se ele voltar) faça qualquer alteração
            que torne o formato inválido, ou torne a data final menor que a inicial, o botão deve ser desabilitado.
            O ideal é que a habilitação/desabilitação do botão seja feita com onkeyup (assim que o usuário
            tirar a pressão da tecla), mas se não tiver jeito pode ser só quando perder o foco mesmo (e eu criaria uma botão
            "falso" para "Checar data", onde o usuário clicaria apenas para o campo perder o foco e realziar a validação).
        </p>
    </div>
	
    <div class="container textWord_about"  data-link="dois">
	
        <p>
            <label class="btn" for="Cinsem">
                <i class="glyphicon glyphicon-calendar"></i>Terceira data
                <input class="form-control checar" id="data3" type="text" maxlength="10"
				       data-funcao="verifica('data3', 'data4', true, 2);">
            </label>
        </p>
        <p>
            <label class="btn" for="Cinsem">
                <i class="glyphicon glyphicon-calendar"></i>Quarta data
                <input class="form-control checar" id="data4" type="text" maxlength="10"
				       data-funcao="verifica('data3', 'data4', false, 2);">
            </label>
        </p>

        <button type="button" class="btn btn-primary btn-sm link" id="botao2" 
		        data-link="tres" disabled="disabled">
            <i class="glyphicon glyphicon-ok"> OK, vamos continuar!</i>
        </button>
		   
        <p>
            Igual a primeira tela, considerando entre a terceira e a quarta datas.
        </p>
    </div>
	
    <div class="container textWord_about"  data-link="tres">
	
        <p>
            <label class="btn" for="Cinsem">
                <i class="glyphicon glyphicon-calendar"></i>Quinta data
                <input class="form-control checar" id="data5" type="text" maxlength="10"
				       data-funcao="verifica('data2', 'data5', false, 3);">
            </label>
        </p>

        <button type="submit" id="botao3" class="btn btn-primary btn-sm"
		        onclick="return verifica('data2', 'data5', false, 3);">
            Submeter formulário
        </button>
		   
        <p>
            A quinta data deve ser <b>IGUAL OU POSTERIOR</b> à <b>SEGUNDA DATA</b>, e ambas devem
            estar no formato correto para que o formulário seja submetido. O botão de submeter
            o formulário precisa estar habilitado, e será desabilitado caso as validações não ocorram (formato de data e comparação
            com segunda data). Da mesma forma seria interessante com onkeyup, mas pode ser quando clicar no botão.
            O campo não é obrigatório, mas caso seja preenchido é feita a validação, e habilitado/desabilitado.
        </p>
    </div>
	        
    <script>      // ALTERNA AS DIV
        $('.textWord_about').not(':first').hide();
        $('.link').click(function() {
            $('.textWord_about').hide();
            $('.textWord_about[data-link=' + $(this).data('link') + ']').fadeIn('slow');
        });
    </script>
        
    <script>    // MÁSCARA DOS CAMPOS
        $(document).ready(function(){
            $('.checar').inputmask("dd/mm/yyyy",
                                    {
                                        "oncomplete": function () {
                                            eval($(this).data("funcao"));
                                    }
            });
        });
		
        function gerarData(str) {
            var partes = str.split("/");
            return new Date(partes[2], partes[1] - 1, partes[0]);
        }
		
        function verifica(idMenor, idMaior, primeiro, botao) {
            $('.message1').remove();
		
            $campoMenor = $('#' + idMenor);
            $campoMaior = $('#' + idMaior);
            $campoAviso = primeiro ? $campoMenor : $campoMaior;
            $botao = $('#botao' + botao);
			
            if (!$campoMaior.val() || !$campoMenor.val())
                return;
			
            if (gerarData($campoMenor.val()) <= gerarData($campoMaior.val())) {
                $botao.removeAttr("disabled");
            } else {
                $campoAviso.after($('<span/>').html("Insira uma data válida").addClass('message1'));
                $botao.attr("disabled", "disabled");
            }
        }
    </script>
</form>

I used that same plugin from question about hours, but to validate the date obliging to be a valid date and I check the button on oncomplete hers.

I used Pastebin because of the problem when pulling the source, so these are the original ones:

<script type="text/javascript" src="https://raw.githubusercontent.com/RobinHerbots/jquery.inputmask/2.x/js/jquery.inputmask.js"></script>
<script type="text/javascript" src="https://raw.githubusercontent.com/RobinHerbots/jquery.inputmask/2.x/js/jquery.inputmask.extensions.js" ></script>
<script type="text/javascript" src="https://raw.githubusercontent.com/RobinHerbots/jquery.inputmask/2.x/js/jquery.inputmask.date.extensions.js"></script>



Explanation of the Function verifica(idMenor, idMaior, primeiro, botao)

  • idMenor will be the field you will compare being the lower date

  • idMaior will be the field you will compare being an equal or later date

  • first is a flag to see if my invalid date warning will be on the first or second id.

  • boot is for me to know which button I need to lock or unlock



The secret to working

$(document).ready(function(){
    $('.checar').inputmask("dd/mm/yyyy",
                            {
                                "oncomplete": function () {
                                    eval($(this).data("funcao"));
                                }
                            });
});
  • eval accepts a string as parameter and it will run it as normal code, example eval("1 + 3") will return 4.

  • attribute a data-funcao input to know exactly which fields need to validate and which order

  • about the submit I assign a function there also to retornar false when the date is invalid, thus it is not submitted.

  • oncomplete is only called when it finishes filling the entire mask, if you want to improve this warning there are other events that can be seen here: https://github.com/RobinHerbots/jquery.inputmask (look for oncomplete, onincomplete...)


Any problem or bug, let me know.

  • 1

    Apparently it’s perfect! I’ll check it out in a little while, but I tested the rules here and it looks like it’s perfect! Thanks!

  • 1

    I added information about the oncomplete at the end of the answer also be interested.

  • 1

    @Gustavox any questions about any line, can speak :)

  • Yes, I’ll study straight to learn, and I’ll ask anything. : ) But I just tested it here in the project and it seems that it was better than it was in various aspects (beyond what I thought). Now for example we can no longer enter with invalid date, because the script itself changes the location of the number (typing 4 at the beginning of the month turns automatic into month 4, thus preventing month 44 for example), being very similar to the field input type:date except for the window with the calendar (which only disturbs when the date is not in the first days of the calendar...). Even worth!

  • 1

    yes this plugin is excellent, a pity still not working right in the latest version, I made a test to put only 0 and it also hangs! :)

  • 1

    A shame really, but it’s working right, and I use the most current jQuery and gave no problem in any other script... It’s perfect! :-)

  • Must be able to handle invalid dates (month 44 and date with only 0s) within the oncomplete: if it is not valid at all, return false.

  • @fake plugin already treats this before arriving at oncomplete :)

  • 2

    @Maiconcarraro I say this in case I use the plugin in the version I said was in trouble: ...a pity it still doesn’t work right in the latest version, I did a test to put only 0 and it also hangs...

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.