<style>
/* Estilos encapsulados para la calculadora */
.edp-calc-rfc-homo { display: flex; flex-direction: column; font-family: 'Silka', sans-serif; margin: 0 auto; padding: 10px; box-sizing: border-box; max-width: 100%; overflow-x: hidden; }
.edp-calc-rfc-homo .content-wrapper { display: flex; justify-content: space-between; gap: 20px; }
.edp-calc-rfc-homo .input-box, .edp-calc-rfc-homo .result-box { flex: 1; display: flex; flex-direction: column; justify-content: flex-start; border-radius: 16px; padding: 24px; box-sizing: border-box; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); }
.edp-calc-rfc-homo .input-box { background: linear-gradient(to bottom left, #EEF7FD, #F2F4F8 50%, #FFEDEA); }
.edp-calc-rfc-homo .result-box { background: linear-gradient(to bottom left, #E3F7EF, #E3F7EF 50%, #EDF6FC); } .edp-calc-rfc-homo h3 { margin-top: 0; margin-bottom: 15px; font-size: 1.25rem; color: #374151; display: flex; align-items: center; gap: 10px; font-weight: 600; }
.edp-calc-rfc-homo h3 span { background: #3D3A62; color: #fff; font-weight: bold; font-size: 1rem; display: inline-flex; width: 28px; height: 28px; border-radius: 50%; align-items: center; justify-content: center; } .edp-calc-rfc-homo .field { position: relative; margin-bottom: 15px; }
.edp-calc-rfc-homo label { text-align: left; font-size: 0.9rem; color: #4B5563; display: block; margin-bottom: 5px; font-weight: 500; }
.edp-calc-rfc-homo input { width: 100%; padding: 12px; font-size: 1rem; border: 1px solid #E5E7EB; border-radius: 8px; outline: none; box-sizing: border-box; transition: border-color 0.3s ease; background: #fff; }
.edp-calc-rfc-homo input:focus { border-color: #3D3A62; } .edp-calc-rfc-homo .btn-calcular { width: 100%; padding: 12px; font-size: 1rem; font-weight: bold; color: #fff; background: #3D3A62; border: none; border-radius: 8px; cursor: pointer; transition: background 0.3s ease; margin-top: 10px; }
.edp-calc-rfc-homo .btn-calcular:hover { background: #2D2A4A; } .edp-calc-rfc-homo .result-box ul { list-style: none; padding: 0; margin: 10px 0 0 0; color: #374151; }
.edp-calc-rfc-homo .result-box ul li { margin-bottom: 10px; font-size: 1.1rem; display: flex; flex-direction: column; align-items: flex-start; }
.edp-calc-rfc-homo .result-box ul li span { font-size: 1.5rem; font-weight: bold; color: #2A4365; margin-top: 5px; }
.edp-calc-rfc-homo .result-box ul li span.mensaje-inicial { font-size: 1rem; font-weight: normal; color: #6B7280; line-height: 1.4; } .edp-calc-rfc-homo #rfcResultado { font-size: 1.8rem; letter-spacing: 2px; font-family: 'Courier New', monospace; background: #fff; padding: 15px; border-radius: 8px; border: 2px dashed #3D3A62; color: #3D3A62; width: 100%; text-align: center; box-sizing: border-box; } .edp-calc-rfc-homo .btn-copiar { padding: 10px 20px; font-size: 0.9rem; font-weight: bold; color: #3D3A62; background: #fff; border: 2px solid #3D3A62; border-radius: 8px; cursor: pointer; transition: all 0.3s ease; margin-top: 15px; width: 100%; }
.edp-calc-rfc-homo .btn-copiar:hover { background: #3D3A62; color: #fff; } .edp-calc-rfc-homo .disclaimer-box { margin: 20px auto; padding: 15px 20px; box-sizing: border-box; background-color: #FDF8E8; border: 1px solid #F3E6C0; border-radius: 8px; font-size: 0.85rem; color: #4B5563; text-align: center; width: 100%; }
.edp-calc-rfc-homo .disclaimer-box a { color: #3D3A62; text-decoration: underline; } @media (max-width: 768px) { .edp-calc-rfc-homo .content-wrapper { flex-direction: column; } .edp-calc-rfc-homo #rfcResultado { font-size: 1.4rem; }
}
</style> <div class="edp-calc-rfc-homo"> <div class="content-wrapper"> <!-- Formulario --> <div class="input-box"> <h3><span>1</span> Introduce tus datos</h3> <form id="rfcForm"> <div class="field"> <label for="nombre">Nombre(s)</label> <input type="text" id="nombre" placeholder="Ej: Juan Carlos" required> </div> <div class="field"> <label for="apellidoPaterno">Apellido Paterno</label> <input type="text" id="apellidoPaterno" placeholder="Ej: García" required> </div> <div class="field"> <label for="apellidoMaterno">Apellido Materno</label> <input type="text" id="apellidoMaterno" placeholder="Ej: López"> </div> <div class="field"> <label for="fechaNacimiento">Fecha de Nacimiento (DD/MM/AAAA)</label> <input type="text" id="fechaNacimiento" placeholder="22/01/1985" maxlength="10" required> </div> <button type="submit" class="btn-calcular">Calcular RFC</button> </form> </div> <!-- Resultados --> <div class="result-box"> <h3><span>2</span> Tu RFC con Homoclave</h3> <ul> <li id="resultadoContainer" style="display:none;"> Tu RFC es: <span id="rfcResultado"></span> </li> <li id="mensajeInicial"> <span class="mensaje-inicial">Completa los datos y presiona "Calcular RFC"</span> </li> </ul> <button type="button" class="btn-copiar" id="btnCopiar" style="display:none;" onclick="copiarRFC()">Copiar RFC</button> </div> </div> <div class="disclaimer-box"> <strong>⚠️ Aviso:</strong> Este cálculo es una aproximación basada en el algoritmo estándar del SAT. Para trámites oficiales, verifica tu RFC en el <a href="https://www.sat.gob.mx/aplicacion/operacion/31274/consulta-tu-clave-de-rfc-mediante-curp" target="_blank">portal del SAT</a>. </div>
</div> <script>
document.addEventListener("DOMContentLoaded", function() { // Tablas y Constantes const toRemoveWords = ["PARA", "AND", "CON", "DEL", "LAS", "LOS", "MAC", "POR", "SUS", "THE", "VAN", "VON", "AL", "DE", "EL", "EN", "LA", "MC", "MI", "OF", "A", "E", "Y"]; const names = ["MARIA", "JOSE", "MA.", "MA", "J.", "J", "MARÍA"]; const inconvenientWords = ["BUEI", "BUEY", "CACA", "CACO", "CAGA", "CAGO", "CAKA", "CAKO", "COGE", "COJA", "COJE", "COJI", "COJO", "CULO", "FETO", "GUEY", "JOTO", "KACA", "KACO", "KAGA", "KAGO", "KOGE", "KOJO", "KAKA", "KULO", "MAME", "MAMO", "MEAR", "MEAS", "MEON", "MION", "MOCO", "MULA", "PEDA", "PEDO", "PENE", "PUTA", "PUTO", "QULO", "RATA", "RUIN"]; const equivalencesOne = {"0":"00","C":"13","P":"27","1":"01","D":"14","Q":"28","2":"02","E":"15","R":"29","3":"03","F":"16","S":"32","4":"04","G":"17","T":"33","5":"05","H":"18","U":"34","6":"06","I":"19","V":"35","7":"07","J":"21","W":"36","8":"08","K":"22","X":"37","9":"09","L":"23","Y":"38","&":"10","M":"24","Z":"39","A":"11","N":"25","Ñ":"40","B":"12","O":"26"}; const equivalencesTwo = {0:"1",17:"I",1:"2",18:"J",2:"3",19:"K",3:"4",20:"L",4:"5",21:"M",5:"6",22:"N",6:"7",23:"P",7:"8",24:"Q",8:"9",25:"R",9:"A",26:"S",10:"B",27:"T",11:"C",28:"U",12:"D",13:"E",14:"F",15:"G",16:"H",29:"V",30:"W",31:"X",32:"Y",33:"Z"}; const equivalencesLetters = {"0":"00","1":"01","2":"02","3":"03","4":"04","5":"05","6":"06","7":"07","8":"08","9":"09","A":"10","B":"11","C":"12","D":"13","E":"14","F":"15","G":"16","H":"17","I":"18","J":"19","K":"20","L":"21","M":"22","N":"23","O":"25","P":"26","Q":"27","R":"28","S":"29","T":"30","U":"31","V":"32","W":"33","X":"34","Y":"35","Z":"36","Ñ":"38"," ":"37","&":"24"}; const vowelWithAccent = {"Á":"A","É":"E","Í":"I","Ó":"O","Ú":"U"}; // Funciones de Limpieza function removeWords(words) { words = words.toUpperCase(); toRemoveWords.forEach(word => { // Usamos espacios alrededor para no borrar partes de palabras words = words.replace(new RegExp("\\b" + word + "\\b", "gi"), " "); }); return words.trim(); } function removeNames(name) { name = name.toUpperCase(); names.forEach(n => { name = name.replace(new RegExp("\\b" + n + "\\b", "gi"), " "); }); return removeWords(name.trim()); } function formatTextRFC(text) { if(!text) return ""; return text.toUpperCase().replace(/Á|É|Í|Ó|Ú/g, match => vowelWithAccent[match]); } function isVowel(char) { return "AEIOU".includes(char); } // Cálculos Matemáticos (Corregidos) function calculateQuotient(values, secuence) { let sum = 0; values.forEach(element => { const multiple = element[1]; // CORRECCIÓN: Multiplicación explícita sum += parseInt(element) * parseInt(multiple); }); // CORRECCIÓN: Multiplicación explícita sum += parseInt(secuence[0][1]) * parseInt(secuence[0][1]); const lastThreeDigits = sum % 1000; const quotient = Math.floor(lastThreeDigits / 34); const residue = lastThreeDigits % 34; return (equivalencesTwo[quotient] || "1") + (equivalencesTwo[residue] || "1"); } function calculateHomoClaveAndDigitalVerify(name) { const secuence = []; for (let i = 0; i < name.length; i++) { const character = name[i]; const value = equivalencesOne[character]; const add0 = i === 0 ? `0${value}` : character === " " ? "00" : value; if (add0) secuence.push(add0); } const values = []; const join = secuence.join("").substring(1); for (let i = 0; i < join.length - 1; i++) { values.push(join[i] + join[i + 1]); } return calculateQuotient(values, secuence); } function getHomoclave(rfc) { let product = 0; for (let i = 0; i < rfc.length; i++) { const character = rfc[i]; const value = equivalencesLetters[character]; if (value !== undefined) { const factor = 13 - i; product += parseInt(value) * parseInt(factor); } } const residue = product % 11; if (residue === 0) return "0"; if (residue > 0) { const total = Math.abs(residue - 11); if (total === 10) return "A"; return total.toString(); } return ""; } function removeInconvenientWords(text) { // Si los primeros 4 caracteres forman una palabra inconveniente const prefix = text.substring(0, 4); if (inconvenientWords.includes(prefix)) { return prefix.substring(0, 3) + "X" + text.substring(4); } return text; } // Generador Principal function generateRfc(name, lastNamePaternal, lastNameMaternal, birthdate) { const nameClean = formatTextRFC(name); const patClean = formatTextRFC(lastNamePaternal); const matClean = formatTextRFC(lastNameMaternal); // 1. Letras del Apellido Paterno // Primera letra const firstLetterPaternal = patClean.substring(0, 1); // Primera vocal interna let firstVowelPatternal = "X"; for (let i = 1; i < patClean.length; i++) { if (isVowel(patClean.charAt(i))) { firstVowelPatternal = patClean.charAt(i); break; } } // 2. Letra Apellido Materno (o X si no hay) const firstLetterMaternal = matClean ? matClean.substring(0, 1) : "X"; // 3. Letra Nombre (Filtrando Jose/Maria) const nameFiltered = removeNames(nameClean); const firstLetterName = nameFiltered.substring(0, 1); // 4. Fecha const dayBirth = birthdate.substring(0, 2); const monthBirth = birthdate.substring(3, 5); const yearBirth = birthdate.substring(8, 10); // Armamos las 4 letras iniciales let rfcLetters = `${firstLetterPaternal}${firstVowelPatternal}${firstLetterMaternal}${firstLetterName}`; // Filtro de palabras inconvenientes rfcLetters = removeInconvenientWords(rfcLetters); // Armamos RFC Base const rfcBase = `${rfcLetters}${yearBirth}${monthBirth}${dayBirth}`; // Calculamos Homoclave const fullNameForHomo = `${patClean} ${matClean || ""} ${nameClean}`.trim(); const clave = calculateHomoClaveAndDigitalVerify(fullNameForHomo); // RFC con Homoclave const rfcWithHomo = rfcBase + clave; // Dígito Verificador const identify = getHomoclave(rfcWithHomo); return rfcWithHomo + identify; } // Formato Fecha const fechaInput = document.getElementById('fechaNacimiento'); if(fechaInput){ fechaInput.addEventListener('input', function(e) { let valor = e.target.value.replace(/\D/g, ''); if (valor.length >= 2) valor = valor.substring(0, 2) + '/' + valor.substring(2); if (valor.length >= 5) valor = valor.substring(0, 5) + '/' + valor.substring(5, 9); e.target.value = valor; }); } // Submit const form = document.getElementById('rfcForm'); if(form){ form.addEventListener('submit', function(e) { e.preventDefault(); const nombre = document.getElementById('nombre').value.trim(); const apellidoPaterno = document.getElementById('apellidoPaterno').value.trim(); const apellidoMaterno = document.getElementById('apellidoMaterno').value.trim(); const fecha = document.getElementById('fechaNacimiento').value.trim(); if (!nombre || !apellidoPaterno || !fecha || fecha.length < 10) { alert('Por favor completa los campos obligatorios correctamente'); return; } const rfc = generateRfc(nombre, apellidoPaterno, apellidoMaterno, fecha); document.getElementById('rfcResultado').textContent = rfc; document.getElementById('resultadoContainer').style.display = 'block'; document.getElementById('mensajeInicial').style.display = 'none'; document.getElementById('btnCopiar').style.display = 'inline-block'; }); } // Copiar window.copiarRFC = function() { const rfc = document.getElementById('rfcResultado').textContent; navigator.clipboard.writeText(rfc).then(() => alert('RFC copiado: ' + rfc)); };
});
</script>