-
Notifications
You must be signed in to change notification settings - Fork 47
/
gmPolylines.js
200 lines (188 loc) · 6.69 KB
/
gmPolylines.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
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
/**
* @ngdoc directive
* @name angulargm.directive:gmPolylines
* @element ANY
*
* @description
* A directive for adding polylines to a `gmMap`. You may have multiple per `gmMap`.
*
* To use, you specify an array of custom objects and tell the directive how to
* extract location data from them. A polyline will be created for each of your
* objects. If you assign a new array to your scope variable or change the
* array's length, the polylines will also update. The one case where
* `gmPolylines` can not automatically detect changes to your objects is when
* you mutate objects in the array. To inform the directive of such changes,
* see the `gmPolylinesUpdate` event below.
*
* Only the `gm-objects`, `gm-id` and `gm-path` attributes are required.
*
* @param {expression} gm-objects an array of objects in the current scope.
* These can be any objects you wish to attach to polylines, the only requirement
* is that they have a uniform method of accessing an id and a path.
*
* @param {expression} gm-path an angular expression that given an object from
* `gm-objects`, evaluates to an array of google.maps.LatLngLiteral objects.
* Your object can be accessed through the variable `object`. For example, if
* your controller has
* ```js
* ...
* $scope.myObjects = [
* { id: 0, path: [ { lat: 5, lng: 5}, {lat: 4, lng: 4} ]},
* { id: 1, path: [ { lat: 6, lng: 6}, {lat: 7, lng: 7} ]}
* ]
* ...
* ```
* then in the `gm-polylines` directive you would put
* ```js
* ...
* gm-objects="myObjects"
* gm-get-path="object.path"
* ...
* ```
*
* @param {expression} gm-polyline-options an angular expression that given
* an object from `gm-objects`, evaluates to a
* [google.maps.PolylineOptions](https://developers.google.com/maps/documentation/javascript/reference#PolylineOptions)
* object. Your object can be accessed through the variable `object`. If
* unspecified, google maps api defaults will be used.
*
* @param {expression} gm-events a variable in the current scope that is used to
* simulate events on polylines. Setting this variable to an object of the form
* ```js
* [
* {
* event: 'click',
* ids: [id1, ...]
* },
* ...
* ]
* ```
* will generate the named events on the polylines with the given ids, if a
* polyline with each id exists. Note: when setting the `gm-events` variable, you
* must set it to a new object for the changes to be detected. Code like
* ```js
* myEvents[0]["ids"] = [0]
* ```
* will not work.
*
*
* @param {expression} gm-on-*event* an angular expression which evaluates to
* an event handler. This handler will be attached to each polyline's \*event\*
* event. The variables 'object' and 'polyline' evaluate to your object and the
* [google.maps.Polyline](https://developers.google.com/maps/documentation/javascript/reference#Polyline),
* respectively. For example:
* ```html
* gm-on-click="myClickFn(object, polyline)"
* ```
* will call your `myClickFn` whenever a polyline is clicked. You may have
* multiple `gm-on-*event*` handlers, but only one for each type of event.
* For events that have an underscore in their name, such as
* 'position_changed', write it as 'gm-on-position-changed'.
*/
/**
* @ngdoc event
* @name angulargm.directive:gmPolylines#gmPolylinesUpdate
* @eventOf angulargm.directive:gmPolylines
* @eventType listen on current gmPolylines scope
*
* @description Manually tell the `gmPolylines` directive to update the polylines.
* This is useful to tell the directive when an object from `gm-objects` is
* mutated--`gmPolylines` can not pick up on such changes automatically.
*
* @param {string} objects Not required. The name of the scope variable which
* holds the objects to update polylines for, i.e. what you set `gm-objects` to.
* It is useful because there may be multiple instances of the `gmPolylines`
* directive. If not specified, all instances of `gmPolylines` which are child
* scopes will update their polylines.
*
* @example
* ```js
* $scope.$broadcast('gmPolylinesUpdate', 'myObjects');
* ```
*/
/**
* @ngdoc event
* @name angulargm.directive:gmPolylines#gmPolylinesRedraw
* @eventOf angulargm.directive:gmPolylines
* @eventType listen on current gmPolylines scope
*
* @description Force the gmPolylines directive to clear and redraw all polylines.
*
* @param {string} objects Not required. The name of the scope variable which
* holds the objects to redraw polylines for, i.e. what you set `gm-objects` to.
* It is useful because there may be multiple instances of the `gmPolylines`
* directive. If not specified, all instances of gmPolylines which are child
* scopes will redraw their polylines.
*
* @example
* ```js
* $scope.$broadcast('gmPolylinesRedraw', 'myObjects');
* ```
*/
/**
* @ngdoc event
* @name angulargm.directive:gmPolylines#gmPolylinesUpdated
* @eventOf angulargm.directive:gmPolylines
* @eventType emit on current gmPolylines scope
*
* @description Emitted when polylines are updated.
*
* @param {string} objects the name of the scope variable which holds the
* objects the gmPolylines directive was constructed with. This is what
* `gm-objects` was set to.
*
* @example
* ```js
* $scope.$on('gmPolylinesUpdated', function(event, objects) {
* if (objects === 'myObjects') {
* ...
* }
* });
* ```
*/
(function () {
'use strict';
angular.module('AngularGM').
directive('gmPolylines', ['$parse', '$compile', '$timeout', '$log', 'angulargmUtils', 'angulargmShape',
function ($parse, $compile, $timeout, $log, angulargmUtils, angulargmShape) {
/** aliases */
var validateLatLng = angulargmUtils.validateLatLng;
function link(scope, element, attrs, controller) {
if (!('gmPath' in attrs)) {
throw 'gmPath attribute required';
}
var polylineOptions = function(object) {
var lineLatLngs = scope.gmPath({object: object});
var path = [];
angular.forEach(lineLatLngs, function(latlng) {
var position = validateLatLng(latlng);
if (position == null) {
$log.warn('Unable to generate lat/lng from ', latlng);
return;
}
path.push(position);
});
var polylineOptions = scope.gmPolylineOptions({object: object});
var options = {};
angular.extend(options, polylineOptions, {path: path});
return options;
};
angulargmShape.createShapeDirective(
'polyline', scope, attrs, controller, polylineOptions
);
}
return {
restrict: 'AE',
priority: 100,
scope: {
gmObjects: '&',
gmId: '&',
gmPath: '&',
gmPolylineOptions: '&',
gmEvents: '&'
},
require: '^gmMap',
link: link
};
}]);
})();