Correção de mascará nos campos texto em dispositivos mobile

Visão Geral

No Latromi, é possível criar máscaras personalizadas para campos de texto nos objetos de formulário.

No entanto, essas máscaras atualmente não funcionam corretamente em dispositivos mobile.

Como uma solução temporária — até a finalização da reformulação dos objetos do Latromi — este tópico irá demonstrar como adicionar um script de correção para contornar essa situação e garantir uma melhor experiência de uso em dispositivos móveis.

Criação do fix JS

Recomendação de nome para o arquivo: MobileMaskFix.js

Para poder trabalhar com mascará em dispositivos Mobile é necessário adicionar um JS de correção, no arquivos Javascripts do objeto formulário, segue o código a ser adicionado abaixo:

function isMobile() {
    var userAgent = navigator.userAgent.toLowerCase();
    return /android|iphone|blackberry|windows phone/.test(userAgent);
}

const myForm = (function () {

    // Adiciona Callbacks no Formulário
    latromi.formManager.setOnFormCreatedCallback(onFormCreated);
    latromi.formManager.setOnEventFiringCallback(onEventFiring);
    latromi.formManager.setOnFieldValueChangedCallback(onFieldValueChanged);
    
    function AddMobileMask(input, mask, remove = false) {
        // Captura os valores fixos da mascará
        var valueInput = RemoveMask(input, mask);
        
        // Ação para o delete de caracteres
        if (remove)
            valueInput = valueInput.slice(0, -1)
        
        // Identifica o tamanho dos valores já preenchidos na mascará para poder mante-los
        var totalValue = valueInput.length;
        var valuePointer = 0;
        var valueWithMask = Array.from(mask);
        
        // Itera sobre os caracteres da mascará para substituir pelos valores do input
        for (var i = 0; i < mask.length; i++) {
            const char = mask[i];
            var canChange = char === '#' || char === 'L';
            
            if (canChange && totalValue > valuePointer) {
               if (char === '#' && isNaN(valueInput[valuePointer]))
                  valueWithMask[i] = '_';
               else
                  valueWithMask[i] = valueInput[valuePointer];
               valuePointer = valuePointer + 1;
            }
            else if (canChange) {
               valueWithMask[i] = '_';
            }
        }
        
        return valueWithMask.join('');
    }
    
    function RemoveMask(input, mask) {
        var valueInput = input.replaceAll('_', '');
        
        mask.matchAll("[^#|L]").forEach(function(val) {
            valueInput = valueInput.replace(val, '');
        });
        
        return valueInput;
    }
    
    function GetFieldsWithMask(fields) {
        return Object.values(fields)
                     .filter(function (obj) {
                        if (obj.mask)
                            return obj;
                     });
    }
    
    function CopyElement(element) {
        var elementCopy = document.createElement('input');
        elementCopy.setAttribute('name', `mobileMask${element.getAttribute("name")}`);
        elementCopy.setAttribute('type', element.getAttribute("type"));
        elementCopy.setAttribute('placeholder', element.getAttribute("placeholder"));
        elementCopy.setAttribute('spellcheck', element.getAttribute("spellcheck"));
        elementCopy.setAttribute('autocomplete', element.getAttribute("autocomplete"));
        elementCopy.setAttribute('style', element.getAttribute("style"));

        elementCopy.className = element.className;
        
        return elementCopy;
    }

    // Ocorre logo após o form ser inicializado
    function onFormCreated(ev) 
    {
        if (isMobile()) {
            var fields = GetFieldsWithMask(ev.form.fields);
            
            fields.forEach(function (obj) {                
                var elementMain = document.querySelector(`[data-field-name='${obj.name}']`);                
                var elementOrigin = elementMain.querySelector(`input[name='${obj.name}']`);
                var elementWithMask = CopyElement(elementOrigin);
                
                elementMain.appendChild(elementWithMask);
                elementOrigin.setAttribute("style", elementOrigin.getAttribute('style') + 'display: none;')
                
                elementWithMask.value = AddMobileMask(elementOrigin.value, obj.mask);

                elementWithMask.addEventListener("input", function () {
                    this.value = AddMobileMask(this.value, obj.mask);
                    elementOrigin.value = RemoveMask(this.value, obj.mask);
                })

                elementWithMask.addEventListener("keydown", function (event) {
                    if (event.key === "Backspace") {
                        event.preventDefault(); // Impede a remoção direta dos separadores
                        this.value = AddMobileMask(this.value, obj.mask, true);
                        elementOrigin.value = RemoveMask(this.value, obj.mask);
                    }
                });
                
                elementWithMask.addEventListener("focusout", function (event) {
                    var form = latromi.formManager.getFormInstance();
                    form.raiseFieldEvent(elementOrigin.attributes["name"].value, "LostFocus", null); // para campos texto
                });
            });
        }
    }

    // Ocorre quando um evento é disparado no Form
    function onEventFiring(ev) { }

    // Ocorre quando o valor de um campo é alterado no Form
    function onFieldValueChanged(ev) { }

    // Todas as funções acima são "privadas", e não podem ser chamadas externamente.
    // As únicas funções que podem ser chamadas externamente são as que compões o resultado a seguir:
    return {
        test: function() { }
    }
})();
1 curtida

Obrigado por atualizar o tópico!

1 curtida