I am learning javascript and at the same time trying to create a simple script that allows you to type a foreign language on a web browser with your keyboard.
So, when you type a for example, there is a single letter mapped to a, so a single character Դ would appear, however to make a character like 厄 appear, you have to type twice, since this language has more characters than the English alphabet.
So, the problem is with that last character. Normally, I should have to type g and h consecutively in the span of one second to produce the 厄 letter, but I have problems waiting to check if within two characters have been typed within one second of eachother inorder to show that letter.
So, I don't think time interval functions are the way to go about this, but I can't see any other method also.
cautions: check key whether up in keydown() & notify keydown the key is upped in keypress();
var start = null;
$('#in').keydown(function (e) {
if (!start) {//checking is a new user input
start = $.now();
}
}).keyup(function (e) {
var timeElapsed = $.now() - start;
start = null;//start the next timing tracking
console.log(['time elapsed:', timeElapsed, 'ms'].join(' '));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
<h2>please input some letter to test</h2>
<input id="in"/>
</label>
another answer about your question,perhaps this is your truly answer.
function duration(timestamps) {
var last = timestamps.pop();
var durations = [];
while (timestamps.length) {
durations.push(last - (last = timestamps.pop()));
}
return durations.reverse();
}
function display(mills) {
if (mills > 1000)
return (mills / 1000) + ' s';
return mills + ' ms';
}
var durations = [];
$('#in').keydown(function (e) {
durations.push($.now());
}).keyup(function (e) {
var current = durations;
current.push($.now());
durations = [];
var timeElapsed = current[current.length - 1] - current[0];
console.log([
['time elapsed:', display(timeElapsed)].join(' '),
['keys duration:', duration(current).map(display)].join(' ')
].join(' --- '));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
<h2>Please input something to test!</h2>
<input id="in"/>
</label>
Below is the sample code to measure the elapsed time between any 2 events.
I added setTimeout just to give you an example.
var startTime = Date.now();
setTimeout(function(){
var elapsedTime = Date.now() - startTime;
console.log('elapsedTime ='+elapsedTime);
}, 100);
Like Alex mentioned, for every press, simply store new Date().getTime(); in a variable, which will get you the latest UTC time. UTC time is given in milliseconds, so on the next key-press, just see if the current time and the stored time differ by 1000!
Related
I am trying to create a Countup counter Starting from 1 to 10000 and i do not want it to reset when user refreshes the page or cancels the page. The Counter should start from 1 for every user that visits the page and keep running in background till it gets to 10000 even if the page is closed.
I have written the page below which;
Starts from the specified number for every new visitor
Saves the progress and does not reset when page is refreshed, however
It does not keep counting when page is closed and starts from the last progress when user closes the tab and comes back later. My code is
function countUp() {
var countEl = document.querySelector('.counter');
var countBar = document.querySelector('.progress-bar');
var x = parseInt(localStorage.getItem('lastCount')) - 1 || 1;
var y = countEl.dataset.to;
var z = countBar.dataset.to;
function addNum() {
countEl.innerHTML = x;
x += 1;
if (x > y && x > z) {
clearInterval(timer);
}
localStorage.setItem('lastCount', x);
}
var timer = window.setInterval(addNum, 1000);
localStorage.setItem("addNum", counter);
toggleBtn.addEventListener('click', function(){
countUp();
toggleBtn.classList.add('hidden');
});
}
countUp();</script>
<body onload=countUp();>
<div class="counter" data-from="0" data-to="10000000"></div>
<div class="progress-bar" data-from="0" data-to="10000000"></div>
</body>
It's difficult to show an example on StackOverflow because it doesn't let you fiddle with localStorage but, it sounds like you want something like:
When a user visits the page check localStorage for a timestamp.
If timestamp exists, go to step 4
Timestamp doesn't exist so get the current timestamp and stash it in localStorage.
Get the current timestamp. Subtract the timestamp from before. If over 10,000, stop, you're done.
Display difference calculated in step 4.
Start a 1 second timer, when time is up, go to step 4.
Something along those lines should work even if they refresh the page and since you are calculating from the original timestamp it will "count" in the background even if the page is closed.
window.addEventListener("DOMContentLoaded", () => {
const start = localStorage.getItem("timestamp") || Date.now();
localStorage.setItem("timestamp", start);
function tick() {
const now = Date.now();
const seconds = Math.floor((now - start) / 1000);
const display = document.getElementById("display");
if (seconds > 10000) return display.innerHTML = "We're done";
display.innerHTML = seconds;
setTimeout(tick, 1000);
}
tick();
});
<div id="display"></div>
So, client-side code can't normally execute when a client-side javascript page is closed.
What you could do, however, is calculate where the timer should be then next time it is loaded.
For example, in your addNum() function, you could in addition to the last count, also store the current date (and time).
function addNum() {
countEl.innerHTML = x;
x += 1;
if (x > y && x > z) {
clearInterval(timer);
}
localStorage.setItem('lastCount', x);
localStorage.setItem('lastDate', new Date());
}
Then, when your code starts, you can retrieve lastDate, and then subtract the current Date() from it.
Then use that to add the difference to your counter.
function countUp() {
let storedCount = parseInt(localStorage.getItem('lastCount'));
let storedDate = Date.parse(localStorage.getItem('lastDate'));
let now = new Date()
let diffSeconds = (now.getTime() - storedDate.getTime()) / 1000;
let storedCount += diffSeconds;
var countEl = document.querySelector('.counter');
var countBar = document.querySelector('.progress-bar');
var x = storedCount - 1 || 1;
var y = countEl.dataset.to;
var z = countBar.dataset.to;
}
I'm sure there are some more changes required to make it work with your code, but the idea is to store the current time so that when the page is closed and reopened, you can 'adjust' the count to catch up to what it should be.
What you want here is not possible just from the client-side code, there is no way for 2 different machines to share that information at all.
Here's the thing though, you can do this with a backend where the database gets updated every time a new IP hits the server. Note with this approach, a user here is one system and not different browsers or sessions.
To update this real-time for someone who is already on the website, run a timer and call an API that specifically gives you the count. Therefore the page gets updated frequently. You can also do this with react-query as it comes with inbuilt functions to do all this.
Hello every body i need help with moment js i've an input field called Start and another called stop
start = moment().format('LT'); // works when i click on the play button
stop = moment().format('LT'); // works when i focus on the counter input beside the play button --> for test
i want to change the start input field manually so i want a validation function that takes the input value and check if the input is valid or not on this form LT for ex: when i delete the value of the input which is 6:39 PM as below in the picture and type for example 6:02:00 PM or 1:00 PM or add a string 5:dfds2 PM i want to console log any error message and return the previous value to the input again also when i remove the current value and add a number like '1 for example' without am or pm so it determines if the number is before or after than stop input value and type in the input field like this 1:00 AM or 1:00PM i used this function to validate the start input field but it gives me wrong answers
function validate(inputVal) {
let temp =this.startTime;
let x = temp;
if(moment(inputVal, "hh:mm").isValid()) {
x= moment(inputVal, "HH:mm").format('hh:mm A');
console.log("inputVal is: " + inputVal + " and x is: " + x);
this.startTime = x
} else {
this.startTime = "temp";
console.log("no");
}
}
here is the pic
for more info u can visit toggl website my idea is taken from there
any help ?! thanx in advance
I went ahead and cleaned up your function a bit, reduced the logic, now you should just make sure the moment format is what your looking for
function validate(val) {
let parsedTime = moment(val, "hh:mm");
if (parsedTime.isValid()) {
this.startTime = parsedTime.format('hh:mm A');
}
}
What I want should be very simple I think, but I end up with too complex situations if I search here, or on Google.
<script language="javascript">
// putten tellen
$(document).ready(function () {
$("input[type='number']").keyup(function () {
$.fn.myFunction();
});
$.fn.myFunction = function () {
var minute_value = $("#minute").val();
var second_value = $("#second").val();
if ((minute_value != '')) {
var productiesec_value = (1 / (parseInt(minute_value) * 60 + parseInt(second_value)));
var productiemin_value = productiesec_value * 60;
var productieuur_value = productiesec_value * 3600;
var productiedag_value = productiesec_value * 86400;
var productieweek_value = productiesec_value * 604800;
var productiemaand_value = productiesec_value * 2629700;
var productiejaar_value = productiesec_value * 31556952;
productiesec_value = (productiesec_value).toFixed(5);
productiemin_value = (productiemin_value).toFixed(2);
productieuur_value = (productieuur_value).toFixed(2);
productiedag_value = (productiedag_value).toFixed(0);
productieweek_value = (productieweek_value).toFixed(0);
productiemaand_value = (productiemaand_value).toFixed(0);
productiejaar_value = (productiejaar_value).toFixed(0);
$("#productiesec").val(productiesec_value.toString());
$("#productiemin").val(productiemin_value.toString());
$("#productieuur").val(productieuur_value.toString());
$("#productiedag").val(productiedag_value.toString());
$("#productieweek").val(productieweek_value.toString());
$("#productiemaand").val(productiemaand_value.toString());
$("#productiejaar").val(productiejaar_value.toString());
}
};
});
</script>
The thing I'd like to accomplish is:
Calculate the production time of a gem in multi-types of time (seconds, minutes, hours etc.) - (Done)
Calculate the production of gems by multiple pits.
Preview: http://hielke.net/projecten/productie/edelsteenput.htm
The idea is that you fill in the minutes in the first field and the seconds in the second field. Then the script should count the production in seconds, minutes, hours etc. on the right side.
After that it must be possible to fill in the second row of minutes and seconds and then counts the total production time. The same for the rest of the rows.
Welcome to SO!
A caveat about your setup: whenever possible, avoid having elements share IDs on your page. IDs are generally for elements which only occur once on your page; otherwise use a class. This practice is why document.getElementById() returns a single element, while document.getElementsByClassName() returns an array, which makes the answer to your question as easy as getting that array's .length.
This being said -- counting the number of elements with the same ID in Javascript is generally considered invalid, as getElementById() will only return one element, and (as far as I know) there isn't a way to iterate over instances of the same ID on a page.
Try changing those IDs to class names if you can, the run a document.getElementsByClassName().length on them to get the count.
I'm trying to make a countdown timer in JS that will change the value of a field every one minute (in the begining there is 20, and then change it to 19,18,17 etc), but it's not working correctly. It's changing value not every 60sec but I have a feel that it works random (sometimes it change value first time after 15 sec, another time it's 53). Any idea what I'm doing wrong? Here is the code:
function getTimeNow(){
var Time = new Date;
return Time.getHours()*60*60+Time.getMinutes()*60 + Time.getSeconds();
}
var start = getTimeNow();
var start_point = start%60;
var target = start+60*20;
function TimeOut(){
if((getTimeNow()-start)%60 == start_point && target>getTimeNow()){
var temp = jQuery('.Timer').html();
temp-=1;
jQuery('.Timer').html(temp);
}
setTimeout(TimeOut,1000);
}
You cannot count on the exact moment a timer function will be called. You need to change your logic to something more resilient to time shifts...
setInterval(function(){count.innerText = count.innerText - 1;},
60*1000);
this is also a lot shorter...
I'm looking for a way to manipulate animation without using libraries
and as usual I make a setTimeout in another setTimout in order to smooth the UI
but I want to make a more accurate function to do it, so if I want to make a 50ms-per-piece
animation, and I type:
............
sum=0,
copy=(new Date()).getMilliseconds()
function change(){
var curTime=(new Date()).getMilliseconds(),
diff=(1000+(curTime-copy))%1000 //caculate the time between each setTimeout
console.log("diff time spam: ",diff)
sum+=diff
copy=curTime
var cur=parseInt(p.style.width)
if (sum<47){//ignore small error
//if time sum is less than 47,since we want a 50ms-per animation
// we wait to count the sum to more than the number
console.log("still wating: ",sum)
}
else{
//here the sum is bigger what we want,so make the UI change
console.log("------------runing: ",sum)
sum=0 //reset the sum to caculate the next diff
if(cur < 100)
{
p.style.width=++cur+"px"
}
else{
clearInterval(temp)
}
}
}
var temp=setInterval(change,10)
I don't know the core thought of my code is right,anyone get some ideas about how to make a more accurate timer in most browser?
Set the JsFiddle url:
http://jsfiddle.net/lanston/Vzdau/1/
Looks too complicated to me, use setInterval and one start date, like:
var start = +new Date();
var frame = -1;
var timer = setInterval(checkIfNewFrame, 20);
function checkIfNewFrame () {
var diff = +new Date() - start;
var f = Math.floor(diff / 50);
if (f > frame) {
// use one of these, depending on whether skip or animate lost frames
++frame; // in case you do not skip
frame = f; // in case you do skip
moveAnimation();
}
}
function moveAnimation () {
... do whatever you want, there is new frame, clear timer past last one
}