Rails6 countdown timer implementation

Introduction

Implement the countdown timer that will be implemented in the portfolio. There is an article that says that jQuery is required to implement the timer, but this time I will proceed with the implementation without using jQuery.

Creation order

As a specific procedure ① Create a deadline, which is a time limit column (2) Write HTML to display the timer on the screen. ③ I want to display the time limit, so write it using javascript

Creating a column

First, as always

$rails generate migration Add Column name To Table name Column name: Data type

Create a migration file with.

In this case, I want to display the time limit in the posting part, so I used deadline as the column name.

$rails generate migration AddDeadlineToMission deadline:datetime

And.

db/migrate/20200903084112_create_missions.rb


class CreateMissions < ActiveRecord::Migration[6.0]
  def change
    create_table :missions do |t|
      t.integer :user_id
      t.text    :content
      t.string  :penalty
      t.datetime   :deadline

      
      t.timestamps
    end
  end
end

Add `` `t.datetime: deadline``` to line 7 of the migration file above. And I saw it from the face of my parents

$ rails db:migrate

To save to the database.

Implementation of timer

スクリーンショット 2020-09-22 0.33.23.png

HTML description

To set a deficit timer like the one above

app/views/missions/new.html.erb


<p>
     <%= f.hidden_field :deadline, :id => "deadline.id" %>
        <input type="text" id="userYear" >Year
        <input type="text" id="userMonth">Month
        <input type="text" id="userDate" >Day
        <input type="text" id="userHour" >Time
        <input type="text" id="userMin"  >Minutes
        <input type="text" id="userSec"  >Seconds
 </p>
       <p id="RealtimeCountdownArea" ></p> #The timer is displayed here

And. Here, `` `: id => deadline.id``` is described because it will be effective in the description of javascript later.

Javascript description

This time, I will write javascript in the script tag of app / views / missions / new.html.erb.

It is as follows.

app/views/missions/new.html.erb


<script>
    
function set2fig(num) {
   //If the number is 1 digit, return it as a 2-digit character string
   var ret;
   if( num < 10 ) { ret = "0" + num; }
   else { ret = num; }
   return ret;
}
function isNumOrZero(num) {
   //If it is not a numerical value, set it to 0 and return it.
   if( isNaN(num) ) { return 0; }
   return num;
}
function showCountdown() {
   //Numerical current date and time(1970-01-01 00:00:Milliseconds from 00)Conversion to
   var nowDate = new Date();
   var dnumNow = nowDate.getTime();
 
   //Numerical value for the specified date and time(1970-01-01 00:00:Milliseconds from 00)Conversion to
   var inputYear  = document.getElementById("userYear").value;
   var inputMonth = document.getElementById("userMonth").value - 1;
   var inputDate  = document.getElementById("userDate").value;
   var inputHour  = document.getElementById("userHour").value;
   var inputMin   = document.getElementById("userMin").value;
   var inputSec   = document.getElementById("userSec").value;
   var targetDate = new Date( isNumOrZero(inputYear), isNumOrZero(inputMonth), isNumOrZero(inputDate), isNumOrZero(inputHour), isNumOrZero(inputMin), isNumOrZero(inputSec) );
   var dnumTarget = targetDate.getTime();
 
   //Prepare the display
   var dlYear  = targetDate.getFullYear();
   var dlMonth = targetDate.getMonth() + 1;
   var dlDate  = targetDate.getDate();
   var dlHour  = targetDate.getHours();
   var dlMin   = targetDate.getMinutes();
   var dlSec   = targetDate.getSeconds();
   var msg1 = "Deadline" + dlYear + "/" + dlMonth + "/" + dlDate + " " + set2fig(dlHour) + ":" + set2fig(dlMin) + ":" + set2fig(dlSec);
 
   //Days after subtraction(millisecond)Calculate the difference between
   var diff2Dates = dnumTarget - dnumNow;
   if( dnumTarget < dnumNow ) {
      //If the deadline has passed-Multiply by 1 to convert to positive value
      diff2Dates *= -1;
   }
 
   //Divide the difference millisecond into days, hours, minutes, and seconds
   var dDays  = diff2Dates / ( 1000 * 60 * 60 * 24 );   //Days
   diff2Dates = diff2Dates % ( 1000 * 60 * 60 * 24 );
   var dHour  = diff2Dates / ( 1000 * 60 * 60 );   //time
   diff2Dates = diff2Dates % ( 1000 * 60 * 60 );
   var dMin   = diff2Dates / ( 1000 * 60 );   //Minutes
   diff2Dates = diff2Dates % ( 1000 * 60 );
   var dSec   = diff2Dates / 1000;   //Seconds
   var msg2 = Math.floor(dDays) + "Day"
            + Math.floor(dHour) + "time"
            + Math.floor(dMin) + "Minutes"
            + Math.floor(dSec) + "Seconds";
 
   //Creating a display string
   var msg;
   if( dnumTarget > dnumNow ) {
      //If the deadline has not come yet
      msg = msg1 + "Until" + msg2 + "is.";
   }
   else {
      //When the deadline has passed
      msg = msg1 + "Already" + msg2 + "It passed before.";
   }
 
   //Display the created character string
   document.getElementById("RealtimeCountdownArea").innerHTML = msg;
   document.getElementById("deadline.id").value =  targetDate; #Most important description

}
//Run every second
setInterval('showCountdown()',1000);


