diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a84f5b..b50fb97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 4.0.2 - UNRELEASED + +### Added +- Added [`api`](https://plugins.doublesecretagency.com/google-maps/dynamic-maps/twig-php-methods/#tag-options) option to Twig/PHP `tag` method. +- Added [`assets`](https://plugins.doublesecretagency.com/google-maps/dynamic-maps/twig-php-methods/#tag-options) option to Twig/PHP `tag` method. +- Added [`callback`](https://plugins.doublesecretagency.com/google-maps/dynamic-maps/twig-php-methods/#tag-options) option to Twig/PHP `tag` method. + ## 4.0.1 - 2021-02-26 ### Added diff --git a/docs/dynamic-maps/map-management.md b/docs/dynamic-maps/map-management.md index f57d5b4..e13cc1b 100644 --- a/docs/dynamic-maps/map-management.md +++ b/docs/dynamic-maps/map-management.md @@ -48,8 +48,6 @@ Most (though not all) of these options are available across JavaScript, Twig, an | `infoWindowOptions` | JS/Twig/PHP | Accepts any [`google.maps.InfoWindowOptions`](https://developers.google.com/maps/documentation/javascript/reference/info-window#InfoWindowOptions) properties. | `infoWindowTemplate` | Twig/PHP | Template path to use for creating [info windows](/dynamic-maps/info-windows/). | | `field` | Twig/PHP | Address field(s) to be included on the map. (includes all by default) -| `js` | Twig/PHP | Whether to preload the necessary external JavaScript. -| `callback` | Twig/PHP | JavaScript function to run after the map has loaded. :::warning Additional Details For more info, please consult either the [JavaScript method](/javascript/googlemaps.js/#map-locations-options) or the [Twig/PHP constructor](/models/dynamic-map-model/#construct-locations-options). diff --git a/docs/dynamic-maps/twig-php-methods.md b/docs/dynamic-maps/twig-php-methods.md index d402282..ef57281 100644 --- a/docs/dynamic-maps/twig-php-methods.md +++ b/docs/dynamic-maps/twig-php-methods.md @@ -23,15 +23,18 @@ The `tag` method also exists in [JavaScript](/dynamic-maps/javascript-methods/#t Regardless of whether you are using Twig or PHP, this will create a new `Twig\Markup` object. -If you are working in Twig, you can use curly braces to output the map directly. +If you are working in Twig, you can use curly braces to output the map directly. This produces a `
` element with a carefully constructed `data-dna` property. #### Arguments - - `options` (_array_) - Configuration options for the rendered `
`. + - `options` (_array_) - Configuration options for the map container and its related JavaScript. -| Option | Type | Default | Description -|:-------|:------:|:-------:|------------- -| `init` | _bool_ | `true` | Whether to automatically initialize the map via JavaScript. +| Option | Type | Default | Description +|:-----------|:--------:|:-------:|:------------ +| `api` | _object_ | `{}` | Optional parameters for the Google Maps API. +| `assets` | _bool_ | `true` | Whether to preload the necessary JavaScript assets. +| `init` | _bool_ | `true` | Whether to automatically initialize the map via JavaScript. +| `callback` | _string_ | `null` | JavaScript function to run after the map has loaded. The `init` option allows the map to be automatically rendered via JavaScript, after the `
` element has first been loaded onto the page via Twig. diff --git a/docs/guides/clustering-markers.md b/docs/guides/clustering-markers.md index a8e66f5..c23417e 100644 --- a/docs/guides/clustering-markers.md +++ b/docs/guides/clustering-markers.md @@ -1,54 +1,58 @@ # Clustering Markers +To implement [marker clustering](https://developers.google.com/maps/documentation/javascript/marker-clustering), an additional JavaScript library is required. + ## Example Before any further explanation, here is the general snippet from which you can copy & paste to add marker clustering to your [dynamic map](/dynamic-maps/). It will likely require some minor adjustments for your site. ```twig -{# Load the marker clustering library #} +{# 1. Load the marker clustering library #} {% js 'https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js' %} -{# Create the JS callback function #} +{# 2. Create the JS callback function #} {% js %} - // Add marker clustering function addClustering() { - // Get the map object - var mapObject = googleMaps.getMap('my-map'); - + var myMap = googleMaps.getMap('my-map'); // Get map & markers - var map = mapObject._map; - var markers = Object.values(mapObject._markers); - + var map = myMap._map; + var markers = Object.values(myMap._markers); // Cluster markers new MarkerClusterer(map, markers, { imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m' }); - } - {% endjs %} -{# Specify callback function in map options #} -{% set options = { - id: 'my-map', - callback: 'addClustering', +{# 3. Get all locations to appear on the map #} +{% set locations = craft.entries.section('locations').all() %} + +{# 4. Specify the map ID #} +{% set mapOptions = { + 'id': 'my-map' } %} -{# Get locations #} -{% set locations = craft.entries.section('locations').all() %} +{# 5. Specify the JS callback function #} +{% set tagOptions = { + 'callback': 'addClustering' +} %} -{# Display the map #} -{{ googleMaps.map(locations, options).tag() }} +{# 6. Display the map #} +{{ googleMaps.map(locations, mapOptions).tag(tagOptions) }} ``` ## Instructions 1. First, you must **load the marker clustering library**. The example above points to a CDN, but you could alternatively store a local copy of the library. -2. You then need to **create the JS callback function**. If desired, this function could be stored in a separate `.js` file. Be sure it gets loaded _after_ the plugin loads [the `googlemaps.js` file](/javascript/googlemaps.js/). +2. You then need to **create the JS callback function**. If desired, this function could be stored in a separate `.js` file. Be sure it gets loaded _after_ the plugin loads the [`googlemaps.js` file](/javascript/googlemaps.js/). + +3. **Get the locations**, just as you normally would. It's very likely that you already have this part worked out. If not, check out the documentation for [creating a dynamic map...](/dynamic-maps/) + +4. **Specify the map's `id`** in the [`map` options](/dynamic-maps/map-management/#map-locations-options). This makes it easy to reference the map in JavaScript. -3. **Specify the `callback` function in the map's [options](/models/dynamic-map-model/#construct-locations-options)**. If you are referencing a named function, simply pass the name of the function. It's also possible to pass an anonymous function (as a string). +5. **Specify the `callback` function** in the [`tag` options](/dynamic-maps/twig-php-methods/#tag-options). If you are referencing a named function, specify the name of the function. Or you can pass an anonymous function (as a _string_ in Twig/PHP). -4. Lastly, you'll want to **get the locations** and **display the map**. It's very likely that you already have this part worked out. If not, check out the documentation for [creating a dynamic map...](/dynamic-maps/) +6. Lastly, **display the map** by providing the `locations`, `mapOptions`, and `tagOptions`. diff --git a/docs/guides/required-js-assets.md b/docs/guides/required-js-assets.md index 27b0e31..989897a 100644 --- a/docs/guides/required-js-assets.md +++ b/docs/guides/required-js-assets.md @@ -22,22 +22,13 @@ In addition to the Google Maps API reference, there are two [JavaScript files](/ ## Disable Automatic Loading -To prevent the required assets from being automatically loaded, simply set the `js` option to `false` when creating a map. +If necessary, you can prevent the required assets from being loaded automatically. When the `tag` method is appended, simply set the `assets` value to `false`. -:::code ```twig -{% set map = googleMaps.map(locations, { - 'js': false -}) %} -``` -```php -$map = GoogleMaps::map($locations, [ - 'js' => false -]); +{{ googleMaps.map(locations).tag({'assets': false}) }} ``` -::: -For more info, see the complete [list of options...](/dynamic-maps/map-management/#map-locations-options) +For more info, see the complete [list of options...](/dynamic-maps/twig-php-methods/#tag-options) ## Loaded Manually diff --git a/docs/models/dynamic-map-model.md b/docs/models/dynamic-map-model.md index 7911437..df2d873 100644 --- a/docs/models/dynamic-map-model.md +++ b/docs/models/dynamic-map-model.md @@ -49,8 +49,6 @@ Once you have the map object in hand, you can then chain other methods to furthe | `infoWindowOptions` | _object_ | _null_ | Accepts any [`google.maps.InfoWindowOptions`](https://developers.google.com/maps/documentation/javascript/reference/info-window#InfoWindowOptions) properties. | `infoWindowTemplate` | _string_ | _null_ | Template path to use for creating [info windows](/dynamic-maps/info-windows/). | `field` | _string_\|_array_ | _null_ | Address field(s) to be included on the map. (includes all by default) -| `js` | _bool_ | _true_ | Whether to preload the necessary external JavaScript. -| `callback` | _string_ | _null_ | JavaScript function to run after the map has finished loading. #### Returns @@ -352,9 +350,12 @@ Renders the necessary `
` container to hold the map. The final `
` will - `$options` (_array_) - Configuration options for the rendered `
`. -| Option | Type | Default | Description -|:-------|:------:|:-------:|------------- -| `init` | _bool_ | `true` | Whether to automatically initialize the map via JavaScript. +| Option | Type | Default | Description +|:-----------|:--------:|:-------:|:------------ +| `api` | _object_ | `{}` | Optional parameters for the Google Maps API. +| `assets` | _bool_ | `true` | Whether to preload the necessary JavaScript assets. +| `init` | _bool_ | `true` | Whether to automatically initialize the map via JavaScript. +| `callback` | _string_ | `null` | JavaScript function to run after the map has loaded. By setting the `init` option to `false`, the map will not be automatically initialized in JavaScript. It must therefore be [manually initialized in JavaScript](/dynamic-maps/javascript-methods/#init-mapid-null-callback-null) when the page has completely rendered. diff --git a/docs/updating-from-smart-map/customizing-the-map-in-twig.md b/docs/updating-from-smart-map/customizing-the-map-in-twig.md index 3af64dc..5b3e6a4 100644 --- a/docs/updating-from-smart-map/customizing-the-map-in-twig.md +++ b/docs/updating-from-smart-map/customizing-the-map-in-twig.md @@ -20,10 +20,8 @@ Please take a closer look to see which items will need to be updated, added, or | Option | | What Changed |:---------------------|----|:------------- -| `mapOptions` | ⭐ | **ADDED!** (new in the Google Maps plugin) | `styles` | ⭐ | **ADDED!** (new in the Google Maps plugin) -| `js` | ⭐ | **ADDED!** (new in the Google Maps plugin) -| `callback` | ⭐ | **ADDED!** (new in the Google Maps plugin) +| `mapOptions` | ⭐ | **ADDED!** (new in the Google Maps plugin) | `maptype` | ❌ | REMOVED (configure via `mapOptions` instead) | `scale` | ❌ | REMOVED (configure via `mapOptions` instead) | `scrollwheel` | ❌ | REMOVED (configure via `mapOptions` instead) diff --git a/src/models/DynamicMap.php b/src/models/DynamicMap.php index 39e7a16..1123a43 100644 --- a/src/models/DynamicMap.php +++ b/src/models/DynamicMap.php @@ -22,6 +22,7 @@ use craft\web\View; use doublesecretagency\googlemaps\fields\AddressField; use doublesecretagency\googlemaps\GoogleMapsPlugin; +use doublesecretagency\googlemaps\helpers\GoogleMaps; use doublesecretagency\googlemaps\helpers\MapHelper; use doublesecretagency\googlemaps\web\assets\JsApiAsset; use Twig\Error\LoaderError; @@ -84,19 +85,9 @@ public function __construct($locations = [], array $options = [], array $config // Set internal map ID $this->id = $options['id']; - // Unless otherwise specified, preload the necessary JavaScript - if (!isset($options['js']) || !is_bool($options['js'])) { - $options['js'] = true; - } - // Get view service $view = Craft::$app->getView(); - // Load assets - if ($options['js']) { - $view->registerAssetBundle(JsApiAsset::class); - } - // Whether devMode is enabled $inDevMode = Craft::$app->getConfig()->general->devMode; @@ -119,7 +110,7 @@ public function __construct($locations = [], array $options = [], array $config ]; // Prevent conflict between map ID and marker IDs - unset($options['id'], $options['js']); + unset($options['id']); // Create markers along with their corresponding info windows $this->_initInfoWindows($locations, $options); @@ -384,33 +375,48 @@ public function tag(array $options = []): Markup throw new Exception('Model misconfigured. The map DNA is empty.'); } - // Alias map from DNA - $map =& $this->_dna[0]; - - // If the first item is not a map, throw an error - if ('map' != $map['type']) { + // If the first DNA item is not a map, throw an error + if ('map' != ($this->_dna[0]['type'] ?? false)) { throw new Exception('Map model misconfigured. The chain must begin with a `map()` segment.'); } - // Compile map container - $html = Html::modifyTagAttributes('
Loading map...
', [ - 'id' => $this->id, - 'class' => 'gm-map', - 'data-dna' => Json::encode($this->_dna), - ]); + // Get view service + $view = Craft::$app->getView(); + + // Unless otherwise specified, preload the necessary JavaScript assets + if (!isset($options['assets']) || !is_bool($options['assets'])) { + $options['assets'] = true; + } + + // If no additional API parameters were specified, default to empty array + if (!isset($options['api']) || !is_array($options['api'])) { + $options['api'] = []; + } + + // If we're permitted to load JS assets + if ($options['assets']) { + // Load assets with optional API parameters + GoogleMaps::loadAssets($options['api']); + } // Initialize the map (unless intentionally suppressed) if ($options['init'] ?? true) { // Get optional callback - $callback = ($map['options']['callback'] ?? 'null'); + $callback = ($options['callback'] ?? 'null'); // Initialize Google Maps after page has loaded $googleMapsInit = "googleMaps.init('{$this->id}', {$callback})"; $js = "addEventListener('load', function () {{$googleMapsInit}});"; // Register JS at the end of the page - $view = Craft::$app->getView(); $view->registerJs($js, $view::POS_END); } + // Compile map container + $html = Html::modifyTagAttributes('
Loading map...
', [ + 'id' => $this->id, + 'class' => 'gm-map', + 'data-dna' => Json::encode($this->_dna), + ]); + // Return Markup return Template::raw($html); }