-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrender.js
127 lines (110 loc) · 3.44 KB
/
render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const makeStateIsActiveDecorator = require(`./active-decorator`)
const UPDATE_ROUTE_KEY = `update_route`
function wrapWackyPromise(promise, cb) {
promise.then((...args) => {
cb(null, ...args)
}, cb)
}
module.exports = function RactiveStateRouter(Ractive, ractiveOptions, options) {
function copyIfAppropriate(value) {
if (options && options.deepCopyDataOnSet) {
return copy(value)
} else {
return value
}
}
return function makeRenderer(stateRouter) {
const ExtendedRactive = Ractive.extend(ractiveOptions || {})
const extendedData = ExtendedRactive.defaults.data
const ractiveData = Ractive.defaults.data
const globalData = {}
globalData[UPDATE_ROUTE_KEY] = {}
const globalRactive = new Ractive({
data: globalData,
})
stateRouter.on(`stateChangeEnd`, () => {
globalRactive.update(UPDATE_ROUTE_KEY)
})
extendedData.makePath = ractiveData.makePath = function makePath() {
globalRactive.get(UPDATE_ROUTE_KEY)
return stateRouter.makePath.apply(null, arguments)
}
extendedData.active = ractiveData.active = function active(stateName, options, className = `active`) {
globalRactive.get(UPDATE_ROUTE_KEY)
return stateRouter.stateIsActive(stateName, options) ? className : ``
}
const activeDecorator = makeStateIsActiveDecorator(stateRouter)
return {
render: function render(context, cb) {
const element = context.element
const inputTemplate = context.template
const defaultDecorators = {
active: activeDecorator,
}
function getData() {
const copyOfContent = copyIfAppropriate(context.content)
return isTemplate(inputTemplate) ? copyOfContent : Object.assign({}, inputTemplate.data, copyOfContent)
}
function getDecorators() {
return isTemplate(inputTemplate) ? defaultDecorators : Object.assign(defaultDecorators, inputTemplate.decorators)
}
function getOptions() {
const bareOptions = isTemplate(inputTemplate) ? { template: inputTemplate } : inputTemplate
return Object.assign({}, bareOptions, {
decorators: getDecorators(),
data: getData(),
el: element,
})
}
try {
const ractive = new ExtendedRactive(getOptions())
cb(null, ractive)
} catch (e) {
cb(e)
}
},
reset: function reset(context, cb) {
const ractive = context.domApi
ractive.off()
if(ractive._observers && Array.isArray(ractive._observers)) {
ractive._observers.forEach(o => o.cancel())
}
wrapWackyPromise(ractive.reset(copyIfAppropriate(context.content)), cb)
},
destroy: function destroy(ractive, cb) {
wrapWackyPromise(ractive.teardown(), cb)
},
getChildElement: function getChildElement(ractive, cb) {
try {
const child = ractive.find(`ui-view`)
cb(null, child)
} catch (e) {
cb(e)
}
},
}
}
}
function copy(value) {
if (Array.isArray(value)) {
return value.map(copy)
} else if (object(value)) {
const target = {}
Object.keys(value).forEach(key => {
target[key] = copy(value[key])
})
return target
} else {
return value
}
}
function object(o) {
return o && typeof o === `object`
}
function isTemplate(inputTemplate) {
return typeof inputTemplate === `string` || isRactiveTemplateObject(inputTemplate)
}
function isRactiveTemplateObject(template) {
// Based on https://github.com/ractivejs/ractive/blob/b1c9e1e5c22daac3210ee7db0f511065b31aac3c/src/Ractive/config/custom/template/template.js#L113-L116
return template && typeof template.v === `number`
}