Update
This commit is contained in:
commit
d182ead446
24
.project
Normal file
24
.project
Normal 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
12
.settings/.jsdtscope
Normal 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>
|
||||
2
.settings/org.eclipse.core.resources.prefs
Normal file
2
.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
10
.settings/org.eclipse.wst.common.component
Normal file
10
.settings/org.eclipse.wst.common.component
Normal 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>
|
||||
7
.settings/org.eclipse.wst.common.project.facet.core.xml
Normal file
7
.settings/org.eclipse.wst.common.project.facet.core.xml
Normal 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>
|
||||
1
.settings/org.eclipse.wst.jsdt.ui.superType.container
Normal file
1
.settings/org.eclipse.wst.jsdt.ui.superType.container
Normal file
@ -0,0 +1 @@
|
||||
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
|
||||
1
.settings/org.eclipse.wst.jsdt.ui.superType.name
Normal file
1
.settings/org.eclipse.wst.jsdt.ui.superType.name
Normal file
@ -0,0 +1 @@
|
||||
Window
|
||||
BIN
aero/.DS_Store
vendored
Normal file
BIN
aero/.DS_Store
vendored
Normal file
Binary file not shown.
50
aero/AeroElement.js
Normal file
50
aero/AeroElement.js
Normal 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
40
aero/AeroMovie.css
Normal 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
146
aero/AeroMovie.js
Normal 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
81
aero/AeroUtilities.js
Normal 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
25
aero/CodeBlock.css
Normal 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
85
aero/CodeBlock.js
Normal 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
79
aero/Deck.css
Normal 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
100
aero/Deck.js
Normal 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
301
aero/Documentation.css
Normal 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
338
aero/DocumentationV2.js
Normal 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
130
aero/Footer.css
Normal 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
48
aero/Footer.js
Normal 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
46
aero/FooterV2.js
Normal 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
348
aero/Grid.css
Normal 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
208
aero/Grid.js
Normal 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
320
aero/Header.css
Normal 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
402
aero/HeaderV2.js
Normal 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
45
aero/Icon.js
Normal 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
141
aero/ModalBox.css
Normal 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
87
aero/ModalBox.js
Normal 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
344
aero/Slide.css
Normal 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
309
aero/Slide.js
Normal 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
297
aero/SlideV2.js
Normal 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
358
aero/SpText.css
Normal 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
152
aero/SpText.js
Normal 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
498
aero/SquareGrid.css
Normal 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
377
aero/SquareGrid.js
Normal 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
405
aero/SquareGridV2.js
Normal 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
571
aero/TextBlock.css
Normal 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
251
aero/TextBlock.js
Normal 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
537
aero/TextBlockV2.js
Normal 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
13
aero/Video.css
Normal 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
66
aero/Video.js
Normal 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
5
aero/WebPage.css
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
184
aero/WebPage.js
Normal file
184
aero/WebPage.js
Normal 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
303
aero/WebPageV2.js
Normal 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
167
aero/aero.js
Normal 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
206
aero/aeroV2.js
Normal 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
156
aero/boot.css
Normal 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
103
aero/boot.js
Normal 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
32
aero/content/AeroColor.js
Normal 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
34
aero/content/AeroImage.js
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
82
aero/gradient-backgrounds.css
Normal file
82
aero/gradient-backgrounds.css
Normal 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
1213
aero/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
aero/icons/LinkedIn-icon.svg
Normal file
1
aero/icons/LinkedIn-icon.svg
Normal 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 |
4
aero/icons/Twitter-icon.svg
Normal file
4
aero/icons/Twitter-icon.svg
Normal 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 |
Loading…
x
Reference in New Issue
Block a user