<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="https://unpkg.com/manuel@0.62.0/dist/style.css">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/manuel@0.62.0/dist/manuel.js"></script>
<script src="https://cdn.rawgit.com/MithrilJS/mithril.js/v0_2_x/mithril.min.js"></script>
<script src="https://unpkg.com/mithril-stream@1.1.0/stream.js"></script>
<script src="https://rawgit.com/ArthurClemens/polythene/master/packages/polythene/polythene-standalone.js"></script>
<script>
const Maybe = {
Just(x){
return { of: Maybe.Just, x}
}
,Nothing(){
return { of: Maybe.Nothing }
}
,map(f){
return function(Ma){
return Ma.of == Maybe.Just
? Maybe.Just( f(Ma.x) )
: Maybe.Nothing()
}
}
}
const {
IconButton
, TextField
, List
, ListTile
, Search
, Button
, Icon
, IndeterminateSpinner: Spinner
} = polythene
const MithrilStreamAutocomplete = manuel({
hyperscript: m
,get: o => o()
,set: (o, x) => o(x)
})
const GithubUserSearch = {
controller(){
const items = m.stream([])
const loginIndex = items.map(indexBy( o => o.login))
const model = {
list: items.map(
xs => xs.map(o => o.login)
)
,input: m.stream('JAForb')
,chosen: m.stream()
,open: m.stream(true)
,highlighted: m.stream('')
}
const loading = m.stream(false)
const request =
afterSilence(1000, model.input).map(function(x){
return x != null && x.length > 2
? Maybe.Just({
method: 'GET'
, url: 'https://api.github.com/search/users?q=' + x
})
: Maybe.Nothing()
})
// side effects
.map(
Maybe.map(function(req){
loading( true )
m.request(req)
.then( res => res.items )
.then( xs => items(xs) )
.then(
() => loading(false)
,() => loading(false)
)
})
)
m.stream.merge(
Object.keys(model)
.map( k => model[k] )
.concat([ loginIndex, loading ])
)
.map( () => m.redraw() )
const view = () =>
m('label', 'Search Github Users'
,MithrilStreamAutocomplete( model, {
filter: () => true
,sort(a, b){
var A = loginIndex()[a]
var B = loginIndex()[b]
return a.score - b.score
}
,renderRoot(config){
return m('.form'
,{ onkeydown: config.onkeydown
}
, [
m(TextField, {
label: 'Github User'
,help: '(Throttled to 1 second)'
,events: {
oninput: config.oninput
// , onfocus: config.onfocus
}
,value: () => model.input()
})
,m(Spinner, { show: loading() })
,config.renderItems(config)
])
}
,renderItem(x, config){
const o = loginIndex()[x]
return m('div'
,{ onmousedown: ()=>
config.clickItem(x)
}
,m(ListTile, {
title:
[x]
.map( config.highlight )
.map(
y => x == model.highlighted()
? m('u', y)
: y
)[0]
,front:
m(Icon, {
type: 'large'
,class: 'avatar'
,src: o.avatar_url
})
})
)
}
,renderItems(config){
return m(List, {
borders: true
,tiles:
config.showingDrawer
? config.filteredList.map(function(x){
return config.renderItem(x, config)
})
: []
})
}
})
)
return { view }
}
,view(o){
return o.view()
}
}
const App = {
view(){
return m(GithubUserSearch)
}
}
m.mount(document.body, App);
function afterSilence(ms, s) {
const r = m.stream()
var timeoutId
var last
s.map(function(){
last = s()
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
r(last);
}, ms);
})
return r
}
function indexBy(f){
return function indexBy$f(xs){
return xs.reduce(function(p, n){
p[f(n)] = n
return p
}, {})
}
}
</script>
</body>
</html>
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |