body onload setTimeout without reference - javascript

At our job we're using a communication portal that logs out after a while. Some of my co-workers asked me for a javascript, that disables the autologout. All i could achieve was to reset the displayes timer, but the timer itself keeps running anyway. Here is how the timer is started:
<body class='asam_body' onLoad='window.setTimeout("DsplTime()",1);' >
As you can see, setTimeout is called at onLoad, but there is no reference to the setTimeout-call, so i can't use the clearTimeout() function. I've also tried to call DsplTime() out of my script, but that still doesn't stop the timer. Everything i found doesn't apply to my case, so i gave up my search after two hours.
Is there any way to influence this serverside body-definition, e.g. by
overriding the onLoad (tried with #document-start)
replacing the string for the definition of the body itself (i guess because the server delivers that, its to late for my script to inject, when the line is there)
getting a reference to the setTiming-Object retroactively
Here's my rather useless approach, that only resets the displayed time:
setInterval(CalcTime, 130000);
setInterval(resetStart, 130000);
setInterval(DsplTime, 130000);
//resetStart and CalcTime are prefined functions,
// without any impact on the timer itself, unfortunately
Thanks in advance!
P.S.: thats the first time i asked something on stackoverflow, so i hope, i asked appropiately:)
Edit:
I tried the brute force approach from Cancel all Javascript's setTimeouts and setIntervals, with
for (var i = 1; i < 99999; i++) {
window.clearInterval(i);
window.clearTimeout(i);
window.mozCancelAnimationFrame(i); // Firefox
}
But still i'm logged out after the same amount of time.
This codesnipped leads to the logout after 1440 minutes:
if (absSec >= 1440)
{
document.location.href = "../project/auth/logout.php";
}
This is part of the function DsplTime() metioned above. Is there any way of manipulating this function, instead of preventing it's call? absSec is out of scope, so i can't change it's value (and i think this wouldn't help anyway?
Edit 2:
So i could manage to stop the timer by
// #run-at document-start
//...
var highestTimeoutId = setTimeout(";");
for (var i = 0 ; i < highestTimeoutId ; i++) {
window.clearTimeout(i);
// window.alert(i);
}
Unfortunately, the script only works every now and then (in like 80% of the pageloading). Plus, isn't this generating a lot of load for the server? I don't want to be blocked...

Why not just override the javascript function DsplTime() so that it doesn't log you out?
go to the debug console and type something like DsplTime = new function(){}
when the interval is up and DsplTime(), the function will do nothing.

Related

How to find which js file creating problem

