Comparing version 0.4.4 to 0.5.0
@@ -48,3 +48,3 @@ 'use strict'; | ||
var App = function () { | ||
function App(elID) { | ||
function App(el) { | ||
var _this = this; | ||
@@ -57,3 +57,3 @@ | ||
this.el = document.getElementById(elID); | ||
this.el = typeof el === 'string' ? document.getElementById(el) : el; | ||
this.state = initialState; | ||
@@ -63,5 +63,2 @@ this.router = new _router3.default(this, options); | ||
var screens = this.SCREENS; | ||
for (var k in screens) { | ||
screens[k].setApp(this); | ||
} | ||
this._render = function (state) { | ||
@@ -107,8 +104,27 @@ return screens[_this.state.$screen].render(state); | ||
} | ||
}, { | ||
key: 'viewFromTemplate', | ||
value: function viewFromTemplate(templateFunc) { | ||
var initialState = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
return App.viewFromTemplate(templateFunc, this, initialState); | ||
} | ||
// shortcut to create views which don't need any handlers/helpers | ||
}, { | ||
key: 'ROUTES', | ||
get: function get() { | ||
return {}; | ||
} | ||
}, { | ||
key: 'SCREENS', | ||
get: function get() { | ||
throw 'SCREENS must be provided by subclass'; | ||
} | ||
}], [{ | ||
key: 'viewFromTemplate', | ||
value: function viewFromTemplate(templateFunc) { | ||
value: function viewFromTemplate(templateFunc, parent) { | ||
var initialState = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; | ||
return new (function (_View) { | ||
@@ -131,14 +147,4 @@ _inherits(_class, _View); | ||
return _class; | ||
}(_view2.default))(); | ||
}(_view2.default))(parent, initialState); | ||
} | ||
}, { | ||
key: 'ROUTES', | ||
get: function get() { | ||
return {}; | ||
} | ||
}, { | ||
key: 'SCREENS', | ||
get: function get() { | ||
throw 'SCREENS must be provided by subclass'; | ||
} | ||
}]); | ||
@@ -145,0 +151,0 @@ |
@@ -25,2 +25,5 @@ 'use strict'; | ||
// allow injecting window dep | ||
var routerWindow = this.window = options.window || window; | ||
this.app = app; | ||
@@ -46,5 +49,5 @@ var routeDefs = this.app.ROUTES; | ||
var navigateToHash = function navigateToHash() { | ||
return _this.navigate(window.location.hash); | ||
return _this.navigate(routerWindow.location.hash); | ||
}; | ||
window.addEventListener('popstate', function () { | ||
routerWindow.addEventListener('popstate', function () { | ||
return navigateToHash(); | ||
@@ -54,5 +57,5 @@ }); | ||
var historyMethod = options.historyMethod || 'pushState'; | ||
var origChangeState = window.history[historyMethod]; | ||
this.changeState = window.history[historyMethod] = function () { | ||
origChangeState.apply(window.history, arguments); | ||
var origChangeState = routerWindow.history[historyMethod]; | ||
this.changeState = routerWindow.history[historyMethod] = function () { | ||
origChangeState.apply(routerWindow.history, arguments); | ||
navigateToHash(); | ||
@@ -128,3 +131,3 @@ }; | ||
fragment = stripHash(fragment); | ||
if (fragment !== stripHash(window.location.hash)) { | ||
if (fragment !== stripHash(this.window.location.hash)) { | ||
this.changeState(null, null, '#' + fragment); | ||
@@ -131,0 +134,0 @@ } |
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -16,4 +18,2 @@ | ||
function View(parent) { | ||
var _this = this; | ||
var initialState = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
@@ -25,8 +25,11 @@ | ||
this.initialState = initialState; | ||
this.app = this.parent.app || this.parent; | ||
Object.assign(this.app.state, this.initialState); | ||
this._template = this.TEMPLATE; | ||
this._views = this.VIEWS; | ||
this._viewRenderers = Object.keys(this._views).reduce(function (renderers, vname) { | ||
var view = _this._views[vname]; | ||
return Object.assign({}, renderers, _defineProperty({}, vname, view.render.bind(view))); | ||
}, {}); | ||
this._viewRenderers = deepMapViews(this._views, function (view) { | ||
return view.render.bind(view); | ||
}); | ||
} | ||
@@ -44,12 +47,9 @@ | ||
} | ||
// shortcut to create views which don't need any handlers/helpers | ||
}, { | ||
key: 'setApp', | ||
value: function setApp(app) { | ||
var _this2 = this; | ||
this.app = app; | ||
Object.assign(app.state, this.initialState); | ||
Object.keys(this._views).forEach(function (v) { | ||
return _this2._views[v].setApp(app); | ||
}); | ||
key: 'viewFromTemplate', | ||
value: function viewFromTemplate(templateFunc) { | ||
return this.app.viewFromTemplate(templateFunc, this); | ||
} | ||
@@ -81,2 +81,16 @@ }, { | ||
exports.default = View; | ||
exports.default = View; | ||
function deepMapViews(views, func) { | ||
if (Array.isArray(views)) { | ||
return views.map(function (view) { | ||
return deepMapViews(view, func); | ||
}); | ||
} else if ((typeof views === 'undefined' ? 'undefined' : _typeof(views)) === 'object' && typeof views.render !== 'function') { | ||
return Object.keys(views).reduce(function (renderers, key) { | ||
return Object.assign({}, renderers, _defineProperty({}, key, deepMapViews(views[key], func))); | ||
}, {}); | ||
} | ||
return func(views); | ||
} |
@@ -13,4 +13,4 @@ import create from 'virtual-dom/create-element'; | ||
export default class App { | ||
constructor(elID, initialState={}, options={}) { | ||
this.el = document.getElementById(elID); | ||
constructor(el, initialState={}, options={}) { | ||
this.el = typeof el === 'string' ? document.getElementById(el) : el; | ||
this.state = initialState; | ||
@@ -20,5 +20,2 @@ this.router = new Router(this, options); | ||
const screens = this.SCREENS; | ||
for (let k in screens) { | ||
screens[k].setApp(this); | ||
} | ||
this._render = state => screens[this.state.$screen].render(state); | ||
@@ -63,4 +60,8 @@ } | ||
viewFromTemplate(templateFunc, initialState={}) { | ||
return App.viewFromTemplate(templateFunc, this, initialState); | ||
} | ||
// shortcut to create views which don't need any handlers/helpers | ||
viewFromTemplate(templateFunc) { | ||
static viewFromTemplate(templateFunc, parent, initialState={}) { | ||
return new (class extends View { | ||
@@ -70,4 +71,4 @@ get TEMPLATE() { | ||
} | ||
})(); | ||
})(parent, initialState); | ||
} | ||
} |
// just the necessary bits of Backbone router+history | ||
export default class Router { | ||
constructor(app, options={}) { | ||
// allow injecting window dep | ||
const routerWindow = this.window = options.window || window; | ||
this.app = app; | ||
@@ -25,9 +28,9 @@ const routeDefs = this.app.ROUTES; | ||
const navigateToHash = () => this.navigate(window.location.hash); | ||
window.addEventListener('popstate', () => navigateToHash()); | ||
const navigateToHash = () => this.navigate(routerWindow.location.hash); | ||
routerWindow.addEventListener('popstate', () => navigateToHash()); | ||
const historyMethod = options.historyMethod || 'pushState'; | ||
const origChangeState = window.history[historyMethod]; | ||
this.changeState = window.history[historyMethod] = function() { | ||
origChangeState.apply(window.history, arguments); | ||
const origChangeState = routerWindow.history[historyMethod]; | ||
this.changeState = routerWindow.history[historyMethod] = function() { | ||
origChangeState.apply(routerWindow.history, arguments); | ||
navigateToHash(); | ||
@@ -67,3 +70,3 @@ }; | ||
fragment = stripHash(fragment); | ||
if (fragment !== stripHash(window.location.hash)) { | ||
if (fragment !== stripHash(this.window.location.hash)) { | ||
this.changeState(null, null, `#${fragment}`); | ||
@@ -70,0 +73,0 @@ } |
@@ -5,8 +5,9 @@ export default class View { | ||
this.initialState = initialState; | ||
this.app = this.parent.app || this.parent; | ||
Object.assign(this.app.state, this.initialState); | ||
this._template = this.TEMPLATE; | ||
this._views = this.VIEWS; | ||
this._viewRenderers = Object.keys(this._views).reduce((renderers, vname) => { | ||
const view = this._views[vname]; | ||
return Object.assign({}, renderers, {[vname]: view.render.bind(view)}); | ||
}, {}); | ||
this._viewRenderers = deepMapViews(this._views, view => view.render.bind(view)); | ||
} | ||
@@ -41,7 +42,19 @@ | ||
setApp(app) { | ||
this.app = app; | ||
Object.assign(app.state, this.initialState); | ||
Object.keys(this._views).forEach(v => this._views[v].setApp(app)); | ||
// shortcut to create views which don't need any handlers/helpers | ||
viewFromTemplate(templateFunc) { | ||
return this.app.viewFromTemplate(templateFunc, this); | ||
} | ||
} | ||
function deepMapViews(views, func) { | ||
if (Array.isArray(views)) { | ||
return views.map(view => deepMapViews(view, func)); | ||
} else if (typeof views === 'object' && typeof views.render !== 'function') { | ||
return Object.keys(views).reduce((renderers, key) => { | ||
return Object.assign({}, renderers, { | ||
[key]: deepMapViews(views[key], func), | ||
}); | ||
}, {}); | ||
} | ||
return func(views); | ||
} |
{ | ||
"name": "panel", | ||
"version": "0.4.4", | ||
"version": "0.5.0", | ||
"description": "virtual-dom view management and routing", | ||
@@ -9,3 +9,4 @@ "main": "build/index.js", | ||
"prepublish": "npm run build", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "mocha --require babel-core/register test", | ||
"test-debug": "mocha debug --require babel-core/register test" | ||
}, | ||
@@ -30,4 +31,9 @@ "repository": { | ||
"babel-cli": "^6.6.5", | ||
"babel-preset-es2015": "^6.6.0" | ||
"babel-core": "^6.7.6", | ||
"babel-preset-es2015": "^6.6.0", | ||
"expect.js": "^0.3.1", | ||
"min-document": "^2.18.0", | ||
"mocha": "^2.4.5", | ||
"raf": "^3.2.0" | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
[![Build Status](https://travis-ci.org/mixpanel/panel.svg?branch=master)](https://travis-ci.org/mixpanel/panel) | ||
# panel | ||
@@ -11,3 +12,3 @@ | ||
get SCREENS() { | ||
return {counter: new CounterView()}; | ||
return {counter: new CounterView(this)}; | ||
} | ||
@@ -14,0 +15,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
32784
15
710
2
48
7