This commit is contained in:
Qx-blocks 2025-05-25 19:37:12 +02:00
commit d182ead446
54 changed files with 9745 additions and 0 deletions

24
.project Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>S8-mktg-aero</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

12
.settings/.jsdtscope Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/node_modules/*|**/*.min.js|**/bower_components/*" kind="src" path="public"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="S8-mktg-aero">
<wb-resource deploy-path="/" source-path="/public"/>
<property name="context-root" value="S8-mktg-aero"/>
</wb-module>
</project-modules>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.web"/>
<fixed facet="wst.jsdt.web"/>
<installed facet="wst.web" version="1.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>

View File

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@ -0,0 +1 @@
Window

BIN
aero/.DS_Store vendored Normal file

Binary file not shown.

50
aero/AeroElement.js Normal file
View File

@ -0,0 +1,50 @@
export const ON_CSS_LOADED = 0x12;
export class AeroElement {
/**
* @type {boolean} current landscape painting option
*/
isLandscape = false;
/**
* @type {number} current screen width painting option
*/
screenWidth = 1920;
/**
* @type {number} current screen height painting option
*/
screenHeight = 1080;
static isCSSLoading = false;
/** CSS is loaded */
css_isLoaded = false;
constructor() {
}
onOrientationChanged(isLandscape) {
/* To be overridden */
this.isLandscape = isLandscape;
}
onScreenResized(width, height) {
/* To be overridden */
this.screenWidth = width;
this.screenHeight = height;
}
}

40
aero/AeroMovie.css Normal file
View File

@ -0,0 +1,40 @@
/* <aero-slide> */
section[class^="aero-movie-"] {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
width: 100%;
}
section[class^="aero-movie-"]>div.text {
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
/* <asset> */
.aero-movie {
background-color: rgb(255, 255, 255);
width: 100%;
/*overflow: auto;*/
}
.aero-movie[loaded = "false"] {
aspect-ratio: 16 / 9;
background-color: aqua;
position: relative;
}
.aero-movie[loaded = "true"] {
height: fit-content;
background-color: white;
position: relative;
}
.aero-movie-video{
width: 100%;
/*overflow: auto;*/
}

146
aero/AeroMovie.js Normal file
View File

@ -0,0 +1,146 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
import { LoadHandler } from "./aero.js";
import { createSpinner } from "./boot.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export const LOW_RESOLUTION_TAG = "-low";
export const HIGH_RESOLUTION_TAG = "-high";
export class AeroMovie extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
constructor(type, props) {
super();
this.type = type;
this.props = props;
}
initializeNodes(handler, state) {
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-movie");
this.sectionNode.setAttribute("loaded", "false");
const spinnerNode = createSpinner();
this.sectionNode.appendChild(spinnerNode);
/* <video> */
this.videoNode = document.createElement("video");
this.videoNode.classList.add("aero-movie-video");
this.videoNode.setAttribute("muted", "");
// this.videoNode.setAttribute("playsinline", "");
this.videoNode.setAttribute("autoplay", "");
this.videoNode.setAttribute("loop", "");
//this.videoNode.setAttribute("controls", "");
// autoplay
this.videoNode.playbackRate = 1.0;
const sourceNode = document.createElement("source");
sourceNode.src = this.props.sequence;
sourceNode.type = "video/mp4";
const _this = this;
this.videoNode.addEventListener('loadeddata', function() {
_this.sectionNode.setAttribute("loaded", "true");
_this.sectionNode.removeChild(spinnerNode);
}, false);
this.videoNode.appendChild(sourceNode);
this.sectionNode.appendChild(this.videoNode);
/* </video> */
return this.sectionNode;
}
render() {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
}
draw() {
}
run() {
this.videoNode.play();
}
generateNextSourceNode() {
if (this.sequenceIndex >= this.sequences.length) { this.sequenceIndex = 0; }
}
}

81
aero/AeroUtilities.js Normal file
View File

@ -0,0 +1,81 @@
export const AeroUtilities = {
/**
*
* @param {*} target
* @param {*} pathname
* @param {*} onLoaded
*/
loadBackgroundImage : function(target, pathname, onLoaded) {
const backgroundImageBuffer = new Image();
const _this = this;
backgroundImageBuffer.onload = function () {
/* assign image from buffer */
target.style.backgroundImage = `url(${backgroundImageBuffer.src})`;
/* notify handler */
if(onLoaded){ onLoaded(); }
};
/* trigger loading */
backgroundImageBuffer.src = pathname;
},
getResourceFromOrigin : function(requestPath, responseType, responseCallback){
this.sendRequest_HTTP_GET(window.location.origin + requestPath, responseType, responseCallback);
},
/**
*
* @param {string} requestPath
* @param {string} responseType
* @param {Function} responseCallback
*/
sendRequest_HTTP_GET : function(requestPath, responseType, responseCallback) {
/**
* Relies on browser cache for speeding things up
*/
let xhr = new XMLHttpRequest();
// first line
xhr.open("GET", requestPath, true);
xhr.responseType = responseType;
// headers
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Access-Control-Allow-Origin', "*");
xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
xhr.setRequestHeader('Access-Control-Allow-Methods', 'X-Requested-With');
xhr.setRequestHeader('Access-Control-Allow-Headers', 'Cookie, Content-Type, Authorization, Content-Length, X-Requested-With');
xhr.setRequestHeader('Access-Control-Expose-Headers', 'Set-Cookie, X-Powered-By');
let _this = this;
// Hook the event that gets called as the request progresses
xhr.onreadystatechange = function () {
// If the request is "DONE" (completed or failed)
if (xhr.readyState == 4) {
// If we got HTTP status 200 (OK)
if (xhr.status == 200) {
responseCallback(xhr.responseText);
}
}
};
// fire request
xhr.send(null);
}
}

25
aero/CodeBlock.css Normal file
View File

@ -0,0 +1,25 @@
.code-block-section {
background-color: rgb(63, 63, 63);
padding: 32px max(15%, 16px) 32px max(15%, 16px);
}
.code-block-window {
background-color: rgb(33, 23, 59);
border-radius: 8px;
padding: 16px 24px;
color: rgb(87, 211, 211);
}
.code-block-window pre {
margin: 0;
padding: 0;
overflow-x: scroll;
tab-size: 2;
}
.code-block-window code {
margin: 0;
padding: 0;
}

85
aero/CodeBlock.js Normal file
View File

@ -0,0 +1,85 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
// Using ES6 import syntax
import hljs from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/highlight.min.js';
// and it's easy to individually load additional languages
import java from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/languages/java.min.js';
import xml from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/languages/xml.min.js';
import { AeroUtilities } from "./AeroUtilities.js";
export class CodeBlock extends AeroElement {
static isLanguageLoaded = false;
constructor(sourcePathname) {
super();
this.sourcePathname = sourcePathname;
if (!this.isLanguageLoaded) {
// Then register the languages you need
hljs.registerLanguage('java', java);
hljs.registerLanguage('xml', xml);
this.isLanguageLoaded = true;
}
}
/**
*
* @param {WebPage} page
*/
build(page) {
//page.css_requireStylesheet("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/styles/default.min.css");
page.css_requireStylesheet("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/styles/atom-one-dark.css");
page.css_requireStylesheet("/aero/CodeBlock.css");
const sectionNode = document.createElement("section");
sectionNode.classList.add("code-block-section");
const windowNode = document.createElement("div");
windowNode.classList.add("code-block-window");
// windowNode.classList.add("theme-atom-one-dark");
const preNode = document.createElement("pre");
//preNode.classList.add("theme-atom-one-dark");
const spanNode = document.createElement("span");
//spanNode.classList.add("language-java");
// spanNode.classList.add("hljs");
const codeNode = document.createElement("code");
//codeNode.innerHTML = highlightedCode;
spanNode.appendChild(codeNode);
preNode.appendChild(spanNode);
windowNode.appendChild(preNode);
sectionNode.appendChild(windowNode);
AeroUtilities.getResourceFromOrigin(this.sourcePathname, "text", sourceCode => {
const highlightedSourceCode = hljs.highlight(sourceCode, { language: 'java' }).value;
codeNode.innerHTML = highlightedSourceCode;
})
return (this.sectionNode = sectionNode);
}
/**
*
* @param {WebPage} page
*/
render(page) {
/* do nothing */
}
}

79
aero/Deck.css Normal file
View File

@ -0,0 +1,79 @@
.aero-deck {
padding: 16px 8% 16px 8%;
display: flex;
flex-wrap: wrap;
background-color: rgb(128, 128, 128);
}
.aero-deck-card-space {
margin: 8px;
}
.aero-deck-card {
border-radius: 8px;
border: solid 2px rgb(200, 200, 200);
}
.aero-deck-card-photo {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
height: 160px;
width: 160px;
z-index: 2;
border-radius: 6px 6px 0px 0px;
}
.aero-deck-card-name {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 16px;
font-weight: bold;
width: 152px;
padding: 4px 4px 4px 4px;
background-color: white;
text-align: center;
}
.aero-deck-card-role {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 16px;
font-weight: normal;
width: 152px;
padding: 4px 4px 4px 4px;
background-color: white;
text-align: center;
}
.aero-deck-card-bio {
font-family: Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 12px;
width: 144px;
padding: 8px 8px 8px 8px;
font-weight: normal;
background-color: white;
border-radius: 0px 0px 6px 6px;
}
@media (orientation : landscape) {
.aero-deck {
padding: 16px 10% 16px 10%;
}
}
@media (max-width: 480px) {
.aero-deck {
padding: 0px calc(50vw - 180px) 0px calc(50vw - 180px);
}
}

100
aero/Deck.js Normal file
View File

@ -0,0 +1,100 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
/**
* aero-deck
*/
export class Deck extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
props;
constructor(props) {
super();
this.props = props;
}
/**
*
* @param {WebPage} page
* @returns {HTMLElement}
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/Deck.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-deck");
this.props.cards.forEach(cardProps => {
let cardSpaceNode = document.createElement("div");
cardSpaceNode.classList.add("aero-deck-card-space");
cardSpaceNode.appendChild(createCard(cardProps));
this.sectionNode.appendChild(cardSpaceNode);
});
/* return wrapper node */
return this.sectionNode;
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
}
getEnveloppe() {
return this.sectionNode;
}
isLoaded(){
return this.isInitialized;
}
}
const createCard = function(props){
let cardNode = document.createElement("div");
cardNode.classList.add("aero-deck-card");
let photoNode = document.createElement("div");
photoNode.classList.add("aero-deck-card-photo");
photoNode.style.backgroundImage = `url('${props.photo}')`;
cardNode.appendChild(photoNode);
let nameNode = document.createElement("div");
nameNode.classList.add("aero-deck-card-name");
nameNode.innerHTML = props.name;
cardNode.appendChild(nameNode);
let roleNode = document.createElement("div");
roleNode.classList.add("aero-deck-card-role");
roleNode.innerHTML = props.role;
cardNode.appendChild(roleNode);
let bioNode = document.createElement("div");
bioNode.classList.add("aero-deck-card-bio");
bioNode.innerHTML = props.bio;
cardNode.appendChild(bioNode);
return cardNode;
}

301
aero/Documentation.css Normal file
View File

@ -0,0 +1,301 @@
/* <structure> */
.aero-doc{
margin: 0px;
padding: 0px;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
.aero-doc-header {
margin: 0px;
padding: 8px;
width: 100%;
font-size: 16px;
font-weight: bold;
color: grey;
background-color: rgb(232, 238, 232);
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
.aero-doc-main {
margin: 0px;
padding: 0px;
width: 100%;
display: flex;
flex-direction: row;
background-color: white;
border-top: solid 1px rgb(169, 169, 169);
}
.aero-doc-table {
width: 24%;
padding: 8px 16px 8px 16px;
}
.aero-doc-content {
width: 76%;
padding: 8px 16px 8px 16px;
height: calc(100vh - 128px);
overflow-y: scroll;
border-left: solid 1px rgb(169, 169, 169);
}
.aero-doc-table > div {
padding: 6px 12px;
border-bottom: solid 1px rgb(225, 217, 255);
}
.aero-doc-table > div > a{
font-size: 24px;
font-weight: bold;
color: rgb(104, 106, 105);
}
@media (orientation : landscape) {
.aero-doc {
border-top: solid 1px rgb(169, 169, 169);
}
.aero-doc-content {
margin: 0px 0px 0px 0px;
padding: 16px 32px 16px 32px;
}
}
@media (orientation : portrait) {
.aero-doc-content {
margin: 0px 0px 0px 0px;
padding: 8px 16px 8px 16px;
}
}
/* <h1> */
.aero-doc-h1 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: lighter;
max-width: 92%;
padding: 8px;
border-radius: 4px;
margin: 0px;
z-index: 8;
text-align: left;
}
@media (orientation : landscape) {
.aero-doc-h1 {
font-size: 64px;
line-height: 64px;
}
}
@media (orientation : portrait) {
.aero-doc-h1 {
font-size: 48px;
line-height: 48px;
}
}
.aero-doc-h1>span.emphasis {
font-weight: bold;
}
.aero-doc-h1 {
padding: 32px 8px 16px 8px;
}
/* </h1> */
/* <h2> */
.aero-doc-h2 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 24px;
line-height: 24px;
font-weight: bold;
max-width: 92%;
padding: 16px 8px 8px 8px;
border-radius: 4px;
/*white-space: nowrap;*/
margin: 0px;
z-index: 6;
text-align: left;
}
@media (orientation : landscape) {
.aero-doc-h2 {
font-size: 24px;
line-height: 24px;
}
}
@media (orientation : portrait) {
.aero-doc-h2 {
font-size: 20px;
line-height: 20px;
}
}
/* </h2> */
/* <p> */
.aero-doc-p {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
text-align: justify;
z-index: 4;
padding: 0px 0px 0px 0px;
padding: 6px 6px 6px 8px;
border-radius: 4px;
margin: 0px;
}
/* <p> */
.aero-doc-p, .aero-doc-ul {
font-size: 16px;
}
.aero-doc-ul>li {
padding: 8px 8px 8px 16px;
}
@media (orientation : landscape) {
.aero-doc-p {
font-size: 16px;
}
}
@media (orientation : portrait) {
.aero-doc-p {
font-size: 13px;
}
}
/* </p> */
.aero-slide>a {
position: absolute;
z-index: 10;
overflow: hidden;
padding: 12px 24px;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
line-height: 16px;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
user-select: none;
background-repeat: repeat-x;
background-position: -1px -1px;
background-size: 110% 110%;
border: 1px solid rgba(240, 240, 255, 1.0);
border-radius: 8px;
appearance: none;
/* appearance */
color: #ffffff;
background-color: rgba(28, 77, 45, 0.16);
background-image: linear-gradient(-180deg, rgb(46 46 46/ 52%) 0%,
rgb(16 16 16/ 67%) 90%);
backdrop-filter: blur(2px);
text-decoration: none;
}
.aero-slide>a:hover {
background-color: #269f42;
background-image: linear-gradient(-180deg, #2fcb53 0%, #269f42 90%);
background-position: -.5em;
border-color: rgba(27, 31, 35, 0.5);
text-decoration: none;
}
.aero-slide>a:focus {
box-shadow: 0 0 0 0.2em rgba(52, 208, 88, 0.4);
text-decoration: none;
}
.aero-slide>a:active {
background-color: #279f43;
background-image: none;
border-color: rgba(27, 31, 35, 0.5);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
text-decoration: none;
}
/* <themes> */
.aero-doc[theme="light"] {
color: black;
/*background-color: rgba(255, 255, 255, 0.24);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.75);*/
/*text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.75);*/
}
.aero-doc[theme="dark"] {
color: white;
/*background-color: rgba(0, 0, 0, 0.16);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 2px rgba(255, 255, 255, 0.75);*/
}
/* </themes> */
/* <svg> */
.aero-doc-pic-svg {
padding: 32px 16px 32px 16px;
}
.aero-doc-pic-svg svg {
fill: black;
stroke: black;
}
/* </svg> */
/* <code> */
.aero-doc-code-section {
padding: 24px max(5%, 16px) 24px max(5%, 16px);
}
.aero-doc-code-window {
background-color: rgb(33, 23, 59);
border-radius: 16px;
padding: 16px 32px;
color: rgb(87, 211, 211);
font-size: 13px;
}
.aero-doc-code-window pre {
margin: 0;
padding: 0;
overflow-x: scroll;
tab-size: 2;
}
.aero-doc-code-window code {
margin: 0;
padding: 0;
}

338
aero/DocumentationV2.js Normal file
View File

@ -0,0 +1,338 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { Icon } from "./Icon.js";
import { WebPage } from "./WebPage.js";
import { WebPageV2 } from "./WebPageV2.js";
// Using ES6 import syntax
import hljs from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/highlight.min.js';
// and it's easy to individually load additional languages
import java from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/languages/java.min.js';
import xml from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/languages/xml.min.js';
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export const LOW_RESOLUTION_TAG = "-low";
export const HIGH_RESOLUTION_TAG = "-high";
export class DocumentationV2 extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
/**
* @type{List<DocElement>}
*/
elements = new Array();
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
/**
*
* @param {WebPageV2} page
* @param {HTMLElement} sources
*/
constructor(page, sources){
super();
/* CSS requirements */
page.css_requireStylesheet("/aero/Documentation.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-doc");
this.headerNode = document.createElement("div");
this.headerNode.classList.add("aero-doc-header");
this.sectionNode.appendChild(this.headerNode);
this.mainNode = document.createElement("div");
this.mainNode.classList.add("aero-doc-main");
this.tableOfContentsNode = document.createElement("div");
this.tableOfContentsNode.classList.add("aero-doc-table");
this.mainNode.appendChild(this.tableOfContentsNode);
this.contentNode = document.createElement("div");
this.contentNode.classList.add("aero-doc-content");
this.mainNode.appendChild(this.contentNode);
this.sectionNode.appendChild(this.mainNode);
this.headerNode.innerHTML = "header zone";
let val;
this.arrangement = (val = sources.getAttribute("arrangement")) ? val : "std";
this.sectionNode.setAttribute("arrangement", this.arrangement);
/* <id> */
if (sources.id != undefined) { this.sectionNode.id = sources.id; }
/* </id> */
/* <elements> */
let node = sources.firstChild;
let index = 2;
while(node){
let type = node.nodeName.toLowerCase();
switch(type){
case "h1" : this.elements.push(new DocHeader1(page, node, "doc-h1-"+(index++))); break;
case "h2" : this.elements.push(new DocHeader2(page, node)); break;
case "p" : this.elements.push(new DocParagraph(page, node)); break;
case "svg" : this.elements.push(new DocSVG(page, node)); break;
case "code" : this.elements.push(new DocCodeBlock(page, node)); break;
}
node = node.nextSibling;
}
this.elements.forEach(element => this.contentNode.appendChild(element.html_getNode()));
this.elements.forEach(element => element.html_appendTableEntry(this.tableOfContentsNode));
/* </elements> */
}
html_getNode(){
/* return wrapper node */
return this.sectionNode;
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
else if (this.isInitialized && page.imageResolution == 1) {
this.redrawHighRes();
}
}
draw() {
}
}
export class DocElement {
constructor(sources) {
}
}
export class DocHeader1 extends DocElement {
constructor(page, sources, id) {
super(sources);
this.id = id;
this.name = sources.innerHTML;
const headerNode = document.createElement("h1");
headerNode.id = id;
headerNode.classList.add("aero-doc-h1");
headerNode.innerHTML = this.name;
this.headerNode = headerNode;
}
html_getNode() { return this.headerNode; }
html_appendTableEntry(tableOfContentsNode) {
const entryNode = document.createElement("div");
const linkNode = document.createElement("a");
linkNode.href = "#"+this.id;
linkNode.innerHTML = this.name;
entryNode.appendChild(linkNode);
tableOfContentsNode.appendChild(entryNode);
}
}
export class DocHeader2 extends DocElement {
constructor(page, sources) {
super(sources);
const headerNode = document.createElement("h2");
headerNode.classList.add("aero-doc-h2");
headerNode.innerHTML = sources.innerHTML;
this.headerNode = headerNode;
}
html_getNode() { return this.headerNode; }
html_appendTableEntry() { /* nothing to add */}
}
export class DocParagraph extends DocElement {
constructor(page, sources) {
super(sources);
const headerNode = document.createElement("p");
headerNode.classList.add("aero-doc-p");
headerNode.innerHTML = sources.innerHTML;
this.headerNode = headerNode;
}
html_getNode() { return this.headerNode; }
html_appendTableEntry() { /* nothing to add */}
}
export class DocSVG extends DocElement {
constructor(page, sources) {
super(sources);
this.pathname = sources.getAttribute("path");
const wrapperNode = document.createElement("div");
wrapperNode.classList.add("aero-doc-pic-svg");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
let val;
const width = (val = sources.getAttribute("width")) ? parseInt(val) : 128;
const height = (val = sources.getAttribute("height")) ? parseInt(val) : 128;
this.icon = new Icon(this.pathname, { width: width, height: height });
wrapperNode.appendChild(this.icon.build());
this.wrapperNode = wrapperNode;
}
html_getNode() { return this.wrapperNode; }
html_appendTableEntry() { /* nothing to add */}
}
export class DocCodeBlock extends DocElement {
static isLanguageLoaded = false;
/**
*
* @param {WebPageV2} page
* @param {HTMLElement} sources
*/
constructor(page, sources){
super(sources);
this.sourcePathname = sources.getAttribute("path");
if (!this.isLanguageLoaded) {
// Then register the languages you need
hljs.registerLanguage('java', java);
hljs.registerLanguage('xml', xml);
this.isLanguageLoaded = true;
}
//page.css_requireStylesheet("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/styles/default.min.css");
page.css_requireStylesheet("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/styles/atom-one-dark.css");
const wrapperNode = document.createElement("div");
wrapperNode.classList.add("aero-doc-code-section");
const windowNode = document.createElement("div");
windowNode.classList.add("aero-doc-code-window");
// windowNode.classList.add("theme-atom-one-dark");
const preNode = document.createElement("pre");
//preNode.classList.add("theme-atom-one-dark");
const spanNode = document.createElement("span");
//spanNode.classList.add("language-java");
// spanNode.classList.add("hljs");
const codeNode = document.createElement("code");
//codeNode.innerHTML = highlightedCode;
spanNode.appendChild(codeNode);
preNode.appendChild(spanNode);
windowNode.appendChild(preNode);
wrapperNode.appendChild(windowNode);
AeroUtilities.getResourceFromOrigin(this.sourcePathname, "text", sourceCode => {
const highlightedSourceCode = hljs.highlight(sourceCode, { language: 'java' }).value;
codeNode.innerHTML = highlightedSourceCode;
})
this.wrapperNode = wrapperNode;
}
html_getNode() { return this.wrapperNode; }
html_appendTableEntry() { /* nothing to add */}
/**
*
* @param {WebPage} page
*/
render(page) {
/* do nothing */
}
}

