Creating a simple library

Hi, I was trying to create a simple library and ran into problems. This is my html file:

<html> <script src = 'p5.min.js'></script> <script src = 'mosaic.js'></script> <script src = 'sketch.js'></script> <body> <script>setMosaic(true)</script> </body> </html> mosaic.js is the library I am creating.

The content of mosaic.js is :

p5.prototype._isMosaic = false; p5.prototype.setMosaic = function(status){ this._isMosaic = status; console.log('set worked'); };

If I call setMosaic from inside the as shown in the html file, it gives me a function not defined error. But I can call setMosaic() successfully from inside setup() or draw() of sketch.js. Calling setMosaic from outside the sketch works when I define setMosaic in /src/environment/environment.js and build p5.js again.

Is there a way to call setMosaic from outside the sketch?

Answers

  • edited March 2015
    • I'm far from JS expertise but AFAIK, JS' prototype is synonymous of Java's static.
    • As such, we can access them by their "full" name w/o the need to instantiate them 1st like:

    <script>p5.prototype.setMosaic(true)</script>
    <script>p5.prototype.isMosaic = true</script>

    • But also make sure p5 library is fully loaded 1st I guess!

    p5.prototype.isMosaic = false;
    
    p5.prototype.setMosaic = function(status) {
      p5.prototype.isMosaic = status;
      console.log("Mosaic is " + status + " now...");
    }
    
  • Hi,

    I understand that I can access isMosaic using full name. But there are other more complex functions that I'd be using and hence I want to be able to call the outside the sketch.

    Yes, I've made sure that p5.js is loading first. As I said, the strange thing is that setMosaic works if I'm calling it from INSIDE setup() in the sketch. This leads me to think that it is something to do with the namespace. Since setup() is already bound to p5, it can see setMosaic() as well.

    And I did try calling p5.setMosaic() outside the sketch, only to get an error saying that p5 is null/undefined.

  • "AFAIK, JS' prototype is synonymous of Java's static."
    Actually, not, quite the contrary. It is a way to define new fields and methods to an existing object / class (to speak in terms of Java).
    Attaching them to the prototype ensures all instances of this class will get these methods, and they can access the internals of the object, via this.

    By default, in P5.js, I suppose calls like setMosaic() is automatically bound to the P5 instance, that's why it works in the sketch. To make them to work outside of the sketch, you have to declare them globally, or attached to your own object (class).

  • edited March 2015 Answer ✓

    And I did try calling p5.setMosaic() outside the sketch, ...

    • You've forgotten the prototype part: p5.prototype.setMosaic(true);
    • Or even: p5.prototype.isMosaic = true;
    • Since that's a static access, we've gotta use "class_name.prototype.static_property"! :-B
  • edited March 2015 Answer ✓

    Other static examples:

    • p5.prototype.println(p5.prototype.sqrt(49));
    • p5.prototype.println(p5.prototype.TAU);

    In Java Mode that'd be:

    • PApplet.println(PApplet.sqrt(49));
    • PApplet.println(PApplet.TAU);
  • @GotoLoop @PhiLho

    Thank you so much. Using the p5.prototype.setMosaic worked. It was so silly of me to not try calling that considering that I tried every other combination (p5.setMosaic, setMosaic, this.setMosaic) possible. I was under the assumption that once I assign the method to the prototype, I can call it by either this.setMosaic() or p5.setMosaic.

  • edited March 2015

    It was so silly of me to not try calling that...

    Well, the example at my 1st reply it was already so: <script>p5.prototype.setMosaic(true)</script>

    I was under the assumption that once I assign the method to the prototype,
    I can call it by either this.setMosaic() or p5.setMosaic().

    1. this.setMosaic(): Much probably, this refers to the window global variable when inside the ".html".
    2. p5.setMosaic(): it doesn't exist! Property setMosaic is defined within p5's prototype.
    • And p5 behaves as a class and thus still needs to be instantiated in order to get a this.
    • The mechanism in which the JS language allows us to access a prototype's property w/o typing in prototype is awkward to say the least.
    • When we instantiate a "class", the object created from it receives a reference to the "class"'s prototype.
    • When we try to access anything not locally present in the created object, JS then tries to find it from its stored prototype's reference, which points to the original "class".
    • In other words, when we instantiate a "class", none of the original "class"'s prototype is instantiated/recreated.
    • Resultant object merely stores its reference so it can seek and find from within the "class"'s prototype later.
    • Therefore, as I stated before, prototype is indeed a synonym of Java's static keyword! :P
  • edited March 2015

    It is a way to define new fields and methods to an existing object / class...

    • Defining methods, that's true. Defining fields, only static 1s! :-\"
    • Everything defined within prototype isn't instantiated at all!
    • Even in Java, objects store neither methods nor static fields!
    • Only non-static fields (instance variables in OOP terms) actually goes into an object!
    • Everything else stays within the "originator class". No need to replicate redundancy! :-B
    • Both Java's methods & non-static fields are equivalent to JS's prototype properties!

    A silly sample trying to prove that. Dunno whether it's clear or not. :-??
    Go to http://p5js.org/reference/#/p5/clear, click at "Edit", paste it and "Run" it from there: :bz

    p5.prototype.isMosaic = "I'm a static prototyped property and I don't instantiate!!!";
    
    p5.prototype.setMosaic = function(status) {
      // If constructed w/ new, prints undefined.
      // otherwise it prints p5.prototype.isMosaic's content:
      console.log(this.isMosaic);
      
      // Instantiates a new isMosaic property
      // and overshadows p5.prototype.isMosaic:
      this.isMosaic = status;
    
      // Since isMosaic was created bound to an object.
      // JS is gonna find isMosac in loco and won't search for its prototyped version:
      console.log(this.isMosaic + '\n');
    }
    
    // Calls setMosaic as a constructor, wrapping it in a new object:
    var instance = new p5.prototype.setMosaic(true);
    console.log(instance.isMosaic); // prints true.
    
    // But still the static prototyped version of isMosaic retains its value:
    console.log(p5.prototype.isMosaic + '\n'); // prints its original value.
    
    // However, calling setMosaic as a regular function
    // prints 1st the prototyped version of isMosaic:
    p5.prototype.setMosaic(true);
    
    // Curiously now, p5.prototype.isMosaic was modified in its static version:
    console.log(p5.prototype.isMosaic); // prints true now.
    
Sign In or Register to comment.