0

I am trying to do front-end timer that would precisely show time left (in minutes and seconds).

This timer is supposed to count, even when user left the site or even close browser.

Although I thought of simple way to do the back-end part of it, I have no idea how to do it front-end, since I don't know JS or jQuery for that matter. I could use gems, but most of them are using cannon to kill a fly. No need for scheduling since I don't need callbacks.

All I want to do is simple timer, where I pass rails variable with time of finish and counts down and stops when it reaches 0.

Here is what I found so far, but how do I pass rails variable into JS/jQuery?

@Edit for possible duplicate. This question is about said timer, but from rails point of view.

Community
  • 1
  • 1
  • Possible duplicate of [The simplest possible JavaScript countdown timer?](http://stackoverflow.com/questions/20618355/the-simplest-possible-javascript-countdown-timer) – Eyeslandic Feb 17 '17 at 13:11
  • 1
    Not really, since this question is about that, but from rails point of view. Imho more like suplementary question. –  Feb 17 '17 at 13:38

3 Answers3

1

The js timer you found will do nicely. The simplest way to pass a RoR variable into the js would be to use standard controller (.rb) -> view (.html.erb) communication channel.

In view:

<% <statement> %> - for conditionals and other pieces of non displayed code
<%= <statement> %> - for displaying variables etc.
<%# <statement> %> - easy way to comment ruby code

Example of what you want to do could then be:

Let us have a controller site_controller.rb:

class SiteController < ApplicationController
  def index
    @time_variable = 5.hours
  end
end

Now we can create a view for this (site/index.html.erb): (Let the startTimer(duration, display) be defined already)

<div id='time'></div>
<script>
  window.onload = function () {
    var timer = <%= @time_variable.to_i %>;
    display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
  };
</script>

Hope this helps.

Jacob
  • 79
  • 7
1

What you want to do is creating a container that will display your text and use javascript to update it's content. To tell the (client-side) javascript to what time it shall count down, you might create a hidden field containing that value, and read it out using jQuery. (Note: Passing the value could also be archieved through AJAX+embedded ruby in the JS-file, but it is much tougher to understand, and creating a hidden field in your html.erb should do your job even a bit faster!)

  1. Retrieving the hidden field's content (a.k.a. the moment in time that your countdown is leading to):

var end_time = $('hidden-field').text();
#hidden-field {
  display:none;
}
<span id='hidden-field'><%= time %></span>
(Note: As rails comes with jQuery, using it saves a lot of headdache. However, usually including the jQuery-library for this would be considered a "cannon to kill a fly". Also, make sure to use the correct CSS-Selecter within the jQuery call.)

You could also simply add this to your html.erb to assign a variable:

<script type='text/javascript'>var end_time = <%= time %> ;</script>

Depending on the format of your time (datetime vs unix timestamp vs...) you then let Javascript do the math. As rails usually saves Daytime-elements in the database, this should work:

var time_left = Math.abs(new Date(end_time) - new Date());

To insert into your page, do this:

$('#result').text(time_left);
#result {
  // Some styling here
}
<p id='result'></p>

To make it work automatically from that point, combine the last two to a function like

var time_left;
function getTimeLeft() {
  time_left = Math.abs(new Date(end_time) - new Date());
  $('#result').text(time_left);
}

This last call will run your function every second

setInterval(getTimeLeft, 1000);

I did not test the code, but it should work or at least give the basic idea how you could do it. If you run into errors, please comment.

Happy coding.

P.S. Jacob's answer is shorter and more on the point. Try it first and come back here if you need to go further.

randmin
  • 470
  • 3
  • 12
  • Thanks a lot. Where do I put `setInterval(getTimeLeft, 1000);` ? Also both Rails and JS use Unix Time right? Does that mean that Date() returns timestamp (single number)? So I would also have to translate said number into minutes and seconds (and remove miliseconds)? –  Feb 17 '17 at 14:09
  • Simply put the setInterval() call at the end of the code, outside of the function. This way, it will be called when all the variables and functions are definied. For conversion of the Date-Object check out (http://stackoverflow.com/questions/5683728/convert-java-util-date-to-string). You're very welcome. – randmin Feb 17 '17 at 15:00
  • I've called in view `` right before `

    ` but it seems like variable is not passed as it should be. When I try to change `$('#result').text(end_time);` just to see if it will show the time, it doesn't show anything.
    –  Feb 17 '17 at 15:13
  • `` is missing the "=". Try `` instead – randmin Feb 17 '17 at 15:26
0

There are a lot of ways to pass data from the back-end to the front-end in Rails.

First of all, there is the possibility of actually performing a request to the server to get back some data. In your case, I think this is overkill.

Another option would be to add the information in your view via the DOM. An often used pattern is to add data attributes to elements. Here's some references to get you started in jquery or plain javascript.

You can pass data to an element in your ERB template like so

<div id="timer" data-startdate="<%= get_date %>"></div>

and then have the front-end read this value and start the countdown appropriately.

Another option would be to expose a javascript variable to your window object, by including it in a script in your ERB template

<script>var startDate = '<%= get_date %>';</script>

Then front-end can then access window.startDate.

Good luck!

gkats
  • 1,117
  • 6
  • 8