130
aero/Footer.css Normal file
View File

@ -0,0 +1,130 @@
/* <footer> */
footer {
background-color: rgb(64, 64, 64);
width: 100%;
color: rgb(128, 128, 128);
}
/* </footer> */
.aero-footer {
background: #2c3840;
color: #8aa0ae;
padding: 0;
margin: 0;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 16px;
font-weight: bold;
}
.aero-footer .marketing-site-footer-menu-social a {
color: #fefefe;
}
.aero-footer .column-block {
margin-bottom: 30px;
}
.aero-footer-row {
margin-bottom: 1rem;
display: flex;
padding: 0 8% 0 8%;
}
.aero-footer-column {
padding: 0px 4% 0px 4%;
}
.aero-footer-social > a > img {
width: 64px;
height: 64px;
margin: 0px 20px 0px 20px;
}
@media screen and (max-width: 39.9375em) {
.aero-footer .columns {
margin-bottom: 2rem;
}
}
.marketing-site-footer-name {
color: #fefefe;
margin-bottom: 1rem;
font-size: 2rem;
}
.marketing-site-footer-title {
color: #fefefe;
margin-bottom: 1rem;
font-size: 1.25rem;
}
.marketing-site-footer-block {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
margin-bottom: 1rem;
}
.marketing-site-footer-block .fa {
font-size: 2rem;
color: #020304;
}
.marketing-site-footer-block p {
margin-left: 1rem;
line-height: 1.125rem;
}
.aero-footer-bottom {
background: #020304;
padding: 8px 8% 8px 8%;
margin-bottom: 0;
color: white;
}
.aero-footer-bottom > a {
display: inline-block;
padding: 2px 8px 2px 8px;
margin: 0px 0px 0px 0px;
border-left: solid 1px #8aa0ae;
text-decoration: none;
color: rgb(128, 128, 128);
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 14px;
font-weight: normal;
}
.aero-footer-bottom > a:hover {
text-decoration: underline;
}
.marketing-site-footer-bottom .marketing-site-footer-bottom-links a {
color: #8aa0ae;
}
@media screen and (max-width: 63.9375em) {
.marketing-site-footer-bottom .marketing-site-footer-bottom-links {
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
}
@media screen and (max-width: 63.9375em) {
.marketing-site-footer-bottom {
text-align: center;
}
}
/* <icon> */
.aero-footer-social-link {
width: 64px;
height: 64px;
margin: 0px 20px 0px 20px;
}

48
aero/Footer.js Normal file
View File

@ -0,0 +1,48 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
export class Footer extends AeroElement {
/** @type{HTMLElement} */
footerNode;
props;
constructor(contentPathname, props) {
super();
this.contentPathname = contentPathname
this.props = props;
}
/**
*
* @param {WebPage} page
* @returns {HTMLElement}
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/Footer.css");
/* build nodes */
this.footerNode = document.createElement('footer');
this.footerNode.classList.add('aero-footer');
AeroUtilities.sendRequest_HTTP_GET(this.contentPathname, "text", content => {
this.footerNode.innerHTML = content;
});
/* return wrapper node */
return this.footerNode;
}
/**
*
* @param {WebPage} page
*/
render(page) {
}
}

46
aero/FooterV2.js Normal file
View File

@ -0,0 +1,46 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { WebPageV2 } from "./WebPageV2.js";
export class FooterV2 extends AeroElement {
/** @type{HTMLElement} */
footerNode;
/**
*
* @param {WebPageV2} page
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super();
/* CSS requirements */
page.css_requireStylesheet("/aero/Footer.css");
/* build nodes */
this.footerNode = document.createElement('footer');
this.footerNode.classList.add('aero-footer');
this.contentPathname = sources.getAttribute("path");
AeroUtilities.sendRequest_HTTP_GET(this.contentPathname, "text", content => {
this.footerNode.innerHTML = content;
});
}
html_getNode() {
/* return wrapper node */
return this.footerNode;
}
/**
*
* @param {WebPageV2} page
*/
render(page) {
}
}

348
aero/Grid.css Normal file
View File

@ -0,0 +1,348 @@
/* <aero-grid> */
.aero-grid {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
width: 100%;
}
.aero-grid > div.text {
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
/* <asset> */
div.aero-grid-asset {
margin: 0px 0px 0px 0px;
padding: 8px 12% 8px 12%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
height: 600px;
z-index: 2;
/*overflow: auto;*/
}
@media (orientation : landscape) {
div.aero-grid-asset {
height: 600px;
padding: 8px 12% 8px 12%;
}
}
@media (orientation : portrait) {
div.aero-grid-asset {
height: 320px;
padding: 4px 0px 4px 0px;
}
}
/* <asset> */
/* <metrics> */
div.aero-grid[type = "metrics"] {
margin: 0px 0px 0px 0px;
padding: 8px 12% 8px 12%;
display: inline-flex;
background-color: black;
z-index: 2;
/*overflow: auto;*/
}
div.aero-grid-metrics-item {
flex: auto;
padding: 20px;
}
div.aero-grid-metrics-item * {
padding: 0px;
margin: 0px;
}
div.aero-grid-metrics-item-value>span {
vertical-align: baseline;
color: #9fffa5;
}
div.aero-grid-metrics-item-value>span.modifier {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 64px;
font-weight: normal;
}
div.aero-grid-metrics-item-value>span.number {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 64px;
font-weight: bold;
padding: 0px 4px 0px 4px;
}
div.aero-grid-metrics-item-value>span.unit {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 32px;
font-weight: bold;
}
div.aero-grid-metrics-item-parameter {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 16px;
font-weight: normal;
padding: 8px;
color: #6be8ea;
}
@media (orientation : landscape) {
/* default */
div.aero-grid-metrics-item {
border-left: 1px solid rgba(64, 64, 64, 0.92);
}
div.aero-grid[type = "metrics"]>div.aero-grid-metrics-item:first-child {
border-left: none;
}
}
@media (orientation : portrait) {
div.aero-grid[type="metrics"] {
display: flex;
flex-wrap: wrap;
}
div.aero-grid-metrics-item {
border-top: 1px solid rgba(64, 64, 64, 0.92);
}
div.aero-grid[type = "metrics"] > div.aero-grid-metrics-item:first-child {
border-top: none;
}
}
/* </metrics> */
/* <h1> */
.aero-grid h1 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: lighter;
max-width: 92%;
padding: 8px;
border-radius: 4px;
margin: 0px;
z-index: 8;
text-align: center;
}
@media (orientation : landscape) {
.aero-grid h1{
font-size: 64px;
line-height: 64px;
}
}
@media (orientation : portrait) {
aero-grid h1{
font-size: 48px;
line-height: 48px;
}
}
.aero-grid h1 > span.emphasis {
font-weight: bold;
}
/* </h1> */
/* <h2> */
.aero-grid h2 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 24px;
line-height: 24px;
font-weight: bold;
max-width: 92%;
padding: 8px;
border-radius: 4px;
/*white-space: nowrap;*/
margin: 0px;
z-index: 6;
text-align: center;
}
@media (orientation : landscape) {
.aero-grid h2 {
font-size: 24px;
line-height: 24px;
}
}
@media (orientation : portrait) {
.aero-grid h2 {
font-size: 20px;
line-height: 20px;
}
}
/* </h2> */
.aero-grid p {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
text-align: justify;
z-index: 4;
padding: 0px 0px 0px 0px;
padding: 6px 6px 6px 8px;
border-radius: 4px;
margin: 0px;
}
.aero-grid > a {
position: absolute;
z-index: 10;
overflow: hidden;
padding: 12px 24px;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
line-height: 16px;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
user-select: none;
background-repeat: repeat-x;
background-position: -1px -1px;
background-size: 110% 110%;
border: 1px solid rgba(240, 240, 255, 1.0);
border-radius: 8px;
appearance: none;
/* appearance */
color: #ffffff;
background-color: rgba(28, 77, 45, 0.16);
background-image: linear-gradient(-180deg, rgb(46 46 46/ 52%) 0%,
rgb(16 16 16/ 67%) 90%);
backdrop-filter: blur(2px);
text-decoration: none;
}
.aero-grid > a:hover {
background-color: #269f42;
background-image: linear-gradient(-180deg, #2fcb53 0%, #269f42 90%);
background-position: -.5em;
border-color: rgba(27, 31, 35, 0.5);
text-decoration: none;
}
.aero-grid > a:focus {
box-shadow: 0 0 0 0.2em rgba(52, 208, 88, 0.4);
text-decoration: none;
}
.aero-grid > a:active {
background-color: #279f43;
background-image: none;
border-color: rgba(27, 31, 35, 0.5);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
text-decoration: none;
}
@media (orientation : landscape) {}
@media (orientation : portrait) {
.aero-grid h1 {
font-size: 32px;
line-height: 32px;
}
.aero-grid h2 {
font-size: 18px;
line-height: 18px;
}
.aero-grid p {
font-size: 16px;
}
}
.aero-grid-paragraph {
font-size: 16px;
padding: 32px 0px 32px 0px;
}
/* </aero-grids> */
/* <aero-grid-prime> */
/* </aero-grid-prime> */
/* <themes> */
.aero-grid[theme = "light"] {
color: black;
/*background-color: rgba(255, 255, 255, 0.24);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.75);*/
/*text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.75);*/
}
.aero-grid[theme = "dark"] {
color: white;
/*background-color: rgba(0, 0, 0, 0.16);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 2px rgba(255, 255, 255, 0.75);*/
}
/* </themes> */
/* <backgrounds> */
.background-color {
background-repeat: no-repeat;
}
.background-pic {
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
/* </backgrounds> */
.aero-grid-deck {
left: 50%;
position: relative;
transform: translateX(-50vw);
margin: 64px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, auto));
/* flex-wrap: wrap; */
gap: 32px;
align-items: center;
}
/* <cards> */
.aero-grid-card {
width: 240px;
aspect-ratio: 2.5 / 3.5;
border: none;
border-radius: 16px;
box-shadow: 0px 0px 8px rgba(75, 75, 75, 0.532);
}
/* </cards> */

208
aero/Grid.js Normal file
View File

@ -0,0 +1,208 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
import { LoadHandler } from "./aero.js";
import { AeroUtilities } from "./AeroUtilities.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export class Grid extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type {HTMLDivElement} */
deckNode;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
constructor(type, props) {
super();
this.type = type;
this.props = props;
}
/**
*
* @param {WebPage} page
* @param {*} state
* @returns
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/Grid.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-grid");
this.setType(this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
/* <background> */
if (this.props.backgroundImage) {
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, this.props.backgroundImage);
}
else if (this.props.backgroundColor) {
this.sectionNode.classList.add("background-colo");
this.sectionNode.style.backgroundColor = this.props.backgroundColor;
}
/* </background> */
/* <deck> */
this.deckNode = document.createElement("div");
this.deckNode.classList.add("aero-grid-deck");
this.props.cards.forEach(card => this.deckNode.appendChild(card.build(page)));
this.sectionNode.appendChild(this.deckNode);
/* </deck> */
return this.sectionNode;
}
setType(type) {
this.sectionNode.setAttribute("type", type);
}
setTheme(theme) {
this.sectionNode.setAttribute("theme", theme);
}
render(state) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
}
draw() {
}
}
export class GridCard extends AeroElement {
/** @type {HTMLDivElement } */
cardNode;
type;
props;
/** @type {HTMLDivElement} */
assetNode;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
constructor(type, props) {
super();
this.type = type;
this.props = props;
}
/**
*
* @param {LoadHandler} handler
* @param {*} state
* @returns
*/
build(page) {
this.cardNode = document.createElement("div");
this.cardNode.classList.add("aero-grid-card");
/* <background> */
if (this.props.backgroundImage) {
this.cardNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.cardNode, this.props.backgroundImage);
}
else if (this.props.backgroundColor) {
this.cardNode.classList.add("background-color");
this.cardNode.style.backgroundColor = this.props.backgroundColor;
}
/* </background> */
this.setType(this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
return this.cardNode;
}
setType(type) {
this.cardNode.setAttribute("type", type);
}
setTheme(theme) {
this.cardNode.setAttribute("theme", theme);
}
}

320
aero/Header.css Normal file
View File

@ -0,0 +1,320 @@
/* <header> */
header {
background-color: rgb(255, 255, 255);
/*width: 100%;*/
width: 100vw;
color: black;
}
.aero-header-placeholder {
width: 100vw;
height: 64px;
}
.aero-header-flying {
width: 100vw;
height: 64px;
position: fixed;
top: 0px;
left: 0px;
z-index: 128;
}
.aero-header-bar {
height: 64px;
}
/* <placeholder> */
header[theme="light"] > .aero-header-placeholder {
background-color: rgb(255, 255, 255);
color: black;
}
header[theme="dark"] > .aero-header-placeholder {
background-color: rgb(0, 0, 0);
color: rgb(255, 255, 255);
}
/* </placeholder> */
/* <flying> */
header[theme="light"] > .aero-header-flying {
background-color: rgb(255, 255, 255);
}
header[theme="dark"] > .aero-header-flying {
background-color: rgb(0, 0, 0);
}
/* </flying> */
/* <bar> */
header[theme="light"] .aero-header-bar {
background-color: rgb(255, 255, 255);
color: black;
border-bottom: solid 1px rgba(192, 192, 192, 0.76);
}
header[theme="dark"] .aero-header-bar {
background-color: rgb(0, 0, 0);
color: rgb(255, 255, 255);
border-bottom: solid 1px rgba(64, 64, 64, 0.76);
}
/* </bar> */
header[theme="dark"] > .aero-header-bar, header[theme="dark"] > .aero-header-placeholder {
background-color: rgb(0, 0, 0);
color: rgb(255, 255, 255);
}
.aero-header-menu>a {
color: rgb(64, 64, 64);
text-decoration: none;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 14px;
font-weight: bold;
}
.menu-login {
width: 64px;
cursor: pointer;
}
.menu-login:hover>img {
fill: blue;
}
.menu-login>img>svg {
fill: black;
}
/* <nav> */
@media (orientation : landscape) {
header {
height: 64px;
}
.aero-header-placeholder {
height: 64px;
}
.aero-header-logo {
width: 12%;
min-width: 64px;
cursor: pointer;
}
.aero-header-logo>img {
margin: 8px 16px 8px 16px;
height: 48px;
width: 48px;
}
.aero-header-bar {
height: 64px;
padding: 0px 4% 0px 4%;
display: flex;
flex-direction: row;
}
.aero-header-bar>* {
flex: auto;
}
nav {
z-index: 12;
width: 72%;
}
nav>ul {
margin: 0px 0px 0px 0px;
margin-inline-start: 0px;
padding-inline-start: 0px;
}
.aero-header-menu {
display: inline-block;
color: red;
text-decoration: none;
padding: 8px 12px 4px 12px;
line-height: 48px;
height: 48px;
cursor: pointer;
}
.aero-header-menu[selected] {
border-bottom: solid 4px rgb(224, 149, 0);
}
.aero-header-menu>a {
padding: 8px;
margin: 0px;
vertical-align: baseline;
}
header[theme="dark"] .aero-header-menu>a {
color: rgb(239, 239, 239);
}
.aero-header-menu:hover>a {
background-color: rgb(94, 53, 231);
border-radius: 4px;
color: rgb(255, 243, 249);
}
.aero-header-social {
width: 16%;
min-width: 64px;
/*overflow: hidden; */
}
.aero-header-social-link>img {
margin: 16px;
width: 32px;
height: 32px;
}
}
@media (orientation : portrait) {
header {
height: 64px;
}
.aero-header-bar {
height: 64px;
padding: 0px 0px 0px 0px;
}
.aero-menu-icons-wrapper {
display: inline-block;
vertical-align: top;
display: flex;
height: 64px;
}
.menu-handler {
display: inline-block;
vertical-align: top;
padding: 0px;
margin: 0px 0px 0px 0px;
cursor: pointer;
}
.menu-handler>img {
margin: 14px 14px 14px 14px;
/*height: 48px;*/
width: 36px;
}
.aero-header-logo {
display: inline-block;
vertical-align: top;
width: 80px;
margin: 0px 0px 0px calc(50vw - 96px);
}
.aero-header-logo>img {
margin: 4px 0px 0px 0px;
width: 56px;
}
nav {
z-index: 12;
width: 80vw;
position: absolute;
top: 72px;
left: 50vw;
transform: translateX(-50%);
padding: 0px;
visibility: hidden;
color: rgb(64, 64, 64);
border: solid 1px rgb(192, 192, 192, 0.76);
background-color: rgba(232, 232, 232, 0.64);
backdrop-filter: blur(16px);
padding: 16px 0 16px 0;
border-radius: 12px;
}
@media screen and (max-width: 600px) {
nav {
width: calc(100% - 64px);
}
}
nav>ul {
margin: 0px 0px 0px 0px;
margin-inline-start: 0px;
padding-inline-start: 0px;
}
.aero-header-menu {
display: block;
color: red;
text-decoration: none;
padding: 12px 12px 12px 12px;
}
.aero-header-menu:first-child {
border-top: none;
}
.aero-header-menu:hover>a {
background-color: rgb(199, 204, 208);
border-radius: 4px;
}
.aero-header-menu[selected] {
border-left: solid 8px rgb(224, 149, 0);
}
.aero-header-menu>a {
font-weight: lighter;
line-height: 48px;
height: 48px;
font-size: 20px;
font-weight: bold;
/*padding: 0px;*/
padding: 8px 8px 8px 16px;
margin: 0px;
color: rgb(0, 0, 0);
vertical-align: baseline;
}
.aero-header-social {
display: inline-block;
vertical-align: top;
margin: 0px 0px 10px 0px;
margin-left: auto;
}
.aero-header-social-link>img {
margin: 16px;
width: 32px;
height: 32px;
}
}
/* </nav> */
/* </header> */

