Created
July 6, 2016 16:53
-
-
Save anonymous/5cd6e118186d5e429d6a1fa9da03668c to your computer and use it in GitHub Desktop.
JS Bin // source http://jsbin.com/jozihiluki
This file contains hidden or 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>JS Bin</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.min.js"></script> | |
<script src="https://wzrd.in/standalone/deep-freeze"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script> | |
<style> | |
#tabs span { | |
border: 1px solid black; | |
border-radius: 7px 7px 0 0; | |
padding: 3px; | |
cursor: pointer; | |
} | |
#tabs span.active { | |
background-color: lightgray; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="tabs"> | |
<span id="model0" class="active">base</span> | |
<!--<span id="model1" class="active">derived1</span>--> | |
</div> | |
<br/> | |
<p id="year"> | |
Year: | |
<span>2014</span> | |
<button>Set</button> | |
</p> | |
<p> | |
<span>foo:</span> | |
<input id="sankey-chart" type="range" min="-50" max="150" value="25"/> | |
<span id="sankey-value"></span> | |
</p> | |
<p> | |
<span>total:</span> | |
<span id="total-value"></span> | |
</p> | |
<script id="jsbin-javascript"> | |
/* jshint esnext: true */ | |
/* jshint asi: true */ | |
/* jshint laxcomma: true */ | |
/* | |
ES6: (state = [], action) => { ... } | |
ES5: function(state, action) { if (!state) state = []; ... } | |
Functions with a single expression using ES6 arrow functions don't need {}: | |
[1,2,3].map(elem => elem * 2) // returns [2,4,6] | |
The const keyword declares a constant. Reusing the same name will throw an error: | |
const foo = 'bar' | |
const foo = 'baz' // throws "SyntaxError: Identifier 'foo' has already been declared" | |
*/ | |
const { createStore, combineReducers } = Redux; | |
const extractId = (id) => parseInt(id.match(/\d+/g)[0]) | |
const sankeyChart = document.getElementById('sankey-chart') | |
, sankeyValue = document.getElementById('sankey-value') | |
, totalValue = document.getElementById('total-value') | |
const defaultYear = document.querySelector('#year span') | |
, setYear = document.querySelector('#year button') | |
//------------------------------------------------------------------------------ | |
var forecastId = 0; | |
const forecastModel = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_MODEL': | |
return state.map(e => { e.active = false; return e }).concat({ | |
id: forecastId++, | |
active: true, | |
defaultYear: action.defaultYear || state[0].defaultYear, | |
drivers: !state[0] ? action.drivers : | |
Object.assign({}, state[0].drivers, action.drivers || {}) | |
}) | |
case 'SELECT_MODEL': | |
return state.map(e => { | |
e.active = e.id === action.id ? true : false | |
return e | |
}) | |
case 'UPDATE_MODEL': | |
const modelIndex = state.findIndex(e => e.active) | |
return state.slice(0, modelIndex) | |
.concat([{ | |
id: state[modelIndex].id, | |
active: true, | |
defaultYear: action.defaultYear || | |
state[modelIndex].defaultYear, | |
drivers: Object.assign({}, state[0].drivers, action.drivers || {}) | |
}]) | |
.concat(state.slice(modelIndex + 1)) | |
case 'DELETE_MODEL': | |
return modelIndex === 0 ? state | |
: state.slice(0, modelIndex) | |
.concat(state.slice(modelIndex + 1)) | |
default: | |
return state | |
} | |
} | |
forecastStore = createStore(forecastModel) | |
// render the view | |
forecastStore.subscribe(() => { | |
const tabs = forecastStore.getState().map(e => { | |
return `<span id="model${e.id}" class="${e.active ? 'active' : ''}" onClick="selectModel(event)">` + | |
`model${e.id}` + | |
`</span>` | |
}).join() | |
document.getElementById('tabs').innerHTML = tabs | |
const activeModel = forecastStore.getState().find(e => e.active) | |
sankeyChart.value = activeModel.drivers.foo | |
defaultYear.innerHTML = activeModel.defaultYear | |
totalValue.innerHTML = activeModel.drivers.total() | |
if (activeModel.id === 0) | |
setYear.setAttribute('disabled', 'disabled') | |
else | |
setYear.removeAttribute('disabled') | |
//console.log(forecastStore.getState(), activeModel) | |
}) | |
// dispatch base model | |
forecastStore.dispatch({ | |
type: 'ADD_MODEL', | |
active: true, | |
defaultYear: 2016, | |
drivers: { | |
foo: 22, | |
total: function() { return this.foo * 3 } | |
} | |
}) | |
function selectModel(event) { | |
const modelId = extractId(event.target.id) | |
forecastStore.dispatch({ | |
type: 'SELECT_MODEL', | |
id: modelId | |
}) | |
console.log('foo' ) | |
} | |
const sankey = (state = sankeyChart.value, action) => { | |
switch (action.type) { | |
case 'SANKEY_DRAG': | |
return action.sankeyValue | |
default: | |
return state | |
} | |
} | |
const sankeyStore = createStore(sankey) | |
sankeyStore.subscribe(() => { | |
sankeyValue.innerHTML = sankeyStore.getState() | |
}) | |
sankeyStore.dispatch({ | |
type: 'SANKEY_DRAG', | |
sankeyValue: sankeyChart.value | |
}) | |
// sankey chart arm dragging | |
sankeyChart.addEventListener('input', (event) => { | |
sankeyStore.dispatch({ | |
type: 'SANKEY_DRAG', | |
sankeyValue: event.target.value | |
}) | |
}) | |
// sankey chart arm let go | |
sankeyChart.addEventListener('mouseup', (event) => { | |
if (forecastStore.getState().find(e => e.active).id === 0) { | |
forecastStore.dispatch({ | |
type: 'ADD_MODEL', | |
drivers: { | |
foo: parseInt(sankeyChart.value) | |
} | |
}) | |
} | |
else { | |
forecastStore.dispatch({ | |
type: 'UPDATE_MODEL', | |
drivers: { | |
foo: parseInt(sankeyChart.value) | |
} | |
}) | |
} | |
console.log('blur') | |
}) | |
/* | |
const todo = (state, action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
return state.id !== action.id ? state : { | |
...state, | |
completed: !state.completed | |
}; | |
default: | |
return state; | |
} | |
}; | |
const todos = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [ | |
...state, | |
{ | |
id: action.id, | |
text: action.text, | |
completed: false | |
} | |
]; | |
case 'TOGGLE_TODO': | |
return state.map(t => todo(t, action)); | |
default: | |
return state; | |
} | |
} | |
const visibilityFilter = (state = 'SHOW_ALL', action) => { | |
switch (action.type) { | |
case 'SET_VISIBILITY_FILTER': | |
return action.filter; | |
default: | |
return state; | |
} | |
} | |
const todoApp = combineReducers({ | |
todos, | |
visibilityFilter | |
}); | |
const store = createStore(todos); | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id:0, | |
text: 'Learn Redux' | |
}); | |
*/ | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">/* jshint esnext: true */ | |
/* jshint asi: true */ | |
/* jshint laxcomma: true */ | |
/* | |
ES6: (state = [], action) => { ... } | |
ES5: function(state, action) { if (!state) state = []; ... } | |
Functions with a single expression using ES6 arrow functions don't need {}: | |
[1,2,3].map(elem => elem * 2) // returns [2,4,6] | |
The const keyword declares a constant. Reusing the same name will throw an error: | |
const foo = 'bar' | |
const foo = 'baz' // throws "SyntaxError: Identifier 'foo' has already been declared" | |
*/ | |
const { createStore, combineReducers } = Redux; | |
const extractId = (id) => parseInt(id.match(/\d+/g)[0]) | |
const sankeyChart = document.getElementById('sankey-chart') | |
, sankeyValue = document.getElementById('sankey-value') | |
, totalValue = document.getElementById('total-value') | |
const defaultYear = document.querySelector('#year span') | |
, setYear = document.querySelector('#year button') | |
//------------------------------------------------------------------------------ | |
var forecastId = 0; | |
const forecastModel = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_MODEL': | |
return state.map(e => { e.active = false; return e }).concat({ | |
id: forecastId++, | |
active: true, | |
defaultYear: action.defaultYear || state[0].defaultYear, | |
drivers: !state[0] ? action.drivers : | |
Object.assign({}, state[0].drivers, action.drivers || {}) | |
}) | |
case 'SELECT_MODEL': | |
return state.map(e => { | |
e.active = e.id === action.id ? true : false | |
return e | |
}) | |
case 'UPDATE_MODEL': | |
const modelIndex = state.findIndex(e => e.active) | |
return state.slice(0, modelIndex) | |
.concat([{ | |
id: state[modelIndex].id, | |
active: true, | |
defaultYear: action.defaultYear || | |
state[modelIndex].defaultYear, | |
drivers: Object.assign({}, state[0].drivers, action.drivers || {}) | |
}]) | |
.concat(state.slice(modelIndex + 1)) | |
case 'DELETE_MODEL': | |
return modelIndex === 0 ? state | |
: state.slice(0, modelIndex) | |
.concat(state.slice(modelIndex + 1)) | |
default: | |
return state | |
} | |
} | |
forecastStore = createStore(forecastModel) | |
// render the view | |
forecastStore.subscribe(() => { | |
const tabs = forecastStore.getState().map(e => { | |
return `<span id="model${e.id}" class="${e.active ? 'active' : ''}" onClick="selectModel(event)">` + | |
`model${e.id}` + | |
`</span>` | |
}).join() | |
document.getElementById('tabs').innerHTML = tabs | |
const activeModel = forecastStore.getState().find(e => e.active) | |
sankeyChart.value = activeModel.drivers.foo | |
defaultYear.innerHTML = activeModel.defaultYear | |
totalValue.innerHTML = activeModel.drivers.total() | |
if (activeModel.id === 0) | |
setYear.setAttribute('disabled', 'disabled') | |
else | |
setYear.removeAttribute('disabled') | |
//console.log(forecastStore.getState(), activeModel) | |
}) | |
// dispatch base model | |
forecastStore.dispatch({ | |
type: 'ADD_MODEL', | |
active: true, | |
defaultYear: 2016, | |
drivers: { | |
foo: 22, | |
total: function() { return this.foo * 3 } | |
} | |
}) | |
function selectModel(event) { | |
const modelId = extractId(event.target.id) | |
forecastStore.dispatch({ | |
type: 'SELECT_MODEL', | |
id: modelId | |
}) | |
console.log('foo' ) | |
} | |
const sankey = (state = sankeyChart.value, action) => { | |
switch (action.type) { | |
case 'SANKEY_DRAG': | |
return action.sankeyValue | |
default: | |
return state | |
} | |
} | |
const sankeyStore = createStore(sankey) | |
sankeyStore.subscribe(() => { | |
sankeyValue.innerHTML = sankeyStore.getState() | |
}) | |
sankeyStore.dispatch({ | |
type: 'SANKEY_DRAG', | |
sankeyValue: sankeyChart.value | |
}) | |
// sankey chart arm dragging | |
sankeyChart.addEventListener('input', (event) => { | |
sankeyStore.dispatch({ | |
type: 'SANKEY_DRAG', | |
sankeyValue: event.target.value | |
}) | |
}) | |
// sankey chart arm let go | |
sankeyChart.addEventListener('mouseup', (event) => { | |
if (forecastStore.getState().find(e => e.active).id === 0) { | |
forecastStore.dispatch({ | |
type: 'ADD_MODEL', | |
drivers: { | |
foo: parseInt(sankeyChart.value) | |
} | |
}) | |
} | |
else { | |
forecastStore.dispatch({ | |
type: 'UPDATE_MODEL', | |
drivers: { | |
foo: parseInt(sankeyChart.value) | |
} | |
}) | |
} | |
console.log('blur') | |
}) | |
/* | |
const todo = (state, action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
return state.id !== action.id ? state : { | |
...state, | |
completed: !state.completed | |
}; | |
default: | |
return state; | |
} | |
}; | |
const todos = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [ | |
...state, | |
{ | |
id: action.id, | |
text: action.text, | |
completed: false | |
} | |
]; | |
case 'TOGGLE_TODO': | |
return state.map(t => todo(t, action)); | |
default: | |
return state; | |
} | |
} | |
const visibilityFilter = (state = 'SHOW_ALL', action) => { | |
switch (action.type) { | |
case 'SET_VISIBILITY_FILTER': | |
return action.filter; | |
default: | |
return state; | |
} | |
} | |
const todoApp = combineReducers({ | |
todos, | |
visibilityFilter | |
}); | |
const store = createStore(todos); | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id:0, | |
text: 'Learn Redux' | |
}); | |
*/</script></body> | |
</html> |
This file contains hidden or 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
/* jshint esnext: true */ | |
/* jshint asi: true */ | |
/* jshint laxcomma: true */ | |
/* | |
ES6: (state = [], action) => { ... } | |
ES5: function(state, action) { if (!state) state = []; ... } | |
Functions with a single expression using ES6 arrow functions don't need {}: | |
[1,2,3].map(elem => elem * 2) // returns [2,4,6] | |
The const keyword declares a constant. Reusing the same name will throw an error: | |
const foo = 'bar' | |
const foo = 'baz' // throws "SyntaxError: Identifier 'foo' has already been declared" | |
*/ | |
const { createStore, combineReducers } = Redux; | |
const extractId = (id) => parseInt(id.match(/\d+/g)[0]) | |
const sankeyChart = document.getElementById('sankey-chart') | |
, sankeyValue = document.getElementById('sankey-value') | |
, totalValue = document.getElementById('total-value') | |
const defaultYear = document.querySelector('#year span') | |
, setYear = document.querySelector('#year button') | |
//------------------------------------------------------------------------------ | |
var forecastId = 0; | |
const forecastModel = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_MODEL': | |
return state.map(e => { e.active = false; return e }).concat({ | |
id: forecastId++, | |
active: true, | |
defaultYear: action.defaultYear || state[0].defaultYear, | |
drivers: !state[0] ? action.drivers : | |
Object.assign({}, state[0].drivers, action.drivers || {}) | |
}) | |
case 'SELECT_MODEL': | |
return state.map(e => { | |
e.active = e.id === action.id ? true : false | |
return e | |
}) | |
case 'UPDATE_MODEL': | |
const modelIndex = state.findIndex(e => e.active) | |
return state.slice(0, modelIndex) | |
.concat([{ | |
id: state[modelIndex].id, | |
active: true, | |
defaultYear: action.defaultYear || | |
state[modelIndex].defaultYear, | |
drivers: Object.assign({}, state[0].drivers, action.drivers || {}) | |
}]) | |
.concat(state.slice(modelIndex + 1)) | |
case 'DELETE_MODEL': | |
return modelIndex === 0 ? state | |
: state.slice(0, modelIndex) | |
.concat(state.slice(modelIndex + 1)) | |
default: | |
return state | |
} | |
} | |
forecastStore = createStore(forecastModel) | |
// render the view | |
forecastStore.subscribe(() => { | |
const tabs = forecastStore.getState().map(e => { | |
return `<span id="model${e.id}" class="${e.active ? 'active' : ''}" onClick="selectModel(event)">` + | |
`model${e.id}` + | |
`</span>` | |
}).join() | |
document.getElementById('tabs').innerHTML = tabs | |
const activeModel = forecastStore.getState().find(e => e.active) | |
sankeyChart.value = activeModel.drivers.foo | |
defaultYear.innerHTML = activeModel.defaultYear | |
totalValue.innerHTML = activeModel.drivers.total() | |
if (activeModel.id === 0) | |
setYear.setAttribute('disabled', 'disabled') | |
else | |
setYear.removeAttribute('disabled') | |
//console.log(forecastStore.getState(), activeModel) | |
}) | |
// dispatch base model | |
forecastStore.dispatch({ | |
type: 'ADD_MODEL', | |
active: true, | |
defaultYear: 2016, | |
drivers: { | |
foo: 22, | |
total: function() { return this.foo * 3 } | |
} | |
}) | |
function selectModel(event) { | |
const modelId = extractId(event.target.id) | |
forecastStore.dispatch({ | |
type: 'SELECT_MODEL', | |
id: modelId | |
}) | |
console.log('foo' ) | |
} | |
const sankey = (state = sankeyChart.value, action) => { | |
switch (action.type) { | |
case 'SANKEY_DRAG': | |
return action.sankeyValue | |
default: | |
return state | |
} | |
} | |
const sankeyStore = createStore(sankey) | |
sankeyStore.subscribe(() => { | |
sankeyValue.innerHTML = sankeyStore.getState() | |
}) | |
sankeyStore.dispatch({ | |
type: 'SANKEY_DRAG', | |
sankeyValue: sankeyChart.value | |
}) | |
// sankey chart arm dragging | |
sankeyChart.addEventListener('input', (event) => { | |
sankeyStore.dispatch({ | |
type: 'SANKEY_DRAG', | |
sankeyValue: event.target.value | |
}) | |
}) | |
// sankey chart arm let go | |
sankeyChart.addEventListener('mouseup', (event) => { | |
if (forecastStore.getState().find(e => e.active).id === 0) { | |
forecastStore.dispatch({ | |
type: 'ADD_MODEL', | |
drivers: { | |
foo: parseInt(sankeyChart.value) | |
} | |
}) | |
} | |
else { | |
forecastStore.dispatch({ | |
type: 'UPDATE_MODEL', | |
drivers: { | |
foo: parseInt(sankeyChart.value) | |
} | |
}) | |
} | |
console.log('blur') | |
}) | |
/* | |
const todo = (state, action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
return state.id !== action.id ? state : { | |
...state, | |
completed: !state.completed | |
}; | |
default: | |
return state; | |
} | |
}; | |
const todos = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [ | |
...state, | |
{ | |
id: action.id, | |
text: action.text, | |
completed: false | |
} | |
]; | |
case 'TOGGLE_TODO': | |
return state.map(t => todo(t, action)); | |
default: | |
return state; | |
} | |
} | |
const visibilityFilter = (state = 'SHOW_ALL', action) => { | |
switch (action.type) { | |
case 'SET_VISIBILITY_FILTER': | |
return action.filter; | |
default: | |
return state; | |
} | |
} | |
const todoApp = combineReducers({ | |
todos, | |
visibilityFilter | |
}); | |
const store = createStore(todos); | |
store.dispatch({ | |
type: 'ADD_TODO', | |
id:0, | |
text: 'Learn Redux' | |
}); | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment