We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi everybody, I've been dealing with this problem for some time now and I can't figure out what I'm doing wrong.
I'm building a website with Jekyll. A lot of people will contribute on different javascript sketches that will be displayed on the home page: some of them will be written with P5.js, other with other libraries.
Since I didn't want to load all the libraries on page load I generated a JSON in which I specify the sketch to load and all the associated libraries:
[
{
"author":"Federico Pepe",
"description":"javascript, Processing",
"href":"http://localhost:4000/js/hero/federico.js",
"includes":[
"https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/addons/p5.dom.min.js"
],
"kind":"javascript",
"title":"Lavoro di Federico Pepe"
},
{
"author":"Alka Cappellazzo",
"description":"Processing",
"href":"http://localhost:4000/js/hero/alka.js",
"includes":[
"https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/addons/p5.dom.min.js"
],
"kind":"javascript",
"title":"Lavoro di Alka"
}
]
I then use a random function to select one of the script in that JSON and then, by using jQuery, I load all the scripts asynchronously and in order:
var loadedData;
$(document).ready(function() {
// Load all the scripts in an array
$.get("{{ site.url }}/homepage.json").done(function(data){
loadedData = data;
item = loadedData[Math.floor(Math.random() * data.length)];
deferredLoading();
});
$("#jsRefresh").click(function() {
deferredLoading();
});
});
and then the function:
function deferredLoading() {
$("canvas").remove();
$("#loading").show();
var dfd = $.Deferred();
item = loadedData[Math.floor(Math.random() * loadedData.length)];
for(i in item.includes) {
dfd.done($.get(item.includes[i]).done());
}
$.when(dfd).done(
$.get(item.href).done(function() {
$("#loading").hide();
$(".item-title").html(item.title + ' | ' + item.author);
$(".item-description").html(item.description);
})
)
dfd.resolve();
}
Now the problem is: when I click the link to fire the function deferredLoading() again, the canvas won't update. If I click the link again the canvas will update but with the script loaded previously.
I made some debugging and figured out that it's a P5.js issue because if I put a simple alert() in the JS I'm loading instead of a sketch, it's loaded properly when I click the link to refresh it.
Any help would be really appreciated
Answers
Bump
$.ajaxSetup({ async: false });
. :ar!http://api.jQuery.com/jQuery.getScript/
https://GitHub.com/processing/p5.js/wiki/Instantiation-Cases
https://CDNjs.CloudFlare.com/ajax/libs/p5.js/0.5.5/p5.js
window.mocha || (window.mocha = 'truthy')
window.p5 && (window.setup || window.draw) && new p5;
$("canvas").remove();
as fallback:http://p5js.org/reference/#/p5/remove
Thank you for your reply!
Before your answered I edited the code a little and made it available on jsFiddle so you can fork, edit and run it without having to install jQuery or Jekyll.
The glitch I'm currently having is that the canvas is not loaded on page load (but the script is!) and the refresh is still one click behind.
Now I'm going through what you suggested above to see if I can manage to make it work properly even though, as I said, since I don't know how many script will be written for P5.js I'm considering other ways to display projects on the homepage.
Finally I've made it. In version 2.x.x, I thought $.ajaxSetup({ async: false }); would be enough to make getScript() to load all scripts orderly, 1 by 1.
Unfortunately it didn't make any apparent effect. ~X(
Although file "p5.min.js" was set out to load 1st, "p5.dom.min.js" still finished 1st b/c it was much smaller. :(
However, "p5.dom.min.js" depends on "p5.min.js" to exist 1st. Thus it crashed upfront! :-O
Now the fix is to implement a recursive function + an array w/ all script paths to load at their correct order:
You can check it out the complete program running online here: :-bd
http://CodePen.io/GoSubRoutine/pen/ZBPjdP/left/?editors=101
And below's the complete ordeal: :)>-
"index.html":
"loader.js":
Thank you :)>-
You're a wizard! ^:)^
As you've discovered an ajax request is something that finishes when it's ready :)
...and regardless of what else is happening in your code. As the jQuery docs also make clear, geScripts is just a wrapper around
$.ajax
- so does nothing to ensure multiple getScript calls complete in a specific order: the success callback simply fires when the associated request completes.You could resolve your issue by nesting requests in success callbacks - i.e. wait for a dependency to load before triggering the next request (old-school and clunky); or you could just use a suitable jquery plugin (for example this); or a module/dependency loader (good background article here).
As for holding off execution of p5 scripts - I'd suggest using instance mode if you can; since you can choose to execute the sketch code when you want using
new p5(sketch)
@fedpep, I'm glad it's finally worked for ya! O:-)
But after checking out your "index.html" below:
https://CodiceInutile.github.io/website-dev/index.html
I've noticed this comment there:
* It currently works only with P5.js script.
L-)Although, due to p5.js' "Global Mode" intricacies, I've made some hacks to conditionally deal w/ it, AFAIK those tricks shouldn't get in the way of loading other libraries besides p5.js! :-@
@blindfish, I don't think it is @fedpep who controls how the loaded JS programs are coded: 8-|
As for dynamically loading scripts in a specific order, function loadOrdered()'s already solved that.
It's just 1 single statement! No need for more extra libraries or patches besides jQuery: :)>-
$.getScript(scripts.shift(), scripts.length && loadOrdered || sketchLoaded);