Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Elm compiler error in the browser
- Loading branch information
Showing
9 changed files
with
875 additions
and
324 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module.exports = { | ||
'env': { | ||
'browser': true, | ||
'es6': true | ||
}, | ||
'extends': 'standard', | ||
'globals': { | ||
'Atomics': 'readonly', | ||
'SharedArrayBuffer': 'readonly' | ||
}, | ||
'parserOptions': { | ||
'ecmaVersion': 2018, | ||
'sourceType': 'module' | ||
}, | ||
'rules': { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"js": { | ||
"indent_size": 2, | ||
"indent_char": " ", | ||
"other": " ", | ||
"indent_level": 0, | ||
"indent_with_tabs": false, | ||
"preserve_newlines": true, | ||
"max_preserve_newlines": 2, | ||
"jslint_happy": true, | ||
"indent_handlebars": true | ||
}, | ||
"json": { | ||
"indent_size": 2, | ||
"indent_char": " " | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
(function refresh () { | ||
var verboseLogging = false | ||
var socketUrl = window.location.origin | ||
|
||
socketUrl = socketUrl.replace() // This is dynamically populated by the reload.js file before it is sent to the browser | ||
var socket | ||
|
||
if (verboseLogging) { | ||
console.log('Reload Script Loaded') | ||
} | ||
|
||
if (!('WebSocket' in window)) { | ||
throw new Error('Reload only works with browsers that support WebSockets') | ||
} | ||
|
||
// Explanation of the flags below: | ||
|
||
// The first change flag is used to tell reload to wait until the socket closes at least once before we allow the page to open on a socket open event. Otherwise reload will go into a inifite loop, as the page will have a socket on open event once it loads for the first time | ||
var firstChangeFlag = false | ||
|
||
// The navigatedAwayFromPageFlag is set to true in the event handler onbeforeunload because we want to short-circuit reload to prevent it from causing the page to reload before the navigation occurs. | ||
var navigatedAwayFromPageFlag | ||
|
||
// Wait until the page loads for the first time and then call the webSocketWaiter function so that we can connect the socket for the first time | ||
window.addEventListener('load', function () { | ||
if (verboseLogging === true) { | ||
console.log('Page Loaded - Calling webSocketWaiter') | ||
} | ||
websocketWaiter() | ||
}) | ||
|
||
// If the user navigates away from the page, we want to short-circuit reload to prevent it from causing the page to reload before the navigation occurs. | ||
window.addEventListener('beforeunload', function () { | ||
if (verboseLogging === true) { | ||
console.log('Navigated away from the current URL') | ||
} | ||
|
||
navigatedAwayFromPageFlag = true | ||
}) | ||
|
||
function showError(error) { | ||
console.error(error) | ||
if (hideCompiling()) { | ||
setTimeout(function () { | ||
showError_(error) | ||
}, 400); | ||
} else { | ||
showError_(error) | ||
} | ||
} | ||
|
||
function showError_(error) { | ||
var nodeContainer = document.getElementById("elm-live:elmErrorContainer"); | ||
if (!nodeContainer) { | ||
nodeContainer = document.createElement('div'); | ||
nodeContainer.id = "elm-live:elmErrorContainer" | ||
document.body.appendChild(nodeContainer); | ||
} | ||
nodeContainer.innerHTML = | ||
"<div id='elm-live:elmErrorBackground' style='z-index: 100; perspective: 500px; transition: opacity 0.3s; opacity: 0; position: fixed; top: 0; left: 0; background-color: rgba(0,0,0,0.3); width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;'>" + | ||
"<xmp id='elm-live:elmError' style='transform: rotateX(-90deg); transition: transform 0.3s; transform-style: preserve-3d; font-size: 16px; overflow: scroll; background-color: rgba(0,0,0,0.9); color: #ddd; width: 70%; height: 60%; padding: 30px'>" + | ||
error + | ||
"</xmp>" + | ||
"</div>" | ||
setTimeout(function () { | ||
document.getElementById("elm-live:elmErrorBackground").style.opacity = 1 | ||
document.getElementById("elm-live:elmError").style.transform = "rotateX(0deg)" | ||
}, 0); | ||
} | ||
|
||
function hideError() { | ||
var node = document.getElementById("elm-live:elmErrorContainer"); | ||
if (node) { | ||
document.getElementById("elm-live:elmErrorBackground").style.opacity = 0 | ||
document.getElementById("elm-live:elmError").style.transform = "rotateX(-90deg)" | ||
setTimeout(function () { | ||
document.getElementById("elm-live:elmErrorContainer").remove(); | ||
}, 300); | ||
} | ||
} | ||
|
||
function showCompiling(message) { | ||
hideError(); | ||
var nodeContainer = document.getElementById("elm-live:elmCompilingContainer"); | ||
if (!nodeContainer) { | ||
nodeContainer = document.createElement('div'); | ||
nodeContainer.id = "elm-live:elmCompilingContainer" | ||
document.body.appendChild(nodeContainer); | ||
} | ||
nodeContainer.innerHTML = | ||
"<style>" + | ||
"#loading {" + | ||
" display: inline-block;" + | ||
" width: 50px;" + | ||
" height: 50px;" + | ||
" border: 3px solid rgba(255,255,255,.3);" + | ||
" border-radius: 50%;" + | ||
" border-top-color: #fff;" + | ||
" animation: spin 1s linear infinite;" + | ||
"}" + | ||
"@keyframes spin {" + | ||
"to { transform: rotate(360deg); }" + | ||
"}" + | ||
"</style>" + | ||
"<div id='elm-live:elmCompilingBackground' style='z-index: 100; transition: opacity 0.3s; opacity: 0; position: fixed; top: 0; left: 0; background-color: rgba(0,0,0,0.3); width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; flex-direction: column'>" + | ||
"<div id='loading'>" + | ||
"</div>" + | ||
"<div style='color: #fff; padding: 30px; font-size: 24px; font-weight: bold; font-family: sans-serif'>" + | ||
message + | ||
"</div>"+ | ||
"</div>" | ||
setTimeout(function () { | ||
document.getElementById("elm-live:elmCompilingBackground").style.opacity = 1 | ||
}, 0); | ||
} | ||
|
||
function hideCompiling() { | ||
var node = document.getElementById("elm-live:elmCompilingContainer"); | ||
if (node) { | ||
document.getElementById("elm-live:elmCompilingBackground").style.opacity = 0 | ||
setTimeout(function () { | ||
document.getElementById("elm-live:elmCompilingContainer").remove(); | ||
}, 300); | ||
return (true); | ||
} else { | ||
return (false); | ||
} | ||
} | ||
|
||
// Check to see if the server sent us reload (meaning a manually reload event was fired) and then reloads the page | ||
var socketOnMessage = function (msg) { | ||
if (msg.data.match(/^error::/)) { | ||
// Displaying the Elm compiler error in the console | ||
// and in the browsers | ||
showError(msg.data.replace(/^error::/, "")); | ||
} | ||
else if (msg.data === 'reload') { | ||
hideCompiling() | ||
window.location.reload() | ||
} | ||
else if (msg.data.match(/^compiling::/)) { | ||
showCompiling(msg.data.replace(/^compiling::/, "")) | ||
} | ||
} | ||
|
||
var socketOnOpen = function (msg) { | ||
if (verboseLogging) { | ||
console.log('Socket Opened') | ||
} | ||
|
||
// We only allow the reload on two conditions, one when the socket closed (firstChange === true) and two if we didn't navigate to a new page (navigatedAwayFromPageFlag === false) | ||
if (firstChangeFlag === true && navigatedAwayFromPageFlag !== true) { | ||
if (verboseLogging) { | ||
// console.log('Reloaded') | ||
} | ||
|
||
// Reset the firstChangeFlag to false so that when the socket on open events are being fired it won't keep reloading the page | ||
firstChangeFlag = false | ||
|
||
// Now that everything is set up properly we reload the page | ||
// window.location.reload() | ||
} | ||
} | ||
|
||
// Socket on close event that sets flags and calls the webSocketWaiter function | ||
var socketOnClose = function (msg) { | ||
if (verboseLogging) { | ||
console.log('Socket Closed - Calling webSocketWaiter') | ||
} | ||
|
||
// We encountered a change so we set firstChangeFlag to true so that as soon as the server comes back up and the socket opens we can allow the reload | ||
firstChangeFlag = true | ||
|
||
// Call the webSocketWaiter function so that we can open a new socket and set the event handlers | ||
websocketWaiter() | ||
} | ||
|
||
var socketOnError = function (msg) { | ||
if (verboseLogging) { | ||
console.log(msg) | ||
} | ||
} | ||
|
||
// Function that opens a new socket and sets the event handlers for the socket | ||
function websocketWaiter () { | ||
if (verboseLogging) { | ||
console.log('Waiting for socket') | ||
} | ||
setTimeout(function () { | ||
socket = new WebSocket(socketUrl); // eslint-disable-line | ||
|
||
socket.onopen = socketOnOpen | ||
socket.onclose = socketOnClose | ||
socket.onmessage = socketOnMessage | ||
socket.onerror = socketOnError | ||
}, 250) | ||
} | ||
})() |
Oops, something went wrong.