I am writing a chatbot application and wanted to catch multiple user inputs by blurring out of the input field and focussing back in after 3 seconds (when the bot responded).
I used setTimeout for this and it works the first time but it seems to get shorter after calling the function multiple times.
The code I used is in a React chat widget and looks like this:
handleKeyPress = (e: KeyboardEvent) => {
if (e.keyCode === 13 && this.input.value.replace(/\s/g, "")) {
this.input.blur();
this.say(this.input.value);
// Reset input value
this.input.value = "";
this.refocus(document.getElementById('userText'));
}
};
refocus = (element: HTMLElement) => {
var time = setTimeout(function() {
element.focus();
}, 3000);
};
In this code I use a setTimeout after sending the message to the backend bot application so that the bot has some time to answer.
I can't figure out why this is not working and could really use some suggestions...
I found a fix for my issue. It appears that the problem had something to do with the focus() / blur() methods. I used a disable = true and disable = false and focus() after the 3 second delay and now the delay is always 3 seconds.
Code now looks like this:
handleKeyPress = (e: KeyboardEvent) => {
if (e.keyCode === 13 && this.input.value.replace(/\s/g, "")) {
this.input.disabled = true;
this.say(this.input.value);
// Reset input value
this.input.value = "";
this.enable((document.getElementById('userText') as HTMLInputElement));
}
};
enable = (element: HTMLInputElement) => {
setTimeout(function() {
element.disabled = false;
element.focus();
}, 3000);
};
Related
document.addEventListener('keydown', (event) => {
var name = event.key;
var code = event.code;
if (name === 'Control') {
location.replace(classroom.google.com)
}
if (event.ctrlKey) {
alert(`Combination of ctrlKey + ${name} \n Key code Value: ${code}`);
} else {
alert(`Key pressed ${name} \n Key code Value: ${code}`);
}
}, false);
// Add event listener on keyup
document.addEventListener('keyup', (event) => {
var name = event.key;
if (name === 'Control') {
location.replace(classroom.google.com)
}
}, false);
How currently when I press the control key, nothing happens. If I make it run an alert instead, then the alert will successfully run. Do I need to use the window.location function instead?
The issue with your code is that you aren't passing a string to location.replace().
Right now, your code looks like this.
location.replace(classroom.google.com);
The issue with this code is that you are not surrounding it with quotes to make it a string, so JavaScript thinks that you are referencing a property of an object, of an object.
Below is what JavaScript thinks is happening.
const classroom = {
google: {
com: undefined,
}
};
console.log(classroom.google.com); // undefined
To fix it, simply surround your parameter in quotes, as so.
location.replace("classroom.google.com");
This should successfully redirect you to classroom.google.com!
I have in NodeJS a variable that updates every second. I want to monitor it to see if it turns below a certain threshold (e.g. 1000).
If it does go below the threshold, it should wait 5 seconds and monitor if the variable goes back above again. If not, it should return a function. If it does go above, it can stop the times and start monitoring again.
Can't get any code to work.
Not sure if the code below is even in the right direction..!
var waitedSoFar = 0;
var imageDisplayed = CheckIfImageIsDisplayed(); //this function is where you check the condition
while(waitedSoFar < 5000)
{
imageDisplayed = CheckIfImageIsDisplayed();
if(imageDisplayed)
{
//success here
break;
}
waitedSoFar += 100;
Thread.Sleep(100);
}
if(!imageDisplayed)
{
//failed, do something here about that.
}
You could have a function that observe and wrap this variable that change so often. Something as simple as
function observeValue(initialValue) {
let value = initialValue
let clearEffects = []
let subscribers = []
return {
value: () => value,
change(val) {
clearEffects.forEach(oldEffect => oldEffect && oldEffect())
value = val
clearEffects = subscribers.map(subscriber => subscriber(value))
},
subscribe(listener) {
subscribers.push(listener)
}
}
}
is generic enough. The function returns three methods:
one to get the current value
one to change the value
on to subscribe on every value change
I would suggest to leverage the last one to monitor and trigger any side effects.
You can use it like this:
const monitor = observeValue(true)
monitor.subscribe((value) => {
if (value !== false) {
return
}
const timeout = setTimeout(() => {
console.log('value was false for five seconds')
}, 5000)
return () => {
clearTimeout(timeout)
}
})
and somewhere else you can change the value with
monitor.change(false)
I am using the following code jsFiddle:
function Field(args) {
this.id = args.id;
this.name = args.name ? args.name : null;
this.reqType = args.reqType ? args.reqType : null;
this.reqUrl = args.reqUrl ? args.reqUrl : null;
this.required = args.required ? true : false;
this.error = args.error ? args.error : null;
this.elem = document.getElementById(this.id);
this.value = this.elem.value;
this.elem.addEventListener('blur', this, false);
this.elem.addEventListener('focus', this, false);
}
// FormTitle is the specific field like a text field. There could be many of them.
function FormTitle(args) {
Field.call(this, args);
}
Field.prototype.getValue = function() { return Helpers.trim( this.value ) };
Field.prototype.blur = function (value) {
alert("blur");
};
Field.prototype.focus = function (value) {
alert("focus");
};
Field.prototype.handleEvent = function(event) {
var prop = event.type;
if ((prop in this) && typeof this[prop] == "function")
this[prop](this.value);
};
inheritPrototype(FormTitle, Field);
var title = new FormTitle({name: "sa", id: "title"});
function inheritPrototype(e, t) {
var n = Object.create(t.prototype);
n.constructor = e;
e.prototype = n
}
if (!Object.create) {
Object.create = function (e) {
function t() {}
if (arguments.length > 1) {
throw new Error("Object.create implementation only accepts the first parameter.")
}
t.prototype = e;
return new t
}
}
The problem is that the 'blur' event is fired every time the field is brought to focus, which is opposite of what you'd expect. This is despite the fact that the focus event isn't even mentioned in the code. The problem is that I cannot replicate this problem in jsFiddle but the problem is happening in IE.
Also, on jsFiddle, there is another problem. The focus event is triggered multiple times...
Is there a possible explanation for this and/or a solution?
Updated:
Bonus question (and last on this, promise).
I added a function addEvent to dynamically add events to form fields instead of adding them all directly in the parent constructor. This is the jsFiddle for it. I am trying to call the function but it doesn't seem to work. What might I be doing wrong?
The alert in your focus handler immediately removes focus away from the field as soon as it gains focus. The loss of focus triggers the blur. It is odd that the blur comes first.
If you change the alerts to console.log (or something that does not steal focus), you will see that the events fire correctly.
http://jsfiddle.net/rsKQq/4/
I have a requirement to show real time update of the number of people who did some action.
I implemented this functionality by making an ajax request to the server every 20 seconds.
But this ajax request happens even if the tab is not in focus/no one is looking at the update. Is there a way to figure out if the tab is active?
I have the following code(simplified version) and it doesn't work.
timer = undefined
$(document).ready ->
timedCountUpdate()
window.top.onblur = ->
clearTimeout(timer)
window.top.onfocus = ->
timer = timedCountUpdate()
#timedCountUpdate = () ->
timer = setTimeout(updateCountIndicator, 20000)
#updateCountIndicator = () ->
$('.indicator').html = 100
timedCountUpdate()
I still see the call being made every 20s even if i am not in the tab that has the app loaded. I am testing in chrome.
In Coffeescript w/ jquery:
$ ->
timeout_id = null
resumeTimer = () ->
# make ajax call here
# Prevent multiple timers from operating simultaneously:
clearTimeout timeout_id if timeout_id?
# Recursive step (ideally fires in 'success' handler of ajax call)
timeout_id = setTimeout(resumeTimer, 2000)
$(window.top).focus () =>
resumeTimer()
$(window.top).blur () =>
clearTimeout timeout_id
# Start timer immediately:
resumeTimer()
I know this is an old question, but I stumbled upon it in a Google search and wanted to provide another alternative that's better suited for what you're wanting to do.
The Page Visibility API is how these types of things should be done moving forward (or now IE10+). The API provides a visibilityChange event that triggers when the visibility of the tab changes. In the callback, checking the document.hidden property will tell you whether the tab is hidden or not.
From there, clear your interval or start it back up again.
In your case, i would do something like :
var tab_paused = false; // global
if (typeof window.top.onblur === 'function')
{
window.top.onblur = function() {
tab_paused = true;
};
}
if (typeof window.top.onfocus === 'function')
{
window.top.onfocus = function() {
tab_paused = false;
};
}
if (typeof document.onfocusout === 'function')
{
document.onfocusin = function() {
tab_paused = true;
};
}
if (typeof document.onfocusin === 'function')
{
document.onfocusin = function() {
tab_paused = false;
};
}
var ctx = setInterval(function() {
if (tab_paused === false)
{
$('.indicator').html(100);
}
}, 100);
I would like to be able to trap the double key press (for the Char T for example) in order to do some special processing.I would like the key presses to happen fast enough to not be interpreted as two separate presses, just like the double click.
Any ideas how i can achieve this?
When the key(s) are hit, make a note of the time. Then compare it with the time you noted the last time they key(s) were hit.
If the difference is within your threshold, consider it a double. Otherwise, don't. Rough example:
var delta = 500;
var lastKeypressTime = 0;
function KeyHandler(event)
{
if ( String.fromCharCode(event.charCode).toUpperCase()) == 'T' )
{
var thisKeypressTime = new Date();
if ( thisKeypressTime - lastKeypressTime <= delta )
{
doDoubleKeypress();
// optional - if we'd rather not detect a triple-press
// as a second double-press, reset the timestamp
thisKeypressTime = 0;
}
lastKeypressTime = thisKeypressTime;
}
}
Have a variable (perhaps first_press) that you set to true when a keypress event happens, and start a timer that will reset the variable to false after a set amount of time (however fast you want them to press the keys).
In your keypress event, if that variable is true then you have a double press.
Example:
var first_press = false;
function key_press() {
if(first_press) {
// they have already clicked once, we have a double
do_double_press();
first_press = false;
} else {
// this is their first key press
first_press = true;
// if they don't click again in half a second, reset
window.setTimeout(function() { first_press = false; }, 500);
}
}
I know is too late to answer but here goes how I have implemented that:
let pressed;
let lastPressed;
let isDoublePress;
const handleDoublePresss = key => {
console.log(key.key, 'pressed two times');
}
const timeOut = () => setTimeout(() => isDoublePress = false, 500);
const keyPress = key => {
pressed = key.keyCode;
if (isDoublePress && pressed === lastPressed) {
isDoublePress = false;
handleDoublePresss(key);
} else {
isDoublePress = true;
timeOut();
}
lastPressed = pressed;
}
window.onkeyup = key => keyPress(key);