<!DOCTYPE html>
<html>
<head>
<link href="//cdn.jsdelivr.net/picnicss/4.1.1/picnic.min.css" rel="stylesheet">
<style>
li:empty {
list-style-type:none;
}
</style>
</head>
<body>
<h1>Hello Mag.JS - Redux!</h1>
<a target="_tab" href="https://github.com/magnumjs/mag.js">GitHub</a>
<hr/>
<div id="counter">
<div>
<button name="inc-odd">Increment Async Odd</button>
<button name="inc">Increment Async</button>
<button name="down">Decrease</button>
<button name="up">Increase</button>
<span></span>
</div>
<div>
<input>
<button name="add">Add</button>
<ul>
<li></li>
</ul>
</div>
</div>
<script src="//cdn.rawgit.com/MaxArt2501/object-observe/master/dist/object-observe.min.js"></script>
<script src="//rawgit.com/magnumjs/mag.js/master/dist/mag.0.21.2.min.js"></script>
<script src="//rawgit.com/magnumjs/mag.js/master/dist/mag.addons.0.21.min.js"></script>
<script src="//rawgit.com/magnumjs/mag.js/master/dist/mag-redux.0.21.min.js"></script>
<script src="mag-mod.js"></script>
<script src="mag-redux-mod.js"></script>
</body>
</html>
var Counter = {}
Counter.controller = function() {
this.input = ''
}
Counter.view = function(state, props) {
state.inc = {
_onClick: props.incrementAsync
}
state['inc-odd'] = {
_onClick: props.incrementIfOdd
}
state.li = props.todos || []
state.up = {
_onClick: props.increaseAction
}
state.down = {
_onClick: props.decreaseAction
}
state.add = {
_onClick: function() {
props.addTodo(state.input)
state.input = ''
}
}
//Combined reducers, no mapping
state.span = props.counter.count
//With mapping
// state.span = props.value
}
//Types:
var types = {
ADD_TODO: 'ADD_TODO',
DECREASE: 'DECREASE',
INCREASE: 'INCREASE'
}
// Action:
var actions1 = {
//Async:
incrementIfOdd: function() {
return function(dispatch, getState) {
var _getState = getState();
var counter = _getState.counter.count;
if (counter % 2 === 0) {
return;
}
dispatch(actions2.increaseAction());
};
},
//Async:
incrementAsync: function() {
return function(dispatch) {
setTimeout(function() {
// Yay! Can invoke sync or async actions with `dispatch`
dispatch(actions2.increaseAction());
}, 1000);
};
},
decreaseAction: {
type: types.DECREASE
},
increaseAction: {
type: types.INCREASE
},
addTodo: {
type: types.ADD_TODO,
text: ''
}
}
//Action: Alternative
var actions2 = {
addTodo: function(text) {
return {
type: types.ADD_TODO,
text: text
};
},
increaseAction: function() {
return {
type: types.INCREASE
};
}
}
// Reducer:
function counter(state, action) {
var count = (state || {}).count || 0;
switch (action.type) {
case types.INCREMENT_COUNTER:
return {
count: count + 1
}
case types.INCREASE:
return {
count: count + 1
};
case types.DECREASE:
return {
count: count - 1
};
default:
return state || 0;
}
}
// Reducer:
function todos(state, action) {
switch (action.type) {
case types.ADD_TODO:
console.log(action)
return state.concat([action.text]);
default:
return state || [];
}
}
// Map Redux state to component props
function mapStateToProps(state) {
return {
todos: state.todos,
value: state.counter.count
};
}
// Map Redux actions to component props
function mapDispatchToProps(dispatch) {
return {
increaseAction: function() {
dispatch(actions2.increaseAction())
},
addTodo: function(text) {
dispatch(actions2.addTodo(text))
}
};
}
//Middleware:
var logger = function logger(store) {
return function(next) {
return function(action) {
//console.log('dispatching', action);
var result = next(action);
//console.log('next state', store.getState());
return result;
};
};
};
//Options: combine reducers
var reducers = {
counter:counter, todos:todos
};
var middleware = []
//Overrides: use defaults no mapping
mapStateToProps = {}
middleware.push(logger)
//Use objects not functions and no mapping defaults
mapDispatchToProps = actions1
// Connected Component:
var App = mag.reduxConnect(mapStateToProps,
mapDispatchToProps, reducers, middleware
)('counter', Counter);
var modInstance = App({
anotherThing: true
})