简体   繁体   中英

HTML Element Replacement in Javascript

The code in question, below, is supposed to replace every instance of, well, it's complicated, but basically it's going to take an IP on a page and turn it into a server name (as defined by me in my code). It kinda works in that it replaces some IPs - but only one per IP, so if there's more than one instance on a page, it only replaces one. How do I go about this?

var arrServerInstances = document.body.innerHTML.match('27015');

    if (arrServerInstances != null)
    {
        if (arrServerInstances.length > 0)
        {   
            //UK Servers
            document.body.innerHTML = document.body.innerHTML.replace('83.222.246.178:27015','Common Grounds D2 UK');
            document.body.innerHTML = document.body.innerHTML.replace('83.222.246.174:27015','Assault 24/7 UK');
            document.body.innerHTML = document.body.innerHTML.replace('83.222.246.176:27015','Officefest UK');
            document.body.innerHTML = document.body.innerHTML.replace('83.222.246.175:27015','Dustfest UK');
            document.body.innerHTML = document.body.innerHTML.replace('83.222.246.177:27015','London Gungame UK');
            document.body.innerHTML = document.body.innerHTML.replace('83.222.246.179:27015','Dust 2 Deatchmatch UK');
            document.body.innerHTML = document.body.innerHTML.replace('83.222.240.93:27015','Mad Hatter\'s TF2 Tea Party UK');
            //US Servers
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.164:27015','Dust/Office Deathmatch US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.169:27015','Zombiemod US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.165:27015','Dust 24/7 -aMs- US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.172:27015','CS 1.6 Gungame US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.239.31:27015','Crackhouse US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.166:27015','Iceworld 24/7 US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.170:27015','Mad as a TF2 Hatter US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.167:27015','Gungame Turbo US');
            document.body.innerHTML = document.body.innerHTML.replace('76.74.236.168:27015','CS:S Iceworld 24/7 US');
        }
    }

PS This is the first thing I've ever written in Javascript, I'm a C, C++, Objective C, VBA (God forbid) programmer, so if there's an easier way to do this, please, don't be afraid to point it out.

You've compiled a list of all strings that match "27015," now you need to loop through every one and compare against your list.

Try a "foreach" loop (kind of difficult in Javascript).
Or try a "while" loop. You would pop each element off the list as you compare (and possibly alter) it, and then exit the loop when there are none left in the list.

I would use jQuery to help you out here, since it has a handy .each() function, as well as making the editing of the DOM a bit easier.

You use a regular expression for the replacement so that you can specify the g flag for global replacement:

s = s.replace(/83\.222\.246\.178:27015/g,'Common Grounds D2 UK');

You shouldn't get the HTML code of the body and put it back for each replacement. That means that for every replacement you create a string representation of every object in the body, then parse it back into elements again.

You can use the indexOf method to look for the first occurance of a string in another, instead of using a regular expression to get every occurance into an array.

// get HTML
var html = document.body.innerHTML;

var hasServerInstances = html.indexOf('27015') != -1;

if (hasServerInstances) {   
  //UK Servers
  html = html
    .replace(/83\.222\.246\.178:27015/g,'Common Grounds D2 UK')
    .replace(/83\.222\.246\.174:27015/g,'Assault 24/7 UK')
    .replace(/83\.222\.246\.176:27015/g,'Officefest UK')
    .replace(/83\.222\.246\.175:27015/g,'Dustfest UK')
    .replace(/83\.222\.246\.177:27015/g,'London Gungame UK')
    .replace(/83\.222\.246\.179:27015/g,'Dust 2 Deatchmatch UK')
    .replace(/83\.222\.240\.93:27015/g,'Mad Hatter\'s TF2 Tea Party UK');
  //US Servers
  html = html
    .replace(/76\.74\.236\.164:27015/g,'Dust/Office Deathmatch US')
    .replace(/76\.74\.236\.169:27015/g,'Zombiemod US')
    .replace(/76\.74\.236\.165:27015/g,'Dust 24/7 -aMs- US')
    .replace(/76\.74\.236\.172:27015/g,'CS 1.6 Gungame US')
    .replace(/76\.74\.239\.31:27015/g,'Crackhouse US')
    .replace(/76\.74\.236\.166:27015/g,'Iceworld 24/7 US')
    .replace(/76\.74\.236\.170:27015/g,'Mad as a TF2 Hatter US')
    .replace(/76\.74\.236\.167:27015/g,'Gungame Turbo US')
    .replace(/76\.74\.236\.168:27015/g,'CS:S Iceworld 24/7 US');
  // put the HTML back
  document.body.innerHTML = html;
}

