Browse Source
- using a <div> container instead of an <iframe> (simplifies the build system, avoids the quirks iframes) - Bulma CSS is encapsulated in the #simulator ID to avoid polluting the rest of the page, as well as increasing the chances to override the page CSSmaster
Youen Toupin
3 years ago
14 changed files with 1645 additions and 178 deletions
File diff suppressed because it is too large
Load Diff
@ -1,50 +0,0 @@ |
|||||||
input[type=number] { |
|
||||||
-moz-appearance:textfield; |
|
||||||
} |
|
||||||
|
|
||||||
.wide-label .field-label { |
|
||||||
flex-grow: 2.5; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown.is-fullwidth { |
|
||||||
display: flex; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown.is-fullwidth .dropdown-trigger, |
|
||||||
.dropdown.is-fullwidth .dropdown-menu { |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-trigger.with-dropdown-icon::after { |
|
||||||
border: 3px solid black; |
|
||||||
border-radius: 2px; |
|
||||||
border-right: 0; |
|
||||||
border-top: 0; |
|
||||||
content: " "; |
|
||||||
display: block; |
|
||||||
height: 0.625em; |
|
||||||
margin-top: -0.4375em; |
|
||||||
pointer-events: none; |
|
||||||
position: absolute; |
|
||||||
top: 50%; |
|
||||||
right: 15px; |
|
||||||
transform: rotate(-45deg); |
|
||||||
transform-origin: center; |
|
||||||
width: 0.625em; |
|
||||||
} |
|
||||||
|
|
||||||
.climate-zone { |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
svg g { |
|
||||||
filter: drop-shadow( 4px 4px 3px rgba(0, 0, 0, .7)); |
|
||||||
} |
|
||||||
|
|
||||||
.climate-zone:hover { |
|
||||||
filter: brightness(1.2); |
|
||||||
} |
|
||||||
|
|
||||||
svg text { |
|
||||||
pointer-events: none; |
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
function closest (el: Element, predicate: (e: Element) => boolean) { |
|
||||||
do if (predicate(el)) return el; |
|
||||||
while (el = el && <Element>el.parentNode); |
|
||||||
} |
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
// Load CSS
|
|
||||||
document.getElementsByTagName('head')[0].innerHTML += (<any>window)['app.css']; |
|
||||||
|
|
||||||
// In order to be able to style SVG elements with CSS, and register events with javascript, we must use inline SVG (we can't use an img tag)
|
|
||||||
// For this purpose, the SVG file contents are embedded in a javascript file
|
|
||||||
document.getElementById('zones-map').innerHTML = (<any>window)['climate-zones-map.svg']; |
|
||||||
|
|
||||||
document.querySelectorAll("[data-activate-modal]").forEach(elt => { |
|
||||||
elt.addEventListener('click', e => { |
|
||||||
document.getElementById(elt.getAttribute('data-activate-modal')).classList.toggle('is-active', true); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
document.querySelectorAll('.modal-close, .modal-card-head .delete').forEach(elt => { |
|
||||||
elt.addEventListener('click', e => { |
|
||||||
closest(elt, e => e.classList.contains('modal')).classList.toggle('is-active', false); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
let zoneSelector = <HTMLSelectElement>document.getElementById('zone-selector'); |
|
||||||
document.querySelectorAll('.climate-zone').forEach(elt => { |
|
||||||
elt.addEventListener('click', e => { |
|
||||||
let zoneName = elt.getAttribute('id'); |
|
||||||
zoneSelector.value = zoneName; |
|
||||||
closest(elt, e => e.classList.contains('modal')).classList.toggle('is-active', false); |
|
||||||
}); |
|
||||||
}); |
|
||||||
}); |
|
@ -1,11 +0,0 @@ |
|||||||
{ |
|
||||||
"compilerOptions": { |
|
||||||
"module": "system", |
|
||||||
"noImplicitAny": true, |
|
||||||
"removeComments": true, |
|
||||||
"preserveConstEnums": true, |
|
||||||
"outFile": "../../.intermediate/app.js", |
|
||||||
"sourceMap": false |
|
||||||
}, |
|
||||||
"include": ["./**/*", "../../.intermediate/app/**/*"] |
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
.modal-background { |
|
||||||
display: none; |
|
||||||
} |
|
||||||
|
|
||||||
.modal-card-head { |
|
||||||
border-top-left-radius: 0; |
|
||||||
border-top-right-radius: 0; |
|
||||||
} |
|
||||||
|
|
||||||
.modal-card { |
|
||||||
box-shadow: 4px 3px 10px 3px rgba(0,0,0,0.7); |
|
||||||
} |
|
@ -0,0 +1,77 @@ |
|||||||
|
#simulator { |
||||||
|
@import "3rdparty/bulma/bulma.sass"; |
||||||
|
|
||||||
|
// properties that Bulma would set on the <html> tag |
||||||
|
font-size: $body-size; |
||||||
|
text-rendering: $body-rendering; |
||||||
|
box-sizing: border-box; |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
background-color: $body-background-color; |
||||||
|
-moz-osx-font-smoothing: grayscale; |
||||||
|
-webkit-font-smoothing: antialiased; |
||||||
|
min-width: $body-min-width; |
||||||
|
overflow-x: hidden; |
||||||
|
overflow-y: auto; |
||||||
|
text-size-adjust: 100%; |
||||||
|
|
||||||
|
// properties that Bulma would set on the <body> tag |
||||||
|
font-weight: $body-weight; |
||||||
|
line-height: $body-line-height; |
||||||
|
font-family: $body-family; |
||||||
|
color: $body-color; |
||||||
|
& > section, & > footer { |
||||||
|
font-size: $body-font-size; // we must set this on each direct child of the #simulator div, because if it's specified in em, it's multiplied by the parent font-size |
||||||
|
} |
||||||
|
|
||||||
|
input[type=number] { |
||||||
|
-moz-appearance:textfield; |
||||||
|
} |
||||||
|
|
||||||
|
.wide-label .field-label { |
||||||
|
flex-grow: 2.5; |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown.is-fullwidth { |
||||||
|
display: flex; |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown.is-fullwidth .dropdown-trigger, |
||||||
|
.dropdown.is-fullwidth .dropdown-menu { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.dropdown-trigger.with-dropdown-icon::after { |
||||||
|
border: 3px solid black; |
||||||
|
border-radius: 2px; |
||||||
|
border-right: 0; |
||||||
|
border-top: 0; |
||||||
|
content: " "; |
||||||
|
display: block; |
||||||
|
height: 0.625em; |
||||||
|
margin-top: -0.4375em; |
||||||
|
pointer-events: none; |
||||||
|
position: absolute; |
||||||
|
top: 50%; |
||||||
|
right: 15px; |
||||||
|
transform: rotate(-45deg); |
||||||
|
transform-origin: center; |
||||||
|
width: 0.625em; |
||||||
|
} |
||||||
|
|
||||||
|
.climate-zone { |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
svg g { |
||||||
|
filter: drop-shadow( 4px 4px 3px rgba(0, 0, 0, .7)); |
||||||
|
} |
||||||
|
|
||||||
|
.climate-zone:hover { |
||||||
|
filter: brightness(1.2); |
||||||
|
} |
||||||
|
|
||||||
|
svg text { |
||||||
|
pointer-events: none; |
||||||
|
} |
||||||
|
} |
@ -1,26 +1,36 @@ |
|||||||
|
function closest (el: Element, predicate: (e: Element) => boolean) { |
||||||
|
do if (predicate(el)) return el; |
||||||
|
while (el = el && <Element>el.parentNode); |
||||||
|
} |
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
document.addEventListener('DOMContentLoaded', function() { |
||||||
let frame = <HTMLIFrameElement>document.querySelector('iframe#simulator'); |
let container = document.getElementById('simulator'); |
||||||
let doc = frame.contentWindow.document; |
|
||||||
|
|
||||||
frame.style.width = '100%'; |
// Insert HTML code in the container
|
||||||
frame.style.border = 'none'; |
container.innerHTML += (<any>window)['simulator.html']; |
||||||
frame.setAttribute('scrolling', 'no'); |
|
||||||
|
|
||||||
// Insert HTML code in the iframe
|
// In order to be able to style SVG elements with CSS, and register events with javascript, we must use inline SVG (we can't use an img tag)
|
||||||
doc.open(); |
// For this purpose, the SVG file contents are embedded in a javascript file
|
||||||
doc.write((<any>window)['simulator.html']); |
document.getElementById('zones-map').innerHTML = (<any>window)['climate-zones-map.svg']; |
||||||
doc.close(); |
|
||||||
|
|
||||||
// Load iframe specific CSS
|
document.querySelectorAll("[data-activate-modal]").forEach(elt => { |
||||||
doc.head.innerHTML += (<any>window)['simulator-in-iframe.css']; |
elt.addEventListener('click', e => { |
||||||
|
document.getElementById(elt.getAttribute('data-activate-modal')).classList.toggle('is-active', true); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
// Add script inside frame
|
document.querySelectorAll('.modal-close, .modal-card-head .delete').forEach(elt => { |
||||||
let script = doc.createElement('script'); |
elt.addEventListener('click', e => { |
||||||
script.type = "text/javascript"; |
closest(elt, e => e.classList.contains('modal')).classList.toggle('is-active', false); |
||||||
script.innerText = (<any>window)['app.js']; |
}); |
||||||
doc.body.appendChild(script); |
}); |
||||||
|
|
||||||
setInterval(() => { |
let zoneSelector = <HTMLSelectElement>document.getElementById('zone-selector'); |
||||||
frame.height = Math.max(doc.body.scrollHeight, 700) + 'px'; |
document.querySelectorAll('.climate-zone').forEach(elt => { |
||||||
}, 100); |
elt.addEventListener('click', e => { |
||||||
|
let zoneName = elt.getAttribute('id'); |
||||||
|
zoneSelector.value = zoneName; |
||||||
|
closest(elt, e => e.classList.contains('modal')).classList.toggle('is-active', false); |
||||||
|
}); |
||||||
|
}); |
||||||
}); |
}); |
||||||
|
@ -1,21 +0,0 @@ |
|||||||
let fs = require('fs') |
|
||||||
|
|
||||||
function embedJs(src, dst) { |
|
||||||
fs.readFile(src, 'utf8', function(err, data) { |
|
||||||
if(err) throw err; |
|
||||||
|
|
||||||
data = data.replace(/\\"/g, '\\\\"'); |
|
||||||
data = "(<any>window)['"+src.replace(/^.*[\\\/]/, '')+"'] = `" + data + "`;"; |
|
||||||
|
|
||||||
fs.writeFile(dst, data, function(err) { |
|
||||||
if(err) throw err; |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
let toolsDir = __dirname; |
|
||||||
let dataDir = toolsDir + "/../data"; |
|
||||||
let srcDir = toolsDir + "/../src"; |
|
||||||
let intermediateDir = toolsDir + "/../.intermediate"; |
|
||||||
|
|
||||||
embedJs(intermediateDir+'/app.js', intermediateDir+'/app.js.ts'); |
|
Loading…
Reference in new issue