402
aero/HeaderV2.js Normal file
View File

@ -0,0 +1,402 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
import { clearChildNodes } from "./aero.js";
/*
export const MENUS = ["Home", "Technology", "Applications", "Team", "Contact"];
export const HREF = ["/index.html", "/technology.html", "/applications.html", "/team.html", "/contact.html"];
*/
/**
*
*/
export class HeaderV2 extends AeroElement {
/** @type{HTMLHeadElement} */
headerNode;
/**
* @type{Nav}
*/
nav;
/**
* @type{Social}
*/
social;
/**
* @type {boolean}
*/
isNavVisible;
/**
* @type{String}
* Color of the flat elements (icon/logo)
*/
flatColor;
/**
*
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super();
this.flatColor = "black";
let val;
this.theme = (val = sources.getAttribute("theme")) ? val : "light";
switch (this.theme) {
default:
case "light": this.flatColor = "black"; break;
case "dark": this.flatColor = "white"; break;
}
this.logo = (val = sources.getAttribute("logo")) ? val : "light";
/* CSS requirements */
page.css_requireStylesheet("/aero/Header.css");
/* build nodes */
this.headerNode = document.createElement('header');
this.headerNode.setAttribute("theme", this.theme);
this.isLandscape = page.isLandscape;
/* build menus */
let node = sources.firstChild;
while (node) {
if (node.nodeName.toLowerCase() == "nav") {
this.nav = new Nav(node);
}
else if (node.nodeName.toLowerCase() == "social") {
this.social = new Social(node);
}
/* save next node */
node = node.nextSibling;
}
this.draw(page, sources);
}
/**
*
* @param {WebPage} page
* @param {HTMLElement} sourceNode
*
* @returns {HTMLElement}
*/
html_getNode() {
/* return wrapper node */
return this.headerNode;
}
load() { /* nothing to load here */ }
/**
*
* @param {WebPage} page
* @returns {}
*/
render(page) {
if (page.isLandscape != this.isLandscape) { // repaint
this.isLandscape = page.isLandscape;
clearChildNodes(this.headerNode);
this.draw();
}
}
draw() {
const placeholderNode = document.createElement("div");
placeholderNode.classList.add("aero-header-placeholder");
this.headerNode.appendChild(placeholderNode);
const flyingNode = document.createElement("div");
flyingNode.classList.add("aero-header-flying");
const barNode = document.createElement("div");
barNode.classList.add("aero-header-bar");
if (this.isLandscape) {
this.drawLandscape(barNode);
}
else {
this.drawPortrait(barNode);
}
flyingNode.appendChild(barNode);
this.headerNode.appendChild(flyingNode);
let lastKnowScrollY = 0;
let deltaScrollY = 0;
let upwardDeltaScrollY = 0;
let ticking = false;
let barPositionY = 0;
let previousMove = 0; /* O :undefined, -1:upward, +1:downward */
const udpateBarPosition = function (y) { flyingNode.style.top = `${y}px`; }
window.addEventListener("scroll", function (e) {
deltaScrollY = window.scrollY - lastKnowScrollY;
lastKnowScrollY = window.scrollY;
if (deltaScrollY < 0) { /* going upward, deltaScrollY < 0 */
//if(previousMove != -1){ barPositionY = -68; }
barPositionY -= deltaScrollY;
//previousMove = -1;
}
else { /* downward, deltaScrollY > 0 */
barPositionY -= deltaScrollY;
//previousMove = 1;
}
if (barPositionY > 0) { barPositionY = 0; }
if (barPositionY < -65) { barPositionY = -65; }
console.log(`barPositionY: ${barPositionY}`);
if (!ticking) {
window.requestAnimationFrame(function () {
udpateBarPosition(barPositionY);
ticking = false;
});
}
ticking = true;
});
}
drawLandscape(barNode) {
/* <front-icon> */
let menuLogoNode = document.createElement("div");
menuLogoNode.classList.add("aero-header-logo");
let frontImgNode = document.createElement("img");
frontImgNode.src = this.logo;
frontImgNode.alt = "logo";
menuLogoNode.appendChild(frontImgNode);
barNode.appendChild(menuLogoNode);
/* </front-icon> */
/* <nav> */
const navNode = this.nav.html_getNode();
barNode.appendChild(navNode);
navNode.style.visibility = "visible";
this.isNavVisible = true; // visible by default in landscape
/* </nav> */
/* <login-icon> */
if(this.social){
barNode.appendChild(this.social.html_getNode());
}
/* </login-icon> */
}
drawPortrait(barNode) {
let iconsWrapperNode = document.createElement("div");
iconsWrapperNode.classList.add("aero-menu-icons-wrapper");
/* <menu-handler-icon> */
let menuHandlerNode = document.createElement("div");
menuHandlerNode.classList.add("menu-handler");
let menuHandlerImgNode = document.createElement("img");
menuHandlerImgNode.src = `/icons/menu-${this.flatColor}.svg`;
menuHandlerImgNode.alt = "menu";
menuHandlerNode.appendChild(menuHandlerImgNode);
iconsWrapperNode.appendChild(menuHandlerNode);
/* </menu-handler-icon> */
/* <logo-icon> */
let menuLogoNode = document.createElement("div");
menuLogoNode.classList.add("aero-header-logo");
let frontImgNode = document.createElement("img");
frontImgNode.src = this.logo;
frontImgNode.alt = "logo";
menuLogoNode.appendChild(frontImgNode);
iconsWrapperNode.appendChild(menuLogoNode);
/* </logo-icon> */
barNode.appendChild(iconsWrapperNode);
let navNode = this.nav.html_getNode();
barNode.appendChild(navNode);
this.isNavVisible = false; // hidden by default in portrait
navNode.style.visibility = "hidden";
let _this = this;
menuHandlerNode.addEventListener("click", function () {
navNode.style.visibility = _this.isNavVisible ? "hidden" : "visible";
_this.isNavVisible = !_this.isNavVisible;
}, false);
/* <login-icon> */
iconsWrapperNode.appendChild(this.social.html_getNode());
/* </login-icon> */
}
buildNavNode() {
/* <nav> */
let navNode = document.createElement('nav');
let unorderedListNode = document.createElement('ul');
this.menus.forEach(menu => unorderedListNode.appendChild(menu.html_getNode()));
navNode.appendChild(unorderedListNode);
/* </nav> */
return navNode;
}
buildLoginNode() {
/* <login-icon> */
const loginNode = document.createElement("a");
loginNode.href = "https://app.alphaventor.com";
loginNode.classList.add("menu-login");
let loginImgNode = document.createElement("img");
loginImgNode.src = `/icons/login-${this.flatColor}.svg`;
loginImgNode.alt = "login";
loginNode.appendChild(loginImgNode);
return loginNode;
/* </login-icon> */
}
/**
*
* @param {AeroWebPage} page
*/
link(page) {
this.page = page;
page.import_CSS("aero/AeroHeader.css");
}
isLoaded() {
return this.isInitialized;
}
}
class Nav {
/**
* @type{Array<Menu>}
*/
menus = new Array();
constructor(sources){
let node = sources.firstChild;
while (node) {
if (node.nodeName.toLowerCase() == "menu") {
this.menus.push(new Menu(node));
}
/* save next node */
node = node.nextSibling;
}
/* <nav> */
let navNode = document.createElement('nav');
let unorderedListNode = document.createElement('ul');
this.menus.forEach(menu => unorderedListNode.appendChild(menu.html_getNode()));
navNode.appendChild(unorderedListNode);
/* </nav> */
this.navNode = navNode;
}
html_getNode(){ return this.navNode; }
}
class Menu {
constructor(source){
let listItemNode = document.createElement('li');
listItemNode.classList.add("aero-header-menu")
let isSelected = (source.getAttribute("selected") != undefined);
if (isSelected) {
listItemNode.setAttribute("selected", "");
}
let aNode = document.createElement("a");
aNode.href = isSelected ? "/" : source.getAttribute("to");
aNode.innerHTML = source.innerHTML;
listItemNode.appendChild(aNode);
this.listItemNode = listItemNode;
}
html_getNode(){
return this.listItemNode;
}
}
class Social {
/**
* @type{Array<Link>}
*/
links = new Array();
constructor(sources){
let node = sources.firstChild;
while (node) {
if (node.nodeName.toLowerCase() == "a") {
this.links.push(new Link(node));
}
/* save next node */
node = node.nextSibling;
}
/* <wrapper> */
let socialNode = document.createElement('div');
socialNode.classList.add("aero-header-social");
this.links.forEach(link => socialNode.appendChild(link.html_getNode()));
/* </wrapper> */
this.socialNode = socialNode;
}
html_getNode(){ return this.socialNode; }
}
class Link {
constructor(sources){
/* <login-icon> */
const loginNode = document.createElement("a");
loginNode.href = sources.getAttribute("to");
loginNode.classList.add("aero-header-social-link");
let loginImgNode = document.createElement("img");
loginImgNode.src = sources.getAttribute("pic");
loginImgNode.alt = "login";
loginNode.appendChild(loginImgNode);
this.loginNode = loginNode;
/* </login-icon> */
}
html_getNode(){ return this.loginNode; }
}

45
aero/Icon.js Normal file
View File

@ -0,0 +1,45 @@
import { AeroUtilities } from "./AeroUtilities.js";
export class Icon {
constructor(pathname, props) {
this.pathname = pathname;
this.props = props;
this.width = props.width ? props.width : 64;
this.height = props.height ? props.height : 64;
}
build() {
this.wrapperNode = document.createElement("div");
AeroUtilities.getResourceFromOrigin(this.pathname, "text", responseText => {
this.wrapperNode.innerHTML = responseText;
let svgNode = this.wrapperNode.getElementsByTagName("svg")[0];
svgNode.setAttribute("width", this.width);
svgNode.setAttribute("height", this.height);
this.svgNode = svgNode;
this.isSVGNodeLoaded = true;
});
return this.wrapperNode;
}
getEnvelope(){ return this.wrapperNode; }
}
export function SVG_inject(target, pathname, width, height){
AeroUtilities.getResourceFromOrigin(pathname, "text", responseText => {
target.innerHTML = responseText;
const svgNode = target.getElementsByTagName("svg")[0];
svgNode.setAttribute("width", width ? width : 64);
svgNode.setAttribute("height", height ? height : 64);
});
}

141
aero/ModalBox.css Normal file
View File

@ -0,0 +1,141 @@
/* modal box */
.modalbox-overlay {
position: fixed;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
background-color: #808080d9;
z-index: 64;
}
.modalbox {
position: absolute;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
width: 600px;
background-color: rgb(240, 240, 240);
border-radius: 16px;
border: 1px solid grey;
box-shadow: rgba(64, 64, 64, 0.507) 0px 4px 16px;
display: flex;
flex-direction: row;
padding: 24px;
z-index: 68;
}
.modalbox-icon {
width: 120px;
margin: 24px;
background-size: contain;
background-repeat: no-repeat;
}
.modalbox-icon>svg {
fill: rgb(241, 241, 41);
filter: drop-shadow(0px 1px 4px rgb(0 0 0 / 0.4));
}
.modalbox-main {
font-family: Arial, Helvetica, sans-serif;
display: flex;
flex-direction: column;
padding: 0px;
}
.modalbox-main>div:last-child {
margin-top: auto;
}
.modalbox-message {
font-size: 20px;
font-weight: bold;
margin-bottom: 80px;
}
.modalbox-message>h1 {
margin: 16px 8px 16px 8px;
font-size: 32px;
font-weight: bold;
}
.modalbox-message>p {
margin: 32px 8px 8px 8px;
font-size: 16px;
font-weight: normal;
}
.modalbox-validation {
padding: 8px;
display: flex;
flex-direction: row;
justify-content: end;
/* Pack items from the end */
}
.modalbox-validation>* {
margin: 2px 8px 2px 8px;
padding: 0px;
}
.modalbox-button {
border: solid 1px green;
padding: 12px 24px 12px 24px;
border-radius: 8px;
background-color: rgb(18, 173, 18);
color: white;
outline: solid 8px rgba(166, 213, 180, 0.588);
cursor: pointer;
font-size: 20px;
}
.modalbox-button:hover {
border: solid 1px rgb(1, 144, 1);
background-color: rgb(17, 197, 17);
}
/* <nav> */
@media (orientation : landscape) {
.modalbox {
width: 600px;
padding: 24px;
flex-direction: row;
}
.modalbox-icon {
width: 120px;
margin: 24px;
}
}
@media (orientation : portrait) {
.modalbox {
width: 80vw;
padding: 5vw;
flex-direction: column;
}
.modalbox-icon {
height: 18vh;
margin: 4vw;
width: auto;
background-position: center;
}
.modalbox-button {
flex-shrink: 0;
flex-grow: 1;
}
}

87
aero/ModalBox.js Normal file
View File

@ -0,0 +1,87 @@
import { AeroElement } from "./AeroElement.js";
export class ModalBox extends AeroElement {
/** @type{object} */
modalLayer;
/**
* @type {HTMLDivElement}
*/
boxNode;
/**
*
* @param {HTMLDivElement} parentNode
*/
constructor(props, onProceed) {
super();
this.wrapperNode = document.createElement("div");
const overlayNode = document.createElement("div");
overlayNode.classList.add("modalbox-overlay");
this.wrapperNode.appendChild(overlayNode);
this.boxNode = document.createElement("div");
this.boxNode.classList.add("modalbox");
/* <left> */
this.iconNode = document.createElement("div");
this.iconNode.classList.add("modalbox-icon");
this.iconNode.style.backgroundImage = `url(${props.image})`;
this.boxNode.appendChild(this.iconNode);
/* </left> */
/* <right> */
this.mainNode = document.createElement("div");
this.mainNode.classList.add("modalbox-main");
/* <message> */
this.messageNode = document.createElement("div");
this.messageNode.classList.add("modalbox-message");
const titleNode = document.createElement("h1");
titleNode.innerHTML = props.title;
this.messageNode.appendChild(titleNode);
const explanationNode = document.createElement("p");
explanationNode.innerHTML = props.explanation;
this.messageNode.appendChild(explanationNode);
this.mainNode.appendChild(this.messageNode);
/* </message> */
this.controlsNode = document.createElement("div");
this.controlsNode.classList.add("modalbox-validation");
this.mainNode.appendChild(this.controlsNode);
this.buttonNode = document.createElement("div");
this.buttonNode.classList.add("modalbox-button");
this.buttonNode.innerHTML = "Proceed to Website";
this.buttonNode.addEventListener("click", function (event) {
event.stopPropagation();
onProceed();
}, false);
this.controlsNode.appendChild(this.buttonNode);
this.boxNode.appendChild(this.mainNode);
/* </right> */
this.wrapperNode.appendChild(this.boxNode);
}
getEnvelope() {
return this.wrapperNode;
}
}

344
aero/Slide.css Normal file
View File

