stop previous event when next one on the same is fired - javascript

searchBox.live('input', function(){
//search in a json object
//update the dom based mathes
});
How do i stop the previous search when a new input is entered in the searchbox

I guess your goal is to search only after user finished typing, right? In such case delay the actual execution of the search in this manner:
var searchTimer = 0;
searchBox.live('input', function(){
window.clearTimeout(searchTimer);
searchTimer = window.setTimeout(function() {
//search in a json object
//update the dom based mathes
}, 500);
});
This will trigger the search half a second after user entered input and cancel all previous calls.

You could try looking at underscores debounce function. You pass it the function and a wait millisecond value and it returns a "debounced" version of the function that queues up incoming function calls and executes the last one in the queue after wait ms.

Related

Javascript prompt alternative in Loop

So, instead of a prompt, I could use an <input type="text"> and a button to do stuff with the values of the input on button click, for example:
var x = [];
$('button').on('click', function(){
x.push($(input[type="text"]).val());
});
However, in a loop for example:
var y=0;
var z=[];
do {
z.push(prompt('input value'));
y++;
}
while (y<5);
The loop would prompt for a value, user inputs value, prompt assigns value to array, then the loop would prompt again until y reaches 5.
Instead of a prompt, I'd like to do this with my text field input and button. How can I get the loop to pause, wait for user to input text, and submit by clicking button, every time it reaches that part of the loop?
Edit: The pushing of 5 values into the array was just an example. Let's say I wanted to create a game where the loop would move up with an "up" and down with a "down" input. I want to be able to request user input during the loop, similar to how the prompt would do it, but without using prompts.
You don't. You completely change your logic, losing the loop entirely:
var z = [];
$('button').on('click', function() {
z.push($(input[type="text"]).val());
if (z.length === 5) {
// Do what you would have done after the end of the loop here
}
});
You've edited the question and commented below that what you do next might vary depending on the input. That's not a problem, you just apply the event-response model to your new requirement. For instance, you said
...Let's say I wanted to create a game where the loop would move up with an "up" and down with a "down" input.
Then:
$('button').on('click', function() {
switch ($(input[type="text"]).val().toLowerCase()) {
case "up":
// Do the "up" thing
break;
case "down":
// Do the "down" thing
break;
}
});
There are several different ways you might handle dispatching, not necessarily a switch. For instance:
var actions = {
up: function() {
// Do the "up" thing
},
down: function() {
// Do the "down" thing
}
};
$('button').on('click', function() {
var action = actions[$(input[type="text"]).val().toLowerCase();
if (action) {
action();
}
});
And so on. The key is that instead of working iteratively (I do this, I get that input, I do the next thing, I get more input), you're working reactively: I get input, I do something. That might require some kind of state management (remembering where you are) beyond what's shown above (the first example has state management: We check the length of z to see how many inputs we've collected).

How to wait 2 seconds for input in Javascript

I im programming tv remote control using javascript and need when user press number 1 function waits 2 seconds if user press one more time 1 (1 channel or 11 channel or 111channel).
i write this function but it gets on display only 11111111 in loop here is my code:
function chChannel(pressed) {
setInterval(function () {
if (lengthCS < 3) {
inputChannel += pressed;
lengthCS = inputChannel.length;
}
}, 2000);
// call function to change channel using variable value inputChannel for ex. 011
};
Any solution please?
So function need to wait 2seconds and then after 2seconds it gets value of pressed numbers in variable InputChannel so that i can then call function to change channel to number from Value InputChannel.
Listening to keypresses and counting them is one well documented thing, but, in context with the actual topic, I would say, there is no correct Waiting method, other than to end the script with a timeout call being set to a function that repeatedly checks, whether the Time to wait has passed by, if not then selftrigger with setTimeout in eg. 100ms, if yes then call a function that continues the main program.
The Waiting thread may then also check and count keypresses, eg. in global variables as a basic solution.
use "setTimeout".
var Timer;
function chChannel(pressed) {
clearTimeout(Timer);
Timer = setTimeout(function () {
if (lengthCS < 3) {
inputChannel += pressed;
lengthCS = inputChannel.length;
}
}, 2000);
// call function to change channel using variable value inputChannel for ex. 011
};
Have you considered using something like underscore's debounce function, would make things a lot simpler all round.
http://underscorejs.org/#debounce
May be something like this might work, on phone can't test it myself...
var inputChannel;
function chChannel(pressed) {
if (inputChannel <= 3) {
inputChannel += pressed;
}
else {
inputChannel = pressed;
}
_.debounce(someFunction, 2000);
};
As long as debounce keeps getting called within the delay it will not execute, and only execute once after the delay.

Create a time interval that will cause a function to run at a random time in JavaScript

I am trying to load a random image at a random time. For some reason this is not randomizing the time, though it does randomize the image. Any ideas what's wrong?
var randomTime2 = 3000; //initialize the random time with this value to start
setInterval(function(){
var randomNum = Math.floor((Math.random()*3)+1);//random num for image
$('.recent-project2 img').fadeTo('slow',0,function(){
var randomImg = "img/recent-projects-"+randomNum+".jpg";
$('.recent-project2 img').attr('src',randomImg);
$('.recent-project2 img').fadeTo('slow',1);
});
randomTime2 = Math.floor(Math.random()*10000);//reset random time
return randomTime2; //return random time
},randomTime2);
Use setTimeout and re-trigger at the end of the function with a random time.
The setInterval call will just add your function and the required interval to an internal table to remember to call your code when the expected delay period passed. Note however that even if you change the variable used to specify the interval this will have no effect on the internal table: that value has been read when you called setInterval and it's now stored.
To randomize the callback time give your function a name and just use setTimeout instead of setInterval:
function MyCallback() {
...
setTimeout(myCallback, new_delay);
}
setTimeout(myCallback, first_delay);
with this approach at each call you can decide a different delay before next call.
You can't change the value of randomTime2 inside the function as it's pass by value, not reference.
setInterval(someFunction, someNumberValue)
This line of code will call someFunction every someNumberValue-miliseconds. The value is not updated dynamically.
There's lots of ways you could make this work, but I suggest simply using setTimeout and making the end of someFunction call it again. For instance:
//psudo-code, might not actually run, just showing you the general idea.
var someFunction = function(){
console.log("Whatever.");
}
var repeatFunction = function(){
someFunction()
var timeoutID = window.setTimeout(repeatFunction, Math.random()*10000);
}
repeatFunction(); //Starts the loop.

How to count active javascript timeouts?

I am using Selenium to test a web app that uses Dojo, and it uses java script to display certain elements. I want to wait until all of the elements are desplayed before I try to manipulate the page, however I am having trouble.
I have started by waiting for the dojo inFlight variable to be 0, this says that all ajax has finished. This doesn't always work because it seems to do some things on a timeout afterwards.
I have also tried repeatedly looking for the element, but this isn't too nice, as perhaps there is some javascript later which will use this field in some way.
So basically I want a method (in firefox at least) to query the javascript waiting to run on a setTimeout (or setInterval) I could even cope with a way of wrapping the built in call through a function of my own just to keep track of this.
Any thoughts or suggestions appreciated!
Every function in JavaScript can be replaced. Consider something like this:
window.originalSetTimeout = window.setTimeout;
window.setTimeout = function(func, delay, params) {
window.timeoutCounter++;
window.originalSetTimeout(window.timeoutCallback, delay, [func, params]);
}
window.timeoutCallback = function(funcAndParams) {
window.timeoutCounter--;
func = funcAndParams[0];
params = funcAndParams[1];
func(params);
}
Then:
selenium.waitForCondition("window.timeoutCounter == 0");
Whenever you call setTimeout of setInterval -- a timer id is returned.
Save that timer id in an array
Inside the function that you're calling on the timeout, pop that timer id off the array. Because we have to remove that id from the array as soon as the timer ends.
Any time you want to check the no. of active timers, just query the length of that array.
Another approach could be like this
const timeoutIndexThen = setTimeout(() => {});
// Some code that might call timeouts...
const timeoutIndexNow = setTimeout(() => {});
const countOfTimeoutsFiredSinceThen = timeoutIndexNow - timeoutIndexThen - 1;
It is based on the fact that each timeout will return a number that is greater by 1 on each call.
So we create some dummy timeout just to get this number at some point.
Then, after a while we call it again and we get a new number. Difference between those numbers is how many times interval was called in between.
Downside of this is that you have to actually create the timeout. Upside is that you don't have to modify original function.

ExtJS listening for global keystrokes with Ext.KeyMap

To polish up an application im developing I am adding keyboard shortcuts for common tasks. I can sue Ext.KeyMap to do this like so...
var map = new Ext.KeyMap("my-element", {
key: 13, // or Ext.EventObject.ENTER
fn: myHandler,
scope: myObject
});
But I want to detect "ss" or "qq" i.e. specific double key strokes of letters. Im not sure how to do this....
My idea is to detect the singular keystroke, add a listener to detect a following key stroke. And to handle the gap between them, set a delayed event that deletes the listener after x amount of time.
Any improvements/suggestions/warnings??
I'm not sure why you would need an additional listener here. Why not store the previous keystroke in a variable (with the timestamp when the keystroke occurred). Then you could just compare the latest keystroke to the previous keystroke. If they are the same, and the timestamp stored is not too far in the past, that's the double key you're after. If the key codes are not the same, or stored timestamp is too old, just update the stored keycode and timestamp with new values.
You don't have to remember all the keys pressed, just the last one. When you think at the double click event, it's similar, but since clicking two times is more popular, it's already implemented for us.
Something like this:
function defineDoubleKeyMap(element, cfg) {
var repeated, timer;
return new Ext.KeyMap(element, {
key: cfg.key,
fn: function() {
if (repeated) {
// when clicked the second time
// stop timer and call our callback
repeated = false;
clearTimeout(timer);
cfg.fn.call(cfg.scope);
}
else {
// remember we clicked once, forget after delay
repeated = true;
// adjust the delay as needed.
// current 1 sec is probably too long
timer = (function(){
repeated = false;
}).defer(1000);
}
}
});
}
defineDoubleKeyMap("my-element", {
key: Ext.EventObject.ENTER,
fn: myHandle,
scope: myObject
});
The probem with this code is that pressing quickly ENTER-DELETE-ENTER will also fire the event as if ENTER-ENTER was pressed. If that's not acceptable, then you have to keep track of all the keypresses - I think you'll have to use Ext.get("my-element").on("keypress") for that.

Categories