# Help extending p5 and dependencies in web dev

**URL:** <https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421>\
**Category:** Coding Questions\
**Created:** [May 14, 2024, 12:34am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421 "2024-05-14T00:34:58Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 12:34am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/1 "2024-05-14T00:34:58Z")

</div>

I’m trying a big project, at least for my skills.  
I’ll reduce the question in a moment, but let me give a little context first.  
I have a server, in node, getting data from api and serving my client.  
Client side I’m building some basic html. A header, a simple html navbar, and a footer. between those two, a canvas.

I’m not sure how to handle dependencies, it’s being a headache.  
But i got everything working (until now) by this setup:

`P5js` is imported from CDN via a `script` tag in `index.html`  
I got a `entry.js`, linked from `index.html` via a`script` tag that has a `type="module" ` property. This is the only way I found to make `import CoolClass from `./uorModules/‘CoolClass.mjs’` work.

It does work.

Cool.

So now how to access p5, globalMode? Well I got code for talking to the server, and data to be passed to my sketch. A little trial and error, i figured out that I should use instance mode. I don’t remember anymore, but in Global mode I got some error (but then again, I might have chosen poorly, and my erro could be some where else.).  
Anyway that how I was working.

```auto
// som e talking to the server.
// await answer
//runP5()

import Deputado from './ourModules/Deputado.mjs';
import CsDeputado from './ourModules/CsDeputado.mjs';
import { colors } from './ourModules/colors.mjs'
import { p5Singleton } from './ourModules/p5Singleton.mjs';
import Grid from './ourModules/Grid.mjs'

let deputados = [];
let lastUpdate = '';
let initialData = []

//The singleton instance
let grid;

// == == == == == 
function getInitialData() {
    axios.get('/api/start')
        .then(response => {
            // Handle success
            console.log('Data received from server:');
            initialData = response.data.deputados
            console.log("Hereby", initialData);
            const lastUpdate = new Date(response.data.lastUpdate);
            const formattedDate = lastUpdate.toLocaleDateString(undefined, {
                day: '2-digit',
                month: '2-digit',
                year: '2-digit'
            });
            const formattedTime = lastUpdate.toLocaleTimeString(undefined, {
                hour: '2-digit',
                minute: '2-digit',
                hour12: false
            });
            const formattedDateTime = `${formattedDate} as ${formattedTime}`;
            document.getElementById('ultima').textContent = `dados atualizados em: ${formattedDateTime}`
            runP5();
        })
        .catch(error => {
            // Handle error
            console.error('There was a problem with the fetch operation:', error);
        });

}
//call it
getInitialData();

function runP5() {
    const s = (p) => {
        p.preload = function() {
        }

        p.setup = function() {}; // === === === --- -> eof setup

        //draw
        p.draw = function() {
        }; // === === === --- -> eof draw

        p.windowResized = function() {
            resetCnv();
        };

        // EOF P5 default functions
        // === === == === === == === === ==

        // === === == === === == === === ==
        // other functions and objects using p5 
        // vvvv ====== ==== vvvv ==== ====== vvvv

        function calcCnvHeight() {
            
        }
        function resetCnv() {
           
        }
        function displaySorted(field) {
           
        }

    }; // === === === === === === === ---- -> end of 's' (instance of p5)

    let myp5 = new p5(s);
}

        // === === == === === == === === ==
        //some classes using p5 
        // vvvv ====== ==== vvvv ==== ====== vvvv

```

But them things grown and I start needing a lot of classes to have things organized, and making all this code inside this function in just one file is… well… not ideal at least.  
Passing ref to p5 in every object or a static reference, was my next choice, but then I’m writing code like `SomeCoolClass.p5.createVector(x, y)`.

I tried a Singleton.

```auto
// p5Singleton.mjs
const p5Singleton = {
    p5Instance: null,
    setInstance: function(p) {
        this.p5Instance = p;
    },
    getInstance: function() {
        return this.p5Instance;
    }
};

export { p5Singleton };

```

than in `entry.mjs`

```auto
import { p5Singleton } from './ourModules/p5Singleton.mjs';
unction runP5() {
    console.log("Im in!")
    const s = (p) => {
        //asap set the p5 Singleton
        p5Singleton.setInstance(p);
// more code... blah

```

and in classes, now in their own file `.mjs`

```auto
export default class CsomeClass {
            constructor(obj) {
                // the Singleton instance
                this.p = p5Singleton.getInstance();
                this.id = obj.id;
                this.nome = obj.nomeEleitoral;
        //blah...
       // and code in the class using p5 goes like
       this.p.rect() /// not really better anyway

```

and then … well I got some code I’ve wrote before, using a different setup that do extends p5.Vector.  
In thatproject I got 4 files for my classes all imported as `script` tags in `index.html` without `'module'`, my sketch as well was a tag and in Global mode. and that worked also. Nothing imports or exports nothing. The class that extends p5 was like this:

```auto
class Gpoint extends p5.Vector {
        constructor(x, y) {
                //lets base it in p5Vector
                super(x, y);
                //several.. this is the original fixed point, not used yet					
                this.fixed_point = createVector(x, y)
                    //the adjusting point coordinates	
                this.gpoint = createVector(x, y);
                // anchor point of the window at creation time - to calc proportions			
                this.origin = createVector(0, 0);
                //the size of window. passin 1 as I'm going to divide by it: https://github.com/processing/p5.js/issues/5821
                // WINDOW SIZING !!			
                this.size = createVector(windowWidth, windowHeight, 1);
                //the ratio of the point to window size
                this.ratio = Gpoint.sub(this.gpoint, this.origin).div(this.size);
                //those so we can use it just as p5Vector, but maybe they just should replace gpoint
                this.x = this.gpoint.x;
                this.y = this.gpoint.y;
                //work arround fo rthe same bug https://github.com/processing/p5.js/issues/5821
                this.z = 1;

                return this;
            } // constructor

        // make from p5Vector
        static make_from_vector(v) {
            return new Gpoint(v.x, v.y);
        }

```

well I managed to use imports and exports so in my new setup `entry.js` sees evertyhing. (there are more classes involved. But when I run everything `GPoint` complains ` **createVector is not defined** `. If I `console.log(p5) from the line above the one throwing the error, i get the p5 obj…

So …  
GRRRRRRR  
sorry…

Than I said. ok I/m going global mode! But for that i must take the`type="module" from script tag and then all my imports stop working again. omg should i go for having all classes linked from a specific `script` tag in html and use Global.

well I’m lost.  
any insight will help me

ps: perhaps a singleton instance Gpoint?

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 2:24am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/2 "2024-05-14T02:24:23Z")

</div>

Updates, but still the question.

I managed to get everything working again via the singleton.  
thank chatgpt to refactoring help. great use for it.

The craziest thing is I call some `static` `p5.Vector.sub()`. And I need to do this call just like that. So i have a global object anyway? Why all this trouble any way rsrsrs.  
gonna keep testing.

update2:

Just tested. changing all calls from `p.strokeWeight()` to `p5.strokeWeight()`  
did not worked.

`Grid.mjs:282 Uncaught TypeError: p5.strokeWeight is not a function`  
but using the singleton and the direct call for the static version works…

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [May 14, 2024, 2:40am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/3 "2024-05-14T02:40:52Z")

</div>

Here’s a simple template that makes p5 globally available, but still controls when p5 is instantiated:

* * *

## index.html:

```auto
<script defer src=//cdn.JsDelivr.net/npm/p5></script>
<script type=module src=index.mjs></script>

```

* * *

## index.mjs:

```js
import runSketch from './sketch.mjs';
runSketch(); // Invoke this after all the rest is ready!

```

* * *

## sketch.mjs:

```js
export default function runSketch() {
  // Make p5.js callbacks globally visible:
  globalThis.preload = preload;
  globalThis.setup = setup;
  globalThis.draw = draw;
  globalThis.windowResized = windowResized;

  globalThis.mocha = 'Hack to block p5.js auto global instantiation.';
  p5.instance || new p5; // Globally instantiate p5.js if it hasn't already.
  globalThis._setupDone = void 0; // Suppress duplicate imported warning.
}

function preload() {
}

function setup() {
}

function draw() {
}

function windowResized() {
}

```

* * *

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 2:44am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/4 "2024-05-14T02:44:19Z")

</div>

Hey @GoToLoop, thanks. I was hoping for your help 🙂

And how would I use it in others files? The classes?  
Also, would I be able to use import statments in thi ssketch file?  
like htis:  
`import Gpoint from './Gpoint.js'`

probably in index.mjs would be fine, right?

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [May 14, 2024, 2:47am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/5 "2024-05-14T02:47:36Z")

</div>

Both are “.mjs” extension files, which have support for keywords `import` & `export`.

The idea is to only invoke **runSketch()** after the rest of your other libraries/modules have been properly initialized.

Just 1 “.mjs” file needs to be present in “index.html”; which in my template is called “index.mjs”.

That entry file “index.mjs” should be responsible to `import` everything else.

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 2:48am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/6 "2024-05-14T02:48:21Z")

</div>

this is my directory:

```auto
├── lastUpdateDate.json
├── lastestData.json
├── package-lock.json
├── package.json
├── public
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── entrada.mjs
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── images
│ │ ├── fotoPlaceHolder.jpg
│ │ └── photoPlaceHolder.jpg
│ ├── index.html
│ ├── ourModules
│ │ ├── CsDeputado.mjs
│ │ ├── Deputado.mjs
│ │ ├── Detalhes.mjs
│ │ ├── Gpoint.js
│ │ ├── Grid.mjs
│ │ ├── Panel-class.js
│ │ ├── Panel.js
│ │ ├── arrayIO.js
│ │ ├── colors.mjs
│ │ └── p5Singleton.mjs
│ ├── site.webmanifest
│ └── style.css
├── server.mjs
├── servidor_app.sublime-project
└── servidor_app.sublime-workspace

```

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 2:50am UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/7 "2024-05-14T02:50:07Z")

</div>

I see, will try this approach tomorrow having Global mode would be cool…  
thanks man.

Will test and ask again later.

thanks

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 1:51pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/8 "2024-05-14T13:51:46Z")

</div>

@GoToLoop Help me understand this, will you?  
The sketch.mjs. seems to work fine in global mode as per your suggestion.  
How would I use the global instance in my classes.  
I thought I wouldn’t need the singleton passing around anymore.  
but…  
ps: my files actually are named:  
index.mjs =\> entry.mjs  
sketch.mjs =\> globalP5.mjs

```auto
// in CsDeputados.mjs
export default class CsDeputado {
            constructor(obj) {
                console.log(p5); // here i got p5 as in the attached image
                this.id = obj.id;
                this.nome = obj.nomeEleitoral;
                this.siglaPartido = obj.siglaPartido;
                this.siglaUf = obj.siglaUf;
                this.imageB64 = obj.imageB64;
                this.image = null; // Initialize as null
                // Load the image
                this.makeP5Image();
                this.dataNascimento = obj.dataNascimento;
                this.badgeWidth = 357;
            }

            makeP5Image() {
                // Using a callback to handle asynchronous loading
                p5.loadImage(this.imageB64, (img) => {// here the error in the image
                    this.image = img; // Set the image when it's loaded
                });
            }

// there's more code below

```

 ![Captura de Tela 2024-05-14 às 10.44.34](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/a/b/aba151a8f443fe5e37c651c6965b56e8ec334f64.png)

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [May 14, 2024, 2:28pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/9 "2024-05-14T14:28:00Z")

</div>

> [@vkbr](#):
>
> How would I use the global instance in my classes.

As the name implies, the “global instance” is globally available after **runSketch()** is invoked!

> [@vkbr](#):
>
> `p5.loadImage(this.imageB64, (img) => {`

p5 has multiple roles: constructor, class & namespace.  
However, it’s not an instance object!  
Instead, the global instance is stored in this static property: p5._instance_

But b/c all p5.js API is globally available after **runSketch()**, we can directly use them w/o the dot notation: `loadImage(this.imageB64, img => {`

Just **loadImage()** is enough to invoke it! 😉

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 3:07pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/10 "2024-05-14T15:07:37Z")

</div>

Man!!! I love you !! 😃  
Thanks a lot. this is like a dream, being able to just use p5.  
no words…  
thanks thanks thanks.

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 3:13pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/11 "2024-05-14T15:13:14Z")

</div>

just merged to main 🙂

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 3:16pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/12 "2024-05-14T15:16:33Z")

</div>

In time, what is this mocha hack? How this works?

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [May 14, 2024, 3:38pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/13 "2024-05-14T15:38:06Z")

</div>

This is from an old code I did:

> [@Rosetta Examples development](https://discourse.processing.org/t/rosetta-examples-development/18945/72):
>
> Well, I did. But it took me more time. mantelpiece_clock I’ve based mine on the Go version (although I barely know anything about that Google language): woozy_face[RosettaCode.org/wiki/Sierpinski\_pentagon#Go](http://RosettaCode.org/wiki/Sierpinski_pentagon#Go) That version uses a fixed palette of 5 primary colors. paintbrush In my sketch conversion I keep track of the current palette's index by returning it at the end of the recursive pentagon() function. triangular_ruler In order to get a free color fill() I’m using beginDraw() + ve…

When I had to lookup how p5js decides to go “Global Mode” and then hack it:

> <https://github.com/processing/p5.js/blob/v1.9.3/src/core/init.js#L27-L38>

As you can notice, if we assign anything [“truthy”](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) to _mocha_, p5.js library will never auto-instantiate p5!

Well, unless we do it ourselves later. 😉

Same for _\_setupDone_, but for suppressing the annoying **warn()** message:

> <https://github.com/processing/p5.js/blob/v1.9.3/src/core/init.js#L16-L25>

---

<div class="post-metadata">

**Author:** ![vkbr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vkbr/32/16844_2.png) [@vkbr](https://discourse.processing.org/u/vkbr)\
**Post date:** [May 14, 2024, 5:19pm UTC](https://discourse.processing.org/t/help-extending-p5-and-dependencies-in-web-dev/44421/14 "2024-05-14T17:19:36Z")

</div>

Cool. thanks for posting.
