We are about to switch to a new forum software. Until then we have removed the registration on this forum.
For larger sketches it would be really handy to be able to have parts of it (configuration data, for example) in a separate file. But I haven't found any way to do this. The sketch file doesn't seem to be able to successfully reference another file. I have tried using a script tag on the main html page, followed by the sketch file, but the sketch file can't seem to see it.
I'm not against learning and using something like require.js if that will solve the problem. But because of the nature of p5.js I'm not sure that would be a solution.
Answers
<script></script>
tags work! B-)<script>
tag before going to the other tags.Let's say we have this "sketch.js" file below:
console.log(p5.SoundFile);
works. Whileconsole.log(createElement);
crashes! @-)This is so b/c "libs/p5.dom.js" haven't found variable p5 in the global scope and couldn't inject itself there. That is, "libs/p5.js" hasn't been loaded & run yet! >-)
A more sophisticated and self-contained ".html" file which loads all 3 libs directly from http://p5js.org.
And the "sketch.js" is now merged and inlined in its own
<script></script>
: :ar!no tabs in p5 ?
@Chrisir: Not everyone is using the p5 editor
@TheProcessor: this more or less the first question I had when I rejoined the forum and led to a very useful discussion on 'Class' structure in JS. See: Splitting a project into separate files.
In short: the standard sketch code itself should remain simple enough that you can keep it in a single file. You can easily separate out your other code (e.g. 'Classes') into separate files (for example like this). I'd personally recommend using instance mode as this doesn't pollute the global scope.
requireJS can be made to work with p5js; but felt rather heavy going to me: lots of boilerplate code and it felt fiddly to set up... :/
I never did get round to trying it with Browserify; but have just been playing around with setting up a web dev environment working with Node, Gulp, Babel and SASS with the intent of experimenting with Browserify, Webpack etc. and eventually setting up my own Yeoman generator; with a sub-generator to scaffold p5js and pixijs projects. At some point the project files will go on Github and I'll post a link on the forum ;)
If you're interested in web-dev and not yet using Node based dev tools; they're well worth learning; and Yeoman is a massive help in getting started. In this case generator-dyno would be a good place to start.
blindfish: thanks for the generator-dyno link; I've been using most of those things individually so that will be a help. I've also been looking at your example code.
Playing around with some example code a bit more, it seems that the problem I'm having is a circular dependency issue: the classes have references to p5.js functions, and the sketch (in instance mode) naturally has references to the class files. No matter what order I put the script tags in, I get Uncaught Reference errors. If I eliminate references to p5 functions in the class files the problem goes away, but that is a pretty big limitation to live with. Is there a way to get around this?
Here's a example. With everything in sketch.js it works.
sketch.js
and if I move the ball def into a separate file and keep the function with a p5 reference in the sketch file, it works, like so:
ballDef.js
sketch.js
but if I move the entire ball definition including the p5-referencing function to a separate file, it fails, regardless of the order I load the script files.
var
it is scoped within its function.I think ballDef in my example is in the global scope; the var isn't being declared inside of a function. And removing the var keyword makes no difference. Actually, putting everything in the global namespace (i.e. also removing the encapsulation of the sketch) doesn't fix the problem either.
"index.html":
"sketch.js":
"classes/Animal.js":
"classes/Dog.js":
"classes/Cat.js":
"classes/Lion.js":
Ah! And for those who rather prefer 1 unified & self-sufficient ".html" file, which grabs all libraries remotely, I present ye this: :-h
OK goToLoop, I tried your example locally, and then went back and looked at my code. You are correct: putting the sketch and the class file in the global space does work. Not sure exactly what I was doing wrong before when I tried that. Working code:
index.html
ballDef.js
sketch.js
Thank you very much for your latest example!
I'm still curious if it's possible to do separate class files without putting the sketch in the global namespace.
1st step is to declare variable classes in each ".js" file that needs it, in order to make sure it exists regardless the order they were loaded & run:
var classes
.Next we wrap the once "global" structure body inside an enclosed auto-run anonymous function, having 1 parameter which will carry on the classes reference:
In the ending parens pair there, we pass our namespace classes, in a way that it auto-initializes w/
{}
in case it's stillundefined
ornull
:})(classes || (classes = {}))
And just before
})(classes || (classes = {}))
, inside the wrapped body, we annex the class or function constructor to the passed classes reference inside the enclosing function:Now the final result for the 4 "classes/*.js" files; enjoy: :-bd
"classes/Animal.js":
"classes/Dog.js":
"classes/Cat.js":
"classes/Lion.js":
Now here's the "sketch.js" file which uses
new
for the p5's constructor and passes our sketch as a callback parameter for it: :bz"sketch.js":
Not even the expression
new p5(p => { })
is assigned to a variable.And the whole main sketch lambda is initialized inline as an argument for it.
Therefore no extra global scope pollution! Just variables p5 & classes and nothing more!!! :))
And lastly, our ".html" file. Where everything is loaded & run in the correct order: B-)
"index.html":
And the self-sufficient & unified "index.html" file too: :(|)
Very nice in-depth explanation. I was able to use the pattern successfully by rewriting my ballDef object as a Class. The (c => { }) syntax is new to me though. I tried re-writing it in standard function syntax but without success. Is the => operator vital to making this work?
Your ballDef, as I'm understanding your code, and except its drawing(), was acting more like a C struct.
Since it's got a method, it should indeed become a full class, w/ capitalized B and 1 constructor: $-)
"classes/Ball.js":
That, plus class and many more, is ECMA6 (a.K.a ES2015) JS. ;))
(c => {})(classes || (classes = {}))
is almost the same functionality as the old:(function (c) {})(classes || (classes = {}))
If you still prefer, you can continue using the old way. :-h
Ah yes, ECMA2105...I've done class inheritance before via 'call', like so:
but 'class' and 'extends' is more explicit and less verbose, which is a good thing.
Just wanted to add for anyone reading this discussion, that if you want to add properties directly to a subclass (and not just methods, as in the previous examples) here's a way to do it- add a constructor to the subclass, and have that constructor call super(). Here's an example, using the Animal class from above as the parent class:
@TheProcessor - you might be interested in my attempt at a (slightly opinionated) dev environment for p5js
My experiments with Browserify are proving rather instructive. I'm already regretting my decision not to pursue it more thoroughly in the past... This probably won't come as a surprise to anyone already familiar with Browserify; but here's what it brings to the mix:
I also had a face-palm moment when thinking about use of p5js with VanillaJS. Using instance mode you just need to assign the p5 instance you create to a truly global variable (by attaching to
window
). You then don't need to pass references around your 'classes' (assuming that these will be used only after p5 has instantiated):Very nice blindfish! Using your idea and GoToLoop's syntax I made a version splitting the circle class into its own file.
sketch.js
classes/Circle.js
index.html
is this still the simplest way to subdivide a p5.js sketch in order to have its classes in different files ?
I'm not a native english speaker but that looks like the definition of "cumbersome " ;)
@phoebus, this whole discussion was about having multiple files w/o "polluting" the global scope. ;;)
Or at least, to pollute as few as possible. 3:-O
I don't care any of this! I put everything in global scope. Like this multi-file sketch for example: >:)
https://Bl.ocks.org/GoSubRoutine/f4e383cfc4de8b063df3ee1c3fc66419
@GoToLoop cool !
about the "use strict" though, does it only push me to make my code more rigorous or will it limit my possibilities ?
https://Developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode