A complete JavaScript library for form masking and validation, dependency-free and with a native callable API.
See the complete documentation site, with interactive examples, API reference, standalone installation, jQuery compatibility, postal-code autocomplete, and geolocation.
- Installation and Configuration
- Basic Configuration
- Validation Classes
- Mask Classes
- Advanced Validations
- Callbacks System
- Address Autocomplete
- Geolocation
- Practical Examples
- JavaScript API
- InnerFormValidation Functions
- Visual Customization
<!-- Recommended: works without jQuery -->
<script src="https://cdn.jsdelivr.net/gh/zonaro/InnerFormValidation@master/InnerFormValidation.js"></script>
<script>
InnerForm.validateCPF('529.982.247-25');
</script>To use it as a jQuery plugin, load jQuery before the same CDN address:
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>jQuery.innerForm = { verbose: true }</script>
<script src="https://cdn.jsdelivr.net/gh/zonaro/InnerFormValidation@master/InnerFormValidation.js"></script>- Download the
InnerFormValidation.jsfile - Include it in your project:
<script>InnerForm.verbose = true</script>
<script src="path/to/InnerFormValidation.js"></script>- None for the standalone API.
- jQuery is optional and enables the legacy plugin methods in
jQuery.fn. - The library never overwrites
$or uses jQuery in its core.
<script src="InnerFormValidation.js"></script>
<script>
const valid = InnerForm.validateCPF('529.982.247-25');
InnerForm.applyCPFMask(document.querySelector('#cpf'));
InnerForm.isValid(document.querySelector('form'));
</script><form class="validate">
<input type="text" class="form-control obg minlen 5" placeholder="Minimum 5 characters">
<button type="submit">Enviar</button>
</form>validate: Add to the<form>element to enable validationmask: Combine with other classes to apply masks automaticallyonkeyup: Validate as the user types (with a 900ms delay)
InnerForm.verbose = true;
InnerForm.onTypeTimeout = 1000;To select elements with the native API, use the function itself:
InnerForm('#meu-formulario').isValid();| Class | Description | Example |
|---|---|---|
obg req required |
Required field | <input class="obg"> |
| Class | Description | Mask Compatible | Example |
|---|---|---|---|
email mail |
Valid email | β | <input class="email"> |
url link |
Valid URL | β | <input class="mask url"> |
cpf |
Valid Brazilian CPF | β | <input class="mask cpf"> |
cnpj |
Valid Brazilian CNPJ | β | <input class="mask cnpj"> |
cpfcnpj |
Valid CPF or CNPJ | β | <input class="mask cpfcnpj"> |
cep |
Valid Brazilian postal code | β | <input class="mask cep"> |
cnh |
Valid Brazilian CNH | β | <input class="mask cnh"> |
tel cel |
Brazilian phone/mobile | β | <input class="mask tel"> |
ean |
EAN barcode | β | <input class="ean"> |
uuid |
Valid UUID/GUID | β | <input class="mask uuid"> |
pix chavepix |
Valid PIX key | β | <input class="pix"> |
latitude lat |
Latitude coordinate | β | <input class="mask latitude"> |
longitude long lng |
Longitude coordinate | β | <input class="mask longitude"> |
uf state |
State abbreviation (UF) | β | <input class="mask uf"> |
oab |
OAB registration (1-6 digits + UF) | β | <input class="mask oab"> |
Fields with the num or number classes now support the following attributes for format customization:
| Attribute | Description | Example |
|---|---|---|
data-separator |
Defines the decimal separator (e.g. , or .). Takes priority over data-decimal. |
<input class="mask num" data-separator="," /> |
data-decimal |
Defines the number of decimal places (e.g. 2). |
<input class="mask num" data-decimal="2" /> |
data-thousand |
Defines the thousands separator (e.g. . or ,). |
<input class="mask num" data-thousand="." /> |
Priority rules:
- If
data-separatorexists, it is used as the decimal separator. - Otherwise, the value of
data-decimalis used (default: 2 decimal places, separator,). - The
data-thousandattribute is optional and defines the thousands separator.
Usage example:
<!-- Number with comma as decimal separator and period as thousands separator -->
<input class="form-control mask num" data-separator="," data-thousand="." placeholder="1.234,56">
<!-- Number with period as decimal separator and comma as thousands separator -->
<input class="form-control mask num" data-separator="." data-thousand="," placeholder="1,234.56">
<!-- Number with 3 decimal places and no thousands separator -->
<input class="form-control mask num" data-decimal="3" placeholder="1234,567">Validation also respects these attributes and accepts only the configured format.
| Class | Description | Mask Compatible | Example |
|---|---|---|---|
alpha |
Letters only (A-Z) | β | <input class="mask alpha"> |
alphanumeric alphanum |
Letters and numbers | β | <input class="mask alphanum"> |
num number |
Numbers only | β | <input class="mask num"> |
upper |
Uppercase only | β | <input class="mask upper"> |
lower |
Lowercase only | β | <input class="mask lower"> |
nospace |
Forbid spaces | β | <input class="mask nospace"> |
| Class | Format | Mask Compatible | Example |
|---|---|---|---|
date data |
dd/MM/yyyy | β | <input class="mask date"> |
time |
hh:mm:ss | β | <input class="mask time"> |
timeshort shorttime |
hh:mm | β | <input class="mask timeshort"> |
datetime |
dd/MM/yyyy hh:mm:ss | β | <input class="mask datetime"> |
datetimeshort |
dd/MM/yyyy hh:mm | β | <input class="mask datetimeshort"> |
minutesecond |
mm:ss | β | <input class="mask minutesecond"> |
monthyear |
MM/yyyy | β | <input class="mask monthyear"> |
daterange |
dd/MM/yyyy ~ dd/MM/yyyy | β | <input class="mask daterange"> |
monthyearrange |
MM/yyyy ~ MM/yyyy | β | <input class="mask monthyearrange"> |
shortmonthyearrange |
MM/yy ~ MM/yy | β | <input class="mask shortmonthyearrange"> |
| Class | Description | Example |
|---|---|---|
len <number> |
Exactly X characters | <input class="len 10"> |
minlen <number> |
At least X characters | <input class="minlen 5"> |
maxlen <number> |
At most X characters | <input class="maxlen 20"> |
leadingzero <number> |
Pad with leading zeros | <input class="mask leadingzero 8"> |
uforstate: validates whether the abbreviation is a valid Brazilian UF.oab: validates whether the input uses the formatNΒΊ(1-6 digits)+UF(e.g.511061SPor511.061/SP).cnh: validates whether the Brazilian CNH is valid and does not contain a repeated sequence (e.g.000.000.000-00).
<input type="text" class="form-control uf onkeyup" placeholder="SP" />
<input type="text" class="form-control mask oab onkeyup" placeholder="511061SP" />InnerForm.validateUF('RJ'); // true
InnerForm.validateUF('ZZ'); // false
InnerForm.validateOAB('511061SP'); // true
InnerForm.validateOAB('511.061/SP'); // true
InnerForm.validateOAB('12345RJ'); // true
InnerForm.validateOAB('123456SA'); // false (invalid UF)
InnerForm.validateCNH('98765432100'); // true/false conforme DV
InnerForm.validateCNH('00000000000'); // false
InnerForm.validateCNH('987.654.321-00'); // true/false
InnerForm.validateCEP('01310-100'); // true (ignora a mΓ‘scara)
InnerForm.validatePhone('(11) 98765-4321'); // trueNote: Add the
maskclass together with the specific class to apply masks automatically.
<!-- CPF: 123.456.789-01 -->
<input class="form-control mask cpf">
<!-- CNPJ: 12.345.678/0001-90 -->
<input class="form-control mask cnpj">
<!-- Automatic CPF or CNPJ -->
<input class="form-control mask cpfcnpj">
<!-- CEP: 12345-678 -->
<input class="form-control mask cep">
<!-- CNH: 123.456.789-00 -->
<input class="form-control mask cnh"><!-- Date: dd/mm/yyyy -->
<input class="form-control mask date">
<!-- Date and time: dd/mm/yyyy hh:mm:ss -->
<input class="form-control mask datetime">
<!-- Time: hh:mm:ss -->
<input class="form-control mask time">
<!-- Month/Year: mm/yyyy -->
<input class="form-control mask monthyear">
<!-- Date range: dd/mm/yyyy ~ dd/mm/yyyy -->
<input class="form-control mask daterange">
<!-- Month/Year range: mm/yyyy ~ mm/yyyy -->
<input class="form-control mask monthyearrange">
<!-- Short Month/Year range: mm/yy ~ mm/yy -->
<input class="form-control mask shortmonthyearrange"><!-- Telefone: (11) 1234-5678 ou (11) 12345-6789 -->
<input class="form-control mask tel">
<!-- URL: automaticamente formata -->
<input class="form-control mask url"><!-- Any card: 1234 5678 9012 3456 -->
<input class="form-control mask creditcard">
<!-- Specific card (Visa only) -->
<input class="form-control mask creditcard visa"><!-- Uppercase only -->
<input class="form-control mask upper">
<!-- Lowercase only -->
<input class="form-control mask lower alpha">
<!-- No spaces -->
<input class="form-control mask nospace">
<!-- Numbers with leading zeros -->
<input class="form-control mask num len 8 leadingzero">
<!-- UUID/GUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -->
<input class="form-control mask uuid"><!-- Over 18 years old -->
<input class="form-control mask date minage 18" placeholder="Date of Birth">
<!-- Under 65 years old -->
<input class="form-control mask date maxage 65">
<!-- Exactly 30 years old -->
<input class="form-control mask date age 30"><!-- Greater than 10 -->
<input class="form-control num after 10">
<!-- Less than 100 -->
<input class="form-control num before 100">
<!-- Between 1 and 10 -->
<input class="form-control num 1 to 10"><!-- After today -->
<input class="form-control mask date after today">
<!-- Before a specific date -->
<input class="form-control mask date before 31/12/2023">
<!-- Between two dates -->
<input class="form-control mask date 01/01/2023 to 31/12/2023"><!-- Strong password (4 of 4 criteria: uppercase, lowercase, number, symbol) -->
<input type="password" class="form-control password strong minlen 8">
<!-- Medium password (3 of 4 criteria) -->
<input type="password" class="form-control password medium minlen 6">
<!-- Custom password (2 of 4 criteria) -->
<input type="password" class="form-control password 2 minlen 4">visa- Visamastercard- Mastercardamex- American Expressdiners- Diners Clubdiscover- Discoverelo- Elohiper- Hiperjcb- JCBaura- Auramaestro- Maestro
<!-- Any valid card -->
<input class="form-control mask creditcard">
<!-- Visa or Mastercard only -->
<input class="form-control mask creditcard visa mastercard"><!-- Valid UUID/GUID in any format -->
<input class="form-control uuid">
<!-- UUID with automatic masking -->
<input class="form-control mask uuid"><!-- Accepts email, CPF, CNPJ, phone number, or UUID -->
<input class="form-control pix">
<!-- Equivalent alias -->
<input class="form-control chavepix"><!-- Must contain a space -->
<input class="form-control contains _space">
<!-- Must contain specific text -->
<input class="form-control contains @gmail.com">
<!-- Must contain any of the characters -->
<input class="form-control containsanychar {}()">
<!-- Must contain all of the characters -->
<input class="form-control containsallchar ABC">
<!-- Must NOT contain specific characters -->
<input class="form-control notcontainschar ABCD"><!-- Compare with another field -->
<input id="senha" type="password" class="form-control">
<input class="form-control eq #senha" placeholder="Confirm Password">
<!-- Compare with a specific value -->
<input class="form-control eqv admin" placeholder="Digite 'admin'">Use data-* attributes to run JavaScript code on validation events:
<input class="form-control obg"
data-beforevalidatecallback="console.log('Before validation')"
data-validcallback="$('#success').show()"
data-invalidcallback="$('#error').show()"
data-aftervalidatecallback="console.log('After validation')"><input class="form-control obg"
data-invalidmessage="This field is required! π"><input class="form-control obg eq #div_OK"
data-invalidcallback="$('#status').text('β Invalid').css('color','red')"
data-validcallback="$('#status').text('β
Valid').css('color','green')">
<div id="status"></div>InnerFormValidation includes integration with the ViaCEP API for Brazilian address autocomplete.
| Class | Description | Example |
|---|---|---|
autocomplete cep |
Postal-code field that searches for an address | <input class="autocomplete cep mask"> |
autocomplete address |
Recebe logradouro | <input class="autocomplete address"> |
autocomplete neighborhood |
Recebe bairro | <input class="autocomplete neighborhood"> |
autocomplete city |
Recebe cidade | <input class="autocomplete city"> |
autocomplete state |
Recebe estado (UF) | <input class="autocomplete state"> |
autocomplete fulladdress |
Receives the complete address | <p class="autocomplete fulladdress"></p> |
autocomplete num number |
Number field (receives focus) | <input class="autocomplete num"> |
autocomplete homenum homenumber |
House number (alphanumeric) | <input class="autocomplete homenum"> |
autocomplete ddd |
Regional area code | <input class="autocomplete ddd"> |
autocomplete ibge |
IBGE code | <input class="autocomplete ibge"> |
autocomplete gia |
GIA code | <input class="autocomplete gia"> |
autocomplete latitude lat |
Recebe latitude automaticamente | <input class="autocomplete latitude"> |
autocomplete longitude long |
Recebe longitude automaticamente | <input class="autocomplete longitude"> |
autocomplete siafi |
SIAFI code | <input class="autocomplete siafi"> |
<div class="row">
<div class="col-md-4">
<label>CEP</label>
<input class="form-control mask cep autocomplete obg" placeholder="00000-000">
</div>
<div class="col-md-6">
<label>Address</label>
<input class="form-control autocomplete address" readonly>
</div>
<div class="col-md-2">
<label>Number</label>
<input class="form-control autocomplete homenum">
</div>
<div class="col-md-4">
<label>Bairro</label>
<input class="form-control autocomplete neighborhood" readonly>
</div>
<div class="col-md-4">
<label>Cidade</label>
<input class="form-control autocomplete city" readonly>
</div>
<div class="col-md-4">
<label>Estado</label>
<input class="form-control autocomplete state" readonly>
</div>
</div><!-- Do not replace value if already filled -->
<input class="form-control autocomplete address noreplace">InnerFormValidation includes advanced geolocation functions that use the browser's native API to obtain the user's location information.
Asynchronously obtains the user's current location using Promises.
// Basic usage
InnerForm.getLocation()
.then(function(location) {
console.log('Latitude:', location.latitude);
console.log('Longitude:', location.longitude);
console.log('Accuracy:', location.accuracyFormatted);
// Fill form fields
$('#latitude').val(location.latitude);
$('#longitude').val(location.longitude);
})
.catch(function(error) {
console.error('Error:', error.userMessage);
alert('Error obtaining location: ' + error.userMessage);
});
// Usage with custom options
InnerForm.getLocation({
enableHighAccuracy: true, // High accuracy
timeout: 15000, // 15-second timeout
maximumAge: 60000 // 60-second cache
})
.then(function(location) {
// Location obtained successfully
console.log('Coordinates:', location.coordinates);
console.log('Google Maps:', location.googleMapsUrl);
})
.catch(function(error) {
// Handle error
console.error('Geolocation error:', error);
});The function returns a rich object with location information:
{
// Main coordinates
latitude: -23.5505,
longitude: -46.6333,
// Accuracy
accuracy: 65.0, // In meters
accuracyFormatted: "65 meters", // Formatted for display
altitudeAccuracy: 12.0, // Altitude accuracy
// Altitude (may be null)
altitude: 760.5, // In meters
// Heading and speed (may be null)
heading: 180.5, // Heading in degrees
speed: 2.5, // Speed in m/s
// Time information
timestamp: 1704067200000, // Timestamp
formattedTime: "01/01/2024 10:00:00", // Formatted date/time
// Useful map URLs
googleMapsUrl: "https://www.google.com/maps?q=-23.5505,-46.6333",
osmUrl: "https://www.openstreetmap.org/?mlat=-23.5505&mlon=-46.6333&zoom=15",
// Information formatted for display
coordinates: "-23.550500, -46.633300", // Formatted coordinates
}Automatic Coordinate Population
Fields with geolocation classes are automatically populated when a location is obtained:
<!-- Automatically populated fields -->
<input type="text" class="form-control autocomplete latitude" readonly>
<input type="text" class="form-control autocomplete longitude" readonly>
<!-- Short versions -->
<input type="text" class="form-control autocomplete lat" readonly>
<input type="text" class="form-control autocomplete long" readonly>
<!-- Non-input elements are populated as well -->
<div class="autocomplete latitude">Waiting for location...</div>
<span class="autocomplete longitude">-</span>Autocomplete behavior:
- π Automatic: Populated every time
getLocation()orwatchLocation()returns a position - π Editable fields: If the field does not have
readonly, uses.setOrReplaceVal()(only fills it when empty or without.noreplace) - π Non-input elements: Divs, spans, etc. have their
text()updated - β‘ Real time: During continuous monitoring, fields are updated with every position change
Usage Example:
// When this function is called, the .autocomplete.latitude
// and .autocomplete.longitude fields are automatically populated!
InnerForm.getLocation().then(function(location) {
console.log('Fields populated automatically!');
// location.latitude -> .autocomplete.latitude
// location.longitude -> .autocomplete.longitude
});
// During monitoring, fields are updated in real time
var watchId = InnerForm.watchLocation(function(location) {
// Fields updated automatically with every change
console.log('Position updated:', location.coordinates);
});For applications that need to track location changes:
// Start monitoring
var watchId = InnerForm.watchLocation(
function(location) {
// Callback called on every position update
console.log('New position:', location.coordinates);
// Update the interface
$('#latitude').val(location.latitude);
$('#longitude').val(location.longitude);
$('#lastUpdate').text(location.formattedTime);
},
function(error) {
// Error callback
console.error('Monitoring error:', error.userMessage);
// Stop monitoring in case of error
InnerForm.clearLocationWatch(watchId);
},
{
enableHighAccuracy: true,
timeout: 10000, // Shorter monitoring timeout
maximumAge: 5000 // Smaller cache for fresher data
}
);
// Stop monitoring when needed
InnerForm.clearLocationWatch(watchId);Practical example of integrating form fields:
<form class="validate">
<div class="row">
<div class="col-md-6">
<label>Latitude</label>
<input type="text" id="latitude" class="form-control autocomplete latitude" readonly>
</div>
<div class="col-md-6">
<label>Longitude</label>
<input type="text" id="longitude" class="form-control autocomplete longitude" readonly>
</div>
<div class="col-md-12">
<button type="button" class="btn btn-primary" onclick="obterLocalizacao()">
π Get My Location
</button>
</div>
</div>
</form>
<script>
function obterLocalizacao() {
// Mostrar loading
$('#latitude').val('Obtendo...');
$('#longitude').val('Obtendo...');
InnerForm.getLocation()
.then(function(location) {
// Preencher campos
$('#latitude').val(location.latitude);
$('#longitude').val(location.longitude);
// Feedback visual
$('#latitude, #longitude').addClass('success');
})
.catch(function(error) {
// Clear fields on error
$('#latitude').val('');
$('#longitude').val('');
alert('Error: ' + error.userMessage);
});
}
</script>The geolocation API can fail for several reasons. The library provides user-friendly messages:
InnerForm.getLocation()
.catch(function(error) {
switch (error.error) {
case 'PERMISSION_DENIED':
alert('You must allow location access');
break;
case 'POSITION_UNAVAILABLE':
alert('Location is currently unavailable');
break;
case 'TIMEOUT':
alert('Tempo limite excedido. Tente novamente');
break;
case 'GEOLOCATION_NOT_SUPPORTED':
alert('Your browser does not support geolocation');
break;
default:
alert('Error desconhecido: ' + error.message);
}
});| Option | Type | Default | Description |
|---|---|---|---|
enableHighAccuracy |
boolean | true | Requests high accuracy (GPS when possible) |
timeout |
number | 10000 | Tempo limite em milissegundos |
maximumAge |
number | 60000 | Maximum acceptable cache age (ms) |
- HTTPS Required: Geolocation works only on HTTPS sites (or localhost)
- User Permission: The browser always requests permission
- Variable Accuracy: Depends on the device (GPS, WiFi, cell towers)
- Compatibility: Works in modern browsers that support the Geolocation API
See the included example files:
ExampleSimples.html- Basic implementationExampleGeolocalizacao.html- Complete interface with monitoringTestForm.html- Dedicated section with all features
// Main function - get a single location
InnerForm.getLocation(options) // Retorna Promise
// Continuous monitoring
InnerForm.watchLocation(successCallback, errorCallback, options) // Retorna watchId
// Stop monitoring
InnerForm.clearLocationWatch(watchId)<form class="validate">
<div class="row">
<!-- Dados Pessoais -->
<div class="col-md-6">
<label>Nome Completo *</label>
<input class="form-control obg alpha" placeholder="Digite seu nome">
</div>
<div class="col-md-6">
<label>Date of Birth (18+) *</label>
<input class="form-control mask date obg minage 18" placeholder="dd/mm/aaaa">
</div>
<div class="col-md-6">
<label>CPF *</label>
<input class="form-control mask cpf obg" placeholder="000.000.000-00">
</div>
<div class="col-md-6">
<label>Telefone *</label>
<input class="form-control mask tel obg" placeholder="(00) 00000-0000">
</div>
<!-- Email -->
<div class="col-md-12">
<label>E-mail *</label>
<input class="form-control email obg" placeholder="seu@email.com">
</div>
<!-- Address via CEP -->
<div class="col-md-4">
<label>CEP *</label>
<input class="form-control mask cep autocomplete obg" placeholder="00000-000">
</div>
<div class="col-md-6">
<label>Address</label>
<input class="form-control autocomplete address" readonly>
</div>
<div class="col-md-2">
<label>Number</label>
<input class="form-control autocomplete homenum">
</div>
<!-- Password -->
<div class="col-md-6">
<label>Password *</label>
<input id="password" type="password" class="form-control password strong minlen 8 obg">
</div>
<div class="col-md-6">
<label>Confirm Password *</label>
<input type="password" class="form-control eq #password obg">
</div>
</div>
<button type="submit" class="btn btn-primary">Cadastrar</button>
</form><form class="validate">
<!-- Card Details -->
<div class="col-md-8">
<label>Card Number</label>
<input class="form-control mask creditcard visa mastercard obg">
</div>
<div class="col-md-4">
<label>Validade</label>
<input class="form-control mask monthyear obg">
</div>
<!-- Valores -->
<div class="col-md-6">
<label>Minimum Amount</label>
<input class="form-control mask num after 0">
</div>
<div class="col-md-6">
<label>Maximum Amount</label>
<input class="form-control mask num 1 to 10000">
</div>
<!-- CNPJ da Empresa -->
<div class="col-md-12">
<label>CNPJ da Empresa</label>
<input class="form-control mask cnpj obg">
</div>
</form>// Validate an individual input
var isValid = $('#meuInput').isValid();
// Validate with custom classes
var isValid = $('#meuInput').isValid('obg', 'minlen 5');
// Validate the entire form
var isValid = $('#meuForm').isValid();
// Validate only fields that received focus
$('#meuForm').find(':input').addClass('prevFocus');
var isValid = $('#meuForm').isValid();Draft mode ignores the required rule so an incomplete form can be saved as a draft β while other validations (email, CPF, etc.) still apply.
1. HTML attribute β add data-draft to the form:
<form class="validate" data-draft>
<input type="text" class="obg email" placeholder="Email">
<button type="submit">Salvar rascunho</button>
</form>2. CSS class β add the draft class to the form:
<form class="validate draft">
<input type="text" class="obg email" placeholder="Email">
</form>3. Global flag β enable for all forms:
InnerForm.draftMode = true;4. Programmatically β via the API:
// Enable draft mode on a form
$('#meuForm').draft();
// Check if draft mode is active
var isDraft = $('#meuForm').isDraft(); // true
// Disable draft mode
$('#meuForm').undraft();- In draft mode, only the required rule (
obg,req,required) is ignored β empty required fields don't block the form. - All other validations still apply: a filled field with an invalid email, CPF, etc. keeps the form invalid even in draft mode.
- The
data-beforevalidatecallback,data-validcallbackanddata-aftervalidatecallbackstill run;data-invalidcallbackruns when a non-required validation fails. data-draft="false"explicitly disables draft mode for that form.- Static API:
InnerForm.draft(form),InnerForm.undraft(form),InnerForm.isDraft(form).
// Apply all masks
$('#meuForm').startMasks();
// Apply validations
$('#meuForm').startValidation();
// Specific masks
$('#telefone').phoneMask();
$('#data').dateMask();
$('#cpf').cpfMask();
$('#uuid').uuidMask(); InnerForm.searchViaCEP('01310-100', '123', 0, function(dadosEndereco) {
console.log('Address encontrado:', dadosEndereco);
// dadosEndereco contains: logradouro, bairro, localidade, uf, etc.
});// Validate with a 1-second delay
$('#input').validateOnType(1000);
// Validate in real time
$('#input').validateOnType(0);// Set the value only if the field is empty
// If not empty, only replaces it if it does not have the class 'noreplace'
$('#campo').setOrReplaceVal('New value');// Get a single location
InnerForm.getLocation()
.then(function(location) {
$('#latitude').val(location.latitude);
$('#longitude').val(location.longitude);
console.log('Accuracy:', location.accuracyFormatted);
})
.catch(function(error) {
console.error('Error:', error.userMessage);
});
// Get location with custom options
InnerForm.getLocation({
enableHighAccuracy: true,
timeout: 15000,
maximumAge: 60000
})
.then(function(location) {
// Use location data
window.open(location.googleMapsUrl, '_blank');
});
// Monitor location continuously
var watchId = InnerForm.watchLocation(
function(location) {
// Success callback - called on every update
$('#coordenadas').text(location.coordinates);
$('#precisao').text(location.accuracyFormatted);
},
function(error) {
// Error callback
console.error('Monitoring error:', error.userMessage);
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 5000
}
);
// Stop monitoring
InnerForm.clearLocationWatch(watchId);The library exposes several utility functions through the InnerFormValidation object. The main available functions are documented below:
Logs messages to the console when verbose mode is enabled.
InnerForm.verbose = true;
InnerForm.log('Mensagem de debug', dados);Logs error messages to the console when verbose mode is enabled.
InnerForm.error('Error found:', error);Logs warnings to the console when verbose mode is enabled.
InnerForm.warn('Aviso:', dados);Adds leading zeros to reach the specified length.
InnerForm.addLeadingZeros(123, 5); // "00123"
InnerForm.addLeadingZeros(-45, 4); // "-045"Calculates the check digit of barcodes using standard algorithms.
InnerForm.barcodeCheckSum("1234567"); // Returns the checksum numberCalculates age based on the birth date and reference date.
InnerForm.getAge("15/03/1990"); // Idade atual
InnerForm.getAge("15/03/1990", new Date("2025-01-01")); // Idade em 2025Expands a two-digit year (YY) to four digits (YYYY) based on the current century.
InnerForm.expandYear(25, 20, 5); // 2025 (near 2024)
InnerForm.expandYear(90, 20, 5); // 1990 (fora do range futuro)Validates whether a string is a valid UUID/GUID. Accepts flexible formats, not only RFC 4122.
InnerForm.validateUUID("ff2bc94c-8ce0-417f-08ce-08ddfce17182"); // true
InnerForm.validateUUID("12345678-1234-1234-1234-123456789abc"); // true
InnerForm.validateUUID("invalid-uuid"); // falseValidates Brazilian phone numbers (landline or mobile), ignoring masks, spaces, parentheses and hyphens. Requires at least 8 digits.
InnerForm.validatePhone("(11) 98765-4321"); // true
InnerForm.validatePhone("1132221234"); // true
InnerForm.validatePhone("1234567"); // false (menos de 8 dΓgitos)Validates Brazilian ZIP codes (CEP) with or without mask (8 digits).
InnerForm.validateCEP("01310100"); // true
InnerForm.validateCEP("01310-100"); // true (ignora a mΓ‘scara)
InnerForm.validateCEP("0131010"); // falseValidates whether a value is a valid latitude coordinate (-90 to +90 degrees).
InnerForm.validateLatitude("-23.550520"); // true
InnerForm.validateLatitude("45.5"); // true
InnerForm.validateLatitude("91"); // false (fora do limite)
InnerForm.validateLatitude("-90.5"); // false (fora do limite)Validates whether a value is a valid longitude coordinate (-180 to +180 degrees).
InnerForm.validateLongitude("-46.633308"); // true
InnerForm.validateLongitude("180"); // true
InnerForm.validateLongitude("181"); // false (fora do limite)
InnerForm.validateLongitude("-180.1"); // false (fora do limite)Validates whether a value contains a valid coordinate pair in several formats.
InnerForm.validateCoordinate("-23.550520,-46.633308"); // true
InnerForm.validateCoordinate("-23.5 -46.6"); // true
InnerForm.validateCoordinate("45;90"); // true
InnerForm.validateCoordinate("91,200"); // false (invalid coordinates)Parses and formats a partial short month/year string "MM/YY" during input.
InnerForm.parseShortMonthYearPartial("0325"); // "03/25"
InnerForm.parseShortMonthYearPartial("12231 02"); // "12/23 ~ 02"Parses and formats a partial month/year string "MM/YYYY" during input.
InnerForm.parseMonthYearPartial("032025"); // "03/2025"
InnerForm.parseMonthYearPartial("122024 01"); // "12/2024 ~ 01"Parses and formats a partial date string "DD/MM/YYYY" during input with smart validation.
InnerForm.parseDatePartial("25122024"); // "25/12/2024"
InnerForm.parseDatePartial("311220241 01"); // "31/12/2024 ~ 01"Validates whether a string represents a valid date no formato DD/MM/YYYY.
InnerForm.validDate("31/12/2023"); // true
InnerForm.validDate("31/02/2023"); // false
InnerForm.validDate("15/03/90"); // true (ano expandido)Converts a date string into a Date object.
InnerForm.parseDate("25/12/2023"); // Date object
InnerForm.parseDate("12/2023"); // 01/12/2023
InnerForm.parseDate("25/12/23"); // 25/12/2023 (ano expandido)Validates a date range no formato "DD/MM/YYYY ~ DD/MM/YYYY".
InnerForm.validDateRange("01/01/2023 ~ 31/12/2023"); // true
InnerForm.validDateRange("31/12/2023 ~ 01/01/2023"); // false (ordem)Validates a month/year range no formato "MM/YYYY ~ MM/YYYY".
InnerForm.validMonthYearRange("01/2023 ~ 12/2023"); // true
InnerForm.validMonthYearRange("12/2023 ~ 01/2023"); // falseValidates a month/year range abreviado no formato "MM/YY ~ MM/YY".
InnerForm.validShortMonthYearRange("01/23 ~ 12/23"); // true
InnerForm.validShortMonthYearRange("12/23 ~ 01/23"); // falseValida formatos de tempo (HH:MM:SS, HH:MM ou MM:SS).
InnerForm.validateTime("14:30:45"); // true
InnerForm.validateTime("14:30"); // true
InnerForm.validateTime("90:30", true); // true (MM:SS)
InnerForm.validateTime("25:30"); // falseValidates EAN barcodes (European Article Number) with checksum verification.
InnerForm.validateEAN("1234567890123"); // Validates whether the checksum is correctValidates that a string contains NONE of the specified characters.
InnerForm.validateNotChar("abc123", "xyz"); // true
InnerForm.validateNotChar("abc123", "abc"); // falseValidates that a string contains AT LEAST ONE of the specified characters.
InnerForm.validateAnyChar("password123", "123"); // true
InnerForm.validateAnyChar("password", "123"); // falseValidates that a string contains ALL of the specified characters.
InnerForm.validateAllChar("password123", "123"); // true
InnerForm.validateAllChar("password12", "123"); // falseValidates a short month/year range in the format "MM/YY ~ MM/YY".
InnerForm.validShortMonthYearRange("01/23 ~ 12/23"); // true
InnerForm.validShortMonthYearRange("12/23 ~ 01/23"); // false (primeira > segunda)Validates a month/year range in the format "MM/YYYY ~ MM/YYYY".
InnerForm.validMonthYearRange("01/2023 ~ 12/2023"); // true
InnerForm.validMonthYearRange("12/2023 ~ 01/2023"); // false (primeira > segunda)Valida um intervalo de datas no formato "DD/MM/YYYY ~ DD/MM/YYYY".
InnerForm.validDateRange("01/01/2023 ~ 31/12/2023"); // true
InnerForm.validDateRange("31/12/2023 ~ 01/01/2023"); // false (primeira > segunda)Validates whether a string is a valid UUID/GUID. Now accepts more flexible formats, not only RFC 4122.
InnerForm.validateUUID("ff2bc94c-8ce0-417f-08ce-08ddfce17182"); // true
InnerForm.validateUUID("12345678-1234-1234-1234-123456789abc"); // true
InnerForm.validateUUID("invalid-uuid"); // falseValidates that a value contains none of the specified characters.
InnerForm.validateNotChar("teste123", "!@#"); // true
InnerForm.validateNotChar("test@123", "@#"); // falseValidates that a value contains at least one of the specified characters.
InnerForm.validateAnyChar("teste123", "123"); // true
InnerForm.validateAnyChar("teste", "123"); // falseValidates that a value contains all of the specified characters.
InnerForm.validateAllChar("teste123!", "t3!"); // true
InnerForm.validateAllChar("teste", "tx"); // falseParses and formats a partial short month/year string "MM/YY" during input with smart validation.
InnerForm.parseShortMonthYearPartial("0325"); // "03/25"
InnerForm.parseShortMonthYearPartial("12231 02"); // "12/23 ~ 02"
InnerForm.parseShortMonthYearPartial("1323"); // "12/23" (limits month to 12)Parses and formats a partial month/year string "MM/YYYY" during input with smart validation.
InnerForm.parseMonthYearPartial("032025"); // "03/2025"
InnerForm.parseMonthYearPartial("122024 01"); // "12/2024 ~ 01"
InnerForm.parseMonthYearPartial("1320245"); // "12/2024 ~ 05" (limits month to 12)Parses and formats a partial date string "DD/MM/YYYY" during input with improved smart validation.
InnerForm.parseDatePartial("25122024"); // "25/12/2024"
InnerForm.parseDatePartial("311220241 01"); // "31/12/2024 ~ 01"
InnerForm.parseDatePartial("32122024"); // "31/12/2024" (limita dia a 31)
InnerForm.parseDatePartial("25132024"); // "25/12/2024" (limits month to 12)Applies a mask that removes all spaces from the input.
InnerForm.applyNoSpaceMask(document.getElementById('field'));Applies a mask that allows only letters and spaces.
InnerForm.applyAlphaMask(document.getElementById('nome'));Applies a mask that allows letters, numbers, and spaces.
InnerForm.applyAlphaNumericMask(document.getElementById('codigo'));Applies a Brazilian phone mask (automatic format).
InnerForm.applyPhoneMask(document.getElementById('telefone'));Formats a string of digits as a date (DD/MM/YYYY).
InnerForm.formatDate("25122023"); // "25/12/2023"Applies a date and time mask (DD/MM/YYYY HH:MM:SS).
InnerForm.applyDateTimeMask(document.getElementById('dataHora'));Applies a date-range mask (DD/MM/YYYY ~ DD/MM/YYYY).
InnerForm.applyDateRangeMask(document.getElementById('periodo'));Applies a month/year range mask (MM/YYYY ~ MM/YYYY) with smart parsing.
InnerForm.applyMonthYearRangeMask(document.getElementById('periodoMensal'));Applies a month/year range mask curto (MM/YY ~ MM/YY) with smart parsing.
InnerForm.applyShortMonthYearRangeMask(document.getElementById('periodoMensalCurto'));Applies a UUID/GUID mask with automatic hyphen formatting.
InnerForm.applyUUIDMask(document.getElementById('uuid'));Applies a mask for latitude coordinates with range validation (-90 a +90).
InnerForm.applyLatitudeMask(document.getElementById('latitude'));
// Supports the 'precision' class to limit decimal places
// Example: <input class="mask latitude precision 6">Applies a mask for longitude coordinates with range validation (-180 a +180).
InnerForm.applyLongitudeMask(document.getElementById('longitude'));
// Supports the 'precision' class to limit decimal places
// Example: <input class="mask longitude precision 4">Applies a month/year range mask abreviado (MM/YY ~ MM/YY).
InnerForm.applyShortMonthYearRangeMask(document.getElementById('periodoAbrev'));Validates a credit card number using the Luhn algorithm.
InnerForm.checkLuhn("4111111111111111"); // true (valid Visa)Identifies the credit card brand and validates the format.
InnerForm.validateCardBrand("4111111111111111"); // "visa"
InnerForm.validateCardBrand("5555555555554444"); // "mastercard"Validates Brazilian CNPJ with check-digit verification.
InnerForm.validateCNPJ("11.222.333/0001-81"); // true/falseAnalyzes password strength based on multiple criteria.
InnerForm.validatePassword("MinhaSenh@123");
// Retorna objeto com: score, hasUpper, hasLower, hasNumber, hasSymbolSearches for address data through the ViaCEP API and runs a callback with the results.
InnerForm.searchViaCEP("01310-100", "123", 500, function(dados) {
console.log("Logradouro:", dados.logradouro);
console.log("Bairro:", dados.bairro);
console.log("Cidade:", dados.localidade);
console.log("UF:", dados.uf);
});Gets the user's current location using the browser Geolocation API.
// Basic usage
InnerForm.getLocation()
.then(function(location) {
console.log('Latitude:', location.latitude);
console.log('Longitude:', location.longitude);
console.log('Accuracy:', location.accuracyFormatted);
console.log('Google Maps:', location.googleMapsUrl);
})
.catch(function(error) {
console.error('Error:', error.userMessage);
});
// With custom options
InnerForm.getLocation({
enableHighAccuracy: true, // High accuracy (GPS)
timeout: 15000, // Timeout de 15 segundos
maximumAge: 60000 // Cache de 60 segundos
});Response object:
{
latitude: -23.5505, // Latitude
longitude: -46.6333, // Longitude
accuracy: 65.0, // Accuracy em metros
accuracyFormatted: "65 metros", // Accuracy formatada
altitude: 760.5, // Altitude (pode ser null)
altitudeAccuracy: 12.0, // Accuracy da altitude
heading: 180.5, // Direction in degrees (may be null)
speed: 2.5, // Speed in m/s (may be null)
timestamp: 1704067200000, // Timestamp
formattedTime: "01/01/2024 10:00:00", // Formatted date/time
coordinates: "-23.550500, -46.633300", // Formatted coordinates
googleMapsUrl: "https://www.google.com/maps?q=-23.5505,-46.6333",
osmUrl: "https://www.openstreetmap.org/?mlat=-23.5505&mlon=-46.6333&zoom=15"
}Continuously monitors the user's location, calling the callback on every update.
var watchId = InnerForm.watchLocation(
function(location) {
// Success callback - called on every new position
console.log('New position:', location.coordinates);
$('#latitude').val(location.latitude);
$('#longitude').val(location.longitude);
},
function(error) {
// Error callback
console.error('Monitoring error:', error.userMessage);
alert('Error: ' + error.userMessage);
},
{
enableHighAccuracy: true,
timeout: 10000, // Shorter monitoring timeout
maximumAge: 5000 // Shorter cache for fresher data
}
);
// Returns a watcher ID for control
console.log('Watch ID:', watchId);Stops active location monitoring.
// Stop specific monitoring
InnerForm.clearLocationWatch(watchId);
// In SPAs, always stop monitoring when changing pages
window.addEventListener('beforeunload', function() {
InnerForm.clearLocationWatch(watchId);
});Error handling:
// Possible errors:
// - PERMISSION_DENIED: User denied permission
// - POSITION_UNAVAILABLE: Location unavailable
// - TIMEOUT: Time limit exceeded
// - GEOLOCATION_NOT_SUPPORTED: Browser does not support geolocation
// - UNKNOWN_ERROR: Unknown error
InnerForm.getLocation()
.catch(function(error) {
switch (error.error) {
case 'PERMISSION_DENIED':
alert('Permission denied. Enable location access in your browser.');
break;
case 'POSITION_UNAVAILABLE':
alert('Location is currently unavailable.');
break;
case 'TIMEOUT':
alert('Time limit exceeded. Try again.');
break;
default:
alert('Error: ' + error.userMessage);
}
});// Enable detailed logs
InnerForm.verbose = true;
// Validation timeout while typing (ms)
InnerForm.onTypeTimeout = 900;The functions can be used individually for custom validation or integration with other systems:
// Custom validation
function validarFormularioCustomizado() {
let isValid = true;
// Validate date
if (!InnerForm.validDate($('#data').val())) {
isValid = false;
alert('Invalid date!');
}
// Validate age
if (InnerForm.getAge($('#nascimento').val()) < 18) {
isValid = false;
alert('Underage!');
}
return isValid;
}
// Apply masks programmatically
$('#telefone').on('input', function() {
InnerForm.applyPhoneMask(this);
});
// Search for a postal code with error handling
InnerForm.searchViaCEP(cep, num, 0, function(dados) {
if (dados.erro) {
console.warn('Postal code not found');
return;
}
$('#endereco').val(dados.logradouro);
$('#bairro').val(dados.bairro);
$('#cidade').val(dados.localidade);
$('#uf').val(dados.uf);
});InnerFormValidation automatically adds CSS classes according to the field state:
/* Valid field (applied only to non-empty values) */
.success {
border-color: #28a745 !important;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
}
/* Invalid field */
.error {
border-color: #dc3545 !important;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
/* Bootstrap compatibility */
.has-error .form-control {
border-color: #dc3545;
}/* Style for required fields */
.obg::before {
content: "* ";
color: red;
}
/* Error animation */
.error {
animation: shake 0.5s;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/* Password strength indicator */
[data-pwstrength="4"] {
border-left: 5px solid #28a745; /* Verde - Forte */
}
[data-pwstrength="3"] {
border-left: 5px solid #ffc107; /* Yellow - Medium */
}
[data-pwstrength="2"],
[data-pwstrength="1"] {
border-left: 5px solid #dc3545; /* Red - Weak */
}After validation, some elements receive data-* attributes with useful information:
// Password strength (0-4)
var forcaSenha = $('#senha').attr('data-pwstrength');
// Detected card brand
var bandeiraCartao = $('#cartao').attr('data-flagcard');| Class | Description |
|---|---|
onkeyup |
Validar conforme digita (com delay) |
notonblur |
Do NOT validate on blur |
notonchange |
Do NOT validate when the value changes |
noreplace |
Autocomplete does not replace existing value |
<!-- Validate only when submitting the form -->
<input class="obg notonblur notonchange">
<!-- Validar em tempo real -->
<input class="obg onkeyup">
<!-- Postal code that does not replace an existing address -->
<input class="mask cep autocomplete noreplace"><script>
InnerForm.verbose = true; // Enables detailed console logs
</script>- β
Success:
InnerForm.log() β οΈ Warning:InnerForm.warn()- β Error:
InnerForm.error()
// In the browser console, you will see:
// InnerFormValidation: Validation started
// InnerFormValidation: PhoneMask started
// InnerFormValidation: Valid input detected- Class Order: Class order may matter in complex validations
- Performance: For large forms, consider using
notonbluron less critical fields - Compatibility: jQuery is optional; when present, legacy plugins are connected to
jQuery.fnwithout changing$ - Empty Fields: Most validations allow empty fields (except
obg/required) - Masks vs. Validation: Not every validation has an equivalent mask, and vice versa
- β
Coordinate masks
.mask.latitudeand.mask.longitude - β
Coordinate validations
.latitude,.longitude,.coordinate - β
Precision support with the
precision <number>class - β Automatic range validation (-90/+90 for latitude, -180/+180 for longitude)
- β Smart masks that accept comma or period decimal separators
- β
Short classes
.lat,.long,.lngto reduce code
- β Automatic autocomplete for geolocation coordinates
- β
Automatic population of
.autocomplete.latitudeand.autocomplete.longitudefields - β
Support for short classes
.autocomplete.latand.autocomplete.long - β
Dedicated example with
ExampleAutoComplete.html - β Seamless integration with existing geolocation functions
- β Automated masks for 30+ data types
- β Configurable real-time validation
- β Robust callbacks system
- β Address autocomplete via ViaCEP
- β Coordinate autocomplete via Geolocation
- β Complete, modern geolocation system
- β Credit card validation with 15+ brands
- β Password validation with configurable criteria
- β Full support for Brazilian documents
- β JavaScript API for programmatic validation
This project is licensed under the MIT License.
Contributions are welcome! Please open an issue or submit a pull request.
- Documentation: GitHub Pages
- Issues: GitHub Issues
- Examples: See the
TestForm.htmlfile for practical examples
- New function:
InnerForm.getLocation()- Gets the user's current location - New function:
InnerForm.watchLocation()- Continuously monitors location - New function:
InnerForm.clearLocationWatch()- Stops active monitoring - Advanced features:
- Modern Promise-based API
- Rich response object with coordinates, accuracy, altitude, and speed
- Automatic Google Maps and OpenStreetMap URLs
- Smart error handling with friendly messages
- Support for high-accuracy and configurable cache options
- Included examples:
ExampleSimples.html- Basic implementationExampleGeolocalizacao.html- Complete interface- Dedicated section in
TestForm.html
- Important fix: UUID validation now accepts more flexible formats
- Before: Only strict RFC 4122 UUIDs were accepted
- Now: Any structurally valid GUID is accepted, including .NET/C# GUIDs
- Example:
ff2bc94c-8ce0-417f-08ce-08ddfce17182now validates correctly β
- New function:
parseMonthYearPartial()- Smart formatting for MM/YYYY ~ MM/YYYY - New function:
parseShortMonthYearPartial()- Smart formatting for MM/YY ~ MM/YY - Improvements: Automatic month validation (maximum 12) and progressive formatting
- Experience: Range masks now have the same fluidity as date masks
- UUID mask: New mask for automatic GUID formatting
- Improved ranges:
monthyearrangeandshortmonthyearrangemasks completely rewritten - Progressive validation: Fields are validated as the user types, with immediate feedback
- Year expansion:
expandYear()function for smart YY β YYYY conversion - Robust validation: New validation functions for date and range values
- Compatibility: Maintains 100% compatibility with previous versions
β If this project was useful, don't forget to star it on GitHub!