Last active
July 8, 2019 13:26
-
-
Save dougwollison/e55ab601c9b3b82cb538f2368c31828a to your computer and use it in GitHub Desktop.
Google Maps Gutenberg Block
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.wp-block-premise-map { | |
.google-map-canvas { | |
height: 400px; | |
background: $color-grey; | |
} | |
.google-map-search { | |
font-size: 16px; | |
padding: 10px 80px 0 0; | |
input { | |
display: block; | |
width: 100%; | |
margin: 0; | |
} | |
button { | |
float: right; | |
margin-right: -80px; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* globals wp, google */ | |
const DEFAULT_COORDS = { lat: 43, lng: -79 }; | |
const GEOCODE_CACHE = {}; | |
const { Component, createRef } = wp.element; | |
const { Button } = wp.components; | |
export default class Selector extends Component { | |
constructor() { | |
super( ...arguments ); | |
this.handleChange = this.handleChange.bind( this ); | |
this.handleSubmit = this.handleSubmit.bind( this ); | |
this.state = { | |
coords: this.props.coords, | |
address: this.props.address || '', | |
zoom: this.props.zoom, | |
options: this.props.options, | |
}; | |
this.mapRef = createRef(); | |
this.geocoder = new google.maps.Geocoder; | |
} | |
updateCoords( coords, no_recenter ) { | |
this.marker.setMap( this.map ); | |
this.marker.setPosition( coords ); | |
if ( ! no_recenter ) { | |
this.map.setCenter( coords ); | |
} | |
this.handleUpdates( { coords } ); | |
} | |
handleUpdates( data ) { | |
this.setState( data ); | |
if ( this.props.onChange ) { | |
this.props.onChange( data ); | |
} | |
} | |
handleChange( event ) { | |
this.setState( { address: event.target.value } ); | |
} | |
handleSubmit( event ) { | |
event.preventDefault(); | |
const address = this.state.address.trim(); | |
if ( address ) { | |
if ( GEOCODE_CACHE[ address ] ) { | |
this.updateCoords( GEOCODE_CACHE[ address ] ); | |
} else { | |
this.geocoder.geocode( { address }, result => { | |
GEOCODE_CACHE[ address ] = result[0].geometry.location.toJSON(); | |
this.updateCoords( GEOCODE_CACHE[ address ] ); | |
} ); | |
} | |
} | |
this.handleUpdates( { address } ); | |
} | |
componentDidMount() { | |
const { coords, zoom, options } = this.state; | |
this.map = new google.maps.Map( this.mapRef.current, { | |
center: coords || DEFAULT_COORDS, | |
zoom: zoom || 10, | |
clickableIcons: false, | |
} ); | |
this.marker = new google.maps.Marker( { | |
clickable: false, | |
} ); | |
if ( options ) { | |
this.map.setOptions( options ); | |
} | |
if ( coords ) { | |
this.marker.setMap( this.map ); | |
this.marker.setPosition( coords ); | |
} | |
this.map.addListener( 'click', event => { | |
this.updateCoords( event.latLng.toJSON(), 'no recenter' ); | |
} ); | |
this.map.addListener( 'zoom_changed', () => { | |
this.handleUpdates( { zoom: this.map.getZoom() } ); | |
} ); | |
} | |
render() { | |
const { showSearch, options } = this.props; | |
const { address } = this.state; | |
if ( options && this.map ) { | |
this.map.setOptions( options ); | |
} | |
return ( | |
<> | |
<div ref={ this.mapRef } className="google-map-canvas"></div> | |
{ showSearch && ( | |
<form className="google-map-search" onSubmit={ this.handleSubmit }> | |
<Button isLarge type="submit">Search</Button> | |
<input type="search" placeholder="Search address" value={ address } onChange={ this.handleChange } /> | |
</form> | |
) } | |
</> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* globals wp */ | |
import GoogleMap from './google-map.component'; | |
const { registerBlockType } = wp.blocks; | |
const { PanelBody, CheckboxControl } = wp.components; | |
const { InspectorControls } = wp.editor; | |
const optionControls = [ | |
{ name: 'fullscreenControl', label: 'Fullscreen' }, | |
{ name: 'mapTypeControl', label: 'Map type' }, | |
{ name: 'streetViewControl', label: 'Street View' }, | |
{ name: 'zoomControl', label: 'Zooming' }, | |
]; | |
registerBlockType( 'premise/map', { | |
title: 'Map', | |
description: 'Display a Google Map of a location.', | |
icon: 'location-alt', | |
category: 'widgets', | |
supports: { | |
html: false, | |
}, | |
attributes: { | |
address: { | |
type: 'string', | |
}, | |
coords: { | |
type: 'object', | |
}, | |
zoom: { | |
type: 'number', | |
}, | |
options: { | |
type: 'object', | |
}, | |
}, | |
edit: ( { attributes, setAttributes, className, isSelected } ) => { | |
var { address, coords, zoom, options } = attributes; | |
options = options || { | |
fullscreenControl: true, | |
mapTypeControl: true, | |
streetViewControl: true, | |
zoomControl: true, | |
}; | |
function handleChanges( changes ) { | |
setAttributes( changes ); | |
} | |
function setOption( name, value ) { | |
var opts = { ...options }; | |
opts[ name ] = value; | |
setAttributes( { options: opts } ); | |
} | |
return ( | |
<> | |
<div className={ className }> | |
<GoogleMap | |
address={ address } | |
coords={ coords } | |
zoom={ zoom } | |
options={ options } | |
onChange={ handleChanges } | |
showSearch={ isSelected } | |
/> | |
</div> | |
<InspectorControls> | |
<PanelBody title="Map UI Options"> | |
{ optionControls.map( option => ( | |
<CheckboxControl | |
key={ option.name } | |
label={ option.label } | |
checked={ options[ option.name ] } | |
onChange={ isChecked => setOption( option.name, isChecked ) } | |
/> | |
) ) } | |
</PanelBody> | |
</InspectorControls> | |
</> | |
); | |
}, | |
save: () => { | |
return null; | |
}, | |
} ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment