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