-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lupengyu
committed
Sep 28, 2015
1 parent
f5ebc4b
commit b9cfd2a
Showing
33 changed files
with
1,141 additions
and
935 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
node_modules | ||
coverage | ||
dep | ||
output |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
define('ei/ActionCreator', [ | ||
'exports', | ||
'./babelHelpers', | ||
'underscore' | ||
], function (exports) { | ||
var babelHelpers = require('./babelHelpers'); | ||
var u = require('underscore'); | ||
var ACTION_ATTR = 'EI_ACTION_TAG'; | ||
var ACTION_TAG = 'EI_ACTION'; | ||
function createFactory(type, factory) { | ||
function ActionCreator(payload) { | ||
var action = u.isFunction(factory) ? factory.apply(null, arguments) : {}; | ||
action.type = type; | ||
return action; | ||
} | ||
ActionCreator[ACTION_ATTR] = ACTION_TAG; | ||
ActionCreator.type = type; | ||
return ActionCreator; | ||
} | ||
exports.extend = function (type, factory) { | ||
if (!u.isString(type)) { | ||
throw new Error('Action Creator must have a type'); | ||
} | ||
return createFactory(type, factory); | ||
}; | ||
exports.is = function (action) { | ||
return action && action[ACTION_ATTR] === ACTION_TAG; | ||
}; | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
define('ei/App', [ | ||
'exports', | ||
'./babelHelpers', | ||
'es6-promise', | ||
'underscore', | ||
'./util/invariant', | ||
'./locator', | ||
'./events', | ||
'./Router', | ||
'./env', | ||
'./url' | ||
], function (exports) { | ||
var babelHelpers = require('./babelHelpers'); | ||
var Promise = require('es6-promise').Promise; | ||
var u = require('underscore'); | ||
var invariant = require('./util/invariant'); | ||
var locator = require('./locator'); | ||
var events = require('./events'); | ||
var Router = require('./Router'); | ||
var env = require('./env'); | ||
var url = require('./url'); | ||
function App(options) { | ||
invariant(options, 'App need options'); | ||
invariant(options.routes, 'App need routes'); | ||
u.extend(this, options); | ||
this.router = new Router(this.routes); | ||
} | ||
App.prototype.bootstrap = function (initialState) { | ||
invariant(env.isClient, 'app-should bootstrap on client only'); | ||
events.emit('app-bootstrap'); | ||
locator.start().on('redirect', u.bind(this.onLocatorRedirect, this)); | ||
var me = this; | ||
var request = url.parse(location.href); | ||
var route = this.route(request); | ||
return route ? me.loadPage(route.page).then(function (Page) { | ||
var page = me.page = new Page(initialState); | ||
page.render(document.getElementById(me.main)); | ||
events.emit('app-ready'); | ||
}) : Promise.reject({ status: 404 }); | ||
}; | ||
App.prototype.onLocatorRedirect = function (path, query) { | ||
var request = { | ||
path: path, | ||
query: query | ||
}; | ||
var me = this; | ||
return me.execute(request).then(function (result) { | ||
if (me.page) { | ||
me.page.dispose(); | ||
} | ||
var page = me.page = result.page; | ||
page.render(document.getElementById(me.main)); | ||
events.emit('app-page-switch-succeed'); | ||
}); | ||
}; | ||
App.prototype.execute = function (request) { | ||
events.emit('app-request'); | ||
var route = this.route(request); | ||
if (!route) { | ||
return Promise.reject({ status: 404 }); | ||
} | ||
var page; | ||
return this.loadPage(route.page).then(function (Page) { | ||
page = new Page(); | ||
return page.getInitialState(request); | ||
}).then(function (state) { | ||
if (env.isServer && request.xhr) { | ||
events.emit('app-response-in-json'); | ||
return { | ||
state: state, | ||
route: route | ||
}; | ||
} | ||
events.emit('app-response-in-html'); | ||
events.emit('app-page-bootstrap'); | ||
page.init(state); | ||
events.emit('app-page-bootstrap-succeed'); | ||
return { | ||
page: page, | ||
route: route | ||
}; | ||
})['catch'](function (error) { | ||
events.emit('app-execute-error', error); | ||
throw error; | ||
}); | ||
}; | ||
App.prototype.setBasePath = function (basePath) { | ||
this.basePath = basePath; | ||
return this; | ||
}; | ||
App.prototype.loadPage = function (page) { | ||
var pool = this.pool; | ||
if (pool && pool[page]) { | ||
events.emit('app-page-loaded'); | ||
return Promise.resolve(pool[page]); | ||
} | ||
return env.isServer ? this.resolveServerModule(page) : this.resolveClientModule(page); | ||
}; | ||
App.prototype.resolveServerModule = function (moduleId) { | ||
events.emit('app-load-page-on-server', moduleId); | ||
var basePath = this.basePath; | ||
invariant(basePath, 'ei need a basePath to resolve your page'); | ||
var path = basePath + '/' + moduleId; | ||
var Page = require(path); | ||
var pool = this.pool; | ||
if (!pool) { | ||
pool = this.pool = {}; | ||
} | ||
pool[moduleId] = Page; | ||
return Promise.resolve(Page); | ||
}; | ||
App.prototype.resolveClientModule = function (moduleId) { | ||
events.emit('app-load-page-on-client'); | ||
return new Promise(function (resolve, reject) { | ||
window.require([moduleId], function (Page) { | ||
resolve(Page); | ||
}); | ||
}); | ||
}; | ||
App.prototype.route = function (request) { | ||
events.emit('app-route'); | ||
var config = this.router.route(request); | ||
if (config) { | ||
events.emit('app-route-succeed'); | ||
} else { | ||
events.emit('app-route-failed'); | ||
} | ||
return config; | ||
}; | ||
module.exports = App; | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
define('ei/Container', [ | ||
'exports', | ||
'./babelHelpers', | ||
'underscore' | ||
], function (exports) { | ||
var babelHelpers = require('./babelHelpers'); | ||
var u = require('underscore'); | ||
var Container = function Container() { | ||
this.boundCallbacks = {}; | ||
this.singletonCallbacks = {}; | ||
this.instantiatedSingletons = {}; | ||
this.registeredObjects = {}; | ||
}; | ||
Container.prototype.make = function (name) { | ||
if (this.registeredObjects[name]) { | ||
return this.registeredObjects[name]; | ||
} | ||
var args = u.toArray(arguments).slice(1); | ||
if (this.singletonCallbacks[name]) { | ||
var instances = this.instantiatedSingletons; | ||
var instance = instances[name]; | ||
if (!instance) { | ||
instance = instances[name] = this.singletonCallbacks[name].apply(this, args); | ||
} | ||
return instance; | ||
} | ||
var boundCallback = this.boundCallbacks[name]; | ||
return boundCallback ? boundCallback.apply(this, args) : null; | ||
}; | ||
Container.prototype.bind = function (name, factory) { | ||
this.boundCallbacks[name] = factory; | ||
return this; | ||
}; | ||
Container.prototype.singleton = function (name, factory) { | ||
this.singletonCallbacks[name] = factory; | ||
return this; | ||
}; | ||
Container.prototype.register = function (name, object) { | ||
this.registeredObjects[name] = object; | ||
return this; | ||
}; | ||
module.exports = Container; | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
define('ei/Context', [ | ||
'exports', | ||
'./babelHelpers', | ||
'underscore', | ||
'./util/composeMiddleware', | ||
'./util/invariant' | ||
], function (exports) { | ||
var babelHelpers = require('./babelHelpers'); | ||
var u = require('underscore'); | ||
var composeMiddleware = require('./util/composeMiddleware'); | ||
var invariant = require('./util/invariant'); | ||
function Context(initialState, reducer, middlewares) { | ||
invariant(u.isFunction(reducer), 'Context need a reducer'); | ||
this.reducer = reducer; | ||
this.store = initialState == null ? {} : initialState; | ||
this.dispatch = composeMiddleware(this, middlewares); | ||
this.getState = u.bind(this.getState, this); | ||
this.listeners = []; | ||
} | ||
Context.prototype.reduce = function (state, action) { | ||
return this.reducer(state, action); | ||
}; | ||
Context.prototype.getState = function () { | ||
return this.store; | ||
}; | ||
Context.prototype.setState = function (store) { | ||
this.store = store; | ||
return this; | ||
}; | ||
Context.prototype.dispatch = function (action) { | ||
if (u.isFunction(action)) { | ||
return action(this.dispatch, this.getState); | ||
} | ||
var nextState = this.reduce(this.store, action); | ||
this.setState(nextState); | ||
for (var listeners = this.listeners.slice(), i = 0, len = listeners.length; i < len; ++i) { | ||
listeners[i](); | ||
} | ||
return action; | ||
}; | ||
Context.prototype.addChangeListener = function (handler) { | ||
this.listeners.push(handler); | ||
return this; | ||
}, Context.prototype.removeChangeListener = function (handler) { | ||
for (var listeners = this.listeners, i = listeners.length - 1; i >= 0; --i) { | ||
if (listeners[i] === handler) { | ||
listeners.splice(i, 1); | ||
return this; | ||
} | ||
} | ||
return this; | ||
}; | ||
module.exports = Context; | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
define('ei/Emitter', [ | ||
'exports', | ||
'./babelHelpers', | ||
'underscore' | ||
], function (exports) { | ||
var babelHelpers = require('./babelHelpers'); | ||
var EMITTER_LISTENER_POOL_ATTR = '__listeners__'; | ||
var EMITTER_CURRENT_EVENT_ATTR = '__event__'; | ||
var u = require('underscore'); | ||
function Emitter() { | ||
} | ||
var mixins = { | ||
on: function on(name, handler) { | ||
var pool = this[EMITTER_LISTENER_POOL_ATTR]; | ||
if (!pool) { | ||
pool = this[EMITTER_LISTENER_POOL_ATTR] = {}; | ||
} | ||
var listeners = pool[name]; | ||
if (!listeners) { | ||
listeners = pool[name] = []; | ||
} | ||
listeners.push(handler); | ||
return this; | ||
}, | ||
off: function off(name, handler) { | ||
var pool = this[EMITTER_LISTENER_POOL_ATTR]; | ||
if (!pool) { | ||
return this; | ||
} | ||
if (!name) { | ||
return this.destroyEvents(); | ||
} | ||
var listeners = pool[name]; | ||
if (!listeners || !listeners.length) { | ||
return this; | ||
} | ||
if (!handler) { | ||
listeners.length = 0; | ||
pool[name] = []; | ||
return this; | ||
} | ||
for (var i = listeners.length - 1; i >= 0; --i) { | ||
if (listeners[i] === handler) { | ||
listeners.splice(i, 1); | ||
return this; | ||
} | ||
} | ||
return this; | ||
}, | ||
once: function once(name, handler) { | ||
var me = this; | ||
var onceHandler = function onceHandler() { | ||
me.off(name, onceHandler); | ||
return handler.apply(me, arguments); | ||
}; | ||
me.on(name, onceHandler); | ||
return this; | ||
}, | ||
emit: function emit(name) { | ||
var pool = this[EMITTER_LISTENER_POOL_ATTR]; | ||
if (!pool) { | ||
return this; | ||
} | ||
var listeners = [].concat(pool[name] || [], pool['*'] || []); | ||
if (!listeners.length) { | ||
return this; | ||
} | ||
this[EMITTER_CURRENT_EVENT_ATTR] = name; | ||
for (var i = 0, len = listeners.length; i < len; ++i) { | ||
listeners[i].apply(this, u.toArray(arguments).slice(1)); | ||
} | ||
this[EMITTER_CURRENT_EVENT_ATTR] = null; | ||
return this; | ||
}, | ||
getCurrentEvent: function getCurrentEvent() { | ||
return this[EMITTER_CURRENT_EVENT_ATTR]; | ||
}, | ||
destroyEvents: function destroyEvents() { | ||
var pool = this[EMITTER_LISTENER_POOL_ATTR]; | ||
if (pool) { | ||
for (var type in pool) { | ||
if (pool[type]) { | ||
pool[type].length = 0; | ||
pool[type] = null; | ||
} | ||
} | ||
this[EMITTER_LISTENER_POOL_ATTR] = null; | ||
} | ||
return this; | ||
} | ||
}; | ||
u.extend(Emitter.prototype, mixins); | ||
Emitter.enable = function (target) { | ||
if (u.isFunction(target)) { | ||
target = target.prototype; | ||
} | ||
return u.extend(target, mixins); | ||
}; | ||
module.exports = Emitter; | ||
}); |
Oops, something went wrong.