How to stop repeating of variables of "setInterval" Javascript - javascript

I'm a beginner at JS , Now am programming a javascript app
in the app there is a button when the user clicks on it, a door supposed to be opened for 10 seconds then close again
I used "set interval" to do this function by :
var rVars = []
rVars.push( {name:"door", val:1} ) // 1 for open , 0 for close
_server.setRoomVariables(r, user, rVars)
var params = {}
params.user = user
params.r = r
myInterval = setInterval("TimeForClose", 20000, params)
This is the code responsible for closing the door after 10 seconds
function TimeForClose(params){
var rVars = []
rVars.push( {name:"door", val:0} )
_server.setRoomVariables(params.r, params.user, rVars)}
And it was done successfully, but the problem was that I found the function "TimeForclose" repeats every 10 seconds , which makes when another user click on the button and door opens for him, the first one repeated function which still repeats will close the door for the second user too and both functions of each of them will be repeated , and so on .
So I read I have to use "clear interval" or timer to stop repeating but when I used it, it didn't stop the repeating so I think I used it Incorrectly
So what's the best way to stop repeating? ( I just want the function to occurs once when someone click on a button then it stops ) .
I hope you give me the correct syntax of the code

Yes, as u said u can use clearInterval() after closing of that door window, try that once

If you need to only execute once, you can use setTimeout
change setIntervalm to setTimeout
myInterval = setTimeout("TimeForClose", 20000, params)
The function is only executed once. If you need to repeat execution, use the setInterval() method.
If you need to repeat excution and stop based on some external event you can use clearTimeout()

Related

JS Performing actions on a popup window

So lately I have been learning JS and trying to interact with webpages, scraping at first but now also doing interactions on a specific webpage.
For instance, I have a webpage that contains a button, I want to press this button roughly every 30 seconds and then it refreshes (and the countdown starts again). I wrote to following script to do this:
var klikCount = 0;
function getPlayElement() {
var playElement = document.querySelector('.button_red');
return playElement;
}
function doKlik() {
var playElement = getPlayElement();
klikCount++;
console.log('Watched ' + klikCount);
playElement.click();
setTimeout(doKlik, 30000);
}
doKlik()
But now I need to step up my game, and every time I click the button a new window pops up and I need to perform an action in there too, then close it and go back to the 'main' script.
Is this possible through JS? Please keep in mind I am a total javascript noob and not aware of a lot of basic functionality.
Thank you,
Alex
DOM events have an isTrusted property that is true only when the event has been generated by the user, instead of synthetically, as it is for the el.click() case.
The popup is one of the numerous Web mechanism that works only if the click, or similar action, has been performed by the user, not the code itself.
Giving a page the ability to open infinite amount of popups has never been a great idea so that very long time ago they killed the feature in many ways.
You could, in your own tab/window, create iframes and perform actions within these frames through postMessage, but I'm not sure that's good enough for you.
Regardless, the code that would work if the click was generated from the user, is something like the following:
document.body.addEventListener(
'click',
event => {
const outer = open(
'about:blank',
'blanka',
'menubar=no,location=yes,resizable=no,scrollbars=no,status=yes'
);
outer.document.open();
outer.document.write('This is a pretty big popup!');
// post a message to the opener (aka current window)
outer.document.write(
'<script>opener.postMessage("O hi Mark!", "*");</script>'
);
// set a timer to close the popup
outer.document.write(
'<script>setTimeout(close, 1000)</script>'
);
outer.document.close();
// you could also outer.close()
// instead of waiting the timeout
}
);
// will receive the message and log
// "O hi Mark!"
addEventListener('message', event => {
console.log(event.data);
});
Every popup has an opener, and every different window can communicate via postMessage.
You can read more about window.open in MDN.

Need help understanding javascript code/jquery

