Decouple FarmMap render element and JS instantiation #436

This commit is contained in:
Michael Stenta 2021-09-06 07:04:33 -04:00
commit 118b448170
5 changed files with 97 additions and 63 deletions

View File

@ -3,7 +3,7 @@
attach: function (instance) {
instance.editAttached.then(() => {
instance.edit.wktOn('featurechange', function(wkt) {
document.querySelector('#' + instance.target).parentElement.querySelector('textarea').value = wkt;
instance.map.getTargetElement().parentElement.querySelector('textarea').value = wkt;
});
});
},

View File

@ -2,9 +2,11 @@
farmOS.map.behaviors.wkt = {
attach: function (instance) {
const settings = instance.farmMapSettings;
// If WKT was set, create a layer.
if (drupalSettings.farm_map[instance.target].wkt) {
var wkt = drupalSettings.farm_map[instance.target].wkt;
if (settings.wkt) {
var wkt = settings.wkt;
var type = 'vector';
var opts = {
title: 'Geometry',
@ -23,7 +25,7 @@
var focusLayerPromise = Promise.resolve(layer);
// If edit is true, enable drawing controls.
if (drupalSettings.farm_map[instance.target].behaviors.wkt.edit) {
if (settings.behaviors && settings.behaviors.wkt && settings.behaviors.wkt.edit) {
if (layer !== undefined) {
instance.editAttached = instance.addBehavior('edit', { layer: layer });
} else {

View File

@ -2,62 +2,17 @@
Drupal.behaviors.farm_map = {
attach: function (context, settings) {
// Get the units.
let units = 'metric';
if (!!drupalSettings.farm_map.units) {
units = drupalSettings.farm_map.units;
}
context.querySelectorAll('[data-map-instantiator="farm_map"]').forEach(function (element) {
// Build default options.
const defaultOptions = {
units,
interactions: {
onFocusOnly: true
},
};
context.querySelectorAll('.farm-map').forEach(function (element) {
// Only create a map once per element.
if (element.getAttribute('processed')) return;
element.setAttribute('processed', true);
// Only create a map once per element.
if (element.getAttribute('processed')) return;
element.setAttribute('processed', true);
element.setAttribute('tabIndex', 0);
element.setAttribute('tabIndex', 0);
const mapId = element.getAttribute('id');
const mapOptions = { ...defaultOptions, ...drupalSettings.farm_map[mapId].instance};
const instance = farmOS.map.create(mapId, mapOptions);
context.querySelectorAll('.ol-popup-closer').forEach(function (element) {
element.onClick = function (element) {
element.focus();
};
});
// If the map is rendered as part of a form field, update the map size
// when the field's visible state changes,
const formWrapper = element.closest('div.form-wrapper');
if (formWrapper != null) {
const formWrapperObserver = new MutationObserver((mutations) => {
// Only update the map size if the wrapper was previously hidden.
if (mutations.some((mutation) => { return mutation.oldValue.includes('display: none')})) {
instance.map.updateSize();
}
});
// Observe the style attribute.
formWrapperObserver.observe(formWrapper, {
attributeFilter: ["style"],
attributeOldValue: true
})
}
// If the map is inside a details element, update the map size when
// the details element is toggled.
const details = element.closest('details');
if (details != null) {
details.addEventListener('toggle', function() {
instance.map.updateSize();
});
}
const drupalSettingsKey = element.getAttribute('id');
const mapInstanceOptions = {};
Drupal.behaviors.farm_map.createMapInstance(context, element, drupalSettingsKey, mapInstanceOptions);
});
// Add an event listener to update the map size when the Gin toolbar is toggled.
@ -79,6 +34,71 @@
}
});
}
},
createMapInstance: function(context, element, drupalSettingsKey, mapInstanceOptions) {
// Get the units.
let units = 'metric';
if (!!drupalSettings.farm_map.units) {
units = drupalSettings.farm_map.units;
}
// Build default options.
const defaultOptions = {
units,
interactions: {
onFocusOnly: true
},
};
const mapOptions = {
...defaultOptions,
...drupalSettings.farm_map[drupalSettingsKey].instance,
...mapInstanceOptions
};
const instance = farmOS.map.create(element, mapOptions);
// Expose settings on the instance so other behaviors don't need to know how to look them up in drupalSettings
instance.farmMapSettings = drupalSettings.farm_map[drupalSettingsKey] || {};
context.querySelectorAll('.ol-popup-closer').forEach(function (element) {
element.onClick = function (element) {
element.focus();
};
});
// If the map is rendered as part of a form field, update the map size
// when the field's visible state changes,
const formWrapper = element.closest('div.form-wrapper');
if (formWrapper != null) {
const formWrapperObserver = new MutationObserver((mutations) => {
// Only update the map size if the wrapper was previously hidden.
if (mutations.some((mutation) => { return mutation.oldValue.includes('display: none')})) {
instance.map.updateSize();
}
});
// Observe the style attribute.
formWrapperObserver.observe(formWrapper, {
attributeFilter: ["style"],
attributeOldValue: true
})
}
// If the map is inside a details element, update the map size when
// the details element is toggled.
const details = element.closest('details');
if (details != null) {
details.addEventListener('toggle', function() {
instance.map.updateSize();
});
}
return instance;
}
};
}(Drupal));

View File

@ -32,16 +32,23 @@ class FarmMap extends RenderElement {
*
* @param array $element
* A renderable array containing a #map_type property, which will be
* appended to 'farm-map-' as the map element ID.
* appended to 'farm-map-' as the map element ID if one has not already
* been provided.
*
* @return array
* A renderable array representing the map.
*/
public static function preRenderMap(array $element) {
// Set the id to the map name.
$map_id = Html::getUniqueId('farm-map-' . $element['#map_type']);
$element['#attributes']['id'] = $map_id;
if (empty($element['#attributes']['id'])) {
// Set the id to the map name.
$map_id = Html::getUniqueId('farm-map-' . $element['#map_type']);
$element['#attributes']['id'] = $map_id;
}
else {
$map_id = $element['#attributes']['id'];
}
// Get the map type.
/** @var \Drupal\farm_map\Entity\MapTypeInterface $map */
@ -50,6 +57,11 @@ class FarmMap extends RenderElement {
// Add the farm-map class.
$element['#attributes']['class'][] = 'farm-map';
// By default, inform farm_map.js that it should instantiate the map.
if (empty($element['#attributes']['data-map-instantiator'])) {
$element['#attributes']['data-map-instantiator'] = 'farm_map';
}
// Attach the farmOS-map and farm_map libraries.
$element['#attached']['library'][] = 'farm_map/farmOS-map';
$element['#attached']['library'][] = 'farm_map/farm_map';

View File

@ -3,10 +3,10 @@
attach: function (instance) {
// Check if there are asset type layers to add.
if (drupalSettings.farm_map[instance.target].asset_type_layers !== undefined) {
if (instance.farmMapSettings.asset_type_layers !== undefined) {
// Add layers for each area type.
var layers = drupalSettings.farm_map[instance.target].asset_type_layers;
var layers = instance.farmMapSettings.asset_type_layers;
// Create any layer groups that were explicitly defined. We do this
// first to ensure that they are available to put asset type layers in.