A vanilla JavaScript plugin for automatic formatting of tax documents from different countries, similar to intl-tel-input but for documents like CPF, CNPJ, NIF, NIPC, SSN, EIN, etc.
- Vanilla JavaScript: No external dependencies
- Automatic Formatting: Applies masks as you type
- Smart Detection: Automatically identifies document type based on length
- Complete Validation: Real validation algorithms (check digits, etc.)
- Multi-country: Initial support for Brazil, Portugal and United States
- Country Selector: Interface similar to intl-tel-input with flags
- Visible Flag: Displays the selected country flag next to the input
- GeoIP Lookup: Automatic country detection via IP (optional)
- Complete API: Public methods for programmatic control
- Custom Events: Event listeners for country changes
- Configurable: Options to customize behavior and appearance
- Modular Validation System: Rules organized by country in separate files
- CPF (11 digits):
123.456.789-01
- CNPJ (14 digits):
12.345.678/0001-90
- NIF (9 digits):
123 456 789
- NIPC (9 digits):
123 456 789
- SSN (9 digits):
123-45-6789
- EIN (9 digits):
12-3456789
<script src="https://cdn.jsdelivr.net/npm/tax-document-input@latest/dist/tax-document-input.min.js"></script>
npm install tax-document-input
Download the tax-document-input.js
file and include in your project:
<script src="path/to/tax-document-input.js"></script>
<input type="text" id="tax-document" />
// Basic initialization
const taxInput = new TaxDocumentInput(document.getElementById('tax-document'));
// With options
const taxInput = new TaxDocumentInput(document.getElementById('tax-document'), {
placeholder: 'Enter your document',
defaultCountry: 'br',
autoGeolocate: false,
onlyCountries: ['br', 'pt']
});
Option | Type | Default | Description |
---|---|---|---|
placeholder |
string | 'Document Tax' |
Input placeholder text |
defaultCountry |
string | 'br' |
Default country (ISO2 code) |
autoGeolocate |
boolean | false |
Enable automatic country detection via IP |
onlyCountries |
array | [] |
Limit available countries (e.g. ['br', 'pt'] ) |
geoIpLookup |
function | null |
Custom function for IP country lookup |
const taxInput = new TaxDocumentInput(document.getElementById('tax-document'), {
placeholder: 'Taxpayer Number',
defaultCountry: 'pt',
autoGeolocate: true,
onlyCountries: ['br', 'pt', 'us'],
geoIpLookup: function(callback) {
// Custom implementation
fetch('https://your-geoip-api.com/lookup')
.then(res => res.json())
.then(data => callback(data.country))
.catch(() => callback('br')); // fallback
}
});
// Uses ipapi.co API by default
const taxInput = new TaxDocumentInput(document.getElementById('input'), {
autoGeolocate: true
});
// Similar to intl-tel-input
const taxInput = new TaxDocumentInput(document.getElementById('input'), {
autoGeolocate: true,
geoIpLookup: callback => {
fetch("https://ipapi.co/json")
.then(res => res.json())
.then(data => callback(data.country_code))
.catch(() => callback("br"));
}
});
Returns the selected country ISO2 code.
const country = taxInput.getSelectedCountry(); // 'br'
Returns complete data of the selected country.
const countryData = taxInput.getSelectedCountryData();
// { name: 'Brasil', iso2: 'br', flag: 'π§π·', documents: {...} }
Returns the current document type based on typed length.
const docType = taxInput.getCurrentDocumentType(); // 'cpf' or 'cnpj'
Sets the country programmatically.
taxInput.setCountry('pt'); // Set Portugal
Returns the formatted input value.
const value = taxInput.getValue(); // '123.456.789-01'
Returns only numbers, without formatting.
const cleanValue = taxInput.getCleanValue(); // '12345678901'
Checks if the document is complete and valid.
const isValid = taxInput.isValid(); // true/false
Returns complete document validation with details.
const validation = taxInput.validateDocument();
// {
// isValid: true,
// error: null,
// documentType: 'cpf',
// documentCategory: 'personal',
// country: 'br',
// details: { formatted: '123.456.789-01', type: 'personal' }
// }
Returns complete information about the current document type.
const info = taxInput.getCurrentDocumentInfo();
// {
// type: 'cpf',
// category: 'personal',
// length: 11,
// mask: 'XXX.XXX.XXX-XX',
// country: 'br'
// }
Fired when the country is changed.
document.getElementById('tax-document').addEventListener('countrychange', function(e) {
console.log('Previous country:', e.detail.previousCountry);
console.log('New country:', e.detail.newCountry);
console.log('Country data:', e.detail.countryData);
});
const input = document.getElementById('tax-document');
const taxInput = new TaxDocumentInput(input);
// Listener for country change
input.addEventListener('countrychange', function(e) {
console.log(`Country changed from ${e.detail.previousCountry} to ${e.detail.newCountry}`);
// Clear previous validations, change labels, etc.
updateFormLabels(e.detail.newCountry);
});
// Listener for input changes
input.addEventListener('input', function(e) {
const docType = taxInput.getCurrentDocumentType();
const isValid = taxInput.isValid();
console.log(`Document: ${docType}, Valid: ${isValid}`);
});
The plugin adds CSS classes that can be customized:
/* Main container */
.tax-document-input {
border: 2px solid #007bff;
border-radius: 8px;
}
/* Country button */
.tax-document-input__country-button {
background-color: #f8f9fa;
}
/* Input field */
.tax-document-input__field {
font-size: 16px;
padding: 12px;
}
/* Countries dropdown */
.tax-document-input__dropdown {
border: 2px solid #007bff;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
/* Dropdown item */
.tax-document-input__dropdown-item:hover {
background-color: #007bff;
color: white;
}
// Initialize multiple inputs at once
const instances = TaxDocumentInput.init('.tax-document-input', {
defaultCountry: 'br'
});
// Or individually
const personalDoc = new TaxDocumentInput(document.getElementById('personal-doc'), {
onlyCountries: ['br'],
placeholder: 'CPF'
});
const companyDoc = new TaxDocumentInput(document.getElementById('company-doc'), {
onlyCountries: ['br'],
placeholder: 'CNPJ'
});
const form = document.getElementById('registration-form');
const taxInput = new TaxDocumentInput(document.getElementById('tax-document'));
form.addEventListener('submit', function(e) {
if (!taxInput.isValid()) {
e.preventDefault();
alert('Invalid tax document!');
return;
}
// Send data
const formData = {
document: taxInput.getCleanValue(),
documentType: taxInput.getCurrentDocumentType(),
country: taxInput.getSelectedCountry()
};
console.log('Data to send:', formData);
});
// Vue.js
new Vue({
mounted() {
this.taxInput = new TaxDocumentInput(this.$refs.taxDocument, {
defaultCountry: 'br'
});
this.$refs.taxDocument.addEventListener('countrychange', (e) => {
this.selectedCountry = e.detail.newCountry;
});
},
beforeDestroy() {
if (this.taxInput) {
this.taxInput.destroy();
}
}
});
// React (in useEffect)
useEffect(() => {
const taxInput = new TaxDocumentInput(inputRef.current);
return () => {
taxInput.destroy();
};
}, []);
Soon, the plugin will support more countries. To contribute, create a pull request.
- Check if the plugin was initialized correctly
- Make sure the element exists in the DOM
- Check the console for JavaScript errors
- Check for CSS conflicts with z-index
- Make sure the parent container doesn't have
overflow: hidden
- HTTPS is recommended for external APIs
- Check if the ipapi.co API is accessible
- Configure a fallback in your custom
geoIpLookup
- Set
autoGeolocate: false
if not needed
MIT License - see the LICENSE file for details.
- Fork the project
- Create a feature branch (
git checkout -b feature/new-feature
) - Commit your changes (
git commit -am 'Add new feature'
) - Push to the branch (
git push origin feature/new-feature
) - Open a Pull Request
- π Issues: GitHub Issues
- π Documentation: GitHub Wiki
If you find this plugin useful, consider sponsoring its development:
- Initial release
- Support for Brazil, Portugal and United States
- Automatic formatting for CPF, CNPJ, NIF, NIPC, SSN, EIN
- Interface with country selector
- Complete API with public methods
- Custom events
- Optional geolocation