commit 19b49c06edfd4f6cfc45c4aa18ac5d29f3fdb6dc
Author: ffff:63.141.240.242 <ffff:63.141.240.242@hub.scroll.pub> Date: 2025-01-01 23:49:52 +0000 Subject: updated script.js diff --git a/script.js b/script.js index 4393223..363c7af 100644 --- a/script.js +++ b/script.js @@ -5,7 +5,7 @@ document.addEventListener("DOMContentLoaded", () => { const error = document.getElementById("error"); const displayResults = (data) => { - document.getElementById("country_name").textContent = data.country; + document.getElementById("country").textContent = data.country; document.getElementById("city").textContent = data.city; document.getElementById("region").textContent = data.region; document.getElementById("timezone").textContent = data.timezone; @@ -35,9 +35,7 @@ document.addEventListener("DOMContentLoaded", () => { error.classList.add("hidden"); try { - const response = await fetch( - `https://api.ipgeolocation.io/ipgeo?apiKey=68f7a83f9d84466bb5054f6b3e8da8a6&ip=${ipAddress}&fields=city&output=json`, - ); + const response = await fetch(`https://ipapi.co/${ipAddress}/json/`); const data = await response.json(); if (data.error) {
commit 31e1d5813985a9251b7d7f82f319a01479b849c1
Author: ffff:63.141.240.242 <ffff:63.141.240.242@hub.scroll.pub> Date: 2025-01-01 23:49:32 +0000 Subject: updated script.js diff --git a/script.js b/script.js index 00d45a5..4393223 100644 --- a/script.js +++ b/script.js @@ -1,53 +1,55 @@ -document.addEventListener('DOMContentLoaded', () => { - const form = document.getElementById('lookupForm'); - const loader = document.getElementById('loader'); - const results = document.getElementById('results'); - const error = document.getElementById('error'); +document.addEventListener("DOMContentLoaded", () => { + const form = document.getElementById("lookupForm"); + const loader = document.getElementById("loader"); + const results = document.getElementById("results"); + const error = document.getElementById("error"); const displayResults = (data) => { - document.getElementById('country').textContent = data.country; - document.getElementById('city').textContent = data.city; - document.getElementById('region').textContent = data.region; - document.getElementById('timezone').textContent = data.timezone; - document.getElementById('isp').textContent = data.isp; - - loader.classList.add('hidden'); - results.classList.remove('hidden'); - error.classList.add('hidden'); + document.getElementById("country_name").textContent = data.country; + document.getElementById("city").textContent = data.city; + document.getElementById("region").textContent = data.region; + document.getElementById("timezone").textContent = data.timezone; + document.getElementById("isp").textContent = data.isp; + + loader.classList.add("hidden"); + results.classList.remove("hidden"); + error.classList.add("hidden"); }; const showError = () => { - loader.classList.add('hidden'); - results.classList.add('hidden'); - error.classList.remove('hidden'); + loader.classList.add("hidden"); + results.classList.add("hidden"); + error.classList.remove("hidden"); }; - form.addEventListener('submit', async (e) => { + form.addEventListener("submit", async (e) => { e.preventDefault(); - - const ipInput = document.getElementById('ipInput'); + + const ipInput = document.getElementById("ipInput"); const ipAddress = ipInput.value.trim(); - + if (!ipAddress) return; - loader.classList.remove('hidden'); - results.classList.add('hidden'); - error.classList.add('hidden'); + loader.classList.remove("hidden"); + results.classList.add("hidden"); + error.classList.add("hidden"); try { - const response = await fetch(`https://ipapi.co/${ipAddress}/json/`); + const response = await fetch( + `https://api.ipgeolocation.io/ipgeo?apiKey=68f7a83f9d84466bb5054f6b3e8da8a6&ip=${ipAddress}&fields=city&output=json`, + ); const data = await response.json(); - + if (data.error) { - throw new Error('Invalid IP address'); + throw new Error("Invalid IP address"); } displayResults({ - country: data.country_name || 'N/A', - city: data.city || 'N/A', - region: data.region || 'N/A', - timezone: data.timezone || 'N/A', - isp: data.org || 'N/A' + country: data.country_name || "N/A", + city: data.city || "N/A", + region: data.region || "N/A", + timezone: data.timezone || "N/A", + isp: data.org || "N/A", }); } catch (err) { showError();
commit 06b87518a2c9b85b33eee819497f6d88d51674f5
Author: root <root@hub.scroll.pub> Date: 2025-01-01 23:43:24 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..3303d4c --- /dev/null +++ b/body.html @@ -0,0 +1,53 @@ +<header> + <h1>IP Lookup</h1> + <p>Discover location details from any IP address</p> +</header> + +<main> + <section class="search-container"> + <form id="lookupForm" aria-label="IP lookup form"> + <input type="text" id="ipInput" placeholder="Enter IP address" pattern="^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" aria-label="IP address input"> + <button type="submit" aria-label="Look up IP">Search</button> + </form> + </section> + + <section class="results-container" aria-live="polite"> + <div id="loader" class="hidden"> + <div class="spinner"></div> + </div> + <div id="results" class="hidden"> + <div class="result-card"> + <h2>Location Details</h2> + <div class="result-grid"> + <div class="result-item"> + <span class="label">Country:</span> + <span id="country"></span> + </div> + <div class="result-item"> + <span class="label">City:</span> + <span id="city"></span> + </div> + <div class="result-item"> + <span class="label">Region:</span> + <span id="region"></span> + </div> + <div class="result-item"> + <span class="label">Timezone:</span> + <span id="timezone"></span> + </div> + <div class="result-item"> + <span class="label">ISP:</span> + <span id="isp"></span> + </div> + </div> + </div> + </div> + <div id="error" class="hidden"> + <p>Unable to find location details for this IP address. Please try again.</p> + </div> + </section> +</main> + +<footer> + <p>Created with care by IP Lookup Team</p> +</footer> diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..233798a --- /dev/null +++ b/index.scroll @@ -0,0 +1,8 @@ +buildHtml +baseUrl https://iplookup.scroll.pub +metaTags +editButton /edit.html +title IP Lookup - Find Location Details From Any IP Address +style.css +body.html +script.js diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..2f1c387 --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_0131RVRYujmXz8ATQ9rHV3Gn", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "Let me create an IP lookup website with a clean and professional design.\n\n---domain---\niplookup.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://iplookup.scroll.pub\nmetaTags\neditButton /edit.html\ntitle IP Lookup - Find Location Details From Any IP Address\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <h1>IP Lookup</h1>\n <p>Discover location details from any IP address</p>\n</header>\n\n<main>\n <section class=\"search-container\">\n <form id=\"lookupForm\" aria-label=\"IP lookup form\">\n <input type=\"text\" id=\"ipInput\" placeholder=\"Enter IP address\" pattern=\"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$\" aria-label=\"IP address input\">\n <button type=\"submit\" aria-label=\"Look up IP\">Search</button>\n </form>\n </section>\n\n <section class=\"results-container\" aria-live=\"polite\">\n <div id=\"loader\" class=\"hidden\">\n <div class=\"spinner\"></div>\n </div>\n <div id=\"results\" class=\"hidden\">\n <div class=\"result-card\">\n <h2>Location Details</h2>\n <div class=\"result-grid\">\n <div class=\"result-item\">\n <span class=\"label\">Country:</span>\n <span id=\"country\"></span>\n </div>\n <div class=\"result-item\">\n <span class=\"label\">City:</span>\n <span id=\"city\"></span>\n </div>\n <div class=\"result-item\">\n <span class=\"label\">Region:</span>\n <span id=\"region\"></span>\n </div>\n <div class=\"result-item\">\n <span class=\"label\">Timezone:</span>\n <span id=\"timezone\"></span>\n </div>\n <div class=\"result-item\">\n <span class=\"label\">ISP:</span>\n <span id=\"isp\"></span>\n </div>\n </div>\n </div>\n </div>\n <div id=\"error\" class=\"hidden\">\n <p>Unable to find location details for this IP address. Please try again.</p>\n </div>\n </section>\n</main>\n\n<footer>\n <p>Created with care by IP Lookup Team</p>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #2c3e50;\n --accent-color: #3498db;\n --background-color: #f5f6fa;\n --card-background: #ffffff;\n --text-color: #2c3e50;\n --error-color: #e74c3c;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n background: var(--background-color);\n color: var(--text-color);\n line-height: 1.6;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\nheader {\n background: var(--primary-color);\n color: white;\n padding: 2rem 1rem;\n text-align: center;\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n}\n\nheader h1 {\n font-size: 2.5rem;\n margin-bottom: 0.5rem;\n}\n\nmain {\n flex: 1;\n padding: 2rem 1rem;\n max-width: 800px;\n margin: 0 auto;\n width: 100%;\n}\n\n.search-container {\n margin-bottom: 2rem;\n}\n\nform {\n display: flex;\n gap: 1rem;\n max-width: 600px;\n margin: 0 auto;\n}\n\ninput {\n flex: 1;\n padding: 1rem;\n border: 2px solid var(--primary-color);\n border-radius: 8px;\n font-size: 1rem;\n transition: border-color 0.3s ease;\n}\n\ninput:focus {\n outline: none;\n border-color: var(--accent-color);\n box-shadow: 0 0 0 3px rgba(52,152,219,0.2);\n}\n\nbutton {\n padding: 1rem 2rem;\n background: var(--accent-color);\n color: white;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-size: 1rem;\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\nbutton:hover {\n background: #2980b9;\n transform: translateY(-2px);\n}\n\n.result-card {\n background: var(--card-background);\n border-radius: 12px;\n padding: 2rem;\n box-shadow: 0 4px 20px rgba(0,0,0,0.1);\n animation: slideUp 0.5s ease;\n}\n\n.result-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1.5rem;\n margin-top: 1.5rem;\n}\n\n.result-item {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.label {\n font-weight: 600;\n color: var(--primary-color);\n}\n\n.hidden {\n display: none;\n}\n\n.spinner {\n width: 50px;\n height: 50px;\n border: 5px solid #f3f3f3;\n border-top: 5px solid var(--accent-color);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin: 2rem auto;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n@keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: var(--primary-color);\n color: white;\n margin-top: auto;\n}\n\n@media (max-width: 600px) {\n form {\n flex-direction: column;\n }\n \n button {\n width: 100%;\n }\n \n .result-grid {\n grid-template-columns: 1fr;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const form = document.getElementById('lookupForm');\n const loader = document.getElementById('loader');\n const results = document.getElementById('results');\n const error = document.getElementById('error');\n\n const displayResults = (data) => {\n document.getElementById('country').textContent = data.country;\n document.getElementById('city').textContent = data.city;\n document.getElementById('region').textContent = data.region;\n document.getElementById('timezone').textContent = data.timezone;\n document.getElementById('isp').textContent = data.isp;\n \n loader.classList.add('hidden');\n results.classList.remove('hidden');\n error.classList.add('hidden');\n };\n\n const showError = () => {\n loader.classList.add('hidden');\n results.classList.add('hidden');\n error.classList.remove('hidden');\n };\n\n form.addEventListener('submit', async (e) => {\n e.preventDefault();\n \n const ipInput = document.getElementById('ipInput');\n const ipAddress = ipInput.value.trim();\n \n if (!ipAddress) return;\n\n loader.classList.remove('hidden');\n results.classList.add('hidden');\n error.classList.add('hidden');\n\n try {\n const response = await fetch(`https://ipapi.co/${ipAddress}/json/`);\n const data = await response.json();\n \n if (data.error) {\n throw new Error('Invalid IP address');\n }\n\n displayResults({\n country: data.country_name || 'N/A',\n city: data.city || 'N/A',\n region: data.region || 'N/A',\n timezone: data.timezone || 'N/A',\n isp: data.org || 'N/A'\n });\n } catch (err) {\n showError();\n }\n });\n});\n\n---end---\n\nThis implementation creates a beautiful and functional IP lookup website with the following features:\n\n1. Clean, semantic HTML5 structure\n2. Responsive design that works on all devices\n3. Modern animations and transitions\n4. Error handling and loading states\n5. Accessibility features (ARIA labels, semantic HTML)\n6. Beautiful card-based design with shadows and animations\n7. CSS Grid and Flexbox for modern layouts\n8. Form validation for IP addresses\n9. Clean error handling and user feedback\n10. Professional color scheme and typography\n\nThe website uses the free ipapi.co API to fetch IP information. The design features a clean, modern interface with smooth animations, proper loading states, and error handling. It's fully responsive and works great on both desktop and mobile devices." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 277, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 2451 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..c498277 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# iplookup.scroll.pub +Website generated by Claude from prompt: make an ip2location look up \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..00d45a5 --- /dev/null +++ b/script.js @@ -0,0 +1,56 @@ +document.addEventListener('DOMContentLoaded', () => { + const form = document.getElementById('lookupForm'); + const loader = document.getElementById('loader'); + const results = document.getElementById('results'); + const error = document.getElementById('error'); + + const displayResults = (data) => { + document.getElementById('country').textContent = data.country; + document.getElementById('city').textContent = data.city; + document.getElementById('region').textContent = data.region; + document.getElementById('timezone').textContent = data.timezone; + document.getElementById('isp').textContent = data.isp; + + loader.classList.add('hidden'); + results.classList.remove('hidden'); + error.classList.add('hidden'); + }; + + const showError = () => { + loader.classList.add('hidden'); + results.classList.add('hidden'); + error.classList.remove('hidden'); + }; + + form.addEventListener('submit', async (e) => { + e.preventDefault(); + + const ipInput = document.getElementById('ipInput'); + const ipAddress = ipInput.value.trim(); + + if (!ipAddress) return; + + loader.classList.remove('hidden'); + results.classList.add('hidden'); + error.classList.add('hidden'); + + try { + const response = await fetch(`https://ipapi.co/${ipAddress}/json/`); + const data = await response.json(); + + if (data.error) { + throw new Error('Invalid IP address'); + } + + displayResults({ + country: data.country_name || 'N/A', + city: data.city || 'N/A', + region: data.region || 'N/A', + timezone: data.timezone || 'N/A', + isp: data.org || 'N/A' + }); + } catch (err) { + showError(); + } + }); +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..75b1e66 --- /dev/null +++ b/style.css @@ -0,0 +1,165 @@ +:root { + --primary-color: #2c3e50; + --accent-color: #3498db; + --background-color: #f5f6fa; + --card-background: #ffffff; + --text-color: #2c3e50; + --error-color: #e74c3c; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', system-ui, sans-serif; + background: var(--background-color); + color: var(--text-color); + line-height: 1.6; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +header { + background: var(--primary-color); + color: white; + padding: 2rem 1rem; + text-align: center; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); +} + +header h1 { + font-size: 2.5rem; + margin-bottom: 0.5rem; +} + +main { + flex: 1; + padding: 2rem 1rem; + max-width: 800px; + margin: 0 auto; + width: 100%; +} + +.search-container { + margin-bottom: 2rem; +} + +form { + display: flex; + gap: 1rem; + max-width: 600px; + margin: 0 auto; +} + +input { + flex: 1; + padding: 1rem; + border: 2px solid var(--primary-color); + border-radius: 8px; + font-size: 1rem; + transition: border-color 0.3s ease; +} + +input:focus { + outline: none; + border-color: var(--accent-color); + box-shadow: 0 0 0 3px rgba(52,152,219,0.2); +} + +button { + padding: 1rem 2rem; + background: var(--accent-color); + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 1rem; + transition: transform 0.2s ease, background-color 0.2s ease; +} + +button:hover { + background: #2980b9; + transform: translateY(-2px); +} + +.result-card { + background: var(--card-background); + border-radius: 12px; + padding: 2rem; + box-shadow: 0 4px 20px rgba(0,0,0,0.1); + animation: slideUp 0.5s ease; +} + +.result-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; + margin-top: 1.5rem; +} + +.result-item { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.label { + font-weight: 600; + color: var(--primary-color); +} + +.hidden { + display: none; +} + +.spinner { + width: 50px; + height: 50px; + border: 5px solid #f3f3f3; + border-top: 5px solid var(--accent-color); + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 2rem auto; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +footer { + text-align: center; + padding: 2rem; + background: var(--primary-color); + color: white; + margin-top: auto; +} + +@media (max-width: 600px) { + form { + flex-direction: column; + } + + button { + width: 100%; + } + + .result-grid { + grid-template-columns: 1fr; + } +}