Albert Nemec Albert Nemec - 5 months ago 11
HTML Question

Javascript onclick event on newly created elements

I've got several functions all linked so it will ...


  1. create new elements and set their properties and stuff

  2. once elements are in place they should trigger function.



And they do! Kind of...

More like they trigger half of a function that's attached to them upon creation. The part where they onclick trigger a function that starts a loading on my progress bar (which is their purpose) is alright. But the much simpler part, where they hide after click, doesn't.

As the code is quite complex I'll place here larger part of it, so don't panic. Problem might be somewhere else then I expect. Here it is...

// defines function for checkpoint
function checkpointed() {
this.style.display = 'none'; // !here dwells the douch part!
if (toLoad < 100) {
toLoad += 100/$(this).attr('numButs');
var sim = setInterval(progressSim, 50);
}

// defining creation of checkpoints
function checkpoints(num) {
var angle = 4.72,
step = (2 * Math.PI) / num;
for (i = 1; i < num + 1; i++) {
var x = $('#progressBar').width()/2 + radius * Math.cos(angle) ;
var y = $('#progressBar').height()/2 + radius * Math.sin(angle);
angle += step;
var newContent = document.createElement('IMG');
var newCheckpoint = document.createElement('SPAN');
var numButs = document.createAttribute('numButs');
numButs.value = num;
var Class = document.createAttribute('class');
Class.value = 'checkpoint';
var img = document.createAttribute('src');
img.value = 'img/lock.png';
newContent.setAttributeNode(img);
newCheckpoint.setAttributeNode(numButs);
newCheckpoint.setAttributeNode(Class);
$(newCheckpoint).append(newContent);
$('.projectBar').append(newCheckpoint);
x -= 24;
y -= 24;
$(newCheckpoint).offset({top:y, left: x});
newCheckpoint.onclick = checkpointed;
};
};

// creates checkpoints upon clicking on create button
document.getElementById('create').onclick = function(){
checkpoints(document.getElementById('numCheckpoint').value);
$(this).hide();
$('#numCheckpoint').hide();
};


I should probably sum up what is this all about.

I have circular progressBar that measures progression of users project. User says "Hey, my project has like 5 steps (or 20 idc)" and "create" button will make 5 checkpoints placed on the progressBar evenly. By clicking on checkpoints you load the progress bar by 20% per clicked checkpoint.

Don't worry though, I've already figured out the code for loading and the geometrics.

However I'm bit stuck here... on simple onclick functions. Please if you have an idea try achieve it with plain JavaScript or jQuery (trying to do this without other frameworks, libraries or plugins).

EDIT: Just found out that checkpoint are set alright, as they really hide after clicking. Problem is in creation of checkpoints as the loop creates about 15 more checkpoints stacked one on another. So you have to click each of them to hide them all... So problem is in the loop.

EDIT2: Figured it out. The loop
for (i = 1; i < num + 1; i++)
had the
num
parameter as a String coming from input field. So simple
parseInt()
did the trick.

Answer

The mixed Jquery and plain Javascript is messing with my head... Any way how about when you create a new element, give it some sort of class. Instead of giving setting onclick, use jQuery's on selector to bind click events to those dynamic elements. Try The Following:

 $(document).on("click", ".Checkpoint", function(event) {
    $(event.target).hide();
    if (toLoad < 100) {
      toLoad += 100 / $(this).attr('numButs');
      var sim = setInterval(progressSim, 50);
    }
  });

  // defining creation of checkpoints
  function checkpoints(num) {
    var angle = 4.72,
      step = (2 * Math.PI) / num;
    for (i = 1; i < num + 1; i++) {
      var x = $('#progressBar').width() / 2 + radius * Math.cos(angle);
      var y = $('#progressBar').height() / 2 + radius * Math.sin(angle);
      angle += step;
      var newContent = $('<img></img>');
      var newCheckpoint = $('<span></span>');
      $("body").append(newCheckpoint);
      newContent.attr("numButs", num);
      newContent.attr("src", 'img/lock.png');
      newContent.addClass("Checkpoint");

      $(newCheckpoint).append(newContent);
      $('.projectBar').append(newCheckpoint);
      x -= 24;
      y -= 24;
      $(newCheckpoint).offset({
        top: y,
        left: x
      });

    }
  }

  // creates checkpoints upon clicking on create button
  $(document).on("click","#create",function(e) {
    checkpoints($('#numCheckpoint').val());
    $(e.target).hide();
    $('#numCheckpoint').hide();
  });

Changed stuff to work more in jQuery, hope you don't mind...