Changes to geoip.scroll.pub

root
root
4 days ago
Initial commit
index.scroll
Changed around line 1
+ buildHtml
+ baseUrl https://geoip.scroll.pub
+ metaTags
+ editButton /edit.html
+ title IP Geolocation Explorer
+ style.css
+ header
+ class header-dark
+ div
+ class container
+ h1 IP Geolocation Explorer
+ p Explore IP addresses worldwide
+ main
+ class main-content
+ section
+ class search-section
+ div
+ class search-container
+ div
+ class country-filter
+ select
+ id countrySelect
+ class select-dark
+ option Select Country
+ value ""
+ div
+ class state-filter
+ select
+ id stateSelect
+ class select-dark
+ option Select State
+ value ""
+ div
+ class search-bar
+ input
+ type text
+ id searchInput
+ placeholder Search by IP, City, or Postal Code
+ class input-dark
+ section
+ class results-section
+ div
+ class table-container
+ table
+ id resultsTable
+ class table-dark
+ thead
+ tr
+ th IP Range
+ th Country
+ th State
+ th City
+ th Postal Code
+ tbody
+ id tableBody
+ div
+ class loading-spinner
+ id loader
+ span Loading...
+ footer
+ class footer-dark
+ div
+ class container
+ p Built with modern web technologies
+ nav
+ class footer-nav
+ a Documentation
+ href #
+ a API
+ href #
+ a About
+ href #
+ script.js
prompt.json
Changed around line 1
+ {
+ "id": "msg_01RaGkkyvpPnKASro8u5gNF7",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "I'll help create this IP Geolocation portal. For the domain, I suggest:\n\n---domain---\ngeoip.scroll.pub\n---index.scroll---\nbuildHtml\nbaseUrl https://geoip.scroll.pub\nmetaTags\neditButton /edit.html\ntitle IP Geolocation Explorer\nstyle.css\nheader\n class header-dark\n div\n class container\n h1 IP Geolocation Explorer\n p Explore IP addresses worldwide\nmain\n class main-content\n section\n class search-section\n div\n class search-container\n div\n class country-filter\n select\n id countrySelect\n class select-dark\n option Select Country\n value \"\"\n div\n class state-filter\n select\n id stateSelect\n class select-dark\n option Select State\n value \"\"\n div\n class search-bar\n input\n type text\n id searchInput\n placeholder Search by IP, City, or Postal Code\n class input-dark\n section\n class results-section\n div\n class table-container\n table\n id resultsTable\n class table-dark\n thead\n tr\n th IP Range\n th Country\n th State\n th City\n th Postal Code\n tbody\n id tableBody\ndiv\n class loading-spinner\n id loader\n span Loading...\nfooter\n class footer-dark\n div\n class container\n p Built with modern web technologies\n nav\n class footer-nav\n a Documentation\n href #\n a API\n href #\n a About\n href #\nscript.js\n---style.css---\n:root {\n --primary-color: #2a2d3e;\n --secondary-color: #1f2133;\n --accent-color: #6c63ff;\n --text-primary: #ffffff;\n --text-secondary: #b3b3b3;\n --border-color: #3f4156;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n background-color: var(--secondary-color);\n color: var(--text-primary);\n line-height: 1.6;\n}\n\n.header-dark {\n background-color: var(--primary-color);\n padding: 2rem 0;\n box-shadow: 0 2px 10px rgba(0,0,0,0.2);\n}\n\n.container {\n max-width: 1200px;\n margin: 0 auto;\n padding: 0 1rem;\n}\n\n.search-section {\n padding: 2rem 0;\n}\n\n.search-container {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1rem;\n margin-bottom: 2rem;\n}\n\n.select-dark, .input-dark {\n width: 100%;\n padding: 0.8rem 1rem;\n border: 1px solid var(--border-color);\n border-radius: 6px;\n background-color: var(--primary-color);\n color: var(--text-primary);\n font-size: 1rem;\n transition: all 0.3s ease;\n}\n\n.select-dark:focus, .input-dark:focus {\n outline: none;\n border-color: var(--accent-color);\n box-shadow: 0 0 0 2px rgba(108, 99, 255, 0.2);\n}\n\n.table-dark {\n width: 100%;\n border-collapse: collapse;\n background-color: var(--primary-color);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.table-dark th, .table-dark td {\n padding: 1rem;\n text-align: left;\n border-bottom: 1px solid var(--border-color);\n}\n\n.table-dark th {\n background-color: var(--secondary-color);\n font-weight: 600;\n}\n\n.table-dark tbody tr:hover {\n background-color: rgba(108, 99, 255, 0.1);\n}\n\n.loading-spinner {\n display: none;\n justify-content: center;\n align-items: center;\n padding: 2rem;\n color: var(--text-secondary);\n}\n\n.footer-dark {\n background-color: var(--primary-color);\n padding: 2rem 0;\n margin-top: 3rem;\n}\n\n.footer-nav {\n display: flex;\n gap: 2rem;\n margin-top: 1rem;\n}\n\n.footer-nav a {\n color: var(--text-secondary);\n text-decoration: none;\n transition: color 0.3s ease;\n}\n\n.footer-nav a:hover {\n color: var(--accent-color);\n}\n\n@media (max-width: 768px) {\n .search-container {\n grid-template-columns: 1fr;\n }\n \n .table-container {\n overflow-x: auto;\n }\n}\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const countrySelect = document.getElementById('countrySelect');\n const stateSelect = document.getElementById('stateSelect');\n const searchInput = document.getElementById('searchInput');\n const tableBody = document.getElementById('tableBody');\n const loader = document.getElementById('loader');\n\n let countries = [];\n let states = [];\n let ipData = [];\n\n // Cache for data\n const cache = {\n countries: null,\n states: null,\n ipData: null\n };\n\n async function fetchData(url) {\n try {\n const response = await fetch(url);\n if (!response.ok) throw new Error('Network response was not ok');\n return await response.json();\n } catch (error) {\n console.error('Error fetching data:', error);\n return null;\n }\n }\n\n async function initializeData() {\n loader.style.display = 'flex';\n\n // Fetch all data in parallel\n const [countriesData, statesData, ipDataRaw] = await Promise.all([\n fetchData('https://cscd.api.ipvi.net/json/countries.json'),\n fetchData('https://cscd.api.ipvi.net/json/states.json'),\n fetch('https://raw.githubusercontent.com/axelawh/geofeed/refs/heads/main/location.csv')\n .then(response => response.text())\n ]);\n\n if (countriesData) {\n cache.countries = countriesData;\n populateCountrySelect(countriesData);\n }\n\n if (statesData) {\n cache.states = statesData;\n }\n\n if (ipDataRaw) {\n cache.ipData = parseCSV(ipDataRaw);\n displayResults(cache.ipData.slice(0, 50)); // Show first 50 results initially\n }\n\n loader.style.display = 'none';\n }\n\n function parseCSV(csv) {\n return csv.split('\\n')\n .filter(line => line.trim())\n .map(line => {\n const [ipRange, countryCode, stateCode, city, postalCode] = line.split(',');\n return { ipRange, countryCode, stateCode, city, postalCode };\n });\n }\n\n function populateCountrySelect(countries) {\n countrySelect.innerHTML = '';\n countries.sort((a, b) => a.name.localeCompare(b.name))\n .forEach(country => {\n const option = document.createElement('option');\n option.value = country.iso2;\n option.textContent = `${country.emoji} ${country.name}`;\n countrySelect.appendChild(option);\n });\n }\n\n function updateStateSelect(countryCode) {\n stateSelect.innerHTML = '';\n if (!countryCode) return;\n\n const countryStates = cache.states.filter(state => state.country_code === countryCode);\n countryStates.sort((a, b) => a.name.localeCompare(b.name))\n .forEach(state => {\n const option = document.createElement('option');\n option.value = state.state_code;\n option.textContent = state.name;\n stateSelect.appendChild(option);\n });\n }\n\n function displayResults(results) {\n tableBody.innerHTML = '';\n results.forEach(result => {\n const tr = document.createElement('tr');\n tr.innerHTML = `\n ${result.ipRange}\n ${result.countryCode}\n ${result.stateCode}\n ${result.city || '-'}\n ${result.postalCode || '-'}\n `;\n tableBody.appendChild(tr);\n });\n }\n\n function filterResults() {\n const searchTerm = searchInput.value.toLowerCase();\n const countryCode = countrySelect.value;\n const stateCode = stateSelect.value;\n\n let filtered = cache.ipData;\n\n if (countryCode) {\n filtered = filtered.filter(item => item.countryCode === countryCode);\n }\n\n if (stateCode) {\n filtered = filtered.filter(item => item.stateCode === stateCode);\n }\n\n if (searchTerm) {\n filtered = filtered.filter(item =>\n item.ipRange.toLowerCase().includes(searchTerm) ||\n item.city?.toLowerCase().includes(searchTerm) ||\n item.postalCode?.toLowerCase().includes(searchTerm)\n );\n }\n\n displayResults(filtered.slice(0, 50));\n }\n\n // Event Listeners\n countrySelect.addEventListener('change', () => {\n updateStateSelect(countrySelect.value);\n filterResults();\n });\n\n stateSelect.addEventListener('change', filterResults);\n\n searchInput.addEventListener('input', debounce(filterResults, 300));\n\n function debounce(func, wait) {\n let timeout;\n return function executedFunction(...args) {\n const later = () => {\n clearTimeout(timeout);\n func(...args);\n };\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n }\n\n // Initialize the application\n initializeData();\n});\n---end---\n\nThis implementation creates a sleek, responsive IP geolocation explorer with a dark theme. It features:\n- Real-time filtering by country and state\n- Fast search functionality\n- Responsive design that works on all devices\n- Efficient data handling with caching\n- Clean, modern UI with smooth transitions\n- Accessibility-friendly markup\n- Performance optimizations with debouncing\n- Error handling for data fetching\n- Progressive loading of results\n\nThe interface is built with pure HTML, CSS, and JavaScript, requiring no external dependencies. The dark theme uses a sophisticated color palette that's easy on the eyes, with subtle animations and transitions for a polished user experience."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 2182,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 2817
+ }
+ }
readme.scroll
Changed around line 1
+ # geoip.scroll.pub
+
+ Prompt: website
+ Agent: claude
+ Model: claude-3-5-sonnet-20241022
+
+ ## User prompt
+ 🌍 IP Geolocation Portal Development Request Objective: Build an interactive web portal that allows users to explore IP addresses by country and state, using data from a geofeed CSV. The portal should allow users to: Filter by Country & State: Select a country from a dropdown, dynamically loading only the corresponding states. Search by Various Fields: A unified search bar for IP, state, city, and postal code lookups. Integrate External Data Sources: Use external JSON sources for country and state information. Provide a Minimalistic, Responsive UI: A dark-themed, fast-loading interface. Efficiently Handle Large Datasets: Ensure smooth filtering and searching across thousands of records. πŸ”— Data Sources 1. Geofeed CSV (IP Data) The IP data is structured in a CSV format with the following structure: IP Range, Country Code, State Code, City, Postal Code πŸ“„ Geofeed File: https://raw.githubusercontent.com/axelawh/geofeed/refs/heads/main/location.csv πŸ“ Example Entries from Geofeed: 2a12:bec4:12a3:f0::/60,US,US-CA,Hollywood Hills West,90046 2a12:bec4:12a3:100::/60,US,US-CA,Los Angeles, 2605:e000:1609:c300::/56,CA,CA-ON,Toronto,M5J 2a12:bec4:12a3:f0::/60 β†’ IPv6 range US β†’ Country code US-CA β†’ ISO State code Hollywood Hills West β†’ City 90046 β†’ Postal code 2. Country Information (JSON API) Contains metadata about countries, including names, ISO codes, regions, timezones, and currency details. πŸ“„ Countries JSON: https://cscd.api.ipvi.net/json/countries.json πŸ“ Example Entries from Country Data: [ { "id": 1, "name": "Afghanistan", "iso3": "AFG", "iso2": "AF", "numeric_code": "004", "phonecode": "93", "capital": "Kabul", "currency": "AFN", "currency_name": "Afghan afghani", "currency_symbol": "Ψ‹", "region": "Asia", "subregion": "Southern Asia", "latitude": "33.00000000", "longitude": "65.00000000", "emoji": "πŸ‡¦πŸ‡«" }, { "id": 2, "name": "Albania", "iso3": "ALB", "iso2": "AL", "numeric_code": "008", "phonecode": "355", "capital": "Tirana", "currency": "ALL", "currency_name": "Albanian lek", "currency_symbol": "L", "region": "Europe", "subregion": "Southern Europe", "latitude": "41.00000000", "longitude": "20.00000000", "emoji": "πŸ‡¦πŸ‡±" } ] The country list provides ISO codes (iso2, iso3), phone codes, capital cities, and currency information. 3. State Information (JSON API) Provides details about states and provinces, including names, country codes, and geographic coordinates. πŸ“„ States JSON: https://cscd.api.ipvi.net/json/states.json πŸ“ Example Entries from State Data: [ { "id": 3901, "name": "Badakhshan", "country_id": 1, "country_code": "AF", "country_name": "Afghanistan", "state_code": "BDS", "latitude": "36.73477250", "longitude": "70.81199530" }, { "id": 3871, "name": "Badghis", "country_id": 1, "country_code": "AF", "country_name": "Afghanistan", "state_code": "BDG", "latitude": "35.16713390", "longitude": "63.76953840" }, { "id": 3884, "name": "Balkh", "country_id": 1, "country_code": "AF", "country_name": "Afghanistan", "state_code": "BAL", "latitude": "36.75506030", "longitude": "66.89753720" } ] Each entry provides the state name, country association, state code, and GPS coordinates. 🌐 Features Required 1. Country & State Filtering A dropdown that lists countries from the Countries JSON. When a country is selected, fetch and populate only the corresponding states from the States JSON. 2. Search Functionality A single search bar that can find IP addresses based on: IP Address (e.g., 2a12:bec4:12a3:f0::/60) State Name (e.g., California) City Name (e.g., Los Angeles) Postal Code (e.g., 90046) Country Code (e.g., US) 3. Display Results in a Table The results should be displayed in a structured table, with columns for: IP Range Country (Flag + Name) State City Postal Code 4. Design & User Experience A dark-themed UI, fast and responsive for both desktop & mobile. Smooth filtering & search, without requiring full page reloads. Auto-complete for search input to improve user experience. Data Handling: Fetch and cache JSON data to minimize requests πŸ’‘ Notes for Development Optimize Data Loading: Since the dataset is large, ensure efficient handling using indexed searches or database caching. Live Filtering: Use JavaScript to filter the results in real-time without reloading the page. Handle Missing Data Gracefully: Some IP records may not have postal codes or city namesβ€”ensure the interface displays them cleanly. Flag Integration: Display country flags dynamically using ISO codes. 🎯 Expected Outcome A polished IP geolocation lookup tool where users can quickly filter and search through IP address data by country, state, or any related field, with smooth navigation and a responsive UI.
+
+ ## System prompt
+ You are an expert web developer. Create a website based on this request: "🌍 IP Geolocation Portal Development Request Objective: Build an interactive web portal that allows users to explore IP addresses by country and state, using data from a geofeed CSV. The portal should allow users to: Filter by Country & State: Select a country from a dropdown, dynamically loading only the corresponding states. Search by Various Fields: A unified search bar for IP, state, city, and postal code lookups. Integrate External Data Sources: Use external JSON sources for country and state information. Provide a Minimalistic, Responsive UI: A dark-themed, fast-loading interface. Efficiently Handle Large Datasets: Ensure smooth filtering and searching across thousands of records. πŸ”— Data Sources 1. Geofeed CSV (IP Data) The IP data is structured in a CSV format with the following structure: IP Range, Country Code, State Code, City, Postal Code πŸ“„ Geofeed File: https://raw.githubusercontent.com/axelawh/geofeed/refs/heads/main/location.csv πŸ“ Example Entries from Geofeed: 2a12:bec4:12a3:f0::/60,US,US-CA,Hollywood Hills West,90046 2a12:bec4:12a3:100::/60,US,US-CA,Los Angeles, 2605:e000:1609:c300::/56,CA,CA-ON,Toronto,M5J 2a12:bec4:12a3:f0::/60 β†’ IPv6 range US β†’ Country code US-CA β†’ ISO State code Hollywood Hills West β†’ City 90046 β†’ Postal code 2. Country Information (JSON API) Contains metadata about countries, including names, ISO codes, regions, timezones, and currency details. πŸ“„ Countries JSON: https://cscd.api.ipvi.net/json/countries.json πŸ“ Example Entries from Country Data: [ { "id": 1, "name": "Afghanistan", "iso3": "AFG", "iso2": "AF", "numeric_code": "004", "phonecode": "93", "capital": "Kabul", "currency": "AFN", "currency_name": "Afghan afghani", "currency_symbol": "Ψ‹", "region": "Asia", "subregion": "Southern Asia", "latitude": "33.00000000", "longitude": "65.00000000", "emoji": "πŸ‡¦πŸ‡«" }, { "id": 2, "name": "Albania", "iso3": "ALB", "iso2": "AL", "numeric_code": "008", "phonecode": "355", "capital": "Tirana", "currency": "ALL", "currency_name": "Albanian lek", "currency_symbol": "L", "region": "Europe", "subregion": "Southern Europe", "latitude": "41.00000000", "longitude": "20.00000000", "emoji": "πŸ‡¦πŸ‡±" } ] The country list provides ISO codes (iso2, iso3), phone codes, capital cities, and currency information. 3. State Information (JSON API) Provides details about states and provinces, including names, country codes, and geographic coordinates. πŸ“„ States JSON: https://cscd.api.ipvi.net/json/states.json πŸ“ Example Entries from State Data: [ { "id": 3901, "name": "Badakhshan", "country_id": 1, "country_code": "AF", "country_name": "Afghanistan", "state_code": "BDS", "latitude": "36.73477250", "longitude": "70.81199530" }, { "id": 3871, "name": "Badghis", "country_id": 1, "country_code": "AF", "country_name": "Afghanistan", "state_code": "BDG", "latitude": "35.16713390", "longitude": "63.76953840" }, { "id": 3884, "name": "Balkh", "country_id": 1, "country_code": "AF", "country_name": "Afghanistan", "state_code": "BAL", "latitude": "36.75506030", "longitude": "66.89753720" } ] Each entry provides the state name, country association, state code, and GPS coordinates. 🌐 Features Required 1. Country & State Filtering A dropdown that lists countries from the Countries JSON. When a country is selected, fetch and populate only the corresponding states from the States JSON. 2. Search Functionality A single search bar that can find IP addresses based on: IP Address (e.g., 2a12:bec4:12a3:f0::/60) State Name (e.g., California) City Name (e.g., Los Angeles) Postal Code (e.g., 90046) Country Code (e.g., US) 3. Display Results in a Table The results should be displayed in a structured table, with columns for: IP Range Country (Flag + Name) State City Postal Code 4. Design & User Experience A dark-themed UI, fast and responsive for both desktop & mobile. Smooth filtering & search, without requiring full page reloads. Auto-complete for search input to improve user experience. Data Handling: Fetch and cache JSON data to minimize requests πŸ’‘ Notes for Development Optimize Data Loading: Since the dataset is large, ensure efficient handling using indexed searches or database caching. Live Filtering: Use JavaScript to filter the results in real-time without reloading the page. Handle Missing Data Gracefully: Some IP records may not have postal codes or city namesβ€”ensure the interface displays them cleanly. Flag Integration: Display country flags dynamically using ISO codes. 🎯 Expected Outcome A polished IP geolocation lookup tool where users can quickly filter and search through IP address data by country, state, or any related field, with smooth navigation and a responsive UI."
+
+ Requirements:
+ - Use only Scroll, CSS, and JavaScript (NO frameworks, NO external dependencies)
+ - Create clean, semantic HTML5
+ - Make it mobile-responsive
+ - Follow modern best practices and accessibility guidelines
+ - Keep it simple but professional
+ - Use only relative links and no external resources
+ - Do not put a copyright symbol or all rights reserved in the footer.
+ - Make it beautiful. Dazzling. Advanced used of CSS.
+
+ As a refresher, for doing the html body, Scroll is a whitespace based language that uses a single indented space to mark a line (aka particle) as a subparticle of a parent line.
+
+ For example:
+
+ header
+ class hero
+ nav
+ div Scroll
+ class logo
+ div
+ class nav-links
+ a Features
+ href #features
+ a Examples
+ href #examples
+ a Edit
+ href edit.html
+ a GitHub
+ class cta-button
+ href https://github.com/breck7/scroll
+ div
+ class hero-content
+ h1 Write Better with Scroll
+ p The extendible markup language that makes source beautiful and compiles to anything
+ a Get Started
+ class primary-button
+ href https://hub.scroll.pub/
+ main
+ section
+ id features
+ class features
+ h2 Why Scroll?
+ div
+ class feature-grid
+ div
+ class feature-card
+ div ⚑
+ class feature-icon
+ h3 Simple Syntax
+ p Like Markdown, but more powerful. No parentheses needed.
+ div
+ class feature-card
+ div 🧩
+ class feature-icon
+ h3 Extendible
+ p Build your own custom parsers.
+ div
+ class feature-card
+ div 🎨
+ class feature-icon
+ h3 Beautiful Output
+ p Create stunning documents with minimal effort.
+ div
+ class feature-card
+ div πŸš€
+ class feature-icon
+ h3 Fast & Light
+ p Built on the efficient PPS Stack.
+ section
+ id examples
+ class code-demo
+ h2 See It In Action
+ div
+ class code-container
+ pre
+ class code-example
+ div
+ class code-output
+ footer
+ div
+ class footer-content
+ div
+ class footer-links
+ a Documentation
+ href https://scroll.pub/tutorial.html
+ a Community
+ href https://www.reddit.com/r/WorldWideScroll/
+ a Blog
+ href https://scroll.pub/blog
+ p Started by Breck Yunits. Evolved by a community.
+ https://twitter.com/breckyunits Breck Yunits
+ https://github.com/breck7/scroll/graphs/contributors community
+
+
+ First suggest a short, memorable domain name ending in scroll.pub that represents this website. Then provide the website files. Use this exact format:
+
+ ---domain---
+ (domainscroll.pub here)
+ ---index.scroll---
+ buildHtml
+ baseUrl https://(domainscroll.pub here)
+ metaTags
+ editButton /edit.html
+ title (Title here)
+ style.css
+
+ (body content here. no blank lines please.)
+
+ script.js
+ ---style.css---
+ (CSS content here)
+ ---script.js---
+ (JavaScript content here)
+ ---end---
script.js
Changed around line 1
+ document.addEventListener('DOMContentLoaded', () => {
+ const countrySelect = document.getElementById('countrySelect');
+ const stateSelect = document.getElementById('stateSelect');
+ const searchInput = document.getElementById('searchInput');
+ const tableBody = document.getElementById('tableBody');
+ const loader = document.getElementById('loader');
+
+ let countries = [];
+ let states = [];
+ let ipData = [];
+
+ // Cache for data
+ const cache = {
+ countries: null,
+ states: null,
+ ipData: null
+ };
+
+ async function fetchData(url) {
+ try {
+ const response = await fetch(url);
+ if (!response.ok) throw new Error('Network response was not ok');
+ return await response.json();
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ return null;
+ }
+ }
+
+ async function initializeData() {
+ loader.style.display = 'flex';
+
+ // Fetch all data in parallel
+ const [countriesData, statesData, ipDataRaw] = await Promise.all([
+ fetchData('https://cscd.api.ipvi.net/json/countries.json'),
+ fetchData('https://cscd.api.ipvi.net/json/states.json'),
+ fetch('https://raw.githubusercontent.com/axelawh/geofeed/refs/heads/main/location.csv')
+ .then(response => response.text())
+ ]);
+
+ if (countriesData) {
+ cache.countries = countriesData;
+ populateCountrySelect(countriesData);
+ }
+
+ if (statesData) {
+ cache.states = statesData;
+ }
+
+ if (ipDataRaw) {
+ cache.ipData = parseCSV(ipDataRaw);
+ displayResults(cache.ipData.slice(0, 50)); // Show first 50 results initially
+ }
+
+ loader.style.display = 'none';
+ }
+
+ function parseCSV(csv) {
+ return csv.split('\n')
+ .filter(line => line.trim())
+ .map(line => {
+ const [ipRange, countryCode, stateCode, city, postalCode] = line.split(',');
+ return { ipRange, countryCode, stateCode, city, postalCode };
+ });
+ }
+
+ function populateCountrySelect(countries) {
+ countrySelect.innerHTML = '';
+ countries.sort((a, b) => a.name.localeCompare(b.name))
+ .forEach(country => {
+ const option = document.createElement('option');
+ option.value = country.iso2;
+ option.textContent = `${country.emoji} ${country.name}`;
+ countrySelect.appendChild(option);
+ });
+ }
+
+ function updateStateSelect(countryCode) {
+ stateSelect.innerHTML = '';
+ if (!countryCode) return;
+
+ const countryStates = cache.states.filter(state => state.country_code === countryCode);
+ countryStates.sort((a, b) => a.name.localeCompare(b.name))
+ .forEach(state => {
+ const option = document.createElement('option');
+ option.value = state.state_code;
+ option.textContent = state.name;
+ stateSelect.appendChild(option);
+ });
+ }
+
+ function displayResults(results) {
+ tableBody.innerHTML = '';
+ results.forEach(result => {
+ const tr = document.createElement('tr');
+ tr.innerHTML = `
+ ${result.ipRange}
+ ${result.countryCode}
+ ${result.stateCode}
+ ${result.city || '-'}
+ ${result.postalCode || '-'}
+ `;
+ tableBody.appendChild(tr);
+ });
+ }
+
+ function filterResults() {
+ const searchTerm = searchInput.value.toLowerCase();
+ const countryCode = countrySelect.value;
+ const stateCode = stateSelect.value;
+
+ let filtered = cache.ipData;
+
+ if (countryCode) {
+ filtered = filtered.filter(item => item.countryCode === countryCode);
+ }
+
+ if (stateCode) {
+ filtered = filtered.filter(item => item.stateCode === stateCode);
+ }
+
+ if (searchTerm) {
+ filtered = filtered.filter(item =>
+ item.ipRange.toLowerCase().includes(searchTerm) ||
+ item.city?.toLowerCase().includes(searchTerm) ||
+ item.postalCode?.toLowerCase().includes(searchTerm)
+ );
+ }
+
+ displayResults(filtered.slice(0, 50));
+ }
+
+ // Event Listeners
+ countrySelect.addEventListener('change', () => {
+ updateStateSelect(countrySelect.value);
+ filterResults();
+ });
+
+ stateSelect.addEventListener('change', filterResults);
+
+ searchInput.addEventListener('input', debounce(filterResults, 300));
+
+ function debounce(func, wait) {
+ let timeout;
+ return function executedFunction(...args) {
+ const later = () => {
+ clearTimeout(timeout);
+ func(...args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ }
+
+ // Initialize the application
+ initializeData();
+ });
style.css
Changed around line 1
+ :root {
+ --primary-color: #2a2d3e;
+ --secondary-color: #1f2133;
+ --accent-color: #6c63ff;
+ --text-primary: #ffffff;
+ --text-secondary: #b3b3b3;
+ --border-color: #3f4156;
+ }
+
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
+ background-color: var(--secondary-color);
+ color: var(--text-primary);
+ line-height: 1.6;
+ }
+
+ .header-dark {
+ background-color: var(--primary-color);
+ padding: 2rem 0;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.2);
+ }
+
+ .container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 1rem;
+ }
+
+ .search-section {
+ padding: 2rem 0;
+ }
+
+ .search-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 1rem;
+ margin-bottom: 2rem;
+ }
+
+ .select-dark, .input-dark {
+ width: 100%;
+ padding: 0.8rem 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: 6px;
+ background-color: var(--primary-color);
+ color: var(--text-primary);
+ font-size: 1rem;
+ transition: all 0.3s ease;
+ }
+
+ .select-dark:focus, .input-dark:focus {
+ outline: none;
+ border-color: var(--accent-color);
+ box-shadow: 0 0 0 2px rgba(108, 99, 255, 0.2);
+ }
+
+ .table-dark {
+ width: 100%;
+ border-collapse: collapse;
+ background-color: var(--primary-color);
+ border-radius: 8px;
+ overflow: hidden;
+ }
+
+ .table-dark th, .table-dark td {
+ padding: 1rem;
+ text-align: left;
+ border-bottom: 1px solid var(--border-color);
+ }
+
+ .table-dark th {
+ background-color: var(--secondary-color);
+ font-weight: 600;
+ }
+
+ .table-dark tbody tr:hover {
+ background-color: rgba(108, 99, 255, 0.1);
+ }
+
+ .loading-spinner {
+ display: none;
+ justify-content: center;
+ align-items: center;
+ padding: 2rem;
+ color: var(--text-secondary);
+ }
+
+ .footer-dark {
+ background-color: var(--primary-color);
+ padding: 2rem 0;
+ margin-top: 3rem;
+ }
+
+ .footer-nav {
+ display: flex;
+ gap: 2rem;
+ margin-top: 1rem;
+ }
+
+ .footer-nav a {
+ color: var(--text-secondary);
+ text-decoration: none;
+ transition: color 0.3s ease;
+ }
+
+ .footer-nav a:hover {
+ color: var(--accent-color);
+ }
+
+ @media (max-width: 768px) {
+ .search-container {
+ grid-template-columns: 1fr;
+ }
+
+ .table-container {
+ overflow-x: auto;
+ }
+ }