UNPKG

11.3 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
6
7var _react = require('react');
8
9var _react2 = _interopRequireDefault(_react);
10
11var _propTypes = require('prop-types');
12
13var _propTypes2 = _interopRequireDefault(_propTypes);
14
15var _omit = require('./utils/omit');
16
17var _omit2 = _interopRequireDefault(_omit);
18
19var _shallowEqual = require('./utils/shallowEqual');
20
21var _shallowEqual2 = _interopRequireDefault(_shallowEqual);
22
23function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
25function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
26
27function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
28
29function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
30
31// utils
32
33
34var mainStyle = {
35 width: '100%',
36 height: '100%',
37 left: 0,
38 top: 0,
39 margin: 0,
40 padding: 0,
41 position: 'absolute'
42};
43
44var style = {
45 width: 0,
46 height: 0,
47 left: 0,
48 top: 0,
49 backgroundColor: 'transparent',
50 position: 'absolute'
51};
52
53var GoogleMapMarkers = function (_Component) {
54 _inherits(GoogleMapMarkers, _Component);
55
56 /* eslint-disable react/forbid-prop-types */
57 function GoogleMapMarkers(props) {
58 _classCallCheck(this, GoogleMapMarkers);
59
60 var _this = _possibleConstructorReturn(this, _Component.call(this, props));
61
62 _this._getState = function () {
63 return {
64 children: _this.props.dispatcher.getChildren(),
65 updateCounter: _this.props.dispatcher.getUpdateCounter()
66 };
67 };
68
69 _this._onChangeHandler = function () {
70 if (!_this.dimensionsCache_) {
71 return;
72 }
73
74 var prevChildCount = (_this.state.children || []).length;
75 var state = _this._getState();
76
77 _this.setState(state, function () {
78 return (state.children || []).length !== prevChildCount && _this._onMouseChangeHandler();
79 });
80 };
81
82 _this._onChildClick = function () {
83 if (_this.props.onChildClick) {
84 if (_this.hoverChildProps_) {
85 var hoverKey = _this.hoverKey_;
86 var childProps = _this.hoverChildProps_;
87 // click works only on hovered item
88 _this.props.onChildClick(hoverKey, childProps);
89 }
90 }
91 };
92
93 _this._onChildMouseDown = function () {
94 if (_this.props.onChildMouseDown) {
95 if (_this.hoverChildProps_) {
96 var hoverKey = _this.hoverKey_;
97 var childProps = _this.hoverChildProps_;
98 // works only on hovered item
99 _this.props.onChildMouseDown(hoverKey, childProps);
100 }
101 }
102 };
103
104 _this._onChildMouseEnter = function (hoverKey, childProps) {
105 if (!_this.dimensionsCache_) {
106 return;
107 }
108
109 if (_this.props.onChildMouseEnter) {
110 _this.props.onChildMouseEnter(hoverKey, childProps);
111 }
112
113 _this.hoverChildProps_ = childProps;
114 _this.hoverKey_ = hoverKey;
115 _this.setState({ hoverKey: hoverKey });
116 };
117
118 _this._onChildMouseLeave = function () {
119 if (!_this.dimensionsCache_) {
120 return;
121 }
122
123 var hoverKey = _this.hoverKey_;
124 var childProps = _this.hoverChildProps_;
125
126 if (hoverKey !== undefined && hoverKey !== null) {
127 if (_this.props.onChildMouseLeave) {
128 _this.props.onChildMouseLeave(hoverKey, childProps);
129 }
130
131 _this.hoverKey_ = null;
132 _this.hoverChildProps_ = null;
133 _this.setState({ hoverKey: null });
134 }
135 };
136
137 _this._onMouseAllow = function (value) {
138 if (!value) {
139 _this._onChildMouseLeave();
140 }
141
142 _this.allowMouse_ = value;
143 };
144
145 _this._onMouseChangeHandler = function () {
146 if (_this.allowMouse_) {
147 _this._onMouseChangeHandlerRaf();
148 }
149 };
150
151 _this._onMouseChangeHandlerRaf = function () {
152 if (!_this.dimensionsCache_) {
153 return;
154 }
155
156 var mp = _this.props.dispatcher.getMousePosition();
157
158 if (mp) {
159 var distances = [];
160 var hoverDistance = _this.props.getHoverDistance();
161
162 _react2.default.Children.forEach(_this.state.children, function (child, childIndex) {
163 if (!child) return;
164 // layers
165 if (child.props.latLng === undefined && child.props.lat === undefined && child.props.lng === undefined) {
166 return;
167 }
168
169 var childKey = child.key !== undefined && child.key !== null ? child.key : childIndex;
170 var dist = _this.props.distanceToMouse(_this.dimensionsCache_[childKey], mp, child.props);
171 if (dist < hoverDistance) {
172 distances.push({
173 key: childKey,
174 dist: dist,
175 props: child.props
176 });
177 }
178 });
179
180 if (distances.length) {
181 distances.sort(function (a, b) {
182 return a.dist - b.dist;
183 });
184 var hoverKey = distances[0].key;
185 var childProps = distances[0].props;
186
187 if (_this.hoverKey_ !== hoverKey) {
188 _this._onChildMouseLeave();
189
190 _this._onChildMouseEnter(hoverKey, childProps);
191 }
192 } else {
193 _this._onChildMouseLeave();
194 }
195 } else {
196 _this._onChildMouseLeave();
197 }
198 };
199
200 _this._getDimensions = function (key) {
201 var childKey = key;
202 return _this.dimensionsCache_[childKey];
203 };
204
205 _this.props.dispatcher.on('kON_CHANGE', _this._onChangeHandler);
206 _this.props.dispatcher.on('kON_MOUSE_POSITION_CHANGE', _this._onMouseChangeHandler);
207 _this.props.dispatcher.on('kON_CLICK', _this._onChildClick);
208 _this.props.dispatcher.on('kON_MDOWN', _this._onChildMouseDown);
209
210 _this.dimensionsCache_ = {};
211 _this.hoverKey_ = null;
212 _this.hoverChildProps_ = null;
213 _this.allowMouse_ = true;
214
215 _this.state = _extends({}, _this._getState(), { hoverKey: null });
216 return _this;
217 }
218 /* eslint-enable react/forbid-prop-types */
219
220 GoogleMapMarkers.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
221 if (this.props.experimental === true) {
222 return !(0, _shallowEqual2.default)(this.props, nextProps) || !(0, _shallowEqual2.default)((0, _omit2.default)(this.state, ['hoverKey']), (0, _omit2.default)(nextState, ['hoverKey']));
223 }
224
225 return !(0, _shallowEqual2.default)(this.props, nextProps) || !(0, _shallowEqual2.default)(this.state, nextState);
226 };
227
228 GoogleMapMarkers.prototype.componentWillUnmount = function componentWillUnmount() {
229 this.props.dispatcher.removeListener('kON_CHANGE', this._onChangeHandler);
230 this.props.dispatcher.removeListener('kON_MOUSE_POSITION_CHANGE', this._onMouseChangeHandler);
231 this.props.dispatcher.removeListener('kON_CLICK', this._onChildClick);
232 this.props.dispatcher.removeListener('kON_MDOWN', this._onChildMouseDown);
233
234 this.dimensionsCache_ = null;
235 };
236
237 GoogleMapMarkers.prototype.render = function render() {
238 var _this2 = this;
239
240 var mainElementStyle = this.props.style || mainStyle;
241 this.dimensionsCache_ = {};
242
243 var markers = _react2.default.Children.map(this.state.children, function (child, childIndex) {
244 if (!child) return undefined;
245 if (child.props.latLng === undefined && child.props.lat === undefined && child.props.lng === undefined) {
246 return _react2.default.cloneElement(child, {
247 $geoService: _this2.props.geoService,
248 $onMouseAllow: _this2._onMouseAllow,
249 $prerender: _this2.props.prerender
250 });
251 }
252
253 var latLng = child.props.latLng !== undefined ? child.props.latLng : { lat: child.props.lat, lng: child.props.lng };
254
255 var pt = _this2.props.insideMapPanes ? _this2.props.geoService.fromLatLngToDivPixel(latLng) : _this2.props.geoService.fromLatLngToCenterPixel(latLng);
256
257 var stylePtPos = {
258 left: pt.x,
259 top: pt.y
260 };
261
262 // If the component has a southeast corner defined (either as a LatLng, or a separate
263 // lat and lng pair), set the width and height based on the distance between the northwest
264 // and the southeast corner to lock the overlay to the correct geographic bounds.
265 if (child.props.seLatLng !== undefined || child.props.seLat !== undefined && child.props.seLng !== undefined) {
266 var seLatLng = child.props.seLatLng !== undefined ? child.props.seLatLng : { lat: child.props.seLat, lng: child.props.seLng };
267
268 var sePt = _this2.props.insideMapPanes ? _this2.props.geoService.fromLatLngToDivPixel(seLatLng) : _this2.props.geoService.fromLatLngToCenterPixel(seLatLng);
269
270 stylePtPos.width = sePt.x - pt.x;
271 stylePtPos.height = sePt.y - pt.y;
272 }
273
274 var containerPt = _this2.props.geoService.fromLatLngToContainerPixel(latLng);
275
276 // to prevent rerender on child element i need to pass
277 // const params $getDimensions and $dimensionKey instead of dimension object
278 var childKey = child.key !== undefined && child.key !== null ? child.key : childIndex;
279
280 _this2.dimensionsCache_[childKey] = _extends({
281 x: containerPt.x,
282 y: containerPt.y
283 }, latLng);
284
285 return _react2.default.createElement(
286 'div',
287 {
288 key: childKey,
289 style: _extends({}, style, stylePtPos),
290 className: child.props.$markerHolderClassName
291 },
292 _react2.default.cloneElement(child, {
293 $hover: childKey === _this2.state.hoverKey,
294 $getDimensions: _this2._getDimensions,
295 $dimensionKey: childKey,
296 $geoService: _this2.props.geoService,
297 $onMouseAllow: _this2._onMouseAllow,
298 $prerender: _this2.props.prerender
299 })
300 );
301 });
302
303 return _react2.default.createElement(
304 'div',
305 { style: mainElementStyle },
306 markers
307 );
308 };
309
310 return GoogleMapMarkers;
311}(_react.Component);
312
313GoogleMapMarkers.propTypes = {
314 geoService: _propTypes2.default.any,
315 style: _propTypes2.default.any,
316 distanceToMouse: _propTypes2.default.func,
317 dispatcher: _propTypes2.default.any,
318 onChildClick: _propTypes2.default.func,
319 onChildMouseDown: _propTypes2.default.func,
320 onChildMouseLeave: _propTypes2.default.func,
321 onChildMouseEnter: _propTypes2.default.func,
322 getHoverDistance: _propTypes2.default.func,
323 insideMapPanes: _propTypes2.default.bool,
324 prerender: _propTypes2.default.bool
325};
326GoogleMapMarkers.defaultProps = {
327 insideMapPanes: false,
328 prerender: false
329};
330exports.default = GoogleMapMarkers;
\No newline at end of file