run code when a table is ready after $(selector).load(URL) - javascript

I load a table into the document and want to bind a function of footbale to it. But whatever I try (ready,load), I cannot get an onload event to do the job. My workaround is a timeout. That is not pretty. But it proofs that the code has no errors.
<body>
<div id="table_wrapper"></div>
</body>
<script>
$("#stable_wrapper").load("rss2table.php"); // <table id="termine">
setTimeout(() => {
$('#termine').footable({
components: {
filtering: FooTable.MyFiltering
}
});
}, 1000); // min. timeout to run propper
</script>
When I try this
$('#termine tbody').ready(function() {
// Run code
console.log("ready");
$('#termine').footable({
components: {
filtering: FooTable.MyFiltering
}
});
});
I get "ready" in the console, but the rest won't work.
Any ideas how to fix this?

Assuming that footable() is a valid library that you're using, then to fix the problem you should use the callback of load() to execute your logic after the AJAX call completes.
In theory the setTimeout() could do this too, but is not considered the best method as you either make the user wait too long, if the request completes before 1s, or it runs before the request completes and nothing happens. The latter of these seems to be the case here, given the behaviour you describe.
To define the callback, place your logic in a function which you provide as the second argument of load():
$("#stable_wrapper").load("rss2table.php", function() {
$('#termine').footable({
components: {
filtering: FooTable.MyFiltering
}
});
});

Related

Can I make Javascript always call a method after JQuery Load?

We have started using jquery load in our site to load contents into a div rather than re-loading whole page. However in the complete function we have a method that re-applies various bindings. Is it possible to provide load method with a default complete function? So developers don't have to specify it in the jquery load complete function.
As we currently are providing a lot of duplicate complete functions
E.g.
$('#Target').load(callBackRedirect, function () {
ApplyBindings('#Target');
});
These bindings can't be applied using on and need to be re-applied on page loads. We also do some other work that we want to do on every page load.
The answer is no.
You need the callback because that's what the method calls when the request is done.
This works with on method to, you might be doing something wrong out there in the code.
You could create a helper function for this.
function loadSomething(targetElement, uri,callback) {
targetElement.load(uri, callback);
}
loadSomething(
$('myElement'),
'mylink.com/content',
function() {
applyBindings($(this));
}
)
Yes. Check out the list of Global AJAX Event Handlers.
e.g.
$(document).ajaxComplete(function() {
alert('Triggered ajaxComplete handler.');
});
That said, you shouldn't need to reapply your bindings after an AJAX call. If you need to do this, you're probably doing something wrong. Check out jQuery.on, which explains how to bind to content which is added dynamically.
Try $.ajaxSetup:
$.ajaxSetup({
complete: function() {
ApplyBindings('#target');
}
});
EDIT
You could also make a named function like:
var ajaxApplyBindings = function() {
ApplyBindings('#Target');
// anything else...
};
And then pass it to load:
$('#Target').load(callBackRedirect, ajaxApplyBindings);

Run JavaScript code after loading and executing an external script

I would like to dynamically load and execute a 3rd party JavaScript file (from a different domain) and then execute some of my own code after that is done. I could use jQuery's $.getScript:
$.getScript('https://login.persona.org/include.js', function () {
// my code
});
but, according to the jQuery documentation, there is no guarantee that the script has executed by the time the callback is invoked.
What are my options here? I need the most basic solution for one-time use.
Updated
Try
console.log("navigatorId:", navigator.id);
$(window).queue("login", Array(
function(next) {
return $.getScript("https://login.persona.org/include.js").then(next)
}
, function() {
console.log("navigatorId:", navigator.id)
}
)).dequeue("login");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
See .queue()
You can try to add a small timeout to your callback to ensure the script file has executed. For example
$.getScript('https://login.persona.org/include.js', function () {
setTimeout(function(){
// my code
}, 25);
});

Qunit error: assertion outside test context

