Slowly change a value with javascript - javascript

I'm making a prototype of an interface for boats. Details aside, I have created a numpad using javascript onClick that lets you input a value and then send that value to another field, let's call it "current". Is there a way to make the "current" field I'm sending to slowly increase until it reaches the value i send from my numpad?
For example, if I enter the number 24 on my numpad and click "submit", the "current" field shows 24 right away, but I would like for it to slowly tick up to 24 in increments. This might sound like a silly detail but it would make quite a difference for my prototype.
Thanks in advance!

You can use javascript's setInterval function:
var handle;
function func() {
// Increment the value by 1
if(necessary value is reached) {
window.clearInterval(handle);
}
}
handle = window.setInterval("func", 50); // Run each 50ms

Related

How to prevent keyup function from lagging when the user types

I am trying to create a search function in jQuery:
$('input').on('keyup', function(){
var searchTerm = $("input").val().toLowerCase();
$('.item').each(function(){
if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1) {
$(this).parent().show();
} else {
$(this).parent().hide();
}
});
});
Each time the user types in the input, it gets compared to the data attribute value of .item divs. If the data attribute of that element contains the search query, it gets displayed - otherwise hidden.
This works perfectly in Chrome, however it is really laggy in Safari for some reason when the user is typing.
Is there a way to fix this?
There are about 1400 divs (.item), and the data-text attribute is only around 10-20 characters for each element
Edit, fixed by removing .show() and .hide() - and replacing with native Javascript
Solution
I have face similar issue before, I think you might want to try adding something called "debounce", which basically add a delay before doing any process. In the keyup case, it will wait for the user to stop typing for any set amount of time (let's say 0.5 second) and then do the process (searches or whatever) If you don't use debounce, it will do the search every single time the user trigger the keyup event.
You can search for articles on how to do debounce, I think there's a lot of them. But in essence it uses the setTimeout and clearTimeout function of JS
Here's from the first article I found: https://levelup.gitconnected.com/debounce-in-javascript-improve-your-applications-performance-5b01855e086
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
How to use this function? simple, just add your actual function (the search function) as the first parameter, and the delay (microseconds) in the second parameter, and then use the .call() function (why do this? because the debounce will return a function). So I guess something like this:
$('input').on('keyup', function(){
var searchTerm = $("input").val().toLowerCase();
debounce(function(){
$('.item').each(function(){
if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1) {
$(this).parent().show();
} else {
$(this).parent().hide();
}
});
}, 500).call();
});
This is how I will do it, because then I can add some stuff outside of the debounce into the keyup event, but you can just put the debounce returned function into a variable and then bind it with the keyup (like in the article), or just straight up put the debounce inside the keyup, like this:
$('input').on('keyup', debounce(function(){
...
},500));
How does it works?
You can read them in the articles, or find answer in StackOverflow, here's what I got Can someone explain the "debounce" function in Javascript
But if I'm using my own words, basically what you first need to understand is setTimeout set a timer before a function is called, and clearTimeout cancel that timer. Now in the debounce you can see that there's a clearTimeout before any setTimeout. So every time the keyup event is triggered it will basically cancel the last timeout set (if any), and then it will set a new timeout. In essence, it will reset the timer to what you set every time the event is triggered.
So for example:
The user want to search "abc"
They type "a" -> the debounce set a timer of 500ms before calling the
actual search of "a"
Before the 500ms is up, the user type "b", so the debounce cancel that "a" search, and search for "ab" instead, while also setting a timer of 500ms before doing it
Before the 500ms is up, the user type "c", so cancel the "ab" search, add a timer of 500ms to search for "abc"
The user stop typing until 500ms is up, now the debounce actually call the search for "abc"
What this results to? The heavy processing for the search is only done once for "abc", you can also put a loader or something to this heavy processing so it looks better for the user
Some quick fixes:
Collate the divs then show/hide in a single statement after the each rather than per iteration.
Changing the DOM is relatively expensive, so doing so in a single statement can greatly increase performance
If this is a table change to divs
Tables need to re-render the whole table on small changes. Fixed cell sizes can help. Not the case in this question, just a general improvement
Use an in-memory filter rather than read the DOM for each item.
Reading the DOM is much slower than in-memory (though in-memory uses more memory of course). For example, filter on .data() rather than [data-] as it will use in-memory. It's possible that this is quick in Chrome as Chrome may be caching the [data- attributes, so may not have an improvement in Chrome
debounce the input event so it only occurs when user has finished typing
Wait until the user has "finished" typing then run the action.
use operator associativity to your advantage
Although an edge case, this line
if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1)
will run the $(this).filter even when searchTerm.length < 1, change to
if (searchTerm.length < 1 || $(this).filter('[data-text *= ' + searchTerm + ']').length > 0)
Example showing this in action
function a() { console.log("a"); return true; }
function b() { console.log("b"); return true; } // b() doesn't need to exist
if (a() || b()) console.log("c")
consider server-side paging / filtering
substantially reduces the "footprint" on the page, so will be much quicker/more responsive, but with a potentially slightly longer delay retrieving the data. Depending on how it's displayed, 1400 records may be a lot for the user to view in one go (hence your filtering).

