Looking to add Javascript & CSS to Vanilla? This is the place to start. There's a few different ways to do this, but some are easier and more optimal.
Adding JS inside of an Addon
Before continuing with this, you need to have and addon. If you don't have one already, see the Addon Quickstart Guide.
Using Typescript
Modern Vanilla is built exclusively with Typescript and javascript modules. As such all primary "entry" files must be in typescript.
Don't know how to use Typescript? Luckily typescript is superset of Javascript. That means everything you do in Javascript, can be done exactly the same way in Typescript, there's just some optional extras (types).
Although typescript-specific knowledge isn't required to get started, it offers many benefits, so it's recommended to check out Typescript in 5 Minutes and the Typescript Handbook if you will be building anything complex in Javascript.
1. Creating an Entry Point
Vanilla ships with a built-in build system. You should already have it up and running after the Localhost Configuration Guide.
Note: If you already have a developer build running (with yarn build:dev
), then you need to restart once after creating your new entry and enabling you addon.
First let's make the entry point. There's currently 3 possible entries, and depending which one you choose will affect where the javascript is loaded. This example will target the forum.
addons/fancyaddon/src/scripts/entries/forum.tsx
console.log("Hello Forum");
After you've enabled your addon and restarted the dev build (Or done a full production build), if you navigate to the forum, you should see "Hello Forum" printed in the console.
1.1 Note on Entrypoints
forum.tsx
will affect the community forum - discussions, categories, groups, profiles.admin.tsx
will affect the dashboard.knowledge.tsx
will affect the knowledge base.common.tsx
will apply to all of the above.- DO NOT USE JQUERY IN THESE FILES. It is is not loaded or available in some areas these files are loaded.
- DO NOT CREATE OTHER FILES IN THE
/entries/
THAN THESE.
2. Importing Another File
Generally you don't want to put everything in 1 file. Since Vanilla supports ES Modules, you create other javascript files in your addon and import them, as long as they are in the src/scripts
directory.
Note: Do not put these other files into the entries directory, as this is a special reserved directory for configuring the build system.
Let's say we wanted to add a click handler that makes an alert onto every User's profile photo. We would do it like this:
addons/fancyaddon/src/scripts/userAlerts.ts
export function setupUserAlerts() {
const userImages = document.querySelectorAll(".ProfilePhoto");
userImages.forEach((image) => {
image.addEventListener("click", handleClick);
})
}
function handleClick(e: MouseEvent) {
e.preventDefault();
alert("User was clicked!");
}
addons/fancyaddon/src/scripts/entries/forum.tsx
import { onReady, onContent } from "@library/utility/appUtils";
import { setupUserAlerts } from "../userAlerts";
console.log("Hello Forum");
onReady(setupUserAlerts);
onContent(setupUserAlerts);
So what did we do?
- We made a function in a new file that adds event listeners to user images. (A very simple listener for now).
- We marked the setup function with
export
so it could be imported from another file. - We declared that we wanted this setup to run on the Ready event, and on the Content event.
Callbacks passed to onReady()
will run once the page has loaded.
Callbacks passed to onContent()
will run when extra content is loaded into the page (such as opening a Modal).
Test it out
Now that we've saved these files we should be able to go to any forum page, click a user image, and see our alert appear.
3. Add a node_module
Our previous implementation of adding the user alerts was fine, but it could be improved a bit by using a utility function from one of vanilla's NPM packages. Lets create a package.json
file and add @vanila/dom-utils
so we can use one of it's utilities. This will be added the same way you would add any package from NPM.
Create the package.json
For more information about the package.json file, see the NPM documentation.
addons/fancyaddon/package.json
{
"name": "vanilla-fancyaddon",
"version": "1.0",
"private": true,
"dependencies": {
"@vanilla/dom-utils": "*"
}
}
When adding Vanilla packages, it is best to use the version matching your current Vanilla installation. By using "*" we are signalling to Vanilla that we want to use whatever version is in our current Vanilla version.
Next we need to run the following:
# Go into the vanilla directory
cd vanilla-dir
yarn
Refactoring the userAlerts
Let's refactor our function to use the delegateEvent
utility. It implements Event Delegation in a simple wrapper, similar to JQuery's $.delegate()
.
addons/fancyaddon/src/scripts/userAlerts.ts
import { delegateEvent } from "@vanilla/dom-utils";
export function setupUserAlerts() {
delegateEvent("click", ".ProfilePhoto", (event, clickedElement) => {
event.preventDefault();
alert("User was clicked!");
});
}
addons/fancyaddon/src/scripts/entries/forum.tsx
Since we're delegating the event, we don't have use the onContent()
handler, so we can remove it.
import { onReady } from "@library/utility/appUtils";
import { setupUserAlerts } from "../userAlerts";
console.log("Hello Forum");
onReady(setupUserAlerts);
Test it out
We should see the same behaviour as the previous step after the refactoring.
4. Adding some CSS
Let's add some CSS to our Addon now.
addons/fancyaddon/src/css/fancystyles.css
Note: SCSS files are supported too. Just change the file extension to .scss
.
* {
color: orange !important;
}
addons/fancyaddon/src/scripts/entries/forum.tsx
In order for our CSS to actually be used, we'll need to import it from our entry.
import { onReady } from "@library/utility/appUtils";
import { setupUserAlerts } from "../userAlerts";
// Add the CSS import.
import "../../css/fancystyles.css;
console.log("Hello Forum");
onReady(setupUserAlerts);