0

I have a problem with selecting dynamically-added elements, each with dynamically-defined ID; script always returns null when using getElemendById.

I want the script to first check, if element with certain ID already exists within the DOM, and if not - create one, if it does - do something else.

My code looks like this:

document.addEventListener('DOMContentLoaded', function () {
  //define variables
  var playersOnField = document.querySelector('.players');

  //using timeBar as indicator of current time frame
  var timeBar = document.querySelector('#time');

  //its maximum value needs to be adjusted to the number of the frames we have
  timeBar.setAttribute("max", data.player_positions.length);


  //display the players position for current frame
  positionPlayers = function() {
    time = timeBar.value;
    currentFrame = data.player_positions[time];
    //check if DOM element representing each player of current frame already exists, if not - create it
    for (var i = 0; i < currentFrame.length; i++) {
      var playerId = currentFrame[i][0];
      //ID's start with number, so they require special unicode notation
      if (!!document.getElementById(`#\\3${playerId} `) == false) {
        console.log('no element, let\'s create one');
        var newPlayer = document.createElement('div');
        newPlayer.id = `${playerId}`;
        playersOnField.appendChild(newPlayer);
      } else {
        console.log('element already exists!');
      }
    }
  }

  //every time the bar changes its postion (and therefore its value) it should trigger the action to set up the players in the current position on the field
  timeBar.addEventListener('change', positionPlayers);
  timeBar.addEventListener('input', positionPlayers);

})

But the function is always returning false, and creating dozens od div's of the same ID, as getElementById never finds any of those newly-appended elements. How can I avoid this happening, preferably using vanilla JS?

Lafioka
  • 5
  • 1
  • 4
  • You seem to have an extra space in the `id` string you are testing for. Also, why use the back-tick string syntax here? if (!!document.getElementById(`#\\3${playerId} `) == false) { – Scott Marcus May 24 '17 at 19:47
  • You're right about that space, and back-tick was to pass variable value to an ID name. Is it wrong? I am rather beggining with JS. – Lafioka May 24 '17 at 19:50
  • Because the elements are dynamically added, in jQuery you would have to go up a level and check the DOM from body or something. I'm not sure how that translates to vanilly JS though. `$('body').find(whatever);` ~ or maybe something along those lines??? -- I guess you're already checking on the `document` though... – sheriffderek May 24 '17 at 19:51
  • What's an example of an ID you expect to see? – Joseph Marikle May 24 '17 at 19:51
  • What is the `\\3` about and do your id's actually start with `#`? – Scott Marcus May 24 '17 at 19:53
  • @ScottMarcus - replied under your answer. and \\3 was to ensure proper unicode, but it turns out it is not necessary (I have found it at some other point of searching for answer, why it's not working - https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers) Joseph - I expect to see just an single or two-digits number as an id, like
    – Lafioka May 24 '17 at 20:01

1 Answers1

0

You seem to have an extra space in the id string you are testing for. Since #{...} is an evaluated value, it shouldn't be in quotes in the first place.

Also, why use the back-tick string syntax here?

if (!!document.getElementById(`#\\3${playerId} `) == false) {

And, getElementById() already knows to look for id's so adding the # is going to search for elements that actually start with #.

Finally, if the element with that id does exist, it will return a "truthy" value that when converted to a Boolean, will convert to true, so there is no need to force a Boolean conversion (with !!) and then check to see if that is false.

That line can be rewritten to:

if (!document.getElementById(${playerId})) {
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Thank you, Scott! You're absolutely right about the #. Nevertheless, the line you have provided isn't exactly working as I wanted, but helped me to develop this: if (!!document.getElementById(`${playerId}`) == false) {} And it is working properly :) I have used "!!" to ensure selector returns boolean and work on it only, if the element was not found (and create it then). – Lafioka May 24 '17 at 19:58
  • @Lafioka I was just updating my answer to explain the Boolean conversion and fix my typo. – Scott Marcus May 24 '17 at 19:59
  • Excellent! Thank you Scott! – Lafioka May 24 '17 at 20:03
  • @Lafioka The `!!` is not needed. Any `if` condition expression will automatically be converted to a Boolean so that the condition can be `true` or `false` and no need to explicitly check for `false` either. Placing a single `!` in front of the expression tests for the opposite of the condition. – Scott Marcus May 24 '17 at 20:03
  • Why the `${}` around `playerId`? – Ruan Mendes May 24 '17 at 20:53
  • I assume OP is using some framework like Angular to resolve the value. – Scott Marcus May 24 '17 at 20:56