1

Please give me a simple tip where to dig!

I have multiple IP's and need to display the location next to each of them.

I have a list of IPS in array via

var table = document.createElement('table');
table.innerHTML = forext;
var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n");

8.8.8.8
8.8.4.4 
...

I can get the location of each of them via input box

$('.send').on('click', function(){

  $.getJSON('https://ipapi.co/'+$('.ip').val()+'/json', function(data){
      $('.city').text(data.city);
      $('.country').text(data.country);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input class="ip" value="8.8.8.8">
<button class="send">Go</button>
<br><br>
<span class="city"></span>, 
<span class="country"></span>

BUT what I need is to print the IPs and the location next to it:

So, I have this:

8.8.8.8
8.8.8.8

BUT I need this

8.8.8.8 -Mountain View, US
8.8.8.8 -Mountain View, US
...

How can I proceed the whole array via http://freegeoip.net/json/? Thank you.

Update 1: Trying to make it using: ips[i]

var ipText='Lookup...';
var table = document.createElement('table');
table.innerHTML = forext;
var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n");

var ipLocations = [];

for(i=0;i<ips.length;i++){

 $.getJSON('https:/freegeoip.net/json/' + ips[i], function(data) {
    // could also use data.country_name, or any other property in the returned JSON
    var outputString = data.ips[i] + ' - ' + data.city + ', ' + data.country_code; 
    ipLocations.push(outputString);

  });

}

ipText = ipLocations.join('\n');
message.innerText = ipText;
Jessica Ray
  • 65
  • 2
  • 5
  • Have you tried using `$('.ip').val()+' - '+data.city` or just a guess but `data.ip` if that is held within the json.... **Example:** `$('.city').text(data.ip+" - "+data.city);` Either that or create another span and append the `data.ip+" - "` into that... – NewToJS Aug 03 '17 at 22:38
  • What do you mean by "print the IPs"? Do you mean insert them into the HTML, or log them in the browser console? – endemic Aug 03 '17 at 22:41
  • either way, it sounds like you want to look into JavaScript [for...of loops](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). If you're having trouble inserting your results into the page content, you should look at the jQuery documentation for how to create and insert a new element, and do that inside of your loop – endemic Aug 03 '17 at 22:46
  • I want to display it as message.innerText = ips; in chrome extension... – Jessica Ray Aug 03 '17 at 22:48
  • 1
    And what do you need by "proceed the whole array"? Where will the array be coming from? Several text input fields? The '.ip' text field, separated by a comma? If you wanna add the IP next to what you have now, just add a span before '.city' span like ` - ` and in your onclick function add `$('.theIP').text(data.ip); after the $('.country')... ` line – Aydin4ik Aug 03 '17 at 22:51
  • I grabbed ips to array from the page (pls view my fists message update) What I have now is list of IP but I need IP+location next to it – Jessica Ray Aug 03 '17 at 22:54
  • 1
    @JessicaRay Ah so you have multiple IP's... Don't you think it would've been relevant to say this in your question from the start? You have also added more relevant source code... Anything else relevant to your question? If so then I recommend you add it rather than having people guess. – NewToJS Aug 03 '17 at 23:00
  • @NewToJS, thank you for advice, have done it.. – Jessica Ray Aug 03 '17 at 23:05

1 Answers1

0

First of all, you really want your IPs to be an array of strings, not a single string. As such, you should change your declaration for var ips = ... and delete the .join("\n") from the end--that turns your convenient list of IP strings into a single string with the IPs separated by newline characters, which you don't want.

Then, when you have an array of IP addresses of a form something like ips = ['8.8.8.8', '8.8.4.4', ... ];

...then you can get the output you described in the following way:

var ipLocations = [];
for (var ip of ips) {
  $.getJSON('https://freegeoip.net/json/' + ip, function(data) {
    // could also use data.country_name, or any other property in the returned JSON
    var outputString = data.ip + ' - ' + data.city + ', ' + data.country_code; 
    ipLocations.push(outputString);
  });
}

Now you have an array of strings with IP address + location, as you described. If you now want to turn THAT into a single string, you can do ipText = ipLocations.join('\n'); to get the output lines separated by newline characters.

If you're going to be outputting this text into an HTML document though, you might want to join on <br> instead of \n, there are many contexts in which whitespace characters like \n will be ignored and you would end up with all your output on one line.

UPDATE:

There were some very silly mistakes in my original answer, chief among them being that I mixed Python and JavaScript syntax (facepalm). Having fixed them, this code does work. That being said, there are some caveats that need to be mentioned, as well as some errors in your Update 1 code that you should really try to understand.

First, the issues in your code:

  • You never got rid of the .join("\n") from line 4 where you define ips, so it's still just a string instead of an array of strings. This means that your for-loop is actually looping over each individual character in the ips string, instead of complete IP addresses.
  • You try to access data.ips[i] inside of the loop. The data variable contains the JSON response to your AJAX request, but automatically converted from a JSON string into an actual JavaScript object by jQuery. It only has the properties that are included in the response. In this case, the response always has an ip property, so you can access data.ip. However, ips is a variable that YOU created--data.ips doesn't exist, so you can't access its indices.
    • As a side note, if you used the for...of syntax, you would also have a loop variable called ip that you can use instead. However, you need to understand that ip and data.ip are not the same variable, even if they will always have the same value in this case.
  • The URL starts with "https:/" instead of "https://". This one is actually my fault, I typo'd it in my original answer >_>;

With that out of the way, you brought up a very important point in your comment-- the function $.getJSON() is asynchronous, so (ignoring the other issues) the code as you wrote it in Update 1 will probably not do what you expect. The code after the call to getJSON will keep running even if your AJAX request doesn't have a response yet, so if you immediately access the ipLocs array it might only have some of the output strings yet, or even be empty.

I'm not going to explain how to wait on non-blocking code to you, because that's a completely different question. I'm also worried that it will only make things more confusing, given your apparent level of familiarity with JavaScript. But if you just want a quick solution that gives you the results that you expect, even if it's not at all best practice, then you can use the ajax function instead of getJSON. This allows you to explicitly tell jQuery to send your AJAX request synchronously, meaning it will wait for a response before continuing to run your code. However, you need to be aware that synchronous requests may temporarily lock your browser, preventing any other actions until the request is completed. That version would look like this:

var ipLocations = [];
for (var ip of ips) {
  $.ajax({
    url: 'https://freegeoip.net/json/' + ip,
    async: false,
    success: function(data) {
      var outputString = data.ip + ' - ' + data.city + ', ' + data.country_code; 
      ipLocations.push(outputString);
    }
  });
}
endemic
  • 189
  • 1
  • 2
  • 13
  • Thank you! I'm close but something wrong here: `code` var table = document.createElement('table'); table.innerHTML = forext; var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n"); ipText = ''; for(i=0;i – Jessica Ray Aug 03 '17 at 23:20
  • Er... you copied the code, but what's the actual problem you're having? – endemic Aug 03 '17 at 23:25
  • Also, I totally forgot to put `var` in front of my variable declarations making them globals, which shouldn't actually cause any explicit problems here but is very silly, so I have edited. – endemic Aug 03 '17 at 23:25
  • oups sorry.... I mean the for(i=0;i – Jessica Ray Aug 03 '17 at 23:25
  • OH WAIT I think I see the problem actually. I will edit my answer. – endemic Aug 03 '17 at 23:26
  • Oh, I missed that. You should really read up on [for...of loops](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). When I say `for ip of ips`, it means "You have a list called `ips`. For each item in that list, which we shall call `ip` temporarily, do the following." If you use an ordinary for loop, the `ip` variable is never defined, so you can't refer to it inside of the loop. You CAN refer to `ips[i]` though. My current answer _should_ be what you're looking for. – endemic Aug 03 '17 at 23:35
  • Thank you a lot for your time I will read the loop related docs. Thanks again! – Jessica Ray Aug 03 '17 at 23:37
  • Trying to make it using ips[i], please kindly take a look at code Update 1 in first message. Is it correct please? Thank you! – Jessica Ray Aug 04 '17 at 00:01
  • nope, doesn'work... I made it work only as - alert (data.city); - I cannot treat this data as a variable or array, just doesn't work... – Jessica Ray Aug 04 '17 at 01:44
  • It works thank you! But the variable ipLocations is only accessible inside the loop. Is it because the code inside your for-loop is a non-blocking code? – Jessica Ray Aug 07 '17 at 04:48
  • "the variable ipLocations is only accessible inside the loop" that... just isn't true. However, the fact that getJSON is asynchronous IS important. TBH there are some VERY silly problems with the code I wrote in my answer, which I will update to fix. There are also some problems in the code you wrote in your Update 1, which I will also address. – endemic Aug 09 '17 at 23:35
  • Also, if you update your answer to include new code, you shouldn't ask "is it correct?" you should TELL us whether it's doing what you expect, and if it isn't then you should include what errors you're seeing. – endemic Aug 09 '17 at 23:35