setTimeout inside for loop with random values

Problem is that setTimeout function within for loop is not getting the correct values despite the fact they were passed correctly. Second problem is that the sleep variable is not working, it simply ignores it. Other variables like i are acting strange, they are not going though the loop, they are going in a random order.
Inside function set_delay
console.log(i);
// 3,5,0,2,4,1 should be 0,1,2,3,4,5
console.log(sleep);
// 6000,6000,7000,9000,9000,10000, those ones are displayied in ASC order but shuold be randomly
console.log(share_screen_rate[i]);
//4,1,6,10,6,2,8 - this is not ok it's random
console.log(top);
// 749.5,2998,299.8,499.667,149,374.75 => this should be in order from smallest (149) to biggest (2998)
setTimeout(function() {
}, sleep);
if I change sleep to a numeric value like 2000 it is respected only for first iteration after nothing, it just goes at 0ms.
FULL CODE
https://jsfiddle.net/ojpv2nxu/
EXPECTED OUTPUT
This should be a simple script to scroll down the page and make pause based on the sleep variable and also read the page chunk by chunk based on the share_screen_rate variable
I think it is a logic issue.... You are expecting the setTimeout to happen x seconds after the last one. But they are firing x seconds after you set it. So it is working as expected.
If you want them to fire x seconds after the last, than you need to change the logic to keep track of the seconds and adjust the timers.
so top of the file add
var timeTrack = 0
and than you need to add to that value
timeTrack += sleep
setTimeout(function() {
}, timeTrack);

Building A Timer in Javascript/jQuery

I'm currently working on a website which would work somewhat like this one:
http://www.keyhero.com/free-typing-test/
I'd like to build a timer which starts on the user's first key press, and ends when the user presses 'Enter'. When the timer ends, I'd want to get the resulting time and push it off to the backend (Django for me) where the WPM will be calculated. However, I have no idea how to get started on this, as I have little experience with jQuery and Javascript and haven't been able to find useful pages.
So my question is, how would I do this? I can post some of my Django files if a better picture of what I am asking is needed.
You manage the key events with .keypress() for know when the person click in the keyboard.
http://api.jquery.com/keypress/
And for key = "ENTER", you just need to validate if is equal to key 13
$('#id_tag').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
alert("Clicked on enter");
return false;
}
});
I see that post too, that are using keyup():
JQuery Event for user pressing enter in a textbox?
Well you're going to have to capture the keypress/keydown/keyup event in a jQuery event, then start a setInterval and have that function increment a counter variable of sorts. Then you just reference that variable whenever you want to see how many seconds have passed. A crude example would be:
window.secondsSinceTyped = 0;
$('#textbox').one('keypress', function (e) {
window.setInterval(function () {
window.secondsSinceTyped++;
}, 1000);
});
Then just reference the variable secondsSinceTyped whenever you want to check the time. Note that I used the jquery one binding which will only bind the event once so that every time you type it doesn't rebind the event.

Multiple javascript timeouts - problem with live data fetching

