diff --git a/src/GoogleMap.js b/src/GoogleMap.js index d45b8102..1c85dbd1 100644 --- a/src/GoogleMap.js +++ b/src/GoogleMap.js @@ -2,34 +2,17 @@ "use strict"; var React = require("react/addons"); +var EventBindingMixin = require("./mixins/EventBindingMixin"); + var mapsNullObject = { }; -var EVENT_MAP = {}; -var EVENT_LIST = "bounds_changed center_changed click dblclick drag dragend dragstart heading_changed idle maptypeid_changed mousemove mouseout mouseover projection_changed resize rightclick tilesloaded tilt_changed zoom_changed" - .split(" ") - .map(toEventList, EVENT_MAP); - -function toEventList (name) { - var eventName = toEventName(name); - this[eventName] = name; - return eventName; -} - -function toEventName(name) { - return `on${ name - .replace(/^(.)/, groupToUpperCase) - .replace(/_(.)/g, groupToUpperCase) }`; -} - -function groupToUpperCase (match, group) { - return group.toUpperCase(); -} - module.exports = React.createClass({ displayName: "GoogleMap", + mixins: [EventBindingMixin], + getDefaultProps () { return { mapOptions: {} @@ -39,26 +22,18 @@ module.exports = React.createClass({ getInitialState () { return { googleMapsApi: this.props.googleMapsApi || mapsNullObject, - map: null, - eventNames: [] + map: null }; }, - componentWillMount () { - this.setState({ - eventNames: this._collect_event_names(this.props) - }); - }, - componentWillReceiveProps (nextProps) { var {googleMapsApi} = nextProps; - var newState = {}; if (mapsNullObject !== googleMapsApi) { - newState.googleMapsApi = googleMapsApi; + this.setState({ + googleMapsApi + }); } - newState.eventNames = this._collect_event_names(nextProps); - this.setState(newState); }, componentDidMount () { @@ -71,7 +46,7 @@ module.exports = React.createClass({ componentWillUnmount () { var {googleMapsApi, map} = this.state; - this._clear_listeners(googleMapsApi, map); + this.clear_listeners(googleMapsApi, map); }, render () { @@ -88,21 +63,7 @@ module.exports = React.createClass({ ); this.setState({ map }); } - this._clear_listeners(googleMapsApi, map); - eventNames.forEach((eventName) => { - var name = EVENT_MAP[eventName]; - googleMapsApi.event.addListener(map, name, this.props[eventName]); - }); - }, - - _collect_event_names (props) { - return EVENT_LIST.filter((eventName) => { - return eventName in props; - }); - }, - - _clear_listeners (googleMapsApi, map) { - googleMapsApi.event.clearInstanceListeners(map); + this.upsert_listeners(googleMapsApi, map); }, _render (props, state) { diff --git a/src/mixins/EventBindingMixin.js b/src/mixins/EventBindingMixin.js new file mode 100644 index 00000000..43a58922 --- /dev/null +++ b/src/mixins/EventBindingMixin.js @@ -0,0 +1,62 @@ +/** @jsx React.DOM */ +"use strict"; + +var EVENT_MAP = {}; +var EVENT_LIST = "bounds_changed center_changed click dblclick drag dragend dragstart heading_changed idle maptypeid_changed mousemove mouseout mouseover projection_changed resize rightclick tilesloaded tilt_changed zoom_changed" + .split(" ") + .map(toEventList, EVENT_MAP); + +function toEventList (name) { + var eventName = toEventName(name); + this[eventName] = name; + return eventName; +} + +function toEventName(name) { + return `on${ name + .replace(/^(.)/, groupToUpperCase) + .replace(/_(.)/g, groupToUpperCase) }`; +} + +function groupToUpperCase (match, group) { + return group.toUpperCase(); +} + +module.exports = { + + getInitialState () { + return { + eventNames: [] + }; + }, + + componentWillMount () { + this.setState({ + eventNames: this._collect_event_names(this.props) + }); + }, + + componentWillReceiveProps (nextProps) { + this.setState({ + eventNames: this._collect_event_names(nextProps) + }); + }, + + upsert_listeners (googleMapsApi, map) { + this.clear_listeners(googleMapsApi, map); + this.state.eventNames.forEach((eventName) => { + var name = EVENT_MAP[eventName]; + googleMapsApi.event.addListener(map, name, this.props[eventName]); + }); + }, + + clear_listeners (googleMapsApi, map) { + googleMapsApi.event.clearInstanceListeners(map); + }, + + _collect_event_names (props) { + return EVENT_LIST.filter((eventName) => { + return eventName in props; + }); + } +};