</script>

Here, the previous : id => deadline.id comes into play. Only by adding such a description You can receive the result processed by javascript as value and display it on the screen. Now you can finally implement the timer.

If you want to display only the timer

It is also possible that you do not want to display the date and time entry field. If you want to display only the deadline and the remaining time of the timer as shown in the picture below, スクリーンショット 2020-09-22 0.49.38.png

app/views/missions/show.thml.erb


      <p>Deadline<%= @mission.deadline %>
      <br>
        <input type="hidden" id="userYear" value = "<%= @mission.deadline.year %>"  > 
        <input type="hidden" id="userMonth"value = "<%= @mission.deadline.month %>" >
        <input type="hidden" id="userDate" value = "<%= @mission.deadline.day %>" >
        <input type="hidden" id="userHour" value = "<%= @mission.deadline.hour %>" >
        <input type="hidden" id="userMin"  value = "<%= @mission.deadline.min %>" >
        <input type="hidden" id="userSec"  value = "<%= @mission.deadline.sec %>" >
      </p>
      <p id="RealtimeCountdownArea" ></p>

<script>



function set2fig(num) {
   //If the number is 1 digit, return it as a 2-digit character string
   var ret;
   if( num < 10 ) { ret = "0" + num; }
   else { ret = num; }
   return ret;
}
function isNumOrZero(num) {
   //If it is not a numerical value, set it to 0 and return it.
   if( isNaN(num) ) { return 0; }
   return num;
}
function showCountdown() {
   //Numerical current date and time(1970-01-01 00:00:Milliseconds from 00)Conversion to
   var nowDate = new Date();
   var dnumNow = nowDate.getTime();
 
   //Numerical value for the specified date and time(1970-01-01 00:00:Milliseconds from 00)Conversion to
   var inputYear  = document.getElementById("userYear").value;
   var inputMonth = document.getElementById("userMonth").value - 1;
   var inputDate  = document.getElementById("userDate").value;
   var inputHour  = document.getElementById("userHour").value;
   var inputMin   = document.getElementById("userMin").value;
   var inputSec   = document.getElementById("userSec").value;
   var targetDate = new Date( isNumOrZero(inputYear), isNumOrZero(inputMonth), isNumOrZero(inputDate), isNumOrZero(inputHour), isNumOrZero(inputMin), isNumOrZero(inputSec) );
   var dnumTarget = targetDate.getTime();
 
   //Prepare the display
   var dlYear  = targetDate.getFullYear();
   var dlMonth = targetDate.getMonth() + 1;
   var dlDate  = targetDate.getDate();
   var dlHour  = targetDate.getHours();
   var dlMin   = targetDate.getMinutes();
   var dlSec   = targetDate.getSeconds();
   var msg1 = "Deadline" + dlYear + "/" + dlMonth + "/" + dlDate + " " + set2fig(dlHour) + ":" + set2fig(dlMin) + ":" + set2fig(dlSec);
 
   //Days after subtraction(millisecond)Calculate the difference between
   var diff2Dates = dnumTarget - dnumNow;
   if( dnumTarget < dnumNow ) {
      //If the deadline has passed-Multiply by 1 to convert to positive value
      diff2Dates *= -1;
   }
 
   //Divide the difference millisecond into days, hours, minutes, and seconds
   var dDays  = diff2Dates / ( 1000 * 60 * 60 * 24 );   //Days
   diff2Dates = diff2Dates % ( 1000 * 60 * 60 * 24 );
   var dHour  = diff2Dates / ( 1000 * 60 * 60 );   //time
   diff2Dates = diff2Dates % ( 1000 * 60 * 60 );
   var dMin   = diff2Dates / ( 1000 * 60 );   //Minutes
   diff2Dates = diff2Dates % ( 1000 * 60 );
   var dSec   = diff2Dates / 1000;   //Seconds
   var msg2 = Math.floor(dDays) + "Day"
            + Math.floor(dHour) + "time"
            + Math.floor(dMin) + "Minutes"
            + Math.floor(dSec) + "Seconds";
 
   //Creating a display string
   var msg;
   if( dnumTarget > dnumNow ) {
      //If the deadline has not come yet
      msg =  "Until the end of the mission" + msg2 ;
   }
   else {
      //When the deadline has passed
      msg = msg1 + "Already" + msg2 + "It passed before.";
   }
 
   //Display the created character string
   document.getElementById("RealtimeCountdownArea").innerHTML = msg;
   document.getElementById("deadline.id").value =  targetDate;

}
//Run every second
setInterval('showCountdown()',1000);

