This repository was archived by the owner on Nov 30, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathmarker-child-model.coffee
230 lines (197 loc) · 8.9 KB
/
marker-child-model.coffee
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
###global _:true,angular:true,google:true, RichMarker:true###
angular.module('uiGmapgoogle-maps.directives.api.models.child')
.factory 'uiGmapMarkerChildModel', [
'uiGmapModelKey', 'uiGmapGmapUtil',
'uiGmapLogger', 'uiGmapEventsHelper', 'uiGmapPropertyAction',
'uiGmapMarkerOptions', 'uiGmapIMarker', 'uiGmapMarkerManager', 'uiGmapPromise',
(ModelKey, GmapUtil, $log, EventsHelper, PropertyAction, MarkerOptions, IMarker, MarkerManager, uiGmapPromise) ->
class MarkerChildModel extends ModelKey
@include GmapUtil
@include EventsHelper
@include MarkerOptions
destroy = (child) ->
if child?.gObject?
child.removeEvents child.externalListeners
child.removeEvents child.internalListeners
if child?.gObject
child.gManager.remove child.gObject if child.removeFromManager
child.gObject.setMap null
child.gObject = null
constructor: (opts) ->
{
scope, @model, @keys, @gMap, @defaults = {},
@doClick, @gManager, @doDrawSelf = true,
@trackModel = true, @needRedraw = false
@isScopeModel = false
} = opts
#where @model is a reference to model in the controller scope
#clonedModel is a copy for comparison (see models-watcher)
@clonedModel = _.clone(@model,true) if @isScopeModel
@deferred = uiGmapPromise.defer()
_.each @keys, (v, k) =>
keyValue = @keys[k]
if keyValue? and not _.isFunction(keyValue) and _.isString(keyValue)
@[k + 'Key'] = keyValue
@idKey = @idKeyKey or 'id'
@id = @model[@idKey] if @model[@idKey]?
super(scope)
@scope.getGMarker = =>
@gObject
@firstTime = true
if @trackModel
@scope.model = @model
@scope.$watch 'model', (newValue, oldValue) =>
if (newValue != oldValue)
@handleModelChanges newValue, oldValue
, true
else
action = new PropertyAction (calledKey) =>
#being in a closure works , direct to setMyScope is not working (but should?)
calledKey = 'all' if _.isFunction calledKey
if not @firstTime
@setMyScope calledKey, scope
, false
_.each @keys, (v, k) ->
scope.$watch k, action.sic(k), true
#hiding destroy functionality as it should only be called via scope.$destroy()
@scope.$on '$destroy', =>
destroy @
# avoid double creation, but this might be needed for <marker>
# @setMyScope 'all', @model, undefined, true
@createMarker @model
$log.info @
destroy: (removeFromManager = true) =>
@removeFromManager = removeFromManager
@scope.$destroy()
handleModelChanges: (newValue, oldValue) =>
changes = @getChanges newValue, oldValue, IMarker.keys
if not @firstTime
ctr = 0
len = _.keys(changes).length
_.each changes, (v, k) =>
ctr += 1
doDraw = len == ctr
@setMyScope k, newValue, oldValue, false, true, doDraw
@needRedraw = true
updateModel: (model) =>
@clonedModel = _.clone(model,true) if @isScopeModel
@setMyScope 'all', model, @model
renderGMarker: (doDraw = true, validCb) ->
#doDraw is to only update the marker on the map when it is really ready
coords = @getProp('coords', @scope, @model)
if @gManager?.isSpiderfied?
isSpiderfied = @gManager.isSpiderfied()
if coords?
if !@validateCoords coords
$log.debug 'MarkerChild does not have coords yet. They may be defined later.'
return
validCb() if validCb?
@gManager.add @gObject if doDraw and @gObject
@gManager.markerSpiderfier.spiderListener(@gObject, window.event) if isSpiderfied
else
@gManager.remove @gObject if doDraw and @gObject
setMyScope: (thingThatChanged, model, oldModel = undefined, isInit = false, doDraw = true) =>
if not model?
model = @model
else
@model = model
if !@gObject
@setOptions @scope, doDraw
justCreated = true
switch thingThatChanged
when 'all'
_.each @keys, (v, k) =>
@setMyScope k, model, oldModel, isInit, doDraw
when 'icon'
@maybeSetScopeValue {gSetter: @setIcon, doDraw}
when 'coords'
@maybeSetScopeValue {gSetter: @setCoords, doDraw}
when 'options'
@createMarker(model, oldModel, isInit, doDraw) if !justCreated
createMarker: (model, oldModel = undefined, isInit = false, doDraw = true) =>
@maybeSetScopeValue {gSetter: @setOptions, doDraw}
@firstTime = false
maybeSetScopeValue: ({gSetter, doDraw = true}) =>
gSetter(@scope, doDraw) if gSetter?
@gManager.draw() if @doDrawSelf and doDraw
isNotValid: (scope, doCheckGmarker = true) =>
hasNoGmarker = unless doCheckGmarker then false else @gObject == undefined
hasIdenticalScopes = unless @trackModel then scope.$id != @scope.$id else false
hasIdenticalScopes or hasNoGmarker
setCoords: (scope, doDraw = true) =>
return if @isNotValid(scope) or !@gObject?
@renderGMarker doDraw, =>
newModelVal = @getProp 'coords', scope, @model
newGValue = @getCoords newModelVal
oldGValue = @gObject.getPosition()
if oldGValue? and newGValue?
return if newGValue.lng() == oldGValue.lng() and newGValue.lat() == oldGValue.lat()
@gObject.setPosition newGValue
@gObject.setVisible @validateCoords newModelVal
setIcon: (scope, doDraw = true) =>
return if @isNotValid(scope) or !@gObject?
@renderGMarker doDraw, =>
oldValue = @gObject.getIcon()
newValue = @getProp 'icon',scope, @model
return if oldValue == newValue
@gObject.setIcon newValue
coords = @getProp 'coords', scope, @model
@gObject.setPosition @getCoords coords
@gObject.setVisible @validateCoords coords
setOptions: (scope, doDraw = true) =>
return if @isNotValid scope, false
@renderGMarker doDraw, =>
coords = @getProp 'coords', scope, @model
icon = @getProp 'icon', scope, @model
_options = @getProp 'options', scope, @model
@opts = @createOptions coords, icon, _options
if @isLabel(@gObject) != @isLabel(@opts) and @gObject?
@gManager.remove @gObject
@gObject = undefined
#update existing options if it is the same type
if @gObject?
@gObject.setOptions @setLabelOptions @opts
unless @gObject
if @isLabel @opts
@gObject = new MarkerWithLabel @setLabelOptions @opts
else if @opts.content
@gObject = new RichMarker @opts
@gObject.getIcon = @gObject.getContent
@gObject.setIcon = @gObject.setContent
else
@gObject = new google.maps.Marker @opts
_.extend @gObject, model: @model
#hook external event handlers for events
@removeEvents @externalListeners if @externalListeners
@removeEvents @internalListeners if @internalListeners
@externalListeners = @setEvents @gObject, @scope, @model, ['dragend']
#must pass fake $evalAsync see events-helper
@internalListeners = @setEvents @gObject, {events: @internalEvents(), $evalAsync: -> }, @model
@gObject.key = @id if @id?
if @gObject and (@gObject.getMap() or @gManager.type != MarkerManager.type)
@deferred.resolve @gObject
else
return @deferred.reject 'gObject is null' unless @gObject
unless @gObject?.getMap() and @gManager.type == MarkerManager.type
$log.debug 'gObject has no map yet'
@deferred.resolve @gObject
if @model[@fitKey]
@gManager.fit()
setLabelOptions: (opts) =>
opts.labelAnchor = @getLabelPositionPoint opts.labelAnchor if opts.labelAnchor
opts
internalEvents: =>
dragend: (marker, eventName, model, mousearg) =>
modelToSet = if @trackModel then @scope.model else @model
newCoords = @setCoordsFromEvent @modelOrKey(modelToSet, @coordsKey), @gObject.getPosition()
modelToSet = @setVal model, @coordsKey, newCoords
#since we ignored dragend for scope above, if @scope.events has it then we should fire it
events = @scope.events
events.dragend(marker, eventName, modelToSet, mousearg) if events?.dragend?
@scope.$apply()
click: (marker, eventName, model, mousearg) =>
click = @getProp 'click', @scope, @model
if @doClick and angular.isFunction(click)
@scope.$evalAsync click marker, eventName, @model, mousearg
MarkerChildModel
]