I have more than 20 js files like jQuery etc in my project, when I scroll it gets hung as it loads very lazily. How to find which file creates the problem?
It may be one of several things and without looking at your code I couldn't possibly say what the cause would actually be. You've asked an extremely subjective comment. There's no silver bullet when it comes to debugging and problem solving.
I've always found the Occams Razor approach the most effective.
"When you remove all other options, whatever remains, however unlikely, must be the problem/solution/answer."
Firstly, before you start removing JS files, have you tried doing a full-search of your project for .scroll? There's a high likelihood that there are several functions which run on-scroll which are causing reflows, a common problem which such code.
Once you've assessed your code, you can verify exactly what happens when the code executes using the "Performance" tab in Google Chrome to do this (Learn how to use the Performance Tab here). You can take the appropriate action.
Assuming that your code suffers from the same problem I've encountered in my formative years using jQuery - multiple or problematic on-scroll events - you can de-bounce the ones which can run after scrolling has completed. You can do this by using the following pattern.
Scenario 1:
This would run many times. 'N' times for each scrollwheel drag (dependent on settings - mine is 10) and even more times when using the scrollbar.
function someFunc() {
let someArr = [];
for(var i = 0; i < 1000000; i++ {
someArr.push((i * 2));
}
for(var i = 0; i < someArr.length; i++ {
someArr[i] /= 0.25;
}
}
$(window).on("scroll", function() {
someFunc();
});
Scenario 2:
This would run once after scrolling has finished. Waiting for 200ms before executing to ensure the user has completely finishing scrolling.
function someFunc() {
let someArr = [];
for(var i = 0; i < 1000000; i++ {
someArr.push((i * 2));
}
for(var i = 0; i < someArr.length; i++ {
someArr[i] /= 0.25;
}
}
let debouncedTimeout = null;
$(window).on("scroll", function() {
if (debouncedTimeout) {
clearTimeout(debouncedTimeout);
}
debouncedTimeout = setTimeout(someFunc(), 200);
});
Add a console.log("Check") with numbers (check1, check2) and so on in every file. Check your console in your browser, look in which series they load in console. If it takes a while to load the next log you know its the previous file with the number you logged.
Your console should say everything.
But loading so many js files is bad practice.
Try to fit everything in to one, so in further bckend development can go to an .min.js
But if you keep doing this. The simplest way is to keep track of the funcioncesequences with console.log, so that you evrything works how it is supposed to
:)

Meteor Collection.find() blocks the entire application during working

I try to display a loading alert on Meteor with modal package during loading of data.
'change .filterPieChart': function(evt){
Modal.show('loadingModal');
/* a little bit of work */
var data = MyCollection.find().fetch(); // takes 3 or 4 seconds
/* lot of work */
Modal.hide('loadingModal');
}
Normally, the alert is displayed at the beginning of the function, and disappears at the end. But here, the alert appears only after the loading time of the MyCollection.find(), and then disappears just behind. How to display it at the beginning of the function ??
I tried to replace Modal.show with reactive variable, and the result is the same, the changing value of reactive variable is detect at the end of the function.
From what you describe, what probably happens is that the JS engine is busy doing your computation (searching through the collection), and indeed blocks the UI, whether your other reactive variable has already been detected or not.
A simple workaround would be to give some time for the UI to show your modal by delaying the collection search (or any other intensive computation), typically with a setTimeout:
Modal.show('loadingModal');
setTimeout(function () {
/* a little bit of work */
var data = MyCollection.find().fetch(); // takes 3 or 4 seconds
/* lot of work */
Modal.hide('loadingModal');
}, 500); // delay in ms
A more complex approach could be to decrease the delay to the bare minimum by using requestAnimationFrame
I think you need to use template level subscription + reactiveVar. It is more the meteor way and your code looks consistent. As i can see you do some additional work ( retrive some data ) on the change event. Make sense to actually really retrive the data on the event instead of simulation this.
Template.TemplateName.onCreated(function () {
this.subsVar = new RelativeVar();
this.autorun( () => {
let subsVar = this.subsVar.get();
this.subscribe('publicationsName', this.subsVar);
})
})
Template.TemplateName.events({
'change .filterPieChart': function(evt){
Template.instance().collectionDate.subsVar.set('value');
Modal.show('loadingModal');
MyCollection.find().fetch();
Modal.hide('loadingModal');
}
})
Please pay attention that i didn't test this code. And you need to use the es6 arrow function.

SWFObject event undefined in Chrome works in IE

I want to get the currentFrame of my Flash movie when it is loaded. I followed the the tutorial found here http://learnswfobject.com/advanced-topics/executing-javascript-when-the-swf-has-finished-loading/index.html and SWFOBJECT CurrentFrame Javascript. I am using SWFObject 2.3 beta. This works perfectly fine on Internet Explorer however it does not work on Google Chrome.
In Chrome I get the error
Uncaught TypeError: e.ref.currentFrame is not a function
Checking e it returns [object Object]
Checking e.ref returns [object HTMLObjectElement]
Checking e.ref.totalFrames returns undefined
var flashvars = {};
var params = {};
var attributes = {};
function mycall(e){
setInterval(function(){console.log("Frame: " + e.ref.currentFrame)},1000);
}
swfobject.embedSWF("notmyswf.swf", "course", "100%", "100%", "6.0.0", false, flashvars, params, attributes, mycall);
Why is this not working on Chrome but works well with IE? Is the event e not detected? Is there a work-around on how to make this work on Chrome?
The purpose of this is for me to create a check if the user is really using the course he has opened and not just leaving it idle. I have already added a code that will check idle but it is not enough. Most learners, have figured out a way to just open a course, leave it there to accumulate hours of training. Some even have a program running in their computers that will just move the mouse 1-pixel every few seconds so that the computer does not go to idle. If I can check the current frame of the Flash movie, I can create a function that will calculate the current page the user is viewing every 15 minutes. If he is stuck in the same page I can then show a prompt that the user must click in order to continue viewing the course or it will automatically close.
I suggest dropping the SWF-based currentFrame approach in favor of monitoring your calls to the database using JavaScript. (Based on your comments, it sounds like the DB calls are being sent by JS, so this shouldn't be a problem.)
If the course bookmark is auto-saved every 3 minutes (as described in your comments), you can cache the value in your page's JS and do a compare every time the save is performed. If the value hasn't changed in x number of minutes, you can display your timeout warning.
If you're using a SCORM wrapper (or similar), this is really simple, just modify the wrapper to include your timer code. Something like:
//Old code (pseudocode, not tested)
function setBoomark (val){
API.SetValue("cmi.core.lesson_location", val);
}
//New code (pseudocode, not tested)
var current_location = "";
var activityTimer;
function disableCourse(){
//do stuff to disable course because it timed out
}
function setBoomark (val){
API.SetValue("cmi.core.lesson_location", val);
if(val === current_location){
//do nothing, timer keeps ticking
} else {
//reset timer using new bookmark value
if(activityTimer){ clearTimeout(activityTimer); }
activityTimer = setTimeout(disableCourse, 15000);
//Update current_location value
current_location = val;
}
}
This is a rough sketch but hopefully you get the idea.
I feel stupid!
It did not work in Chrome and Firefox because I used the wrong casing for the functions but in IE11 it works no matter the case.
So the correct functions are:
e.ref.CurrentFrame() //I used currentFrame() which still works in IE11
e.ref.TotalFrames() //I used totalFrames() which still works in IE11
e.ref.PercentLoaded() //I used this correctly and was able to get the value

Why does waitForKeyElements() only trigger once despite later changes?

For several years I've used the waitForKeyElements() function to track changes in webpages from a userscript. However, sometimes I've found it doesn't trigger as expected and have worked around out. I've run into another example of this problem, and so am now trying to figure out what the problem is. The following is the barest example I can create.
Given a simple HTML page that looks like this:
<span class="e1">blah</span>
And some Javascript:
// function defined here https://gist.github.com/BrockA/2625891
waitForKeyElements('.e1', handle_e1, false);
function handle_e1(node) {
console.log(node.text());
alert(node.text());
}
setInterval(function() {
$('.e1').text("updated: "+Math.random());
}, 5000);
I would expect this code to trigger an alert() and a console.log() every 5 seconds. However, it only triggers once. Any ideas?
Here's a codepen that demonstrates this.
By design and default, waitForKeyElements processes a node just once. To tell it to keep checking, return true from the callback function.
You'll also want to compare the string (or whatever) to see if it has changed.
So, in this case, handle_e1() would be something like:
function handle_e1 (jNode) {
var newTxt = jNode.text ();
if (typeof this.lastTxt === "undefined" || this.lastTxt !== newTxt) {
console.log (newTxt);
this.lastTxt = newTxt;
}
return true; // Allow repeat firings for this node.
}
With the constant string comparisons though, performance might be an issue if you have a lot of this on one page. In that scenario, switching to a MutationObserver approach might be best.

setTimeout not working on safari mobile

I have a function that shows a menu when clicking on it, and I want it to disappear after 5 seconds. This is my javascript - it works properly on desktop browser but it doesn't disappear on the mobile ones.
$(function() {
$('#prod_btn').click(function() {
$(this).addClass('selected').next('ul').css('display', 'block');
setTimeout(hideMenu, 5000);
});
});
function hideMenu() {
$('#prod_btn').removeClass('selected').next('ul').css('display', 'none');
}
Where is the problem?
Thanks
I've just had the same problem. My code is running great in any browser on my Mac, but on iOs devices it doesn't work.
I use ".bind(this)" on my timeout function and that is what is causing the problem for me.
When I extend the function object with ".bind" in my script it works like a charm.
My code is something like this:
searchTimeout = setTimeout(function() {
...
}.bind(this),250);
For this to work on iOs devices I (like mentioned above) just added this:
Function.prototype.bind = function(parent) {
var f = this;
var args = [];
for (var a = 1; a < arguments.length; a++) {
args[args.length] = arguments[a];
}
var temp = function() {
return f.apply(parent, args);
}
return(temp);
}
I don't see any .bind on your setTimeout, but for others with the same problem this may be the issue. That's why I'm posting :-)
I moved your example to a jsbin, and it's working on my iphone 4.
Please test it out going here from your devices: http://jsbin.com/asihac/5
You can see the code here http://jsbin.com/asihac/5/edit
The example is using jQuery - latest and I only added the required css class.
this doesn't apply to your code, but a common problem with long-running scripts failing on iOS devices is that MobileSafari kills a javascript thread after 10 seconds have elapsed. you should be able to use setTimeout and/or setInterval to work around this, or you can avoid it by making a shortcut to it and thereby running it as an app. see https://discussions.apple.com/thread/2298038, particularly the comments by Dane Harrigan.
Keep in mind also that any setTimeout function is actually likely fire while DOM elements are rendering if the delay is set to a value too short. While that might seem obvious, it can be easily confused with no method firing whatsoever. A good way to test is to have an alert prompt run.
window.onLoad(alert("hey!"));
Then check to see if your function fires after.

Categories