Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Last active October 19, 2015 06:25
Show Gist options
  • Save tomhodgins/c6f4b30abb1073c302ba to your computer and use it in GitHub Desktop.
Save tomhodgins/c6f4b30abb1073c302ba to your computer and use it in GitHub Desktop.
JOE: The JavaScript Operating Environment. Running live at http://staticresource.com
<!DOCTYPE html>
<html manifest=joe.manifest>
<head>
<meta charset=utf-8>
<title>JOE: The JavaScript Operating Environment</title>
<meta name=apple-mobile-web-app-capable content=yes>
<meta name=apple-mobile-web-app-title content=JOE>
<meta name=apple-mobile-web-app-status-bar-style content=black>
<meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,minimal-ui">
<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,700,900,200italic,300italic,400italic,600italic,700italic,900italic" rel=stylesheet type=text/css>
<link href="http://fonts.googleapis.com/css?family=Source+Code+Pro:300,400,500,600,700,900" rel=stylesheet type=text/css>
<style>
* {box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-kerning:auto}
body {font-family:'OpenSans','Source Sans Pro',Roboto,'HelveticaNeue-Light','Helvetica Neue Light','Helvetica Neue','Myriad Pro','Segoe UI',Myriad,Helvetica,'Lucida Grande','DejaVu Sans Condensed','Liberation Sans','Nimbus Sans L',Tahoma,Geneva,Arial,sans-serif;margin:0;-webkit-text-size-adjust:100%;background:#073642;color:#839496;font-size:12pt}
code,pre {display:inline-block;font-size:100%;font-family:'Source Code Pro',Consolas,'Andale Mono WT','Andale Mono','Lucida Console','Lucida Sans Typewriter','DejaVu Sans Mono','Bitstream Vera Sans Mono','Liberation Mono','Nimbus Mono L',Monaco,'Courier New',Courier,monospace;font-weight:400;color:#eee8d5;cursor:pointer}
code:hover {background:#eee8d5;color:#073642}
section {position:relative;padding:20px;-webkit-user-select:none;user-select:none}
section + section {border-top:1px solid #002b36}
section .exit, section .zoom {font-size:24pt;position:absolute;top:5px;right:15px;color:#586e75;cursor:pointer;transition:color .1s ease-in-out}
section .zoom {right:45px}
section .exit:hover,section .exit:focus,section .zoom:hover,section .zoom:focus {color:#dc322f}
section h1 {margin:0;color:#839496}
section h1 + div,section h1 + iframe{margin-top:.5em}
input[type=text] {width:calc(100% - 65px);float:left;-webkit-appearance:none;appearance:none;background:#002b36;color:#eee8d5;border:1px solid #586e75;border-radius:1px;padding:5px;font-size:14pt;font-weight:normal;outline:none}
input[type=submit] {width:50px;float:right;margin-bottom:20px;-webkit-appearance:none;appearance:none;background:#586e75;color:#002b36;border:1px solid #586e75;border-radius:1px;padding:5px;font-size:14pt;font-weight:normal;outline:none;cursor:pointer}
input[type=submit]:hover,input[type=submit]:focus { background:#657b83;border-color:#657b83}
iframe {border:none;width:100%;min-height:350px;overflow:auto;resize:vertical}
</style>
<script>eval(unescape(escape('♶♡♲☠♡☽♤♯♣♵♭♥♮♴☮♣♲♥♡♴♥♅♬♥♭♥♮♴☨☢♣♡♮♶♡♳☢☩☬♢☽♡☮♧♥♴♃♯♮♴♥♸♴☨☢☲♤☢☩☬♣☽♤♯♣♵♭♥♮♴☮♣♲♥♡♴♥♅♬♥♭♥♮♴☨☢♬♩♮♫☢☩☬♤☽♤♯♣♵♭♥♮♴☮♣♲♥♡♴♥♅♬♥♭♥♮♴☨☢♬♩♮♫☢☩☻♡☮♷♩♤♴♨☽☲☰☰☻♡☮♨♥♩♧♨♴☽☲☰☰☻♢☮♦♩♬♬♓♴♹♬♥☽☢☣☰☷☳☶☴☲☢☻♢☮♢♥♧♩♮♐♡♴♨☨☩☻♢☮♭♯♶♥♔♯☨☱☰☬☰☩☻♢☮♬♩♮♥♔♯☨☱☹☰☬☰☩☻♢☮♱♵♡♤♲♡♴♩♣♃♵♲♶♥♔♯☨☲☰☰☬☰☬☲☰☰☬☱☰☩☻♢☮♬♩♮♥♔♯☨☲☰☰☬☱☹☰☩☻♢☮♱♵♡♤♲♡♴♩♣♃♵♲♶♥♔♯☨☲☰☰☬☲☰☰☬☱☹☰☬☲☰☰☩☻♢☮♬♩♮♥♔♯☨☱☰☬☲☰☰☩☻♢☮♱♵♡♤♲♡♴♩♣♃♵♲♶♥♔♯☨☰☬☲☰☰☬☰☬☱☹☰☩☻♢☮♬♩♮♥♔♯☨☰☬☱☰☩☻♢☮♱♵♡♤♲♡♴♩♣♃♵♲♶♥♔♯☨☰☬☰☬☱☰☬☰☩☻♢☮♣♬♯♳♥♐♡♴♨☨☩☻♢☮♦♩♬♬☨☩☻♢☮♦♩♬♬♓♴♹♬♥☽☢☣☸☳☹☴☹☶☢☻♢☮♦♯♮♴☽☢♢♯♬♤☠☱☰☰♰♸☠♃♯♵♲♩♥♲☢☻♢☮♦♩♬♬♔♥♸♴☨☢♪☢☬☱☵☬☱☲☵☩☻♢☮♦♩♬♬♔♥♸♴☨☢♯♥☢☬☶☳☬☱☲☵☩☻♣☮♴♹♰♥☽☢♩♭♡♧♥☯♸☭♩♣♯♮☢☻♣☮♲♥♬☽☢♳♨♯♲♴♣♵♴☠♩♣♯♮☢☻♤☮♲♥♬☽☢♡♰♰♬♥☭♴♯♵♣♨☭♩♣♯♮☢☻♣☮♨♲♥♦☽♤☮♨♲♥♦☽♡☮♴♯♄♡♴♡♕♒♌☨☢♩♭♡♧♥☯♰♮♧☢☩☻♤♯♣♵♭♥♮♴☮♧♥♴♅♬♥♭♥♮♴♳♂♹♔♡♧♎♡♭♥☨☢♨♥♡♤☢☩♛☰♝☮♡♰♰♥♮♤♃♨♩♬♤☨♣☩☻♤♯♣♵♭♥♮♴☮♧♥♴♅♬♥♭♥♮♴♳♂♹♔♡♧♎♡♭♥☨☢♨♥♡♤☢☩♛☰♝☮♡♰♰♥♮♤♃♨♩♬♤☨♤☩☻').replace(/u../g,'')))</script>
</head>
<body>
<section>
<input type=text autocapitalize=off autocorrect=off>
<input type=submit onclick=enterCommand(input.value) value=Go>
</section>
<script>
var prompt = document.getElementsByTagName('section')[0],
prompt_input = document.querySelectorAll('[type=text]')[0],
iHeight = window.innerHeight - 175,
log = '',
output = '',
known = '',
entries = '',
fullscreen_mode = false,
silent_mode = false,
command = {
calc: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/calc.html" style="height:'+iHeight+'px;min-height:'+550+'px"></iframe>'
},
cards: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/deck.html" style="height:'+iHeight+'px"></iframe>'
},
clear: function (){
if (silent_mode !== true){
silent_mode = true
}
var sections = document.querySelectorAll('section');
for (i=0;i<sections.length;i++){
if (i<sections.length-1){
sections[i].remove()
}
}
},
demos: function(){
var demos = {
'Notifications': {
url: 'http://staticresource.com/notifications.html',
desc: 'JavaScript Notifications Plugin'
},
'Gestures': {
url: 'http://staticresource.com/gestures.html',
desc: 'Simple gesture detection in JS'
},
'Multitouch': {
url: 'http://staticresource.com/touches.html',
desc: 'Multouch Support in JS'
},
'Conjure': {
url: 'http://staticresource.com/conjure.html',
desc: 'Front-end templating in JS'
},
'Countdown': {
url: 'http://staticresource.com/count.html',
desc: 'Countdown using a random interval'
},
'Validation': {
url: 'http://staticresource.com/validation.html',
desc: 'Form Validation with filters, tests, and error messages'
},
'Guided Form': {
url: 'http://staticresource.com/guidedForm.html',
desc: 'Clickable backdrop behind form that focuses next empty field '
},
'Personas': {
url: 'http://staticresource.com/personas-demo.html',
desc: 'Adding custom content for different target audiences'
}
};
output = ''
for (entries in demos){
output += '<a href="#" onclick="this.parentNode.innerHTML=\'<iframe src='+demos[entries].url+' style=height:'+iHeight+'px;background:white></iframe>\'">'+entries+'</a><span>'+demos[entries].desc+'</span><br>'
}
output += '<style>.demos a:not(.exit){display:inline-block;color:#0087ff;padding: 5px 0;}.demos a:not(.exit):hover,.demos a:not(.exit):focus{color:#00afaf;}.demos span:before {content:" - "}</style>'
},
draw: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/sketch.html" style="height:'+iHeight+'px"></iframe>'
},
encode: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/encode.html" style="height:'+iHeight+'px"></iframe>'
},
game: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/game.html" style="height:'+iHeight+'px"></iframe>'
},
gold: function(){
output = '<img src="http://www.kitconet.com/charts/metals/gold/t24_au_en_caoz_2.gif" style="width:500px;max-width:100%;opacity:.6;border-radius:2px">'
},
help: function(){
output = 'Known commands include: '
for (known in command){
output += '<code onclick="interpret(\''+known+'\');addToHistory(\''+known+'\');">'+known+'</code>'
}
output += '<style>.help code:after {content:",";display:inline;background:#073642;padding-right:5px}.help code:last-of-type:after {content:""}code:hover:after{color:#eee8d5}</style>'
},
hexadecimal: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/grid.html" style="height:'+iHeight+'px"></iframe>'
},
menu: function(){
var menu = {
'Control Panel': 'https://staticresource.com:10000',
'Hue Scenes': 'https://my.meethue.com/en-us/my-scenes',
'PHPmyAdmin': 'http://staticresource.com/pma',
'Plex': 'http://staticresource.com/plex',
'BuildMogul': 'http://buildmogul.com/vip',
'Ballr': 'http://staticresource.com:3010/users/sign_in',
'Unicons': 'http://unicons.io/'
};
output = ''
for (entries in menu){
output += '<a href="'+menu[entries]+'">'+entries+'</a><br>'
}
output += '<style>.menu a:not(.exit){display:inline-block;color:#0087ff;padding: 5px 0;}.menu a:not(.exit):hover,.menu a:not(.exit):focus{color:#00afaf;}</style>'
},
memo: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/tinkerpad" style="height:'+iHeight+'px"></iframe>'
},
reminder: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/reminders.html" style="height:'+iHeight+'px"></iframe>'
},
search: function(){
fullscreen_mode = true
output = '<iframe src="https://qwant.com" style="height:'+iHeight+'px"></iframe>'
},
shuffle: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/shuffle.html" style="height:'+iHeight+'px"></iframe>'
},
silver: function(){
output = '<img src="http://www.kitconet.com/charts/metals/silver/t24_ag_en_caoz_2.gif" style="width:500px;max-width:100%;opacity:.6;border-radius:2px">'
},
time: function(){
var d = new Date(),
days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
day = days[d.getDay()],
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
month = months[d.getMonth()],
date = d.getDate(),
suf = ['th','st','nd','rd'],
v = date%100,
date = date+(suf[(v-20)%10]||suf[v]||suf[0]),
hours = d.getHours(),
minutes = d.getMinutes(),
noon = '';
// Display hours in 12-hour format, and set am/pm
if (hours==12){
noon = 'pm'
} else if (hours>12){
hours = hours-12
noon = 'pm'
} else if (hours==0){
hours = 12
noon = 'am'
} else {
noon = 'am'
}
// Add '0' to minutes if less than 10
if(minutes<10){
minutes = '0'+minutes
}
// Output the Timestamp
var timestamp = day+' '+month+' '+date+', '+hours+':'+minutes+' '+noon;
output = timestamp
},
usd: function(){
output = '<img src="http://www.weblinks247.com/exrate/24hr-cad-small.gif" style="width:500px;max-width:100%;opacity:.6;border-radius:2px">'
},
web: function(){
fullscreen_mode = true
output = '<iframe src="http://staticresource.com/speedtest.html" style="height:'+iHeight+'px"></iframe>'
},
weather: function(){
output = '<div style="background:#839496;padding-top:5px;max-height:245px;overflow:hidden;border-radius:2px;"><iframe id="forecast_embed" src="http://forecast.io/embed/#lat=43.612426&lon=-79.488147&name=Mimico&color=#fdf6e3&font=Open+Sans&units=ca"> </iframe></div>'
},
welcome: function(){
output = '<p>Welcome to JOE, the JavaScript Operating Environment. This is a web page concept using keyboard input as a means to access and control the display of information.</p><p>Type “<code onclick="interpret(\'help\');addToHistory(\'help\');">help</code>” to see a list of known commands.</p>'
}
};
function enterCommand(input){
if(prompt_input.value != ''){
log = input
prompt_input.value = ''
interpret(input)
if (silent_mode !== true){
addToHistory(input)
} else {
silent_mode = false
}
prompt_input.focus()
} else {
prompt_input.focus()
}
}
function interpret(input){
for (known in command){
if (input == known){
window.command[known]()
}
}
}
function addToHistory(input){
var section = document.createElement('section'),
history = document.createElement('h1'),
exit = document.createElement('a');
exit.innerHTML = '×'
exit.classList.add('exit')
exit.setAttribute('onclick', 'this.parentNode.remove();prompt_input.focus()')
section.appendChild(exit)
section.classList.add(input)
history.innerHTML = input
section.appendChild(history)
if (output != ''){
if (fullscreen_mode == true){
output = output + '<a class="zoom" onclick="if(this.previousSibling.requestFullscreen){this.previousSibling.requestFullscreen()}else if(this.previousSibling.msRequestFullscreen){this.previousSibling.msRequestFullscreen()}else if(this.previousSibling.mozRequestFullScreen){this.previousSibling.mozRequestFullScreen()}else if(this.previousSibling.webkitRequestFullscreen){this.previousSibling.webkitRequestFullscreen()}">+</a>'
fullscreen_mode = false
}
var content = document.createElement('div');
content.innerHTML = output
section.appendChild(content)
output = ''
}
document.getElementsByTagName('body')[0].insertBefore(section, prompt)
window.scrollTo(0, document.body.scrollHeight)
}
document.onkeydown = function(e){
e = e || window.event
var charCode = (typeof e.which=='number')?e.which:e.keyCode;
charCode==13 && enterCommand(prompt_input.value) // enter key submits the command
charCode==38 && (prompt_input.value = log) // up key shows last command
}
interpret('welcome')
addToHistory('welcome')
window.addEventListener('load', function(e){
window.scrollTo(0,0)
prompt_input.focus()
})
</script>
</body>
</html>
CACHE MANIFEST
# version 9
CACHE:
http://staticresource.com/index.html
#apps
http://staticresource.com/sketch.html
http://staticresource.com/encode.html
http://staticresource.com/game.html
http://staticresource.com/shuffle.html
http://staticresource.com/reminders.html
http://staticresource.com/speedtest.html
http://staticresource.com/calc.html
http://staticresource.com/deck.html
http://staticresource.com/grid.html
#demos
http://staticresource.com/gestures.html
http://staticresource.com/touches.html
http://staticresource.com/notifications.html
http://staticresource.com/conjure.html
http://staticresource.com/count.html
http://staticresource.com/validation.html
http://staticresource.com/guidedForm.html
http://staticresource.com/personas-demo.html
NETWORK:
*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment