Skip to content

Instantly share code, notes, and snippets.

@dougwollison
Last active July 8, 2019 13:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dougwollison/e55ab601c9b3b82cb538f2368c31828a to your computer and use it in GitHub Desktop.
Save dougwollison/e55ab601c9b3b82cb538f2368c31828a to your computer and use it in GitHub Desktop.
Google Maps Gutenberg Block
.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;
}
}
}
/* 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>
) }
</>
);
}
}
/* 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