We're running an angular app and need to wait until angular is done on the page before we try and run our automation.
Our automation is separate from the application, so we need to be able to run a javascript function against the browser to know if the DOM is finished loading and the events are all attached.
jQuery.active is actually tracking the number of active AJAX requests, not the active amount of jquery functions running.
If what you're aiming for is something that fires after all ajax calls are done, do something like this:
var counter = 1;
ajaxCallComplete = function() {
counter++;
if(counter >= ajaxCalls) {
//Do automation
}
};
Have that declared somewhere, and have your ajax call count declared as well. Have each AJAX call invoke this when it finishes. Don't know if this answers your question fully, but it should get you in the right direction.
Related
First of all, it has two pages: example.com/pageA and example.com/pageB, it's not a SPA.
How to run a delay task after the page being killed by history.back?
I tried using setTimeout but failed to execute the task after history.back, because the timer will be clear in stack when page change.
var a = 1
function refresh() {
// <p id="count"></p>
count.innerText = a
}
function foo() {
a += 1
refresh()
}
// called in PageB
function goBackA() {
setTimeout(foo, 1000)
history.back()
}
In PageA the count still be 1 instead of 2.
For security reason, your goal to run some code after page being killed will never be supported by the browser, because it's dangerous when some code can run on a different page.
Once the page being reload/killed, all the unfinished tasks will be clear even if in a SharedWorker.
So, two ways to accomplish your logic:
change to SPA
give another page a hint like query
One javascript file that my webpage loads has this call
window.setTimeout(function() {
self.MakeWaterFall(self)
}, 500);
That .js file is hosted on other server and is loaded on webpage similar like many js libs from CDNs are loaded,, and that file has 'hardcoded' setTimeout call after 500ms
Now, I'd like that 'MakeWaterFall' function to run little later on a page
I'd like it to run after custom trigger fires, after ajax data comes down the wire and renders posts on a page.
This is that binded trigger that I need to 'move' MakeWaterFall fn to..
$(window).bind( 'grid:items:added' , function(){
// .. some custom events on elements +
MakeWaterFall(window);
} ) ;
this question in essence is like 'can I hook up before window.setTimeout runs and block one spec call and move it somewhere else, latter in the code' ?
also not that I have other bunch of code that runs in other places in code via window.setTimeout code,, I know that sucks :(
thanks
use a callback-function like this:
function myFunction(callback){
myFunction1();
if(typeof(callback) === "function()"){
myFunction2();
}}"
ok I found a solution and it's very simple actually .. it incudes this steps:
1) I made sure that I loaded my custom.js file earlier on the page, before hosted CDN 'problematic' js file comes on page (that has setTimeout in it)
2) I preserved native function and made my custom one and did this:
// save original setTimeout function to savedST
window.savedST = window.setTimeout ;
// define custom window.setTimeout function and hook to it
window.setTimeout = function(a, b){
// I'm testing if this calls waterfall fn.. then bounce that f() to other binded event
if ( a.toString().indexOf( 'MakeWaterFall' ) > -1 ){
$(window).bind( 'grid:items:added', function(){
a();
});
} else {
// run normal or original setTimeout as usual
savedST(a, b);
}
} ;
I'm sure this is something that will help someone that will need to override "setTimeout" and/or "setInterval", native window functions
cheers, k
I am making a general loading animation for my angular application.
I have a service which toggles a loading animation on and off and the events are happening as I expect them to, my issue is that the UI is not updating with the events.
The turn on and turn off of the loading animation occurs in the same function call so my guess is that the ui isn't updated until the function call completes which basically means that my turning on and off or the loading animation has no effect.
How can I write this in a way that the UI will be updated as the variables change. I added in a pause to simulate heavy calculation on load just to check... which is the datetime stuff.
The two broadcasts are the start and stop of the loading state.
function activateController(promises, controllerId) {
var startData = { controllerId: controllerId };
$broadcast(configcommonProvider.config.controllerActivateStartEvent, startData);
return $q.all(promises).then(function (eventArgs) {
var e = new Date().getTime() + (2 * 1000);
while (new Date().getTime() <= e) { }
var successData = { controllerId: controllerId };
$broadcast(configcommonProvider.config.controllerActivateSuccessEvent, successData);
});
}
Try calling $apply() on your scope object after the broadcast, it should force a digest cycle which should update the UI.
JavaScript is single-threaded and - conceptually - the changes in the GUI are on the same thread as the program.
This is exactly why there are so many callbacks in Javascript APIs (which you might have noticed working with AJAX). The only way to get around the single-threaded nature of JS is not to wait for something to finish at all. Instead - to be called back when something is finished.
What you want to do (long running calculations) is something very unnatural in JS, so the only real solution will be quite verbose. You need to run a webworker in parallel to your code and wait until it signals that it is finished. The shortest no-nosense example of using webworkers is probably the official HTML5 specification on WHATWG site.
I have a bit of javascript, triggered from an HTML button, that calls a function. This is using Jquery as well, so there are a couple of underlying functions from that that get called in this process, too. In my script I make a couple of changes to window.location in order to communicate to a remote system (which is supposed to fire off different scripts in response to these calls). This window.location definition is not using the HTTP protocol, but FMP, a registered - on my machine anyway - protocol for FileMaker Pro.
Sample code:
function compareJSON() {
dataSession=({ //build object for output });
$.each( dataSession.chapters , function( indexC, value ) {
//compare objects to some others, testing and changing data
});
//Call remote script on other system
window.location= "fmp://blah.dee.com/Blar?script=SaveJSON&$JSONobject=" + JSON.stringify( dataSession );
//Call remote script on other system
window.location="fmp://blah.dee.com/Blar?script=EditJSON";
}
(Keep in mind, since this is using Jquery, that simply pressing the button that calls this compareJSON() function creates a stack of 2 or 3 other functions before running my function. But, even if it were being called directly in some manner, the compare function itself would be on the stack and thus window.location wouldn't get evaluated until the end of that function.)
The problem is that it looks like the Window.Location isn't being finalized/set/sent/whatever until the ENTIRE JS call stack is finished. So, when I click the button that starts these function calls the stack gets a few Jquery functions put on it (e.g. 'handler', 'default', 'each loop'...), then it hits the JS code that I wrote, which in turn adds a few more function calls to the stack; and then there are a few more Jquery functions that added to the stack, etc. But these stacked window.location definitions made in my functions don't actually trigger the remote system until I step all the way through the JS call stack and exit everything. So the window.location is only defined/set to be whatever was last set in the function calls, instead of including all the intervening definitions/sets that occurred in the stack. It's like a variable that gets changed multiple times in the call stack but only gets read once at the end.
Is there a way to force window.location to be evaluated when it is set instead of waiting for whatever the last setting was?
Thanks,
J
You may want to use an iframe:
function callScript(url) {
var ifr = document.createElement('iframe');
ifr.src = url;
// you can even add ifr.onload = function() {doSomething();}; if you want
}
This will allow any number of calls at once.
This might not work, but the timeout idea is to change something like this:
// code code code ...
window.location = newUrl;
// more code ...
into:
// code code code ...
window.location = newUrl;
setTimeout(function() {
// more code ...
}, 1);
That allows the browser an interval in which it can do something before starting the next event loop for the timer handler.
I want to run some code on all my treeView nodes depending on a value returned from the database and repeat this until a certain value is returned.
I was thinking that:
Give all my tree nodes the same css class so I can access them from JQuery
have a timer in my JQuery function that used ajax to go to the database, when a certain value is returned then stop the timer
Two questions here. How can I make my function run for each of the nodes and how do I do a timer in JavaScript, so:
$(function(){
$('cssClassOfAllMyNodes').WhatFunctionToCallHere?((){
//How do I do Timer functionality in JavaScript?
ForEachTimeInterval
{
//use Ajax to go to database and retrieve a value
AjaxCallBackFunction(result)
{
if (result = 1)
//How to stop the timer here?
}
}
});
});
Hope i'm clear. Thanks a lot
thanks a lot for the answer. And i would like you to comment on the design.
Bascially what i'm trying to acheive is a Windows Wokflow type functionality where each node in my tree updates its image depending on its status, where its status is got from querying the database with a key unique to the tree node. I'm open to ideas on other ways to implement this if you have any. thanks again
Without commenting on your design you can refer to these
$.each()
setTimeout() or setInterval()
You can do:
$(function(){
$('cssClassOfAllMyNodes').each(function (){
// Do something with "this" - "this" refers to current node.
});
});
Te proper way to handle timers in JS is to have a reference to each timeout or interval and then clearing them out.
The difference between them is:
The timeout will only run once, unless stopped before;
The interval will run indefinitely, until stopped.
So you can do something like:
var delay = 2000; // miliseconds
var timer = setTimeout("functionToBeCalled", delay);
clearTimeout(timer); // whenever you need.
Please note you can pass a string to setTimeout (same with setInterval) with the name of the function to be called. Or you could pass a reference to the function itself:
var callback = function () { alert(1); };
var timer = setTimeout(callback, delay);
Be sure not to set an Interval for AJAX requests, because you response might be delayed and successive calls to the server could eventually overlap.
Instead, you should call setTimeout and when the answer arrives then call setTimeout again.