@ -0,0 +1,344 @@
/* <aero-slide> */
.aero-slide {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
width: 100%;
display: flex;
flex-direction: column;
box-sizing: content-box;
}
/* <text> */
.aero-slide-text {
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
@media (orientation : landscape) {
div.aero-slide-text {
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
}
@media (orientation : portrait) {
div.aero-slide-text {
margin: 0px 0px 0px 0px;
padding: 8px 4% 8px 4%;
}
}
/* <text> */
/* <asset> */
div.aero-slide-picture {
padding: 0px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
z-index: 2;
aspect-ratio: 3 / 2;
/*overflow: auto;*/
}
@media (orientation : landscape) {
div.aero-slide-picture {
margin: 0px 20% 0px 20%;
width: 60%;
}
.aero-slide[type="hThird"]>.aero-slide-picture {
margin: 32px 32px 32px 32px;
background-size: contain;
}
}
@media (orientation : portrait) {
div.aero-slide-picture {
margin: 0px 4% 0px 4%;
width: 92%;
}
.aero-slide[type="hThird"]>.aero-slide-picture {
margin: 32px 32px 32px 32px;
background-size: contain;
}
.aero-slide[type="hThird"] {
display: flex;
flex-direction: row-reverse;
padding: 8px 16% 8px 16%;
}
}
/* <asset> */
/* <arrangements> */
@media (orientation : landscape) {
.aero-slide[arrangement="text-up"] {
flex-direction: column;
}
.aero-slide[arrangement="text-down"] {
flex-direction: column-reverse;
}
.aero-slide[arrangement="text-left"] {
flex-direction: row;
}
.aero-slide[arrangement="text-right"] {
flex-direction: row-reverse;
}
}
/* </arrangements> */
/* <h1> */
.aero-slide-text>h1 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: lighter;
max-width: 92%;
padding: 8px;
border-radius: 4px;
margin: 0px;
z-index: 8;
text-align: left;
}
@media (orientation : landscape) {
.aero-slide-text>h1 {
font-size: 64px;
line-height: 64px;
}
}
@media (orientation : portrait) {
aero-slide-text>h1 {
font-size: 48px;
line-height: 48px;
}
}
.aero-slide-text>h1>span.emphasis {
font-weight: bold;
}
/* </h1> */
/* <h2> */
.aero-slide-text>h2 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 24px;
line-height: 24px;
font-weight: bold;
max-width: 92%;
padding: 8px;
border-radius: 4px;
/*white-space: nowrap;*/
margin: 0px;
z-index: 6;
text-align: left;
}
@media (orientation : landscape) {
.aero-slide-text>h2 {
font-size: 24px;
line-height: 24px;
}
}
@media (orientation : portrait) {
.aero-slide-text>h2 {
font-size: 20px;
line-height: 20px;
}
}
/* </h2> */
.aero-slide-text>p {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
text-align: left;
z-index: 4;
padding: 0px 0px 0px 0px;
padding: 6px 6px 6px 8px;
border-radius: 4px;
margin: 0px;
}
@media (orientation : landscape) {
.aero-slide-text>p {
font-size: 16px;
}
}
@media (orientation : portrait) {
.aero-slide-text>p {
font-size: 20px;
}
}
.aero-slide>a {
position: absolute;
z-index: 10;
overflow: hidden;
padding: 12px 24px;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
line-height: 16px;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
user-select: none;
background-repeat: repeat-x;
background-position: -1px -1px;
background-size: 110% 110%;
border: 1px solid rgba(240, 240, 255, 1.0);
border-radius: 8px;
appearance: none;
/* appearance */
color: #ffffff;
background-color: rgba(28, 77, 45, 0.16);
background-image: linear-gradient(-180deg, rgb(46 46 46/ 52%) 0%,
rgb(16 16 16/ 67%) 90%);
backdrop-filter: blur(2px);
text-decoration: none;
}
.aero-slide>a:hover {
background-color: #269f42;
background-image: linear-gradient(-180deg, #2fcb53 0%, #269f42 90%);
background-position: -.5em;
border-color: rgba(27, 31, 35, 0.5);
text-decoration: none;
}
.aero-slide>a:focus {
box-shadow: 0 0 0 0.2em rgba(52, 208, 88, 0.4);
text-decoration: none;
}
.aero-slide>a:active {
background-color: #279f43;
background-image: none;
border-color: rgba(27, 31, 35, 0.5);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
text-decoration: none;
}
@media (orientation : landscape) {}
@media (orientation : portrait) {
.aero-slide h1 {
font-size: 32px;
line-height: 32px;
}
.aero-slide h2 {
font-size: 18px;
line-height: 18px;
}
.aero-slide p {
font-size: 16px;
}
}
.aero-slide-paragraph {
font-size: 16px;
padding: 32px 0px 32px 0px;
}
/* </aero-slides> */
/* <aero-slide-prime> */
/* </aero-slide-prime> */
/* <themes> */
.aero-slide[theme="light"] {
color: black;
/*background-color: rgba(255, 255, 255, 0.24);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.75);*/
/*text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.75);*/
}
.aero-slide[theme="dark"] {
color: white;
/*background-color: rgba(0, 0, 0, 0.16);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 2px rgba(255, 255, 255, 0.75);*/
}
/* </themes> */
/* <backgrounds> */
div[class^="background-"] {
background-repeat: no-repeat;
}
.background-white {
background-color: white;
}
.background-blue {
background-color: blue;
}
.background-teal {
background-color: teal;
}
.background-black {
background-color: black;
}
.background-grey64 {
background-color: rgb(64, 64, 64);
}
.background-grey128 {
background-color: rgb(128, 128, 128);
}
.background-grey192 {
background-color: rgb(192, 192, 192);
}
.background-pic {
background-size: cover;
background-position: center;
}
/* </backgrounds> */

309
aero/Slide.js Normal file
View File

@ -0,0 +1,309 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { WebPage } from "./WebPage.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export const LOW_RESOLUTION_TAG = "-low";
export const HIGH_RESOLUTION_TAG = "-high";
export class Slide extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
constructor(type, props) {
super();
this.type = type;
this.props = props;
}
/**
*
* @param {WebPage} handler
* @returns {HTMLElement}
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/Slide.css");
page.css_requireStylesheet("/aero/gradient-backgrounds.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-slide");
this.sectionNode.setAttribute("type", this.type);
this.setType(this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
if (this.props.arrangement) { this.setArrangement(this.props.arrangement); }
/* <id> */
if (this.props.id != undefined) {
this.sectionNode.id = this.props.id;
}
/* </id> */
/* <background> */
if (this.props.background != undefined || this.props.backgroundColor != undefined) {
let backgroundParam = this.props.background;
switch (backgroundParam) {
case "black": this.sectionNode.classList.add("background-black"); break;
case "white": this.sectionNode.classList.add("background-white"); break;
case "grey64": this.sectionNode.classList.add("background-grey64"); break;
case "grey128": this.sectionNode.classList.add("background-grey128"); break;
case "grey192": this.sectionNode.classList.add("background-grey192"); break;
}
}
else if (this.props.backgroundGradient != undefined) {
this.sectionNode.classList.add("aero-background-gradient-" + this.props.backgroundGradient);
}
else if (this.props.backgroundImage != undefined) {
let backgroundImagePath = this.props.backgroundImage;
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, backgroundImagePath, () => this.render(page));
}
/* </background> */
/* <text> */
let textNode = document.createElement("div");
textNode.classList.add("aero-slide-text");
/* <h1> */
if (this.props.title != undefined) {
let h1Node = document.createElement("h1");
h1Node.innerHTML = this.props.title;
textNode.appendChild(h1Node);
}
/* </h1> */
/* <h2> */
if (this.props.subtitle != undefined) {
let h2Node = document.createElement("h2");
h2Node.innerHTML = this.props.subtitle;
textNode.appendChild(h2Node);
}
/* </h2> */
/* <p> */
if (this.props.paragraph != undefined) {
let pNode = document.createElement("p");
pNode.innerHTML = this.props.paragraph;
textNode.appendChild(pNode);
}
/* </p> */
this.sectionNode.appendChild(textNode);
/* </text> */
/* <metrics> */
if (this.props.metrics != undefined) { this.drawMetrics(this.props.metrics); }
/* <metrics> */
/* <asset> */
if (this.props.asset != undefined) {
let assetNode = document.createElement("div");
assetNode.classList.add("aero-slide-picture");
if (this.props.assetAspectRatio) { assetNode.style.aspectRatio = this.props.assetAspectRatio; }
let assetImagePath = this.props.asset;
AeroUtilities.loadBackgroundImage(assetNode, assetImagePath, () => { });
this.sectionNode.appendChild(assetNode);
}
/* </assset> */
/* return wrapper node */
return this.sectionNode;
}
setType(type) {
this.sectionNode.setAttribute("type", type);
}
setTheme(theme) {
this.sectionNode.setAttribute("theme", theme);
}
setArrangement(arrangement) {
this.sectionNode.setAttribute("arrangement", arrangement);
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
else if (this.isInitialized && page.imageResolution == 1) {
this.redrawHighRes();
}
}
draw() {
}
drawMetrics(script) {
/*
<div class="metrics-4">
<div class="metrics-item">
<div class="metrics-item-value">
<span class="number">6000</span><span class="unit">kg</span>
</div>
<div class="metrics-item-parameter">Max nacelle weight</div>
</div>
<div class="metrics-item">
<div class="metrics-item-value">
<span class="modifier">></span><span class="number">12</span><span
class="unit">h</span>
</div>
<div class="metrics-item-parameter">Flight time (ECO MODE 250
km/h, full load)</div>
</div>
<div class="metrics-item">
<div class="metrics-item-value">
<span class="modifier">></span><span class="number">3000</span><span
class="unit">km</span>
</div>
<div class="metrics-item-parameter">Range (ECO MODE 250 km/h,
full load)</div>
</div>
<div class="metrics-item">
<div class="metrics-item-value">
<span class="modifier">></span><span class="number">450</span><span
class="unit">km/h</span>
</div>
<div class="metrics-item-parameter">Max speed</div>
</div>
</div>
*/
let metricsNode = document.createElement("div");
metricsNode.classList.add(`aero-slide-metrics`);
script.forEach(metric => {
let metricsItemNode = document.createElement("div");
metricsItemNode.classList.add("aero-slide-metrics-item");
let metricsItemValueNode = document.createElement("div");
metricsItemValueNode.classList.add("aero-slide-metrics-item-value");
let content = "";
if (metric.modifier != undefined) {
content += `<span class="modifier">${metric.modifier}</span>`;
}
content += `<span class="number">${metric.number}</span>`;
content += `<span class="unit">${metric.unit}</span>`;
metricsItemValueNode.innerHTML = content;
metricsItemNode.appendChild(metricsItemValueNode);
let metricsItemParameterNode = document.createElement("div");
metricsItemParameterNode.classList.add("aero-slide-metrics-item-parameter");
metricsItemParameterNode.innerHTML = metric.parameter;
metricsItemNode.appendChild(metricsItemParameterNode);
metricsNode.appendChild(metricsItemNode);
})
this.sectionNode.appendChild(metricsNode);
}
redrawHighRes() {
if (this.hasBackgroundImage && this.backgroundImagePath.includes(LOW_RESOLUTION_TAG)) {
let highResPath = this.backgroundImagePath.replace(LOW_RESOLUTION_TAG, HIGH_RESOLUTION_TAG);
let highResImageBuffer = new Image();
let _this = this;
highResImageBuffer.onload = function () {
_this.sectionNode.style.backgroundImage = `url(${highResImageBuffer.src})`;
_this.isBackgroundImageLoaded = true;
_this.page.notifyElementHasBeenLoaded();
};
this.isBackgroundImageLoaded = false;
highResImageBuffer.src = highResPath; // trigger
}
if (this.hasAssetImage && this.assetImagePath.includes(LOW_RESOLUTION_TAG)) {
let highResPath = this.assetImagePath.replace(LOW_RESOLUTION_TAG, HIGH_RESOLUTION_TAG);
let highResImageBuffer = new Image();
let _this = this;
highResImageBuffer.onload = function () {
_this.assetNode.style.backgroundImage = `url(${highResImageBuffer.src})`;
_this.isAssetImageLoaded = true;
_this.page.notifyElementHasBeenLoaded();
};
this.isAssetImageLoaded = false;
highResImageBuffer.src = highResPath; // trigger
}
}
}

297
aero/SlideV2.js Normal file
View File

@ -0,0 +1,297 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { WebPage } from "./WebPage.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export const LOW_RESOLUTION_TAG = "-low";
export const HIGH_RESOLUTION_TAG = "-high";
export class SlideV2 extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
/**
*
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super();
/* CSS requirements */
page.css_requireStylesheet("/aero/Slide.css");
page.css_requireStylesheet("/aero/gradient-backgrounds.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-slide");
/* <id> */
this.id = sources.id;
if (this.id) { this.sectionNode.id = this.id; }
/* </id> */
let val;
/* <type> */
this.type = (val = sources.getAttribute("type")) ? val : "prime";
this.sectionNode.setAttribute("type", this.type);
/* </type> */
/* <theme> */
this.theme = (val = sources.getAttribute("theme")) ? val : "light";
this.sectionNode.setAttribute("theme", this.theme);
/* </theme> */
/* <arrangement> */
this.arrangement = (val = sources.getAttribute("arrangement")) ? val : "default";
this.sectionNode.setAttribute("arrangement", this.arrangement);
/* </arrangement> */
/* <background> */
if (sources.hasAttribute("backgroundColor")) {
this.sectionNode.style.backgroundColor = sources.getAttribute("backgroundColor");
}
else if (val = sources.getAttribute("backgroundGradient")) {
this.sectionNode.classList.add("aero-background-gradient-" + val);
}
else if (val = sources.getAttribute("backgroundImage")) {
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, val, () => this.render(page));
}
/* </background> */
/* <text> */
let textNode = document.createElement("div");
textNode.classList.add("aero-slide-text");
let sourceNode = sources.firstChild;
while (sourceNode) {
let type = sourceNode.nodeName.toLowerCase();
switch (type) {
case "h1": {
let h1Node = document.createElement("h1");
h1Node.innerHTML = sourceNode.innerHTML;
textNode.appendChild(h1Node);
} break;
case "h2": {
let h2Node = document.createElement("h2");
h2Node.innerHTML = sourceNode.innerHTML;
textNode.appendChild(h2Node);
} break;
case "p": {
let pNode = document.createElement("p");
pNode.innerHTML = sourceNode.innerHTML;
textNode.appendChild(pNode);
} break;
}
sourceNode = sourceNode.nextSibling; /* next source node */
}
this.sectionNode.appendChild(textNode);
/* </text> */
/* <metrics> */
//if (sources.metrics != undefined) { this.drawMetrics(this.props.metrics); }
/* <metrics> */
/* <asset> */
if (val = sources.getAttribute("asset")) {
let assetImagePath = val;
let assetNode = document.createElement("div");
assetNode.classList.add("aero-slide-picture");
if (val = sources.getAttribute("assetAspectRatio")) { assetNode.style.aspectRatio = val; }
AeroUtilities.loadBackgroundImage(assetNode, assetImagePath, () => { });
this.sectionNode.appendChild(assetNode);
}
/* </assset> */
}
html_getNode(){
return this.sectionNode;
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
else if (this.isInitialized && page.imageResolution == 1) {
this.redrawHighRes();
}
}
draw() {
}
drawMetrics(script) {
/*
<div class="metrics-4">
<div class="metrics-item">
<div class="metrics-item-value">
<span class="number">6000</span><span class="unit">kg</span>
</div>
<div class="metrics-item-parameter">Max nacelle weight</div>
</div>
<div class="metrics-item">
<div class="metrics-item-value">
<span class="modifier">></span><span class="number">12</span><span
class="unit">h</span>
</div>
<div class="metrics-item-parameter">Flight time (ECO MODE 250
km/h, full load)</div>
</div>
<div class="metrics-item">
<div class="metrics-item-value">
<span class="modifier">></span><span class="number">3000</span><span
class="unit">km</span>
</div>
<div class="metrics-item-parameter">Range (ECO MODE 250 km/h,
full load)</div>
</div>
<div class="metrics-item">
<div class="metrics-item-value">
<span class="modifier">></span><span class="number">450</span><span
class="unit">km/h</span>
</div>
<div class="metrics-item-parameter">Max speed</div>
</div>
</div>
*/
let metricsNode = document.createElement("div");
metricsNode.classList.add(`aero-slide-metrics`);
script.forEach(metric => {
let metricsItemNode = document.createElement("div");
metricsItemNode.classList.add("aero-slide-metrics-item");
let metricsItemValueNode = document.createElement("div");
metricsItemValueNode.classList.add("aero-slide-metrics-item-value");
let content = "";
if (metric.modifier != undefined) {
content += `<span class="modifier">${metric.modifier}</span>`;
}
content += `<span class="number">${metric.number}</span>`;
content += `<span class="unit">${metric.unit}</span>`;
metricsItemValueNode.innerHTML = content;
metricsItemNode.appendChild(metricsItemValueNode);
let metricsItemParameterNode = document.createElement("div");
metricsItemParameterNode.classList.add("aero-slide-metrics-item-parameter");
metricsItemParameterNode.innerHTML = metric.parameter;
metricsItemNode.appendChild(metricsItemParameterNode);
metricsNode.appendChild(metricsItemNode);
})
this.sectionNode.appendChild(metricsNode);
}
redrawHighRes() {
if (this.hasBackgroundImage && this.backgroundImagePath.includes(LOW_RESOLUTION_TAG)) {
let highResPath = this.backgroundImagePath.replace(LOW_RESOLUTION_TAG, HIGH_RESOLUTION_TAG);
let highResImageBuffer = new Image();
let _this = this;
highResImageBuffer.onload = function () {
_this.sectionNode.style.backgroundImage = `url(${highResImageBuffer.src})`;
_this.isBackgroundImageLoaded = true;
_this.page.notifyElementHasBeenLoaded();
};
this.isBackgroundImageLoaded = false;
highResImageBuffer.src = highResPath; // trigger
}
if (this.hasAssetImage && this.assetImagePath.includes(LOW_RESOLUTION_TAG)) {
let highResPath = this.assetImagePath.replace(LOW_RESOLUTION_TAG, HIGH_RESOLUTION_TAG);
let highResImageBuffer = new Image();
let _this = this;
highResImageBuffer.onload = function () {
_this.assetNode.style.backgroundImage = `url(${highResImageBuffer.src})`;
_this.isAssetImageLoaded = true;
_this.page.notifyElementHasBeenLoaded();
};
this.isAssetImageLoaded = false;
highResImageBuffer.src = highResPath; // trigger
}
}
}

358
aero/SpText.css Normal file
View File

@ -0,0 +1,358 @@
/* <aero-slide> */
/* <text> */
.sptext {
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
@media (orientation : landscape) {
.sptext {
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
}
@media (orientation : portrait) {
.sptext {
margin: 0px 0px 0px 0px;
padding: 8px 4% 8px 4%;
}
}
/* <text> */
/* <asset> */
div.aero-slide-picture {
padding: 0px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
z-index: 2;
aspect-ratio: 3 / 2;
/*overflow: auto;*/
}
@media (orientation : landscape) {
div.aero-slide-picture {
margin: 0px 20% 0px 20%;
width: 60%;
}
.aero-slide[type="hThird"]>.aero-slide-picture {
margin: 32px 32px 32px 32px;
background-size: contain;
}
}
@media (orientation : portrait) {
div.aero-slide-picture {
margin: 0px 4% 0px 4%;
width: 92%;
}
.aero-slide[type="hThird"]>.aero-slide-picture {
margin: 32px 32px 32px 32px;
background-size: contain;
}
.aero-slide[type="hThird"] {
display: flex;
flex-direction: row-reverse;
padding: 8px 16% 8px 16%;
}
}
/* <asset> */
/* <arrangements> */
@media (orientation : landscape) {
.aero-slide[arrangement="text-up"] {
flex-direction: column;
}
.aero-slide[arrangement="text-down"] {
flex-direction: column-reverse;
}
.aero-slide[arrangement="text-left"] {
flex-direction: row;
}
.aero-slide[arrangement="text-right"] {
flex-direction: row-reverse;
}
}
/* </arrangements> */
/* <h1> */
.sptext>h1 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: lighter;
max-width: 92%;
padding: 32px 8px 16px 8px;
border-radius: 4px;
margin: 0px;
z-index: 8;
text-align: left;
}
@media (orientation : landscape) {
.sptext>h1 {
font-size: 64px;
line-height: 64px;
}
}
@media (orientation : portrait) {
aero-slide-text>h1 {
font-size: 48px;
line-height: 48px;
}
}
.sptext>h1>span.emphasis {
font-weight: bold;
}
/* </h1> */
/* <h2> */
.sptext>h2 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 24px;
line-height: 24px;
font-weight: bold;
max-width: 92%;
padding: 16px 8px 8px 8px;
border-radius: 4px;
/*white-space: nowrap;*/
margin: 0px;
z-index: 6;
text-align: left;
}
@media (orientation : landscape) {
.sptext>h2 {
font-size: 24px;
line-height: 24px;
}
}
@media (orientation : portrait) {
.sptext>h2 {
font-size: 20px;
line-height: 20px;
}
}
/* </h2> */
/* <p> */
.sptext>p, .sptext>ul {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 16px;
font-weight: normal;
text-align: justify;
z-index: 4;
padding: 12px 8px 12px 8px;
border-radius: 4px;
margin: 0px;
}
.sptext>ul>li {
padding: 8px 8px 8px 16px;
}
@media (orientation : landscape) {
.sptext>p, .sptext>ul {
font-size: 16px;
}
}
@media (orientation : portrait) {
.sptext>p, .sptext>ul {
font-size: 13px;
}
}
/* </p> */
.aero-slide>a {
position: absolute;
z-index: 10;
overflow: hidden;
padding: 12px 24px;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
line-height: 16px;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
user-select: none;
background-repeat: repeat-x;
background-position: -1px -1px;
background-size: 110% 110%;
border: 1px solid rgba(240, 240, 255, 1.0);
border-radius: 8px;
appearance: none;
/* appearance */
color: #ffffff;
background-color: rgba(28, 77, 45, 0.16);
background-image: linear-gradient(-180deg, rgb(46 46 46/ 52%) 0%,
rgb(16 16 16/ 67%) 90%);
backdrop-filter: blur(2px);
text-decoration: none;
}
.aero-slide>a:hover {
background-color: #269f42;
background-image: linear-gradient(-180deg, #2fcb53 0%, #269f42 90%);
background-position: -.5em;
border-color: rgba(27, 31, 35, 0.5);
text-decoration: none;
}
.aero-slide>a:focus {
box-shadow: 0 0 0 0.2em rgba(52, 208, 88, 0.4);
text-decoration: none;
}
.aero-slide>a:active {
background-color: #279f43;
background-image: none;
border-color: rgba(27, 31, 35, 0.5);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
text-decoration: none;
}
@media (orientation : landscape) {}
@media (orientation : portrait) {
.aero-slide h1 {
font-size: 32px;
line-height: 32px;
}
.aero-slide h2 {
font-size: 18px;
line-height: 18px;
}
.aero-slide p {
font-size: 16px;
}
}
.aero-slide-paragraph {
font-size: 16px;
padding: 32px 0px 32px 0px;
}
/* </aero-slides> */
/* <aero-slide-prime> */
/* </aero-slide-prime> */
/* <themes> */
.sptext[theme="light"] {
color: black;
/*background-color: rgba(255, 255, 255, 0.24);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.75);*/
/*text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.75);*/
}
.sptext[theme="dark"] {
color: white;
/*background-color: rgba(0, 0, 0, 0.16);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 2px rgba(255, 255, 255, 0.75);*/
}
/* </themes> */
/* <svg> */
.sptext-pic-svg {
padding: 32px 16px 32px 16px;
}
.sptext[theme="light"] > .sptext-pic-svg svg {
fill: black;
stroke: black;
}
.sptext[theme="dark"] > .sptext-pic-svg svg {
fill: white;
stroke: white;
}
/* </svg> */
/* <backgrounds> */
div[class^="background-"] {
background-repeat: no-repeat;
}
.background-white {
background-color: white;
}
.background-blue {
background-color: blue;
}
.background-teal {
background-color: teal;
}
.background-black {
background-color: black;
}
.background-grey64 {
background-color: rgb(64, 64, 64);
}
.background-grey128 {
background-color: rgb(128, 128, 128);
}
.background-grey192 {
background-color: rgb(192, 192, 192);
}
.background-pic {
background-size: cover;
background-position: center;
}
/* </backgrounds> */

152
aero/SpText.js Normal file
View File

@ -0,0 +1,152 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { Icon } from "./Icon.js";
import { WebPage } from "./WebPage.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export class SpText extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
constructor(contentPathname, props) {
super();
this.contentPathname = contentPathname;
this.props = props;
}
/**
*
* @param {WebPage} handler
* @returns {HTMLElement}
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/SpText.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("sptext");
this.sectionNode.setAttribute("type", this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
if (this.props.arrangement) { this.setArrangement(this.props.arrangement); }
/* <id> */
if (this.props.id != undefined) {
this.sectionNode.id = this.props.id;
}
/* </id> */
/* <background> */
if (this.props.backgroundColor != undefined) {
this.sectionNode.style.backgroundColor = this.props.backgroundColor;
}
else if (this.props.backgroundGradient != undefined) {
this.sectionNode.classList.add("aero-background-gradient-" + this.props.backgroundGradient);
}
else if (this.props.backgroundImage != undefined) {
let backgroundImagePath = this.props.backgroundImage;
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, backgroundImagePath, () => this.render(page));
}
/* </background> */
/* <elements> */
AeroUtilities.sendRequest_HTTP_GET(this.contentPathname, "text", content => {
this.sectionNode.innerHTML = content;
});
/* </elements> */
/* return wrapper node */
return this.sectionNode;
}
setTheme(theme) {
this.sectionNode.setAttribute("theme", theme);
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
else if (this.isInitialized && page.imageResolution == 1) {
this.redrawHighRes();
}
}
draw() {
}
}

