From 43b791d2610fa86083832b8579f25703a01f0ad7 Mon Sep 17 00:00:00 2001 From: Tom Chen Date: Sat, 8 Nov 2014 13:01:03 +0800 Subject: [PATCH] feat(index): create common child components by factory --- src/GoogleMapsMixin.js | 8 +-- src/InfoWindow.js | 72 -------------------- src/Marker.js | 70 ------------------- src/Polygon.js | 71 ------------------- src/Polyline.js | 71 ------------------- src/helpers/create_child_component.js | 98 +++++++++++++++++++++++++++ src/index.js | 33 +++++++-- 7 files changed, 131 insertions(+), 292 deletions(-) delete mode 100644 src/InfoWindow.js delete mode 100644 src/Marker.js delete mode 100644 src/Polygon.js delete mode 100644 src/Polyline.js create mode 100644 src/helpers/create_child_component.js diff --git a/src/GoogleMapsMixin.js b/src/GoogleMapsMixin.js index 0aed9f74..3269d637 100644 --- a/src/GoogleMapsMixin.js +++ b/src/GoogleMapsMixin.js @@ -14,7 +14,7 @@ module.exports = { getMap: React.PropTypes.func, getApi: React.PropTypes.func, hasMap: React.PropTypes.func, - getRef: React.PropTypes.func, + getInstanceByRef: React.PropTypes.func, _set_map: React.PropTypes.func }, @@ -23,7 +23,7 @@ module.exports = { getMap: this._get_map, getApi: this._get_api, hasMap: this._has_map, - getRef: this._get_ref, + getInstanceByRef: this._get_instance_by_ref, _set_map: this._set_map }; }, @@ -40,8 +40,8 @@ module.exports = { return !!this._get_map(); }, - _get_ref (key) { - return this.refs[key]; + _get_instance_by_ref (key) { + return this.refs[key].state._instance; }, _set_map (map) { diff --git a/src/InfoWindow.js b/src/InfoWindow.js deleted file mode 100644 index d117ec3c..00000000 --- a/src/InfoWindow.js +++ /dev/null @@ -1,72 +0,0 @@ -"use strict"; -var React = require("react/addons"); - -var ChildMixin = require("./mixins/ChildMixin"); -var EventBindingMixin = require("./mixins/EventBindingMixin"); - -module.exports = React.createClass({ - displayName: "InfoWindow", - - mixins: [ChildMixin, EventBindingMixin], - - getInitialState () { - return { - infowindow: null - }; - }, - - componentDidMount () { - var infowindow = this._init_infowindow(); - if (!infowindow) return; - this.add_listeners(infowindow); - }, - - componentWillUpdate () { - var {infowindow} = this.state; - if (!infowindow) return; - this.clear_listeners(infowindow); - }, - - componentDidUpdate () { - var infowindow = this._init_infowindow(); - if (!infowindow) return; - this.add_listeners(infowindow); - infowindow.setOptions(this.props); - }, - - componentWillUnmount () { - var {infowindow} = this.state; - if(!infowindow) return; - this.clear_listeners(infowindow); - this.setState({ infowindow: null }); - }, - - render () { - return this._render(this.props, this.state); - }, - - get_event_names () { - return "click dblclick drag dragend dragstart mousedown mousemove mouseout mouseover mouseup rightclick"; - }, - - _init_infowindow () { - var {context} = this; - var {infowindow} = this.state; - if(infowindow || !context.hasMap() || !context.getApi()) { - return infowindow; - } - var {InfoWindow} = context.getApi(); - if (this.props.owner) { - var {marker} = context.getRef(this.props.owner).state; - } - infowindow = new InfoWindow(this.props); - infowindow.open(context.getMap(), marker); - this.expose_getters_from(InfoWindow.prototype, infowindow); - this.setState({ infowindow }); - return infowindow; - }, - - _render (props, state) { - return null; - } -}); diff --git a/src/Marker.js b/src/Marker.js deleted file mode 100644 index f9f382f6..00000000 --- a/src/Marker.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; -var React = require("react/addons"); - -var ChildMixin = require("./mixins/ChildMixin"); -var EventBindingMixin = require("./mixins/EventBindingMixin"); - -module.exports = React.createClass({ - displayName: "Marker", - - mixins: [ChildMixin, EventBindingMixin], - - getInitialState () { - return { - marker: null - }; - }, - - componentDidMount () { - var marker = this._init_marker(); - if (!marker) return; - this.add_listeners(marker); - }, - - componentWillUpdate () { - var {marker} = this.state; - if (!marker) return; - this.clear_listeners(marker); - }, - - componentDidUpdate () { - var marker = this._init_marker(); - if (!marker) return; - this.add_listeners(marker); - marker.setOptions(this.props); - }, - - componentWillUnmount () { - var {marker} = this.state; - if (!marker) return; - this.clear_listeners(marker); - marker.setMap(null); - }, - - render () { - return this._render(this.props, this.state); - }, - - get_event_names () { - return "animation_changed click clickable_changed cursor_changed dblclick drag dragend draggable_changed dragstart flat_changed icon_changed mousedown mouseout mouseover mouseup position_changed rightclick shape_changed title_changed visible_changed zindex_changed"; - }, - - _init_marker () { - var {context} = this; - var {marker} = this.state; - if (marker || !context.hasMap() || !context.getApi()) { - return marker; - } - var {Marker} = context.getApi(); - marker = new Marker(this.props); - marker.setMap(context.getMap()); - - this.expose_getters_from(Marker.prototype, marker); - this.setState({ marker }); - return marker; - }, - - _render (props, state) { - return (props.children)? props.children : null; - } -}); diff --git a/src/Polygon.js b/src/Polygon.js deleted file mode 100644 index d4dca617..00000000 --- a/src/Polygon.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; -var React = require("react/addons"); - -var ChildMixin = require("./mixins/ChildMixin"); -var EventBindingMixin = require("./mixins/EventBindingMixin"); - -module.exports = React.createClass({ - displayName: "Polygon", - - mixins: [ChildMixin, EventBindingMixin], - - getInitialState () { - return { - polygon: null - }; - }, - - componentDidMount () { - var polygon = this._init_polygon(); - if (!polygon) return; - this.add_listeners(polygon); - }, - - componentWillUpdate () { - var {polygon} = this.state; - if (!polygon) return; - this.clear_listeners(polygon); - }, - - componentDidUpdate () { - var polygon = this._init_polygon(); - if (!polygon) return; - this.add_listeners(polygon); - polygon.setOptions(this.props); - }, - - componentWillUnmount () { - var {polygon} = this.state; - if (!polygon) return; - this.clear_listeners(polygon); - polygon.setMap(null); - this.setState({ polygon: null }); - }, - - render () { - return this._render(this.props, this.state); - }, - - get_event_names () { - return "click dblclick drag dragend dragstart mousedown mousemove mouseout mouseover mouseup rightclick"; - }, - - _init_polygon () { - var {context} = this; - var {polygon} = this.state; - if (polygon || !context.hasMap() || !context.getApi()) { - return polygon; - } - var {Polygon} = context.getApi(); - polygon = new Polygon(this.props); - polygon.setMap(context.getMap()); - - this.expose_getters_from(Polygon.prototype, polygon); - this.setState({ polygon }); - return polygon; - }, - - _render (props, state) { - return null; - } -}); diff --git a/src/Polyline.js b/src/Polyline.js deleted file mode 100644 index 49550e02..00000000 --- a/src/Polyline.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; -var React = require("react/addons"); - -var ChildMixin = require("./mixins/ChildMixin"); -var EventBindingMixin = require("./mixins/EventBindingMixin"); - -module.exports = React.createClass({ - displayName: "Polyline", - - mixins: [ChildMixin, EventBindingMixin], - - getInitialState () { - return { - polyline: null - }; - }, - - componentDidMount () { - var polyline = this._init_polyline(); - if (!polyline) return; - this.add_listeners(polyline); - }, - - componentWillUpdate () { - var {polyline} = this.state; - if (!polyline) return; - this.clear_listeners(polyline); - }, - - componentDidUpdate () { - var polyline = this._init_polyline(); - if (!polyline) return; - this.add_listeners(polyline); - polyline.setOptions(this.props); - }, - - componentWillUnmount () { - var {polyline} = this.state; - if (!polyline) return; - this.clear_listeners(polyline); - polyline.setMap(null); - this.setState({ polyline: null }); - }, - - render () { - return this._render(this.props, this.state); - }, - - get_event_names () { - return "click dblclick drag dragend dragstart mousedown mousemove mouseout mouseover mouseup rightclick"; - }, - - _init_polyline () { - var {context} = this; - var {polyline} = this.state; - if (polyline || !context.hasMap() || !context.getApi()) { - return polyline; - } - var {Polyline} = context.getApi(); - polyline = new Polyline(this.props); - polyline.setMap(context.getMap()); - - this.expose_getters_from(Polyline.prototype, polyline); - this.setState({ polyline }); - return polyline; - }, - - _render (props, state) { - return null; - } -}); diff --git a/src/helpers/create_child_component.js b/src/helpers/create_child_component.js new file mode 100644 index 00000000..a17073c3 --- /dev/null +++ b/src/helpers/create_child_component.js @@ -0,0 +1,98 @@ +"use strict"; +var React = require("react/addons"), + + expose_getters_from = require("./expose_getters_from"), + EventBindingMixin = require("../mixins/EventBindingMixin"); + +function ensure_instance_created (component, createdCallback, createFactory) { + var {context} = component, + {_instance} = component.state, + noInstance = !_instance; + + if (noInstance && context.getApi() && context.hasMap() && createFactory) { + _instance = createFactory(component, context); + } + if (_instance) { + createdCallback(_instance); + if (noInstance) { + component.setState({_instance}); + } + } +} + +function setMapToInstance (component, instance) { + instance.setMap(component.context.getMap()); +} + +module.exports = (childName, eventNames, _created_callback) => { + var createdCallback = _created_callback || setMapToInstance; + + function create_instance (component, context) { + var ChildClass = context.getApi()[childName], + instance = new ChildClass(component.props); + + expose_getters_from(component, ChildClass.prototype, instance); + return instance; + } + + /* + * shouldComponentUpdate: true. Always rerender for child + */ + return React.createClass({ + displayName: childName, + + mixins: [EventBindingMixin], + + contextTypes: { + getMap: React.PropTypes.func, + getApi: React.PropTypes.func, + hasMap: React.PropTypes.func, + getInstanceByRef: React.PropTypes.func + }, + + getInitialState () { + return { + _instance: null + }; + }, + + componentDidMount () { + ensure_instance_created(this, (instance) => { + this.add_listeners(instance); + createdCallback(this, instance); + }, create_instance); + }, + + componentWillUpdate () { + ensure_instance_created(this, this.clear_listeners); + }, + + componentDidUpdate () { + ensure_instance_created(this, (instance) => { + instance.setOptions(this.props); + this.add_listeners(instance); + createdCallback(this, instance); + }, create_instance); + }, + + componentWillUnmount () { + ensure_instance_created(this, (instance) => { + this.clear_listeners(instance); + instance.setMap(null); + }); + }, + + render () { + return this._render(this.props, this.state); + }, + + get_event_names () { + return "animation_changed click clickable_changed cursor_changed dblclick drag dragend draggable_changed dragstart flat_changed icon_changed mousedown mouseout mouseover mouseup position_changed rightclick shape_changed title_changed visible_changed zindex_changed"; + }, + + _render (props, state) { + return null; + } + }); +}; + diff --git a/src/index.js b/src/index.js index ddc2f433..18474bc0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,32 @@ "use strict"; +var create_child_component = require("./helpers/create_child_component"), + + BASIC_EVENT_NAMES = "click dblclick drag dragend dragstart mousedown mousemove mouseout mouseover mouseup rightclick"; + exports.GoogleMapsMixin = require("./GoogleMapsMixin"); exports.Map = require("./Map"); -exports.Marker = require("./Marker"); -exports.Polygon = require("./Polygon"); -exports.Polyline = require("./Polyline"); -exports.InfoWindow = require("./InfoWindow"); + +[ + [ + "Marker", + "animation_changed click clickable_changed cursor_changed dblclick drag dragend draggable_changed dragstart flat_changed icon_changed mousedown mouseout mouseover mouseup position_changed rightclick shape_changed title_changed visible_changed zindex_changed", + ], + [ + "Polyline", + BASIC_EVENT_NAMES, + ], + [ + "Polygon", + BASIC_EVENT_NAMES, + ], + [ + "InfoWindow", + BASIC_EVENT_NAMES, + (component, infoWindow) => { + var {context} = component; + infoWindow.open(context.getMap(), context.getInstanceByRef(component.props.owner)); + } + ], +].forEach((args) => { + exports[args[0]] = create_child_component.apply(null, args); +});