Refresh an instantiation of p5 - p5.js

I have multiple instantiations of sketches in my document. How do I actually rerun specific instantiations with a screen refresh?
Assuming I have:
function buildSketch(){
var sketch1 = function(sketch){
sketch.setup = function(){
//Do my thing
}
}
new p5(sketch1);
}
function buildSecondSketch(){
var sketch2 = function(sketch){
sketch.setup = function(){
//Do my thing
}
}
new p5(sketch2);
}
I know that if I attach the sketch to the window object, I can the refresh, but this seems... hacky e.g:
function buildSecondSketch(){
window.sketch = sketch // Adding this seems to help
var sketch2 = function(sketch){
sketch.setup = function(){
//Do my thing
}
}
new p5(sketch2);
}
And then I would just:
sketch.setup()
Which works. But I have no idea why this works.

You should not call the setup() function yourself.
The simplest thing to do might be to add a refresh() function to each of your sketches. This function would sipmly reset the state of your sketch by setting any sketch-level variables back to their original values. Then just call that function. This is basically what you're doing by calling setup() yourself, but avoids you short-circuiting P5.js's internal automatic function calling.
Either way, you have to keep around a reference to the sketch variables. You could do that using window.sketch, which is just creating a global variable, or you could declare them outside your buildSketch() functions.
You could also get rid of the old p5 instances and reinstantiate them, but that would require keeping around a reference to each p5 instance.

Related

How do I call a javascript function from Go/WASM using Invoke that acts upon a js.Value?

I need to check for fullscreen support with my Go WASM Canvas project, before switching to fullscreen mode. I have the following code so far:
var fullscreenFunc js.Value
var fullscreenNotSupported bool
set with the following logic:
fullscreenFunc = app.Get("requestFullscreen")
if fullscreenFunc.IsUndefined() {
fullscreenFunc = app.Get("mozRequestFullScreen")
if fullscreenFunc.IsUndefined() {
fullscreenFunc = app.Get("webkitRequestFullscreen")
if fullscreenFunc.IsUndefined() {
fullscreenFunc = app.Get("msRequestFullscreen")
if fullscreenFunc.IsUndefined() {
fullscreenNotSupported = true
println("Fullscreen not supported")
}
}
}
}
I was expecting to be able to call the correct function with js.Invoke, but I see no way to tell the Invoke upon which object the call should be made. My 'app' value is being interpreted just as a param.
func Fullscreen(app js.Value) {
if fullscreenNotSupported {
return
}
fullscreenFunc.Invoke(app)
}
resulting in:
panic: JavaScript error: 'mozRequestFullScreen' called on an object that does not implement interface Element.
So am I correct in my thinking that the only way I can call the correct method, is not to store the Function, but to store a string of the function name, and then 'invoke' / 'call' it using the following approach?
app.Call(fullscreenFunctionNameString)
It feels like I misunderstood the purpose of Invoke. Is it only for js.Global() type calls?
[edit] Using 'Call', at least it seems possible to derive the function name without having to repeat the above browser specifics:
fullscreenFunctionName = fullscreenFunc.Get("name").String()
app.Call(fullscreenFunctionNameString)
It doesn't answer the question, but is probably of help to someone trying to do the same.
The arguments to invoke get turned into arguments for the javascript function it wraps. Since those fullscreen functions don't need any arguments, I think you might just need to change:
fullscreenFunc.Invoke(app)
To:
fullscreenFunc.Invoke()
...assuming app is the same JS element in both places. If not your Call solution is probably your best bet.

google.picker.DocsUploadView().setParent('XXXX') issue