498
aero/SquareGrid.css Normal file
View File

@ -0,0 +1,498 @@
/** */
@media (width >= 620px) {
.square-grid-wrapper {
top: 0px;
left: 0px;
padding: 32px 32px 32px 32px;
background-color: white;
overflow-y: hidden;
}
.square-grid-deck {
display: grid;
/* flex-direction: row; */
/* flex-wrap: wrap; */
grid-template-columns: repeat(auto-fill, 256px);
/*grid-template-rows: repeat(auto-fill, 208px);*/
grid-gap: 32px 32px;
grid-auto-flow: row dense;
width: 100%;
justify-content: center;
}
}
@media (width < 620px) {
.square-grid-wrapper {
top: 0px;
left: 0px;
padding: 32px 0px 32px 0px;
background-color: white;
overflow-y: hidden;
}
.square-grid-deck {
display: grid;
/* flex-direction: row; */
/* flex-wrap: wrap; */
grid-template-columns: repeat(auto-fill, 44vw);
grid-template-rows: repeat(auto-fill, 44vw);
grid-gap: 4vw 4vw;
grid-auto-flow: row dense;
width: 100%;
justify-content: center;
}
}
/* all cards */
.square-grid-card {
box-sizing: border-box;
position: relative;
padding: 8px;
margin: 0px;
border-radius: 16px;
box-shadow: 0px 0px 4px rgb(172, 172, 172);
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: normal;
overflow: hidden;
}
.square-grid-card h1 {
font-size: 24px;
padding: 2px 0px;
margin: 8px 0px 4px 8px;
width: fit-content;
font-weight: bold;
}
.square-grid-card h2 {
font-size: 18px;
padding: 2px 0px;
margin: 6px 0px 4px 8px;
width: fit-content;
font-weight: bold;
}
.square-grid-card p {
font-size: 14px;
padding: 0px;
margin: 4px 16px 4px 8px;
width: fit-content;
}
.square-grid-card ul {
padding: 8px 0px 8px 16px;
margin: 0px;
width: fit-content;
}
.square-grid-card li {
font-size: 14px;
margin: 0px;
padding: 4px;
width: fit-content;
color: rgb(38, 5, 84);
}
@media (width <= 620px) {
.square-grid-card h1 {
font-size: 20px;
}
.square-grid-card h2 {
font-size: 16px;
font-weight: normal;
}
.square-grid-card p {
font-size: 12px;
}
.square-grid-card li {
font-size: 12px;
}
}
/* <size> */
@media (width >= 620px) {
.square-grid-card[size="std"] {
grid-column: auto / span 1;
grid-row: auto / span 1;
width: 256px;
height: 256px;
}
.square-grid-card[size="large-horizontal"] {
grid-column: auto / span 2;
grid-row: auto / span 1;
width: 544px;
height: 256px;
}
.square-grid-card[size="large-vertical"] {
grid-column: auto / span 1;
grid-row: auto / span 2;
width: 256px;
height: 544px;
}
.square-grid-card[size="large-square"] {
grid-column: auto / span 2;
grid-row: auto / span 2;
width: 544px;
height: 544px;
}
}
@media (width < 620px) {
.square-grid-card[size="std"] {
grid-column: auto / span 1;
grid-row: auto / span 1;
width: 44vw;
height: 44vw;
}
.square-grid-card[size="large-horizontal"] {
grid-column: auto / span 2;
grid-row: auto / span 1;
width: 92vw;
height: 44vw;
}
.square-grid-card[size="large-vertical"] {
grid-column: auto / span 1;
grid-row: auto / span 2;
width: 44vw;
height: 92vw;
}
.square-grid-card[size="large-square"] {
grid-column: auto / span 2;
grid-row: auto / span 2;
width: 92vw;
height: 92vw;
}
}
/* </size> */
/* <type> */
.square-grid-card[type="create"] {
border-radius: 24px;
border: 8px dashed rgb(204, 204, 204);
background-color: white;
overflow: hidden;
color: rgb(200, 200, 200);
}
.square-grid-card[type="create"]:hover {
border-color: aqua;
}
.square-grid-card[type="access"] {
border: 1px solid rgb(182, 182, 182);
background-color: white;
background-image: url("/S8-pkgs-ui-carbide/collections/grids/pics/turbine-pic.png");
background-size: cover;
overflow: hidden;
}
.square-grid-card[type="access"]:hover {
outline: 8px solid rgb(203 223 255);
}
/* </type> */
/* <theme> */
.square-grid-card[theme="light"] {
border-color: rgb(204, 204, 204);
}
.square-grid-card[theme="light"] h1 {
color: rgb(36, 36, 36);
}
.square-grid-card[theme="light"] h2 {
color: rgb(36, 36, 36);
}
.square-grid-card[theme="light"] p {
color: rgb(36, 36, 36);
/*text-shadow: 0px 0px 4px white;*/
}
.square-grid-card[theme="light"] li {
color: rgb(38, 5, 84);
/*text-shadow: 0px 0px 4px white;*/
}
.square-grid-card[theme="dark"] {
border-color: rgb(80, 80, 80);
}
.square-grid-card[theme="dark"] h1 {
color: white;
}
.square-grid-card[theme="dark"] h2 {
color: white;
}
.square-grid-card[theme="dark"] p {
color: white;
}
.square-grid-card[theme="dark"] li {
color: rgb(253, 226, 255);
/*text-shadow: 0px 0px 4px white;*/
}
/* </theme> */
.square-grid-card-group {
background-color: aliceblue;
font-size: 14px;
padding: 2px 8px;
/* margin-left: 8px; */
border-radius: 8px;
width: fit-content;
}
/* <link> */
.square-grid-card-link {
color: white;
font-size: 14px;
font-weight: bold;
padding: 4px 12px 4px 4px;
margin: 16px 8px 8px 8px;
width: fit-content;
display: flex;
flex-direction: row;
align-items: center;
background-color: #3862fbca;
/*background-image: linear-gradient(to right, #3525e5 0%, #3525e5 20%, #b214d2 100%);*/
border-radius: 20px;
cursor: pointer;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.367);
}
.square-grid-card-link:hover {
background-color: #476bed;
}
.square-grid-card-link-pic {
width: 24px;
height: 24px;
margin: 0px;
padding: 0px;
background-size: auto;
background-position: center;
background-repeat: no-repeat;
}
.square-grid-card-link-pic > svg {
stroke: #ffffff;
fill: #ffffff;
}
.square-grid-card-link-text {
padding-bottom: 2px;
font-size: 14px;
margin-left: 8px;
color: #ffffff;
}
.square-grid-card-link:hover > .square-grid-card-link-pic >svg {
stroke: white;
fill: white;
}
.square-grid-card-link:hover > .square-grid-card-link-text{
color: white;
}
/* </link> */
.square-grid-card-point {
font-size: 14px;
padding: 8px 16px 8px 8px;
margin: 4px;
width: fit-content;
display: flex;
flex-direction: row;
align-items: start;
gap: 16px;
}
.square-grid-card-point-icon {
width: 32px;
height: 32px;
margin: 0px;
padding: 0px;
background-size: auto;
background-position: center;
background-repeat: no-repeat;
}
.square-grid-card[theme="light"] .square-grid-card-point-icon>svg {
fill: black;
stroke: black;
}
.square-grid-card[theme="dark"] .square-grid-card-point-icon>svg {
fill: white;
stroke: white;
}
.square-grid-card-point-text {
border-left: solid 1px rgba(44, 44, 44, 0.906);
padding-left: 8px;
}
/* <create-card> */
/* <mobile-hideable> */
@media (width <= 620px) {
.square-grid-mobile-hideable {
display: none;
}
}
/* </mobile-hideable> */
.square-grid-card-create-header {
font-family: SF Pro Text, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 128px;
font-weight: bold;
letter-spacing: -0.016em;
text-align: center;
margin-top: 4px;
margin-bottom: 4px;
color: rgb(200, 200, 200);
}
.square-grid-card-create-body {
font-family: SF Pro Text, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 12px;
font-weight: 400;
letter-spacing: -0.016em;
text-align: center;
margin-top: 4px;
margin-bottom: 4px;
color: rgb(200, 200, 200);
}
/* <create-card> */
/* <repository-card> */
.square-grid-card-access[selected] {
border: 2px solid #769ff4;
box-shadow: 0px 0px 4px rgb(103, 143, 167);
}
.square-grid-card-access-image {
height: 128px;
width: 100%;
background-image: url("/S8-pkgs-ui-carbide/collections/grids/pics/turbine-pic.png");
background-size: cover;
border-bottom: 1px solid rgb(182, 182, 182);
}
.square-grid-card-access-panel {
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
font-weight: 600;
letter-spacing: -0.016em;
text-align: left;
margin: 6px 8px 0px 8px;
max-height: 32px;
color: white;
}
.square-grid-card-access-panel>h1 {
width: fit-content;
font-size: 20px;
font-weight: 600;
letter-spacing: -0.016em;
text-align: left;
margin: 10px 2px 0px 2px;
padding: 2px 6px 2px 6px;
}
.square-grid-card-access-panel>h2 {
width: fit-content;
display: block;
font-size: 12px;
font-weight: 500;
letter-spacing: -0.016em;
text-align: left;
margin: 10px 8px 0px 8px;
padding: 2.25px 8px;
background-color: rgb(53, 53, 53);
border-radius: 9px;
}
.square-grid-card-access-panel>p {
width: fit-content;
font-size: 14px;
font-weight: 400;
letter-spacing: -0.016em;
text-align: left;
margin: 10px 8px 0px 8px;
padding: 0px;
}
.square-grid-card-access-info {
font-family: SF Pro Text, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 12px;
font-weight: 400;
letter-spacing: -0.016em;
text-align: left;
height: 32px;
margin: 6px 8px 12px 8px;
text-overflow: ellipsis;
}
.square-grid-card-access-popover-root {
height: 16px;
width: 16px;
position: relative;
margin-left: 72px;
}
/* </repository-card> */

377
aero/SquareGrid.js Normal file
View File

@ -0,0 +1,377 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
import { LoadHandler } from "./aero.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { Icon } from "./Icon.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export class SquareGrid extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type {HTMLDivElement} */
deckNode;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
constructor(type, props) {
super();
this.type = type;
this.props = props;
}
/**
*
* @param {WebPage} page
* @param {*} state
* @returns
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/SquareGrid.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("square-grid-wrapper");
this.setType(this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
/* <background> */
if (this.props.backgroundImage) {
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, this.props.backgroundImage);
}
else if (this.props.backgroundColor) {
this.sectionNode.classList.add("background-colo");
this.sectionNode.style.backgroundColor = this.props.backgroundColor;
}
/* </background> */
/* <deck> */
this.deckNode = document.createElement("div");
this.deckNode.classList.add("square-grid-deck");
this.props.cards.forEach(card => this.deckNode.appendChild(card.build(page)));
this.sectionNode.appendChild(this.deckNode);
/* </deck> */
return this.sectionNode;
}
setType(type) {
this.sectionNode.setAttribute("type", type);
}
setTheme(theme) {
this.sectionNode.setAttribute("theme", theme);
}
render(state) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
}
draw() {
}
}
export class SquareGridCard extends AeroElement {
/** @type {HTMLDivElement } */
cardNode;
type;
props;
/** @type {HTMLDivElement} */
assetNode;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
constructor(type, size, props) {
super();
this.type = type;
this.size = size;
this.props = props;
}
/**
*
* @param {LoadHandler} handler
* @param {*} state
* @returns
*/
build(page) {
this.cardNode = document.createElement("div");
this.cardNode.classList.add("square-grid-card");
this.cardNode.setAttribute("size", this.size);
/* <background> */
if (this.props.backgroundImage) {
this.cardNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.cardNode, this.props.backgroundImage);
}
else if (this.props.backgroundColor) {
this.cardNode.classList.add("background-color");
this.cardNode.style.backgroundColor = this.props.backgroundColor;
}
/* </background> */
/* <elements> */
if (this.props.elements) {
this.props.elements.forEach(element => {
this.cardNode.appendChild(element.build(page));
});
}
/* </elements> */
this.setType(this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
return this.cardNode;
}
setType(type) {
this.cardNode.setAttribute("type", type);
}
setTheme(theme) {
this.cardNode.setAttribute("theme", theme);
}
}
export class SquareGridCardElement {
constructor(props) {
this.props = props;
this.isMobileHideable = props.isMobileHideable ? props.isMobileHideable : false;
}
}
export class SquareGridCardGroup extends SquareGridCardElement {
constructor(props) {
super(props);
}
build(page) {
/* <group> */
const groupNode = document.createElement("div");
groupNode.classList.add("square-grid-card-group");
groupNode.innerHTML = this.props.txt;
/* </group> */
return this.groupNode = groupNode;
}
}
export class SquareGridCardH1 extends SquareGridCardElement {
constructor(props) {
super(props);
this.txt = props.txt;
}
build(page) {
const headerNode = document.createElement("h1");
if (this.isMobileHideable) { headerNode.classList.add("square-grid-mobile-hideable"); }
headerNode.innerHTML = this.txt;
return this.headerNode = headerNode;
}
}
export class SquareGridCardH2 extends SquareGridCardElement {
constructor(props) {
super(props);
this.txt = props.txt;
}
build(page) {
const headerNode = document.createElement("h2");
if (this.isMobileHideable) { headerNode.classList.add("square-grid-mobile-hideable"); }
headerNode.innerHTML = this.txt;
return this.headerNode = headerNode;
}
}
export class SquareGridCardParagraph extends SquareGridCardElement {
constructor(props) {
super(props);
this.txt = props.txt;
}
/**
*
* @param {WebPage} page
*/
build(page) {
const pNode = document.createElement("p");
if (this.isMobileHideable) { pNode.classList.add("square-grid-mobile-hideable"); }
pNode.innerHTML = this.txt;
return this.pNode = pNode;
}
}
export class SquareGridCardPoint extends SquareGridCardElement {
constructor(props) {
super(props);
this.iconPathname = props.icon;
this.text = props.text;
}
/**
*
* @param {WebPage} page
*/
build(page) {
const pointNode = document.createElement("div");
pointNode.classList.add("square-grid-card-point");
if (this.isMobileHideable) { pointNode.classList.add("square-grid-mobile-hideable"); }
const linkIcon = new Icon(this.iconPathname, { width: 32, height: 32 });
linkIcon.build();
linkIcon.getEnvelope().classList.add("square-grid-card-point-icon");
pointNode.appendChild(linkIcon.getEnvelope());
const textNode = document.createElement("span");
textNode.classList.add("square-grid-card-point-text");
textNode.innerHTML = this.text;
pointNode.appendChild(textNode);
this.linkNode = pointNode;
return this.linkNode;
}
}
export class SquareGridCardLink extends SquareGridCardElement {
constructor(props) {
super(props);
this.iconPathname = props.icon;
this.text = props.text;
this.url = props.url;
}
/**
*
* @param {WebPage} page
*/
build(page) {
const linkNode = document.createElement("div");
linkNode.classList.add("square-grid-card-link");
if (this.isMobileHideable) { linkNode.classList.add("square-grid-mobile-hideable"); }
const linkIcon = new Icon(this.iconPathname, { width: 24, height: 24 });
linkIcon.build();
linkIcon.getEnvelope().classList.add("square-grid-card-link-pic");
linkNode.appendChild(linkIcon.getEnvelope());
const spanNode = document.createElement("span");
spanNode.classList.add("square-grid-card-link-text");
spanNode.innerHTML = this.text;
linkNode.appendChild(spanNode);
linkNode.addEventListener("click", () => {window.location = this.url; }, false);
this.linkNode = linkNode;
return this.linkNode;
}
}

405
aero/SquareGridV2.js Normal file
View File

