0

I would appreciate some help with the following.

I have had to set the id for each my countdown timer dynamically for each row of my cards so that each timer has a unique id. I set the IDs through a $each loop and that works fine and tested.

I am trying to find it so I can output the values of the countdown timer.

Before I did it with php. Using the SQL result row id was the id.

 $("#timer<?php echo $id; ?>").val(days + "d " + hours + "h "+ minutes + "m " + seconds + "s" ).css("color", "black");

The timer counter display would look like this.

<input id="timer<?php echo $id; ?>"  class="timer" type="text" name="" value="" disabled>

The timer counter display looks like this as THEtimer id now set via a $each loop dynamically.

The array ids are used for the timer counter id. eg. "timer3"

<input id="timer"  class="timer" type="text" name="" value="" disabled>

I have left the variable like this in a class so you see it working $('.timer')

$('.timer').val(days + "d " + hours + "h "+ minutes + "m " + seconds + "s" ).css("color", "black");

My Problem How do I fill in the elements $(xxxx).. something like this $("#",timer+id) The # needs to be there.

The snippet

In the snippet, I have left the element as $('.timer') so you see it working.

After page load press the start timer button to start the counter timer. It will alert the Id of the counter before starting the counter.

End game

I want each row to have its own unique countdown timer

$(document).ready(function(){
  // simulates jason data result from Ajax
  var data = [

{ "id":"1", "name": "Mike" ,"surname": "Rynes" ,"expiredate": "2021/02/25 23:25:00"},
{ "id":"2", "name": "James" ,"surname": "Bond" ,"expiredate": "2021/02/26 23:25:00"},
{ "id":"3", "name": "Harry" ,"surname": "Potter" ,"expiredate": "2021/02/27 23:25:00"},
  
    ];
  
     $.each(data, function( i, person ) {
    
    
   var personDetailCloned = $('.card').first().clone().show();
      
   personDetailCloned.find('.id').text(person.id);
   personDetailCloned.find('.name').text(person.name);
   personDetailCloned.find('.surname').text(person.surname);
   personDetailCloned.find('.expiredate').val(person.expiredate);
      
      //Generate a random number to be used for timer id
       var timerid = Math.floor(Math.random() * 100);
               personDetailCloned.find('.timer').attr("id","timer"+person.id);
       
      $('.card-container').append(personDetailCloned);
    
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

<div class="album py-1">
  <div class="container bg-light">
    <div class="row py-2">
      <div class="col-md-3 card-container" >
        <div class="card mb-3 shadow-sm"  style="display:none;">
          <div class="hover-container">
         </div>
          <div class="card-body CarDetail">
           <p class="card-text font-weight-bold">ID:
                 <span class="id"></span>
            </p>
            <p class="card-text font-weight-bold">Name:
                   <span class="name"></span>
            </p>
            <p class="card-text font-weight-bold">Surname:  
                <span class=" surname"></span>
            </p>
            <div class="d-flex justify-content-between align-items-center">
              <p class="font-weight-bold ">Registration: 
                 <span class="font-weight-plain"></span>
                <span class="registration"></span> <span>Expires:
                
        <input  type="text" class="timer"  id="timer"  value=""> </span> 

         <input type="text" class="expiredate" value="">
              </p>  
              
                    
<script>

$(document).ready(function () {
$(document).on('click', '.card .starttimer-btn', function(event){

var expiredate = $(this).closest('.card').find('.expiredate').val();
var id = $(this).closest('.card').find('.timer').attr("id");

 
alert(id);


//alert(expiredate);

var countDownDate = new Date(expiredate).getTime();

// Update the count down every 1 second
var x = setInterval(function() {

  // Get today's date and time
  var now = new Date().getTime();

  // Find the distance between now and the count down date
  var distance = countDownDate - now;

  // Time calculations for days, hours, minutes and seconds
  var days = Math.floor(distance / (1000 * 60 * 60 * 24));
  var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((distance % (1000 * 60)) / 1000);

  //Output the result in an element with id="demo"
 $('.timer').val(days + "d " + hours + "h "+ minutes + "m " + seconds + "s" ).css("color", "black");


  // If the count down is finished, write some text
  if (distance < 0) {
    clearInterval(x);
    document.getElementById("demo").innerHTML = "EXPIRED";
  }
}, 1000);

});
});

</script>

</div>
 <p><button class="starttimer-btn" >Start Timer</button> </p>
 </div>
 </div>
</div>   
    </div>
  </div>

</div>

Any help and advice to get me there is very appreciated thank you!

freedomn-m
  • 27,664
  • 8
  • 35
  • 57
Jvaskana
  • 53
  • 9
  • It looks like all that question boils down to: *how do I use a variable in a selector eg `$("#",timer+id)`* - if that's the case, you're very close: `$("#timer" + id)` – freedomn-m Feb 25 '21 at 20:47
  • Does this answer your question? [jQuery: using a variable as a selector](https://stackoverflow.com/questions/17097947/jquery-using-a-variable-as-a-selector) – freedomn-m Feb 25 '21 at 20:48
  • @ freedomn-m Thanks i have tied what you suggested but unfortunately it has not worked. The button start timer button does nothing now. I spent a lot of time and effort contructing this post as some say not enough info. Please run a code snippet so I see a working version of that you are suggesting. I did hope it would be that simple :-) – Jvaskana Feb 25 '21 at 21:07
  • The alert I setup in the Snippet proves timer ID is working. – Jvaskana Feb 25 '21 at 21:08
  • Look at what the alert is telling you and at what I've suggested. The alert states "timer1" but I've suggested `"timer"+id` which would give you "timertimer1" - shouldn't have been too hard for you to realise that you already had the "timer" prefix so you don't need that in the text. Giving `$("#"+id).val(...`. Added a snippet with an answer so you don't have to come back with "didn't work" :) – freedomn-m Feb 25 '21 at 21:14
  • @freedomn-m Thanks for your help :-) Some times things get so complicated that I begin to miss the simple things. – Jvaskana Feb 25 '21 at 21:18
  • You do have a bit of an XY problem. Your real problem is "How can I reference this input?" which you've attempted to solve by adding a dynamic ID - but then you've asked "How can I access the dynamic ID" - the answer is: **don't use a dynamic ID**. *They are not your friend*. Updated the answer to show you how to remove the need for the dynamic ID. – freedomn-m Feb 25 '21 at 21:25
  • @freedomn-m, thanks for you advice and the ammendments! – Jvaskana Feb 25 '21 at 22:11

1 Answers1

0

As the id retrieved from .attr("id") already contains the full id, you can use:

$("#" + id).val(...

to add the "id selector" (#) in front of your id.

Everything else is unchanged.

$(document).ready(function() {
  // simulates jason data result from Ajax
  var data = [

    {
      "id": "1",
      "name": "Mike",
      "surname": "Rynes",
      "expiredate": "2021/02/25 23:25:00"
    },
    {
      "id": "2",
      "name": "James",
      "surname": "Bond",
      "expiredate": "2021/02/26 23:25:00"
    },
    {
      "id": "3",
      "name": "Harry",
      "surname": "Potter",
      "expiredate": "2021/02/27 23:25:00"
    },

  ];

  $.each(data, function(i, person) {


    var personDetailCloned = $('.card').first().clone().show();

    personDetailCloned.find('.id').text(person.id);
    personDetailCloned.find('.name').text(person.name);
    personDetailCloned.find('.surname').text(person.surname);
    personDetailCloned.find('.expiredate').val(person.expiredate);

    //Generate a random number to be used for timer id
    var timerid = Math.floor(Math.random() * 100);
    personDetailCloned.find('.timer').attr("id", "timer" + person.id);

    $('.card-container').append(personDetailCloned);

  });
});


$(document).ready(function() {
  $(document).on('click', '.card .starttimer-btn', function(event) {

    var expiredate = $(this).closest('.card').find('.expiredate').val();
    var id = $(this).closest('.card').find('.timer').attr("id");


    alert(id);


    //alert(expiredate);

    var countDownDate = new Date(expiredate).getTime();

    // Update the count down every 1 second
    var x = setInterval(function() {

      // Get today's date and time
      var now = new Date().getTime();

      // Find the distance between now and the count down date
      var distance = countDownDate - now;

      // Time calculations for days, hours, minutes and seconds
      var days = Math.floor(distance / (1000 * 60 * 60 * 24));
      var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
      var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
      var seconds = Math.floor((distance % (1000 * 60)) / 1000);

      //Output the result in an element with id="demo"
      console.log(id, $('#' + id).length);
      
      $('#' + id).val(days + "d " + hours + "h " + minutes + "m " + seconds + "s").css("color", "black");


      // If the count down is finished, write some text
      if (distance < 0) {
        clearInterval(x);
        document.getElementById("demo").innerHTML = "EXPIRED";
      }
    }, 1000);

  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

<div class="album py-1">
  <div class="container bg-light">
    <div class="row py-2">
      <div class="col-md-3 card-container">
        <div class="card mb-3 shadow-sm" style="display:none;">
          <div class="hover-container">
          </div>
          <div class="card-body CarDetail">
            <p class="card-text font-weight-bold">ID:
              <span class="id"></span>
            </p>
            <p class="card-text font-weight-bold">Name:
              <span class="name"></span>
            </p>
            <p class="card-text font-weight-bold">Surname:
              <span class=" surname"></span>
            </p>
            <div class="d-flex justify-content-between align-items-center">
              <p class="font-weight-bold ">Registration:
                <span class="font-weight-plain"></span>
                <span class="registration"></span>
                <span>Expires:
                    <input  type="text" class="timer"  id="timer"  value=""> 
                </span>
                <input type="text" class="expiredate" value="">
              </p>
            </div>
            <p><button class="starttimer-btn">Start Timer</button> </p>
          </div>
        </div>
      </div>
    </div>
  </div>

</div>

While the above answers your question, it would be remiss of me not to remind you that dynamic IDs are not-your-friend(tm).

You rarely need a dynamic ID (if a framework adds them, which they do in some cases then you can ignore them).

With two minor changes to your code, you can get rid of the dynamic IDs:

Instead of

var id = ...

Store the element itself:

var timerOutput = $(this).closest('.card').find('.timer');

then you can reference it directly:

timerOutput.val(...

Updated snippet (just 2 lines changed (and a console.log removed))

$(document).ready(function() {
  // simulates jason data result from Ajax
  var data = [

    {
      "id": "1",
      "name": "Mike",
      "surname": "Rynes",
      "expiredate": "2021/02/25 23:25:00"
    },
    {
      "id": "2",
      "name": "James",
      "surname": "Bond",
      "expiredate": "2021/02/26 23:25:00"
    },
    {
      "id": "3",
      "name": "Harry",
      "surname": "Potter",
      "expiredate": "2021/02/27 23:25:00"
    },

  ];

  $.each(data, function(i, person) {


    var personDetailCloned = $('.card').first().clone().show();

    personDetailCloned.find('.id').text(person.id);
    personDetailCloned.find('.name').text(person.name);
    personDetailCloned.find('.surname').text(person.surname);
    personDetailCloned.find('.expiredate').val(person.expiredate);

    //Generate a random number to be used for timer id
    var timerid = Math.floor(Math.random() * 100);
    personDetailCloned.find('.timer').attr("id", "timer" + person.id);

    $('.card-container').append(personDetailCloned);

  });
});


$(document).ready(function() {
  $(document).on('click', '.card .starttimer-btn', function(event) {

    var expiredate = $(this).closest('.card').find('.expiredate').val();
    
    // get the element (jquery obj)
    var timerOutput = $(this).closest('.card').find('.timer');
    var countDownDate = new Date(expiredate).getTime();

    // Update the count down every 1 second
    var x = setInterval(function() {

      // Get today's date and time
      var now = new Date().getTime();

      // Find the distance between now and the count down date
      var distance = countDownDate - now;

      // Time calculations for days, hours, minutes and seconds
      var days = Math.floor(distance / (1000 * 60 * 60 * 24));
      var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
      var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
      var seconds = Math.floor((distance % (1000 * 60)) / 1000);

      timerOutput.val(days + "d " + hours + "h " + minutes + "m " + seconds + "s").css("color", "black");


      // If the count down is finished, write some text
      if (distance < 0) {
        clearInterval(x);
        document.getElementById("demo").innerHTML = "EXPIRED";
      }
    }, 1000);

  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

<div class="album py-1">
  <div class="container bg-light">
    <div class="row py-2">
      <div class="col-md-3 card-container">
        <div class="card mb-3 shadow-sm" style="display:none;">
          <div class="hover-container">
          </div>
          <div class="card-body CarDetail">
            <p class="card-text font-weight-bold">ID:
              <span class="id"></span>
            </p>
            <p class="card-text font-weight-bold">Name:
              <span class="name"></span>
            </p>
            <p class="card-text font-weight-bold">Surname:
              <span class=" surname"></span>
            </p>
            <div class="d-flex justify-content-between align-items-center">
              <p class="font-weight-bold ">Registration:
                <span class="font-weight-plain"></span>
                <span class="registration"></span>
                <span>Expires:
                    <input  type="text" class="timer"  id="timer"  value=""> 
                </span>
                <input type="text" class="expiredate" value="">
              </p>
            </div>
            <p><button class="starttimer-btn">Start Timer</button> </p>
          </div>
        </div>
      </div>
    </div>
  </div>

</div>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57