Kortic, Anthony Ladeuil

Contrôle automatisé de pattern zipcodes

Postulat

Permettre l'ouverture du clavier ad hoc sur mobile selon les patterns de code postaux par pays.

  • Compatibilité devices mobile/desktop
  • Contrôle du pattern à la saisie et indicateur visuel
  • Automatisation (ajout d'un simple attribut)
  • Evolution des patterns facilitée
  • Pattern par défaut personnalisable
  • Nécessite JQuery

nb : vous devez créer une classe CSS personnelle .error ou utiliser celle disponible dans les sources du site voir la css

Exemples

Source Javascript $.fn.zipcode

;(function ($) {

    'use strict';

/*
    $.array_range = function(start, count){
        return Array(count).fill(0).map((e,i) => i + start);
    };
*/



    $.fn.zipcode = function(opts) {

        var settings = $.extend({
                'attribute': 'data-zipcode',
                'maxlength' : 10,
                'useLocale': false,
                'sendpattern': false
            }, opts),

            // inputmode disponible quand les navigateurs voudront bien l'implémenter.
            patterns = {
                'default': { // 5 digits type number
                    'type': 'number',
                    'inputmode': 'numeric',
                    'length': 5,
                    'regex': /^[0-9]{5}$/
                },
                'nl': {
                    'type': 'text',
                    'inputmode': 'text',
                    'length': 10,
                    'regex': /^(?:NL-)?(?:[1-9][0-9]{3} ?(?:[A-EGHJ-NPRTVWXZ][A-EGHJ-NPRSTVWXZ]|S[BCEGHJ-NPRTVWXZ]))$/i
                },
                'be': {
                    'type': 'number',
                    'inputmode': 'numeric',
                    'length': 4,
                    'regex': /^[0-9]{4}$/
                },
                'uk': {
                    'type': 'text',
                    'inputmode': 'text',
                    'length': 8,
                    'regex': /((?:(?:gir)|(?:[a-pr-uwyz])(?:(?:[0-9](?:[a-hjkpstuw]|[0-9])?)|(?:[a-hk-y][0-9](?:[0-9]|[abehmnprv-y])?)))) ?([0-9][abd-hjlnp-uw-z]{2})/,
                    'only': /[0-9A-Z]/
                },
                'us': {
                    'type': 'text',
                    'inputmode': 'text',
                    'length': null,
                    'regex': /^[0-9]{5}(?:(-| )[0-9]{4})?$/,
                    'only': / [0-9]\-/
                }
            };


        $(this).each(function() {

            var element_ = $(this),
                key = settings.useLocale === false ? ( element_.attr(settings.attribute).length ? element_.attr(settings.attribute).toLowerCase() : 'default') : settings.useLocale.toLowerCase(),
                pattern  = patterns[ $.array_key_exists(key, patterns) ? key : 'default' ];

                element_.attr({
                    'type': pattern.type,
                    'inputmode': pattern.inputmode,
                    'maxlength': pattern.length !== null ? pattern.length : settings.maxlength
                }).data('is_selected', false);

                if(pattern.type !== 'text') {
                    element_.data('count', 0).attr({
                        'min': 0,
                        'max': '9'.repeat(pattern.length),
                        'step': 1000
                    });
                }

                // envoyer la regExp au back pour contrôle
                if(settings.sendpattern) {
                    var inputPattern = $('<input/>', {
                        'type': 'hidden',
                        'value': pattern.regex,
                        'name': 'pattern'
                    });
                    element_.parents('form').append(inputPattern);
                }

                element_.on('change keyup',  function(){

                    element_.removeClass('error');

                    var reg = new RegExp( pattern.regex, 'ig');

                    if(element_.val().length) {
                        if(!reg.test(element_.val())){
                            element_.addClass('error');
                        }

                    }

                }).on('keyup keydown touchstart touchend', function(e) {

                    var currentVal = element_.val().trim();

                    if( $.inArray(e.type, ['keyup', 'touchend']) !== -1) {
                        element_.data('count', currentVal.length);
                    }

                    element_.data('is_selected', window.getSelection().toString().length > 0);

                    if(pattern.inputmode === 'numeric' && $.inArray(e.type, ['keydown', 'touchstart']) !== -1) {

                        if ( $.inArray(e.which, [38, 40]) != -1 ) {
                            e.preventDefault();
                        }

                        if ( $.inArray( parseInt(e.which, 10), $.range(48, 10).concat([8, 9, 13]).concat($.range(37, 4)) ) == -1 ) {
                            e.preventDefault();
                        }

                        if ( element_.data('count') == element_.attr('maxlength') && $.inArray( parseInt(e.which, 10), $.range(48, 10)) != -1 && !element_.data('is_selected') ) {
                            e.preventDefault();
                        }

                        if ( currentVal.length > element_.attr('maxlength') ) {
                            element_.val(currentVal.substr(0, element_.attr('maxlength')));
                        }

                    }
                });

            return this;

        });
    };

    $(document).ready(function(){

        // appel générique pour les champs avec attribut data-zipcode
        $('[data-zipcode]').zipcode({
            'sendpattern': true // ajoute un champ caché dans le formulaire parent du champ pour envoyer la RegExp pour traitement back
        });

        /*
         **
         ***
            appel pour les champs avec attribut data-specific et/ou variable locale définie

            $('[data-specific]').zipcode({
                'attribute': 'data-specific',
                'useLocale': 'fr' // ou variable js globale
            });
         ***
         **
        */

    });

})(jQuery);
Voir aussi…