@ -0,0 +1,405 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { Icon } from "./Icon.js";
import { WebPageV2 } from "./WebPageV2.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export class SquareGridV2 extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
/**
* @type{List<SquareGridCard>}
*/
cards = new Array();
/** @type {HTMLDivElement} */
deckNode;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/**
*
* @param {WebPageV2} page
* @param {HTMLElement} sources
* @returns
*/
constructor(page, sources) {
super();
/* CSS requirements */
page.css_requireStylesheet("/aero/SquareGrid.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("square-grid-wrapper");
let val;
this.type = (val = sources.getAttribute("type")) ? val : "std";
this.sectionNode.setAttribute("type", this.type);
this.theme = (val = sources.getAttribute("theme")) ? val : "light";
this.sectionNode.setAttribute("theme", this.theme);
/* <background> */
if (val = sources.getAttribute("backgroundImage")) {
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, val);
}
else if (val = sources.getAttribute("backgroundColor")) {
this.sectionNode.classList.add("background-color");
this.sectionNode.style.backgroundColor = val;
}
/* </background> */
/* <deck> */
this.deckNode = document.createElement("div");
this.deckNode.classList.add("square-grid-deck");
let node = sources.firstChild;
while(node){
let type = node.nodeName.toLowerCase();
if(type == "card"){
this.cards.push(new SquareGridCard(node));
}
node = node.nextSibling;
}
this.cards.forEach(card => this.deckNode.appendChild(card.html_getNode()));
this.sectionNode.appendChild(this.deckNode);
/* </deck> */
}
html_getNode(){
return this.sectionNode;
}
render(state) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
}
draw() {
}
}
export class SquareGridCard extends AeroElement {
/** @type {HTMLDivElement } */
cardNode;
type;
/**
* @type{List<SquareGridCardElement>}
*/
elements = new Array();
/** @type {HTMLDivElement} */
assetNode;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/**
*
* @param {HTMLElement} sources
*/
constructor(sources) {
super();
this.cardNode = document.createElement("div");
this.cardNode.classList.add("square-grid-card");
let val;
this.type = (val = sources.getAttribute("type")) ? val : "light";
this.cardNode.setAttribute("type", this.type);
this.theme = (val = sources.getAttribute("theme")) ? val : "light";
this.cardNode.setAttribute("theme", this.theme);
this.size = (val = sources.getAttribute("size")) ? val : "std";
this.cardNode.setAttribute("size", this.size);
/* <background> */
if (val = sources.getAttribute("backgroundImage")) {
this.cardNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.cardNode, val);
}
else if (val = sources.getAttribute("backgroundColor")) {
this.cardNode.classList.add("background-color");
this.cardNode.style.backgroundColor = val;
}
/* </background> */
/* <elements> */
let node = sources.firstChild;
while(node){
let type = node.nodeName.toLowerCase();
switch(type){
case "hgroup" : { this.elements.push(new SquareGridCardGroup(node)); } break;
case "h1" : { this.elements.push(new SquareGridCardH1(node)); } break;
case "h2" : { this.elements.push(new SquareGridCardH2(node)); } break;
case "p" : { this.elements.push(new SquareGridCardParagraph(node)); } break;
case "a" : { this.elements.push(new SquareGridCardLink(node)); } break;
case "li" : { this.elements.push(new SquareGridCardPoint(node)); } break;
case "ul" : { this.elements.push(new SquareGridCardList(node)); } break;
}
node = node.nextSibling;
}
/* </elements> */
this.elements.forEach(element => { this.cardNode.appendChild(element.html_getNode()); });
}
html_getNode(){
return this.cardNode;
}
}
export class SquareGridCardElement {
constructor(sources) {
this.isMobileHideable = sources.hasAttribute("isMobileHideable");
}
}
export class SquareGridCardGroup extends SquareGridCardElement {
constructor(sources) {
super(sources);
/* <group> */
const groupNode = document.createElement("div");
groupNode.classList.add("square-grid-card-group");
groupNode.innerHTML = sources.innerHTML;
/* </group> */
this.groupNode = groupNode;
}
html_getNode(){ return this.groupNode; }
}
export class SquareGridCardH1 extends SquareGridCardElement {
constructor(sources) {
super(sources);
const headerNode = document.createElement("h1");
if (this.isMobileHideable) { headerNode.classList.add("square-grid-mobile-hideable"); }
headerNode.innerHTML = sources.innerHTML;
this.headerNode = headerNode;
}
html_getNode(){ return this.headerNode; }
}
export class SquareGridCardH2 extends SquareGridCardElement {
constructor(sources) {
super(sources);
const headerNode = document.createElement("h2");
if (this.isMobileHideable) { headerNode.classList.add("square-grid-mobile-hideable"); }
headerNode.innerHTML = sources.innerHTML;
this.headerNode = headerNode;
}
html_getNode(){ return this.headerNode; }
}
export class SquareGridCardParagraph extends SquareGridCardElement {
constructor(sources) {
super(sources);
const pNode = document.createElement("p");
if (this.isMobileHideable) { pNode.classList.add("square-grid-mobile-hideable"); }
/* <elements> */
let node = sources.firstChild, nextNode;
while(node){
nextNode = node.nextSibling;
pNode.appendChild(node);
node = nextNode;
}
/* </elements> */
this.pNode = pNode;
}
html_getNode(){ return this.pNode; }
}
export class SquareGridCardPoint extends SquareGridCardElement {
constructor(sources) {
super(sources);
this.iconPathname = sources.getAttribute("icon");
const pointNode = document.createElement("div");
pointNode.classList.add("square-grid-card-point");
if (this.isMobileHideable) { pointNode.classList.add("square-grid-mobile-hideable"); }
const linkIcon = new Icon(this.iconPathname, { width: 32, height: 32 });
linkIcon.build();
linkIcon.getEnvelope().classList.add("square-grid-card-point-icon");
pointNode.appendChild(linkIcon.getEnvelope());
const textNode = document.createElement("span");
textNode.classList.add("square-grid-card-point-text");
textNode.innerHTML = sources.innerHTML;
pointNode.appendChild(textNode);
this.linkNode = pointNode;
}
html_getNode(){ return this.linkNode; }
}
export class SquareGridCardLink extends SquareGridCardElement {
/**
*
* @param {HTMLElement} sources
*/
constructor(sources) {
super(sources);
this.iconPathname = sources.getAttribute("icon");
this.url = sources.getAttribute("href");
const linkNode = document.createElement("div");
linkNode.classList.add("square-grid-card-link");
if (this.isMobileHideable) { linkNode.classList.add("square-grid-mobile-hideable"); }
const linkIcon = new Icon(this.iconPathname, { width: 24, height: 24 });
linkIcon.build();
linkIcon.getEnvelope().classList.add("square-grid-card-link-pic");
linkNode.appendChild(linkIcon.getEnvelope());
const spanNode = document.createElement("span");
spanNode.classList.add("square-grid-card-link-text");
spanNode.innerHTML = sources.innerHTML;
linkNode.appendChild(spanNode);
linkNode.addEventListener("click", () => {window.location = this.url; }, false);
this.linkNode = linkNode;
}
html_getNode(){ return this.linkNode; }
}
export class SquareGridCardList extends SquareGridCardElement {
constructor(sources) {
super(sources);
const listNode = document.createElement("ul");
if (this.isMobileHideable) { listNode.classList.add("square-grid-mobile-hideable"); }
/* <elements> */
let node = sources.firstChild;
while(node){
let type = node.nodeName.toLowerCase();
switch(type){
case "li" : {
const itemNode = document.createElement("li")
itemNode.innerHTML = node.innerHTML;
listNode.appendChild(itemNode);
} break;
}
node = node.nextSibling;
}
/* </elements> */
this.listNode = listNode;
}
html_getNode(){ return this.listNode; }
}

571
aero/TextBlock.css Normal file
View File

@ -0,0 +1,571 @@
/* <aero-slide> */
/* <text> */
.textblock {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
margin: 0px 0px 0px 0px;
padding: 8px 16% 8px 16%;
}
@media (orientation : landscape) {
.textblock {
margin: 0px 0px 0px 0px;
padding: 32px 16% 8px 16%;
}
}
@media (orientation : portrait) {
.textblock {
margin: 0px 0px 0px 0px;
padding: 16px 4% 8px 4%;
}
}
/* <text> */
/* <asset> */
div.aero-slide-picture {
padding: 0px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
z-index: 2;
aspect-ratio: 3 / 2;
/*overflow: auto;*/
}
@media (orientation : landscape) {
div.aero-slide-picture {
margin: 0px 20% 0px 20%;
width: 60%;
}
.aero-slide[type="hThird"]>.aero-slide-picture {
margin: 32px 32px 32px 32px;
background-size: contain;
}
}
@media (orientation : portrait) {
div.aero-slide-picture {
margin: 0px 4% 0px 4%;
width: 92%;
}
.aero-slide[type="hThird"]>.aero-slide-picture {
margin: 32px 32px 32px 32px;
background-size: contain;
}
.aero-slide[type="hThird"] {
display: flex;
flex-direction: row-reverse;
padding: 8px 16% 8px 16%;
}
}
/* <asset> */
/* <arrangements> */
@media (orientation : landscape) {
.aero-slide[arrangement="text-up"] {
flex-direction: column;
}
.aero-slide[arrangement="text-down"] {
flex-direction: column-reverse;
}
.aero-slide[arrangement="text-left"] {
flex-direction: row;
}
.aero-slide[arrangement="text-right"] {
flex-direction: row-reverse;
}
}
/* </arrangements> */
/* <h1> */
.textblock>h1 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: lighter;
max-width: 92%;
padding: 8px;
border-radius: 4px;
margin: 0px;
z-index: 8;
text-align: left;
}
.textblock>h1>span:first-child {
margin: 0px 16px 0px 0px;
}
.textblock[type="legal"]>h1 {
font-size: 32px;
color: #1635a5;
padding: 16px 8px 8px 8px;
}
@media (orientation : landscape) {
.textblock>h1 {
font-size: 64px;
line-height: 64px;
}
}
@media (orientation : portrait) {
aero-slide-text>h1 {
font-size: 48px;
line-height: 48px;
}
}
.textblock>h1>span.emphasis {
font-weight: bold;
}
.textblock[type="legal"]>h1 {
padding: 32px 8px 16px 8px;
}
/* </h1> */
/* <h2> */
.textblock>h2 {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
"Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-size: 24px;
line-height: 24px;
font-weight: bold;
max-width: 92%;
padding: 16px 8px 8px 8px;
border-radius: 4px;
/*white-space: nowrap;*/
margin: 0px;
z-index: 6;
text-align: left;
}
.textblock>h2>span:first-child {
margin: 0px 8px 0px 0px;
}
.textblock[type="legal"]>h2 {
font-size: 20px;
padding: 16px 8px 8px 8px;
}
@media (orientation : landscape) {
.textblock>h2 {
font-size: 24px;
line-height: 24px;
}
}
@media (orientation : portrait) {
.textblock>h2 {
font-size: 20px;
line-height: 20px;
}
}
/* </h2> */
/* <p> */
.textblock>p {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
text-align: justify;
z-index: 4;
padding: 0px 0px 0px 0px;
padding: 6px 6px 6px 8px;
border-radius: 4px;
margin: 0px;
}
.textblock>p code, .textblock>ul code, .textblock>ol code{
font-weight: bold;
color: #1635a5;
}
/* <p> */
.textblock[type="legal"]>p {
font-size: 16px;
}
.textblock[type="legal"]>ul>li {
padding: 8px 8px 8px 16px;
}
@media (orientation : landscape) {
.textblock>p {
font-size: 16px;
}
}
@media (orientation : portrait) {
.textblock>p {
font-size: 13px;
}
}
/* </p> */
/* <ol> */
.textblock>ol {
counter-reset: section;
margin: 8px 0px 0px 0px;
padding: 0px 0px 0px 24px;
}
.textblock>ol>li {
margin: 4px 0px 0px 0px;
padding: 4px;
text-align: justify;
}
/* </ol> */
/* <ul> */
.textblock>ul>li {
font-size: 16px;
padding: 4px 8px;
}
.textblock[type="legal"]>ul {
font-size: 16px;
padding: 0px 0px 0px 24px;
}
.textblock[type="legal"]>ul>li {
padding: 8px 8px 8px 16px;
text-align: justify;
}
@media (orientation : landscape) {
.textblock>ul {
font-size: 16px;
}
}
@media (orientation : portrait) {
.textblock>ul {
font-size: 13px;
}
}
/* </ul> */
/* <a> */
.textblock-links {
display: flex;
flex-direction: row;
padding: 8px;
}
.textblock-link {
color: white;
font-size: 14px;
font-weight: bold;
padding: 4px;
margin: 8px;
width: fit-content;
display: flex;
flex-direction: row;
align-items: center;
background-color: #3862fbca;
/*background-image: linear-gradient(to right, #3525e5 0%, #3525e5 20%, #b214d2 100%);*/
border-radius: 20px;
cursor: pointer;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.367);
text-decoration: none;
}
.textblock-link:hover {
background-color: #476bed;
}
.textblock-link-pic {
width: 24px;
height: 24px;
margin: 0px;
padding: 0px;
background-size: auto;
background-position: center;
background-repeat: no-repeat;
}
.textblock-link-pic > svg {
stroke: #ffffff;
fill: #ffffff;
}
.textblock-link-text {
padding-bottom: 2px;
font-size: 14px;
margin-left: 8px;
color: #ffffff;
}
.textblock-link:hover > .textblock-link-pic >svg {
stroke: white;
fill: white;
}
.textblock-link:hover > .textblock-link-text{
color: white;
}
/* <a:styles> */
.textblock-link[type="marketing"] {
padding: 12px 24px;
border-radius: 4px;
}
.textblock-link[type="marketing"]>.textblock-link-text {
font-size: 16px;
font-weight: bold;
}
/* </a:styles> */
/* <a:color> */
.textblock-link[color="resource"] {
color: white;
background-color: #3862fbca;
}
.textblock-link[color="resource"]:hover {
background-color: #7291ff;
}
.textblock-link[color="doc"] {
color: white;
background-color: #008925ca;
}
.textblock-link[color="doc"]:hover {
background-color: #02c035ca;
}
/* </a:color> */
/* </a> */
.aero-slide>a {
position: absolute;
z-index: 10;
overflow: hidden;
padding: 12px 24px;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
font-size: 20px;
font-weight: normal;
line-height: 16px;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
user-select: none;
background-repeat: repeat-x;
background-position: -1px -1px;
background-size: 110% 110%;
border: 1px solid rgba(240, 240, 255, 1.0);
border-radius: 8px;
appearance: none;
/* appearance */
color: #ffffff;
background-color: rgba(28, 77, 45, 0.16);
background-image: linear-gradient(-180deg, rgb(46 46 46/ 52%) 0%,
rgb(16 16 16/ 67%) 90%);
backdrop-filter: blur(2px);
text-decoration: none;
}
.aero-slide>a:hover {
background-color: #269f42;
background-image: linear-gradient(-180deg, #2fcb53 0%, #269f42 90%);
background-position: -.5em;
border-color: rgba(27, 31, 35, 0.5);
text-decoration: none;
}
.aero-slide>a:focus {
box-shadow: 0 0 0 0.2em rgba(52, 208, 88, 0.4);
text-decoration: none;
}
.aero-slide>a:active {
background-color: #279f43;
background-image: none;
border-color: rgba(27, 31, 35, 0.5);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
text-decoration: none;
}
@media (orientation : landscape) {}
@media (orientation : portrait) {
.aero-slide h1 {
font-size: 32px;
line-height: 32px;
}
.aero-slide h2 {
font-size: 18px;
line-height: 18px;
}
.aero-slide p {
font-size: 16px;
}
}
.aero-slide-paragraph {
font-size: 16px;
padding: 32px 0px 32px 0px;
}
/* </aero-slides> */
/* <aero-slide-prime> */
/* </aero-slide-prime> */
/* <themes> */
.textblock[theme="light"] {
color: black;
/*background-color: rgba(255, 255, 255, 0.24);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.75);*/
/*text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.75);*/
}
.textblock[theme="dark"] {
color: white;
/*background-color: rgba(0, 0, 0, 0.16);*/
/*backdrop-filter: blur(12px);*/
/*text-shadow: 0px 0px 2px rgba(255, 255, 255, 0.75);*/
}
/* </themes> */
/* <svg> */
.textblock-pic-svg {
padding: 32px 16px 32px 16px;
}
.textblock[theme="light"] > .textblock-pic-svg svg {
fill: black;
stroke: black;
}
.textblock[theme="dark"] > .textblock-pic-svg svg {
fill: white;
stroke: white;
}
/* </svg> */
/* <backgrounds> */
div[class^="background-"] {
background-repeat: no-repeat;
}
.background-white {
background-color: white;
}
.background-blue {
background-color: blue;
}
.background-teal {
background-color: teal;
}
.background-black {
background-color: black;
}
.background-grey64 {
background-color: rgb(64, 64, 64);
}
.background-grey128 {
background-color: rgb(128, 128, 128);
}
.background-grey192 {
background-color: rgb(192, 192, 192);
}
.background-pic {
background-size: cover;
background-position: center;
}
/* </backgrounds> */
/* <code> */
.txbk-code-section {
padding: 24px max(5%, 16px) 24px max(5%, 16px);
}
.txbk-code-window {
background-color: rgb(33, 23, 59);
border-radius: 16px;
padding: 16px 32px;
color: rgb(87, 211, 211);
}
.txbk-code-window pre {
margin: 0;
padding: 0;
overflow-x: hidden;
tab-size: 2;
}
.txbk-code-window code {
margin: 0;
padding: 0;
}

251
aero/TextBlock.js Normal file
View File

@ -0,0 +1,251 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { Icon } from "./Icon.js";
import { WebPage } from "./WebPage.js";
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export const LOW_RESOLUTION_TAG = "-low";
export const HIGH_RESOLUTION_TAG = "-high";
export class TextBlock extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
props;
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
constructor(type, props) {
super();
this.type = type;
this.props = props;
}
/**
*
* @param {WebPage} handler
* @returns {HTMLElement}
*/
build(page) {
/* CSS requirements */
page.css_requireStylesheet("/aero/TextBlock.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("textblock");
this.sectionNode.setAttribute("type", this.type);
this.setType(this.type);
this.setTheme(this.props.theme ? this.props.theme : "light");
if (this.props.arrangement) { this.setArrangement(this.props.arrangement); }
/* <id> */
if (this.props.id != undefined) {
this.sectionNode.id = this.props.id;
}
/* </id> */
/* <background> */
if (this.props.background != undefined || this.props.backgroundColor != undefined) {
let backgroundParam = this.props.background;
switch (backgroundParam) {
case "black": this.sectionNode.classList.add("background-black"); break;
case "white": this.sectionNode.classList.add("background-white"); break;
case "grey64": this.sectionNode.classList.add("background-grey64"); break;
case "grey128": this.sectionNode.classList.add("background-grey128"); break;
case "grey192": this.sectionNode.classList.add("background-grey192"); break;
}
}
else if (this.props.backgroundGradient != undefined) {
this.sectionNode.classList.add("aero-background-gradient-" + this.props.backgroundGradient);
}
else if (this.props.backgroundImage != undefined) {
let backgroundImagePath = this.props.backgroundImage;
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, backgroundImagePath, () => this.render(page));
}
/* </background> */
/* <elements> */
this.props.elements.forEach(element => this.sectionNode.appendChild(element.build(page)));
/* </elements> */
/* return wrapper node */
return this.sectionNode;
}
setType(type) {
this.sectionNode.setAttribute("type", type);
}
setTheme(theme) {
this.sectionNode.setAttribute("theme", theme);
}
setArrangement(arrangement) {
this.sectionNode.setAttribute("arrangement", arrangement);
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
else if (this.isInitialized && page.imageResolution == 1) {
this.redrawHighRes();
}
}
draw() {
}
}
export class TextBlockElement {
constructor(props) {
this.props = props ? props : {};
}
}
export class TxBkHeader1 extends TextBlockElement {
constructor(text, props) {
super(props);
this.text = text;
}
build(page) {
const headerNode = document.createElement("h1");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
headerNode.innerHTML = this.text;
return this.headerNode = headerNode;
}
}
export class TxBkHeader2 extends TextBlockElement {
constructor(text, props) {
super(props);
this.text = text;
}
build(page) {
const headerNode = document.createElement("h2");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
headerNode.innerHTML = this.text;
return this.headerNode = headerNode;
}
}
export class TxBkParagraph extends TextBlockElement {
constructor(text, props) {
super(props);
this.text = text;
}
build(page) {
const headerNode = document.createElement("p");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
headerNode.innerHTML = this.text;
return this.headerNode = headerNode;
}
}
export class TxBkSVG extends TextBlockElement {
constructor(pathname, props) {
super(props);
this.pathname = pathname;
}
build(page) {
const wrapperNode = document.createElement("div");
wrapperNode.classList.add("textblock-pic-svg");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
this.icon = new Icon(this.pathname, this.props);
wrapperNode.appendChild(this.icon.build());
return this.wrapperNode = wrapperNode;
}
}

537
aero/TextBlockV2.js Normal file
View File

