We are playing a clicker game on a website where a button will be displayed at a random time, first 7 players to click it will be shown as the winners of that round. I wrote the clicker function bellow and always use it on my Chrome console.
(function () {
setInterval(() => {
const button = document.querySelector(“.click-button);
if (!button) return;
button.click();
}, 5);
})();
I was playing it with mobile network of 50 - 70 mbps of speed and was among the top 5 until when other players started using VPS Machine which have over 4gbps of internet speed. I now have a VPS running Windows server 2022 but cant still perform better. So My question is, Is it that my VPS speed is slower than their own or My Laptop have less specification than their own or I need a better javascript code than the one above?
Running the above code on a VPS server with a download speed of 4.3gbps and upload speed of 4.1gbps through a browser console and click faster
Instead of polling for the button, you could use a MutationObserver that will notify you when the button changes or is inserted into the document. Unless you can get to the event that triggers the button activation, this is probably the fastest you can do.
Assuming that the button is inserted into a <div id="button-container"></div>:
const callback = mutations => {mutations.forEach(m => m.addedNodes.forEach(node => node.tagName === 'BUTTON' && node.click()))}
const observer = new MutationObserver(callback)
const container = document.getElementById('button-container')
observer.observe(container, {childList: true})
Have a look at this codepen
Replacing the forEach() with a for will give you a few additional nanoseconds.
Your code can be a little faster by caching the function and the button outside the interval
(function() {
const button = document.querySelector(".click-button");
const buttonClick = () => button.click();
if (button) setInterval(buttonClick, 5);
})();
If the button does not exist at all, then the code above will not work. Then you do need the mutation oberver
Related
I'm creating a chrome extension. I need to know when a user clicked on a specific button how many mili seconds will take long, to receive that command to website server. I have a web Worker that is connected to that website too. Could I get the exact time when a button clicked to when data received by website's server? It doesn't matter how many mili seconds take that the respond back to me, the time of receiving request to server after click is mu issue now. can someone help me please?
I'm looking for javascript code to get the time distance between button clicked and received that by website's server.
It is easy to get the time when button is clicked by finding that button and attaching an event handler on it, that calls performance.now()
const t0 = 0;
document.getElementById('buttonId').addEventListener('click',() => {
t0 = performance.now();
});
Detecting when the server response is received is not trivial. You might need to use the chrome.webRequest api.
Alternatively, a simpler way would be to look for side-effects of the request, that happen in the DOM. (A loader appearing and disappearing, data rows appearing, button being disabled and re-enabled, etc).
You can either poll for these changes, or use the mutationObserver api to detect when elements containing expected attributes are available in the DOM.
Let's say you are polling for the button being re-enabled, every 10ms:
const t1 = 0;
const interval = window.setInterval(() => {
if (!document.getElementById('buttonId').getAttribute('disabled')) {
t1 = performance.now();
requestTime = t1 - t0;
console.log(requestTime);
window.clearInterval(interval);
}
},10);
I was searching for a way how to communicate between multiple tabs or windows in a browser (on the same domain, not CORS).
I am using timer and it should working on all site pages. If there's a way to stop/pause/play timer on all pages (new windows) simultaneously ?
For example I have 2 tabs - page 1 and page 2... on both pages I have running the same timer. If I click pause timer on page 1 it must pause on page 2 too.
I can't find a solution all day long ... help please.
My timer code:
const Timer = easytimer.Timer;
const getSavedTime = () => JSON.parse(localStorage.getItem('time')) || {};
const instance = new Timer({ startValues: getSavedTime() });
instance.addEventListener('secondsUpdated', () => {
document.querySelector('.example').textContent = instance.getTimeValues().toString();
localStorage.setItem('time', JSON.stringify(instance.getTimeValues()));
});
instance.addEventListener('started', () => localStorage.setItem('running', '1'));
instance.addEventListener('paused', () => localStorage.removeItem('running'));
instance.addEventListener('stopped', () => {
localStorage.removeItem('time');
localStorage.removeItem('running');
document.querySelector('.saved').textContent = '';
document.querySelector('.example').textContent = '';
});
document.querySelector('.saved').textContent = localStorage.getItem('time');
document.querySelector('.example').textContent = instance.getTimeValues().toString();
document.querySelector('.start-button').addEventListener('click', () => instance.start({ startValues: getSavedTime() }));
document.querySelector('.pause-button').addEventListener('click', () => instance.pause());
document.querySelector('.stop-button').addEventListener('click', () => instance.stop());
if (localStorage.getItem('running') === '1') {
instance.start({ startValues: getSavedTime() });
}
listen event:
window.addEventListener('storage', function (e) {
console.log("storage event occured here");
},false);
You can use BroadcastChannel to communicate between different tabs within the same origin.
The harder part would be managing which tab gets to "run" the timer code and which tabs just "listen" to the events. Then, if the tab that was running the timer got closed, how would you coordinate deciding which other tab should take over that role.
A better option might be to put the timer code in a Web Worker (specifically a SharedWorker), and then just use BroadcastChannel (and/or maybe the port property of the SharedWorker) to send the events out to the tabs.
If you're lucky, you might be able to get your easytimer.Timer class to run within a Web Worker without any modifications - although you would still need to do some work to hook it up to the BroadcastChannel.
Safari on iOS puts a scrubber on its lock screen for simple HTMLAudioElements. For example:
const a = new Audio();
a.src = 'https://example.com/audio.m4a'
a.play();
JSFiddle: https://jsfiddle.net/0seckLfd/
The lock screen will allow me to choose a position in the currently playing audio file.
How can I disable the ability for the user to scrub the file on the lock screen? The metadata showing is fine, and being able to pause/play is also acceptable, but I'm also fine with disabling it all if I need to.
DISABLE Player on lock screen completely
if you want to completely remove the lock screen player you could do something like
const a = new Audio();
document.querySelector('button').addEventListener('click', (e) => {
a.src = 'http://sprott.physics.wisc.edu/wop/sounds/Bicycle%20Race-Full.m4a'
a.play();
});
document.addEventListener('visibilitychange', () => {
if (document.hidden) a.src = undefined
})
https://jsfiddle.net/5s8c9eL0/3/
that is stoping the player when changing tab or locking screen
(code to be cleaned improved depending on your needs)
From my understanding you can't block/hide the scrubbing commands unless you can tag the audio as a live stream. That being said, you can use js to refuse scrubbing server-side. Reference the answer here. Although that answer speaks of video, it also works with audio.
The lock screen / control center scrubber can also be avoided by using Web Audio API.
This is an example of preloading a sound and playing it, with commentary and error handling:
try {
// <audio> element is simpler for sound effects,
// but in iOS/iPad it shows up in the Control Center, as if it's music you'd want to play/pause/etc.
// Also, on subsequent plays, it only plays part of the sound.
// And Web Audio API is better for playing sound effects anyway because it can play a sound overlapping with itself, without maintaining a pool of <audio> elements.
window.audioContext = window.audioContext || new AudioContext(); // Interoperate with other things using Web Audio API, assuming they use the same global & pattern.
const audio_buffer_promise =
fetch("audio/sound.wav")
.then(response => response.arrayBuffer())
.then(array_buffer => audioContext.decodeAudioData(array_buffer))
var play_sound = async function () {
audioContext.resume(); // in case it was not allowed to start until a user interaction
// Note that this should be before waiting for the audio buffer,
// so that it works the first time (it would no longer be "within a user gesture")
// This only works if play_sound is called during a user gesture (at least once), otherwise audioContext.resume(); needs to be called externally.
const audio_buffer = await audio_buffer_promise; // Promises can be awaited any number of times. This waits for the fetch the first time, and is instant the next time.
// Note that if the fetch failed, it will not retry. One could instead rely on HTTP caching and just fetch() each time, but that would be a little less efficient as it would need to decode the audio file each time, so the best option might be custom caching with request error handling.
const source = audioContext.createBufferSource();
source.buffer = audio_buffer;
source.connect(audioContext.destination);
source.start();
};
} catch (error) {
console.log("AudioContext not supported", error);
play_sound = function() {
// no-op
// console.log("SFX disabled because AudioContext setup failed.");
};
}
I did a search, in search of a way to help you, but I did not find an effective way to disable the commands, however, I found a way to customize them, it may help you, follow the apple tutorial link
I think what's left to do now is wait, see if ios 13 will bring some option that will do what you want.
Safari on iOS puts a scrubber on its lock screen for simple HTMLAudioElements. For example:
const a = new Audio();
a.src = 'https://example.com/audio.m4a'
a.play();
JSFiddle: https://jsfiddle.net/0seckLfd/
The lock screen will allow me to choose a position in the currently playing audio file.
How can I disable the ability for the user to scrub the file on the lock screen? The metadata showing is fine, and being able to pause/play is also acceptable, but I'm also fine with disabling it all if I need to.
DISABLE Player on lock screen completely
if you want to completely remove the lock screen player you could do something like
const a = new Audio();
document.querySelector('button').addEventListener('click', (e) => {
a.src = 'http://sprott.physics.wisc.edu/wop/sounds/Bicycle%20Race-Full.m4a'
a.play();
});
document.addEventListener('visibilitychange', () => {
if (document.hidden) a.src = undefined
})
https://jsfiddle.net/5s8c9eL0/3/
that is stoping the player when changing tab or locking screen
(code to be cleaned improved depending on your needs)
From my understanding you can't block/hide the scrubbing commands unless you can tag the audio as a live stream. That being said, you can use js to refuse scrubbing server-side. Reference the answer here. Although that answer speaks of video, it also works with audio.
The lock screen / control center scrubber can also be avoided by using Web Audio API.
This is an example of preloading a sound and playing it, with commentary and error handling:
try {
// <audio> element is simpler for sound effects,
// but in iOS/iPad it shows up in the Control Center, as if it's music you'd want to play/pause/etc.
// Also, on subsequent plays, it only plays part of the sound.
// And Web Audio API is better for playing sound effects anyway because it can play a sound overlapping with itself, without maintaining a pool of <audio> elements.
window.audioContext = window.audioContext || new AudioContext(); // Interoperate with other things using Web Audio API, assuming they use the same global & pattern.
const audio_buffer_promise =
fetch("audio/sound.wav")
.then(response => response.arrayBuffer())
.then(array_buffer => audioContext.decodeAudioData(array_buffer))
var play_sound = async function () {
audioContext.resume(); // in case it was not allowed to start until a user interaction
// Note that this should be before waiting for the audio buffer,
// so that it works the first time (it would no longer be "within a user gesture")
// This only works if play_sound is called during a user gesture (at least once), otherwise audioContext.resume(); needs to be called externally.
const audio_buffer = await audio_buffer_promise; // Promises can be awaited any number of times. This waits for the fetch the first time, and is instant the next time.
// Note that if the fetch failed, it will not retry. One could instead rely on HTTP caching and just fetch() each time, but that would be a little less efficient as it would need to decode the audio file each time, so the best option might be custom caching with request error handling.
const source = audioContext.createBufferSource();
source.buffer = audio_buffer;
source.connect(audioContext.destination);
source.start();
};
} catch (error) {
console.log("AudioContext not supported", error);
play_sound = function() {
// no-op
// console.log("SFX disabled because AudioContext setup failed.");
};
}
I did a search, in search of a way to help you, but I did not find an effective way to disable the commands, however, I found a way to customize them, it may help you, follow the apple tutorial link
I think what's left to do now is wait, see if ios 13 will bring some option that will do what you want.
I'm making a webpage with dynamic content that enters the view with AJAX polling. The page JS occasionally downloads updated information and renders it on the page while the user is reading other information. This sort of thing is costly to bandwidth and processing time. I would like to have the polling pause when the page is not being viewed.
I've noticed most of the webpages I have open spend the majority of their time minimized or in a nonviewed tab. I'd like to be able to pause the scripts until the page is actually being viewed.
I have no idea how to do it, and it seems to be trying to break out of the sandbox of the html DOM and reach into the user's system. It may be impossible, if the JS engine has no knowledge of its rendering environment. I've never even seen a different site do this (not that the user is intended to see it...)
So it makes for an interesting question for discussion, I think. How would you write a web app that is CPU heavy to pause when not being used? Giving the user a pause button is not reliable, I'd like it to be automatic.
Your best solution would be something like this:
var inactiveTimer;
var active = true;
function setTimer(){
inactiveTimer = setTimeOut("stopAjaxUpdateFunction()", 120000); //120 seconds
}
setTimer();
document.onmouseover = function() { clearTimeout ( inactiveTimer );
setTimer();
resumeAjaxUpdate();
}; //clear the timer and reset it.
function stopAjaxUpdateFunction(){
//Turn off AJAX update
active = false;
}
function resumeAjaxUpdate(){
if(active == false){
//Turn on AJAX update
active = true;
}else{
//do nothing since we are still active and the AJAX update is still on.
}
}
The stopAjaxUpdateFunction should stop the AJAX update progress.
How about setting an "inactivity timeout" which gets reset every time a mouse or keyboard event is received in the DOM? I believe this is how most IM programs decide that you're "away" (though they do it by hooking the input messages at the system-wide level)
I've looked at that problem before for a research project. At the time (2-3 years ago) I did not find a way to get information from the browser about whether or not you are minimized :(
First check when the window loses and gains focus.
window.onblur = function () { /* stop */ };
window.onfocus = function () { /* start */ };
Also, for various reasons, the user may stop reading the page without causing it to lose focus (e.g. he gets up and walks away from the computer). In that case, you have to assume after a period of inactivity (no mouse or keyboard events) that the users' attention has left the page. The code to do that is described in another answer.
I know you've already accepted an answer but I'd personally use a combination of several of the answers mentioned here for various reasons, including:
Using mouse events only alienates users proficient at keyboard based browsing.
Using blur/focus events don't allow for users who go make a cup of tea ;-)
I'd most likely use something like the following as a guideline:
var idleTimer, userIsIdle, pollingTimer;
document.onkeydown = document.onmousemove = resetTimer;
window.onload = function () {
pollingTimer = window.setTimeout(runPollingFunction, 30000);
resetTimer();
/* IE's onblur/onfocus is buggy */
if (window.navigator.appName == "Microsoft Internet Explorer")
document.onfocusin = resetTimer,
document.onfocusout = setIdle;
else
window.onfocus = resetTimer,
window.onblur = setIdle;
}
function resetTimer() {
if (userIsIdle)
setBack();
window.clearTimeout(idleTimer);
idleTimer = window.setTimeout(setIdle, 120000); // 2 minutes of no activity
}
function setIdle() {
userIsIdle = true;
window.clearTimeout(pollingTimer); // Clear the timer that initiates polling
window.clearTimeout(setIdle);
}
function setBack() {
userIsIdle = false;
runPollingFunction(); // call the polling function to instantly update page
pollingTimer = window.setTimeout(runPollingFunction, 300000);
}
You can listen for mousemove and keypress events. If one of those has been fired in the past X seconds, then continue with your updating. Otherwise, don't update.
It's not perfect, but I think it's the best you can do with pure JS.
If you want to venture into the world of Flash, Silverlight, or Java, you may be able to get more information from the browser.