-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.html
551 lines (479 loc) · 24.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Brigade | Event-driven scripting (for Kubernetes)</title>
<meta name="description" content="Brigade is a platform for running scriptable, automated tasks in the cloud. Brigade runs as part of a Kubernetes cluster.">
<meta name="keywords" content="Brigade,Kubernetes,CNCF,Kube,Deploy,CI,CD,Pipeline,Scripting,Automating,Webhook,Events,k8s,Containers,Helm,Simple,Cloud,Application,App,Brigade.sh">
<!-- twitter card-->
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@brigadecore" />
<meta name="twitter:title" content="Brigade | Event-driven scripting for Kubernetes." />
<meta name="twitter:description" content="Brigade is a platform for running scriptable, automated tasks in the cloud. Brigade runs as part of a Kubernetes cluster." />
<meta name="twitter:image" content="https://brigade.sh/logo.png" />
<link rel="icon" type="image/png" href="assets/images/favicon.png">
<!-- load assets -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/scss/brigade-app.scss" />
<!-- BEGIN: Google Analytics -->
<!-- Load google analytics only after user grants consent -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.1/cookieconsent.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.1/cookieconsent.min.js" data-cfasync="false"></script>
<script>
const propertyID = "UA-130516746-5";
var popup;
window.addEventListener('load', function(){
window.cookieconsent.initialise({
type: "opt-in",
theme: "classic",
palette: {
popup: {
background: "#467495",
text: "#fff"
},
button: {
background: "#fd0",
text: "#000"
}
},
onInitialise: function(status) {
// request gtag.js on page-load when the client already consented
if(status == cookieconsent.status.allow) setCookies();
},
onStatusChange: function(status) {
// resquest gtag cookies on a new consent
if (this.hasConsented()) setCookies();
else deleteCookies(this.options.cookie.name)
},
/* enable this to hide the cookie banner outside GDPR regions
law: {
regionalLaw: false,
},
location: true,
},
*/
function (p) {
popup = p;
}
});
});
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', propertyID);
function setCookies() {
var s = document.createElement('script');
s.type = "text/javascript"
s.async = "true";
s.src = `https://www.googletagmanager.com/gtag/js?id=${propertyID}`;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
};
function deleteCookies(cookieconsent_name) {
var keep = [cookieconsent_name, "DYNSRV"];
document.cookie.split(';').forEach(function(c) {
c = c.split('=')[0].trim();
if (!~keep.indexOf(c))
document.cookie = c + '=;' + 'expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/';
});
};
</script>
<!-- END: Google Analytics -->
</head>
<body>
<section class="hero is-danger">
<div class="container">
<div class="hero-body">
<p class="title">
The Brigade project is <em><a href="https://www.cncf.io/archived-projects">archived</a></em>.
<a href="https://github.com/cncf/toc/pull/915">Learn more</a>.
</p>
</div>
</div>
</section>
<nav class="navbar is-transparent" role="navigation" aria-label="main navigation" id="topbar">
<div class="navbar-brand">
<a class="navbar-item" href="https://brigade.sh">
<img src="assets/images/brigade.svg" title="Brigade" alt="Brigade" />
</a>
</div>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarTop">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
<div class="navbar-menu" id="navbarTop">
<div class="navbar-end">
<li class="navbar-item"><a href="https://brigade.sh/" title="Brigade Home">Home</a></li>
<li class="navbar-item"><a href="https://docs.brigade.sh/" title="Brigade Documentation">Docs</a></li>
<li class="navbar-item"><a href="https://blog.brigade.sh/" title="Brigade Blog">Blog</a></li>
<li class="navbar-item"><a href="https://github.com/brigadecore/brigade/" title="Brigade on Github">Github</a></li>
</div>
</div>
</nav>
<div class="row fullheight fullwidth" id="intro">
<div class="columns is-centered">
<div class="column is-two-thirds">
<h1>Brigade is a platform for running
scriptable, automated tasks.</h1>
</div>
</div>
<section class="dots">
<em></em>
<em></em>
<em></em>
<em></em>
<em></em>
<em></em>
<em></em>
<em></em>
<em></em>
<em></em>
</section>
</div>
<section id="code" class="brigade-examples content">
<div class="row">
<div class="columns is-centered retrobox">
<div class="column is-half-tablet">
<div class="carousel-wrapper">
<h2>Simple, powerful scripting</h2>
<p>Each project uses JavaScript or TypeScript to implement dynamic event-handling.</p>
<div class="carousel">
<ul class="slides">
<input type="radio" name="radio-buttons" id="img-1" checked />
<li class="slide-container">
<div class="slide-image">
<pre><em>// Run unit tests for a Github push using TypeScript</em>
import { events, Job } from "@brigadecore/brigadier"
const localPath = "/workspaces/brigade"
events.on("brigade.sh/github", "push", async event => {
let test = new Job("test", "golang:1.17", event)
test.primaryContainer.sourceMountPath = localPath
test.primaryContainer.workingDirectory = localPath
test.primaryContainer.command = ["make"]
test.primaryContainer.arguments = ["test"]
await test.run()
})
events.process()</pre>
</div>
<div class="carousel-controls">
<label for="img-2" class="next-slide">
<span>›</span>
</label>
</div>
</li>
<input type="radio" name="radio-buttons" id="img-2" />
<li class="slide-container">
<div class="slide-image">
<pre>
<em>// Update a MongoDB database using JavaScript</em>
const { events, Job } = require("@brigadecore/brigadier");
events.on("brigade.sh/cli", "exec", async event => {
let mongo = new Job("update-db", "mongo:5.0.3", event);
mongo.primaryContainer.environment = {
MONGO_URL: event.project.secrets.mongoURL,
MONGO_USER: event.project.secrets.mongoUser,
MONGO_PASSWORD: event.project.secrets.mongoPassword
};
mongo.primaryContainer.command = ["bash"];
mongo.primaryContainer.arguments = [
"-c",
dbCmd(event.project, `db.mydb.insert(${event.payload})`)
];
await mongo.run();
});
function dbCmd(p, script) {
return 'mongo ${MONGO_URL}/test -u ${MONGO_USER} -p ${MONGO_PASSWORD}' +
`--eval '${script}'`
}
events.process();
</pre>
</div>
<div class="carousel-controls">
<label for="img-1" class="prev-slide">
<span>‹</span>
</label>
<label for="img-3" class="next-slide">
<span>›</span>
</label>
</div>
</li>
<input type="radio" name="radio-buttons" id="img-3" />
<li class="slide-container">
<div class="slide-image">
<pre>
<em>// Handle a Slack message event in JavaScript</em>
const { events } = require("@brigadecore/brigadier");
events.on("brigade.sh/slack", "hello", async event => {
console.log("Hello " + event.payload + "!");
return "Message received!";
});
events.process();
</pre>
</div>
<div class="carousel-controls">
<label for="img-2" class="prev-slide">
<span>‹</span>
</label>
<label for="img-4" class="next-slide">
<span>›</span>
</label>
</div>
</li>
<input type="radio" name="radio-buttons" id="img-4" />
<li class="slide-container">
<div class="slide-image">
<pre>
<em>// Utilize a shared workspace between jobs in JavaScript</em>
const { events, Job } = require("@brigadecore/brigadier");
events.on("brigade.sh/cli", "exec", async event => {
let job1 = new Job("first-job", "debian:latest", event);
job1.primaryContainer.workspaceMountPath = "/share";
job1.primaryContainer.command = ["bash"];
job1.primaryContainer.arguments = ["-c", "echo 'Hello!' > /share/message"];
await job1.run();
let job2 = new Job("second-job", "debian:latest", event);
job2.primaryContainer.workspaceMountPath = "/share";
job2.primaryContainer.command = ["cat"];
job2.primaryContainer.arguments = ["/share/message"];
await job2.run();
});
events.process();
</pre>
</div>
<div class="carousel-controls">
<label for="img-3" class="prev-slide">
<span>‹</span>
</label>
</div>
</li>
<div class="carousel-dots">
<label for="img-1" class="carousel-dot" id="img-dot-1"></label>
<label for="img-2" class="carousel-dot" id="img-dot-2"></label>
<label for="img-3" class="carousel-dot" id="img-dot-3"></label>
<label for="img-4" class="carousel-dot" id="img-dot-4"></label>
</div>
</ul> <!-- /Slides -->
<ul class="slide-triggers">
<li class="slide-trigger">
<label for="img-1" id="img-dot-1">
<img src="assets/images/ex-icon-01.png" alt="GitHub" /> Unit tests for a GitHub push
</label>
</li>
<li class="slide-trigger">
<label for="img-2" id="img-dot-2">
<img src="assets/images/mongo-14.png" alt="MongoDB" /> Update a MongoDB database
</label>
</li>
<li class="slide-trigger">
<label for="img-3" id="img-dot-3">
<img src="assets/images/ex-icon-05.png" alt="Slack" /> Handle a Slack message
</label>
</li>
<li class="slide-trigger">
<label for="img-4" id="img-dot-4">
<img src="assets/images/ex-icon-02.png" alt="Utilize a shared workspace between jobs" /> Utilize a shared workspace between jobs
</label>
</li>
</ul>
</div>
</div> <!-- /column -->
</div>
<div class="column is-half-tablet code-examples">
<h4>Example use cases:</h4>
<p>Check out <a href="https://docs.brigade.sh/" target="_blank">our docs</a> for more. <img src="assets/images/arrow.png" class="arrow" /></p>
</div>
</div>
</div>
</div>
</section>
<section id="kubernetes" class="brigade-cluster content retrobox">
<div class="row">
<div class="columns is-mobile">
<div class="is-half-desktop column">
<h2>Runs inside your cluster</h2>
<p>By running Brigade as a service inside your <a href="https://kubernetes.io/" target="_blank">Kubernetes</a> cluster, you can harness the power of millions of available Docker images.</p>
<p>Brigade can be used to chain containers together to build processing pipelines.</p>
<ul class="fancy">
<li>Watch for incoming requests from services like GitHub, Docker Hub, and Bitbucket</li>
<li>Run unit tests, process data, and store results</li>
<li>Handle events from services like Slack</li>
</ul>
<iframe width="100%" height="315" class="is-hidden-tablet" src="https://www.youtube-nocookie.com/embed/EqJ9_k56Q3U?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<div class="is-half column is-hidden-touch">
<aside class="cli">
<pre>
<em>// install Brigade using Helm v3.7.0+</em>
export HELM_EXPERIMENTAL_OCI=1
helm install brigade \
oci://ghcr.io/brigadecore/brigade \
--version v2.6.0 \
--create-namespace \
--namespace brigade \
--wait
<em>// check Brigade status</em>
helm get all brigade --namespace brigade
</pre>
</aside>
</div>
</div>
</div>
</section>
<div class="row fullwidth content is-hidden-mobile" id="video">
<div class="columns is-mobile">
<div class="column retrobox is-one-third is-left">
<iframe width="100%" height="315" src="https://www.youtube-nocookie.com/embed/EqJ9_k56Q3U?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<p><a href="https://www.youtube.com/channel/UCjeocwsYKby4BFVT8IWlr-A">See more Brigade videos</a></p>
</div>
</div>
</div>
<div class="row fullwidth content" id="community">
<div class="columns is-mobile">
<div class="column is-offset-one-third-tablet is-half-tablet retrobox">
<h2>Fast & Flexible</h2>
<p>Brigade is designed for teams. It is not a SaaS, nor does it require a legion of domain experts to configure and run it. Instead, it should be easy to install, configure, and maintain.</p>
<p>Brigade is designed to quickly and efficently handle large volumes of events - check out the <a href="https://github.com/brigadecore/brigade-noisy-neighbor">Noisy Neighbor</a> and <a href="https://github.com/brigadecore/brigade-metrics">Brigade Metrics</a> repos, which offer operational and testing insights into Brigade 2.</p>
</div>
</div>
</div>
<div class="row fullwidth" id="v2">
<div class="columns is-left is-mobile content">
<div class="column retrobox retrobox-v2 is-three-quarters-desktop is-full-mobile">
<h2>What's new in Brigade v2?</h2>
<p>Brigade has been <a href="https://github.com/brigadecore/brigade/tree/master/2.0-PROPOSAL">re-designed</a> from the ground up, bringing some exciting features and notable improvements over v1. However, much of Brigade's core functionality remains the same. We're still focused on cloud-native, event-driven scripting. Here are some of the highlights:</p>
<ul class="fancy">
<li>Brigade continues to run on Kubernetes; however, users of Brigade never have to interact with Kubernetes directly.</li>
<li>Brigade offers full management of user and service account authorization/authentication.</li>
<li>Brigade persists all logs to its backing data store so that underlying Kubernetes resources (pods, secrets, etc.) can be removed once completed, leaving the Kubernetes cluster in a clean, manageable state.</li>
<li>Brigade enables high event throughput via its backing message queue -- and substrate resources are distributed fairly so that a project with heavy activity won't block other projects when events come in.</li>
<li>Brigade's Gateway ecosystem is growing rapidly, with gateways for GitHub, DockerHub, CloudEvents and more. Developers can utilize official SDKs to write their own.</li>
</ul>
<p>
Learn more in the <a href="https://docs.brigade.sh/intro/quickstart/">Brigade documentation</a>.
<br><br>
</p>
</div>
<div class="column is-one-quarter">
</div>
</div>
</div>
<!-- pipes animation -->
<div class="pipe-wrapper">
<div id="pipes">
<svg viewBox="0 0 1400 3900" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5"><path d="M1225 25v550c0 50-50 100-100 100h-100c-50 0-100 50-100 100v400c0 50-50 100-100 100H325c-50 0-100 50-100 100v300c0 50 50 100 100 100h350c37.165 0 100 50 100 100v100c0 50-50 100-100 100H475c-50 0-100 50-100 100v100c0 50-50 100-100 100H175c-50 0-100 50-100 100v600c0 50 50 100 100 100h50c50 0 100 50 100 100v600" fill="none" stroke="#ffc233" stroke-width="50"/><path d="M1175 25v450c0 50-50 100-100 100H425c-50 0-100 50-100 100v400c0 50 50 100 100 100h500c50 0 100 50 100 100v100c0 44.415 50 100 100 100h100c52.316 0 100 50 100 100v200c0 50-50 100-100 100h-200c-50 0-100 50-100 100v200c0 50-50 100-100 100H525c-50 0-100 50-100 100v250c0 50 50 100 100 100h200c57.267 0 100 50 100 100v700c0 50-50 100-100 100H375c-50 0-100 50-100 100v150" fill="none" stroke="#f79649" stroke-width="50"/><path d="M1125 25v350c0 50-50 100-100 100H925c-50 0-100 50-100 100v200c0 50 50 100 100 100h300c50 0 100 50 100 100v500c0 50-50 100-100 100H225c-50 0-100 50-100 100v150c0 50 50 100 100 100h350c50 0 100 50 100 100v450c0 50 50 100 100 100h200c50 0 100 50 100 100v500c0 50-50 100-100 100H325c-50 0-100 50-100 100v500" fill="none" stroke="#f36652" stroke-width="50"/><path d="M1075 25v250c0 50-50 100-100 100H275c-50 0-100 50-100 100v400c0 50 50 100 100 100h400c50 0 100 50 100 100v600c0 50 50 100 100 100h100c50 0 100 50 100 100 0 5.947 3.883 63.273 3.883 150 0 50 46.117 100 96.117 100h100c50 0 100 50 100 100v700c0 50-50 100-100 100H275c-50 0-100 50-100 100v750" fill="none" stroke="#a17398" stroke-width="50"/><path d="M1025 25v150c0 50-50 100-100 100H725c-50 0-100 50-100 100v300c0 50-50 100-100 100H125c-50 0-100 50-100 100v500c0 50 50 100 100 100h300c50 0 100 50 100 100v800c0 66.541 50 100 100 100h500c50 0 100 50 100 100v200c0 50-50 100-100 100H625c-50 0-100 50-100 100v400c0 50-50 100-100 100H225c-50 0-100 50-100 100v300" fill="none" stroke="#3d88b0" stroke-width="50"/></svg>
</div>
<script src="https://unpkg.com/[email protected]/dist/tornis.js"></script>
<script type="text/javascript">
window.addEventListener('load', function () {
const stripes = document.getElementsByTagName("path");
function scrollChanged(){
for(var i = 0;i<stripes.length;i++){
stripes[i].style.strokeDashoffset = 7149*(1-(state.scroll.top/(state.size.docY - state.size.y)));
}
}
const { watchViewport } = tornis;
const { getViewportState } = tornis;
const updateValues = ({ size, scroll, mouse, orientation }) => {
state = getViewportState();
if (scroll.changed) {
scrollChanged();
}
};
watchViewport(updateValues);
});
</script>
</div>
<footer>
<div class="row footerwrap">
<div class="columns is-centered">
<div class="column brigade-logo">
<a href="https://brigade.sh/" title="Brigade">
<strong>
</strong><br>
<img src="assets/images/wordmark.svg" title="Brigade" alt="Brigade" class="is-hidden-mobile" />
</a>
</div>
<div class="column">
<h4>Project Links</h4>
<ul>
<li><a href="https://docs.brigade.sh/intro/quickstart/">Brigade Docs</a></li>
<li><a href="https://kubernetes.slack.com/archives/C87MF1RFD/">Slack</a> (#brigade)</li>
<li><a href="https://twitter.com/brigadecore">Twitter</a></li>
<li><a href="https://www.youtube.com/channel/UCjeocwsYKby4BFVT8IWlr-A">YouTube</a></li>
</ul>
</div>
<div class="column">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/brigadecore/brigade/blob/master/code-of-conduct.md">Code of Conduct</a></li>
<li><a href="https://hackmd.io/KyyZMHyzSzGEiQY0ZHPqgw?view">Community Meeting</a></li>
<li><a href="https://github.com/brigadecore/community/blob/main/contributing.md">Contributing</a></li>
</ul>
</div>
<div class="column">
<div class="box cncf">
<p>Brigade is a <strong>Cloud Native Computing Foundation</strong> archived project.</p>
<p><a href="https://www.cncf.io/projects/brigade/" title="Cloud Native Computing Foundation" target="_blank"><img src="assets/images/cncf-color.png" alt="We are a Cloud Native Computing Foundation sandbox project" /></a></p>
</div>
</div>
</div>
<div class="columns is-centered">
<div class="column is-full">
<p>© Brigade Authors 2017 - 2022 | Documentation distributed under <a href="https://creativecommons.org/licenses/by/4.0">CC-BY-4.0</a>. © 2021 The Linux Foundation. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our <a href="https://www.linuxfoundation.org/trademark-usage/">Trademark Usage</a> page.</p>
<hr>
<p>The <a href="https://codepen.io/andybarefoot/pen/WNrYqNj">"Scroll for pipes"</a> background animation is by <a href="https://twitter.com/andybarefoot">Andy Barefoot</a>. Used under <a href="https://blog.codepen.io/documentation/licensing/">MIT License</a>.</p>
</div>
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/foundation.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/plugins/foundation.orbit.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
if(window.localStorage) {
ga('create', 'UA-130516746-5', 'www.brigade.sh', {
'storage': 'none'
, 'clientId': window.localStorage.getItem('ga_clientId')
});
ga(function(tracker) {
window.localStorage.setItem('ga_clientId', tracker.get('clientId'));
});
}
else {
ga('create', 'UA-130516746-5', 'www.brigade.sh');
}
ga('send', 'pageview');
</script>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
}
});
</script>
</body>
</html>