Skip to content

Commit c66f7cf

Browse files
author
Allen Kim
committed
issue allenhwkim#333, added two-way binding for custom-marker directive
1 parent e1127bc commit c66f7cf

File tree

4 files changed

+207
-59
lines changed

4 files changed

+207
-59
lines changed

directives/custom-marker.js

Lines changed: 76 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,15 @@
2626
*/
2727
(function() {
2828
'use strict';
29-
var parser, $timeout;
30-
31-
var cAbortEvent = function (e) {
32-
e.preventDefault && e.preventDefault();
33-
e.cancelBubble = true;
34-
e.stopPropagation && e.stopPropagation();
35-
};
29+
var parser, $timeout, $compile;
3630

3731
var CustomMarker = function(options) {
3832
options = options || {};
3933

4034
this.el = document.createElement('div');
4135
this.el.style.display = 'inline-block';
4236
this.visible = true;
43-
for (var key in options) {
37+
for (var key in options) { /* jshint ignore:line */
4438
this[key] = options[key];
4539
}
4640
};
@@ -49,13 +43,16 @@
4943

5044
CustomMarker.prototype = new google.maps.OverlayView();
5145

52-
CustomMarker.prototype.setContent = function(html) {
53-
this.el.innerHTML = this.content = html;
46+
CustomMarker.prototype.setContent = function(html, scope) {
47+
this.el.innerHTML = html;
5448
this.el.style.position = 'absolute';
49+
if (scope) {
50+
$compile(angular.element(this.el).contents())(scope);
51+
}
5552
};
5653

5754
CustomMarker.prototype.setPosition = function(position) {
58-
position && (this.position = position);
55+
position && (this.position = position); /* jshint ignore:line */
5956
if (this.getProjection() && typeof this.position.lng == 'function') {
6057
var posPixel = this.getProjection().fromLatLngToDivPixel(this.position);
6158
var x = Math.round(posPixel.x - (this.el.offsetWidth/2));
@@ -66,7 +63,7 @@
6663
};
6764

6865
CustomMarker.prototype.setZIndex = function(zIndex) {
69-
zIndex && (this.zIndex = zIndex);
66+
zIndex && (this.zIndex = zIndex); /* jshint ignore:line */
7067
this.el.style.zIndex = this.zIndex;
7168
};
7269

@@ -77,14 +74,14 @@
7774

7875
CustomMarker.prototype.addClass = function(className) {
7976
var classNames = this.el.className.trim().split(' ');
80-
(classNames.indexOf(className) == -1) && classNames.push(className);
77+
(classNames.indexOf(className) == -1) && classNames.push(className); /* jshint ignore:line */
8178
this.el.className = classNames.join(' ');
8279
};
8380

8481
CustomMarker.prototype.removeClass = function(className) {
8582
var classNames = this.el.className.split(' ');
8683
var index = classNames.indexOf(className);
87-
(index > -1) && classNames.splice(index, 1);
84+
(index > -1) && classNames.splice(index, 1); /* jshint ignore:line */
8885
this.el.className = classNames.join(' ');
8986
};
9087

@@ -104,60 +101,83 @@
104101
};
105102
};
106103

107-
var customMarkerDirective = function(Attr2Options, _$timeout_) {
104+
var linkFunc = function(orgHtml, varsToWatch) {
105+
//console.log('orgHtml', orgHtml, 'varsToWatch', varsToWatch);
106+
107+
return function(scope, element, attrs, mapController) {
108+
109+
var orgAttrs = parser.orgAttributes(element);
110+
var filtered = parser.filter(attrs);
111+
var options = parser.getOptions(filtered, scope);
112+
var events = parser.getEvents(scope, filtered);
113+
114+
/**
115+
* build a custom marker element
116+
*/
117+
var removedEl = element[0].parentElement.removeChild(element[0]);
118+
console.log("custom-marker options", options);
119+
var customMarker = new CustomMarker(options);
120+
121+
$timeout(function() { //apply contents, class, and location after it is compiled
122+
scope.$watch('[' + varsToWatch.join(',') + ']', function(val) {
123+
customMarker.setContent(orgHtml, scope);
124+
});
125+
126+
customMarker.setContent(removedEl.innerHTML, scope);
127+
var classNames = removedEl.firstElementChild.className;
128+
customMarker.addClass('custom-marker');
129+
customMarker.addClass(classNames);
130+
console.log('customMarker', customMarker);
131+
132+
if (!(options.position instanceof google.maps.LatLng)) {
133+
mapController.getGeoLocation(options.position).then(
134+
function(latlng) {
135+
customMarker.setPosition(latlng);
136+
}
137+
);
138+
}
139+
});
140+
141+
console.log("custom-marker events", "events");
142+
for (var eventName in events) { /* jshint ignore:line */
143+
google.maps.event.addDomListener(
144+
customMarker.el, eventName, events[eventName]);
145+
}
146+
mapController.addObject('customMarkers', customMarker);
147+
148+
element.bind('$destroy', function() {
149+
//Is it required to remove event listeners when DOM is removed?
150+
mapController.deleteObject('customMarkers', customMarker);
151+
});
152+
153+
}; // linkFunc
154+
};
155+
156+
var customMarkerDirective = function(Attr2Options, _$timeout_, _$compile_) {
108157
parser = Attr2Options;
109158
$timeout = _$timeout_;
159+
$compile = _$compile_;
110160
setCustomMarker();
111161

112162
return {
113163
restrict: 'E',
114164
require: '^map',
115-
link: function(scope, element, attrs, mapController) {
116-
117-
var orgAttrs = parser.orgAttributes(element);
118-
var filtered = parser.filter(attrs);
119-
var options = parser.getOptions(filtered, scope);
120-
var events = parser.getEvents(scope, filtered);
121-
122-
/**
123-
* build a custom marker element
124-
*/
125-
var removedEl = element[0].parentElement.removeChild(element[0]);
126-
console.log("custom-marker options", options);
127-
var customMarker = new CustomMarker(options);
128-
129-
$timeout(function() { //apply contents, class, and location after it is compiled
130-
customMarker.setContent(removedEl.innerHTML);
131-
var classNames = removedEl.firstElementChild.className;
132-
customMarker.addClass('custom-marker');
133-
customMarker.addClass(classNames);
134-
console.log('customMarker', customMarker);
135-
136-
if (!(options.position instanceof google.maps.LatLng)) {
137-
mapController.getGeoLocation(options.position).then(
138-
function(latlng) {
139-
customMarker.setPosition(latlng);
140-
}
141-
);
165+
compile: function(element) {
166+
var orgHtml = element.html();
167+
var matches = orgHtml.match(/{{([^}]+)}}/g);
168+
var varsToWatch = [];
169+
(matches || []).forEach(function(match) { //filter out that contains '::', 'this.'
170+
var toWatch = match.replace('{{','').replace('}}','');
171+
if (match.indexOf('::') == -1 && match.indexOf('this.') == -1 && varsToWatch.indexOf(toWatch) == -1) {
172+
varsToWatch.push(match.replace('{{','').replace('}}',''));
142173
}
143174
});
144175

145-
console.log("custom-marker events", "events");
146-
for (var eventName in events) {
147-
google.maps.event.addDomListener(
148-
customMarker.el, eventName, events[eventName]);
149-
}
150-
mapController.addObject('customMarkers', customMarker);
151-
152-
element.bind('$destroy', function() {
153-
//Is it required to remove event listeners when DOM is removed?
154-
mapController.deleteObject('customMarkers', customMarker);
155-
});
156-
157-
} //link
176+
return linkFunc(orgHtml, varsToWatch);
177+
}
158178
}; // return
159179
};// function
160-
customMarkerDirective.$inject = ['Attr2Options', '$timeout'];
180+
customMarkerDirective.$inject = ['Attr2Options', '$timeout', '$compile'];
161181

162182
angular.module('ngMap').directive('customMarker', customMarkerDirective);
163183
})();
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<!doctype html>
2+
<html ng-app="ngMap">
3+
<head>
4+
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
5+
<script src="lib/angular.js"></script>
6+
<!--
7+
<script src="../build/scripts/ng-map.min.js"></script>
8+
-->
9+
<script src="../app.js"></script>
10+
<script src="../directives/map_controller.js"></script>
11+
<script src="../directives/map.js"></script>
12+
<script src="../directives/marker.js"></script>
13+
<script src="../directives/custom-marker.js"></script>
14+
<script src="../services/geo_coder.js"></script>
15+
<script src="../services/navigator_geolocation.js"></script>
16+
<script src="../services/attr2_options.js"></script>
17+
<style>
18+
.custom-marker.my1 {
19+
font-size: 1.5em;
20+
padding: 10px;
21+
background: #fff;
22+
-webkit-border-radius: 4px;
23+
-moz-border-radius: 4px;
24+
border-radius: 4px;
25+
border: #7F7F7F solid 1px;
26+
}
27+
28+
.custom-marker.my1:after {
29+
content: '';
30+
position: absolute;
31+
border-style: solid;
32+
border-width: 7px 6px 0;
33+
border-color: #fff transparent;
34+
display: block;
35+
width: 0;
36+
z-index: 1;
37+
margin-left: -6px;
38+
bottom: -6px;
39+
left: 50%;
40+
}
41+
42+
.custom-marker.my1:before {
43+
content: '';
44+
position: absolute;
45+
border-style: solid;
46+
border-width: 7px 6px 0;
47+
border-color: #7F7F7F transparent;
48+
display: block;
49+
width: 0;
50+
z-index: 0;
51+
margin-left: -6px;
52+
bottom: -7px;
53+
left: 50%;
54+
}
55+
56+
.custom-marker.my2 {
57+
font-size: 1.5em;
58+
padding: 10px;
59+
background: #fff;
60+
-webkit-border-radius: 4px;
61+
-moz-border-radius: 4px;
62+
border-radius: 4px;
63+
border: #7F7F7F solid 1px;
64+
background: red;
65+
}
66+
67+
.custom-marker.my2:after {
68+
content: '';
69+
position: absolute;
70+
border-style: solid;
71+
border-width: 7px 6px 0;
72+
border-color: red transparent;
73+
display: block;
74+
width: 0;
75+
z-index: 1;
76+
margin-left: -6px;
77+
bottom: -6px;
78+
left: 50%;
79+
}
80+
81+
.custom-marker.my2:before {
82+
content: '';
83+
position: absolute;
84+
border-style: solid;
85+
border-width: 7px 6px 0;
86+
border-color: #7F7F7F transparent;
87+
display: block;
88+
width: 0;
89+
z-index: 0;
90+
margin-left: -6px;
91+
bottom: -7px;
92+
left: 50%;
93+
}
94+
</style>
95+
<script>
96+
angular.module('ngMap').run(function($rootScope) {
97+
$rootScope.mouseover = function() {
98+
console.log('mouseover', this);
99+
this.style.backgroundColor = 'grey';
100+
};
101+
$rootScope.mouseout = function() {
102+
this.style.backgroundColor = 'white';
103+
};
104+
$rootScope.click = function() {console.log('click')};
105+
$rootScope.customMarkers = [
106+
{address: "1600 pennsylvania ave, washington DC", "class": "my1"},
107+
{address: "600 pennsylvania ave, washington DC", "class": "my2"},
108+
];
109+
$rootScope.world = "World";
110+
});
111+
</script>
112+
</head>
113+
<body>
114+
<map zoom="13" center="1600 pennsylvania ave, washington DC">
115+
<custom-marker ng-repeat="cm in customMarkers" position="{{cm.address}}"
116+
on-mouseover="mouseover()" on-mouseout="mouseout()"
117+
on-click="click()">
118+
<div class="{{cm.class}}">
119+
<div> Custom Marker {{cm.class}}</div>
120+
<div> Hello {{world}}</div>
121+
</div>
122+
</custom-marker>
123+
</map>
124+
<br/>
125+
Enter your name : <input ng-model="world" />
126+
</body>
127+
</html>
128+

testapp/custom-marker.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
var i=0, interval, chats = document.querySelectorAll('#chats li');
2222
var talk = function(){
2323
var el = chats[i];
24-
console.log(i, chats.length, el, $scope.map.customMarkers);
2524
$scope.map.customMarkers.usa.setVisible(false);
2625
$scope.map.customMarkers.can.setVisible(false);
2726
$scope.map.customMarkers[el.className].setContent(el.innerHTML);

testapp/map-lazy-load.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html ng-app="myapp">
33
<head>
44
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
5-
<script src="../build/scripts/ng-map.min.js"></script>
5+
<script src="../build/scripts/ng-map.debug.js"></script>
66
<!--
77
<script src="../app.js"></script>
88
<script src="../directives/map_controller.js"></script>
@@ -33,7 +33,7 @@
3333
</head>
3434
<body>
3535

36-
<div map-lazy-load="https://maps.google.com/maps/api/js" ng-controller="MyCtrl">
36+
<div map-lazy-load="https://maps.google.com/maps/api/js?libraries=places" ng-controller="MyCtrl">
3737
<map center="41,-87" zoom="3">
3838

3939
<info-window id="foo">
@@ -66,6 +66,7 @@
6666

6767
<marker position="41, -79" on-click="showInfoWindow('bar')" />
6868
</map>
69+
<input places-auto-complete size=80/>
6970
</div>
7071

7172
</body>

0 commit comments

Comments
 (0)