@ -0,0 +1,537 @@
import { AeroElement } from "./AeroElement.js";
import { AeroUtilities } from "./AeroUtilities.js";
import { Icon, SVG_inject } from "./Icon.js";
import { WebPage } from "./WebPage.js";
import { WebPageV2 } from "./WebPageV2.js";
// Using ES6 import syntax
import hljs from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/highlight.min.js';
// and it's easy to individually load additional languages
import java from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/languages/java.min.js';
import xml from 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/es/languages/xml.min.js';
/*
Turn this:
{
_type: "aero-slide-prime",
theme: "dark",
title: `The power of <b>tomorrow</b>`,
subtitle: "Hi There",
paragraph: `this is a very
long text indeed that spread on multiple lines`,
background : {
_type : "pic",
source : "assets/truc0002.jpg"
}
},
into this:
<section class="aero-slide-prime aero-theme-dark background-black">
<div class="text">
<h1>Say Hello to <span class="emphasis">OCTOFAN</span></h1>
<h2>The world's first H2-powered multirole heavy duty drone with
switchable nacelles</h2>
</div>
<div class="asset"
style="background-image: url('assets/aircrafts/freighter/render0x07-low.png');">
</div>
</section>
*/
export const LOW_RESOLUTION_TAG = "-low";
export const HIGH_RESOLUTION_TAG = "-high";
export class TextBlockV2 extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
type;
/**
* @type{List<TextBlockElement>}
*/
elements = new Array();
/** @type{boolean} */
hasBackgroundImage = false;
/** @type{boolean} */
isBackgroundImageLoaded = false;
/** @type{string} */
backgroundImagePath;
/** @type{boolean} */
hasAssetImage = false;
/** @type{boolean} */
isAssetImageLoaded = false;
/** @type{string} */
assetImagePath;
/** @type {HTMLDivElement} */
assetNode;
/**
*
* @param {WebPageV2} page
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super();
/* CSS requirements */
page.css_requireStylesheet("/aero/TextBlock.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("textblock");
let val;
this.type = (val = sources.getAttribute("type")) ? val : "std";
this.sectionNode.setAttribute("type", this.type);
this.theme = (val = sources.getAttribute("theme")) ? val : "light";
this.sectionNode.setAttribute("theme", this.theme);
this.arrangement = (val = sources.getAttribute("arrangement")) ? val : "std";
this.sectionNode.setAttribute("arrangement", this.arrangement);
this.numbering = (val = sources.getAttribute("numbering")) ? val : "none";
/* <id> */
if (sources.id != undefined) { this.sectionNode.id = sources.id; }
/* </id> */
/* <background> */
if (val = sources.getAttribute("backgroundColor")) {
switch (val) {
case "black": this.sectionNode.classList.add("background-black"); break;
case "white": this.sectionNode.classList.add("background-white"); break;
case "grey64": this.sectionNode.classList.add("background-grey64"); break;
case "grey128": this.sectionNode.classList.add("background-grey128"); break;
case "grey192": this.sectionNode.classList.add("background-grey192"); break;
}
}
else if (val = sources.getAttribute("backgroundGradient")) {
/* ee */
page.css_requireStylesheet("/aero/gradient-backgrounds.css");
this.sectionNode.classList.add("aero-background-gradient-" + val);
}
else if (val = sources.getAttribute("backgroundImage")) {
this.sectionNode.classList.add("background-pic");
AeroUtilities.loadBackgroundImage(this.sectionNode, val, () => this.render(page));
}
/* </background> */
/* <elements> */
const numbering = {
type: this.numbering,
h1Number: 0,
h2Number: 0,
pNumber: 0
};
let node = sources.firstChild;
while (node) {
let type = node.nodeName.toLowerCase();
switch (type) {
case "h1": {
numbering.h1Number++;
this.elements.push(new TxBkHeader1(page, node, numbering));
numbering.h2Number = 0;
} break;
case "h2": {
numbering.h2Number++;
this.elements.push(new TxBkHeader2(page, node, numbering));
numbering.pNumber = 0;
} break;
case "p": this.elements.push(new TxBkParagraph(page, node)); break;
case "svg": this.elements.push(new TxBkSVG(page, node)); break;
case "snippet": this.elements.push(new TxBkCodeSnippet(page, node)); break;
case "ol": this.elements.push(new TxOrderedBkList(page, node)); break;
case "ul": this.elements.push(new TxUnorderedBkList(page, node)); break;
case "links": this.elements.push(new TxBkLinks(page, node)); break;
}
node = node.nextSibling;
}
this.elements.forEach(element => this.sectionNode.appendChild(element.html_getNode()));
/* </elements> */
}
html_getNode() {
/* return wrapper node */
return this.sectionNode;
}
/**
*
* @param {WebPage} page
*/
render(page) {
if (!this.isInitialized) {
this.draw();
this.isInitialized = true;
}
else if (this.isInitialized && page.imageResolution == 1) {
this.redrawHighRes();
}
}
draw() {
}
}
export class TextBlockElement {
constructor(sources) {
}
}
export class TxBkHeader1 extends TextBlockElement {
constructor(page, sources, numbering) {
super(sources);
const headerNode = document.createElement("h1");
switch(numbering.type){
case "none" : {
headerNode.innerHTML = sources.innerHTML;
} break;
case "1.2.3" : {
const numberNode = document.createElement("span");
numberNode.innerHTML = `${numbering.h1Number}.`;
headerNode.appendChild(numberNode);
const textNode = document.createElement("span");
textNode.innerHTML = sources.innerHTML;
headerNode.appendChild(textNode);
} break;
}
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
this.headerNode = headerNode;
}
html_getNode() { return this.headerNode; }
}
export class TxBkHeader2 extends TextBlockElement {
constructor(page, sources, numbering) {
super(sources);
const headerNode = document.createElement("h2");
switch(numbering.type){
case "none" : {
headerNode.innerHTML = sources.innerHTML;
} break;
case "1.2.3" : {
const numberNode = document.createElement("span");
numberNode.innerHTML = `${numbering.h1Number}.${numbering.h2Number}.`;
headerNode.appendChild(numberNode);
const textNode = document.createElement("span");
textNode.innerHTML = sources.innerHTML;
headerNode.appendChild(textNode);
} break;
}
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
this.headerNode = headerNode;
}
html_getNode() { return this.headerNode; }
}
export class TxBkParagraph extends TextBlockElement {
constructor(page, sources) {
super(sources);
const headerNode = document.createElement("p");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
headerNode.innerHTML = sources.innerHTML;
this.headerNode = headerNode;
}
html_getNode() { return this.headerNode; }
}
export class TxBkSVG extends TextBlockElement {
constructor(page, sources) {
super(sources);
this.pathname = sources.getAttribute("path");
const wrapperNode = document.createElement("div");
wrapperNode.classList.add("textblock-pic-svg");
//if (this.isMobileHideable) { headerNode.classList.add("txbk-mobile-hideable"); }
let val;
const width = (val = sources.getAttribute("width")) ? parseInt(val) : 128;
const height = (val = sources.getAttribute("height")) ? parseInt(val) : 128;
this.icon = new Icon(this.pathname, { width: width, height: height });
wrapperNode.appendChild(this.icon.build());
this.wrapperNode = wrapperNode;
}
html_getNode() { return this.wrapperNode; }
}
export class TxBkCodeSnippet extends TextBlockElement {
static isLanguageLoaded = false;
/**
*
* @param {WebPageV2} page
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super(sources);
this.sourcePathname = sources.getAttribute("path");
if (!this.isLanguageLoaded) {
// Then register the languages you need
hljs.registerLanguage('java', java);
hljs.registerLanguage('xml', xml);
this.isLanguageLoaded = true;
}
//page.css_requireStylesheet("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/styles/default.min.css");
page.css_requireStylesheet("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.0/styles/atom-one-dark.css");
const wrapperNode = document.createElement("div");
wrapperNode.classList.add("txbk-code-section");
const windowNode = document.createElement("div");
windowNode.classList.add("txbk-code-window");
// windowNode.classList.add("theme-atom-one-dark");
const preNode = document.createElement("pre");
//preNode.classList.add("theme-atom-one-dark");
const spanNode = document.createElement("span");
//spanNode.classList.add("language-java");
// spanNode.classList.add("hljs");
const codeNode = document.createElement("code");
//codeNode.innerHTML = highlightedCode;
spanNode.appendChild(codeNode);
preNode.appendChild(spanNode);
windowNode.appendChild(preNode);
wrapperNode.appendChild(windowNode);
AeroUtilities.getResourceFromOrigin(this.sourcePathname, "text", sourceCode => {
const highlightedSourceCode = hljs.highlight(sourceCode, { language: 'java' }).value;
codeNode.innerHTML = highlightedSourceCode;
})
this.wrapperNode = wrapperNode;
}
html_getNode() { return this.wrapperNode; }
/**
*
* @param {WebPage} page
*/
render(page) {
/* do nothing */
}
}
export class TxOrderedBkList extends TextBlockElement {
constructor(page, sources) {
super(sources);
const listNode = document.createElement("ol");
//listNode.classList.add("textblock-list");
if (this.isMobileHideable) { listNode.classList.add("square-grid-mobile-hideable"); }
let val;
this.type = (val = sources.getAttribute("type")) ? val : "1";
listNode.setAttribute("type", this.type);
/* <elements> */
let node = sources.firstChild;
while (node) {
let type = node.nodeName.toLowerCase();
switch (type) {
case "li": {
const itemNode = document.createElement("li")
itemNode.innerHTML = node.innerHTML;
listNode.appendChild(itemNode);
} break;
}
node = node.nextSibling;
}
/* </elements> */
this.listNode = listNode;
}
html_getNode() { return this.listNode; }
}
export class TxUnorderedBkList extends TextBlockElement {
constructor(page, sources) {
super(sources);
const listNode = document.createElement("ul");
//listNode.classList.add("textblock-list");
if (this.isMobileHideable) { listNode.classList.add("square-grid-mobile-hideable"); }
/* <elements> */
let node = sources.firstChild;
while (node) {
let type = node.nodeName.toLowerCase();
switch (type) {
case "li": {
const itemNode = document.createElement("li")
itemNode.innerHTML = node.innerHTML;
listNode.appendChild(itemNode);
} break;
}
node = node.nextSibling;
}
/* </elements> */
this.listNode = listNode;
}
html_getNode() { return this.listNode; }
}
export class TxBkLinks extends TextBlockElement {
/**
* @type{List<Object>}
*/
elements = new Array();
/**
*
* @param {*} page
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super(sources);
const wrapperNode = document.createElement("div");
wrapperNode.classList.add("textblock-links");
if (this.isMobileHideable) { wrapperNode.classList.add("square-grid-mobile-hideable"); }
/* <elements> */
let node = sources.firstChild;
while (node) {
let type = node.nodeName.toLowerCase();
switch (type) {
case "a": this.elements.push(new TxBkAnchor(page, node)); break;
}
node = node.nextSibling;
}
this.elements.forEach(element => {
let cellNode = document.createElement("div");
cellNode.appendChild(element.html_getNode());
wrapperNode.appendChild(cellNode);
});
/* </elements> */
this.wrapperNode = wrapperNode;
}
html_getNode() { return this.wrapperNode; }
}
export class TxBkAnchor {
/**
*
* @param {HTMLElement} sources
*/
constructor(page, sources) {
this.iconPathname = sources.getAttribute("icon");
this.url = sources.getAttribute("href");
this.type = sources.hasAttribute("type") ? sources.getAttribute("type") : "std";
this.color = sources.hasAttribute("color") ? sources.getAttribute("color") : "std";
const linkNode = document.createElement("a");
linkNode.setAttribute("type", this.type);
linkNode.setAttribute("color", this.color);
linkNode.classList.add("textblock-link");
if (this.isMobileHideable) { linkNode.classList.add("square-grid-mobile-hideable"); }
const picNode = document.createElement("span");
picNode.classList.add("textblock-link-pic");
SVG_inject(picNode, this.iconPathname, 24, 24);
linkNode.appendChild(picNode);
const textNode = document.createElement("span");
textNode.classList.add("textblock-link-text");
textNode.innerHTML = sources.innerHTML;
linkNode.appendChild(textNode);
let val;
if (val = sources.getAttribute("href")) { linkNode.href = val; }
/* download="proposed_file_name" */
if (val = sources.getAttribute("client-filename")) { linkNode.download = val; }
this.linkNode = linkNode;
}
html_getNode() { return this.linkNode; }
}

13
aero/Video.css Normal file
View File

@ -0,0 +1,13 @@
.aero-video-wrapper {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande",
sans-serif;
margin: 0px 0px 0px 0px;
padding: 0px;
}
.aero-video {
width: 100vw;
}

66
aero/Video.js Normal file
View File

@ -0,0 +1,66 @@
import { AeroElement } from "./AeroElement.js";
import { WebPage } from "./WebPage.js";
export class Video extends AeroElement {
/** @type {HTMLElement } */
sectionNode;
/**
*
* @param {HTMLElement} sources
*/
constructor(page, sources) {
super();
/* CSS requirements */
page.css_requireStylesheet("/aero/Video.css");
/* build nodes */
this.sectionNode = document.createElement("section");
this.sectionNode.classList.add("aero-video-wrapper");
/*
<video loop autoplay muted class="VideoMain">
<source src="https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" type="video/mp4">
</video>
*/
this.videoNode = document.createElement("video");
this.videoNode.classList.add("aero-video");
this.videoNode.setAttribute("loop", "");
this.videoNode.setAttribute("autoplay", "");
this.videoNode.setAttribute("muted", "");
let val;
/* <type> */
const vsrc = (val = sources.getAttribute("src")) ? val : null;
if (vsrc) {
this.sourceNode = document.createElement("source");
this.sourceNode.src = vsrc;
this.sourceNode.setAttribute("type", "video/mp4");
}
this.videoNode.appendChild(this.sourceNode);
this.sectionNode.appendChild(this.videoNode);
}
html_getNode() {
return this.sectionNode;
}
/**
*
* @param {WebPage} page
*/
render(page) {
}
}

5
aero/WebPage.css Normal file
View File

@ -0,0 +1,5 @@
body {
background-color: black;
}

184
aero/WebPage.js Normal file
View File

@ -0,0 +1,184 @@
import { AeroElement } from "./AeroElement.js";
export class WebPage {
props;
/**
* @type {Map<string, boolean>}
* // build stylesheets map
*/
css_stylesheetsMap = new Map();
/** @type {HTMLBodyElement} */
bodyNode;
/** @type {HTMLDivElement} */
wrapperNode;
/** @type {HTMLDivElement} */
baseLayerNode;
/** @type {HTMLDivElement} */
topLayerNode;
/** @type {HTMLDivElement} */
veilNode;
/** @type {Array<AeroElement>} */
elements;
/** @type {MediaQueryList} */
orientationObserver;
/**
* @type {number}
* 0: load low resolution
* 1: load high resolution
*/
imageResolution = 0;
isLandscape;
css_isStylesheetsLoadingCompleted = false;
constructor(elements, props) {
this.elements = elements;
this.props = props;
/* CSS requirements */
this.css_requireStylesheet("/aero/WebPage.css");
this.css_requireStylesheet("/aero/ModalBox.css");
}
generateState() {
/* compute new state */
let state = {};
state.
state.imageResolution = this.imageResolution;
return state;
}
start() {
/* build */
this.baseLayerNode = document.querySelector("#base");
/* retrieve page info */
this.orientationObserver = window.matchMedia("(orientation: landscape)");
this.isLandscape = this.orientationObserver.matches;
this.imageResolution = 0;
/* orientation */
const page = this;
this.orientationObserver.addEventListener("change", function (event) {
page.isLandscape = page.orientationObserver.matches;
page.render();
}, false);
/* initialize all (base) components */
this.elements.forEach(element => this.baseLayerNode.appendChild(element.build(this)));
this.topLayerNode = document.querySelector("#overlay");
this.veilNode = document.querySelector("#veil");
}
hide() {
this.baseLayerNode.classList.add("hidden");
this.topLayerNode.classList.add("hidden");
this.veilNode.classList.remove("hidden");
}
show() {
this.baseLayerNode.classList.remove("hidden");
this.topLayerNode.classList.remove("hidden");
this.veilNode.classList.add("hidden");
}
render() {
//this.elements.forEach(element => element.render(this));
}
run() {
this.elements.forEach(element => { if (element.run) { element.run(); } });
}
notifyElementHasBeenLoaded() {
if (this.areAllElementsLoaded() && this.imageResolution == 0) {
this.imageResolution = 1;
this.render();
}
}
/**
*
* @param {*} width
* @param {*} height
*/
onScreenResized(width, height) {
this.elements.forEach(element => element.onScreenResized(width, height));
}
onUpdate() {
if (this.css_isStylesheetsLoadingCompleted) {
this.render();
this.show();
}
}
css_onStyleSheetLoaded() {
/* check if all css stylesheets have been loaded */
this.css_isStylesheetsLoadingCompleted = true;
this.css_stylesheetsMap.forEach(value => {
if (!value) { this.css_isStylesheetsLoadingCompleted = false; }
});
this.onUpdate();
}
/**
* Trigger css loading if necessary
* @param {} pathname
*/
css_requireStylesheet(pathname) {
if (!this.css_stylesheetsMap.has(pathname)) {
this.css_stylesheetsMap.set(pathname, false);
/** @type{HTMLLinkElement} */
const linkNode = document.createElement("link");
linkNode.type = "text/css";
linkNode.rel = "stylesheet";
linkNode.href = pathname;
linkNode.addEventListener("load", () => {
this.css_stylesheetsMap.set(pathname, true);
this.css_onStyleSheetLoaded();
});
/* append and trigger */
document.head.appendChild(linkNode);
}
}
}

303
aero/WebPageV2.js Normal file
View File

@ -0,0 +1,303 @@
import { AeroElement } from "./AeroElement.js";
import { FooterV2 } from "./FooterV2.js";
import { HeaderV2 } from "./HeaderV2.js";
import { ModalBox } from "./ModalBox.js";
import { SlideV2 } from "./SlideV2.js";
import { SquareGridV2 } from "./SquareGridV2.js";
import { TextBlockV2 } from "./TextBlockV2.js";
import { DocumentationV2 } from "./DocumentationV2.js";
import { Video } from "./Video.js";
/**
*
* @param {*} props
*/
export const boot = function(){
const page = new WebPageV2();
page.start();
}
/**
*
* @param {*} prefix
* @param {HTMLElement} sourceNode
*/
export const buildPageElement = function (page, sourceNode) {
const type = sourceNode.nodeName.toLowerCase();
switch (type) {
case "header": return new HeaderV2(page, sourceNode);
case "slide": return new SlideV2(page, sourceNode);
case "square-grid": return new SquareGridV2(page, sourceNode);
case "text-block": return new TextBlockV2(page, sourceNode);
case "video": return new Video(page, sourceNode);
case "footer": return new FooterV2(page, sourceNode);
case "aero-doc": return new DocumentationV2(page, sourceNode);
default : return null;
}
}
const COOKIES_KEY = "has-cookies-already-been-displayed";
export class WebPageV2 {
/**
* @type {Map<string, boolean>}
* // build stylesheets map
*/
css_stylesheetsMap = new Map();
/** @type {HTMLBodyElement} */
bodyNode;
/** @type {HTMLDivElement} */
wrapperNode;
/** @type {HTMLDivElement} */
baseLayerNode;
/** @type {HTMLDivElement} */
topLayerNode;
/** @type {HTMLDivElement} */
veilNode;
/** @type {MediaQueryList} */
orientationObserver;
/** @type{Array<AeroElement>} */
elements = new Array();
/**
* @type {number}
* 0: load low resolution
* 1: load high resolution
*/
imageResolution = 0;
isLandscape;
css_isStylesheetsLoadingCompleted = false;
constructor() {
/* CSS requirements */
this.css_requireStylesheet("/aero/WebPage.css");
this.css_requireStylesheet("/aero/ModalBox.css");
const sources = document.querySelector("#aero-page");
let node = sources.firstChild;
while (node) {
const element = buildPageElement(this, node);
/** add element */
if(element !=null){ this.elements.push(element); }
/* save next node */
node = node.nextSibling;
}
document.body.removeChild(sources);
console.log("WEBPAGE loaded!");
}
generateState() {
/* compute new state */
let state = {};
state.
state.imageResolution = this.imageResolution;
return state;
}
start() {
/* create structure */
this.createStructure();
/** populate structure */
this.elements.forEach(element => this.baseLayerNode.appendChild(element.html_getNode()));
let val, hasBeenShown = (val = window.sessionStorage.getItem(COOKIES_KEY)) ? val : false;
if (!hasBeenShown) {
const modalBox = new ModalBox({
image: "/icons/cookie.png",
title: "0 cookies : Total privacy",
explanation: "Zero cookie policy means that no tracking of any kind is used on this site."
}, () => {
this.topLayerNode.removeChild(modalBox.getEnvelope());
/* run */
page.run();
});
this.topLayerNode.appendChild(modalBox.getEnvelope());
window.sessionStorage.setItem(COOKIES_KEY, true);
}
/* retrieve page info */
this.orientationObserver = window.matchMedia("(orientation: landscape)");
this.isLandscape = this.orientationObserver.matches;
this.imageResolution = 0;
/* orientation */
const page = this;
this.orientationObserver.addEventListener("change", function (event) {
page.isLandscape = page.orientationObserver.matches;
page.render();
}, false);
}
hide() {
this.baseLayerNode.classList.add("hidden");
this.topLayerNode.classList.add("hidden");
this.veilNode.classList.remove("hidden");
}
show() {
this.baseLayerNode.classList.remove("hidden");
this.topLayerNode.classList.remove("hidden");
this.veilNode.classList.add("hidden");
}
render() {
this.elements.forEach(element => element.render(this));
}
run() {
this.elements.forEach(element => { if (element.run) { element.run(); } });
}
notifyElementHasBeenLoaded() {
if (this.areAllElementsLoaded() && this.imageResolution == 0) {
this.imageResolution = 1;
this.render();
}
}
/**
*
* @param {*} width
* @param {*} height
*/
onScreenResized(width, height) {
this.elements.forEach(element => element.onScreenResized(width, height));
}
onUpdate() {
if (this.css_isStylesheetsLoadingCompleted) {
this.render();
this.show();
}
}
css_onStyleSheetLoaded() {
/* check if all css stylesheets have been loaded */
this.css_isStylesheetsLoadingCompleted = true;
this.css_stylesheetsMap.forEach(value => {
if (!value) { this.css_isStylesheetsLoadingCompleted = false; }
});
this.onUpdate();
}
/**
* Trigger css loading if necessary
* @param {} pathname
*/
css_requireStylesheet(pathname) {
if (!this.css_stylesheetsMap.has(pathname)) {
this.css_stylesheetsMap.set(pathname, false);
/** @type{HTMLLinkElement} */
const linkNode = document.createElement("link");
linkNode.type = "text/css";
linkNode.rel = "stylesheet";
linkNode.href = pathname;
linkNode.addEventListener("load", () => {
this.css_stylesheetsMap.set(pathname, true);
this.css_onStyleSheetLoaded();
});
/* append and trigger */
document.head.appendChild(linkNode);
}
}
createStructure(){
/* <structure> */
const bodyNode = document.body;
const wrapperNode = document.createElement("div");
/* build */
const baseLayerNode = document.createElement("div");
baseLayerNode.classList.add("hidden");
baseLayerNode.id = "base";
wrapperNode.appendChild(baseLayerNode);
this.baseLayerNode = baseLayerNode;
const topLayerNode = document.createElement("div");
topLayerNode.classList.add("hidden");
topLayerNode.id = "overlay";
wrapperNode.appendChild(topLayerNode);
this.topLayerNode = topLayerNode;
const veilNode = document.createElement("div");
veilNode.id = "veil";
wrapperNode.appendChild(veilNode);
bodyNode.appendChild(wrapperNode);
this.veilNode = veilNode;
this.wrapperNode = wrapperNode;
/* </structure> */
veilNode.appendChild(this.createSpinner());
}
createSpinner() {
//const iconPathname = this.iconPathname;
const node = document.createElement("div");
node.className = "boot-loader";
node.innerHTML = `
<div class="boot-embedded-icon"></div>
<div class="boot-spinner">
<svg class="circular" viewBox="25 25 50 50">
<circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/>
</svg>
</div>`;
return node;
}
}