I am building a real-time system which (with a use of websockets) updates a table with live data of different frequencies (can be 3 times per second, can be once every 2 seconds - dependant on the type of data).
I am currently struggling to find a way of letting the user know when a particular field has not been updated in the last 5 seconds. That is, if no new data is fetched, I shouldn't keep the old value there, but rather change it to '--' or something similar.
After a long way to the javascript, final function which updates fields looks like that (extremely simplified):
function changeValue(data){
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
}
This function gets called each time a field needs to be changed. I've got between 2 and 40 different fields (dependant on the user) that are changed.
What is the best way of setting timers in order to change the values of the fields to '--' every 5 seconds, if no update has been made?
I would be really grateful for some tips,
Thanks,
Karol.
Since you want to indicate timeout on a per-field basis, you have two obvious options:
Have a global interval timer that ticks over fairly frequently and looks through all of your fields for a timeout.
Have independent timers for each field which just deal with that field.
I think on balance I prefer (1) to (2), because we're only dealing with one interval timer then and it makes the housekeeping simpler.
Since IDs in documents must be unique, we can use your field ID values as a key in a hash (an object) to store last updated times. This is kind of a spin on the previous answer but works on a per-field basis. So here's how we'd set those last updated times:
var lastUpdatedTimes = {};
function changeValue(data){
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
lastUpdatedTimes[fieldId] = new Date().getTime();
}
Then you set up an interval timer to check each of them.
function checkFieldsForTimeout(){
var now = new Date.getTime();
// For each ID in lastUpdatedTimes, see if 'now minus
// last updated' is > 5000 and is so, set the field
// text to '--' and remove that entry from the last
// updated list with "delete lastUpdatedTimes[itemId]".
}
Should a timed-out field spring back to life, the "--" will be replaced by some real text again.
By deleting the last updated time from "lastUpdatedTimes" whenever we put "--" into a field, we make sure that the interval timer isn't wasting time processing fields that have already been timed out.
This answer was extended to handling multiple fields after the comment by #Andrew (please see also his answer).
Introduce a property updatedTime, which holds the last time the data was updated, in each data. A periodic timer checks updatedTime for all data and updates the text field if appropriate. The check has to be twice as often as the detection period. Your function changeValue() updates updatedTime and the text field.
function checkData() {
var now = new Date.getTime();
for "each data" {
if (now - data.updatedTime >= 5000) {
var fieldId = data.fieldId;
$('span#'+fieldId).text('--');
}
}
}
function changeValue(data) {
var fieldId = data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
data.updatedTime = new Date.getTime();
}
// Install periodic timer to check last updates:
setInterval(checkData, 5000 / 2); // interval = half the required detection period

Javascript time helper? -Interesting problem!

I am new to the world of javascript and even trying google search has not really helped me find what I am looking for.
So I have come here in the hope you can point me in the right direction.
RULE= It must not be click! Can be done by tabbing!
I have many text fields which the user will input times that have been recorded.
E.g. Event 1 happened at 11:31am
Event 2 happened at 11:59am
I want to make this process as easy as possible for the user by having the textbox formatted in hours and seconds in 24hr format:
So the textbox value= 00:00 and when the user selects the text box they can enter the hours part. Then it will jump to the seconds part.
Any idea if there is something that can do that if so could you link me. If not could you give me an idea of what the coding will be like and if there are easier alternatives.
I have made some pseudo code to help you understand my implementation goal:
for count = 0 , while count is less than 20, count++
{
create a texbox with name time+count, set the value to ="00:00"
}
when the user enters numbers they go into the hour segment until that is completed
the script then jumps the cursor to the minutes segment
if time+count+1 is lesser thatn time+count message user that time error "An event cannot occur before the previous event"
Thankyou for hearing me out!
I don't really know of any time pickers that would suit your needs, but here's a basic idea of how one would be implemented:
You have two textboxes, or multiple pairs of textboxes
In each textbox, you put an event handler to handle "onkeyup" event
In onkeyup handler, check if lenght of text in box is 2
If length is 2 -> focus the next textbox
This way the user can simply keep on typing the numbers.
You may need to add some additional checks into the event listener, for example to make sure that if the user comes back to the field, they can edit it easily (eg. if they press shift-tab, it won't focus an incorrect field)
If you wanted to be really fancy, you could have a single textbox for times. Then, each time user presses a key, you'd check if it's a number. If user first types two numbers, it would then insert a : as the separator if the third key is a number, and so on.
This might be a beginning. Using jQuery this is not such a painful task.
http://jsfiddle.net/sArjQ/
for(var i = 0; i < 20; i++) {
var input = $("<input>", { name: 'time' + i, // create input element
val: '00:00' });
input.click(function() {
$(this).prop({ selectionStart: 0, // move caret to beginning on click
selectionEnd: 0 });
}).keydown(function() {
var sel = $(this).prop('selectionStart'),
val = $(this).val(),
newsel = sel === 2 ? 3 : sel; // so that it moves two positions for :
$(this).val(val.substring(0, newsel) // automatically set value
+ val.substring(newsel + 1))
.prop({ selectionStart: newsel, // move caret along
selectionEnd: newsel });
});
$('body').append(input);
}

Categories

Resources