So apparently the following can be used to automate linkedin steps of unfollowing a contact. I tried to run this code in the Chrome Console, and I'm not sure if it works. So I need help from someone who knows Javascript and JQuery to understand what this does, and then I can modify it to make it work.
var buttons = $("button"),
interval = setInterval(function(){
var btn = $('.is-following');
console.log("Clicking:", btn);
btn.click();
if (buttons.length === 0) {
clearInterval(interval);
}
}, 1000);
PS: The linkedin page that lets to unfollow your contacts is below. Login, and then navigate to the below.
https://www.linkedin.com/mynetwork/invite-connect/connections/
First, it selects all the buttons and stores them on the variable buttons ($("TAG") will select elements with the tag TAG). Then, it creates an interval that will be stored in the variable interval (bad practice, btw, because it isn't using "var" to declare the variable, so, it's a global variable, that should be avoided... but it's necessary to declare it as global in order to use clearInterval) that will execute the function inside the setInterval function call every second (1000 ms). That function will get all the elements that have the class "is-following" and will store them on the variable btn. Then, it will log the... buttons? After that, it will execute the click event on all of those buttons. Finally it will check if the amount of buttons are 0. If true, it'll stop the interval.

Within Google apps script, what replaces Utilities.sleep() to prevent double clicks?

I'm writing an add-on within Google Docs Script. From a sidebar, it writes info into the Doc, not a spreadsheet. Depending on connection speeds, the Doc is updated between <1 sec and 5 secs with the info.
My issue is with user double clicks. I can disable the button; however, the script takes less than a second to complete, yet the Doc is updated in > 1 sec. The finished script enables the button. The user clicks the button again and the script attempts to write the info for the first time. The end result is a double entry.
My solution thoughts were: 1. a wait or pause 2. a callback function or 3. Locks.
Issues:
Callback: I couldn't figure out what event/input I could use to tell the script to unlock the button now. I could do an infinite loop that constantly checks forever until the Doc has been updated, but that didn't seem like a solid solution.
Lock: There isn't anything there to simply just wait. It can wait for the function to become available, but that isn't a problem. The problem is the script is done to fast relative to the Doc update.
Any thoughts?
Thanks.
I think of this solution:
Each time the script is called, you compare document's current text with the text which was passed to your script on the previous call.
Some pseudo code:
var previousText = "";
function addEntry() {
var body = DocumentApp.getActiveDocument().getBody();
var currentText = body.getText();
if (currentText === previousText) {
// Enable button here
return;
}
// Add entry to document AND currentText
// ...
// ...
previousText = currentText; // Save the text for future checks
// Enable button here
}
function onButtonClick(e) {
addEntry();
// Disable button here
}
I got it. I didn't realize the .withSuccessHandler also waited for the Doc to be updated. I assumed it only waited for the .saveSettings(settings) to finish. Now the SuccessHandler(enablesButton) at the appropriate time to prevent double clicks.
google.script.run.withFailureHandler(onFailure).withSuccessHandler(enableButton)
.saveSettings(settings);

document.getElementById does not return null, but also does not do what I want. No error in javascript console

In this instance, I load a single paypal page, in which I am prompted to login. Once I login, the page changes, through the use of other javascripts on paypal's end. The address does not change on this transition, nor does the source code in any material way. I am trying to find a way to have my script wait long enough after the first click to be able to get the element that loads after. I thought I could do this fairly simple using the following:
document.getElementById("submitLogin").click();
window.onload = function() {
document.getElementById("continue").click();
};
When the script is executed, the first button is clicked, the page transitions, but it won't click the second button that loads. My javascript console does not report any errors, suggesting that it is able to "get" the element. Not sure why it won't click it though.
If nothing else, you could always poll for the existence of the "continue" element at some interval:
function clickContinue() {
var button = document.getElementById("continue");
return button ? button.click() : setTimeout(clickContinue, 100);
}
document.getElementById("submitLogin").click();
clickContinue();
If you go this route, you'll probably want to include a failsafe so it doesn't run too long, in case something unexpected happens. Something like this should work:
clickContinue.interval = 100; // Look for "continue" button every 0.1 second
clickContinue.ttl = 10000; // Approximate time to live: 10 seconds ~ 10,000 ms
clickContinue.tries = clickContinue.ttl / clickContinue.interval | 0;
function clickContinue() {
var button = document.getElementById("continue"),
interval = clickContinue.interval;
return button ? button.click() :
clickContinue.tries-- && setTimeout(clickContinue, interval);
}
// ...
Take a look at PayPal's API docs and see if they provide a way to set up a callback to handle this, though. This polling technique should probably only be used as a last resort.

How can I detect with JavaScript/jQuery if the user is currently active on the page?

I am needing to detect when a user is inactive (not clicking or typing) on the current page for more than 30 minutes.
I thinking it might be best to use event blubbling attached to the body tag and then just keep resetting a timer for 30 minutes, but I'm not exactly sure how to create this.
I have jQuery available, although I'm not sure how much of this will actually use jQuery.
Edit: I'm more needing to know if they are actively using the site, therefore clicking (changing fields or position within a field or selecting checkboxes/radios) or typing (in an input, textarea, etc). If they are in another tab or using another program, then my assumption is they are not using the site and therefore should be logged out (for security reasons).
Edit #2: So everyone is clear, this is not at all for determining if the user is logged in, authenticated or anything. Right now the server will log the user out if they don't make a page request within 30 minutes. This functionality to prevent the times when someone spends >30 minutes filling in a form and then submitting the form only to find out that they haven't been logged out. Therefore, this will be used in combination with the server site to determine if the user is inactive (not clicking or typing). Basically, the deal is that after 25 minutes of idle, they will be presented with a dialog to enter their password. If they don't within 5 minutes, the system automatically logs them out as well as the server's session is logged out (next time a page is accessed, as with most sites).
The Javascript is only used as a warning to user. If JavaScript is disabled, then they won't get the warning and (along with most of the site not working) they will be logged out next time they request a new page.
This is what I've come up with. It seems to work in most browsers, but I want to be sure it will work everywhere, all the time:
var timeoutTime = 1800000;
var timeoutTimer = setTimeout(ShowTimeOutWarning, timeoutTime);
$(document).ready(function() {
$('body').bind('mousedown keydown', function(event) {
clearTimeout(timeoutTimer);
timeoutTimer = setTimeout(ShowTimeOutWarning, timeoutTime);
});
});
Anyone see any problems?
Ifvisible.js is a crossbrowser lightweight solution that does just that. It can detect when the user switches to another tab and back to the current tab. It can also detect when the user goes idle and becomes active again. It's pretty flexible.
You can watch mouse movement, but that's about the best you're going to get for indication of a user still being there without listening to the click event. But there is no way for javascript to tell if it is the active tab or if the browser is even open. (well, you could get the width and height of the browser and that'd tell you if it was minimized)
I just recently did something like this, albeit using Prototype instead of JQuery, but I imagine the implementation would be roughly the same as long as JQuery supports custom events.
In a nutshell, IdleMonitor is a class that observes mouse and keyboard events (adjust accordingly for your needs). Every 30 seconds it resets the timer and broadcasts an state:idle event, unless it gets a mouse/key event, in which case it broadcasts a state:active event.
var IdleMonitor = Class.create({
debug: false,
idleInterval: 30000, // idle interval, in milliseconds
active: null,
initialize: function() {
document.observe("mousemove", this.sendActiveSignal.bind(this));
document.observe("keypress", this.sendActiveSignal.bind(this));
this.timer = setTimeout(this.sendIdleSignal.bind(this), this.idleInterval);
},
// use this to override the default idleInterval
useInterval: function(ii) {
this.idleInterval = ii;
clearTimeout(this.timer);
this.timer = setTimeout(this.sendIdleSignal.bind(this), ii);
},
sendIdleSignal: function(args) {
// console.log("state:idle");
document.fire('state:idle');
this.active = false;
clearTimeout(this.timer);
},
sendActiveSignal: function() {
if(!this.active){
// console.log("state:active");
document.fire('state:active');
this.active = true;
this.timer = setTimeout(this.sendIdleSignal.bind(this), this.idleInterval);
}
}
});
Then I just created another class that has the following somewhere in it:
Event.observe(document, 'state:idle', your-on-idle-functionality);
Event.observe(document, 'state:active', your-on-active-functionality)
Ifvisible is a nice JS lib to check user inactivity.
ifvisible.setIdleDuration(120); // Page will become idle after 120 seconds
ifvisible.on("idle", function(){
// do something
});
Using jQuery, you can easily watch mouse movement, and use it to set a variable indicating activity to true, then using vanilla javascript, you can check this variable every 30 minutes (or any other interval) to see if its true. If it's false, run your function or whatever.
Look up setTimeout and setInterval for doing the timing. You'll also probably have to run a function every minute or so to reset the variable to false.
Here my shot:
var lastActivityDateTime = null;
function checkActivity( )
{
var currentTime = new Date();
var diff = (lastActivityDateTime.getTime( ) - currentTime.getTime( ));
if ( diff >= 30*60*1000)
{
//user wasn't active;
...
}
setTimeout( 30*60*1000-diff, checkActivity);
}
setTimeout( 30*60*1000, checkActivity); // for first time we setup for 30 min.
// for each event define handler and inside update global timer
$( "body").live( "event_you_want_to_track", handler);
function handler()
{
lastActivityDateTime = new Date();
// rest of your code if needed.
}
If it's a security issue, doing this clientside with javascript is absolutely the wrong end of the pipe to be performing this check. The user could easily have javascript disabled: what does your application do then? What if the user closes their browser before the timeout. do they ever get logged out?
Most serverside frameworks have some kind of session timeout setting for logins. Just use that and save yourself the engineering work.
You can't rely on the assumption that people cannot log in without javascript, therefore the user has javascript. Such an assumption is no deterrent to any determined, or even modestly educated attacker.
Using javascript for this is like a security guard handing customers the key to the bank vault. The only way it works is on faith.
Please believe me when I say that using javascript in this way (and requiring javascript for logins!!) is an incredibly thick skulled way to engineer any kind of web app.
Without using JS, a simpler (and safer) way would simply be to have a lastActivity timestamp stored with the user's session and checking it on page load. Assuming you are using PHP (you can easily redo this code for another platform):
if(($_SESSION['lastAct'] + 1800) < time()) {
unset($_SESSION);
session_destroy();
header('Location: session_timeout_message.php');
exit;
}
$_SESSION['lastAct'] = time();
and add this in your page (optional, the user will be logged out regardless of if the page is refreshed or not (as he logs out on next page log)).
<meta http-equiv="refresh" content="1801;" />
You can add and remove classes to the document depending on the user active status.
// If the window is focused, a mouse wheel or touchmove event is detected
$(window).on('focus wheel touchmove', function() {
$( 'html' ).addClass('active').removeClass('inactive');
});
// If the window losses focus
$(window).on('blur', function() {
$( 'html' ).addClass('inactive').removeClass('active');
});
After that, you can check every while if the html has the "active" class and send an AJAX request to check the session status and perform the action you need:
setInterval( function() {
if ( $( 'html' ).hasClass('active') ) {
//Send ajax request to check the session
$.ajax({
//your parameters here
});
}
}, 60000 ); /* loops every minute */
If your concern is the lost of information for the user after a login timeout; another option would be to simply store all the posted information upon the opening of a new session (a new session will always be started when the older session has been closed/scrapped by the server) when the request to a page is made before re-routing to the logging page. If the user successfully login, then you can use this saved information to return the user back to where he was. This way, even if the user walk away a few hours, he can always return back to where he was after a successful login; without losing any information.
This require more work by the programmer but it's a great feature totally appreciated by the users. They especially appreciate the fact that they can fully concentrate about what they have to do without stressing out about potentially losing their information every 30 minutes or so.

Categories