167
aero/aero.js Normal file
View File

@ -0,0 +1,167 @@
import { AeroElement } from "./AeroElement.js";
import { Deck } from "./Deck.js";
import { Footer } from "./Footer.js";
import { Grid, GridCard } from "./Grid.js";
import { AeroMovie } from "./AeroMovie.js";
import { Slide } from "./Slide.js";
import { WebPage } from "./WebPage.js";
import { SquareGrid, SquareGridCard, SquareGridCardGroup, SquareGridCardH1, SquareGridCardH2, SquareGridCardLink, SquareGridCardParagraph, SquareGridCardPoint } from "./SquareGrid.js";
import { CodeBlock } from "./CodeBlock.js";
import { TextBlock, TxBkHeader1, TxBkHeader2, TxBkParagraph, TxBkSVG } from "./TextBlock.js";
import { SpText } from "./SpText.js";
export const page = function (elements, props) {
return new WebPage(elements, props);
}
export const slide = function (type, props) {
return new Slide(type, props);
}
export const movie = function (type, props) {
return new AeroMovie(type, props);
}
export const deck = function (props) {
return new Deck(props);
}
export const grid = function (type, props) {
return new Grid(type, props);
}
export const gridCard = function (type, props) {
return new GridCard(type, props);
}
export const sqGrid = function (type, props) {
return new SquareGrid(type, props);
}
export const sqGridCard = function (type, size, props) {
return new SquareGridCard(type, size, props);
}
export const sqGridCardGroup = function (props) {
return new SquareGridCardGroup(props);
}
export const sqGridCardH1 = function (props) {
return new SquareGridCardH1(props);
}
export const sqGridCardH2 = function (props) {
return new SquareGridCardH2(props);
}
export const sqGridCardParagraph = function (props) {
return new SquareGridCardParagraph(props);
}
export const sqGridCardPoint = function (props) {
return new SquareGridCardPoint(props);
}
export const sqGridCardLink = function (props) {
return new SquareGridCardLink(props);
}
export const codeBlock = function (source) {
return new CodeBlock(source);
}
export const textBlock = function (type, props) { return new TextBlock(type, props); }
export const txbkH1 = function (text, props) { return new TxBkHeader1(text, props); }
export const txbkH2 = function (text, props) { return new TxBkHeader2(text, props); }
export const txbkP = function (text, props) { return new TxBkParagraph(text, props); }
export const txbkSVG = function (pathname, props) { return new TxBkSVG(pathname, props); }
export const spText = function (contentPathname, props) { return new SpText(contentPathname, props); }
export const footer = function (contentPathname, props) {
return new Footer(contentPathname, props);
}
export const footSocial = function (props) {
return new FooterSocialLink(props);
}
export const footLegal = function (props) {
return new FooterLegalLink(props);
}
/**
*
*/
export class LoadHandler {
/**
* @type{Set<string>}
*/
resources;
/**
* @param{function}
*/
onLoaded = null;
index = 0;
constructor() {
this.resources = new Set();
}
generateId() {
return `generated-${this.index++}`;
}
registerLoading(name) {
this.resources.add(name);
}
notifyCompleted(name) {
this.resources.delete(name);
if (this.onLoaded != null && this.resources.size == 0) {
this.onLoaded();
}
}
listenCompleted(onLoaded) {
if (this.resources.size == 0) {
onLoaded();
}
else {
this.onLoaded = onLoaded;
}
}
}
/**
* @param{HTMLDivElement} enveloppeNode
*/
export function clearChildNodes(enveloppeNode) {
let child;
while ((child = enveloppeNode.firstChild)) {
enveloppeNode.removeChild(enveloppeNode.lastChild);
}
}

206
aero/aeroV2.js Normal file
View File

@ -0,0 +1,206 @@
import { AeroElement } from "./AeroElement.js";
import { Deck } from "./Deck.js";
import { Footer } from "./Footer.js";
import { Grid, GridCard } from "./Grid.js";
import { Header } from "./Header.js";
import { AeroMovie } from "./AeroMovie.js";
import { Slide } from "./Slide.js";
import { WebPage } from "./WebPage.js";
import { SquareGrid, SquareGridCard, SquareGridCardGroup, SquareGridCardH1, SquareGridCardH2, SquareGridCardLink, SquareGridCardParagraph, SquareGridCardPoint } from "./SquareGrid.js";
import { CodeBlock } from "./CodeBlock.js";
import { TextBlock, TxBkHeader1, TxBkHeader2, TxBkParagraph, TxBkSVG } from "./TextBlock.js";
import { SpText } from "./SpText.js";
import { HeaderV2 } from "./HeaderV2.js";
export const buildPage = function(){
const sourceNode = document.querySelector("#aero-source");
const page = new WebPage();
buildElements(page, sourceNode, buildElement);
}
export const buildElements = function(page, parentNode, buildFunction){
let sourceNode = parentNode.firstChild, nextNode;
while (sourceNode) {
/* save next node */
nextNode = sourceNode.nextSibling;
/* create new node and insert it before source node */
parentNode.insertBefore(buildFunction(page, sourceNode), sourceNode);
/* remove source node */
parentNode.removeChild(sourceNode);
/* roll over */
sourceNode = nextNode;
}
}
/**
*
* @param {*} prefix
* @param {HTMLElement} sourceNode
*/
export const buildElement = function (page, sourceNode) {
const type = sourceNode.nodeName.toLowerCase();
switch (type) {
case "aero-header": return new HeaderV2(page, sourceNode).html_getNode();
default : return sourceNode;
}
}
export const header = function (props) {
return new Header(props);
}
export const slide = function (type, props) {
return new Slide(type, props);
}
export const movie = function (type, props) {
return new AeroMovie(type, props);
}
export const deck = function (props) {
return new Deck(props);
}
export const grid = function (type, props) {
return new Grid(type, props);
}
export const gridCard = function (type, props) {
return new GridCard(type, props);
}
export const sqGrid = function (type, props) {
return new SquareGrid(type, props);
}
export const sqGridCard = function (type, size, props) {
return new SquareGridCard(type, size, props);
}
export const sqGridCardGroup = function (props) {
return new SquareGridCardGroup(props);
}
export const sqGridCardH1 = function (props) {
return new SquareGridCardH1(props);
}
export const sqGridCardH2 = function (props) {
return new SquareGridCardH2(props);
}
export const sqGridCardParagraph = function (props) {
return new SquareGridCardParagraph(props);
}
export const sqGridCardPoint = function (props) {
return new SquareGridCardPoint(props);
}
export const sqGridCardLink = function (props) {
return new SquareGridCardLink(props);
}
export const codeBlock = function (source) {
return new CodeBlock(source);
}
export const textBlock = function (type, props) { return new TextBlock(type, props); }
export const txbkH1 = function (text, props) { return new TxBkHeader1(text, props); }
export const txbkH2 = function (text, props) { return new TxBkHeader2(text, props); }
export const txbkP = function (text, props) { return new TxBkParagraph(text, props); }
export const txbkSVG = function (pathname, props) { return new TxBkSVG(pathname, props); }
export const spText = function (contentPathname, props) { return new SpText(contentPathname, props); }
export const footer = function (contentPathname, props) {
return new Footer(contentPathname, props);
}
export const footSocial = function (props) {
return new FooterSocialLink(props);
}
export const footLegal = function (props) {
return new FooterLegalLink(props);
}
/**
*
*/
export class LoadHandler {
/**
* @type{Set<string>}
*/
resources;
/**
* @param{function}
*/
onLoaded = null;
index = 0;
constructor() {
this.resources = new Set();
}
generateId() {
return `generated-${this.index++}`;
}
registerLoading(name) {
this.resources.add(name);
}
notifyCompleted(name) {
this.resources.delete(name);
if (this.onLoaded != null && this.resources.size == 0) {
this.onLoaded();
}
}
listenCompleted(onLoaded) {
if (this.resources.size == 0) {
onLoaded();
}
else {
this.onLoaded = onLoaded;
}
}
}
/**
* @param{HTMLDivElement} enveloppeNode
*/
export function clearChildNodes(enveloppeNode) {
let child;
while ((child = enveloppeNode.firstChild)) {
enveloppeNode.removeChild(enveloppeNode.lastChild);
}
}

156
aero/boot.css Normal file
View File

@ -0,0 +1,156 @@
.hidden {
visibility: hidden;
height: 0px;
overflow: hidden;
}
body {
background-color: black;
padding: 0px;
margin: 0px;
}
body > div#aero-page {
display: none;
}
#base-layer {
z-index: 2;
background-color: rgb(255, 255, 255);
padding: 0px;
margin: 0px;
}
#overlay {
z-index: 64;
background-color: rgb(255, 255, 255);
position: absolute;
top: 0px;
bottom: 0px;
padding: 0px;
margin: 0px;
}
#veil {
z-index: 128;
background: rgb(89, 85, 85);
background: linear-gradient(0deg, rgba(89, 85, 85, 1) 25%, rgba(62, 60, 60, 1) 70%, rgba(66, 66, 66, 1) 100%);
position: absolute;
width: 100vw;
height: 100vh;
top: 0px;
bottom: 0px;
padding: 0px;
margin: 0px;
}
.boot-loader, .boot-spinner, .boot-embedded-icon {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.boot-spinner, .boot-embedded-icon {
margin: 0px;
padding: 0px;
}
.boot-spinner {
width: 172px;
height: 172px;
}
.boot-embedded-icon {
width: 128px;
height: 128px;
background-image: url('/logos/S8-logo-v4-256px.png');
background-position: center;
background-size: contain;
}
.loader:before {
content: '';
display: block;
padding-top: 100%;
}
.circular {
-webkit-animation: rotate 2s linear infinite;
animation: rotate 2s linear infinite;
height: 100%;
-webkit-transform-origin: center center;
-ms-transform-origin: center center;
transform-origin: center center;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.path {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
-webkit-animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
stroke-linecap: round;
}
@keyframes rotate {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -124;
}
}
@keyframes color {
100%, 0% {
stroke: rgb(255, 73, 218);
}
40% {
stroke: #f22d8c;
}
66% {
stroke: #7f0fda;
}
80%, 90% {
stroke: #f9c909;
}
}

103
aero/boot.js Normal file
View File

@ -0,0 +1,103 @@
import { ModalBox } from "./ModalBox.js";
import { WebPageV2 } from "./WebPageV2.js";
export const bootV2 = function(props){
const page = new WebPageV2(props);
page.start();
}
/**
*
* @param {*} pagePathname
*/
export const boot = function (props) {
/* <structure> */
const pagePathname = props.page;
const hasCookiesModalBox = props.hasCookiesModalBox ? props.hasCookiesModalBox : false;
const iconPathname = props.iconPathname;
const bodyNode = document.body;
const wrapperNode = document.createElement("div");
/* build */
const baseLayerNode = document.createElement("div");
baseLayerNode.classList.add("hidden");
baseLayerNode.id = "base";
wrapperNode.appendChild(baseLayerNode);
const topLayerNode = document.createElement("div");
topLayerNode.classList.add("hidden");
topLayerNode.id = "overlay";
wrapperNode.appendChild(topLayerNode);
const veilNode = document.createElement("div");
veilNode.id = "veil";
wrapperNode.appendChild(veilNode);
bodyNode.appendChild(wrapperNode);
/* </structure> */
veilNode.appendChild(createSpinner());
/**
* import { WEB_PAGE } from './';
window.WEB_PAGE = WEB_PAGE;
*/
import(pagePathname).then((mod) => {
const page = mod.WEB_PAGE;
/* start page */
page.start();
console.log("WEBPAGE loaded!");
if (hasCookiesModalBox) {
const modalBox = new ModalBox({
image: "icons/cookie.png",
title: "0 cookies : Total privacy",
explanation: "Zero cookie policy means that no tracking of any kind is used on this site."
}, () => {
topLayerNode.removeChild(modalBox.getEnvelope());
/* run */
page.run();
});
topLayerNode.appendChild(modalBox.getEnvelope());
}
});
}
export const createSpinner = function (iconPathname) {
const node = document.createElement("div");
node.className = "boot-loader";
node.innerHTML = `
<div class="boot-embedded-icon"></div>
<div class="boot-spinner">
<svg class="circular" viewBox="25 25 50 50">
<circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/>
</svg>
</div>`;
return node;
}

32
aero/content/AeroColor.js Normal file
View File

@ -0,0 +1,32 @@
export class AeroColor {
static BLACK = new AeroColor(0, 0, 0);
constructor(red, green, blue, transparency = -2) {
super();
this.r = red;
this.g = green;
this.b = blue;
this.a = transparency;
}
/**
*
* @param {HTMLElement} target
*/
applyAsBackground(target) {
if(this.a > -1){
target.style.backgroundColor = `rgb(${this.r},${this.g},${this.b},${this.a})`;
}
else{
target.style.backgroundColor = `rgb(${this.r},${this.g},${this.b})`;
}
}
}

34
aero/content/AeroImage.js Normal file
View File

@ -0,0 +1,34 @@
export class AeroImage {
constructor(pathname) {
super();
this.pathname = pathname;
}
/**
*
*/
applyAsBackground(target) {
const backgroundImageBuffer = new Image();
const _this = this;
backgroundImageBuffer.onload = function () {
/* assign image from buffer */
target.style.backgroundImage = `url(${backgroundImageBuffer.src})`;
/* notify handler */
if (onLoaded) { onLoaded(); }
};
/* trigger loading */
backgroundImageBuffer.src = pathname;
}
}

View File

@ -0,0 +1,82 @@
.aero-background-gradient-light0012 {
background:
radial-gradient(circle farthest-side at 50% 180%, white 15%, transparent 20%),
radial-gradient(closest-corner at 121% 84%, #ef5d5d 190%, transparent 307%),
radial-gradient(closest-side at 40% 77%, #fff64d 76%, transparent 185%),
linear-gradient(#9933ff 10%, transparent);
}
.aero-background-gradient-light0016 {
background:
linear-gradient(142deg, transparent, white),
linear-gradient(108deg, red, transparent),
linear-gradient(45deg, #fff722, #ff26f9);
}
.aero-background-gradient-dark0014 {
background:
radial-gradient(circle farthest-side at 50% 180%, rgb(85, 85, 85) 15%, transparent 20%),
radial-gradient(closest-corner at 121% 84%, #96125f 190%, transparent 307%),
radial-gradient(closest-side at 40% 77%, #908912 76%, transparent 185%),
linear-gradient(#5f209f 10%, transparent);
}
.aero-background-gradient-dark0016 {
background: linear-gradient(108deg, #05050e, transparent), linear-gradient(45deg, #FFF72D, #262bff);
}
.aero-background-gradient-light-tile00 {
background: linear-gradient(108deg, #fae7eb, white);
}
.aero-background-gradient-light-tile01 {
background: linear-gradient(108deg, #e0d4e7, white);
}
.aero-background-gradient-light-tile02 {
background: linear-gradient(108deg, #dbeef7, white);
}
.aero-background-gradient-light-tile03 {
background: linear-gradient(108deg, #d0edef, white);
}
.aero-background-gradient-light-tile04 {
background: linear-gradient(108deg, #b5f6cf, white);
}
.aero-background-gradient-light-tile05 {
background: linear-gradient(108deg, #e3e5ff, white);
}
.aero-background-gradient-light-tile06 {
background: linear-gradient(108deg, #faedcb, white);
}
.aero-background-gradient-light-tile07 {
background: linear-gradient(108deg, #fcd5ce, white);
}
.aero-background-gradient-wip {
background: repeating-linear-gradient(
45deg,
#e9e9e9,
#e4e4e4 32px,
#f8d2a0 32px,
#f8d2a0 64px
);
}

1213
aero/highlight.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<?xml version="1.0" ?><svg height="72" viewBox="0 0 72 72" width="72" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M8,72 L64,72 C68.418278,72 72,68.418278 72,64 L72,8 C72,3.581722 68.418278,-8.11624501e-16 64,0 L8,0 C3.581722,8.11624501e-16 -5.41083001e-16,3.581722 0,8 L0,64 C5.41083001e-16,68.418278 3.581722,72 8,72 Z" fill="#007EBB"/><path d="M62,62 L51.315625,62 L51.315625,43.8021149 C51.315625,38.8127542 49.4197917,36.0245323 45.4707031,36.0245323 C41.1746094,36.0245323 38.9300781,38.9261103 38.9300781,43.8021149 L38.9300781,62 L28.6333333,62 L28.6333333,27.3333333 L38.9300781,27.3333333 L38.9300781,32.0029283 C38.9300781,32.0029283 42.0260417,26.2742151 49.3825521,26.2742151 C56.7356771,26.2742151 62,30.7644705 62,40.051212 L62,62 Z M16.349349,22.7940133 C12.8420573,22.7940133 10,19.9296567 10,16.3970067 C10,12.8643566 12.8420573,10 16.349349,10 C19.8566406,10 22.6970052,12.8643566 22.6970052,16.3970067 C22.6970052,19.9296567 19.8566406,22.7940133 16.349349,22.7940133 Z M11.0325521,62 L21.769401,62 L21.769401,27.3333333 L11.0325521,27.3333333 L11.0325521,62 Z" fill="#FFF"/></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 248 204">
<path fill="#1d9bf0" d="M221.95 51.29c.15 2.17.15 4.34.15 6.53 0 66.73-50.8 143.69-143.69 143.69v-.04c-27.44.04-54.31-7.82-77.41-22.64 3.99.48 8 .72 12.02.73 22.74.02 44.83-7.61 62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07 7.57 1.46 15.37 1.16 22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02 3.91 14.88 6.08 22.92 6.32C11.58 63.31 4.74 33.79 18.14 10.71c25.64 31.55 63.47 50.73 104.08 52.76-4.07-17.54 1.49-35.92 14.61-48.25 20.34-19.12 52.33-18.14 71.45 2.19 11.31-2.23 22.15-6.38 32.07-12.26-3.77 11.69-11.66 21.62-22.2 27.93 10.01-1.18 19.79-3.86 29-7.95-6.78 10.16-15.32 19.01-25.2 26.16z"/>
</svg>

After

Width:  |  Height:  |  Size: 732 B