</script>


If you set input type =" hidden " as above, the entry field will not be displayed on the screen, but the six `<input type = ・ ・ ・>` will be deleted. This does not mean that it will start normally.

Also, <input type = "hidden" id = "userYear" value = "<% = @ mission.deadline.year%>"> `

value="<%= @mission.deadline.year %>"I will explain why the part of is such a description. This is because deadline is a column that takes a data type called datetime, but datetime stores date and time information such as year, month, day, hour, minute, and second. Therefore, with the above description, new.html.The date and time of the deadline described in the erb part can be retrieved.



# Summary
 The difficulty was quite high, but the sense of accomplishment was amazing. I would appreciate it if you could refer to it as much as possible.

 Reference article
https://www.nishishi.com/javascript-tips/realtime-countdown-deadline.html


Recommended Posts

Rails6 countdown timer implementation
iOS app development: Timer app (4. Countdown implementation)
[rails] gem'payjp' implementation procedure
Rails Action Text implementation
Rails search function implementation
Rails implementation of ajax removal
Rails fuzzy search function implementation
[Rails 6] Implementation of search function
[Rails] Implementation of category function
[Java] Timer processing implementation method
Login function implementation with rails
[Rails] Implementation of tutorial function
[Rails] Implementation of like function
[Rails 6] Pagination function implementation (kaminari)
[Rails] Implementation of user logic deletion
[Rails] Implementation of CSV import function
[Rails] Asynchronous implementation of like function
[rails] Login screen implementation in devise
[Rails] Implementation of image preview function
[Rails] About implementation of like function
[Rails] Implementation of user withdrawal function
[Rails] Implementation of CSV export function
[Rails] Implementation of many-to-many category functions
[Rails] gem ancestry category function implementation
[Ruby on Rails] Comment function implementation
[Rails 6] Like function (synchronous → asynchronous) implementation
[Rails] Comment function implementation procedure memo
[Ruby on Rails] Follow function implementation: Bidirectional
Rails [For beginners] Implementation of comment function
Rails Basic CRUD function implementation procedure scaffold
[Rails 6] Implementation of SNS (Twitter) sharing function
[Vue.js] Implementation of menu function Implementation version rails6
[Ruby on rails] Implementation of like function
[Rails] Implementation of validation that maintains uniqueness
[Vue.js] Implementation of menu function Vue.js introduction rails6