Trying to get some help with this code block.
My script first looks for a specific folder and if it exists the pass the id of the folder to the google.picker.DocsUploadView(). When I hard-code the value of setParent to 'gdfid', everything works well. On the other hand, I need the code to be parameterized.
thanks in advance for any assistance
Pete
here's my code:
var gdfid;
function createPicker() {
if (pickerApiLoaded && oauthToken) {
gapi.client.drive.files.list({
"corpora": "user",
"spaces": "drive",
"fields": "files(id,name)",
"q": "name = 'myUploads"
}).then(function(response) {
console.log( response.result.files.length );
if (response.result.files.length > 0) {
console.log( response.result );
gdfid = response.result.files[0].id;
}
//alert('Folder ID: ' + gdfid);
});
var picker = new google.picker.PickerBuilder().
setTitle('Upload to myPratt Folder').
enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
enableFeature(google.picker.Feature.NAV_HIDDEN).
addView(new google.picker.DocsUploadView().
setIncludeFolders(false).
setParent('gdfid')). //tried with and without quotes
setOAuthToken(oauthToken).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
It's probably the .then{} promise code block. I've had lots of trouble with them. The problem is that the .then{} code block has a closed scope.
When you assign gdfid = response.result.files[0].id; it's assumed that it is changing the global variable. But it isn't. It's only creating a local version of gdfid.
I ran around in circles myself for ages trying to figure out how to save external state information from within a .then{} block. Any possible solutions I came up with, were invariably no better than the callback hell that promises were supposed to solve in the first place. I even had problems returning objects out from it. I think the problem is that a .then{} block needs to run from a returned promise. Promises are actually functions earmarked to run in the future. They are subject to scoping restrictions, because they cannot make assumptions about the state of code outside the function. And they only pass object/variables a certain way. Trying to assign globals or returning data the regular way, from inside the .then{} block, is fraught with problems. It will often leave you tearing your hair out.
Try refactoring your code into a function with async/await, and use a try-catch statement to capture promise fails (Note: The try-catch statement still suffers from the global variable isolation problem, but at least it seems to be solely within the catch block. This is only an issue when an error occurs). I find async await much cleaner and easier to understand, and the scoping of variables works more intuitively.
In your case you could rewrite the code thus:
function async createPicker() {
var gdfid;
if (pickerApiLoaded && oauthToken) {
try {
var response = await gapi.client.drive.files.list({
"corpora": "user",
"spaces": "drive",
"fields": "files(id,name)",
"q": "name = 'myUploads"
});
console.log( response.result.files.length );
if (response.result.files.length > 0) {
console.log( response.result );
gdfid = response.result.files[0].id;
}
//alert('Folder ID: ' + gdfid);
var picker = new google.picker.PickerBuilder()
.setTitle('Upload to myPratt Folder')
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.addView(new google.picker.DocsUploadView()
.setIncludeFolders(false)
.setParent(gdfid)) //tried with and without quotes
.setOAuthToken(oauthToken)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
} catch (e) {
console.log("Error displaying file list");
}
};
}
The only real difference here, is the await in front of the gapi.client.drive.files
function forces the code to wait for a callback to assign the response variable. This is not too much of a slowdown issue when running single popup UI elements that the user interacts with.
The gdfid variable is no longer global. In fact you don't even need it. You could setParent directly from the response variable.

When to use asObservable() in rxjs?

I am wondering what is the use of asObservable:
As per docs:
An observable sequence that hides the identity of the
source sequence.
But why would you need to hide the sequence?
When to use Subject.prototype.asObservable()
The purpose of this is to prevent leaking the "observer side" of the Subject out of an API. Basically to prevent a leaky abstraction when you don't want people to be able to "next" into the resulting observable.
Example
(NOTE: This really isn't how you should make a data source like this into an Observable, instead you should use the new Observable constructor, See below).
const myAPI = {
getData: () => {
const subject = new Subject();
const source = new SomeWeirdDataSource();
source.onMessage = (data) => subject.next({ type: 'message', data });
source.onOtherMessage = (data) => subject.next({ type: 'othermessage', data });
return subject.asObservable();
}
};
Now when someone gets the observable result from myAPI.getData() they can't next values in to the result:
const result = myAPI.getData();
result.next('LOL hax!'); // throws an error because `next` doesn't exist
You should usually be using new Observable(), though
In the example above, we're probably creating something we didn't mean to. For one, getData() isn't lazy like most observables, it's going to create the underlying data source SomeWeirdDataSource (and presumably some side effects) immediately. This also means if you retry or repeat the resulting observable, it's not going to work like you think it will.
It's better to encapsulate the creation of your data source within your observable like so:
const myAPI = {
getData: () => return new Observable(subscriber => {
const source = new SomeWeirdDataSource();
source.onMessage = (data) => subscriber.next({ type: 'message', data });
source.onOtherMessage = (data) => subscriber.next({ type: 'othermessage', data });
return () => {
// Even better, now we can tear down the data source for cancellation!
source.destroy();
};
});
}
With the code above, any behavior, including making it "not lazy" can be composed on top of the observable using RxJS's existing operators.
A Subject can act both as an observer and an observable.
An Obervable has 2 methods.
subscribe
unsubscribe
Whenever you subscribe to an observable, you get an observer which has next, error and complete methods on it.
You'd need to hide the sequence because you don't want the stream source to be publicly available in every component. You can refer to #BenLesh's example, for the same.
P.S. : When I first-time came through Reactive Javascript, I was not able to understand asObservable. Because I had to make sure I understand the basics clearly and then go for asObservable. :)
In addition to this answer I would mention that in my opinion it depends on the language in use.
For untyped (or weakly typed) languages like JavaScript it might make sense to conceal the source object from the caller by creating a delegate object like asObservable() method does. Although if you think about it it won't prevent a caller from doing observable.source.next(...). So this technique doesn't prevent the Subject API from leaking, but it indeed makes it more hidden form the caller.
On the other hand, for strongly typed languages like TypeScript the method asObservable() doesn't seem to make much sense (if any).
Statically typed languages solve the API leakage problem by simply utilizing the type system (e.g. interfaces). For example, if your getData() method is defined as returning Observable<T> then you can safely return the original Subject, and the caller will get a compilation error if attempting to call getData().next() on it.
Think about this modified example:
let myAPI: { getData: () => Observable<any> }
myAPI = {
getData: () => {
const subject = new Subject()
// ... stuff ...
return subject
}
}
myAPI.getData().next() // <--- error TS2339: Property 'next' does not exist on type 'Observable<any>'
Of course, since it all compiles to JavaScript in the end of the day there might still be cases when you want to create a delegate. But my point is that the room for those cases is much smaller then when using vanilla JavaScript , and probably in majority of cases you don't need that method.
(Typescript Only) Use Types Instead of asObservable()
I like what Alex Vayda is saying about using types instead, so I'm going to add some additional information to clarify.
If you use asObservable(), then you are running the following code.
/**
* Creates a new Observable with this Subject as the source. You can do this
* to create customize Observer-side logic of the Subject and conceal it from
* code that uses the Observable.
* #return {Observable} Observable that the Subject casts to
*/
asObservable(): Observable<T> {
const observable = new Observable<T>();
(<any>observable).source = this;
return observable;
}
This is useful for Javascript, but not needed in Typescript. I'll explain why below.
Example
export class ExampleViewModel {
// I don't want the outside codeworld to be able to set this INPUT
// so I'm going to make it private. This means it's scoped to this class
// and only this class can set it.
private _exampleData = new BehaviorSubject<ExampleData>(null);
// I do however want the outside codeworld to be able to listen to
// this data source as an OUTPUT. Therefore, I make it public so that
// any code that has reference to this class can listen to this data
// source, but can't write to it because of a type cast.
// So I write this
public exampleData$ = this._exampleData as Observable<ExampleData>;
// and not this
// public exampleData$ = this._exampleData.asObservable();
}
Both do the samething, but one doesn't add additional code calls or memory allocation to your program.
❌this._exampleData.asObservable();❌
Requires additional memory allocation and computation at runtime.
✅this._exampleData as Observable<ExampleData>;✅
Handled by the type system and will NOT add additional code or memory allocation at runtime.
Conclusion
If your colleagues try this, referenceToExampleViewModel.exampleData$.next(new ExampleData());, then it will be caught at compile time and the type system won't let them, because exampleData$ has been casted to Observable<ExampleData> and is no longer of type BehaviorSubject<ExampleData>, but they will be able to listen (.subscribe()) to that source of data or extend it (.pipe()).
This is useful when you only want a particular service or class to be setting the source of information. It also helps with separating the input from the output, which makes debugging easier.

ReSharper won't convert functions to lambda expressions if they contain "this"

Resharper presents a very helpful option for callback functions that are written in conventional JavaScript to convert them to lambda expressions.
I use it all the time. However, it doesn't seem to give the option if there's a reference to this inside the function.
Example:
// ReSharper will convert this function:
setTimeout(function() {
console.log("This one gives me the option to convert!");
});
// ReSharper will NOT convert this function:
setTimeout(function() {
console.log("This one doesn't!");
this.willConvert = false;
});
// This is what it looks like after converted
setTimeout(() => {
console.log("This one has been converted");
});
Is there a way to change an option in ReSharper to give this option more liberally?
I'm not sure, but I suspect this is because it's not a clean refactoring if this is present. The lambda syntax changes what this means. In your example, the function passed to setTimeout has this set to the global object. If you convert it to an arrow function, this changes to be the same this as where the function is declared (in this particular case, that looks like the global object again, but in other cases it could be a surrounding function, etc).
If ReSharper suggested this change, it would be too easy to introduce a breaking change.
Please try this:
setTimeout(() => {
var self = this;
console.log("This one doesn't!");
self.willConvert = false;
});

Asynchronous image loading in AS3

I understand that images are to be loaded asynchronously in AS3, and that that synchronisation should be handled using events and event listeners.
So, in a simple case, it would look like this:
var loader : Loader = new Loader();
var im_file: URLRequest = new URLRequest ("imfile.png");
loader.load(im_file);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loading_complete);
function loading_complete (e : Event) : void
{ // ... do smt with your loaded data // }
What I want to do is have a PreLoader class that will load all the images I need beforehand.
In that case, how do I let all the other classes know when the loading is done?
Do I dispatch events? What is the best practise in this case?
Thanks in advance,
Praskaton
Most likely you want to create a queue and add your image paths to the queue. Then after each image is done loading, you proceed to the next item in the queue. When all images are loaded, you dispatch a COMPLETE event or something similar to let your app know it's all done.
Check QueueLoader or Casalib for how they implement single or bulk image loading.
Adding to the answer that #Boon provided, this is how you could go about the actual setting up of the image queue.
Firstly, you need a list that will store all of the images that still need to be loaded. This makes it easy for you to define as many images as you want. It can be the 'queue':
var queue:Array = [
"http://interfacelift.com/wallpaper/previews/03177_orionnebulaintheinfrared#2x.jpg",
"http://interfacelift.com/wallpaper/previews/03175_purpleclouds#2x.jpg",
"http://interfacelift.com/wallpaper/previews/03173_goodmorning2013#2x.jpg"
];
The next thing to do is set up what I would call the 'core' method of what we're doing. It will handle loading the next image as well as notifying us when the queue is empty. It looks something like this:
function loadNext():void
{
if(queue.length > 0)
{
// Notice here that we use .pop() on the queue, which will select and
// remove the last item from queue.
var req:URLRequest = new URLRequest( queue.pop() );
var photo:Loader = new Loader();
photo.load(req);
photo.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
}
else
{
// The queue is finished - dispatch an event or whatever you fancy to
// let the rest of the application know we're done here.
trace("Queue finished.");
}
}
And then of course our listener function to deal with the completion of loaded images. Notice here that we call loadNext() - this is the key to beginning the load of the next image in the queue only once the currently loading image has finished.
function loadComplete(e:Event):void
{
addChild(e.target.content as Bitmap);
// Begin loading next image in the queue.
loadNext();
}
And to start the process we of course just use this, which will either immediately notify us that the queue is finished if it's empty, or start loading the images in sequence.
// Start loading the queue.
loadNext();
Additional / tidy up:
If you want to be able to recycle this code or just tidy up, you can easily make this into a class. The class could be called ImageQueue and its structure will contain the above queue array, loadNext() method and loadComplete() method. It can also have an add() method for adding images to the queue initially in a cleaner manner.
Here is the foundation of that class, which you can finish up if you're interested:
public class ImageQueue
{
private var _queue:Array = [];
public function add(image:String):void{ }
public function loadNext():void{ }
private function _loadComplete(e:Event):void{ }
}

Resources