diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a645d87
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+public-notepad.txt
+.htaccess
+
+*.mrpack
+*.zip
+
+.well-known/
+videos/
+texturepacks/
+mc-worlds/
+assets/files/
+assets/musics/
\ No newline at end of file
diff --git a/assets/css/errors.css b/assets/css/errors.css
new file mode 100644
index 0000000..878c5cd
--- /dev/null
+++ b/assets/css/errors.css
@@ -0,0 +1,58 @@
+@import 'fonts.css';
+
+body {
+ background-image: url('../images/darkbg.webp');
+ background-size: cover;
+}
+
+#particles-js {
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ z-index: -10;
+ top: 0;
+ left: 0;
+}
+
+button {
+ display: inline;
+ font-family: 'JetBrains Mono', sans-serif, Fallback;
+ font-style: italic;
+ color: green;
+ background-color: transparent;
+ border: 0.01em solid green;
+ margin: 0.1em;
+}
+
+button:hover {
+ color: black;
+ background-color: green;
+ border-radius: 0.25em;
+ font-weight: 900;
+}
+
+button:active {
+ color: green;
+ background-color: white;
+}
+
+error-section {
+ display: block;
+ font-family: 'JetBrains Mono', Fallback, sans-serif;
+ color: green;
+ z-index: 1;
+ border: 3px solid green;
+ width: 50em;
+ margin: 3em auto;
+ padding: 2em;
+ background-color: rgb(15, 15, 15);
+}
+
+error-code {
+ display: inline;
+ font-size: 2em;
+}
+
+error-desc {
+ display: inline;
+}
\ No newline at end of file
diff --git a/assets/css/fonts.css b/assets/css/fonts.css
new file mode 100644
index 0000000..8b0551f
--- /dev/null
+++ b/assets/css/fonts.css
@@ -0,0 +1,64 @@
+/* Meyrin Font */
+@font-face {
+ font-family: 'Meyrin';
+ font-style: normal;
+ font-display: swap;
+ src: url('https://cdn.jsdelivr.net/gh/optional-is/Meyrin@master/formats/Meyrin.woff') format('woff'),
+ /* Modern Browsers */
+ url('https://cdn.jsdelivr.net/gh/optional-is/Meyrin@master/formats/Meyrin.ttf') format('truetype'),
+ /* Safari, Android, iOS */
+ url('https://cdn.jsdelivr.net/gh/optional-is/Meyrin@master/formats/Meyrin.svg#svgFontName') format('svg'),
+ /* Legacy iOS */
+ url('https://cdn.jsdelivr.net/gh/optional-is/Meyrin@master/formats/Meyrin.eot') format('embedded-opentype'),
+ /* IE9 Compatibility Mode */
+ url('https://cdn.jsdelivr.net/gh/optional-is/Meyrin@master/formats/Meyrin.eot?#iefix') format('embedded-opentype');
+ /* IE6-IE8 */
+}
+
+/* JetBrains Mono normal Font */
+@font-face {
+ font-family: 'JetBrains Mono';
+ /* Variable font */
+ font-style: normal;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono@master/fonts/variable/JetBrainsMono%5Bwght%5D.woff2') format('woff2');
+ src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono@master/fonts/variable/JetBrainsMono%5Bwght%5D.ttf') format('truetype');
+}
+
+/* JetBrains Mono italic Font */
+@font-face {
+ font-family: 'JetBrains Mono';
+ /* Variable font */
+ font-style: italic;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono@master/fonts/variable/JetBrainsMono-Italic%5Bwght%5D.woff2') format('woff2');
+ src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono@master/fonts/variable/JetBrainsMono-Italic%5Bwght%5D.ttf') format('truetype');
+}
+
+/* FixedSysExcelsior Font */
+@font-face {
+ font-family: 'FixedSysExcelsior';
+ font-style: normal;
+ font-display: swap;
+ src: url('https://github.com/kika/fixedsys/releases/download/v3.02.9/FSEX302.ttf') format('truetype');
+}
+
+/* InterVariable normal Font */
+@font-face {
+ font-family: InterVariable;
+ font-style: normal;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url('https://rsms.me/inter/font-files/InterVariable.woff2?v=4.0') format('woff2');
+}
+
+/* InterVariable italic Font */
+@font-face {
+ font-family: InterVariable;
+ font-style: italic;
+ font-weight: 100 900;
+ font-display: swap;
+ src: url('https://rsms.me/inter/font-files/InterVariable-Italic.woff2?v=4.0') format('woff2');
+}
\ No newline at end of file
diff --git a/assets/css/index.css b/assets/css/index.css
new file mode 100644
index 0000000..b2c3dcd
--- /dev/null
+++ b/assets/css/index.css
@@ -0,0 +1,25 @@
+.meyrin {
+ font-family: Meyrin, serif;
+ font-size: 1.5em;
+}
+
+.cc-img {
+ height: 22px !important;
+ margin-left: 3px;
+ vertical-align: text-bottom;
+}
+
+.Inter {
+ font-family: InterVariable, sans-serif;
+ font-style: normal;
+ font-weight: 500;
+}
+
+.footer {
+ z-index: 1;
+ border: 3px solid green;
+ width: 25em;
+ padding: 1em;
+ font-size: 1em;
+ margin: 2em auto;
+}
\ No newline at end of file
diff --git a/assets/css/modpacks.css b/assets/css/modpacks.css
new file mode 100644
index 0000000..49ff677
--- /dev/null
+++ b/assets/css/modpacks.css
@@ -0,0 +1,8 @@
+.content {
+ z-index: 1;
+ border: 3px solid green;
+ width: 50em;
+ padding: 1em;
+ font-size: 1.25em;
+ margin: 2em auto;
+ }
\ No newline at end of file
diff --git a/assets/css/redirect-anim.css b/assets/css/redirect-anim.css
new file mode 100644
index 0000000..848f334
--- /dev/null
+++ b/assets/css/redirect-anim.css
@@ -0,0 +1,159 @@
+:root {
+ --b: #262626;
+ --w: #dcdcd2;
+ --s: 2s;
+ /* change speed */
+}
+
+*,
+*:before,
+*:after {
+ box-sizing: border-box;
+ transform-style: preserve-3d;
+}
+
+body {
+ margin: 0;
+ padding: 0;
+ width: 100vw;
+ height: 100vh;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: var(--b);
+}
+
+.content {
+ width: 50vmin;
+ height: 50vmin;
+ text-align: center;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ perspective: 1000vmin;
+}
+
+.bars {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ padding: 6.5vmin 3vmin;
+ animation: mirror1 calc(var(--s) * 2) ease 0s infinite;
+}
+
+.bars+.bars {
+ transform: rotate(90deg) rotateX(180deg);
+ animation: mirror2 calc(var(--s) * 2) ease calc(var(--s) / 2) infinite;
+}
+
+.bar {
+ width: 44vmin;
+ height: 3vmin;
+ margin: 2vmin 0vmin;
+ background: linear-gradient(90deg, #fff0 33%, var(--w) 33% 67%, #fff0 67% 100%);
+ animation: grow var(--s) ease-in-out 0s infinite alternate;
+ background-size: 300%;
+ background-position-x: -203%;
+}
+
+@keyframes mirror1 {
+
+ 0%,
+ 47%,
+ 99.99%,
+ 100% {
+ transform: rotate(180deg) rotateX(0deg);
+ }
+
+ 47.01%,
+ 99.98% {
+ transform: rotate(180deg) rotateX(180deg);
+ }
+}
+
+@keyframes mirror2 {
+
+ 0%,
+ 47%,
+ 99.99%,
+ 100% {
+ transform: rotate(90deg) rotateX(180deg);
+ }
+
+ 47.01%,
+ 99.98% {
+ transform: rotate(90deg) rotateX(0deg);
+ }
+}
+
+@keyframes grow {
+
+ 0%,
+ 25% {
+ background-position-x: -297%;
+ }
+
+ 45%,
+ 55% {
+ background-position-x: -250%;
+ }
+
+ 75%,
+ 100% {
+ background-position-x: -203%;
+ }
+}
+
+.bar:nth-child(2) {
+ animation-delay: calc(var(--s) * -0.02);
+}
+
+.bar:nth-child(3) {
+ animation-delay: calc(var(--s) * -0.04);
+}
+
+.bar:nth-child(4) {
+ animation-delay: calc(var(--s) * -0.06);
+}
+
+.bar:nth-child(5) {
+ animation-delay: calc(var(--s) * -0.08);
+}
+
+.bar:nth-child(6) {
+ animation-delay: calc(var(--s) * -0.1);
+}
+
+.bar:nth-child(7) {
+ animation-delay: calc(var(--s) * -0.12);
+}
+
+.bars:nth-child(2) .bar:nth-child(1) {
+ animation-delay: calc(calc(var(--s) * -0.001) - calc(var(--s) / 2));
+}
+
+.bars:nth-child(2) .bar:nth-child(2) {
+ animation-delay: calc(calc(var(--s) * -0.02) - calc(var(--s) / 2));
+}
+
+.bars:nth-child(2) .bar:nth-child(3) {
+ animation-delay: calc(calc(var(--s) * -0.04) - calc(var(--s) / 2));
+}
+
+.bars:nth-child(2) .bar:nth-child(4) {
+ animation-delay: calc(calc(var(--s) * -0.06) - calc(var(--s) / 2));
+}
+
+.bars:nth-child(2) .bar:nth-child(5) {
+ animation-delay: calc(calc(var(--s) * -0.08) - calc(var(--s) / 2));
+}
+
+.bars:nth-child(2) .bar:nth-child(6) {
+ animation-delay: calc(calc(var(--s) * -0.1) - calc(var(--s) / 2));
+}
+
+.bars:nth-child(2) .bar:nth-child(7) {
+ animation-delay: calc(calc(var(--s) * -0.12) - calc(var(--s) / 2));
+}
\ No newline at end of file
diff --git a/assets/css/redirect.css b/assets/css/redirect.css
new file mode 100644
index 0000000..efcb319
--- /dev/null
+++ b/assets/css/redirect.css
@@ -0,0 +1,31 @@
+@import url('redirect-anim.css');
+
+/* @import is for the animation on the redirect page */
+body {
+ color: white;
+ font-family: 'JetBrains Mono', sans-serif;
+}
+
+a {
+ color: white;
+}
+
+#particles-js {
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ z-index: -999;
+ top: 0;
+ left: 0;
+}
+
+.content {
+ z-index: -998;
+ position: fixed;
+ opacity: 0.25;
+}
+
+p {
+ z-index: 999;
+ position: fixed;
+}
\ No newline at end of file
diff --git a/assets/css/styles.css b/assets/css/styles.css
new file mode 100644
index 0000000..5ccc84a
--- /dev/null
+++ b/assets/css/styles.css
@@ -0,0 +1,81 @@
+@import 'fonts.css';
+
+body {
+ font-family: 'JetBrains Mono', Fallback, sans-serif;
+ color: green;
+ background-image: url('../images/darkbg.webp');
+ background-size: cover;
+}
+
+#particles-js {
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ z-index: -10;
+ top: 0;
+ left: 0;
+}
+
+.fse {
+ font-family: 'FixedSysExcelsior', Fallback, sans-serif;
+}
+
+a {
+ color: green;
+ text-decoration: underline;
+}
+
+.l {
+ text-decoration: underline green;
+}
+
+.qrc {
+ width: 15%;
+}
+
+button {
+ display: inline;
+ font-family: 'JetBrains Mono', sans-serif, Fallback;
+ font-style: italic;
+ color: green;
+ background-color: transparent;
+ border: 0.01em solid green;
+ margin: 0.1em;
+}
+
+button:hover {
+ color: black;
+ background-color: green;
+ border-radius: 0.25em;
+ font-weight: 900;
+}
+
+button:active {
+ color: green;
+ background-color: white;
+}
+
+.italic {
+ font-style: italic;
+}
+
+.desc {
+ font-size: 0.7em
+}
+
+.code {
+ border-color: white;
+ border-width: 0.1em;
+ border-style: solid;
+ background-color: black;
+ color: blue;
+}
+
+.header {
+ z-index: 1;
+ border: 3px solid green;
+ width: 20em;
+ padding: 1em;
+ font-size: 2em;
+ margin: 2em auto;
+}
\ No newline at end of file
diff --git a/assets/icons/base.avif b/assets/icons/base.avif
new file mode 100644
index 0000000..534f228
Binary files /dev/null and b/assets/icons/base.avif differ
diff --git a/assets/icons/base.ico b/assets/icons/base.ico
new file mode 100644
index 0000000..c693250
Binary files /dev/null and b/assets/icons/base.ico differ
diff --git a/assets/icons/sewt.avif b/assets/icons/sewt.avif
new file mode 100644
index 0000000..53054dd
Binary files /dev/null and b/assets/icons/sewt.avif differ
diff --git a/assets/icons/sewt.ico b/assets/icons/sewt.ico
new file mode 100644
index 0000000..54116b6
Binary files /dev/null and b/assets/icons/sewt.ico differ
diff --git a/assets/images/ResponseCode/403.png b/assets/images/ResponseCode/403.png
new file mode 100644
index 0000000..2957559
Binary files /dev/null and b/assets/images/ResponseCode/403.png differ
diff --git a/assets/images/ResponseCode/404.png b/assets/images/ResponseCode/404.png
new file mode 100644
index 0000000..e2d1b29
Binary files /dev/null and b/assets/images/ResponseCode/404.png differ
diff --git a/assets/images/ResponseCode/418.png b/assets/images/ResponseCode/418.png
new file mode 100644
index 0000000..c14bea4
Binary files /dev/null and b/assets/images/ResponseCode/418.png differ
diff --git a/assets/images/ResponseCode/500.png b/assets/images/ResponseCode/500.png
new file mode 100644
index 0000000..e4e2d5d
Binary files /dev/null and b/assets/images/ResponseCode/500.png differ
diff --git a/assets/images/ResponseCode/503.png b/assets/images/ResponseCode/503.png
new file mode 100644
index 0000000..f893e3e
Binary files /dev/null and b/assets/images/ResponseCode/503.png differ
diff --git a/assets/images/ResponseCode/CREDITS.txt b/assets/images/ResponseCode/CREDITS.txt
new file mode 100644
index 0000000..450bd57
--- /dev/null
+++ b/assets/images/ResponseCode/CREDITS.txt
@@ -0,0 +1 @@
+https://github.com/SAWARATSUKI/KawaiiLogos
diff --git a/assets/images/SEWT.webp b/assets/images/SEWT.webp
new file mode 100644
index 0000000..c710262
Binary files /dev/null and b/assets/images/SEWT.webp differ
diff --git a/assets/images/SkyExploreWasTaken.png b/assets/images/SkyExploreWasTaken.png
new file mode 100644
index 0000000..60a6f55
Binary files /dev/null and b/assets/images/SkyExploreWasTaken.png differ
diff --git a/assets/images/SkyExploreWasTaken.webp b/assets/images/SkyExploreWasTaken.webp
new file mode 100644
index 0000000..d7851e9
Binary files /dev/null and b/assets/images/SkyExploreWasTaken.webp differ
diff --git a/assets/images/darkbg.webp b/assets/images/darkbg.webp
new file mode 100644
index 0000000..ad65f43
Binary files /dev/null and b/assets/images/darkbg.webp differ
diff --git a/assets/images/gravatar-qrc.webp b/assets/images/gravatar-qrc.webp
new file mode 100644
index 0000000..5843bf5
Binary files /dev/null and b/assets/images/gravatar-qrc.webp differ
diff --git a/assets/images/twitch-recap-2024.png b/assets/images/twitch-recap-2024.png
new file mode 100644
index 0000000..4a42752
Binary files /dev/null and b/assets/images/twitch-recap-2024.png differ
diff --git a/assets/js/config.js b/assets/js/config.js
new file mode 100644
index 0000000..0ee4442
--- /dev/null
+++ b/assets/js/config.js
@@ -0,0 +1,123 @@
+/* -----------------------------------------------
+/* How to use? : Check the GitHub README
+/* ----------------------------------------------- */
+
+/* To load a config file (particles.json) you need to host this demo (MAMP/WAMP/local)... */
+
+
+
+/* Otherwise just put the config content (json): */
+
+particlesJS('particles-js',
+
+ {
+ "particles": {
+ "number": {
+ "value": 43,
+ "density": {
+ "enable": true,
+ "value_area": 800
+ }
+ },
+ "color": {
+ "value": "#ffffff"
+ },
+ "shape": {
+ "type": "circle",
+ "stroke": {
+ "width": 0,
+ "color": "#000000"
+ },
+ "polygon": {
+ "nb_sides": 5
+ },
+ "image": {
+ "src": "img/github.svg",
+ "width": 100,
+ "height": 100
+ }
+ },
+ "opacity": {
+ "value": 0.5,
+ "random": true,
+ "anim": {
+ "enable": false,
+ "speed": 1,
+ "opacity_min": 0.1,
+ "sync": false
+ }
+ },
+ "size": {
+ "value": 3,
+ "random": true,
+ "anim": {
+ "enable": false,
+ "speed": 40,
+ "size_min": 0.1,
+ "sync": false
+ }
+ },
+ "line_linked": {
+ "enable": true,
+ "distance": 150,
+ "color": "#ffffff",
+ "opacity": 0.5445204668671129,
+ "width": 1
+ },
+ "move": {
+ "enable": true,
+ "speed": 6,
+ "direction": "none",
+ "random": true,
+ "straight": false,
+ "out_mode": "out",
+ "bounce": false,
+ "attract": {
+ "enable": true,
+ "rotateX": 600,
+ "rotateY": 1200
+ }
+ }
+ },
+ "interactivity": {
+ "detect_on": "window",
+ "events": {
+ "onhover": {
+ "enable": true,
+ "mode": "grab"
+ },
+ "onclick": {
+ "enable": false,
+ "mode": "bubble"
+ },
+ "resize": true
+ },
+ "modes": {
+ "grab": {
+ "distance": 251.73215698496793,
+ "line_linked": {
+ "opacity": 0.3399433427762041
+ }
+ },
+ "bubble": {
+ "distance": 167.8214379899786,
+ "size": 3.99574852357092,
+ "duration": 0.39957485235709195,
+ "opacity": 8,
+ "speed": 3
+ },
+ "repulse": {
+ "distance": 200,
+ "duration": 0.4
+ },
+ "push": {
+ "particles_nb": 4
+ },
+ "remove": {
+ "particles_nb": 2
+ }
+ }
+ },
+ "retina_detect": true
+ }
+);
\ No newline at end of file
diff --git a/assets/js/index.js b/assets/js/index.js
new file mode 100644
index 0000000..52becd3
--- /dev/null
+++ b/assets/js/index.js
@@ -0,0 +1,19 @@
+document.addEventListener("DOMContentLoaded", function () {
+ // Sélectionne tous les éléments avec la classe "code"
+ const codeElements = document.querySelectorAll('.blink');
+
+ // Fonction pour alterner la visibilité des éléments
+ function toggleVisibility() {
+ codeElements.forEach(element => {
+ if (element.style.visibility === 'hidden') {
+ element.style.visibility = 'visible';
+ } else {
+ element.style.visibility = 'hidden';
+ }
+ });
+ }
+
+ // Définit l'intervalle de clignotement (par exemple, toutes les 500 ms)
+ setInterval(toggleVisibility, 500);
+});
+document.getElementById("sewt-desc").innerText = "a little > websites > developer."
\ No newline at end of file
diff --git a/assets/js/navigator.js b/assets/js/navigator.js
new file mode 100644
index 0000000..243b950
--- /dev/null
+++ b/assets/js/navigator.js
@@ -0,0 +1,16 @@
+let appCodeName = navigator.appCodeName;
+let appName = navigator.appName;
+let appVersion = navigator.appVersion;
+let language = navigator.language;
+let onLine = navigator.onLine;
+let platform = navigator.platform;
+let product = navigator.product;
+let userAgent = navigator.userAgent;
+document.getElementById("appcodename").innerText = "Browser appCodeName is : " + appCodeName;
+document.getElementById("appname").innerText = "Browser appName is : " + appName;
+document.getElementById("appversion").innerText = "Browser appVersion is : " + appVersion;
+document.getElementById("language").innerText = "Browser language is : " + language
+document.getElementById("online").innerText = "Is the browser online : " + onLine;
+document.getElementById("platform").innerText = "Browser platform : " + platform;
+document.getElementById("product").innerText = "Browser engine name : " + product;
+document.getElementById("useragent").innerText = "Browser user-agent header : " + userAgent;
\ No newline at end of file
diff --git a/assets/js/particles.js b/assets/js/particles.js
new file mode 100644
index 0000000..bf84d81
--- /dev/null
+++ b/assets/js/particles.js
@@ -0,0 +1,1541 @@
+/* -----------------------------------------------
+/* Author : Vincent Garreau - vincentgarreau.com
+/* MIT license: http://opensource.org/licenses/MIT
+/* Demo / Generator : vincentgarreau.com/particles.js
+/* GitHub : github.com/VincentGarreau/particles.js
+/* How to use? : Check the GitHub README
+/* v2.0.0
+/* ----------------------------------------------- */
+
+var pJS = function (tag_id, params) {
+
+ var canvas_el = document.querySelector('#' + tag_id + ' > .particles-js-canvas-el');
+
+ /* particles.js variables with default values */
+ this.pJS = {
+ canvas: {
+ el: canvas_el,
+ w: canvas_el.offsetWidth,
+ h: canvas_el.offsetHeight
+ },
+ particles: {
+ number: {
+ value: 400,
+ density: {
+ enable: true,
+ value_area: 800
+ }
+ },
+ color: {
+ value: '#fff'
+ },
+ shape: {
+ type: 'circle',
+ stroke: {
+ width: 0,
+ color: '#ff0000'
+ },
+ polygon: {
+ nb_sides: 5
+ },
+ image: {
+ src: '',
+ width: 100,
+ height: 100
+ }
+ },
+ opacity: {
+ value: 1,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 2,
+ opacity_min: 0,
+ sync: false
+ }
+ },
+ size: {
+ value: 20,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 20,
+ size_min: 0,
+ sync: false
+ }
+ },
+ line_linked: {
+ enable: true,
+ distance: 100,
+ color: '#fff',
+ opacity: 1,
+ width: 1
+ },
+ move: {
+ enable: true,
+ speed: 2,
+ direction: 'none',
+ random: false,
+ straight: false,
+ out_mode: 'out',
+ bounce: false,
+ attract: {
+ enable: false,
+ rotateX: 3000,
+ rotateY: 3000
+ }
+ },
+ array: []
+ },
+ interactivity: {
+ detect_on: 'canvas',
+ events: {
+ onhover: {
+ enable: true,
+ mode: 'grab'
+ },
+ onclick: {
+ enable: true,
+ mode: 'push'
+ },
+ resize: true
+ },
+ modes: {
+ grab: {
+ distance: 100,
+ line_linked: {
+ opacity: 1
+ }
+ },
+ bubble: {
+ distance: 200,
+ size: 80,
+ duration: 0.4
+ },
+ repulse: {
+ distance: 200,
+ duration: 0.4
+ },
+ push: {
+ particles_nb: 4
+ },
+ remove: {
+ particles_nb: 2
+ }
+ },
+ mouse: {}
+ },
+ retina_detect: false,
+ fn: {
+ interact: {},
+ modes: {},
+ vendors: {}
+ },
+ tmp: {}
+ };
+
+ var pJS = this.pJS;
+
+ /* params settings */
+ if (params) {
+ Object.deepExtend(pJS, params);
+ }
+
+ pJS.tmp.obj = {
+ size_value: pJS.particles.size.value,
+ size_anim_speed: pJS.particles.size.anim.speed,
+ move_speed: pJS.particles.move.speed,
+ line_linked_distance: pJS.particles.line_linked.distance,
+ line_linked_width: pJS.particles.line_linked.width,
+ mode_grab_distance: pJS.interactivity.modes.grab.distance,
+ mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
+ mode_bubble_size: pJS.interactivity.modes.bubble.size,
+ mode_repulse_distance: pJS.interactivity.modes.repulse.distance
+ };
+
+
+ pJS.fn.retinaInit = function () {
+
+ if (pJS.retina_detect && window.devicePixelRatio > 1) {
+ pJS.canvas.pxratio = window.devicePixelRatio;
+ pJS.tmp.retina = true;
+ }
+ else {
+ pJS.canvas.pxratio = 1;
+ pJS.tmp.retina = false;
+ }
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
+
+ pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
+ pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
+ pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
+ pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
+ pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
+ pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
+
+ };
+
+
+
+ /* ---------- pJS functions - canvas ------------ */
+
+ pJS.fn.canvasInit = function () {
+ pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
+ };
+
+ pJS.fn.canvasSize = function () {
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ if (pJS && pJS.interactivity.events.resize) {
+
+ window.addEventListener('resize', function () {
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight;
+
+ /* resize canvas */
+ if (pJS.tmp.retina) {
+ pJS.canvas.w *= pJS.canvas.pxratio;
+ pJS.canvas.h *= pJS.canvas.pxratio;
+ }
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ /* repaint canvas on anim disabled */
+ if (!pJS.particles.move.enable) {
+ pJS.fn.particlesEmpty();
+ pJS.fn.particlesCreate();
+ pJS.fn.particlesDraw();
+ pJS.fn.vendors.densityAutoParticles();
+ }
+
+ /* density particles enabled */
+ pJS.fn.vendors.densityAutoParticles();
+
+ });
+
+ }
+
+ };
+
+
+ pJS.fn.canvasPaint = function () {
+ pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+ pJS.fn.canvasClear = function () {
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+
+ /* --------- pJS functions - particles ----------- */
+
+ pJS.fn.particle = function (color, opacity, position) {
+
+ /* size */
+ this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
+ if (pJS.particles.size.anim.enable) {
+ this.size_status = false;
+ this.vs = pJS.particles.size.anim.speed / 100;
+ if (!pJS.particles.size.anim.sync) {
+ this.vs = this.vs * Math.random();
+ }
+ }
+
+ /* position */
+ this.x = position ? position.x : Math.random() * pJS.canvas.w;
+ this.y = position ? position.y : Math.random() * pJS.canvas.h;
+
+ /* check position - into the canvas */
+ if (this.x > pJS.canvas.w - this.radius * 2) this.x = this.x - this.radius;
+ else if (this.x < this.radius * 2) this.x = this.x + this.radius;
+ if (this.y > pJS.canvas.h - this.radius * 2) this.y = this.y - this.radius;
+ else if (this.y < this.radius * 2) this.y = this.y + this.radius;
+
+ /* check position - avoid overlap */
+ if (pJS.particles.move.bounce) {
+ pJS.fn.vendors.checkOverlap(this, position);
+ }
+
+ /* color */
+ this.color = {};
+ if (typeof (color.value) == 'object') {
+
+ if (color.value instanceof Array) {
+ var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
+ this.color.rgb = hexToRgb(color_selected);
+ } else {
+ if (color.value.r != undefined && color.value.g != undefined && color.value.b != undefined) {
+ this.color.rgb = {
+ r: color.value.r,
+ g: color.value.g,
+ b: color.value.b
+ }
+ }
+ if (color.value.h != undefined && color.value.s != undefined && color.value.l != undefined) {
+ this.color.hsl = {
+ h: color.value.h,
+ s: color.value.s,
+ l: color.value.l
+ }
+ }
+ }
+
+ }
+ else if (color.value == 'random') {
+ this.color.rgb = {
+ r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
+ }
+ }
+ else if (typeof (color.value) == 'string') {
+ this.color = color;
+ this.color.rgb = hexToRgb(this.color.value);
+ }
+
+ /* opacity */
+ this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
+ if (pJS.particles.opacity.anim.enable) {
+ this.opacity_status = false;
+ this.vo = pJS.particles.opacity.anim.speed / 100;
+ if (!pJS.particles.opacity.anim.sync) {
+ this.vo = this.vo * Math.random();
+ }
+ }
+
+ /* animation - velocity for speed */
+ var velbase = {}
+ switch (pJS.particles.move.direction) {
+ case 'top':
+ velbase = { x: 0, y: -1 };
+ break;
+ case 'top-right':
+ velbase = { x: 0.5, y: -0.5 };
+ break;
+ case 'right':
+ velbase = { x: 1, y: -0 };
+ break;
+ case 'bottom-right':
+ velbase = { x: 0.5, y: 0.5 };
+ break;
+ case 'bottom':
+ velbase = { x: 0, y: 1 };
+ break;
+ case 'bottom-left':
+ velbase = { x: -0.5, y: 1 };
+ break;
+ case 'left':
+ velbase = { x: -1, y: 0 };
+ break;
+ case 'top-left':
+ velbase = { x: -0.5, y: -0.5 };
+ break;
+ default:
+ velbase = { x: 0, y: 0 };
+ break;
+ }
+
+ if (pJS.particles.move.straight) {
+ this.vx = velbase.x;
+ this.vy = velbase.y;
+ if (pJS.particles.move.random) {
+ this.vx = this.vx * (Math.random());
+ this.vy = this.vy * (Math.random());
+ }
+ } else {
+ this.vx = velbase.x + Math.random() - 0.5;
+ this.vy = velbase.y + Math.random() - 0.5;
+ }
+
+ // var theta = 2.0 * Math.PI * Math.random();
+ // this.vx = Math.cos(theta);
+ // this.vy = Math.sin(theta);
+
+ this.vx_i = this.vx;
+ this.vy_i = this.vy;
+
+
+
+ /* if shape is image */
+
+ var shape_type = pJS.particles.shape.type;
+ if (typeof (shape_type) == 'object') {
+ if (shape_type instanceof Array) {
+ var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
+ this.shape = shape_selected;
+ }
+ } else {
+ this.shape = shape_type;
+ }
+
+ if (this.shape == 'image') {
+ var sh = pJS.particles.shape;
+ this.img = {
+ src: sh.image.src,
+ ratio: sh.image.width / sh.image.height
+ }
+ if (!this.img.ratio) this.img.ratio = 1;
+ if (pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined) {
+ pJS.fn.vendors.createSvgImg(this);
+ if (pJS.tmp.pushing) {
+ this.img.loaded = false;
+ }
+ }
+ }
+
+
+
+ };
+
+
+ pJS.fn.particle.prototype.draw = function () {
+
+ var p = this;
+
+ if (p.radius_bubble != undefined) {
+ var radius = p.radius_bubble;
+ } else {
+ var radius = p.radius;
+ }
+
+ if (p.opacity_bubble != undefined) {
+ var opacity = p.opacity_bubble;
+ } else {
+ var opacity = p.opacity;
+ }
+
+ if (p.color.rgb) {
+ var color_value = 'rgba(' + p.color.rgb.r + ',' + p.color.rgb.g + ',' + p.color.rgb.b + ',' + opacity + ')';
+ } else {
+ var color_value = 'hsla(' + p.color.hsl.h + ',' + p.color.hsl.s + '%,' + p.color.hsl.l + '%,' + opacity + ')';
+ }
+
+ pJS.canvas.ctx.fillStyle = color_value;
+ pJS.canvas.ctx.beginPath();
+
+ switch (p.shape) {
+
+ case 'circle':
+ pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
+ break;
+
+ case 'edge':
+ pJS.canvas.ctx.rect(p.x - radius, p.y - radius, radius * 2, radius * 2);
+ break;
+
+ case 'triangle':
+ pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x - radius, p.y + radius / 1.66, radius * 2, 3, 2);
+ break;
+
+ case 'polygon':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius / (pJS.particles.shape.polygon.nb_sides / 3.5), // startX
+ p.y - radius / (2.66 / 3.5), // startY
+ radius * 2.66 / (pJS.particles.shape.polygon.nb_sides / 3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 1 // sideCountDenominator
+ );
+ break;
+
+ case 'star':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius * 2 / (pJS.particles.shape.polygon.nb_sides / 4), // startX
+ p.y - radius / (2 * 2.66 / 3.5), // startY
+ radius * 2 * 2.66 / (pJS.particles.shape.polygon.nb_sides / 3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 2 // sideCountDenominator
+ );
+ break;
+
+ case 'image':
+
+ function draw() {
+ pJS.canvas.ctx.drawImage(
+ img_obj,
+ p.x - radius,
+ p.y - radius,
+ radius * 2,
+ radius * 2 / p.img.ratio
+ );
+ }
+
+ if (pJS.tmp.img_type == 'svg') {
+ var img_obj = p.img.obj;
+ } else {
+ var img_obj = pJS.tmp.img_obj;
+ }
+
+ if (img_obj) {
+ draw();
+ }
+
+ break;
+
+ }
+
+ pJS.canvas.ctx.closePath();
+
+ if (pJS.particles.shape.stroke.width > 0) {
+ pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
+ pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
+ pJS.canvas.ctx.stroke();
+ }
+
+ pJS.canvas.ctx.fill();
+
+ };
+
+
+ pJS.fn.particlesCreate = function () {
+ for (var i = 0; i < pJS.particles.number.value; i++) {
+ pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
+ }
+ };
+
+ pJS.fn.particlesUpdate = function () {
+
+ for (var i = 0; i < pJS.particles.array.length; i++) {
+
+ /* the particle */
+ var p = pJS.particles.array[i];
+
+ // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
+ // var f = -BANG_SIZE / d;
+ // if ( d < BANG_SIZE ) {
+ // var t = Math.atan2( dy, dx );
+ // p.vx = f * Math.cos(t);
+ // p.vy = f * Math.sin(t);
+ // }
+
+ /* move the particle */
+ if (pJS.particles.move.enable) {
+ var ms = pJS.particles.move.speed / 2;
+ p.x += p.vx * ms;
+ p.y += p.vy * ms;
+ }
+
+ /* change opacity status */
+ if (pJS.particles.opacity.anim.enable) {
+ if (p.opacity_status == true) {
+ if (p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
+ p.opacity += p.vo;
+ } else {
+ if (p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
+ p.opacity -= p.vo;
+ }
+ if (p.opacity < 0) p.opacity = 0;
+ }
+
+ /* change size */
+ if (pJS.particles.size.anim.enable) {
+ if (p.size_status == true) {
+ if (p.radius >= pJS.particles.size.value) p.size_status = false;
+ p.radius += p.vs;
+ } else {
+ if (p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
+ p.radius -= p.vs;
+ }
+ if (p.radius < 0) p.radius = 0;
+ }
+
+ /* change particle position if it is out of canvas */
+ if (pJS.particles.move.out_mode == 'bounce') {
+ var new_pos = {
+ x_left: p.radius,
+ x_right: pJS.canvas.w,
+ y_top: p.radius,
+ y_bottom: pJS.canvas.h
+ }
+ } else {
+ var new_pos = {
+ x_left: -p.radius,
+ x_right: pJS.canvas.w + p.radius,
+ y_top: -p.radius,
+ y_bottom: pJS.canvas.h + p.radius
+ }
+ }
+
+ if (p.x - p.radius > pJS.canvas.w) {
+ p.x = new_pos.x_left;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ else if (p.x + p.radius < 0) {
+ p.x = new_pos.x_right;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ if (p.y - p.radius > pJS.canvas.h) {
+ p.y = new_pos.y_top;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+ else if (p.y + p.radius < 0) {
+ p.y = new_pos.y_bottom;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+
+ /* out of canvas modes */
+ switch (pJS.particles.move.out_mode) {
+ case 'bounce':
+ if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (p.x - p.radius < 0) p.vx = -p.vx;
+ if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (p.y - p.radius < 0) p.vy = -p.vy;
+ break;
+ }
+
+ /* events */
+ if (isInArray('grab', pJS.interactivity.events.onhover.mode)) {
+ pJS.fn.modes.grabParticle(p);
+ }
+
+ if (isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)) {
+ pJS.fn.modes.bubbleParticle(p);
+ }
+
+ if (isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
+ pJS.fn.modes.repulseParticle(p);
+ }
+
+ /* interaction auto between particles */
+ if (pJS.particles.line_linked.enable || pJS.particles.move.attract.enable) {
+ for (var j = i + 1; j < pJS.particles.array.length; j++) {
+ var p2 = pJS.particles.array[j];
+
+ /* link particles */
+ if (pJS.particles.line_linked.enable) {
+ pJS.fn.interact.linkParticles(p, p2);
+ }
+
+ /* attract particles */
+ if (pJS.particles.move.attract.enable) {
+ pJS.fn.interact.attractParticles(p, p2);
+ }
+
+ /* bounce particles */
+ if (pJS.particles.move.bounce) {
+ pJS.fn.interact.bounceParticles(p, p2);
+ }
+
+ }
+ }
+
+
+ }
+
+ };
+
+ pJS.fn.particlesDraw = function () {
+
+ /* clear canvas */
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+
+ /* update each particles param */
+ pJS.fn.particlesUpdate();
+
+ /* draw each particle */
+ for (var i = 0; i < pJS.particles.array.length; i++) {
+ var p = pJS.particles.array[i];
+ p.draw();
+ }
+
+ };
+
+ pJS.fn.particlesEmpty = function () {
+ pJS.particles.array = [];
+ };
+
+ pJS.fn.particlesRefresh = function () {
+
+ /* init all */
+ cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
+ cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ pJS.tmp.source_svg = undefined;
+ pJS.tmp.img_obj = undefined;
+ pJS.tmp.count_svg = 0;
+ pJS.fn.particlesEmpty();
+ pJS.fn.canvasClear();
+
+ /* restart */
+ pJS.fn.vendors.start();
+
+ };
+
+
+ /* ---------- pJS functions - particles interaction ------------ */
+
+ pJS.fn.interact.linkParticles = function (p1, p2) {
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx * dx + dy * dy);
+
+ /* draw a line between p1 and p2 if the distance between them is under the config distance */
+ if (dist <= pJS.particles.line_linked.distance) {
+
+ var opacity_line = pJS.particles.line_linked.opacity - (dist / (1 / pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
+
+ if (opacity_line > 0) {
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba(' + color_line.r + ',' + color_line.g + ',' + color_line.b + ',' + opacity_line + ')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p1.x, p1.y);
+ pJS.canvas.ctx.lineTo(p2.x, p2.y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.interact.attractParticles = function (p1, p2) {
+
+ /* condensed particles */
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx * dx + dy * dy);
+
+ if (dist <= pJS.particles.line_linked.distance) {
+
+ var ax = dx / (pJS.particles.move.attract.rotateX * 1000),
+ ay = dy / (pJS.particles.move.attract.rotateY * 1000);
+
+ p1.vx -= ax;
+ p1.vy -= ay;
+
+ p2.vx += ax;
+ p2.vy += ay;
+
+ }
+
+
+ }
+
+
+ pJS.fn.interact.bounceParticles = function (p1, p2) {
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx * dx + dy * dy),
+ dist_p = p1.radius + p2.radius;
+
+ if (dist <= dist_p) {
+ p1.vx = -p1.vx;
+ p1.vy = -p1.vy;
+
+ p2.vx = -p2.vx;
+ p2.vy = -p2.vy;
+ }
+
+ }
+
+
+ /* ---------- pJS functions - modes events ------------ */
+
+ pJS.fn.modes.pushParticles = function (nb, pos) {
+
+ pJS.tmp.pushing = true;
+
+ for (var i = 0; i < nb; i++) {
+ pJS.particles.array.push(
+ new pJS.fn.particle(
+ pJS.particles.color,
+ pJS.particles.opacity.value,
+ {
+ 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
+ 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
+ }
+ )
+ )
+ if (i == nb - 1) {
+ if (!pJS.particles.move.enable) {
+ pJS.fn.particlesDraw();
+ }
+ pJS.tmp.pushing = false;
+ }
+ }
+
+ };
+
+
+ pJS.fn.modes.removeParticles = function (nb) {
+
+ pJS.particles.array.splice(0, nb);
+ if (!pJS.particles.move.enable) {
+ pJS.fn.particlesDraw();
+ }
+
+ };
+
+
+ pJS.fn.modes.bubbleParticle = function (p) {
+
+ /* on hover event */
+ if (pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)) {
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse),
+ ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
+
+ function init() {
+ p.opacity_bubble = p.opacity;
+ p.radius_bubble = p.radius;
+ }
+
+ /* mousemove - check ratio */
+ if (dist_mouse <= pJS.interactivity.modes.bubble.distance) {
+
+ if (ratio >= 0 && pJS.interactivity.status == 'mousemove') {
+
+ /* size */
+ if (pJS.interactivity.modes.bubble.size != pJS.particles.size.value) {
+
+ if (pJS.interactivity.modes.bubble.size > pJS.particles.size.value) {
+ var size = p.radius + (pJS.interactivity.modes.bubble.size * ratio);
+ if (size >= 0) {
+ p.radius_bubble = size;
+ }
+ } else {
+ var dif = p.radius - pJS.interactivity.modes.bubble.size,
+ size = p.radius - (dif * ratio);
+ if (size > 0) {
+ p.radius_bubble = size;
+ } else {
+ p.radius_bubble = 0;
+ }
+ }
+
+ }
+
+ /* opacity */
+ if (pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value) {
+
+ if (pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value) {
+ var opacity = pJS.interactivity.modes.bubble.opacity * ratio;
+ if (opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity) {
+ p.opacity_bubble = opacity;
+ }
+ } else {
+ var opacity = p.opacity - (pJS.particles.opacity.value - pJS.interactivity.modes.bubble.opacity) * ratio;
+ if (opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity) {
+ p.opacity_bubble = opacity;
+ }
+ }
+
+ }
+
+ }
+
+ } else {
+ init();
+ }
+
+
+ /* mouseleave */
+ if (pJS.interactivity.status == 'mouseleave') {
+ init();
+ }
+
+ }
+
+ /* on click event */
+ else if (pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)) {
+
+
+ if (pJS.tmp.bubble_clicking) {
+ var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
+ dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse),
+ time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time) / 1000;
+
+ if (time_spent > pJS.interactivity.modes.bubble.duration) {
+ pJS.tmp.bubble_duration_end = true;
+ }
+
+ if (time_spent > pJS.interactivity.modes.bubble.duration * 2) {
+ pJS.tmp.bubble_clicking = false;
+ pJS.tmp.bubble_duration_end = false;
+ }
+ }
+
+
+ function process(bubble_param, particles_param, p_obj_bubble, p_obj, id) {
+
+ if (bubble_param != particles_param) {
+
+ if (!pJS.tmp.bubble_duration_end) {
+ if (dist_mouse <= pJS.interactivity.modes.bubble.distance) {
+ if (p_obj_bubble != undefined) var obj = p_obj_bubble;
+ else var obj = p_obj;
+ if (obj != bubble_param) {
+ var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
+ if (id == 'size') p.radius_bubble = value;
+ if (id == 'opacity') p.opacity_bubble = value;
+ }
+ } else {
+ if (id == 'size') p.radius_bubble = undefined;
+ if (id == 'opacity') p.opacity_bubble = undefined;
+ }
+ } else {
+ if (p_obj_bubble != undefined) {
+ var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
+ dif = bubble_param - value_tmp;
+ value = bubble_param + dif;
+ if (id == 'size') p.radius_bubble = value;
+ if (id == 'opacity') p.opacity_bubble = value;
+ }
+ }
+
+ }
+
+ }
+
+ if (pJS.tmp.bubble_clicking) {
+ /* size */
+ process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
+ /* opacity */
+ process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.modes.repulseParticle = function (p) {
+
+ if (pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse);
+
+ var normVec = { x: dx_mouse / dist_mouse, y: dy_mouse / dist_mouse },
+ repulseRadius = pJS.interactivity.modes.repulse.distance,
+ velocity = 100,
+ repulseFactor = clamp((1 / repulseRadius) * (-1 * Math.pow(dist_mouse / repulseRadius, 2) + 1) * repulseRadius * velocity, 0, 50);
+
+ var pos = {
+ x: p.x + normVec.x * repulseFactor,
+ y: p.y + normVec.y * repulseFactor
+ }
+
+ if (pJS.particles.move.out_mode == 'bounce') {
+ if (pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
+ if (pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
+ } else {
+ p.x = pos.x;
+ p.y = pos.y;
+ }
+
+ }
+
+
+ else if (pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
+
+ if (!pJS.tmp.repulse_finish) {
+ pJS.tmp.repulse_count++;
+ if (pJS.tmp.repulse_count == pJS.particles.array.length) {
+ pJS.tmp.repulse_finish = true;
+ }
+ }
+
+ if (pJS.tmp.repulse_clicking) {
+
+ var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance / 6, 3);
+
+ var dx = pJS.interactivity.mouse.click_pos_x - p.x,
+ dy = pJS.interactivity.mouse.click_pos_y - p.y,
+ d = dx * dx + dy * dy;
+
+ var force = -repulseRadius / d * 1;
+
+ function process() {
+
+ var f = Math.atan2(dy, dx);
+ p.vx = force * Math.cos(f);
+ p.vy = force * Math.sin(f);
+
+ if (pJS.particles.move.out_mode == 'bounce') {
+ var pos = {
+ x: p.x + p.vx,
+ y: p.y + p.vy
+ }
+ if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (pos.x - p.radius < 0) p.vx = -p.vx;
+ if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (pos.y - p.radius < 0) p.vy = -p.vy;
+ }
+
+ }
+
+ // default
+ if (d <= repulseRadius) {
+ process();
+ }
+
+ // bang - slow motion mode
+ // if(!pJS.tmp.repulse_finish){
+ // if(d <= repulseRadius){
+ // process();
+ // }
+ // }else{
+ // process();
+ // }
+
+
+ } else {
+
+ if (pJS.tmp.repulse_clicking == false) {
+
+ p.vx = p.vx_i;
+ p.vy = p.vy_i;
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ pJS.fn.modes.grabParticle = function (p) {
+
+ if (pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove') {
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse);
+
+ /* draw a line between the cursor and the particle if the distance between them is under the config distance */
+ if (dist_mouse <= pJS.interactivity.modes.grab.distance) {
+
+ var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1 / pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
+
+ if (opacity_line > 0) {
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba(' + color_line.r + ',' + color_line.g + ',' + color_line.b + ',' + opacity_line + ')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p.x, p.y);
+ pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ }
+
+ };
+
+
+
+ /* ---------- pJS functions - vendors ------------ */
+
+ pJS.fn.vendors.eventsListeners = function () {
+
+ /* events target element */
+ if (pJS.interactivity.detect_on == 'window') {
+ pJS.interactivity.el = window;
+ } else {
+ pJS.interactivity.el = pJS.canvas.el;
+ }
+
+
+ /* detect mouse pos - on hover / click event */
+ if (pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable) {
+
+ /* el on mousemove */
+ pJS.interactivity.el.addEventListener('mousemove', function (e) {
+
+ if (pJS.interactivity.el == window) {
+ var pos_x = e.clientX,
+ pos_y = e.clientY;
+ }
+ else {
+ var pos_x = e.offsetX || e.clientX,
+ pos_y = e.offsetY || e.clientY;
+ }
+
+ pJS.interactivity.mouse.pos_x = pos_x;
+ pJS.interactivity.mouse.pos_y = pos_y;
+
+ if (pJS.tmp.retina) {
+ pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
+ pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
+ }
+
+ pJS.interactivity.status = 'mousemove';
+
+ });
+
+ /* el on onmouseleave */
+ pJS.interactivity.el.addEventListener('mouseleave', function (e) {
+
+ pJS.interactivity.mouse.pos_x = null;
+ pJS.interactivity.mouse.pos_y = null;
+ pJS.interactivity.status = 'mouseleave';
+
+ });
+
+ }
+
+ /* on click event */
+ if (pJS.interactivity.events.onclick.enable) {
+
+ pJS.interactivity.el.addEventListener('click', function () {
+
+ pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
+ pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
+ pJS.interactivity.mouse.click_time = new Date().getTime();
+
+ if (pJS.interactivity.events.onclick.enable) {
+
+ switch (pJS.interactivity.events.onclick.mode) {
+
+ case 'push':
+ if (pJS.particles.move.enable) {
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ } else {
+ if (pJS.interactivity.modes.push.particles_nb == 1) {
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }
+ else if (pJS.interactivity.modes.push.particles_nb > 1) {
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
+ }
+ }
+ break;
+
+ case 'remove':
+ pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
+ break;
+
+ case 'bubble':
+ pJS.tmp.bubble_clicking = true;
+ break;
+
+ case 'repulse':
+ pJS.tmp.repulse_clicking = true;
+ pJS.tmp.repulse_count = 0;
+ pJS.tmp.repulse_finish = false;
+ setTimeout(function () {
+ pJS.tmp.repulse_clicking = false;
+ }, pJS.interactivity.modes.repulse.duration * 1000)
+ break;
+
+ }
+
+ }
+
+ });
+
+ }
+
+
+ };
+
+ pJS.fn.vendors.densityAutoParticles = function () {
+
+ if (pJS.particles.number.density.enable) {
+
+ /* calc area */
+ var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
+ if (pJS.tmp.retina) {
+ area = area / (pJS.canvas.pxratio * 2);
+ }
+
+ /* calc number of particles based on density area */
+ var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
+
+ /* add or remove X particles */
+ var missing_particles = pJS.particles.array.length - nb_particles;
+ if (missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
+ else pJS.fn.modes.removeParticles(missing_particles);
+
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkOverlap = function (p1, position) {
+ for (var i = 0; i < pJS.particles.array.length; i++) {
+ var p2 = pJS.particles.array[i];
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx * dx + dy * dy);
+
+ if (dist <= p1.radius + p2.radius) {
+ p1.x = position ? position.x : Math.random() * pJS.canvas.w;
+ p1.y = position ? position.y : Math.random() * pJS.canvas.h;
+ pJS.fn.vendors.checkOverlap(p1);
+ }
+ }
+ };
+
+
+ pJS.fn.vendors.createSvgImg = function (p) {
+
+ /* set color to svg element */
+ var svgXml = pJS.tmp.source_svg,
+ rgbHex = /#([0-9A-F]{3,6})/gi,
+ coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
+ if (p.color.rgb) {
+ var color_value = 'rgba(' + p.color.rgb.r + ',' + p.color.rgb.g + ',' + p.color.rgb.b + ',' + p.opacity + ')';
+ } else {
+ var color_value = 'hsla(' + p.color.hsl.h + ',' + p.color.hsl.s + '%,' + p.color.hsl.l + '%,' + p.opacity + ')';
+ }
+ return color_value;
+ });
+
+ /* prepare to create img with colored svg */
+ var svg = new Blob([coloredSvgXml], { type: 'image/svg+xml;charset=utf-8' }),
+ DOMURL = window.URL || window.webkitURL || window,
+ url = DOMURL.createObjectURL(svg);
+
+ /* create particle img obj */
+ var img = new Image();
+ img.addEventListener('load', function () {
+ p.img.obj = img;
+ p.img.loaded = true;
+ DOMURL.revokeObjectURL(url);
+ pJS.tmp.count_svg++;
+ });
+ img.src = url;
+
+ };
+
+
+ pJS.fn.vendors.destroypJS = function () {
+ cancelAnimationFrame(pJS.fn.drawAnimFrame);
+ canvas_el.remove();
+ pJSDom = null;
+ };
+
+
+ pJS.fn.vendors.drawShape = function (c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator) {
+
+ // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
+ var sideCount = sideCountNumerator * sideCountDenominator;
+ var decimalSides = sideCountNumerator / sideCountDenominator;
+ var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
+ var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
+ c.save();
+ c.beginPath();
+ c.translate(startX, startY);
+ c.moveTo(0, 0);
+ for (var i = 0; i < sideCount; i++) {
+ c.lineTo(sideLength, 0);
+ c.translate(sideLength, 0);
+ c.rotate(interiorAngle);
+ }
+ //c.stroke();
+ c.fill();
+ c.restore();
+
+ };
+
+ pJS.fn.vendors.exportImg = function () {
+ window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
+ };
+
+
+ pJS.fn.vendors.loadImg = function (type) {
+
+ pJS.tmp.img_error = undefined;
+
+ if (pJS.particles.shape.image.src != '') {
+
+ if (type == 'svg') {
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', pJS.particles.shape.image.src);
+ xhr.onreadystatechange = function (data) {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ pJS.tmp.source_svg = data.currentTarget.response;
+ pJS.fn.vendors.checkBeforeDraw();
+ } else {
+ console.log('Error pJS - Image not found');
+ pJS.tmp.img_error = true;
+ }
+ }
+ }
+ xhr.send();
+
+ } else {
+
+ var img = new Image();
+ img.addEventListener('load', function () {
+ pJS.tmp.img_obj = img;
+ pJS.fn.vendors.checkBeforeDraw();
+ });
+ img.src = pJS.particles.shape.image.src;
+
+ }
+
+ } else {
+ console.log('Error pJS - No image.src');
+ pJS.tmp.img_error = true;
+ }
+
+ };
+
+
+ pJS.fn.vendors.draw = function () {
+
+ if (pJS.particles.shape.type == 'image') {
+
+ if (pJS.tmp.img_type == 'svg') {
+
+ if (pJS.tmp.count_svg >= pJS.particles.number.value) {
+ pJS.fn.particlesDraw();
+ if (!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ } else {
+ //console.log('still loading...');
+ if (!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ } else {
+
+ if (pJS.tmp.img_obj != undefined) {
+ pJS.fn.particlesDraw();
+ if (!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ } else {
+ if (!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }
+
+ } else {
+ pJS.fn.particlesDraw();
+ if (!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkBeforeDraw = function () {
+
+ // if shape is image
+ if (pJS.particles.shape.type == 'image') {
+
+ if (pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined) {
+ pJS.tmp.checkAnimFrame = requestAnimFrame(check);
+ } else {
+ //console.log('images loaded! cancel check');
+ cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
+ if (!pJS.tmp.img_error) {
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ }
+
+ } else {
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ };
+
+
+ pJS.fn.vendors.init = function () {
+
+ /* init canvas + particles */
+ pJS.fn.retinaInit();
+ pJS.fn.canvasInit();
+ pJS.fn.canvasSize();
+ pJS.fn.canvasPaint();
+ pJS.fn.particlesCreate();
+ pJS.fn.vendors.densityAutoParticles();
+
+ /* particles.line_linked - convert hex colors to rgb */
+ pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
+
+ };
+
+
+ pJS.fn.vendors.start = function () {
+
+ if (isInArray('image', pJS.particles.shape.type)) {
+ pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);
+ pJS.fn.vendors.loadImg(pJS.tmp.img_type);
+ } else {
+ pJS.fn.vendors.checkBeforeDraw();
+ }
+
+ };
+
+
+
+
+ /* ---------- pJS - start ------------ */
+
+
+ pJS.fn.vendors.eventsListeners();
+
+ pJS.fn.vendors.start();
+
+
+
+};
+
+/* ---------- global functions - vendors ------------ */
+
+Object.deepExtend = function (destination, source) {
+ for (var property in source) {
+ if (source[property] && source[property].constructor &&
+ source[property].constructor === Object) {
+ destination[property] = destination[property] || {};
+ arguments.callee(destination[property], source[property]);
+ } else {
+ destination[property] = source[property];
+ }
+ }
+ return destination;
+};
+
+window.requestAnimFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function (callback) {
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+
+window.cancelRequestAnimFrame = (function () {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelRequestAnimationFrame ||
+ window.mozCancelRequestAnimationFrame ||
+ window.oCancelRequestAnimationFrame ||
+ window.msCancelRequestAnimationFrame ||
+ clearTimeout
+})();
+
+function hexToRgb(hex) {
+ // By Tim Down - http://stackoverflow.com/a/5624139/3493650
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ hex = hex.replace(shorthandRegex, function (m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+};
+
+function clamp(number, min, max) {
+ return Math.min(Math.max(number, min), max);
+};
+
+function isInArray(value, array) {
+ return array.indexOf(value) > -1;
+}
+
+
+/* ---------- particles.js functions - start ------------ */
+
+window.pJSDom = [];
+
+window.particlesJS = function (tag_id, params) {
+
+ //console.log(params);
+
+ /* no string id? so it's object params, and set the id with default id */
+ if (typeof (tag_id) != 'string') {
+ params = tag_id;
+ tag_id = 'particles-js';
+ }
+
+ /* no id? set the id to default id */
+ if (!tag_id) {
+ tag_id = 'particles-js';
+ }
+
+ /* pJS elements */
+ var pJS_tag = document.getElementById(tag_id),
+ pJS_canvas_class = 'particles-js-canvas-el',
+ exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
+
+ /* remove canvas if exists into the pJS target tag */
+ if (exist_canvas.length) {
+ while (exist_canvas.length > 0) {
+ pJS_tag.removeChild(exist_canvas[0]);
+ }
+ }
+
+ /* create canvas element */
+ var canvas_el = document.createElement('canvas');
+ canvas_el.className = pJS_canvas_class;
+
+ /* set size canvas */
+ canvas_el.style.width = "100%";
+ canvas_el.style.height = "100%";
+
+ /* append canvas */
+ var canvas = document.getElementById(tag_id).appendChild(canvas_el);
+
+ /* launch particle.js */
+ if (canvas != null) {
+ pJSDom.push(new pJS(tag_id, params));
+ }
+
+};
+
+window.particlesJS.load = function (tag_id, path_config_json, callback) {
+
+ /* load json config */
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', path_config_json);
+ xhr.onreadystatechange = function (data) {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ var params = JSON.parse(data.currentTarget.response);
+ window.particlesJS(tag_id, params);
+ if (callback) callback();
+ } else {
+ console.log('Error pJS - XMLHttpRequest status: ' + xhr.status);
+ console.log('Error pJS - File config not found');
+ }
+ }
+ };
+ xhr.send();
+
+};
\ No newline at end of file
diff --git a/assets/js/redirect.js b/assets/js/redirect.js
new file mode 100644
index 0000000..3a71ca6
--- /dev/null
+++ b/assets/js/redirect.js
@@ -0,0 +1,50 @@
+document.addEventListener("DOMContentLoaded", function () {
+ // Fonction pour obtenir les paramètres d'URL
+ function getQueryParams() {
+ const params = {};
+ const queryString = window.location.search.substring(1);
+ const regex = /([^&=]+)=([^&]*)/g;
+ let match;
+ while (match = regex.exec(queryString)) {
+ params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
+ }
+ return params;
+ }
+
+ // Fonction pour charger les redirections à partir du fichier JSON relatif au script
+ function loadRedirections() {
+ const jsonUrl = new URL('../json/redirect.json', import.meta.url).href;
+ return fetch(jsonUrl)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error("Erreur lors du chargement du fichier JSON");
+ }
+ return response.json();
+ })
+ .catch(error => {
+ console.error("Erreur:", error);
+ return {}; // Retourner un objet vide si le chargement échoue
+ });
+ }
+
+ const defaultRedirection = '../';
+
+ // Charger les redirections et appliquer la logique
+ loadRedirections().then(redirections => {
+ const queryParams = getQueryParams();
+
+ // Déterminer l'URL cible en fonction des paramètres d'URL
+ const targetUrl = queryParams.link && redirections[queryParams.link] ? redirections[queryParams.link] : defaultRedirection;
+
+ // Mettre à jour le lien "here"
+ const hereElement = document.getElementById('here');
+ if (hereElement) {
+ hereElement.href = targetUrl;
+ }
+
+ // Rediriger après 3 secondes
+ setTimeout(function () {
+ window.location.href = targetUrl;
+ }, 3000);
+ });
+});
\ No newline at end of file
diff --git a/assets/json/redirect.json b/assets/json/redirect.json
new file mode 100644
index 0000000..b4146ba
--- /dev/null
+++ b/assets/json/redirect.json
@@ -0,0 +1,6 @@
+{
+ "youtube": "https://youtube.com/@SkyExploreWasTaken?sub_confirmation=1",
+ "twitch": "https://twitch.tv/skyexplorewastaken",
+ "discord": "https://dsc.gg/sewt-server",
+ "github": "https://github.com/SkyExploreWasTaken"
+}
\ No newline at end of file
diff --git a/errors/403.html b/errors/403.html
new file mode 100644
index 0000000..fc8a89a
--- /dev/null
+++ b/errors/403.html
@@ -0,0 +1,27 @@
+
+
+
+
+ SEWT Website - Navigator Test
+
+
+
+
+
+
+
+
+
+
+
+ 403
+ Forbidden
+
+ You don't have permission to access this resource.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/errors/404.html b/errors/404.html
new file mode 100644
index 0000000..f46b18a
--- /dev/null
+++ b/errors/404.html
@@ -0,0 +1,27 @@
+
+
+
+
+ SEWT Website - Navigator Test
+
+
+
+
+
+
+
+
+
+
+
+ 404
+ Not Found
+
+ The requested URL was not found on this server.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/errors/500.html b/errors/500.html
new file mode 100644
index 0000000..69a440f
--- /dev/null
+++ b/errors/500.html
@@ -0,0 +1,29 @@
+
+
+
+
+ SEWT Website - Navigator Test
+
+
+
+
+
+
+
+
+
+
+
+ 500
+ Internal Server Error
+
+ The server encountered an internal error or misconfiguration and was unable to complete your request.
+
+ Please contact the server administrator at [no address given] to inform them of the time this error occurred, and the actions you performed just before this error.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..b6e3d46
--- /dev/null
+++ b/index.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+ SEWT Website
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modpacks/balkanarchy/index.html b/modpacks/balkanarchy/index.html
new file mode 100644
index 0000000..971dcd5
--- /dev/null
+++ b/modpacks/balkanarchy/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+ Balkanarchy Modpack
+
+
+
+
+
+
+
+
+
+
+
+
+
Balkanarchy Modpack
+
Discord of the Balkanarchy Minecraft server.
+
Minecraft 1.21.1 - Fabric 0.16.9
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modpacks/creative-ssmp/index.html b/modpacks/creative-ssmp/index.html
new file mode 100644
index 0000000..59e4dc7
--- /dev/null
+++ b/modpacks/creative-ssmp/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+ Creative SSMP Modpack
+
+
+
+
+
+
+
+
+
+
+
+
+
Creative SSMP Modpack
+
Minecraft 1.21 - Fabric 0.16.9
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modpacks/immersiveportals/index.html b/modpacks/immersiveportals/index.html
new file mode 100644
index 0000000..c4d1e13
--- /dev/null
+++ b/modpacks/immersiveportals/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+ Immersive Portals Modpack
+
+
+
+
+
+
+
+
+
+
+
+
+
Immersive Portals Modpack (used in my Backrooms map):
+
Minecraft 1.20.4 - Fabric 0.16.9
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modpacks/index.html b/modpacks/index.html
new file mode 100644
index 0000000..85fd983
--- /dev/null
+++ b/modpacks/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Modpacks List
+
+
+
+
+
+
+
+
+
+
+
+
+
My Minecraft Modpacks List:
+
+ Immersive Portals Modpack (used in my Backrooms map): link
+ Creative SSMP Modpack: link
+ Balkanarchy Modpack: link
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/navigator.html b/pages/navigator.html
new file mode 100644
index 0000000..f8d2c92
--- /dev/null
+++ b/pages/navigator.html
@@ -0,0 +1,30 @@
+
+
+
+
+ SEWT Website - Navigator Test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/redirect.html b/pages/redirect.html
new file mode 100644
index 0000000..e0e9e32
--- /dev/null
+++ b/pages/redirect.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
+
+
+
+
+
+
+ If the redirect doesn't work, please click here .
+
+
+
+
+
+
+
+
+
\ No newline at end of file