forked from ManuelDeLeon/viewmodel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhooks.coffee
More file actions
168 lines (147 loc) · 5.1 KB
/
hooks.coffee
File metadata and controls
168 lines (147 loc) · 5.1 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
getArgumentResult = (arg, data) ->
if arg instanceof Function
return arg(data)
return arg
((history) ->
pushState = history.pushState
replaceState = history.replaceState
history.pushState = (state, title, url) ->
if typeof history.onstatechange is 'function'
history.onstatechange state, title, url
pushState.apply history, arguments
history.replaceState = (state) ->
if typeof history.onstatechange is 'function'
history.onstatechange state, title, url
replaceState.apply history, arguments
return
) window.history
Blaze.Template.prototype.createViewModel = (data) ->
template = this
argCount = 0
vmName = null
vmObjects = []
for arg in template.viewmodelArgs
argCount++
argResult = getArgumentResult(arg, data)
if argCount is 1
if VmHelper.isString argResult
vmName = argResult
else
vmObjects.push argResult
else if argCount is template.viewmodelArgs.length
if not (VmHelper.isString(argResult) or argResult instanceof Array)
vmObjects.push argResult
else
vmObjects.push argResult
viewmodel = new ViewModel vmName, {}
for obj in vmObjects when obj
viewmodel.extend obj
viewmodel._vm_autoruns = (obj.autorun for obj in vmObjects when obj?.autorun)
viewmodel
Blaze.Template.prototype.viewmodel = ->
template = this
args = arguments
template.viewmodelArgs = args
argTotal = args.length
vmHelpers = []
lastArg = args[argTotal - 1]
if VmHelper.isString lastArg
vmHelpers.push lastArg
else if lastArg instanceof Array
for helper in lastArg
vmHelpers.push helper
for helperName in vmHelpers
do (helperName) ->
helper = {}
helper[helperName] = ->
Template.instance().viewmodel[helperName]()
template.helpers helper
created = false
template.onCreated ->
that = this
this.viewmodel = template.createViewModel(this.data)
if that.data
this.autorun ->
that.viewmodel.extend Template.currentData()
this.viewmodel.templateInstance = this;
this.viewmodel._vm_addParent this.viewmodel, this
if this.viewmodel.onCreated
this.viewmodel.onCreated this
if onUrl = this.viewmodel.onUrl
if not that.viewmodel._vm_hasId
if Meteor.isDev
console.log "Cannot save state on the URL for a view model without a name"
else
props = if _.isArray(onUrl) then onUrl else [onUrl]
tName = that.viewmodel._vm_id.substring("_vm_".length)
tName = encodeURI(tName)
tName = tName.split('.').join("%2E") if ~tName.indexOf(".")
# Update URL from view model
this.autorun (c) ->
url = window.location.href
for prop in props
if that.viewmodel[prop]
value = that.viewmodel[prop]() or ""
url = VmHelper.updateQueryString( tName + "." + encodeURI(prop), value.toString(), url)
else
if Meteor.isDev
console.log "View model '#{that.viewmodel._vm_id}' doesn't have property '#{prop}'"
window.history.pushState(null, null, url) if not c.firstRun and document.URL isnt url
# Update view model from URL
updateFromUrl = (state, title, url = document.URL) ->
for key, value of VmHelper.url(url).queryKey when ~key.indexOf(".")
[temp, property] = key.split(".")
property = decodeURI(property)
if property in props
if temp is tName
that.viewmodel[property] decodeURI(value)
window.onpopstate = window.history.onstatechange = updateFromUrl
updateFromUrl()
if not created
if this.viewmodel.blaze_helpers
helpers = this.viewmodel.blaze_helpers
template.helpers( if _.isFunction(helpers) then helpers() else helpers )
if this.viewmodel.blaze_events
events = this.viewmodel.blaze_events
template.events( if _.isFunction(events) then events() else events )
created = true
return
template.onRendered ->
that = this
if this.viewmodel._vm_autoruns?.length
for autorun in this.viewmodel._vm_autoruns
if _.isArray(autorun)
for ar in autorun
do (ar) ->
that.autorun (c) ->
ar.call(that.viewmodel, c)
else
do (autorun) ->
that.autorun (c) ->
autorun.call(that.viewmodel, c)
if this.viewmodel.beforeBind
this.viewmodel.beforeBind this
if this.viewmodel.onRendered
this.viewmodel.onRendered this
this.viewmodel.bind this
if this.viewmodel.afterBind
this.viewmodel.afterBind this
return
template.onDestroyed ->
if this.viewmodel.onDestroyed
this.viewmodel.onDestroyed this
this.viewmodel.dispose()
return
return
htmls = { }
Blaze.Template.prototype.elementBind = (selector, data) ->
name = this.viewName
html = null
if data
html = $("<div></div>").append($(Blaze.toHTMLWithData(this, data)))
else if htmls[name]
html = htmls[name]
else
html = $("<div></div>").append($(Blaze.toHTML(this)))
htmls[name] = html
ViewModel.parseBind(html.find(selector).data("bind"))