You can even use regular expressions to match multiple servers in a single replace:

// get HTML
var html = document.body.innerHTML;

var hasServerInstances = html.indexOf('27015') != -1;

if (hasServerInstances) {   
  //UK Servers
  html = html.replace(/83\.222\.246\.17[4-9]:27015/g, function(m){
    switch(m) {
      case '174': return 'Assault 24/7 UK';
      case '175': return 'Dustfest UK';
      case '176': return 'Officefest UK';
      case '177': return 'London Gungame UK';
      case '178': return 'Common Grounds D2 UK';
      case '179': return 'Dust 2 Deatchmatch UK';
    }
  });
  html = html.replace(/83\.222\.240\.93:27015/g,'Mad Hatter\'s TF2 Tea Party UK');
  //US Servers
  html = html.replace(/76\.74\.236\.1(6[4-9]|7[02]):27015/g, function(m){
    switch(m) {
      case '164': return 'Dust/Office Deathmatch US';
      case '165': return 'Dust 24/7 -aMs- US';
      case '166': return 'Iceworld 24/7 US';
      case '167': return 'Gungame Turbo US';
      case '168': return 'CS:S Iceworld 24/7 US';
      case '169': return 'Zombiemod US';
      case '170': return 'Mad as a TF2 Hatter US';
      case '172': return 'CS 1.6 Gungame US';
    }
  });
  html = html.replace(/76\.74\.239\.31:27015/g,'Crackhouse US');
  // put the HTML back
  document.body.innerHTML = html;
}

You could do the following:

var ips = {
  '83.222.246.178:27015':'Common Grounds D2 UK',
  '83.222.246.178:27015':'Common Grounds D2 UK',
  '83.222.246.178:27015':'Common Grounds D2 UK'
  // The rest of the ip adress go here
};

var text = document.body.innerHTML;
for(var i in ips)text=text.replace(RegExp(i,'g'),ips[i]);
document.body.innerHTML = text;

I would separate the data from the code and process data from a data structure.

This new version has the following advantages:

  1. It only sets the innerHTML back once which means there's only one DOM reparse and reflow rather than lots.
  2. The data is put into a table and looped through rather than lots of copied lines of code.
  3. This code will replace all occurrences of a given IP because of the addition of the "g" flag.
  4. This code properly escapes the periods in the regular expression so that they only match a period instead of the usual regular expression wildcard character.
  5. I've made it into a function so your variables aren't global
  6. I've compressed the if comparison into one compound comparison
  7. Removed the duplicate ":27015" from every string and put it once into the code

Here's the code:

function attachIpNames() {
    var str = document.body.innerHTML;
    var arrServerInstances = str.match('27015');
    if (arrServerInstances && arrServerInstances.length > 0) {
        var definitions = [
             //UK Servers
            '83.222.246.178', 'Common Grounds D2 UK',
            '83.222.246.174', 'Assault 24/7 UK',
            '83.222.246.176', 'Officefest UK',
            '83.222.246.175', 'Dustfest UK',
            '83.222.246.177', 'London Gungame UK',
            '83.222.246.179', 'Dust 2 Deatchmatch UK',
            '83.222.240.93',  'Mad Hatter\'s TF2 Tea Party UK',
            //US Servers
            '76.74.236.164', 'Dust/Office Deathmatch US',
            '76.74.236.169', 'Zombiemod US',
            '76.74.236.165', 'Dust 24/7 -aMs- US',
            '76.74.236.172', 'CS 1.6 Gungame US',
            '76.74.239.31',  'Crackhouse US',
            '76.74.236.166', 'Iceworld 24/7 US',
            '76.74.236.170', 'Mad as a TF2 Hatter US',
            '76.74.236.167', 'Gungame Turbo US',
            '76.74.236.168', 'CS:S Iceworld 24/7 US'
        ];

        var target;
        for (var i = 0; i < definitions.length; i+= 2) {
            target = definitions[i].replace(".", "\\.") + ":27015";         // get target and escape the period so it will match an actual period in the regex
            str = str.replace(new RegExp(target, "g"), definitions[i+1]);
        }
        document.body.innerHTML = str;
    }
}

If this were my code, I would try to narrow the replacement down to only targeted divs so that I didn't cause a reflow in the entire document and it would probably be faster too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM