1+ <!DOCTYPE html>
2+ < html >
3+ < head >
4+ < title > IP Address Tracker</ title >
5+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6+ < style >
7+ body {
8+ font-family : Arial, sans-serif;
9+ margin : 0 ;
10+ padding : 20px ;
11+ background-color : # f5f5f5 ;
12+ }
13+
14+ .container {
15+ max-width : 600px ;
16+ margin : 0 auto;
17+ background : white;
18+ padding : 20px ;
19+ border-radius : 8px ;
20+ box-shadow : 0 2px 10px rgba (0 , 0 , 0 , 0.1 );
21+ }
22+
23+ h1 {
24+ text-align : center;
25+ color : # 333 ;
26+ margin-bottom : 25px ;
27+ }
28+
29+ .search-box {
30+ display : flex;
31+ margin-bottom : 20px ;
32+ gap : 10px ;
33+ }
34+
35+ input {
36+ flex : 1 ;
37+ padding : 10px ;
38+ border : 1px solid # ddd ;
39+ border-radius : 4px ;
40+ font-size : 16px ;
41+ }
42+
43+ button {
44+ padding : 10px 15px ;
45+ background : # 4CAF50 ;
46+ color : white;
47+ border : none;
48+ border-radius : 4px ;
49+ cursor : pointer;
50+ font-size : 16px ;
51+ transition : background 0.3s ;
52+ }
53+
54+ button : hover {
55+ background : # 45a049 ;
56+ }
57+
58+ button : disabled {
59+ background : # cccccc ;
60+ cursor : not-allowed;
61+ }
62+
63+ .results {
64+ border-top : 1px solid # eee ;
65+ padding-top : 20px ;
66+ }
67+
68+ .result-item {
69+ display : flex;
70+ margin-bottom : 10px ;
71+ padding : 8px 0 ;
72+ border-bottom : 1px solid # f0f0f0 ;
73+ }
74+
75+ .label {
76+ font-weight : bold;
77+ width : 120px ;
78+ color : # 555 ;
79+ }
80+
81+ .value {
82+ flex : 1 ;
83+ color : # 222 ;
84+ }
85+
86+ .loading {
87+ text-align : center;
88+ padding : 20px ;
89+ color : # 666 ;
90+ display : none;
91+ }
92+
93+ .error {
94+ color : # d32f2f ;
95+ text-align : center;
96+ padding : 10px ;
97+ margin-top : 10px ;
98+ display : none;
99+ }
100+
101+ .note {
102+ font-size : 12px ;
103+ color : # 666 ;
104+ font-style : italic;
105+ margin-top : 5px ;
106+ }
107+
108+ @media (max-width : 600px ) {
109+ .search-box {
110+ flex-direction : column;
111+ }
112+
113+ .result-item {
114+ flex-direction : column;
115+ }
116+
117+ .label {
118+ width : 100% ;
119+ margin-bottom : 5px ;
120+ }
121+ }
122+ </ style >
123+ </ head >
124+ < body >
125+ < div class ="container ">
126+ < h1 > IP Address Tracker</ h1 >
127+ < div class ="search-box ">
128+ < input type ="text " id ="ip-input " placeholder ="Enter IP address (e.g., 8.8.8.8) ">
129+ < button id ="search-btn "> Search</ button >
130+ < button id ="my-ip-btn "> Use My IP</ button >
131+ </ div >
132+
133+ < div class ="error " id ="error-message "> </ div >
134+ < div class ="loading " id ="loading "> Loading IP data...</ div >
135+
136+ < div class ="results " id ="results ">
137+ < div class ="result-item ">
138+ < span class ="label "> IP Address</ span >
139+ < span id ="ip-address " class ="value "> -</ span >
140+ </ div >
141+ < div class ="result-item ">
142+ < span class ="label "> Country</ span >
143+ < span id ="country " class ="value "> -</ span >
144+ </ div >
145+ < div class ="result-item ">
146+ < span class ="label "> Region/State</ span >
147+ < span id ="region " class ="value "> -</ span >
148+ </ div >
149+ < div class ="result-item ">
150+ < span class ="label "> City</ span >
151+ < span id ="city " class ="value "> -</ span >
152+ </ div >
153+ < div class ="result-item ">
154+ < span class ="label "> Postal Code</ span >
155+ < span id ="postal " class ="value "> -< span class ="note "> (approximate location, may vary for privacy)</ span > </ span >
156+ </ div >
157+ < div class ="result-item ">
158+ < span class ="label "> ISP</ span >
159+ < span id ="isp " class ="value "> -</ span >
160+ </ div >
161+ </ div >
162+ </ div >
163+
164+ < script >
165+ document . addEventListener ( 'DOMContentLoaded' , function ( ) {
166+ const searchBtn = document . getElementById ( 'search-btn' ) ;
167+ const myIpBtn = document . getElementById ( 'my-ip-btn' ) ;
168+ const ipInput = document . getElementById ( 'ip-input' ) ;
169+ const loading = document . getElementById ( 'loading' ) ;
170+ const errorMsg = document . getElementById ( 'error-message' ) ;
171+ const results = document . getElementById ( 'results' ) ;
172+
173+ // Validate IP address format
174+ function isValidIP ( ip ) {
175+ const ipv4Regex = / ^ ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] [ 0 - 9 ] | [ 0 1 ] ? [ 0 - 9 ] [ 0 - 9 ] ? ) $ / ;
176+ const ipv6Regex = / ^ ( [ 0 - 9 a - f A - F ] { 1 , 4 } : ) { 7 } [ 0 - 9 a - f A - F ] { 1 , 4 } $ / ;
177+ return ipv4Regex . test ( ip ) || ipv6Regex . test ( ip ) ;
178+ }
179+
180+ function showLoading ( ) {
181+ loading . style . display = 'block' ;
182+ results . style . display = 'none' ;
183+ errorMsg . style . display = 'none' ;
184+ searchBtn . disabled = true ;
185+ myIpBtn . disabled = true ;
186+ }
187+
188+ function hideLoading ( ) {
189+ loading . style . display = 'none' ;
190+ results . style . display = 'block' ;
191+ searchBtn . disabled = false ;
192+ myIpBtn . disabled = false ;
193+ }
194+
195+ function showError ( message ) {
196+ errorMsg . textContent = message ;
197+ errorMsg . style . display = 'block' ;
198+ results . style . display = 'none' ;
199+ }
200+
201+ function hideError ( ) {
202+ errorMsg . style . display = 'none' ;
203+ }
204+
205+ function trackIp ( ip ) {
206+ showLoading ( ) ;
207+ hideError ( ) ;
208+
209+ fetch ( `https://ipapi.co/${ ip } /json/` )
210+ . then ( response => {
211+ if ( ! response . ok ) {
212+ throw new Error ( 'Network response was not ok' ) ;
213+ }
214+ return response . json ( ) ;
215+ } )
216+ . then ( data => {
217+ if ( data . error ) {
218+ throw new Error ( data . reason || 'Error fetching IP data' ) ;
219+ }
220+ displayResults ( data ) ;
221+ hideLoading ( ) ;
222+ } )
223+ . catch ( error => {
224+ console . error ( 'Error:' , error ) ;
225+ showError ( error . message || 'Failed to fetch IP data' ) ;
226+ hideLoading ( ) ;
227+ } ) ;
228+ }
229+
230+ searchBtn . addEventListener ( 'click' , function ( ) {
231+ const ip = ipInput . value . trim ( ) ;
232+ if ( ! ip ) {
233+ showError ( 'Please enter an IP address' ) ;
234+ return ;
235+ }
236+
237+ if ( ! isValidIP ( ip ) ) {
238+ showError ( 'Please enter a valid IP address' ) ;
239+ return ;
240+ }
241+
242+ trackIp ( ip ) ;
243+ } ) ;
244+
245+ myIpBtn . addEventListener ( 'click' , function ( ) {
246+ showLoading ( ) ;
247+ hideError ( ) ;
248+
249+ fetch ( 'https://ipapi.co/json/' )
250+ . then ( response => {
251+ if ( ! response . ok ) {
252+ throw new Error ( 'Network response was not ok' ) ;
253+ }
254+ return response . json ( ) ;
255+ } )
256+ . then ( data => {
257+ if ( data . error ) {
258+ throw new Error ( data . reason || 'Error fetching your IP data' ) ;
259+ }
260+ ipInput . value = data . ip ;
261+ displayResults ( data ) ;
262+ hideLoading ( ) ;
263+ } )
264+ . catch ( error => {
265+ console . error ( 'Error:' , error ) ;
266+ showError ( error . message || 'Failed to fetch your IP data' ) ;
267+ hideLoading ( ) ;
268+ } ) ;
269+ } ) ;
270+
271+ function displayResults ( data ) {
272+ document . getElementById ( 'ip-address' ) . textContent = data . ip || '-' ;
273+ document . getElementById ( 'country' ) . textContent = data . country_name || '-' ;
274+ document . getElementById ( 'region' ) . textContent = data . region || '-' ;
275+ document . getElementById ( 'city' ) . textContent = data . city || '-' ;
276+ document . getElementById ( 'postal' ) . textContent = data . postal || '-' ;
277+ document . getElementById ( 'isp' ) . textContent = data . org || '-' ;
278+ }
279+ } ) ;
280+ </ script >
281+ </ body >
282+ </ html >
0 commit comments