Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
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.
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!)
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.
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.
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!
Related
So I have this JS script:
<script>
function getCheckedProperty(obj,args)
{
if(document.getElementById("<%=checkbox1.ClientID %>").checked)
return true;
else
return false;
}
</script>
This only works for checkBox1. I want to be able to pass control id from parameters, so that it can return value of passed control. Also, please, respond with the usage.
<asp:CustomValidator runat="server" ClientValidationFunction="getCheckedProperty()></asp:CustomValidator>
TIY. SRJ.
Check this question it might have your answer.
if I get it right you want to get ids dynamically for example checkbox1, checkbox2,...
You can add the dynamic part to the id like this:
for (var i = 1; i < n; i++) {
var id = "checkbox" + i;
var ch = document.getElementById(id);
if (ch.checked == false)
return false;
}
return true;
Unfortantly, this is a real problem. The control name(s) are generated at runtime, and ALSO THIS:
document.getElementById("<%=checkbox1.ClientID %>")
So at page render time, the .net pre-processor will SWAP out the <% %> at render time.
this is also why you can't say have the js code in a external library and expect this to work.
However, your DEAD OBVIOUS question remains. Stuff a name into a simple variable and use that to get the control. After all, we can't and would not want to HARD code the value as per above, and it would be beyond silly to assume we ONLY have a means to HARD code references to controls.
So, you want of course this:
var MyControl = 'Checkbox1';
var ckBox = document.getElementById(MyControl);
if (ckBox.checked)
alert('Check box ' + MyControl + ' is checked!');
else
alert('Check box ' + MyControl + ' is UN-checked');
Now in fact the ABOVE can and will work if you force the control name generation as static.
so, here is the markup:
<asp:CheckBox ID="CheckBox1" runat="server" ClientIDMode="Static" />
So, if you ARE able and ARE willing to use ClientIDMode static, then the .net processing will NOT re-name your control. As a result you can do this:
var MyControl = 'Checkbox1';
var ckBox = document.getElementById(MyControl);
Or, even this (as HARD coded)
var ckBox = document.getElementById('CheckBox1');
Or even this:
var ckbox2 = document.getElementById(<%= CheckBox1.ClientID %>);
Now, the last one above? Well, we ARE useing the .net pre-processor to swap out the name - but it will still work - and clientID will not be changed - but the pre-processor is STILL involved.
AGAIN: the <%= 'SomeControlName.ClientID%> ONLY works because this expression is SWAPPED out at runtime by the .net web page pre-processor. This occures BEFORE the js code is run.
So you can NOT use a variable in the above <%=%> expressions since the js code HAS NOT even run and the new js code has not even been generated at this point in time.
In effect, you would (have to) do a PAGE search for the control. If you can NOT adopt ClientIdMode="static", then you MUST SEARCH the page.
You can write your OWN search routines - kind of like adopting a nice road to world poverty, or you bite the bullet, and adopt a library that WILL do the heavy lifting for you.
So, without using (forcing) StaticID on the control? then you now have to accept the BIG HUGE LARGE MASSIVE decision and introduce jQuery into your application.
jQuery is able to scour and search and look and loop and find that control for you on the web page. This is a cost not without processing cost, and not without a big speed penalty.
So, without staticID's, then you can adopt jquery and do this:
<script src="Scripts/jquery-3.5.1.js"></script>
<script>
// so if you decide and adopt jQuery, then it can do the searching for you
// BUT YOU ARE now adopting and committing to a whole new js library
// so, with jQuery we cna do this:
function jstest2(){
var ckbox2 = $('#CheckBox1');
var ckboxdom = ckbox2[0];
alert('status of check box = ' + ckboxdom.checked);
// of course the above is STILL hard code
// get control by runtime or NON hard code
// get (search) for check box based on control name in
// a variable
var MyCheckBox = 'CheckBox1';
var ckbox3 = $('#' + MyCheckBox);
var ckboxdom3 = ckbox3[0];
alert('status of check box = ' + ckboxdom3.checked);
</script>
I found after doing a nuget of jQuery, the fans on my laptop became too hot to even keep on my lap. But, things did settle down, and eventually the VS editors caught up, and things did settle down.
Also keep in mind that you have to re-learn how to reference a simple control.
eg:
<script>
function getbox() {
var tbox = document.getElementById('TextBox1');
alert(tbox.value);
// jQuery example
var tbox2 = $('#TextBox1');
alert(tbox2.val());
}
</script>
So notice now, how the long time js standard and approach is "value" as a property?
Well, now you using .val() that is a function (method) of that search result. So just keep in mind that by adopting jQuery, then all of your code that needs to get simple values from controls has to under go a syntax change, and you as a developer will have to re-lean how to reference a simple control with new syntax. The check box is a great example - it now becomes a array, and you use that array to get at the checked property.
And same in above for a simple grab of a value from a text box.
Notice how the syntax and approach to getting the value of the text box NOW has changed!!!! So you need a cheat-sheet since simple things like value now become .val().
And the same changes occur for say a label on a web page (again syntax changes).
You will ALSO notice that the results of the check box example are an array!!! So we had to drill down into the resulting array[] to get the "checked" value.
Of course how big of a deal your code changes are by adopting jQuery? Well, it depends, on relative medium sized or even a small project? $20,000 was budgeted and we still changing things.
On larger projects you simply need more manpower and would add another zero to the above cost to adopt jQuery.
However, jQuery is now widespread used, and it will do the "dirty work" of searching the DOM for you, and if you need runtime resolution as opposed to compile time resolution to find a simple control on a web page, then jQuery is probably your best choice. And I find that jQuery is really nice for ajax calls - so while it is a big change, it still well worth the effort to adopt the jQuery library and risk introducing this framework into your existing projects.
Very new to Javascript and have been searching the webs for assistance, but haven't quite found a solution.
I am attempting to use javascript to split/remove the output of a particular field. The data in the survey is being pulled from our school's database after a user logs in to the survey via shibboleth. All the information is being displayed, so that part works, but one particular field is appending an email address (#email.com) to a field.
I want to omit this part from being displayed. Either my javascript is incorrect or the javascript is not being loaded/read. The javascript code was borrowed from a colleague and it works on his surveys, but he has a lot of other things going on in his survey and this works for him.
Qualtrics.SurveyEngine.addOnload(function()
{
/*Place your JavaScript here to run when the page loads*/
var iid = "${e://Field/theUTIID}";
var split_array = iid.split("#",1);
var eid = split_array[0];
Qualtrics.SurveyEngine.setEmbeddedData('theUTIID', eid);
});
Qualtrics.SurveyEngine.addOnReady(function()
{
/*Place your JavaScript here to run when the page is fully displayed*/
var iid = "${e://Field/theUTIID}";
var split_array = iid.split("#",1);
var eid = split_array[0];
Qualtrics.SurveyEngine.setEmbeddedData('theUTIID', eid);
});
I have this in both the Onload and OnReady for testing. Doesn't matter if I have this is one location or the other, I am not getting the desired results.
I only have one question on the survey (it's just a test survey) and so the javascript code is with the first and only question.
Survey Question has the following in a text entry. Again, output is displayed, but need the #email.com to removed from the EID field.
The code looks correct (other than it only needs to be in one or the other function). I'm guessing it isn't a problem with the code, but where you are trying to pipe the embedded variable. The JavaScript above has to be attached to a question on a separate page before the place where you want to pipe it.
Add a page break, then pipe theUTIID into a question on the next page.
This question already has answers here:
How to pass a javascript variable to server side method
(3 answers)
Closed 7 years ago.
Here is an example:
JavaScript:
var b = 'Banana';
var list= <%= getJson() %>; // want to pass b?
C# Method:
using System.Web.Script.Serialization;
....
public string getJson(string x)
{
var list = new List<object>{new []{ "1","Apple"}, new []{ "2",x}};
return (new JavaScriptSerializer()).Serialize(list);
}
How can I pass variable b when I call getJson() from JavaScript?
The problem is, the server-side code executes and generates the page (including the javascript which is just text at this point). The page is then sent to the browser where the javascript is executed.
By that time, it's too late to do anything server-side.
Your options are:
Do a GET/POST/similar of the whole page back to the server, with the new variable from JS in a form field. This is trivial but causes a full-page refresh and is becoming less and less desirable.
Use a Javascript Ajax request to pass the variable back to the server and ask it for updated content. Use the response from the server to update the page for the user
The documentation for how to do the latter using jQuery is available here and there are literally thousands of examples around Stack Overflow.
Remember, anything called inside the <% ... %> tags get processed on the server side before the page even loads. If you need to dynamically load information from the server based on a variable, you need to make an AJAX request.
If you are able to, the easiest way to do this is with jQuery.
I'm new with primefaces and JSF, but is there anyway to create a p:dataTable that has a
p:column which acts like a stopwatch?
Like this
Subject|Time Remaining|Subject Title
MATH | 00:03:00 |Mathematics 1
SCIENCE| 00:33:00 |Science 1
HISTORY| 01:03:00 |History1
It gets the remaining time from a database, then the javascript code does the stopwatch so it is on client side. I already have a javascript code that does the ticking part for the remaining time, but It only works for one row.
You can use Primefaces Ajax Polling component which makes ajax calls in a specified interval.
Or else you can use put Javascript as specified in this stackoverflow Question.
I'd like to start by saying that my code is working perfectly, this is more a "how best to do it" kind of question.
So I have code like this in my .aspx file:
function EditRelationship() {
var projects=<%= GetProjectsForEditRelationship() %>;
// fill in the projects list
$('#erProjectsSelect').empty();
for(var i in projects)
$('#erProjectsSelect').append('<option value='+projects[i][0]+'>'+projects[i][1]+'</option>');
var rels=<%= GetRelationshipsForEditRelationship() %>;
// etc
}
Again, it's working fine. The problem is that VS2008 kinda chokes on code like this, it's underlining the < character in the tags (with associated warnings), then refusing to provide code completion for the rest of the javascript. It's also refusing to format my document anymore, giving parsing errors. The last part is my worst annoyance.
I could put some of these in evals I guess, but it seems sorta dumb to add additional layers and runtime performance hits just to shut VS up, and it's not always an option (I can't remember off the top of my head where this wasn't an option but trust me I had a weird construct).
So my question is, how do you best write this (where best means fewest VS complaints)? Neither eval nor ajax calls fit this imo.
If your aim is to reduce VS complaints, and if you are running asp.net 4 (supporting Static client Ids), maybe a strategy like the following would be better?
Create a ASP:HiddenField control, set its ClientIdMode to "Static"
Assign the value of GetRelationshipsForEditRelationship() to this field on page load
In your javascript, read the value from the hidden field instead, I assume you know how to do this.
It's more work than your solution, and you will add some data to the postback (if you perform any) but it won't cause any VS complaints I guess :)
You could do this from your page in the code-behind
ClientScript.RegisterArrayDeclaration("projects", "1, 2, 3, 4");
or to construct something like JSON you could write it out
ClientScript.RegisterClientScriptBlock(GetType(), "JSONDeclarations", "your json stuff");
UPDATE Based on my comment
<script id="declaration" type="text/javascript">
var projects=<%= GetProjectsForEditRelationship() %>;
var rels=<%= GetRelationshipsForEditRelationship() %>;
</script>
<script type="text/javascript">
function EditRelationship() {
// fill in the projects list
$('#erProjectsSelect').empty();
for(var i in projects)
$('#erProjectsSelect').append('<option value='+projects[i][0]+'>'+projects[i][1]+'</option>');
}
</script>
I don't have VS2008 installed to test with, so take this with a grain of salt, but have you tried something like this?
var projects = (<%= GetProjectsForEditRelationship() %>);
Something like that might trick the JavaScript parser into ignoring the content of your expression.
For what it's worth, VS2010 correctly parses and highlights your original code snippet.
Is it an option to move this to VS2010? I just copied and pasted your code and the IDE interpreted it correctly.
The best solution is to put javascript in a separate file and avoid this entirely. For this particular function, you're doing server-side work. Why not build the list of options that you intend to add dynamically in codebehind, put them in a hidden div, and then just have jQuery add them from the already-rendered HTML?
If you have a situation where you really want to dynamically create a lot javascript this way, consider using ScriptManager in codebehind to set up the variables you'll need as scripts and register them, then your inline script won't need to escape
ScriptManager.RegisterClientScript("projects = " + GetProductsForEditRelationship());
(Basically, that is not the complete syntax, which is context dependent). Then refer to "projects" in your function.
(edit)
A little cleaner way to do this on a larger scale, set up everything you need like this in codebehind:
string script = "var servervars = {" +
"GetProductsForEditRelationship: " + GetProductsForEditRelationship() +
"GetRelationshipsForEditRelationship: " + GetRelationshipsForEditRelationship() +
"}"
and refer to everything like:
servervars.GetProductsForEditRelationship
If you do this a lot, of course, you can create a class to automate the construction of the script.