I'm trying to make this thing where in one tab you type something, and in another it pops up. However, I have to constantly reload the page to get my next message. First, this is what I tried.
<!DOCTYPE html>
<html>
<body>
<p id="message"></p>
<script>
var x = localStorage.getItem('message')
var i;
for (i = 0; i < 5) {
document.getElementById('message').innerHTML = x;
}
</script>
</body>
</html>
HOWEVER, this puts the page in a constant reloading state. How would I do this? Thanks!
Use setInterval instead of a loop.
setInterval(function() {
var x = localStorage.getItem('message');
document.getElementById('message').innerHTML = x;
}, 1000);
This will update every second.
Instead of constantly polling for updates, you can set up an event listenener to catch every message that is sent. You can do this thanks to the storage event:
// Every time a change it made to this domain's localStorage (item added, changed, removed)
window.addEventListener('storage', function() {
// Update your DOM
document.getElementById('message').innerHTML = localStorage.getItem('message');
});
You have an infinite loop. A for loop has four steps.
Initialization: Declaring the variable and its initial value(Happens
once)
Condition: Checking the condition to continue the loop
Final
Expression: Usually where you handle your logic that will end your
loop like incrementing the i variable
Execution: Execute the code in the code block
Your method is working but it never stops working, hence why your browser doesn't stop loading.
The for loop moves too quickly anyway and it would be better to put to listen for a storage event update on your document.
var messageContainer = document.querySelector('#message')
window.addEventListener('storage', function() {
var text = localStorage.getItem('message')
messageContainer.textContent = text
}
Related
I have a game written in JavaScript and what it basically does is start a ten seconds timer and register the number of times the user is able to click on a certain button, before the timer elapses.
How the code works:
When a user clicks on the button, an element gets added to an array, using push function, then a different function returns the length of the array as the number of times clicked.
The problem with this:
If a user opens up the dev tools and alters the number of times an element is added to the array per click, this will change the outcome of the result.
My Approach:
What I decided to do is to store the length before I ran the push function and also after I ran the push function, then compare their differences and if it's greater than 1, it means something is not right. This seemed to work in my head until I wrote it down in code and discovered that if the user pushed multiple times before I checked the differences then it would go unnoticed. Please big brained guys, help me.
My code:
$('body').on('click', '.btn.z', function () {
// start listening
startCountingClicks()
})
var timerStarted = false;
var tc = [];
function startCountingClicks () {
$('.btn.z').html('ClickZed');
$('.Score').html('Your Score: '+gettc()+" clicks");
if (timerStarted == false) {
startTimer(10, $('#time'));
}
// user does multiple push before this function: startCountingClicks is called
var previous_length = tc.length; // get length before push
tc.push(1);
var new_length = tc.length; // get length after push
if (new_length - previous_length !== 1) {
console.log("fraud"); // this is supposed to catch a thief!!!
}
console.log(new_length+" "+previous_length);
timerStarted = true;
}
function gettc (){
// get number of clicks
return tc.length ;
}
A code that totally breaks this:
$('button').click(function(){tc.push(1); tc.push(1)})
EDIT:
I do not wish to protect against dev tools, though I am not against that method if it works. I just wish to get a better way of counting my clicks, a way that can't be affected by writing code on the dev tools.
You can't really stop people from doing stuff on the client side. It is pointless trying to prevent that. The best thing you can do is make sure whatever is sent matches what you expect on the server side.
I am making a small userscript for a survey site. Whenever I click the survey and it is indicated that I did not receive it the script is supposed to refresh a certain amount of times trying to claim the survey until it gives up.
(If you do not know what a userscript is, think of it as something that stays running all the time on a specific website, so you can control things using javascript selectors and stuff)
This is my script so far (the javascript portion as that is what the problem is in):
var elementExists = document.getElementsByClassName("message warning")[0];
if(elementExists)
{
var attempts = 0;
while(attempts<5)
{
attempts += 1;
location.reload();
if(elementExists)
{
//nothing
}
else
{
window.stop();
}
}
window.stop();
}
This is actually my first time using Javascript so I assumed that would be the reason for errors, but after 45 minutes of debugging I am completely baffled. If I remove that last "window.stop();" the code refreshes the webpage infinitely. If that stays there then the code doesn't even start. It seems almost as if the while loop is being skipped if the "window.stop();" is present. Is this something that Javascript does, or is the problem elsewhere?
If someone could lead me in the right direction or help me fix this I would be very grateful!
(Also I checked the selector to see if that is the issue, but I have done that correctly)
UPDATE: Turns out location.reload(); stops the script and thus forces a reload. Since I am creating a userscript I realized that I could use the Greasemonkey APIs (or more like stumbled upon). By using GM_setValue and GM_getValue I was able to work around this problem and the script successfully reloaded a certain amount of times (depending on the variable tries) and stopped when it finished. But after messing around a bit, then reverting to the older version the script, the script doesn't doesn't execute at all anymore; "counter < tries" seems to be false for some reason... could anyone figure out why? Also if documentation is needed:
https://wiki.greasespot.net/GM_getValue
https://wiki.greasespot.net/GM_setValue
var tries = 5;
var elementExists = document.getElementsByClassName("message warning")[0];
var counter = GM_getValue('counter', 0);
if(elementExists && counter < tries)
{
GM_setValue('counter', ++counter);
location.reload();
}
(Both counter and tries seem to be integer values.. so there should be in problem in comparing them...)
Also as suggested by #yuriy636 I attempted to reset the variables and created something like this
var tries = 5;
var elementExists = document.getElementsByClassName("message warning")[0];
var counter1 = GM_getValue('counter1', 0);
if(elementExists && counter1 < tries)
{
GM_setValue('counter1', ++counter1);
location.reload();
}
if(elementExists && counter1 == tries)
{
GM_deleteValue('counter1');
window.close();
}
if(!!elementExists)
{
GM_deleteValue('counter1');
return;
alert("stops script while hidden");
}
But again I am hit with the infinite loop.. RIP
Update 2: Not so RIP afterall... solution:
var tries = 50;
var elementExists = document.getElementsByClassName("message warning")[0];
var counter = GM_getValue('counter', 0);
if(elementExists && counter < tries)
{
GM_setValue("counter", counter + 1);
location.reload();
}
else
{
GM_deleteValue("counter");
}
if(elementExists && counter >= tries)
{
window.close();
}
100% Working, after indicated amount of tries, if error still exists the page is closed
The most likely problem is that you have location.reload() in your while loop. This causes the page to refresh before anything interesting happens in your loop. In this particular code I would expect the page to refresh seemingly infinitely because every time the page refreshes, it will refresh again.
Normally this would look more like:
var elements = document.getElementsByClassName("message warning");
for (var i = 0; i < elements.length; i++) {
console.log (elements[i]);
}
.getElementsByClassName returns an array of elements with the class message and/or warning which you are capturing only the 1st one [0]. Hope that helps.
I'm new to javascript, and I'm trying to see if what I want to do is possible. I want to take a current webpage that I have open in my browser, and execute new javascript. There is a timer on this page, and when it increases to a particular time, I want it to execute a button click.
This would be the time that is changing and that I want to add into a if statement:
07:34:04
Will this changing time raise an event that would cause a javascript to run? I want something along the lines of:
if time = 7:35:00 then click button.
Thanks for your help!
I'll like to make a contribution..
I don't know much about the javascript time format, but I'll post back if I can look it up.
Any way you can use a function such as this:
var waiter;
function waitForTimer(extime, fn)
{
//Here, fn is the function to be executed..
//While extime is the time at which the function is to be executed..
waiter = setInterval(function(fn,extime){
//this function will check every one second..
if( extime == time )
{
fn();
clearInterval(waiter);
}
else
log("waiting for " + time);
}, 1000);
}
I hope this helps.
This is a basic jquery problem I think, but it is very annoying. This is what I am doing:
load a href class="tab" lists file (external) from jquery
click on href and load from external file again
setinterval 1000 refresh the results (2) with load() method AGAIN
Question is: At refresh period, the value for name selector changes every 1 second (because of refresh), that I recently clicked the hrefs from #1.
$('a.tab').live('click',function() {
var value = $(this).attr('name');
//....
setInterval(function(){
$("div#timed").load('retriever.php', {"update":value} );
} ,1000);//set interval
//....
$(this).undelegate('click');
});
I think that you want to cancel the other interval timers when you start a new one.
edit — oops hold on I'm fixing it ... ok thanks #kingjiv!!
$('a.tab').live('click',function() {
var value = $(this).attr('name');
var timers = $('body').data('timers') || {};
//....
for (var n in timers) clearInterval(timers[n]);
timers[value] = setInterval(function(){
$("div#timed").load('retriever.php', {"update":value} );
} ,1000);//set interval
//....
$(this).undelegate('click');
$('body').data('timers', timers);
});
As others have said, that "undelegate()" call is probably not doing what you think/want.
edit again — this could be done more intelligently; there really only needs to be one timer id stored on the body, of course. I'm kind-of slow sometimes.
$(document).ready(function() {
$('#domain').change(function() {
//
});
});
The code inside the change function will basically send ajax request to run a PHP script. The #domain is a text input field. So basically what I want to do is to send ajax requests as user types in some text inside the text field (for example search suggestions).
However, I would like to set a time interval in order to lessen the load of PHP server. Because if jQuery sends AJAX request every time user adds another letter to the text field it would consume lots of bandwidth.
So I would like to set let's say 2 seconds as an interval. The AJAX request will be fired every time the user types a letter but with maximum frequency of 2 seconds.
How can I do that?
$(function() {
var timer = 0;
$("#domain").change(function() {
clearTimeout(timer);
timer = setTimeout(function(){
// Do stuff here
}, 2000);
});
});
$(document).ready(function() {
var ajaxQueue;
$('#domain').change(function() {
if(!ajaxQueue) {
ajaxQueue = setTimeout(function() {
/* your stuff */
ajaxQueue = null;
}, 2000);
}
});
});
What you really want to do is check how long since the last change event so you keep track of the number of milliseconds between events rather than make a call every 2 seconds.
$(document).ready(function() {
var lastreq = 0; //0 means there were never any requests sent
$('#domain').change(function() {
var d = new Date();
var currenttime = d.getTime(); //get the time of this change event
var interval = currenttime - lastreq; //how many milliseconds since the last request
if(interval >= 2000){ //more than 2 seconds
lastreq = currenttime; //set lastreq for next change event
//perform AJAX call
}
});
});
Off the top of my head without trying this in a browser. Something like this:
$('#domain').change(function() {
if (!this.sendToServer) { // some expando property I made up
var that = this;
this.sendToServer = setTimeout(function(that) {
// use "that" as a reference to your element that fired the onchange.
// Do your AJAX call here
that.sendToServer = undefined;
}, yourTimeoutTimeInMillis)
}
else {
clearTimeout(this.sendToServer);
}
});
two variables, charBuffer, sendFlag
Use a setTimeout to have a function be called every two seconds.
This function checks if the buffer has stuff in it.
If it does, it sends/empties the stuff and clears the sent flag (to false).
and It should also clear the timeout, and set it again
else it sets the flag (to true).
Everytime the user hits a key, store it in the buffer.
if the sent flag is clear (it's false), do nothing.
else (it's true) send/empty the stuff currently in the buffer and clear the flag (to false),
and It should also clear the timeout, and set it again
This will make it so that the first time you press a key, it is sent, and a minimum of 2 seconds must pass before it can send again.
Could use some tweaking, but i use this setup to do something similar.
I am coming across this problem more and more (the more i do UI ajax stuff) so i packaged this up into a plugin available here