I've searched all over and it appears this error is due to not using asyncTest properly. However, per the documentation, it appears that I am doing it correctly. I'm guessing I'm missing a small detail somewhere and need an extra pair of eyes...
I'm trying to test some code that makes an ajax request to get a page and then loads it in a lightbox. lightbox-content does not show up in the DOM until after the ajax call has completed and can be displayed. So, I can only check for it in my onComplete call back, which is where I have my test to see if it loaded it correctly.
Here is my code:
asyncTest('mytest', 1, function() {
utils.lightbox.show('/login', {
onComplete: function() {
ok($('#lighbox-content').is(':visible'), 'Lightbox loaded the /login page.');
start();
}
});
});
I get the error:
Uncaught Error: assertion outside test context, was at HTMLDivElement.window.utils
Can anyone see where I'm going wrong?
I agree that your code matches the documentation as far as I can tell.
Update
Even though the documentation doesn't show it, I wonder if you must tell QUnit to stop at some point so it knows to wait after the test function returns. I would think that QUnit assumes this since it's an async test, but it's worth a shot.
asyncTest('mytest', 1, function() {
stop();
...
});
I've been using Sinon.JS to avoid making the AJAX calls in the first place. This has three immediate benefits:
I don't depend on a server to respond to the requests.
I can specify different results for each test.
The tests run much faster.
The mocking can be done at the XMLHttpRequest level or on the jQuery method and is quite easy. Here's an example from one of my tests:
module("geo", {
setup: function () {
this.server = sinon.fakeServer.create();
},
teardown: function () {
this.server.restore();
}
}
test("returns detected ZIP code", function () {
this.server.respondWith("/geo/detect-zip-from-ip",
[ 200, { "Content-Type": "text/html" }, '90210' ]);
geo.detectZip(function (zip) {
assertThat(zip, is('90210'));
});
this.server.respond();
});
I have found a solution for my case, hope your problem has the same source.
Explaining in words:
I have a complicated asynchronous test
I have delayed events, and there are ok and equal assertions inside
Of course, all this is wrapped inside asyncTest
But, when the test is "completed" and I call start(), the event handlers remain there
After calling start(), all further calls of ok inside that asyncTest become illegal
And throw exceptions
I wonder what happens if the number in expect(in your example it's the second parameter) is exceeded. The same exception?
Explaining in code:
asyncTest('mytest', /*1,*/ function() {
function imgLoadedOrFailed (result) {
clearTimeout(imageTimeToLive);
img.off();
ok(result, 'Image in carousel pane has been loaded');
}
var imageTimeToLive = setTimeout(
imgLoadedOrFailed.bind(this, false),
5000),
img = panes[index].find('img:first');
if (img) {
img.on('load', imgLoadedOrFailed.bind(this, true));
img.on('error', imgLoadedOrFailed.bind(this, false));
}
});
// at some point I call: start();
In this example, when I "finish" the test calling start(), the onload and onerror events can still happen.

Execute a javascript function as last inside a page

I need to be sure that a certain script within a page is executed as last.
I thought of using JQuery
$(document).ready( ... )
but if there are more functions of this type, which is actually executed last?
There are many ways to delay the execution of a script.
There is no way to programatically detect all of them.
For a reliable solution you would have to reverse engine the code of each page you care about, figure out what it is doing (and when) and write your delay script specifically for that page. (For a value of "reliable" equal to "until they change the page").
$(document).ready( ... )
is not executed last. The last function executed ( so, after document ready ) is the one(s) from <body onload>.
Example : <body onload="myJSfunction();">
Here, the javascript myJSfunction is executed at the end, after $(document).ready( ... ).
This depends on the order in which you have registered them.
E.g:
$(document).ready( function() { alert("first"); });
$(document).ready( function() { alert("second"); });
$(document).ready( function() { alert("third"); });​
would alert "first" then "second" then "third"
So adding a <script> to the bottom of your page with an $(document).ready( yourfunction ); would suffice.
Theoretically you can do something like this:
// Form array of functions which sould be called with according order
$.readyArray = [function () { ... }, function () { ... }, function () { ... }, ...];
// just execute them in this order when onready event
$(document).ready(function() {
for (var i = 0; i < $.readyArray.length; i++) {
//apply, calls function in current context and pass arguments object
$.readyArray[i].apply(this,[arguments]);
}
});
If refactoring (as Quentin suggested) is not an option (e.g. you are updating a just part of a framework or a product), you can use four approaches, which should give you a good chance achieving what you need. See the following snippets with jQuery:
(1) Wait until 'document' is ready
By document is meant the visible DOM. The script will fire when all it should be rendered really rendered is.
$(document).ready(function() {
console.log('Document is ready.');
});
(2) Wait until top-level JS (Root) 'window' object is ready
The full root object can (will) be ready some time after the DOM is ready.
$(window).ready(function() {
console.log('Window is ready.');
});
(3) Wait until 'window' is fully loaded using .bind
This fires immediately after 'window' is ready, so your script can act on objects (elements) rendered during $(window).ready() above.
$(window).bind("load", function() {
console.log('Window bind is ready.');
});
(4) Wait until Ajax calls are completed
This is as far as you can go - the script will fire when 'window' is ready, loaded, all the code run and all the Ajax actions are completed. Unfortunately, since one Ajax can call another one, it can fire several times during the page load.
$(window).ajaxComplete(function() {
console.log('Window bind is ready, Ajax finished.');
}
In simple Javascript solution, you could call the javascript function at end of your HTML document inside the script tag. This works well when you are not using jQuery.
In case of jQuery you could use load method.The load event is sent to an element when it and all sub-elements have been completely loaded.
For more info look at
http://api.jquery.com/load-event/
Try this,
$(window).bind("load", function() {
//code here
});

jQuery: How can I perform an action after .css has executed?

So my issue is pretty straight forward, since there is seemingly no callback for after a .css is executed, what options do I have for making performing something after a task is done?
I'm creating a simple lightbox, and I need to wait for the center align to finish...
$("#img_lightbox").css("top", top);
So when that completes, I then need to fade in the whole thing, but since there is no callback option (to the best of my knowledge) it will occasionally start fading in before the alignment finishes... how can this prevented?
Any help is appreciated, thank you.
Anything being chained with your jQuery object will execute after the function before it. The easiest way to accomplish what you are asking is with Plugins.
jQuery.fn.myPlugin = function () {
//code to execute
return this;
}
$("#img_lightbox").css("top", top).myPlugin();
You could even write a plugin to execute a custom function, so you do not need to create plugins for every function you might happen to need to run:
jQuery.fn.myCallback= function (callback) {
this.each(function () {
callback.call($(this));
});
return this;
}
$("#img_lightbox").css("top", top).myCallback(function () {
// some code to run where this = $("#img_lightbox")
});
But incase I am still misunderstanding, you may be wanting a callback for your fade function: (otherwise please clarify more)
$("#img_lightbox").fadeIn('slow', function () {
$(this).css("top", top)
});
Adding and removing CSS styles are synchronous functions -- there is no callback because the next statement will be executed once the style has been applied. Rendering of the updated style is slightly different, since that will happen during the next repaint, but unless you're doing some serious number-crunching in your UI code, the difference would be completely unnoticeable. In any case, it would be applied before the 'fading in' starts to happen.
If you're seeing something wrong with your display, I'd suggest that the problem lies elsewhere.
jQuery provides you with a way to tell once the document is "ready" and in the correct state to execute code correctly. Use one of the following:
$(document).ready(function(){
//your code here
});
or the shorter,
$(function(){
//your code here
});
More information at http://api.jquery.com/ready/

Categories

Resources