|
1 | | -// Project Registry |
| 1 | +// Project Registry |
2 | 2 | // Each project's HTML and logic lives in its own file under js/projects/ |
3 | 3 |
|
4 | 4 | function getProjectHTML(projectName) { |
@@ -4665,6 +4665,305 @@ bestDisplay.textContent = bestScore; |
4665 | 4665 | // MORSE CODE TRANSLATOR |
4666 | 4666 | // ============================================ |
4667 | 4667 | // ============================================ |
| 4668 | +function getMorseCodeHTML() { |
| 4669 | + return ` |
| 4670 | + <div class="project-content"> |
| 4671 | + <h2>📻 Morse Code Translator</h2> |
| 4672 | + <div class="morse-container"> |
| 4673 | + <div class="input-section"> |
| 4674 | + <div class="mode-toggle"> |
| 4675 | + <input type="radio" id="modeTextToMorse" name="translationMode" value="textToMorse" checked> |
| 4676 | + <label for="modeTextToMorse">Text to Morse</label> |
| 4677 | + <input type="radio" id="modeMorseToText" name="translationMode" value="morseToText"> |
| 4678 | + <label for="modeMorseToText">Morse to Text</label> |
| 4679 | + </div> |
| 4680 | + <label id="inputLabel" for="textInput">Enter Text:</label> |
| 4681 | + <textarea id="textInput" rows="4" placeholder="Type your message here..."></textarea> |
| 4682 | + <button class="btn-translate" id="translateBtn">📻 Translate to Morse</button> |
| 4683 | + </div> |
| 4684 | + |
| 4685 | + <div class="output-section"> |
| 4686 | + <h3>Translation Output:</h3> |
| 4687 | + <div class="morse-output" id="morseOutput"> |
| 4688 | + <p class="placeholder">Your translation will appear here...</p> |
| 4689 | + </div> |
| 4690 | + </div> |
| 4691 | + |
| 4692 | + <div class="morse-chart"> |
| 4693 | + <h4>📊 Morse Code Reference Chart</h4> |
| 4694 | + <div class="chart-grid" id="morseChart"></div> |
| 4695 | + </div> |
| 4696 | + </div> |
| 4697 | + </div> |
| 4698 | + |
| 4699 | + <style> |
| 4700 | + .morse-container { |
| 4701 | + padding: 2rem; |
| 4702 | + max-width: 800px; |
| 4703 | + margin: 0 auto; |
| 4704 | + } |
| 4705 | + |
| 4706 | + .input-section { |
| 4707 | + margin-bottom: 2rem; |
| 4708 | + } |
| 4709 | + |
| 4710 | + .mode-toggle { |
| 4711 | + display: flex; |
| 4712 | + gap: 1rem; |
| 4713 | + margin-bottom: 1.5rem; |
| 4714 | + } |
| 4715 | + |
| 4716 | + .mode-toggle input[type="radio"] { |
| 4717 | + display: none; |
| 4718 | + } |
| 4719 | + |
| 4720 | + .mode-toggle label { |
| 4721 | + padding: 0.5rem 1rem; |
| 4722 | + border: 2px solid var(--primary-color); |
| 4723 | + border-radius: 8px; |
| 4724 | + cursor: pointer; |
| 4725 | + font-weight: bold; |
| 4726 | + color: var(--text-color); |
| 4727 | + transition: var(--transition); |
| 4728 | + margin-bottom: 0 !important; |
| 4729 | + display: inline-block !important; |
| 4730 | + } |
| 4731 | + |
| 4732 | + .mode-toggle input[type="radio"]:checked + label { |
| 4733 | + background: var(--primary-color); |
| 4734 | + color: white; |
| 4735 | + } |
| 4736 | + |
| 4737 | + .input-section label { |
| 4738 | + display: block; |
| 4739 | + margin-bottom: 0.5rem; |
| 4740 | + font-size: 1.1rem; |
| 4741 | + font-weight: 600; |
| 4742 | + } |
| 4743 | + |
| 4744 | + .input-section textarea { |
| 4745 | + width: 100%; |
| 4746 | + padding: 1rem; |
| 4747 | + font-size: 1.1rem; |
| 4748 | + border: 2px solid var(--border-color); |
| 4749 | + border-radius: 10px; |
| 4750 | + background: var(--bg-color); |
| 4751 | + color: var(--text-color); |
| 4752 | + resize: vertical; |
| 4753 | + font-family: inherit; |
| 4754 | + } |
| 4755 | + |
| 4756 | + .btn-translate { |
| 4757 | + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); |
| 4758 | + color: white; |
| 4759 | + border: none; |
| 4760 | + padding: 1rem 2rem; |
| 4761 | + border-radius: 50px; |
| 4762 | + font-size: 1.1rem; |
| 4763 | + cursor: pointer; |
| 4764 | + margin-top: 1rem; |
| 4765 | + transition: var(--transition); |
| 4766 | + } |
| 4767 | + |
| 4768 | + .btn-translate:hover { |
| 4769 | + transform: scale(1.05); |
| 4770 | + box-shadow: 0 5px 20px rgba(99, 102, 241, 0.4); |
| 4771 | + } |
| 4772 | + |
| 4773 | + .output-section h3 { |
| 4774 | + margin-bottom: 1rem; |
| 4775 | + } |
| 4776 | + |
| 4777 | + .morse-output { |
| 4778 | + background: var(--surface-color); |
| 4779 | + border: 2px solid var(--border-color); |
| 4780 | + border-radius: 10px; |
| 4781 | + padding: 1.5rem; |
| 4782 | + min-height: 100px; |
| 4783 | + margin-bottom: 2rem; |
| 4784 | + } |
| 4785 | + |
| 4786 | + .morse-word { |
| 4787 | + display: inline-block; |
| 4788 | + margin: 0.5rem; |
| 4789 | + padding: 0.75rem 1rem; |
| 4790 | + background: var(--bg-color); |
| 4791 | + border-radius: 8px; |
| 4792 | + font-family: 'Courier New', monospace; |
| 4793 | + font-size: 1.2rem; |
| 4794 | + font-weight: bold; |
| 4795 | + color: var(--primary-color); |
| 4796 | + animation: fadeIn 0.3s ease; |
| 4797 | + } |
| 4798 | + |
| 4799 | + .placeholder { |
| 4800 | + color: var(--text-secondary); |
| 4801 | + text-align: center; |
| 4802 | + font-style: italic; |
| 4803 | + } |
| 4804 | + |
| 4805 | + .morse-chart { |
| 4806 | + margin-top: 3rem; |
| 4807 | + } |
| 4808 | + |
| 4809 | + .morse-chart h4 { |
| 4810 | + margin-bottom: 1rem; |
| 4811 | + text-align: center; |
| 4812 | + } |
| 4813 | + |
| 4814 | + .chart-grid { |
| 4815 | + display: grid; |
| 4816 | + grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); |
| 4817 | + gap: 0.5rem; |
| 4818 | + } |
| 4819 | + |
| 4820 | + .chart-item { |
| 4821 | + background: var(--surface-color); |
| 4822 | + border: 1px solid var(--border-color); |
| 4823 | + border-radius: 8px; |
| 4824 | + padding: 0.5rem; |
| 4825 | + text-align: center; |
| 4826 | + font-size: 0.9rem; |
| 4827 | + } |
| 4828 | + |
| 4829 | + .chart-char { |
| 4830 | + font-weight: bold; |
| 4831 | + font-size: 1.1rem; |
| 4832 | + color: var(--primary-color); |
| 4833 | + } |
| 4834 | + |
| 4835 | + .chart-morse { |
| 4836 | + font-family: 'Courier New', monospace; |
| 4837 | + color: var(--text-secondary); |
| 4838 | + margin-top: 0.25rem; |
| 4839 | + } |
| 4840 | + </style> |
| 4841 | + `; |
| 4842 | +} |
| 4843 | + |
| 4844 | +function initMorseCode() { |
| 4845 | + const morseCode = { |
| 4846 | + 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', |
| 4847 | + 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', |
| 4848 | + 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', |
| 4849 | + 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', |
| 4850 | + 'Y': '-.--', 'Z': '--..', '0': '-----', '1': '.----', '2': '..---', |
| 4851 | + '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', |
| 4852 | + '8': '---..', '9': '----.', '.': '.-.-.-', ',': '--..--', '?': '..--..', |
| 4853 | + '!': '-.-.--', '-': '-....-', '/': '-..-.', '@': '.--.-.', '(': '-.--.', |
| 4854 | + ')': '-.--.-', ' ': '/' |
| 4855 | + }; |
| 4856 | + |
| 4857 | + const textInput = document.getElementById('textInput'); |
| 4858 | + const translateBtn = document.getElementById('translateBtn'); |
| 4859 | + const morseOutput = document.getElementById('morseOutput'); |
| 4860 | + const morseChart = document.getElementById('morseChart'); |
| 4861 | + const modeTextToMorse = document.getElementById('modeTextToMorse'); |
| 4862 | + const modeMorseToText = document.getElementById('modeMorseToText'); |
| 4863 | + const inputLabel = document.getElementById('inputLabel'); |
| 4864 | + |
| 4865 | + // Switch Modes |
| 4866 | + modeTextToMorse.addEventListener('change', () => { |
| 4867 | + if (modeTextToMorse.checked) { |
| 4868 | + inputLabel.textContent = 'Enter Text:'; |
| 4869 | + textInput.placeholder = 'Type your message here...'; |
| 4870 | + textInput.value = ''; |
| 4871 | + morseOutput.innerHTML = '<p class="placeholder">Your translation will appear here...</p>'; |
| 4872 | + translateBtn.innerHTML = '📻 Translate to Morse'; |
| 4873 | + } |
| 4874 | + }); |
| 4875 | + |
| 4876 | + modeMorseToText.addEventListener('change', () => { |
| 4877 | + if (modeMorseToText.checked) { |
| 4878 | + inputLabel.textContent = 'Enter Morse Code:'; |
| 4879 | + textInput.placeholder = "Type morse code (separate letters with space, words with double spaces)..."; |
| 4880 | + textInput.value = ''; |
| 4881 | + morseOutput.innerHTML = '<p class="placeholder">Your translation will appear here...</p>'; |
| 4882 | + translateBtn.innerHTML = '📝 Translate to Text'; |
| 4883 | + } |
| 4884 | + }); |
| 4885 | + |
| 4886 | + Object.keys(morseCode).forEach(char => { |
| 4887 | + if (char !== ' ') { |
| 4888 | + const item = document.createElement('div'); |
| 4889 | + item.className = 'chart-item'; |
| 4890 | + item.innerHTML = ` |
| 4891 | + <div class="chart-char">${char}</div> |
| 4892 | + <div class="chart-morse">${morseCode[char]}</div> |
| 4893 | + `; |
| 4894 | + morseChart.appendChild(item); |
| 4895 | + } |
| 4896 | + }); |
| 4897 | + |
| 4898 | + function translate() { |
| 4899 | + const text = textInput.value.toUpperCase(); |
| 4900 | + if (!text.trim()) { |
| 4901 | + morseOutput.innerHTML = '<p class="placeholder">Please enter something to translate!</p>'; |
| 4902 | + return; |
| 4903 | + } |
| 4904 | + |
| 4905 | + morseOutput.innerHTML = ''; |
| 4906 | + |
| 4907 | + if (modeMorseToText.checked) { |
| 4908 | + // Morse to Text |
| 4909 | + const reverseMorseCode = {}; |
| 4910 | + Object.keys(morseCode).forEach(key => { |
| 4911 | + reverseMorseCode[morseCode[key]] = key; |
| 4912 | + }); |
| 4913 | + |
| 4914 | + const words = text.trim().split(/(?:\s*\/\s*|\s{2,})/); |
| 4915 | + |
| 4916 | + words.forEach((word, wordIndex) => { |
| 4917 | + const chars = word.trim().split(/\s+/); |
| 4918 | + let textWord = ''; |
| 4919 | + chars.forEach(char => { |
| 4920 | + if (reverseMorseCode[char]) { |
| 4921 | + textWord += reverseMorseCode[char]; |
| 4922 | + } else if (char) { |
| 4923 | + textWord += '?'; |
| 4924 | + } |
| 4925 | + }); |
| 4926 | + |
| 4927 | + if (textWord.trim()) { |
| 4928 | + const wordEl = document.createElement('div'); |
| 4929 | + wordEl.className = 'morse-word'; |
| 4930 | + wordEl.style.fontFamily = 'inherit'; |
| 4931 | + wordEl.style.letterSpacing = '2px'; |
| 4932 | + wordEl.textContent = textWord.trim(); |
| 4933 | + wordEl.style.animationDelay = `${wordIndex * 0.1}s`; |
| 4934 | + morseOutput.appendChild(wordEl); |
| 4935 | + } |
| 4936 | + }); |
| 4937 | + } else { |
| 4938 | + // Text to Morse |
| 4939 | + const words = text.split(' '); |
| 4940 | + |
| 4941 | + words.forEach((word, wordIndex) => { |
| 4942 | + let morseWord = ''; |
| 4943 | + for (let char of word) { |
| 4944 | + if (morseCode[char]) { |
| 4945 | + morseWord += morseCode[char] + ' '; |
| 4946 | + } |
| 4947 | + } |
| 4948 | + |
| 4949 | + if (morseWord.trim()) { |
| 4950 | + const wordEl = document.createElement('div'); |
| 4951 | + wordEl.className = 'morse-word'; |
| 4952 | + wordEl.textContent = morseWord.trim(); |
| 4953 | + wordEl.style.animationDelay = `${wordIndex * 0.1}s`; |
| 4954 | + morseOutput.appendChild(wordEl); |
| 4955 | + } |
| 4956 | + }); |
| 4957 | + } |
| 4958 | + } |
| 4959 | + |
| 4960 | + translateBtn.addEventListener('click', translate); |
| 4961 | + textInput.addEventListener('keypress', (e) => { |
| 4962 | + if (e.key === 'Enter' && e.ctrlKey) { |
| 4963 | + translate(); |
| 4964 | + } |
| 4965 | + }); |
| 4966 | +} |
4668 | 4967 | // PRIME ANALYZER |
4669 | 4968 | // ============================================ |
4670 | 4969 | function getPrimeAnalyzerHTML() { |
|
0 commit comments