feat: update style

This commit is contained in:
2026-01-02 17:45:41 +01:00
parent fdc753b32f
commit a7d189d89d
9 changed files with 1336 additions and 493 deletions

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,66 +9,199 @@
<script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles -->
<style>
/* Einfacher Lade-Spinner */
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader {
border: 4px solid rgba(168, 85, 247, 0.3); /* Lila transparent */
border-left-color: #a855f7; /* Lila */
border: 4px solid rgba(168, 85, 247, 0.1);
/* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Ergebnis-Pre-Formatierung */
.result-pre {
white-space: pre-wrap;
word-break: break-all;
font-family: monospace;
background-color: #1f2937; /* Dunkelgrau */
color: #d1d5db; /* Hellgrau */
font-family: 'Courier New', Courier, monospace;
background-color: rgba(0, 0, 0, 0.3);
color: #e5e7eb;
padding: 1rem;
border-radius: 0.375rem; /* rounded-md */
border-radius: 0.375rem;
max-height: 400px;
overflow-y: auto;
font-size: 0.875rem; /* text-sm */
font-size: 0.875rem;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
/* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; }
nav a { color: #c4b5fd; text-decoration: none; white-space: nowrap; }
nav a:hover { color: #a78bfa; text-decoration: underline; }
header { background-color: #374151; padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
@media (min-width: 768px) { header { flex-direction: row; justify-content: space-between; } }
header h1 { font-size: 1.5rem; font-weight: bold; color: #e5e7eb; }
.hidden { display: none; }
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
</style>
</head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header>
<h1>uTools Network Suite</h1>
<body
class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav>
<ul>
<li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="dns-lookup.html" class="active-link">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li>
</ul>
</nav>
</header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6">
<div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 text-center">DNS Lookup</h1>
<h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">DNS Lookup</h1>
<!-- Bereich für DNS Lookup -->
<div class="mt-8 p-4 bg-gray-700 rounded">
<div class="flex flex-col sm:flex-row gap-2 mb-4">
<div class="mt-8 p-6 glass-card rounded-xl">
<div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="dns-domain-input" placeholder="Enter domain name (e.g., google.com)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono">
<select id="dns-type-select" class="px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent">
class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<select id="dns-type-select"
class="px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent cursor-pointer">
<option value="ANY">ANY</option>
<option value="A">A</option>
<option value="AAAA">AAAA</option>
@@ -80,30 +214,38 @@
<option value="PTR">PTR (Reverse)</option>
</select>
<button id="dns-lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out">
class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Lookup DNS
</button>
</div>
<div id="dns-lookup-error" class="text-red-400 mb-4 hidden"></div>
<div id="dns-lookup-results-section" class="hidden mt-4 border-t border-gray-600 pt-4">
<h3 class="text-lg font-semibold text-purple-300 mb-2">DNS Results for: <span id="dns-lookup-query" class="font-mono text-purple-400"></span></h3>
<div id="dns-lookup-loader" class="loader hidden mb-2"></div>
<pre id="dns-lookup-output" class="result-pre"></pre> <!-- Ergebnisbereich -->
<div id="dns-lookup-error"
class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded"></div>
<div id="dns-lookup-results-section" class="hidden mt-6 border-t border-gray-700/50 pt-6 fade-in">
<h3 class="text-lg font-semibold text-purple-300 mb-4 flex items-center gap-2">
<div class="w-1.5 h-6 bg-purple-500 rounded-full"></div>
DNS Results for: <span id="dns-lookup-query" class="font-mono text-purple-400 ml-1"></span>
</h3>
<div id="dns-lookup-loader" class="loader hidden mb-4"></div>
<pre id="dns-lookup-output" class="result-pre custom-scrollbar"></pre> <!-- Ergebnisbereich -->
</div>
</div>
<!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div>
<!-- Globaler Fehlerbereich -->
<div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<!-- Footer für Version -->
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p>
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p>
</footer>
<!-- Footer für Version -->
<footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de"
class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
</div>
<!-- Eigene JS-Logik für diese Seite -->
<script src="dns-lookup.js"></script>
</body>
</html>

View File

@@ -44,6 +44,11 @@ document.addEventListener('DOMContentLoaded', () => {
* @param {function} displayFn - Funktion zur Formatierung und Anzeige der Daten im outputElement.
*/
async function fetchAndDisplay(endpoint, params, resultsSection, loaderElement, errorElement, queryElement, outputElement, displayFn) {
// Reset animation
resultsSection.classList.remove('fade-in');
void resultsSection.offsetWidth; // Trigger reflow
resultsSection.classList.add('fade-in');
resultsSection.classList.remove('hidden');
loaderElement.classList.remove('hidden');
errorElement.classList.add('hidden');

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,87 +9,299 @@
<script src="https://cdn.tailwindcss.com"></script>
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<!-- Eigene Styles -->
<style>
/* Container für Karten müssen eine Höhe haben */
#map { height: 300px; }
#lookup-map { height: 250px; } /* Höhe für Lookup-Karte */
#map {
height: 300px;
}
#lookup-map {
height: 250px;
}
/* Höhe für Lookup-Karte */
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader {
border: 4px solid rgba(168, 85, 247, 0.3); /* Lila transparent */
border-left-color: #a855f7; /* Lila */
border: 4px solid rgba(168, 85, 247, 0.1);
/* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
/* gray-900 mit Opacity */
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
/* gray-800 mit Opacity */
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Basis für Glitch-Effekt (Beispiel: Text-Schatten) */
.glitch-text:hover {
text-shadow:
1px 1px 0px rgba(168, 85, 247, 0.7), /* Lila */
-1px -1px 0px rgba(76, 29, 149, 0.7); /* Dunkleres Lila */
2px 2px 0px rgba(168, 85, 247, 0.4),
-2px -2px 0px rgba(236, 72, 153, 0.4);
}
/* Klickbarer IP-Cursor und Link-Styling */
#ip-address-link {
cursor: pointer;
text-decoration: none; /* Standard-Link-Unterstreichung entfernen */
cursor: pointer;
text-decoration: none;
position: relative;
display: inline-block;
transition: color 0.3s ease;
}
#ip-address-link:hover {
text-decoration: underline; /* Unterstreichung beim Hover */
#ip-address-link::after {
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 2px;
bottom: 0;
left: 0;
background-color: #d8b4fe;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
#ip-address-link:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
}
/* Traceroute Output Formatierung */
#traceroute-output pre, .result-pre { /* Gemeinsamer Stil für <pre> */
white-space: pre-wrap; /* Zeilenumbruch */
word-break: break-all; /* Lange Zeilen umbrechen */
font-family: monospace;
background-color: #1f2937; /* Dunkelgrau */
color: #d1d5db; /* Hellgrau */
#traceroute-output pre,
.result-pre {
white-space: pre-wrap;
word-break: break-all;
font-family: 'Courier New', Courier, monospace;
/* Mehr Terminal-Feeling */
background-color: rgba(0, 0, 0, 0.3);
/* Transparenter */
color: #e5e7eb;
padding: 1rem;
border-radius: 0.375rem; /* rounded-md */
border-radius: 0.375rem;
max-height: 400px;
overflow-y: auto;
font-size: 0.875rem; /* text-sm */
font-size: 0.875rem;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
#traceroute-output .hop-line {
margin-bottom: 0.25rem;
padding-left: 0.5rem;
border-left: 2px solid transparent;
transition: border-left-color 0.3s;
}
#traceroute-output .hop-line:hover {
border-left-color: #a855f7;
background: rgba(255, 255, 255, 0.02);
}
#traceroute-output .hop-number {
display: inline-block;
width: 30px;
text-align: right;
margin-right: 15px;
color: #6b7280;
font-weight: bold;
}
#traceroute-output .hop-ip {
color: #60a5fa;
font-weight: 500;
}
#traceroute-output .hop-hostname {
color: #c084fc;
}
/* Helleres Lila */
#traceroute-output .hop-rtt {
color: #34d399;
margin-left: 8px;
font-size: 0.85em;
}
#traceroute-output .hop-timeout {
color: #f87171;
}
#traceroute-output .info-line {
color: #fbbf24;
font-style: italic;
}
#traceroute-output .error-line {
color: #f87171;
font-weight: bold;
border-left: 3px solid #f87171;
padding-left: 10px;
}
#traceroute-output .end-line {
color: #d8b4fe;
font-weight: bold;
margin-top: 15px;
text-transform: uppercase;
letter-spacing: 0.05em;
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 10px;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
#traceroute-output .hop-line { margin-bottom: 0.25rem; }
#traceroute-output .hop-number { display: inline-block; width: 30px; text-align: right; margin-right: 10px; color: #9ca3af; } /* Grau */
#traceroute-output .hop-ip { color: #60a5fa; } /* Blau */
#traceroute-output .hop-hostname { color: #a78bfa; } /* Lila */
#traceroute-output .hop-rtt { color: #34d399; margin-left: 5px;} /* Grün */
#traceroute-output .hop-timeout { color: #f87171; } /* Rot */
#traceroute-output .info-line { color: #fbbf24; font-style: italic;} /* Gelb */
#traceroute-output .error-line { color: #f87171; font-weight: bold;} /* Rot */
#traceroute-output .end-line { color: #a78bfa; font-weight: bold; margin-top: 10px;} /* Lila */
/* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; } /* flex-wrap hinzugefügt */
nav a { color: #c4b5fd; /* purple-300 */ text-decoration: none; white-space: nowrap; } /* nowrap hinzugefügt */
nav a:hover { color: #a78bfa; /* purple-400 */ text-decoration: underline; }
header { background-color: #374151; /* gray-700 */ padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; /* rounded-lg */ display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } /* Flex direction geändert */
@media (min-width: 768px) { /* md breakpoint */
header { flex-direction: row; justify-content: space-between; }
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
header h1 { font-size: 1.5rem; /* text-2xl */ font-weight: bold; color: #e5e7eb; /* gray-200 */ }
/* Hilfsklasse zum Verstecken */
.hidden { display: none; }
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
/* Purple tint */
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
/* Optional active state */
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
/* Sehr transparent */
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
/* Standard property for compatibility */
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
</style>
</head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header>
<h1>uTools Network Suite</h1> <!-- Name angepasst -->
<body
class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav>
<ul>
<li><a href="index.html">IP Info & Tools</a></li>
<li><a href="index.html" class="active-link">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li>
@@ -97,166 +310,260 @@
</nav>
</header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6">
<div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 glitch-text text-center">IP Information</h1> <!-- Titel angepasst -->
<h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">Your Digital Footprint</h1>
<!-- Bereich für EIGENE IP-Infos -->
<div id="info-section" class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div id="info-section" class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8">
<!-- Linke Spalte: Eigene IP, Geo, ASN, rDNS -->
<div class="space-y-4 p-4 bg-gray-700 rounded">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Your Public IP</h2>
<div id="ip-info" class="min-h-[50px]">
<div id="ip-loader" class="loader"></div>
<!-- Geändert zu <a> Tag -->
<a id="ip-address-link" href="#" class="text-2xl font-mono font-bold text-purple-400 break-all hidden" title="Go to WHOIS Lookup for this IP">
<span id="ip-address"></span> <!-- Span für den eigentlichen Text -->
</a>
</div>
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Geolocation</h2>
<div id="geo-info" class="min-h-[100px] space-y-1 text-sm">
<div id="geo-loader" class="loader"></div>
<div class="hidden"> <!-- Hide data until loaded -->
<p><strong>Country:</strong> <span id="country">-</span></p>
<p><strong>Region:</strong> <span id="region">-</span></p>
<p><strong>City:</strong> <span id="city">-</span></p>
<p><strong>Postal Code:</strong> <span id="postal">-</span></p>
<p><strong>Coordinates:</strong> <span id="coords">-</span></p>
<p><strong>Timezone:</strong> <span id="timezone">-</span></p>
<p id="geo-error" class="text-red-400"></p>
<div class="space-y-6 fade-in" style="animation-delay: 0.1s;">
<!-- IP Card -->
<div class="glass-card rounded-lg p-5 relative overflow-hidden group">
<div class="absolute top-0 right-0 p-2 opacity-10 group-hover:opacity-20 transition-opacity">
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-purple-500" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
</svg>
</div>
<h2 class="text-xs font-bold text-purple-400 uppercase tracking-widest mb-2">Your Public IP</h2>
<div id="ip-info" class="min-h-[40px] flex items-center">
<div id="ip-loader" class="loader"></div>
<a id="ip-address-link" href="#"
class="text-3xl font-mono font-bold text-white tracking-tight break-all hidden hover:text-purple-300 transition-colors"
title="Click for WHOIS Lookup">
<span id="ip-address"></span>
</a>
</div>
</div>
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">ASN</h2>
<div id="asn-info" class="min-h-[50px] space-y-1 text-sm">
<div id="asn-loader" class="loader"></div>
<div class="hidden"> <!-- Hide data until loaded -->
<p><strong>Number:</strong> <span id="asn-number">-</span></p>
<p><strong>Organization:</strong> <span id="asn-org">-</span></p>
<p id="asn-error" class="text-red-400"></p>
</div>
<!-- Geo/ASN Combo Card -->
<div class="glass-card rounded-lg p-5 space-y-4">
<div>
<h2
class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 border-b border-gray-700 pb-1">
Location Details</h2>
<div id="geo-info" class="min-h-[80px] space-y-1 text-sm text-gray-300">
<div id="geo-loader" class="loader"></div>
<div class="hidden grid grid-cols-2 gap-x-2 gap-y-1">
<p><span class="text-gray-500">Country:</span> <span id="country"
class="text-gray-200 font-medium">-</span></p>
<p><span class="text-gray-500">Region:</span> <span id="region"
class="text-gray-200 font-medium">-</span></p>
<p><span class="text-gray-500">City:</span> <span id="city"
class="text-gray-200 font-medium">-</span></p>
<p><span class="text-gray-500">Zip:</span> <span id="postal"
class="text-gray-200 font-medium">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Coords:</span> <span id="coords"
class="font-mono text-xs text-purple-300">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Time:</span> <span id="timezone"
class="text-gray-200 font-medium">-</span></p>
<p id="geo-error" class="text-red-400 col-span-2 text-xs"></p>
</div>
</div>
</div>
<div>
<h2
class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 border-b border-gray-700 pb-1">
Network (ASN)</h2>
<div id="asn-info" class="min-h-[40px] space-y-1 text-sm text-gray-300">
<div id="asn-loader" class="loader"></div>
<div class="hidden">
<p><span class="text-gray-500">AS Number:</span> <span id="asn-number"
class="font-mono text-purple-300">-</span></p>
<p><span class="text-gray-500">Org:</span> <span id="asn-org"
class="font-medium text-white">-</span></p>
<p id="asn-error" class="text-red-400 text-xs"></p>
</div>
</div>
</div>
</div>
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Reverse DNS (rDNS)</h2>
<div id="rdns-info" class="min-h-[50px] space-y-1 text-sm">
<div id="rdns-loader" class="loader"></div>
<div class="hidden"> <!-- Hide data until loaded -->
<ul id="rdns-list" class="list-disc list-inside"><li>-</li></ul>
<p id="rdns-error" class="text-red-400"></p>
</div>
<!-- rDNS Card -->
<div class="glass-card rounded-lg p-5">
<h2
class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 border-b border-gray-700 pb-1">
Hostname (rDNS)</h2>
<div id="rdns-info" class="min-h-[30px] text-sm text-gray-300">
<div id="rdns-loader" class="loader"></div>
<div class="hidden">
<ul id="rdns-list" class="list-none space-y-1 font-mono text-xs text-green-400">
<li>-</li>
</ul>
<p id="rdns-error" class="text-red-400 text-xs"></p>
</div>
</div>
</div>
</div>
<!-- Rechte Spalte: Eigene Karte -->
<div class="space-y-4 p-4 bg-gray-700 rounded">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Your Location Map</h2>
<div id="map-container" class="bg-gray-600 rounded min-h-[300px] flex items-center justify-center relative">
<div id="map-loader" class="loader absolute"></div>
<div id="map" class="w-full rounded hidden"></div>
<p id="map-message" class="text-gray-400 hidden absolute">Could not load map.</p>
</div>
<div class="space-y-4 fade-in" style="animation-delay: 0.2s;">
<h2 class="text-lg font-semibold text-gray-200 flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-purple-400" viewBox="0 0 20 20"
fill="currentColor">
<path fill-rule="evenodd"
d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z"
clip-rule="evenodd" />
</svg>
Location Visualization
</h2>
<div id="map-container"
class="bg-gray-800/50 rounded-lg min-h-[400px] h-full flex items-center justify-center relative border border-gray-700/50 shadow-inner overflow-hidden">
<div id="map-loader" class="loader absolute z-10"></div>
<div id="map"
class="w-full h-full rounded-lg hidden z-0 opacity-80 hover:opacity-100 transition-opacity duration-700">
</div>
<p id="map-message" class="text-gray-400 hidden absolute text-sm">Could not load map.</p>
<div class="absolute inset-0 pointer-events-none rounded-lg ring-1 ring-inset ring-white/10"></div>
</div>
</div>
</div>
<!-- Bereich für IP Lookup -->
<div class="mt-8 p-4 bg-gray-700 rounded">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1 mb-4">IP Address Lookup</h2>
<div class="flex flex-col sm:flex-row gap-2 mb-4">
<input type="text" id="lookup-ip-input" placeholder="Enter IP address (e.g., 8.8.8.8)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono">
<div class="mt-8 p-6 glass-card rounded-xl">
<h2
class="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-purple-400 to-pink-500 mb-4 flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-pink-500" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
IP Address / Domain Lookup
</h2>
<div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="lookup-ip-input" placeholder="Enter IP or Domain (e.g., 8.8.8.8 or google.com)"
class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<button id="lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out">
Lookup IP
class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Lookup
</button>
</div>
<div id="lookup-error" class="text-red-400 mb-4 hidden"></div>
<div id="lookup-error" class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded">
</div>
<!-- Ergebnisse des Lookups (initial versteckt) -->
<div id="lookup-results-section" class="hidden grid grid-cols-1 md:grid-cols-2 gap-6 mt-4 border-t border-gray-600 pt-4">
<!-- Linke Spalte: IP, Geo, ASN, rDNS -->
<div class="space-y-4">
<h3 class="text-lg font-semibold text-purple-300">Lookup Result for: <span id="lookup-ip-address" class="font-mono text-purple-400"></span></h3>
<div id="lookup-result-loader" class="loader hidden"></div> <!-- Loader für den gesamten Block -->
<div id="lookup-results-section"
class="hidden grid grid-cols-1 md:grid-cols-2 gap-8 mt-6 border-t border-gray-700/50 pt-6 fade-in">
<!-- Linke Spalte: IP, Geo, ASN, rDNS -->
<div class="space-y-6">
<h3 class="text-lg font-semibold text-gray-200">Result for: <span id="lookup-ip-address"
class="font-mono text-purple-400 bg-purple-500/10 px-2 py-0.5 rounded"></span></h3>
<div id="lookup-result-loader" class="loader hidden"></div>
<div id="lookup-geo-info" class="space-y-1 text-sm">
<h4 class="font-semibold text-purple-300">Geolocation</h4>
<p><strong>Country:</strong> <span id="lookup-country">-</span></p>
<p><strong>Region:</strong> <span id="lookup-region">-</span></p>
<p><strong>City:</strong> <span id="lookup-city">-</span></p>
<p><strong>Postal Code:</strong> <span id="lookup-postal">-</span></p>
<p><strong>Coordinates:</strong> <span id="lookup-coords">-</span></p>
<p><strong>Timezone:</strong> <span id="lookup-timezone">-</span></p>
<p id="lookup-geo-error" class="text-red-400"></p>
<div id="lookup-geo-info" class="space-y-1 text-sm text-gray-300">
<h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2">Geolocation</h4>
<div class="grid grid-cols-2 gap-x-2 gap-y-1">
<p><span class="text-gray-500">Country:</span> <span id="lookup-country"
class="text-white">-</span></p>
<p><span class="text-gray-500">Region:</span> <span id="lookup-region"
class="text-white">-</span></p>
<p><span class="text-gray-500">City:</span> <span id="lookup-city"
class="text-white">-</span></p>
<p><span class="text-gray-500">Zip:</span> <span id="lookup-postal"
class="text-white">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Coords:</span> <span id="lookup-coords"
class="font-mono text-purple-300">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Time:</span> <span id="lookup-timezone"
class="text-white">-</span></p>
<p id="lookup-geo-error" class="text-red-400 col-span-2"></p>
</div>
</div>
<div id="lookup-asn-info" class="space-y-1 text-sm">
<h4 class="font-semibold text-purple-300">ASN</h4>
<p><strong>Number:</strong> <span id="lookup-asn-number">-</span></p>
<p><strong>Organization:</strong> <span id="lookup-asn-org">-</span></p>
<div id="lookup-asn-info" class="space-y-1 text-sm text-gray-300">
<h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2 mt-4">ASN</h4>
<p><span class="text-gray-500">Number:</span> <span id="lookup-asn-number"
class="text-white font-mono">-</span></p>
<p><span class="text-gray-500">Org:</span> <span id="lookup-asn-org" class="text-white">-</span>
</p>
<p id="lookup-asn-error" class="text-red-400"></p>
</div>
<div id="lookup-rdns-info" class="space-y-1 text-sm">
<h4 class="font-semibold text-purple-300">Reverse DNS (rDNS)</h4>
<ul id="lookup-rdns-list" class="list-disc list-inside"><li>-</li></ul>
<div id="lookup-rdns-info" class="space-y-1 text-sm text-gray-300">
<h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2 mt-4">Reverse DNS</h4>
<ul id="lookup-rdns-list" class="list-none space-y-1 font-mono text-xs text-green-400">
<li>-</li>
</ul>
<p id="lookup-rdns-error" class="text-red-400"></p>
</div>
</div>
</div>
<!-- Rechte Spalte: Karte & Aktionen -->
<div class="space-y-4">
<h4 class="font-semibold text-purple-300">Location Map</h4>
<div id="lookup-map-container" class="bg-gray-600 rounded min-h-[250px] flex items-center justify-center relative">
<div id="lookup-map-loader" class="loader hidden absolute"></div>
<div id="lookup-map" class="w-full rounded hidden"></div> <!-- Höhe via CSS -->
<p id="lookup-map-message" class="text-gray-400 hidden absolute">Could not load map.</p>
</div>
<!-- Optional: Buttons für Ping/Trace für diese IP -->
<div class="mt-4 space-x-2">
<button id="lookup-ping-button" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded text-sm transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" disabled>Ping this IP</button>
<button id="lookup-trace-button" class="bg-teal-600 hover:bg-teal-700 text-white font-bold py-1 px-3 rounded text-sm transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" disabled>Trace this IP</button>
<button id="lookup-scan-button" class="bg-red-600 hover:bg-red-700 text-white font-bold py-1 px-3 rounded text-sm transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" disabled>Scan Ports</button>
</div>
<!-- Bereich für Ping-Ergebnisse (Lookup) -->
<div id="lookup-ping-results" class="mt-2 text-sm hidden">
<h4 class="font-semibold text-purple-300">Ping Results</h4>
<div id="lookup-ping-loader" class="loader hidden"></div>
<pre id="lookup-ping-output" class="mt-1 whitespace-pre-wrap break-all font-mono bg-gray-900 text-gray-300 p-2 rounded text-xs"></pre>
<p id="lookup-ping-error" class="text-red-400"></p>
</div>
</div>
<!-- Rechte Spalte: Karte & Aktionen -->
<div class="space-y-6">
<h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2">Location Map</h4>
<div id="lookup-map-container"
class="glass-panel rounded-lg min-h-[250px] flex items-center justify-center relative overflow-hidden">
<div id="lookup-map-loader" class="loader hidden absolute z-10"></div>
<div id="lookup-map" class="w-full rounded hidden opacity-90"></div>
<p id="lookup-map-message" class="text-gray-400 hidden absolute">Could not load map.</p>
<div class="absolute inset-0 pointer-events-none ring-1 ring-inset ring-white/10 rounded-lg">
</div>
</div>
<!-- Action Buttons -->
<div class="flex flex-wrap gap-2 pt-2">
<button id="lookup-ping-button"
class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-gray-600 hover:border-gray-500 shadow-md"
disabled>Ping</button>
<button id="lookup-trace-button"
class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-gray-600 hover:border-gray-500 shadow-md"
disabled>Trace</button>
<button id="lookup-scan-button"
class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-gray-600 hover:border-gray-500 shadow-md"
disabled>Port Scan</button>
</div>
<!-- Bereich für Ping-Ergebnisse (Lookup) -->
<div id="lookup-ping-results" class="mt-4 text-sm hidden fade-in">
<h4 class="font-bold text-purple-400 mb-2 flex items-center gap-2">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div> Ping Results
</h4>
<div id="lookup-ping-loader" class="loader hidden"></div>
<pre id="lookup-ping-output" class="result-pre mt-1"></pre>
<p id="lookup-ping-error" class="text-red-400 mt-2"></p>
</div>
</div>
</div>
</div>
<!-- Bereich für Traceroute -->
<div id="traceroute-section" class="mt-8 p-4 bg-gray-700 rounded hidden">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1 mb-4">Traceroute Results</h2>
<div id="traceroute-status" class="flex items-center mb-2">
<div id="traceroute-loader" class="loader mr-2 hidden"></div>
<span id="traceroute-message" class="text-gray-400"></span>
</div>
<div id="traceroute-output"><pre></pre></div>
<div id="traceroute-section" class="mt-8 p-6 glass-card rounded-xl hidden fade-in">
<h2 class="text-xl font-bold text-purple-300 border-b border-purple-500/30 pb-2 mb-4">Traceroute Results
</h2>
<div id="traceroute-status" class="flex items-center mb-4 text-sm">
<div id="traceroute-loader" class="loader mr-3 hidden"></div>
<span id="traceroute-message" class="text-gray-300"></span>
</div>
<div id="traceroute-output" class="rounded-lg overflow-hidden custom-scrollbar">
<pre class="m-0"></pre>
</div>
</div>
<!-- Bereich für Port Scan -->
<div id="port-scan-section" class="mt-8 p-4 bg-gray-700 rounded hidden">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1 mb-4">Port Scan Results</h2>
<div id="port-scan-status" class="flex items-center mb-2">
<div id="port-scan-loader" class="loader mr-2 hidden"></div>
<span id="port-scan-message" class="text-gray-400"></span>
</div>
<div id="port-scan-output" class="text-sm font-mono"></div>
<div id="port-scan-section" class="mt-8 p-6 glass-card rounded-xl hidden fade-in">
<h2 class="text-xl font-bold text-purple-300 border-b border-purple-500/30 pb-2 mb-4">Port Scan Results</h2>
<div id="port-scan-status" class="flex items-center mb-4 text-sm">
<div id="port-scan-loader" class="loader mr-3 hidden"></div>
<span id="port-scan-message" class="text-gray-300"></span>
</div>
<div id="port-scan-output"
class="text-sm font-mono bg-gray-900/50 p-4 rounded-lg border border-gray-700/50 max-h-[300px] overflow-y-auto">
</div>
</div>
<!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div>
<div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<!-- Footer für Version -->
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p>
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p>
<footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de"
class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
@@ -264,9 +571,9 @@
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<!-- Eigene JS-Logik -->
<script src="script.js"></script>
</body>
</html>

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,82 +9,227 @@
<script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles -->
<style>
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader {
border: 4px solid rgba(168, 85, 247, 0.3);
border-left-color: #a855f7;
border: 4px solid rgba(168, 85, 247, 0.1);
/* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Ergebnis-Pre-Formatierung */
.result-pre {
white-space: pre-wrap;
word-break: break-all;
font-family: monospace;
background-color: #1f2937;
color: #d1d5db;
font-family: 'Courier New', Courier, monospace;
background-color: rgba(0, 0, 0, 0.3);
color: #e5e7eb;
padding: 1rem;
border-radius: 0.375rem;
max-height: 400px;
overflow-y: auto;
font-size: 1.25rem; /* Larger font for the result */
font-size: 1.25rem;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
/* Navigations-Styling */
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; }
nav a { color: #c4b5fd; text-decoration: none; white-space: nowrap; }
nav a:hover { color: #a78bfa; text-decoration: underline; }
header { background-color: #374151; padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
@media (min-width: 768px) { header { flex-direction: row; justify-content: space-between; } }
header h1 { font-size: 1.5rem; font-weight: bold; color: #e5e7eb; }
.hidden { display: none; }
</style>
</head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header>
<h1>uTools Network Suite</h1>
<body
class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav>
<ul>
<li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li>
<li><a href="mac-lookup.html" class="active-link">MAC Lookup</a></li>
</ul>
</nav>
</header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6">
<div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 text-center">MAC Address Vendor Lookup</h1>
<h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">MAC Address Vendor Lookup</h1>
<div class="mt-8 p-4 bg-gray-700 rounded">
<div class="flex flex-col sm:flex-row gap-2 mb-4">
<div class="mt-8 p-6 glass-card rounded-xl">
<div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="mac-input" placeholder="Enter MAC address (e.g., 00:1A:2B:3C:4D:5E)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono">
class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<button id="mac-lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out">
class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Find Vendor
</button>
</div>
<div id="mac-lookup-error" class="text-red-400 mb-4 hidden"></div>
<div id="mac-lookup-results-section" class="hidden mt-4 border-t border-gray-600 pt-4">
<h3 class="text-lg font-semibold text-purple-300 mb-2">Vendor for: <span id="mac-lookup-query" class="font-mono text-purple-400"></span></h3>
<div id="mac-lookup-loader" class="loader hidden mb-2 mx-auto"></div>
<pre id="mac-lookup-output" class="result-pre"></pre>
<div id="mac-lookup-error"
class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded"></div>
<div id="mac-lookup-results-section" class="hidden mt-6 border-t border-gray-700/50 pt-6 fade-in">
<h3 class="text-lg font-semibold text-purple-300 mb-4 flex items-center justify-center gap-2">
<div class="w-1.5 h-6 bg-purple-500 rounded-full"></div>
Vendor for: <span id="mac-lookup-query" class="font-mono text-purple-400 ml-1"></span>
</h3>
<div id="mac-lookup-loader" class="loader hidden mb-4 mx-auto"></div>
<pre id="mac-lookup-output" class="result-pre custom-scrollbar"></pre>
</div>
</div>
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div>
<div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p>
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p>
</footer>
<footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de"
class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
</div>
<script src="mac-lookup.js"></script>
</body>
</html>

View File

@@ -43,6 +43,11 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
// Reset animation
macLookupResultsSection.classList.remove('fade-in');
void macLookupResultsSection.offsetWidth; // Trigger reflow
macLookupResultsSection.classList.add('fade-in');
macLookupResultsSection.classList.remove('hidden');
macLookupLoader.classList.remove('hidden');
macLookupErrorEl.classList.add('hidden');

View File

@@ -149,33 +149,33 @@ document.addEventListener('DOMContentLoaded', () => {
}
}
/**
* Aktualisiert die rDNS Liste generisch.
* @param {HTMLElement} listElement - Das UL Element.
* @param {Array|object} rdnsData - Die rDNS Daten oder ein Fehlerobjekt.
* @param {HTMLElement} [loaderElement] - Das zu versteckende Loader-Element.
* @param {HTMLElement} [errorElement] - Das Element zur Anzeige von Fehlern.
*/
/**
* Aktualisiert die rDNS Liste generisch.
* @param {HTMLElement} listElement - Das UL Element.
* @param {Array|object} rdnsData - Die rDNS Daten oder ein Fehlerobjekt.
* @param {HTMLElement} [loaderElement] - Das zu versteckende Loader-Element.
* @param {HTMLElement} [errorElement] - Das Element zur Anzeige von Fehlern.
*/
function updateRdns(listElement, rdnsData, loaderElement = null, errorElement = null) {
if (loaderElement) loaderElement.classList.add('hidden');
if (listElement) listElement.innerHTML = ''; // Clear previous entries
if (errorElement) errorElement.textContent = '';
// Zeige das Elternelement des listElements, falls es vorher versteckt war
const dataContainer = listElement?.closest('div:not(.loader)');
if (dataContainer?.classList.contains('hidden')) {
// Zeige das Elternelement des listElements, falls es vorher versteckt war
const dataContainer = listElement?.closest('div:not(.loader)');
if (dataContainer?.classList.contains('hidden')) {
dataContainer.classList.remove('hidden');
}
if (rdnsData && Array.isArray(rdnsData)) {
if (rdnsData.length > 0) {
rdnsData.forEach(hostname => {
rdnsData.forEach(hostname => {
const li = document.createElement('li');
li.textContent = hostname;
if (listElement) listElement.appendChild(li);
});
} else {
if (listElement) listElement.innerHTML = '<li>No rDNS records found.</li>'; // Klarere Meldung
if (listElement) listElement.innerHTML = '<li>No rDNS records found.</li>'; // Klarere Meldung
}
} else if (rdnsData && rdnsData.error) {
if (listElement) listElement.innerHTML = '<li>-</li>';
@@ -241,10 +241,10 @@ document.addEventListener('DOMContentLoaded', () => {
messageElement.classList.remove('hidden');
messageElement.textContent = 'Map could not be loaded (missing or invalid coordinates).';
// If map existed, remove it to clean up resources
if(mapInstance) {
mapInstance.remove();
window[mapId + '_instance'] = null;
}
if (mapInstance) {
mapInstance.remove();
window[mapId + '_instance'] = null;
}
return null;
}
}
@@ -357,8 +357,8 @@ document.addEventListener('DOMContentLoaded', () => {
}
/** Setzt den Lookup-Ergebnisbereich zurück */
function resetLookupResults() {
/** Setzt den Lookup-Ergebnisbereich zurück */
function resetLookupResults() {
if (!lookupResultsSection) return;
lookupResultsSection.classList.add('hidden');
if (lookupResultLoader) lookupResultLoader.classList.add('hidden');
@@ -396,7 +396,7 @@ document.addEventListener('DOMContentLoaded', () => {
portScanEventSource.close();
portScanEventSource = null;
}
}
}
/** Ruft Informationen für eine spezifische IP ab */
async function fetchLookupInfo(ipToLookup) {
@@ -452,8 +452,8 @@ document.addEventListener('DOMContentLoaded', () => {
resetLookupResults(); // Hide the section again on error
} finally {
if (lookupResultLoader) lookupResultLoader.classList.add('hidden'); // Hide main loader
// Map loader is handled by initOrUpdateMap
if (lookupResultLoader) lookupResultLoader.classList.add('hidden'); // Hide main loader
// Map loader is handled by initOrUpdateMap
}
}
@@ -522,10 +522,10 @@ document.addEventListener('DOMContentLoaded', () => {
if (data.stats.rtt) {
outputText += `Round Trip Time (ms): min=${data.stats.rtt.min}, avg=${data.stats.rtt.avg}, max=${data.stats.rtt.max}, mdev=${data.stats.rtt.mdev}\n`;
} else if (data.stats.packets.received === 0) {
outputText += `Status: Host unreachable or request timed out.\n`;
outputText += `Status: Host unreachable or request timed out.\n`;
}
} else {
outputText += `Could not parse statistics.\n`;
outputText += `Could not parse statistics.\n`;
}
outputText += `\n--- Raw Output ---\n${data.rawOutput || 'No raw output available.'}`;
lookupPingOutputEl.textContent = outputText;
@@ -571,7 +571,7 @@ document.addEventListener('DOMContentLoaded', () => {
console.error('EventSource failed:', event);
let errorMsg = 'Connection error during traceroute.';
if (eventSource.readyState === EventSource.CLOSED) {
errorMsg = 'Connection closed. Server might have stopped or a network issue occurred.';
errorMsg = 'Connection closed. Server might have stopped or a network issue occurred.';
}
tracerouteMessage.textContent = errorMsg;
tracerouteLoader.classList.add('hidden');
@@ -587,14 +587,14 @@ document.addEventListener('DOMContentLoaded', () => {
});
eventSource.addEventListener('info', (event) => {
try {
try {
const infoData = JSON.parse(event.data);
displayTracerouteLine(infoData.message, 'info-line');
} catch (e) { displayTracerouteLine(`[Error parsing info data: ${event.data}]`, 'error-line'); }
});
eventSource.addEventListener('error', (event) => { // Backend error event
try {
try {
const errorData = JSON.parse(event.data);
displayTracerouteLine(errorData.error, 'error-line');
tracerouteMessage.textContent = `Error during traceroute: ${errorData.error}`;
@@ -603,7 +603,7 @@ document.addEventListener('DOMContentLoaded', () => {
eventSource.addEventListener('end', (event) => {
console.log('SSE connection closed by server (end event).');
try {
try {
const endData = JSON.parse(event.data);
const endMessage = `Traceroute finished ${endData.exitCode === 0 ? 'successfully' : `with exit code ${endData.exitCode}`}.`;
displayTracerouteLine(endMessage, 'end-line');
@@ -615,18 +615,19 @@ document.addEventListener('DOMContentLoaded', () => {
}
function displayTracerouteLine(text, className = '') {
if (!tracerouteOutputEl) return;
const lineDiv = document.createElement('div');
if (className) lineDiv.classList.add(className);
lineDiv.textContent = text;
tracerouteOutputEl.appendChild(lineDiv);
tracerouteOutputEl.scrollTop = tracerouteOutputEl.scrollHeight;
if (!tracerouteOutputEl) return;
const lineDiv = document.createElement('div');
if (className) lineDiv.classList.add(className);
lineDiv.classList.add('fade-in'); // Animation hinzufügen
lineDiv.textContent = text;
tracerouteOutputEl.appendChild(lineDiv);
tracerouteOutputEl.scrollTop = tracerouteOutputEl.scrollHeight;
}
function displayTracerouteHop(hopData) {
if (!tracerouteOutputEl) return;
const lineDiv = document.createElement('div');
lineDiv.classList.add('hop-line');
lineDiv.classList.add('hop-line', 'fade-in'); // Animation hinzufügen
const hopNumSpan = document.createElement('span');
hopNumSpan.classList.add('hop-number');
@@ -645,12 +646,12 @@ document.addEventListener('DOMContentLoaded', () => {
lineDiv.appendChild(hostSpan);
}
} else if (hopData.rtt && hopData.rtt.every(r => r === '*')) {
const timeoutSpan = document.createElement('span');
timeoutSpan.classList.add('hop-timeout');
timeoutSpan.textContent = '* * *';
lineDiv.appendChild(timeoutSpan);
const timeoutSpan = document.createElement('span');
timeoutSpan.classList.add('hop-timeout');
timeoutSpan.textContent = '* * *';
lineDiv.appendChild(timeoutSpan);
} else {
lineDiv.appendChild(document.createTextNode(hopData.rawLine || 'Unknown hop format'));
lineDiv.appendChild(document.createTextNode(hopData.rawLine || 'Unknown hop format'));
}
if (hopData.rtt && Array.isArray(hopData.rtt)) {
@@ -729,7 +730,7 @@ document.addEventListener('DOMContentLoaded', () => {
function displayPortScanResult(data) {
if (!portScanOutputEl) return;
const lineDiv = document.createElement('div');
lineDiv.classList.add('mb-1');
lineDiv.classList.add('mb-1', 'fade-in'); // Animation hinzufügen
let statusColor = 'text-gray-400';
let statusText = data.status.toUpperCase();
@@ -794,38 +795,38 @@ document.addEventListener('DOMContentLoaded', () => {
// lookupIpInput.value = resolvedIp;
fetchLookupInfo(resolvedIp); // Fetch info for the resolved IP
} else {
// Should be caught by the error in resolveDomainToIp, but as a fallback:
showLookupError(`Could not resolve domain ${query} to an IP address.`);
// Should be caught by the error in resolveDomainToIp, but as a fallback:
showLookupError(`Could not resolve domain ${query} to an IP address.`);
}
} catch (error) {
showLookupError(error.message); // Display resolution error
} finally {
hideLookupStatus(); // Hide status message regardless of outcome
hideLookupStatus(); // Hide status message regardless of outcome
}
}
}
function handleLookupPingClick() {
if (currentLookupIp) {
console.log(`Starting ping for looked-up IP: ${currentLookupIp}`);
runLookupPing(currentLookupIp); // Call the new ping function
}
}
function handleLookupPingClick() {
if (currentLookupIp) {
console.log(`Starting ping for looked-up IP: ${currentLookupIp}`);
runLookupPing(currentLookupIp); // Call the new ping function
}
}
function handleLookupTraceClick() {
if (currentLookupIp) {
console.log(`Starting traceroute for looked-up IP: ${currentLookupIp}`);
startTraceroute(currentLookupIp);
}
}
function handleLookupTraceClick() {
if (currentLookupIp) {
console.log(`Starting traceroute for looked-up IP: ${currentLookupIp}`);
startTraceroute(currentLookupIp);
}
}
function handleLookupScanClick() {
function handleLookupScanClick() {
if (currentLookupIp) {
console.log(`Starting port scan for looked-up IP: ${currentLookupIp}`);
startPortScan(currentLookupIp);
}
}
}
// --- Initial Load & Event Listeners ---
fetchIpInfo(); // Lade Infos zur eigenen IP

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,116 +9,164 @@
<script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles (für Navigation etc., wie in index.html) -->
<style>
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader {
border: 4px solid rgba(168, 85, 247, 0.1);
/* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; } /* flex-wrap hinzugefügt */
nav a { color: #c4b5fd; /* purple-300 */ text-decoration: none; white-space: nowrap; } /* nowrap hinzugefügt */
nav a:hover { color: #a78bfa; /* purple-400 */ text-decoration: underline; }
header { background-color: #374151; /* gray-700 */ padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; /* rounded-lg */ display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } /* Flex direction geändert */
@media (min-width: 768px) { /* md breakpoint */
header { flex-direction: row; justify-content: space-between; }
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
header h1 { font-size: 1.5rem; /* text-2xl */ font-weight: bold; color: #e5e7eb; /* gray-200 */ }
/* Styling für Formular und Ergebnisse */
label { display: block; margin-bottom: 0.5rem; font-weight: 600; color: #d1d5db; /* gray-300 */ }
input[type="text"] {
width: 100%;
padding: 0.75rem;
margin-bottom: 1rem;
background-color: #4b5563; /* gray-600 */
border: 1px solid #6b7280; /* gray-500 */
border-radius: 0.375rem; /* rounded-md */
color: #e5e7eb; /* gray-200 */
font-family: monospace;
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
input[type="text"]:focus {
outline: none;
border-color: #a78bfa; /* purple-400 */
box-shadow: 0 0 0 2px rgba(167, 139, 250, 0.5);
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
button[type="submit"] {
background-color: #8b5cf6; /* purple-500 */
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 0.375rem; /* rounded-md */
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s;
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
button[type="submit"]:hover {
background-color: #7c3aed; /* purple-600 */
}
#results, #examples {
margin-top: 2rem;
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
background-color: #374151; /* gray-700 */
border-radius: 0.5rem; /* rounded-lg */
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
#results h3, #examples h3 {
font-size: 1.25rem; /* text-xl */
font-weight: 600;
color: #c4b5fd; /* purple-300 */
margin-bottom: 1rem;
border-bottom: 1px solid #6b7280; /* gray-500 */
padding-bottom: 0.5rem;
}
#results p {
margin-bottom: 0.75rem;
color: #d1d5db; /* gray-300 */
}
#results p strong {
color: #e5e7eb; /* gray-200 */
min-width: 150px; /* Für bessere Ausrichtung */
display: inline-block;
}
#results span {
font-family: monospace;
color: #a78bfa; /* purple-400 */
}
/* Styling für Beispiel-Tabelle */
#examples table {
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
}
#examples th, #examples td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid #4b5563; /* gray-600 */
color: #d1d5db; /* gray-300 */
}
#examples th {
color: #e5e7eb; /* gray-200 */
font-weight: 600;
}
#examples td code {
font-family: monospace;
background-color: #4b5563; /* gray-600 */
padding: 0.2rem 0.4rem;
border-radius: 0.25rem;
color: #c4b5fd; /* purple-300 */
}
#examples .example-link {
color: #a78bfa; /* purple-400 */
cursor: pointer;
text-decoration: underline;
}
#examples .example-link:hover {
color: #c4b5fd; /* purple-300 */
}
.hidden { display: none; }
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
</style>
</head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header>
<h1>uTools Network Suite</h1> <!-- Titel angepasst -->
<body
class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav>
<ul>
<li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="subnet-calculator.html" class="active-link">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li>
@@ -125,92 +174,133 @@
</nav>
</header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6">
<div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h2 class="text-2xl font-bold mb-6 text-purple-400 text-center">IP Subnetz Rechner</h2>
<h2 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">IP Subnetz Rechner</h2>
<form id="subnet-form" class="mb-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<form id="subnet-form" class="mb-8 glass-card p-6 rounded-xl">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label for="ip-address">IP Adresse:</label>
<label for="ip-address"
class="block text-gray-400 text-sm font-bold mb-2 uppercase tracking-wide">IP Adresse:</label>
<input type="text" id="ip-address" name="ip-address" placeholder="z.B. 192.168.1.1" required
class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono">
class="w-full px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all">
</div>
<div>
<label for="cidr">CIDR / Subnetzmaske:</label>
<label for="cidr" class="block text-gray-400 text-sm font-bold mb-2 uppercase tracking-wide">CIDR /
Maske:</label>
<input type="text" id="cidr" name="cidr" placeholder="z.B. 24 oder 255.255.255.0" required
class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono">
class="w-full px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all">
</div>
</div>
<button type="submit"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out">
class="w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Berechnen
</button>
</form>
<div id="results" class="bg-gray-700 rounded p-6 hidden"> <!-- Ergebnisse initial verstecken -->
<h3 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-2 mb-4">Ergebnisse:</h3>
<div class="space-y-2 text-sm">
<p><strong>Netzwerkadresse:</strong> <span id="network-address" class="font-mono text-purple-400">-</span></p>
<p><strong>Broadcast-Adresse:</strong> <span id="broadcast-address" class="font-mono text-purple-400">-</span></p>
<p><strong>Subnetzmaske:</strong> <span id="subnet-mask" class="font-mono text-purple-400">-</span></p>
<p><strong>Anzahl der Hosts:</strong> <span id="host-count" class="font-mono text-purple-400">-</span></p>
<p><strong>Erste Host-Adresse:</strong> <span id="first-host" class="font-mono text-purple-400">-</span></p>
<p><strong>Letzte Host-Adresse:</strong> <span id="last-host" class="font-mono text-purple-400">-</span></p>
<div id="results" class="glass-card rounded-xl p-6 hidden fade-in"> <!-- Ergebnisse initial verstecken -->
<h3
class="text-xl font-bold text-purple-300 border-b border-purple-500/30 pb-2 mb-4 flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
Ergebnisse:
</h3>
<div class="space-y-3 text-sm">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Netzwerkadresse:</span>
<span id="network-address" class="font-mono text-white font-semibold">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Broadcast-Adresse:</span>
<span id="broadcast-address" class="font-mono text-purple-400 font-semibold">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Subnetzmaske:</span>
<span id="subnet-mask" class="font-mono text-gray-300">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Anzahl der Hosts:</span>
<span id="host-count" class="font-mono text-green-400 font-bold">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Erste Host-Adresse:</span>
<span id="first-host" class="font-mono text-blue-300">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
<span class="text-gray-400">Letzte Host-Adresse:</span>
<span id="last-host" class="font-mono text-blue-300">-</span>
</div>
</div>
</div>
<!-- Beispiel-Subnetze -->
<div id="examples" class="bg-gray-700 rounded p-6 mt-8">
<h3 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-2 mb-4">Beispiel-Subnetze (Private Adressbereiche)</h3>
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead>
<tr>
<th>Bereich</th>
<th>CIDR</th>
<th>Subnetzmaske</th>
<th>Beschreibung</th>
<th>Aktion</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-600">
<tr>
<td><code>192.168.0.0 - 192.168.255.255</code></td>
<td><code>/16</code> (Gesamt)</td>
<td><code>255.255.0.0</code></td>
<td>Klasse C (oft als /24 genutzt)</td>
<td><span class="example-link" data-ip="192.168.1.1" data-cidr="24">Beispiel /24</span></td>
</tr>
<tr>
<td><code>172.16.0.0 - 172.31.255.255</code></td>
<td><code>/12</code> (Gesamt)</td>
<td><code>255.240.0.0</code></td>
<td>Klasse B</td>
<td><span class="example-link" data-ip="172.16.10.5" data-cidr="16">Beispiel /16</span></td>
</tr>
<tr>
<td><code>10.0.0.0 - 10.255.255.255</code></td>
<td><code>/8</code> (Gesamt)</td>
<td><code>255.0.0.0</code></td>
<td>Klasse A</td>
<td><span class="example-link" data-ip="10.0.50.100" data-cidr="8">Beispiel /8</span></td>
</tr>
</tbody>
</table>
</div>
<p class="mt-4 text-xs text-gray-400">Klicken Sie auf "Beispiel", um die Felder oben auszufüllen und die Berechnung zu starten.</p>
<div id="examples" class="glass-card rounded-xl p-6 mt-8">
<h3 class="text-lg font-bold text-gray-400 uppercase tracking-wider border-b border-gray-700/50 pb-2 mb-4">
Beispiel-Subnetze (Private Adressbereiche)</h3>
<div class="overflow-x-auto">
<table class="min-w-full text-sm text-left text-gray-400">
<thead class="text-xs uppercase bg-gray-800/50 text-gray-200">
<tr>
<th scope="col" class="px-6 py-3">Bereich</th>
<th scope="col" class="px-6 py-3">CIDR</th>
<th scope="col" class="px-6 py-3">Subnetzmaske</th>
<th scope="col" class="px-6 py-3">Beschreibung</th>
<th scope="col" class="px-6 py-3">Aktion</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-700/50">
<tr class="hover:bg-gray-700/30 transition-colors">
<td class="px-6 py-4 font-mono text-white">192.168.0.0 - 192.168.255.255</td>
<td class="px-6 py-4 font-mono">/16 (Gesamt)</td>
<td class="px-6 py-4 font-mono">255.255.0.0</td>
<td class="px-6 py-4">Klasse C (oft als /24 genutzt)</td>
<td class="px-6 py-4"><span
class="example-link text-purple-400 hover:text-purple-300 cursor-pointer underline"
data-ip="192.168.1.1" data-cidr="24">Beispiel /24</span></td>
</tr>
<tr class="hover:bg-gray-700/30 transition-colors">
<td class="px-6 py-4 font-mono text-white">172.16.0.0 - 172.31.255.255</td>
<td class="px-6 py-4 font-mono">/12 (Gesamt)</td>
<td class="px-6 py-4 font-mono">255.240.0.0</td>
<td class="px-6 py-4">Klasse B</td>
<td class="px-6 py-4"><span
class="example-link text-purple-400 hover:text-purple-300 cursor-pointer underline"
data-ip="172.16.10.5" data-cidr="16">Beispiel /16</span></td>
</tr>
<tr class="hover:bg-gray-700/30 transition-colors">
<td class="px-6 py-4 font-mono text-white">10.0.0.0 - 10.255.255.255</td>
<td class="px-6 py-4 font-mono">/8 (Gesamt)</td>
<td class="px-6 py-4 font-mono">255.0.0.0</td>
<td class="px-6 py-4">Klasse A</td>
<td class="px-6 py-4"><span
class="example-link text-purple-400 hover:text-purple-300 cursor-pointer underline"
data-ip="10.0.50.100" data-cidr="8">Beispiel /8</span></td>
</tr>
</tbody>
</table>
</div>
<p class="mt-4 text-xs text-gray-500 italic">Klicken Sie auf "Beispiel", um die Felder oben auszufüllen und
die Berechnung zu starten.</p>
</div>
<!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div>
<!-- Globaler Fehlerbereich -->
<div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
</div>
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p>
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p> <!-- Footer mit Version hinzugefügt -->
<footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de"
class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
<!-- Footer mit Version hinzugefügt -->
</footer>
<!-- Nur das Skript für den Rechner laden -->
@@ -248,8 +338,8 @@
console.error('Failed to fetch version info:', error);
if (commitShaEl) commitShaEl.textContent = 'error';
if (globalErrorEl) { // Zeige Fehler global an, wenn Element existiert
globalErrorEl.textContent = `Error loading version: ${error.message}`;
globalErrorEl.classList.remove('hidden');
globalErrorEl.textContent = `Error loading version: ${error.message}`;
globalErrorEl.classList.remove('hidden');
}
}
}
@@ -257,4 +347,5 @@
});
</script>
</body>
</html>

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,90 +9,230 @@
<script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles -->
<style>
/* Einfacher Lade-Spinner */
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader {
border: 4px solid rgba(168, 85, 247, 0.3); /* Lila transparent */
border-left-color: #a855f7; /* Lila */
border: 4px solid rgba(168, 85, 247, 0.1);
/* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Ergebnis-Pre-Formatierung */
.result-pre {
white-space: pre-wrap;
word-break: break-all;
font-family: monospace;
background-color: #1f2937; /* Dunkelgrau */
color: #d1d5db; /* Hellgrau */
font-family: 'Courier New', Courier, monospace;
background-color: rgba(0, 0, 0, 0.3);
color: #e5e7eb;
padding: 1rem;
border-radius: 0.375rem; /* rounded-md */
max-height: 600px; /* Mehr Höhe für WHOIS */
border-radius: 0.375rem;
max-height: 600px;
overflow-y: auto;
font-size: 0.875rem; /* text-sm */
font-size: 0.875rem;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
/* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; }
nav a { color: #c4b5fd; text-decoration: none; white-space: nowrap; }
nav a:hover { color: #a78bfa; text-decoration: underline; }
header { background-color: #374151; padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
@media (min-width: 768px) { header { flex-direction: row; justify-content: space-between; } }
header h1 { font-size: 1.5rem; font-weight: bold; color: #e5e7eb; }
.hidden { display: none; }
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
</style>
</head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header>
<h1>uTools Network Suite</h1>
<body
class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav>
<ul>
<li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="whois-lookup.html" class="active-link">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li>
</ul>
</nav>
</header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6">
<div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 text-center">WHOIS Lookup</h1>
<h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">WHOIS Lookup</h1>
<!-- Bereich für WHOIS Lookup -->
<div class="mt-8 p-4 bg-gray-700 rounded">
<div class="flex flex-col sm:flex-row gap-2 mb-4">
<div class="mt-8 p-6 glass-card rounded-xl">
<div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="whois-query-input" placeholder="Enter domain or IP (e.g., google.com or 8.8.8.8)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono">
class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<button id="whois-lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out">
class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Lookup WHOIS
</button>
</div>
<div id="whois-lookup-error" class="text-red-400 mb-4 hidden"></div>
<div id="whois-lookup-results-section" class="hidden mt-4 border-t border-gray-600 pt-4">
<h3 class="text-lg font-semibold text-purple-300 mb-2">WHOIS Results for: <span id="whois-lookup-query" class="font-mono text-purple-400"></span></h3>
<div id="whois-lookup-loader" class="loader hidden mb-2"></div>
<pre id="whois-lookup-output" class="result-pre"></pre> <!-- Ergebnisbereich -->
<div id="whois-lookup-error"
class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded"></div>
<div id="whois-lookup-results-section" class="hidden mt-6 border-t border-gray-700/50 pt-6 fade-in">
<h3 class="text-lg font-semibold text-purple-300 mb-4 flex items-center gap-2">
<div class="w-1.5 h-6 bg-purple-500 rounded-full"></div>
WHOIS Results for: <span id="whois-lookup-query" class="font-mono text-purple-400 ml-1"></span>
</h3>
<div id="whois-lookup-loader" class="loader hidden mb-4"></div>
<pre id="whois-lookup-output" class="result-pre custom-scrollbar"></pre> <!-- Ergebnisbereich -->
</div>
</div>
<!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div>
<!-- Globaler Fehlerbereich -->
<div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<!-- Footer für Version -->
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p>
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p>
</footer>
<!-- Footer für Version -->
<footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de"
class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
</div>
<!-- Eigene JS-Logik für diese Seite -->
<script src="whois-lookup.js"></script>
</body>
</html>

View File

@@ -43,6 +43,11 @@ document.addEventListener('DOMContentLoaded', () => {
* @param {function} displayFn - Funktion zur Formatierung und Anzeige der Daten im outputElement.
*/
async function fetchAndDisplay(endpoint, params, resultsSection, loaderElement, errorElement, queryElement, outputElement, displayFn) {
// Reset animation
resultsSection.classList.remove('fade-in');
void resultsSection.offsetWidth; // Trigger reflow
resultsSection.classList.add('fade-in');
resultsSection.classList.remove('hidden');
loaderElement.classList.remove('hidden');
errorElement.classList.add('hidden');
@@ -94,10 +99,10 @@ document.addEventListener('DOMContentLoaded', () => {
function displayWhoisResults(data, outputEl) {
// WHOIS data can be large and unstructured, display as raw text
if (typeof data.result === 'string') {
outputEl.textContent = data.result; // Display raw text
outputEl.textContent = data.result; // Display raw text
} else {
// Fallback if the result is not a string (shouldn't happen with current backend)
outputEl.textContent = JSON.stringify(data.result, null, 2);
// Fallback if the result is not a string (shouldn't happen with current backend)
outputEl.textContent = JSON.stringify(data.result, null, 2);
}
}