Archivos de Código
index.html
app.js
document.addEventListener('DOMContentLoaded', () => {
// Initialize the translator
const translator = new Translator();
// DOM elements
const themeToggle = document.getElementById('theme-toggle');
const menuToggle = document.getElementById('menu-toggle');
const closeMenu = document.getElementById('close-menu');
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('overlay');
const sourceLanguageSelect = document.getElementById('source-language');
const targetLanguageSelect = document.getElementById('target-language');
const sourceText = document.getElementById('source-text');
const targetText = document.getElementById('target-text');
const translateBtn = document.getElementById('translate-btn');
const swapLanguagesBtn = document.getElementById('swap-languages');
const clearSourceBtn = document.getElementById('clear-source');
const copySourceBtn = document.getElementById('copy-source');
const copyTargetBtn = document.getElementById('copy-target');
const speakSourceBtn = document.getElementById('speak-source');
const speakTargetBtn = document.getElementById('speak-target');
// Theme management
function initTheme() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.setAttribute('data-theme', savedTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
}
}
function toggleTheme() {
const currentTheme = document.body.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.body.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
}
// Initialize theme
initTheme();
// Menu functionality
function toggleMenu() {
sidebar.classList.toggle('active');
overlay.classList.toggle('active');
document.body.style.overflow = sidebar.classList.contains('active') ? 'hidden' : '';
}
function closeMenuHandler() {
sidebar.classList.remove('active');
overlay.classList.remove('active');
document.body.style.overflow = '';
}
// Populate language dropdowns
window.populateLanguageDropdowns();
// Translation functionality
async function translateText() {
try {
const source = sourceLanguageSelect.value;
const target = targetLanguageSelect.value;
const text = sourceText.value;
if (!text.trim()) {
targetText.value = '';
return;
}
// Show loading state
targetText.value = 'Traduciendo...';
translateBtn.disabled = true;
const translatedText = await translator.translate(text, source, target);
targetText.value = translatedText;
} catch (error) {
targetText.value = `Error: ${error.message}`;
} finally {
translateBtn.disabled = false;
}
}
// Utility functions
function swapLanguages() {
// Only swap if source is not "auto"
if (sourceLanguageSelect.value !== 'auto') {
const sourceValue = sourceLanguageSelect.value;
const targetValue = targetLanguageSelect.value;
sourceLanguageSelect.value = targetValue;
targetLanguageSelect.value = sourceValue;
// Also swap the text content
const sourceContent = sourceText.value;
sourceText.value = targetText.value;
targetText.value = sourceContent;
}
}
function clearSource() {
sourceText.value = '';
targetText.value = '';
sourceText.focus();
}
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
// You could add a visual feedback here
} catch (error) {
console.error('Failed to copy text:', error);
}
}
function speakText(text, language) {
// Stop any ongoing speech
if (window.speechSynthesis.speaking) {
window.speechSynthesis.cancel();
}
if (!text) return;
const utterance = new SpeechSynthesisUtterance(text);
// Set language for speech if it's not "auto"
if (language !== 'auto') {
utterance.lang = language;
}
window.speechSynthesis.speak(utterance);
}
// Event listeners
menuToggle.addEventListener('click', toggleMenu);
closeMenu.addEventListener('click', closeMenuHandler);
overlay.addEventListener('click', closeMenuHandler);
themeToggle.addEventListener('click', toggleTheme);
translateBtn.addEventListener('click', translateText);
// Auto-translate after a shorter delay when typing (300ms instead of 1000ms)
let typingTimer;
sourceText.addEventListener('input', () => {
clearTimeout(typingTimer);
typingTimer = setTimeout(translateText, 300);
});
swapLanguagesBtn.addEventListener('click', swapLanguages);
clearSourceBtn.addEventListener('click', clearSource);
copySourceBtn.addEventListener('click', () => {
copyToClipboard(sourceText.value);
});
copyTargetBtn.addEventListener('click', () => {
copyToClipboard(targetText.value);
});
speakSourceBtn.addEventListener('click', () => {
speakText(sourceText.value, sourceLanguageSelect.value);
});
speakTargetBtn.addEventListener('click', () => {
speakText(targetText.value, targetLanguageSelect.value);
});
// Also translate when languages change
sourceLanguageSelect.addEventListener('change', translateText);
targetLanguageSelect.addEventListener('change', translateText);
});
languages.js
const LANGUAGES = {
"auto": "Detectar idioma",
"af": "Afrikáans",
"sq": "Albanés",
"am": "Amárico",
"ar": "Árabe",
"hy": "Armenio",
"az": "Azerí",
"eu": "Vasco",
"be": "Bielorruso",
"bn": "Bengalí",
"bs": "Bosnio",
"bg": "Búlgaro",
"ca": "Catalán",
"ceb": "Cebuano",
"zh-CN": "Chino (Simplificado)",
"zh-TW": "Chino (Tradicional)",
"co": "Corso",
"hr": "Croata",
"cs": "Checo",
"da": "Danés",
"nl": "Neerlandés",
"en": "Inglés",
"eo": "Esperanto",
"et": "Estonio",
"fi": "Finés",
"fr": "Francés",
"fy": "Frisón",
"gl": "Gallego",
"ka": "Georgiano",
"de": "Alemán",
"el": "Griego",
"gu": "Gujarati",
"ht": "Criollo haitiano",
"ha": "Hausa",
"haw": "Hawaiano",
"he": "Hebreo",
"hi": "Hindi",
"hmn": "Hmong",
"hu": "Húngaro",
"is": "Islandés",
"ig": "Igbo",
"id": "Indonesio",
"ga": "Irlandés",
"it": "Italiano",
"ja": "Japonés",
"jv": "Javanés",
"kn": "Canarés",
"kk": "Kazajo",
"km": "Jemer",
"rw": "Kinyarwanda",
"ko": "Coreano",
"ku": "Kurdo",
"ky": "Kirguís",
"lo": "Lao",
"la": "Latín",
"lv": "Letón",
"lt": "Lituano",
"lb": "Luxemburgués",
"mk": "Macedonio",
"mg": "Malgache",
"ms": "Malayo",
"ml": "Malayalam",
"mt": "Maltés",
"mi": "Maorí",
"mr": "Marathi",
"mn": "Mongol",
"my": "Myanmar (Birmano)",
"ne": "Nepalí",
"no": "Noruego",
"ny": "Nyanja (Chichewa)",
"or": "Odia (Oriya)",
"ps": "Pastún",
"fa": "Persa",
"pl": "Polaco",
"pt": "Portugués",
"pa": "Punjabi",
"ro": "Rumano",
"ru": "Ruso",
"sm": "Samoano",
"gd": "Gaélico escocés",
"sr": "Serbio",
"st": "Sesotho",
"sn": "Shona",
"sd": "Sindhi",
"si": "Cingalés",
"sk": "Eslovaco",
"sl": "Esloveno",
"so": "Somalí",
"es": "Español",
"su": "Sundanés",
"sw": "Suajili",
"sv": "Sueco",
"tl": "Tagalo (Filipino)",
"tg": "Tayiko",
"ta": "Tamil",
"tt": "Tártaro",
"te": "Telugu",
"th": "Tailandés",
"tr": "Turco",
"tk": "Turcomano",
"uk": "Ucraniano",
"ur": "Urdu",
"ug": "Uigur",
"uz": "Uzbeko",
"vi": "Vietnamita",
"cy": "Galés",
"xh": "Xhosa",
"yi": "Yiddish",
"yo": "Yoruba",
"zu": "Zulú"
};
// Make the function available globally
window.populateLanguageDropdowns = function() {
const sourceLanguageSelect = document.getElementById('source-language');
const targetLanguageSelect = document.getElementById('target-language');
// Clear existing options
sourceLanguageSelect.innerHTML = '';
targetLanguageSelect.innerHTML = '';
// Add options for source language (including auto-detect)
for (const [code, name] of Object.entries(LANGUAGES)) {
const option = document.createElement('option');
option.value = code;
option.textContent = name;
sourceLanguageSelect.appendChild(option);
// Don't add 'auto' to target language dropdown
if (code !== 'auto') {
const targetOption = document.createElement('option');
targetOption.value = code;
targetOption.textContent = name;
targetLanguageSelect.appendChild(targetOption);
}
}
// Set defaults
sourceLanguageSelect.value = 'auto';
targetLanguageSelect.value = 'es';
}
styles.css
:root {
--bg-color: #f5f5f5;
--text-color: #333;
--primary-color: #4285F4;
--secondary-color: #34A853;
--accent-color: #EA4335;
--surface-color: #ffffff;
--border-color: #e0e0e0;
--shadow-color: rgba(0, 0, 0, 0.1);
}
[data-theme="dark"] {
--bg-color: #1f1f1f;
--text-color: #f5f5f5;
--primary-color: #8AB4F8;
--secondary-color: #81C995;
--accent-color: #F28B82;
--surface-color: #2d2d2d;
--border-color: #444;
--shadow-color: rgba(0, 0, 0, 0.3);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
position: relative;
}
h1 {
font-size: 1.8rem;
color: var(--primary-color);
text-align: center;
margin: 0 auto;
}
#theme-toggle {
background: none;
border: none;
cursor: pointer;
font-size: 1.5rem;
color: var(--text-color);
}
#theme-toggle .fa-sun {
display: none;
}
[data-theme="dark"] #theme-toggle .fa-moon {
display: none;
}
[data-theme="dark"] #theme-toggle .fa-sun {
display: inline;
}
.translation-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 20px;
justify-content: center;
align-items: stretch;
}
.language-container {
flex: 1;
min-width: 280px;
display: flex;
flex-direction: column;
}
.select-container {
position: relative;
margin-bottom: 10px;
}
select {
width: 100%;
padding: 12px;
border: 1px solid var(--border-color);
border-radius: 8px;
background-color: var(--surface-color);
color: var(--text-color);
font-size: 1rem;
appearance: none;
cursor: pointer;
}
.select-container::after {
content: '\f107';
font-family: 'Font Awesome 5 Free';
font-weight: 900;
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
textarea {
width: 100%;
height: 200px;
padding: 15px;
border: 1px solid var(--border-color);
border-radius: 8px;
background-color: var(--surface-color);
color: var(--text-color);
font-size: 1rem;
resize: none;
flex-grow: 1;
}
#swap-languages {
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
align-self: center;
transition: transform 0.3s;
}
#swap-languages:hover {
transform: rotate(180deg);
}
.controls {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 10px;
}
.controls button {
background: none;
border: none;
color: var(--text-color);
font-size: 1rem;
cursor: pointer;
padding: 5px;
border-radius: 4px;
transition: background-color 0.2s;
}
.controls button:hover {
background-color: var(--border-color);
}
#translate-btn {
display: block;
width: 100%;
max-width: 200px;
margin: 0 auto;
padding: 12px;
background-color: var(--secondary-color);
color: white;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: bold;
cursor: pointer;
transition: background-color 0.2s;
}
#translate-btn:hover {
background-color: #2d9547;
}
.menu-toggle {
background: none;
border: none;
cursor: pointer;
font-size: 1.5rem;
color: var(--text-color);
padding: 5px;
}
.sidebar {
position: fixed;
top: 0;
left: -280px;
width: 280px;
height: 100%;
background-color: var(--surface-color);
z-index: 1000;
transition: left 0.3s ease;
box-shadow: 2px 0 10px var(--shadow-color);
overflow-y: auto;
}
.sidebar.active {
left: 0;
}
.sidebar-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
border-bottom: 1px solid var(--border-color);
}
.sidebar-header h3 {
margin: 0;
color: var(--primary-color);
}
#close-menu {
background: none;
border: none;
color: var(--text-color);
font-size: 1.2rem;
cursor: pointer;
}
.translator-links {
list-style: none;
padding: 0;
margin: 0;
}
.translator-links li {
border-bottom: 1px solid var(--border-color);
}
.translator-links li.active {
background-color: rgba(var(--primary-color-rgb), 0.1);
}
.translator-links a {
display: block;
padding: 15px 20px;
color: var(--text-color);
text-decoration: none;
transition: background-color 0.2s;
}
.translator-links a:hover {
background-color: var(--border-color);
}
#overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
display: none;
}
#overlay.active {
display: block;
}
footer {
margin-top: 50px;
text-align: center;
color: var(--text-color);
opacity: 0.7;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.translation-container {
flex-direction: column;
}
#swap-languages {
margin: 10px 0;
transform: rotate(90deg);
}
#swap-languages:hover {
transform: rotate(270deg);
}
h1 {
font-size: 1.5rem;
}
}
translator.js
class Translator {
constructor() {
this.baseUrl = 'https://translate.googleapis.com/translate_a/single';
}
async translate(text, sourceLanguage, targetLanguage) {
if (!text.trim()) {
return '';
}
try {
const params = new URLSearchParams({
client: 'gtx', // unofficial API
sl: sourceLanguage,
tl: targetLanguage,
dt: 't', // return translated text
q: text
});
const response = await fetch(`${this.baseUrl}?${params.toString()}`);
if (!response.ok) {
throw new Error(`Translation request failed with status: ${response.status}`);
}
const data = await response.json();
// Extract translated text from the response
// The response structure is complex nested arrays
let translatedText = '';
if (data && data[0]) {
for (const segment of data[0]) {
if (segment[0]) {
translatedText += segment[0];
}
}
}
return translatedText;
} catch (error) {
console.error('Translation error:', error);
throw new Error('Failed to translate text. Please try again later.');
}
}
}
morse/index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Traductor código Morse gratuito - Convierte texto a código Morse y viceversa">
<meta name="keywords" content="traductor morse, código morse, convertir morse, texto a morse">
<meta name="author" content="Traductor App">
<meta name="robots" content="index, follow">
<title>Traductor Morse</title>
<link rel="stylesheet" href="../styles.css">
<link rel="stylesheet" href="morse-styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div class="container">
<header>
<button id="menu-toggle" class="menu-toggle" aria-label="Toggle menu">
<i class="fas fa-bars"></i>
</button>
<h1>Traductor Morse</h1>
<button id="theme-toggle" aria-label="Toggle dark mode">
<i class="fas fa-moon"></i>
<i class="fas fa-sun"></i>
</button>
</header>
<nav id="sidebar" class="sidebar">
<div class="sidebar-header">
<h3>Traductores</h3>
<button id="close-menu" aria-label="Close menu">
<i class="fas fa-times"></i>
</button>
</div>
<ul class="translator-links">
<li><a href="../index.html">Traductor General</a></li>
<li><a href="../binary/index.html">Traductor Binario</a></li>
<li class="active"><a href="index.html">Traductor Morse</a></li>
<li><a href="../braille/index.html">Traductor Braille</a></li>
<li><a href="../leet/index.html">Traductor Leet</a></li>
</ul>
</nav>
<div id="overlay"></div>
<div class="translation-container">
<div class="language-container">
<h3>Texto</h3>
<textarea id="source-text" placeholder="Escribe texto para convertir a código Morse..."></textarea>
<div class="controls">
<button id="clear-source" aria-label="Borrar texto"><i class="fas fa-times"></i></button>
<button id="copy-source" aria-label="Copiar texto"><i class="fas fa-copy"></i></button>
</div>
</div>
<button id="swap-languages" aria-label="Intercambiar">
<i class="fas fa-exchange-alt"></i>
</button>
<div class="language-container">
<h3>Morse</h3>
<textarea id="target-text" placeholder="Código Morse..." readonly></textarea>
<div class="controls">
<button id="copy-target" aria-label="Copiar traducción"><i class="fas fa-copy"></i></button>
<button id="play-morse" aria-label="Reproducir Morse"><i class="fas fa-play"></i></button>
</div>
</div>
</div>
<button id="translate-btn">Convertir</button>
<footer>
<p>Traductor Morse - Convierte texto a código Morse y viceversa</p>
</footer>
</div>
<script src="morse-translator.js"></script>
<script src="morse-app.js"></script>
</body>
</html>
morse/morse-app.js
document.addEventListener('DOMContentLoaded', () => {
// Initialize the translator
const morseTranslator = new MorseTranslator();
// DOM elements
const themeToggle = document.getElementById('theme-toggle');
const menuToggle = document.getElementById('menu-toggle');
const closeMenu = document.getElementById('close-menu');
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('overlay');
const sourceText = document.getElementById('source-text');
const targetText = document.getElementById('target-text');
const translateBtn = document.getElementById('translate-btn');
const swapLanguagesBtn = document.getElementById('swap-languages');
const clearSourceBtn = document.getElementById('clear-source');
const copySourceBtn = document.getElementById('copy-source');
const copyTargetBtn = document.getElementById('copy-target');
const playMorseBtn = document.getElementById('play-morse');
// Theme management
function initTheme() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.setAttribute('data-theme', savedTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
}
}
function toggleTheme() {
const currentTheme = document.body.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.body.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
}
// Menu functionality
function toggleMenu() {
sidebar.classList.toggle('active');
overlay.classList.toggle('active');
document.body.style.overflow = sidebar.classList.contains('active') ? 'hidden' : '';
}
function closeMenuHandler() {
sidebar.classList.remove('active');
overlay.classList.remove('active');
document.body.style.overflow = '';
}
// Initialize theme
initTheme();
// Translation functionality
function translate() {
try {
const text = sourceText.value;
if (!text.trim()) {
targetText.value = '';
return;
}
// Check if source is morse or text
const isMorse = /^[.\-/ ]+$/.test(text.trim());
if (isMorse) {
targetText.value = morseTranslator.morseToText(text);
} else {
targetText.value = morseTranslator.textToMorse(text);
}
} catch (error) {
targetText.value = `Error: ${error.message}`;
}
}
// Utility functions
function swapLanguages() {
const sourceContent = sourceText.value;
sourceText.value = targetText.value;
targetText.value = sourceContent;
}
function clearSource() {
sourceText.value = '';
targetText.value = '';
sourceText.focus();
}
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
// You could add a visual feedback here
} catch (error) {
console.error('Failed to copy text:', error);
}
}
function playMorse() {
const morse = targetText.value;
if (morse && /^[.\-/ ]+$/.test(morse)) {
morseTranslator.playMorse(morse);
}
}
// Event listeners
menuToggle.addEventListener('click', toggleMenu);
closeMenu.addEventListener('click', closeMenuHandler);
overlay.addEventListener('click', closeMenuHandler);
themeToggle.addEventListener('click', toggleTheme);
translateBtn.addEventListener('click', translate);
// Auto-translate after a shorter delay when typing
let typingTimer;
sourceText.addEventListener('input', () => {
clearTimeout(typingTimer);
typingTimer = setTimeout(translate, 300);
});
swapLanguagesBtn.addEventListener('click', swapLanguages);
clearSourceBtn.addEventListener('click', clearSource);
copySourceBtn.addEventListener('click', () => {
copyToClipboard(sourceText.value);
});
copyTargetBtn.addEventListener('click', () => {
copyToClipboard(targetText.value);
});
playMorseBtn.addEventListener('click', playMorse);
});
morse/morse-styles.css
/* Additional styles specific to morse translator */
.language-container h3 {
margin-bottom: 10px;
color: var(--primary-color);
}
#play-morse {
background-color: var(--secondary-color);
color: white;
border-radius: 4px;
padding: 5px 10px;
}
#play-morse:hover {
background-color: #2d9547;
}
morse/morse-translator.js
class MorseTranslator {
constructor() {
this.morseMap = {
'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..',
'0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-',
'5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.',
'.': '.-.-.-', ',': '--..--', '?': '..--..', "'": '.----.', '!': '-.-.--',
'/': '-..-.', '(': '-.--.', ')': '-.--.-', '&': '.-...', ':': '---...',
';': '-.-.-.', '=': '-...-', '+': '.-.-.', '-': '-....-', '_': '..--.-',
'"': '.-..-.', '$': '...-..-', '@': '.--.-.', ' ': '/'
};
// Create reverse mapping (morse to text)
this.textMap = {};
for (const [key, value] of Object.entries(this.morseMap)) {
this.textMap[value] = key;
}
}
textToMorse(text) {
return text.toUpperCase().split('').map(char => {
return this.morseMap[char] || char;
}).join(' ');
}
morseToText(morse) {
return morse.split(' ').map(code => {
return this.textMap[code] || code;
}).join('');
}
playMorse(morse) {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const dotDuration = 80; // milliseconds
const playTone = (duration, pause) => {
return new Promise(resolve => {
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.value = 700;
oscillator.type = 'sine';
oscillator.start();
setTimeout(() => {
oscillator.stop();
setTimeout(resolve, pause);
}, duration);
});
};
const playSequence = async (sequence) => {
for (const char of sequence) {
if (char === '.') {
await playTone(dotDuration, dotDuration);
} else if (char === '-') {
await playTone(dotDuration * 3, dotDuration);
} else if (char === ' ') {
await new Promise(resolve => setTimeout(resolve, dotDuration * 3));
} else if (char === '/') {
await new Promise(resolve => setTimeout(resolve, dotDuration * 7));
}
}
};
playSequence(morse);
}
}
binary/index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Traductor binario gratuito - Convierte texto a código binario y viceversa">
<meta name="keywords" content="traductor binario, código binario, convertir binario, texto a binario">
<meta name="author" content="Traductor App">
<meta name="robots" content="index, follow">
<title>Traductor Binario</title>
<link rel="stylesheet" href="../styles.css">
<link rel="stylesheet" href="binary-styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div class="container">
<header>
<button id="menu-toggle" class="menu-toggle" aria-label="Toggle menu">
<i class="fas fa-bars"></i>
</button>
<h1>Traductor Binario</h1>
<button id="theme-toggle" aria-label="Toggle dark mode">
<i class="fas fa-moon"></i>
<i class="fas fa-sun"></i>
</button>
</header>
<nav id="sidebar" class="sidebar">
<div class="sidebar-header">
<h3>Traductores</h3>
<button id="close-menu" aria-label="Close menu">
<i class="fas fa-times"></i>
</button>
</div>
<ul class="translator-links">
<li><a href="../index.html">Traductor General</a></li>
<li class="active"><a href="index.html">Traductor Binario</a></li>
<li><a href="../morse/index.html">Traductor Morse</a></li>
<li><a href="../braille/index.html">Traductor Braille</a></li>
<li><a href="../leet/index.html">Traductor Leet</a></li>
</ul>
</nav>
<div id="overlay"></div>
<div class="translation-container">
<div class="language-container">
<h3>Texto</h3>
<textarea id="source-text" placeholder="Escribe texto para convertir a binario..."></textarea>
<div class="controls">
<button id="clear-source" aria-label="Borrar texto"><i class="fas fa-times"></i></button>
<button id="copy-source" aria-label="Copiar texto"><i class="fas fa-copy"></i></button>
</div>
</div>
<button id="swap-languages" aria-label="Intercambiar">
<i class="fas fa-exchange-alt"></i>
</button>
<div class="language-container">
<h3>Binario</h3>
<textarea id="target-text" placeholder="Código binario..." readonly></textarea>
<div class="controls">
<button id="copy-target" aria-label="Copiar traducción"><i class="fas fa-copy"></i></button>
</div>
</div>
</div>
<button id="translate-btn">Convertir</button>
<footer>
<p>Traductor binario - Convierte texto a código binario y viceversa</p>
</footer>
</div>
<script src="binary-translator.js"></script>
<script src="binary-app.js"></script>
</body>
</html>
binary/binary-app.js
document.addEventListener('DOMContentLoaded', () => {
// Initialize the translator
const binaryTranslator = new BinaryTranslator();
// DOM elements
const themeToggle = document.getElementById('theme-toggle');
const menuToggle = document.getElementById('menu-toggle');
const closeMenu = document.getElementById('close-menu');
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('overlay');
const sourceText = document.getElementById('source-text');
const targetText = document.getElementById('target-text');
const translateBtn = document.getElementById('translate-btn');
const swapLanguagesBtn = document.getElementById('swap-languages');
const clearSourceBtn = document.getElementById('clear-source');
const copySourceBtn = document.getElementById('copy-source');
const copyTargetBtn = document.getElementById('copy-target');
// Theme management
function initTheme() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.setAttribute('data-theme', savedTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
}
}
function toggleTheme() {
const currentTheme = document.body.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.body.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
}
// Menu functionality
function toggleMenu() {
sidebar.classList.toggle('active');
overlay.classList.toggle('active');
document.body.style.overflow = sidebar.classList.contains('active') ? 'hidden' : '';
}
function closeMenuHandler() {
sidebar.classList.remove('active');
overlay.classList.remove('active');
document.body.style.overflow = '';
}
// Initialize theme
initTheme();
// Translation functionality
function translate() {
try {
const text = sourceText.value;
if (!text.trim()) {
targetText.value = '';
return;
}
// Check if source is binary or text
const isBinary = /^[01\s]+$/.test(text.trim());
if (isBinary) {
targetText.value = binaryTranslator.binaryToText(text);
} else {
targetText.value = binaryTranslator.textToBinary(text);
}
} catch (error) {
targetText.value = `Error: ${error.message}`;
}
}
// Utility functions
function swapLanguages() {
const sourceContent = sourceText.value;
sourceText.value = targetText.value;
targetText.value = sourceContent;
}
function clearSource() {
sourceText.value = '';
targetText.value = '';
sourceText.focus();
}
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
// You could add a visual feedback here
} catch (error) {
console.error('Failed to copy text:', error);
}
}
// Event listeners
menuToggle.addEventListener('click', toggleMenu);
closeMenu.addEventListener('click', closeMenuHandler);
overlay.addEventListener('click', closeMenuHandler);
themeToggle.addEventListener('click', toggleTheme);
translateBtn.addEventListener('click', translate);
// Auto-translate after a shorter delay when typing
let typingTimer;
sourceText.addEventListener('input', () => {
clearTimeout(typingTimer);
typingTimer = setTimeout(translate, 300);
});
swapLanguagesBtn.addEventListener('click', swapLanguages);
clearSourceBtn.addEventListener('click', clearSource);
copySourceBtn.addEventListener('click', () => {
copyToClipboard(sourceText.value);
});
copyTargetBtn.addEventListener('click', () => {
copyToClipboard(targetText.value);
});
});
binary/binary-styles.css
/* Additional styles specific to binary translator */
.language-container h3 {
margin-bottom: 10px;
color: var(--primary-color);
}
binary/binary-translator.js
class BinaryTranslator {
textToBinary(text) {
return text.split('').map(char => {
const binary = char.charCodeAt(0).toString(2);
// Ensure each binary representation is 8 bits long
return binary.padStart(8, '0');
}).join(' ');
}
binaryToText(binary) {
// Remove any extra spaces and split by space
const cleanBinary = binary.trim().replace(/\s+/g, ' ');
// Check if input is valid binary
if (!/^[01\s]+$/.test(cleanBinary)) {
throw new Error('El texto no es un código binario válido');
}
try {
return cleanBinary.split(' ').map(bin => {
if (bin.length === 0) return '';
return String.fromCharCode(parseInt(bin, 2));
}).join('');
} catch (error) {
throw new Error('Error al convertir binario a texto');
}
}
}
README.txt
Puedes ver y usar el traductor desde Github aquí:
https://octavioproyt456.github.io/Translator/
Comentarios (2)
Inicia sesión para comentar
Poquitos archivos XDDD