<script type="text/javascript"> ////////// // This is an error handler to show JS errors to the user. // More info at https://github.com/ubershmekel/show-js-errors // Please modify `showJsErrorsMessage` to suit your needs. ////////// var showJsErrorsMessage = "Unexpected error :( "; function showAlert(message) { if (!document.body) { // toasts don't work before the body exists, so we postpone the toast. setTimeout(function () { showAlert(message); }, 200); return; }; var containerId = 'snackAlertsContainer'; var containerElem = document.getElementById(containerId); if (!containerElem) { // We need a container so alerts don't overlap var containerElem = document.createElement("div"); containerElem.id = containerId; document.body.appendChild(containerElem); } // Get the snackbar DIV var elem = document.createElement("div"); elem.innerHTML = message; // Add the "show" class to DIV elem.className = "snackAlert show"; elem.onmouseenter = function() { if (hiderTimeoutId) { clearTimeout(hiderTimeoutId); hiderTimeoutId = 0; } } elem.onmouseleave = function() { scheduleRemoval(); } var hiderTimeoutId = 0; function scheduleRemoval() { var timeBeforeFadeoutStartsMs = 3000; if (hiderTimeoutId) { // Oddly this can happen when mousing over quickly. return; } hiderTimeoutId = setTimeout(function() { // Start fading element out // Make sure `fadeoutDuration` fits the css transition duration var fadeoutDuration = 1000; elem.className = elem.className.replace("show", "hiding"); setTimeout(function () { // Remove the element entirely elem.parentNode.removeChild(elem); }, fadeoutDuration); }, timeBeforeFadeoutStartsMs); } scheduleRemoval(); containerElem.appendChild(elem); } window.onerror = function (msg, url, linenumber) { // Tell users when errors occur // Based on http://stackoverflow.com/questions/2604976/javascript-how-to-display-script-errors-in-a-popup-alert/2604997#2604997 // Note that if you get the `msg` as "Script error." that's because of cross-origin scrubbing, // see: https://stackoverflow.com/questions/19141195/how-can-we-listen-for-errors-that-do-not-trigger-window-onerror/19141439#19141439 showAlert(showJsErrorsMessage + msg) // `return false` to report on dev console too return false; } window.addEventListener("unhandledrejection", function (event) { // Handle unhandled promises, these should probably just throw, yet here we are. showAlert(showJsErrorsMessage + " Broken promise - " + event.reason); //throw 'broken promise: ' + event.reason }); </script> <style type="text/css"> #snackAlertsContainer { /* Sit on top of the screen */ position: fixed; /* Add a z-index if needed */ z-index: 1; bottom: 0; right: 0; width: 0; } .snackAlert { display: none; /* Hidden by default. Visible on click */ margin: auto; position: relative; right: 54vw; width: 50vw; /* `bottom` is tied to the animation `fadein` */ bottom: 20px; margin-bottom: 16px; background-color: #933; color: #fff; text-align: center; border-radius: 2px; padding: 16px; opacity: 1; -webkit-transition: opacity 1s ease-in-out; -moz-transition: opacity 1s ease-in-out; -ms-transition: opacity 1s ease-in-out; -o-transition: opacity 1s ease-in-out; transition: opacity 1s ease-in-out; } /* Show the snackbar when clicking on a button (class added with JavaScript) */ .snackAlert.hiding { display: block; opacity: 0; } .snackAlert.show { display: block; opacity: 1; /* Show the snackbar */ /* Add animation: Take 0.5 seconds to fade in and out the snackbar. However, delay the fade out process for 2.5 seconds */ -webkit-animation: fadein 1.5s; animation: fadein 1.5s; } /* Animations to fade the snackbar in and out */ @-webkit-keyframes fadein { from { bottom: 0; opacity: 0; } to { bottom: 20px; opacity: 1; } } @keyframes fadein { from { bottom: 0; opacity: 0; } to { bottom: 20px; opacity: 1; } } </style>