From cba8939843cc027de14711791119e7c4a1a5d53d Mon Sep 17 00:00:00 2001 From: David Molineus Date: Wed, 9 Nov 2016 10:27:18 +0100 Subject: [PATCH 01/14] Implement overpass layer. --- module/config/config.php | 1 + module/dca/tl_leaflet_layer.php | 82 ++++++++++++++++++- .../Mapper/Layer/OverpassLayerMapper.php | 74 +++++++++++++++++ .../Contao/Leaflet/Mapper/OptionsBuilder.php | 2 +- 4 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php diff --git a/module/config/config.php b/module/config/config.php index 9a94685..1ff685b 100644 --- a/module/config/config.php +++ b/module/config/config.php @@ -98,6 +98,7 @@ $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Layer\MarkersLa $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Layer\GroupLayerMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Layer\VectorsLayerMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Layer\ReferenceLayerMapper'; +$GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Layer\OverpassLayerMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = function () { return new \Netzmacht\Contao\Leaflet\Mapper\Layer\MarkerClusterLayerMapper( $GLOBALS['container'][\Netzmacht\Contao\Leaflet\DependencyInjection\LeafletServices::MAP_ASSETS] diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index 9c9988c..cc42fd3 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -213,7 +213,20 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'reuseTiles', 'bounds' ) - ) + ), + 'overpass extends default' => array( + 'config' => array( + 'overpassQuery', + 'overpassEndpoint', + 'overpassCallback', + 'minZoom', + ), + '+expert' => array( + 'minZoomIndicatorPosition', + 'minZoomIndicatorMessageNoLayer', + 'minZoomIndicatorMessage', + ), + ), ), 'metasubselectpalettes' => array( @@ -783,5 +796,72 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'eval' => array('maxlength' => 5, 'rgxp' => 'digit', 'tl_class' => 'w50', 'nullIfEmpty' => true), 'sql' => "int(9) NOT NULL default '0'" ), + 'overpassQuery' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['overpassQuery'], + 'exclude' => true, + 'inputType' => 'textarea', + 'eval' => array( + 'preserveTags' => true, + 'decodeEntities' => true, + 'allowHtml' => true, + 'rte' => 'ace', + 'tl_class' => 'clr' + ), + 'sql' => "mediumtext NULL" + ), + 'overpassEndpoint' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['overpassEndpoint'], + 'exclude' => true, + 'inputType' => 'text', + 'default' => null, + 'eval' => array('tl_class' => 'long'), + 'sql' => "varchar(255) NOT NULL default ''" + ), + 'overpassCallback' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['overpassCallback'], + 'exclude' => true, + 'inputType' => 'textarea', + 'eval' => array( + 'preserveTags' => true, + 'decodeEntities' => true, + 'allowHtml' => true, + 'rte' => 'ace|javascript', + 'tl_class' => 'clr' + ), + 'sql' => "mediumtext NULL" + ), + 'minZoomIndicatorPosition' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['minZoomIndicatorPosition'], + 'exclude' => true, + 'inputType' => 'select', + 'filter' => true, + 'sorting' => true, + 'options' => array('topleft', 'topright', 'bottomleft', 'bottomright'), + 'reference' => &$GLOBALS['TL_LANG']['tl_leaflet_layer'], + 'eval' => array('mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50', 'helpwizard' => true), + 'sql' => "varchar(255) NOT NULL default ''" + ), + 'minZoomIndicatorMessage' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['minZoomIndicatorMessage'], + 'exclude' => true, + 'inputType' => 'text', + 'default' => null, + 'eval' => array('tl_class' => 'long'), + 'sql' => "varchar(255) NOT NULL default ''" + ), + 'minZoomIndicatorMessageNoLayer' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['minZoomIndicatorMessageNoLayer'], + 'exclude' => true, + 'inputType' => 'text', + 'default' => null, + 'eval' => array('tl_class' => 'long'), + 'sql' => "varchar(255) NOT NULL default ''" + ), ) ); diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php new file mode 100644 index 0000000..ca6da15 --- /dev/null +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php @@ -0,0 +1,74 @@ + + * @copyright 2016 netzmacht David Molineus. All rights reserved. + * @filesource + * + */ + +namespace Netzmacht\Contao\Leaflet\Mapper\Layer; + +use Netzmacht\Contao\Leaflet\Filter\Filter; +use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper; +use Netzmacht\Contao\Leaflet\Mapper\OptionsBuilder; +use Netzmacht\JavascriptBuilder\Type\Expression; +use Netzmacht\LeafletPHP\Definition; +use Netzmacht\LeafletPHP\Plugins\OverpassLayer\OverpassLayer; + +/** + * Class OverpassLayerMapper + * + * @package Netzmacht\Contao\Leaflet\Mapper\Layer + */ +class OverpassLayerMapper extends AbstractLayerMapper +{ + /** + * The definition type. + * + * @var string + */ + protected static $type = 'overpass'; + + /** + * {@inheritdoc} + */ + protected function initialize() + { + parent::initialize(); + + $this->optionsBuilder + ->addOption('overpassQuery', 'query') + ->addConditionalOption('minZoom') + ->addConditionalOption('overpassEndpoint', 'endpoint'); + } + + /** + * {@inheritdoc} + */ + protected function build( + Definition $definition, + \Model $model, + DefinitionMapper $mapper, + Filter $filter = null, + Definition $parent = null + ) { + if (!$definition instanceof OverpassLayer) { + return; + } + + $minZoomIndicatorOptions = $definition->getMinZoomIndicatorOptions(); + $minZoomIndicatorOptionsBuilder = new OptionsBuilder(); + $minZoomIndicatorOptionsBuilder + ->addConditionalOption('minZoomIndicatorPosition', 'position') + ->addConditionalOption('minZoomIndicatorMessageNoLayer', 'minZoomMessageNoLayer') + ->addConditionalOption('minZoomIndicatorMessage', 'minZoomMessage'); + + $minZoomIndicatorOptionsBuilder->build($minZoomIndicatorOptions, $model); + + if ($model->overpassCallback) { + $definition->setCallback(new Expression($model->overpassCallback)); + } + } +} diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/OptionsBuilder.php b/src/Netzmacht/Contao/Leaflet/Mapper/OptionsBuilder.php index e1e9d17..377e7f0 100644 --- a/src/Netzmacht/Contao/Leaflet/Mapper/OptionsBuilder.php +++ b/src/Netzmacht/Contao/Leaflet/Mapper/OptionsBuilder.php @@ -162,7 +162,7 @@ class OptionsBuilder * * @return void */ - private function buildConditionals(Definition $definition, \Model $model) + private function buildConditionals($definition, \Model $model) { foreach ($this->conditional as $column => $conditions) { foreach ($conditions as $value => $options) { From 422433bc52d652571eaf8349c3ff2177050a0e05 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Wed, 9 Nov 2016 11:23:26 +0100 Subject: [PATCH 02/14] Bugfixes. --- module/assets/img/overpass.png | Bin 0 -> 780 bytes module/config/config.php | 4 ++++ module/dca/tl_leaflet_layer.php | 12 +++++------ .../Mapper/Layer/OverpassLayerMapper.php | 19 ++++++++++++------ 4 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 module/assets/img/overpass.png diff --git a/module/assets/img/overpass.png b/module/assets/img/overpass.png new file mode 100644 index 0000000000000000000000000000000000000000..2c41621367f1d3ac6391035a64d958ba9e8e8a37 GIT binary patch literal 780 zcmV+n1M~ceP)cB(nKF3=x}||$~tJK zUceG2;)@3eJOCG60=X{$QCtt8eM>8yZ+QpWPvjycZ4)xKWx%Q~2Z)If0vN|hxaIZe zfA@w=L9rfSeb#n)V91H|$P7w12l2x@i|LUmfP6OHxgB#!wNTEC!*1ts?D$dCUN=ke zfaoGITAltdiFV_DEp%!%xTIuKfCB!&Du$hQ*m)kNA`>)v17wRlCam?u-##j~2hlLiL&tw5%cG(Hd8kc7gj4vLO@N9KvoBnK1oN=>D1-t~b@Btk|zj89YE zM-=Ek9{g))AJ>&Qq7s&t&|&{__TKZ6*8c&-AaUn0V&cj#0R{kin;F4Fs}2?b0000< KMNUMnLSTa9=}~b2 literal 0 HcmV?d00001 diff --git a/module/config/config.php b/module/config/config.php index 1ff685b..f0c9e4b 100644 --- a/module/config/config.php +++ b/module/config/config.php @@ -271,6 +271,10 @@ $GLOBALS['LEAFLET_LAYERS'] = array 'children' => false, 'icon' => 'system/modules/leaflet/assets/img/tile.png', ), + 'overpass' => array( + 'children' => false, + 'icon' => 'system/modules/leaflet/assets/img/overpass.png', + ), ); /* diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index cc42fd3..f856829 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -792,9 +792,9 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['cacheLifeTime'], 'exclude' => true, 'inputType' => 'text', - 'default' => null, - 'eval' => array('maxlength' => 5, 'rgxp' => 'digit', 'tl_class' => 'w50', 'nullIfEmpty' => true), - 'sql' => "int(9) NOT NULL default '0'" + 'default' => 0, + 'eval' => array('maxlength' => 5, 'rgxp' => 'digit', 'tl_class' => 'w50'), + 'sql' => "int(10) unsigned NOT NULL default '0'" ), 'overpassQuery' => array ( @@ -815,7 +815,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['overpassEndpoint'], 'exclude' => true, 'inputType' => 'text', - 'default' => null, + 'default' => '', 'eval' => array('tl_class' => 'long'), 'sql' => "varchar(255) NOT NULL default ''" ), @@ -850,7 +850,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['minZoomIndicatorMessage'], 'exclude' => true, 'inputType' => 'text', - 'default' => null, + 'default' => '', 'eval' => array('tl_class' => 'long'), 'sql' => "varchar(255) NOT NULL default ''" ), @@ -859,7 +859,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['minZoomIndicatorMessageNoLayer'], 'exclude' => true, 'inputType' => 'text', - 'default' => null, + 'default' => '', 'eval' => array('tl_class' => 'long'), 'sql' => "varchar(255) NOT NULL default ''" ), diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php index ca6da15..1f9029d 100644 --- a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php @@ -31,6 +31,13 @@ class OverpassLayerMapper extends AbstractLayerMapper */ protected static $type = 'overpass'; + /** + * The definition class. + * + * @var string + */ + protected static $definitionClass = 'Netzmacht\LeafletPHP\Plugins\OverpassLayer\OverpassLayer'; + /** * {@inheritdoc} */ @@ -39,9 +46,9 @@ class OverpassLayerMapper extends AbstractLayerMapper parent::initialize(); $this->optionsBuilder - ->addOption('overpassQuery', 'query') - ->addConditionalOption('minZoom') - ->addConditionalOption('overpassEndpoint', 'endpoint'); + ->addOption('query', 'overpassQuery') + ->addOption('minzoom', 'minZoom') + ->addOption('overpassEndpoint', 'endpoint'); } /** @@ -61,9 +68,9 @@ class OverpassLayerMapper extends AbstractLayerMapper $minZoomIndicatorOptions = $definition->getMinZoomIndicatorOptions(); $minZoomIndicatorOptionsBuilder = new OptionsBuilder(); $minZoomIndicatorOptionsBuilder - ->addConditionalOption('minZoomIndicatorPosition', 'position') - ->addConditionalOption('minZoomIndicatorMessageNoLayer', 'minZoomMessageNoLayer') - ->addConditionalOption('minZoomIndicatorMessage', 'minZoomMessage'); + ->addOption('position', 'minZoomIndicatorPosition') + ->addOption('minZoomMessageNoLayer', 'minZoomIndicatorMessageNoLayer') + ->addOption('minZoomMessage', 'minZoomIndicatorMessage'); $minZoomIndicatorOptionsBuilder->build($minZoomIndicatorOptions, $model); From 37065f2183c1909c07347195638e6ff446d0abac Mon Sep 17 00:00:00 2001 From: David Molineus Date: Wed, 9 Nov 2016 11:47:57 +0100 Subject: [PATCH 03/14] Add query to the tree view. --- module/config/config.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/module/config/config.php b/module/config/config.php index f0c9e4b..7250c30 100644 --- a/module/config/config.php +++ b/module/config/config.php @@ -274,6 +274,13 @@ $GLOBALS['LEAFLET_LAYERS'] = array 'overpass' => array( 'children' => false, 'icon' => 'system/modules/leaflet/assets/img/overpass.png', + 'label' => function ($row, $label) { + if ($row['overpassQuery']) { + $label .= ' ' . \StringUtil::substr($row['overpassQuery'], 50) . ''; + } + + return $label; + } ), ); From 8947efc351396e07265a7715bd79d3a71512a6f6 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Wed, 9 Nov 2016 11:57:44 +0100 Subject: [PATCH 04/14] Improve input mask. --- module/dca/tl_leaflet_layer.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index f856829..7f867b4 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -218,13 +218,14 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'config' => array( 'overpassQuery', 'overpassEndpoint', - 'overpassCallback', 'minZoom', + 'overpassCallback', ), '+expert' => array( 'minZoomIndicatorPosition', - 'minZoomIndicatorMessageNoLayer', + 'debug', 'minZoomIndicatorMessage', + 'minZoomIndicatorMessageNoLayer', ), ), ), @@ -816,7 +817,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'exclude' => true, 'inputType' => 'text', 'default' => '', - 'eval' => array('tl_class' => 'long'), + 'eval' => array('tl_class' => 'w50'), 'sql' => "varchar(255) NOT NULL default ''" ), 'overpassCallback' => array @@ -851,7 +852,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'exclude' => true, 'inputType' => 'text', 'default' => '', - 'eval' => array('tl_class' => 'long'), + 'eval' => array('tl_class' => 'clr w50'), 'sql' => "varchar(255) NOT NULL default ''" ), 'minZoomIndicatorMessageNoLayer' => array @@ -860,8 +861,17 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'exclude' => true, 'inputType' => 'text', 'default' => '', - 'eval' => array('tl_class' => 'long'), + 'eval' => array('tl_class' => 'w50'), 'sql' => "varchar(255) NOT NULL default ''" ), + 'debug' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['debug'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => false, + 'eval' => array('tl_class' => 'w50 m12'), + 'sql' => "char(1) NOT NULL default ''" + ), ) ); From 74f500513ac39d3d131b8d3696d8d283ceb12ed3 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Wed, 9 Nov 2016 12:00:57 +0100 Subject: [PATCH 05/14] Support debug mode. --- .../Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php index 1f9029d..afd093c 100644 --- a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php @@ -48,6 +48,7 @@ class OverpassLayerMapper extends AbstractLayerMapper $this->optionsBuilder ->addOption('query', 'overpassQuery') ->addOption('minzoom', 'minZoom') + ->addOption('debug') ->addOption('overpassEndpoint', 'endpoint'); } From 130848c1f366e68a7fa8c94dd57e9b95915dfe93 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 09:10:31 +0100 Subject: [PATCH 06/14] Typos. --- assets/maps/src/Contao.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/maps/src/Contao.js b/assets/maps/src/Contao.js index a088a9e..243addd 100644 --- a/assets/maps/src/Contao.js +++ b/assets/maps/src/Contao.js @@ -110,7 +110,7 @@ L.Contao = L.Class.extend({ }, /** - * Layer a url into a layer using omnivore. + * Load data from an url into a layer using omnivore. * * @param hash The leaflet url hash. * @param type The response content format. @@ -126,7 +126,7 @@ L.Contao = L.Class.extend({ // Required because Control.Loading tries to get _leafet_id which is created here. L.stamp(layer); - // Add listender for map bounds changes. + // Add listener for map bounds changes. if (map.options.dynamicLoad && layer.options.boundsMode == 'fit') { layer.options.requestHash = hash; map.on('moveend', layer.refreshData, layer); From c61e2d9cc9f868d4f7962a5d1db068e07ede6893 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 11:00:10 +0100 Subject: [PATCH 07/14] Refactor overpass support using own implementation of overpass layer. --- assets/maps/contao-leaflet.js | 2 +- assets/maps/src/Mixin.Map.js | 36 +-- assets/maps/src/OverpassLayer.js | 215 ++++++++++++++++++ module/config/config.php | 6 +- module/dca/tl_leaflet_layer.php | 8 +- .../Definition/Layer/OverpassLayer.php | 190 ++++++++++++++++ .../Mapper/Layer/OverpassLayerMapper.php | 27 +-- 7 files changed, 447 insertions(+), 37 deletions(-) create mode 100644 assets/maps/src/OverpassLayer.js create mode 100644 src/Netzmacht/Contao/Leaflet/Definition/Layer/OverpassLayer.php diff --git a/assets/maps/contao-leaflet.js b/assets/maps/contao-leaflet.js index fd25c46..c6ac251 100644 --- a/assets/maps/contao-leaflet.js +++ b/assets/maps/contao-leaflet.js @@ -1 +1 @@ -L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;onetzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===a.status||n(a.status)?o.call(a,null,a):o.call(a,a,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var r=t.match(/^\s*https?:\/\/[^\/]*/);e=r&&r[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var a=new window.XMLHttpRequest;if(e&&!("withCredentials"in a)){a=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in a?a.onload=i:a.onreadystatechange=function(){4===a.readyState&&i()},a.onerror=function(t){o.call(this,t||!0,null),o=function(){}},a.onprogress=function(){},a.ontimeout=function(t){o.call(this,t,null),o=function(){}},a.onabort=function(t){o.call(this,t,null),o=function(){}},a.open("GET",t,!0),a.send(null),s=!0,a}}); \ No newline at end of file diff --git a/assets/maps/src/Mixin.Map.js b/assets/maps/src/Mixin.Map.js index e1b8268..110ff44 100644 --- a/assets/maps/src/Mixin.Map.js +++ b/assets/maps/src/Mixin.Map.js @@ -30,23 +30,31 @@ L.Map.include({ } if (this._dynamicBounds) { - options = {}; - - if (this.options.boundsPadding) { - options.padding = this.options.boundsPadding; - } else { - if (this.options.boundsPaddingTopLeft) { - options.paddingTopLeft = this.options.boundsPaddingTopLeft; - } - if (this.options.boundsPaddingBottomRight) { - options.paddingBottomRight = this.options.boundsPaddingBottomRight; - } - } - - this.fitBounds(this._dynamicBounds, options); + this.fitBounds(this._dynamicBounds, this.getBoundsOptions()); } }, + /** + * Get the bounds optons + * @returns {{}} + */ + getBoundsOptions: function () { + options = {}; + + if (this.options.boundsPadding) { + options.padding = this.options.boundsPadding; + } else { + if (this.options.boundsPaddingTopLeft) { + options.paddingTopLeft = this.options.boundsPaddingTopLeft; + } + if (this.options.boundsPaddingBottomRight) { + options.paddingBottomRight = this.options.boundsPaddingBottomRight; + } + } + + return options; + }, + /** * Scan recursively for bounds in a layer and extend _dynamicBounds if any found. * diff --git a/assets/maps/src/OverpassLayer.js b/assets/maps/src/OverpassLayer.js new file mode 100644 index 0000000..2018903 --- /dev/null +++ b/assets/maps/src/OverpassLayer.js @@ -0,0 +1,215 @@ +/** + * Get the bounds as overpass bbox string. + * + * @returns {string} + */ +L.LatLngBounds.prototype.toOverpassBBoxString = function () { + var a = this._southWest, + b = this._northEast; + + return [a.lat, a.lng, b.lat, b.lng].join(","); +}; + +/** + * Implementation of the overpass layer. Heavily inspired by + * https://github.com/kartenkarsten/leaflet-layer-overpass. + */ +L.OverPassLayer = L.FeatureGroup.extend({ + options: { + minZoom: 0, + endpoint: '//overpass-api.de/api/', + query: '(node(BBOX)[organic];node(BBOX)[second_hand];);out qt;' + }, + /** + * Initialize the layer. + * + * @param options + */ + initialize: function (options) { + L.Util.setOptions(this, options); + + this.options.pointToLayer = this.pointToLayer; + this.options.onEachFeature = this.onEachFeature; + this.options.dynamicLoad = this.options.query.match(/BBOX/g) ? true : false; + + this._layer = L.geoJson(); + this._layers = {}; + + this.addLayer(this._layer); + }, + /** + * Refresh the data of the layer. + * + * TODO: Implement some caching. + */ + refreshData: function () { + if (this._map.getZoom() < this.options.minZoom) { + return; + } + + var bounds = this._map.getBounds().toOverpassBBoxString(); + var query = this.options.query.replace(/(BBOX)/g, bounds); + var url = this.options.endpoint + "interpreter?data=[out:json];" + query; + + this._map.fire('dataloading', {layer: this}); + + this.request(url, function (error, response) { + var data = JSON.parse(response.response); + var features = osmtogeojson(data); + var layer = L.geoJson(features, { + pointToLayer: this.options.pointToLayer.bind(this), + onEachFeature: this.options.onEachFeature.bind(this) + }); + + this.addLayer(layer); + this.removeLayer(this._layer); + this._layer = layer; + + if (this.options.boundsMode === 'extend' && layer.getBounds().isValid()) { + var bounds = this._map.getBounds(); + bounds = bounds.extend(layer.getBounds()); + + this._map.fitBounds(bounds, this._map.getBoundsOptions()); + } + + this._map.fire('dataload', {layer: this}); + }.bind(this)); + }, + /** + * @param map + */ + onAdd: function (map) { + if (this.options.boundsMode === 'fit' && this.options.dynamicLoad) { + map.on('moveend', this.refreshData, this); + } + + this.refreshData(); + }, + pointToLayer: function (feature, latlng) { + var type = 'marker'; + var marker = L.marker(latlng, feature.properties.options); + + if (feature.properties) { + if (feature.properties.radius) { + marker.setRadius(feature.properties.radius); + } + + if (feature.properties.icon) { + var icon = this._map.getIcon(feature.properties.icon); + + if (icon) { + marker.setIcon(icon); + } + } + + L.contao.bindPopupFromFeature(marker, feature); + } + + this._map.fire('point:added', {marker: marker, feature: feature, latlng: latlng, type: type}); + + return marker; + }, + onEachFeature: function (feature, layer) { + if (feature.properties) { + L.Util.setOptions(layer, feature.properties.options); + + L.contao.bindPopupFromFeature(layer, feature); + + this._map.fire('feature:added', {feature: feature, layer: layer}); + } + }, + /** + * Make an ajax request. Clone of corslite from MapQuest. + */ + request: function (url, callback, cors) { + var sent = false; + + if (typeof window.XMLHttpRequest === 'undefined') { + return callback(Error('Browser not supported')); + } + + if (typeof cors === 'undefined') { + var m = url.match(/^\s*https?:\/\/[^\/]*/); + cors = m && (m[0] !== location.protocol + '//' + location.hostname + + (location.port ? ':' + location.port : '')); + } + + var x = new window.XMLHttpRequest(); + + function isSuccessful(status) { + return status >= 200 && status < 300 || status === 304; + } + + if (cors && !('withCredentials' in x)) { + // IE8-9 + x = new window.XDomainRequest(); + + // Ensure callback is never called synchronously, i.e., before + // x.send() returns (this has been observed in the wild). + // See https://github.com/mapbox/mapbox.js/issues/472 + var original = callback; + callback = function() { + if (sent) { + original.apply(this, arguments); + } else { + var that = this, args = arguments; + setTimeout(function() { + original.apply(that, args); + }, 0); + } + } + } + + function loaded() { + if ( + // XDomainRequest + x.status === undefined || + // modern browsers + isSuccessful(x.status)) callback.call(x, null, x); + else callback.call(x, x, null); + } + + // Both `onreadystatechange` and `onload` can fire. `onreadystatechange` + // has [been supported for longer](http://stackoverflow.com/a/9181508/229001). + if ('onload' in x) { + x.onload = loaded; + } else { + x.onreadystatechange = function readystate() { + if (x.readyState === 4) { + loaded(); + } + }; + } + + // Call the callback with the XMLHttpRequest object as an error and prevent + // it from ever being called again by reassigning it to `noop` + x.onerror = function error(evt) { + // XDomainRequest provides no evt parameter + callback.call(this, evt || true, null); + callback = function() { }; + }; + + // IE9 must have onprogress be set to a unique function. + x.onprogress = function() { }; + + x.ontimeout = function(evt) { + callback.call(this, evt, null); + callback = function() { }; + }; + + x.onabort = function(evt) { + callback.call(this, evt, null); + callback = function() { }; + }; + + // GET is the only supported HTTP Verb by XDomainRequest and is the + // only one supported here. + x.open('GET', url, true); + + // Send the request. Sending data is not supported. + x.send(null); + sent = true; + + return x; + } +}); diff --git a/module/config/config.php b/module/config/config.php index 7250c30..11c0100 100644 --- a/module/config/config.php +++ b/module/config/config.php @@ -280,7 +280,11 @@ $GLOBALS['LEAFLET_LAYERS'] = array } return $label; - } + }, + 'boundsMode' => array( + 'extend' => true, + 'fit' => true, + ), ), ); diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index 7f867b4..fa7710a 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -219,13 +219,11 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'overpassQuery', 'overpassEndpoint', 'minZoom', - 'overpassCallback', + 'boundsMode' ), '+expert' => array( - 'minZoomIndicatorPosition', - 'debug', - 'minZoomIndicatorMessage', - 'minZoomIndicatorMessageNoLayer', + 'onEachFeature', + 'pointToLayer', ), ), ), diff --git a/src/Netzmacht/Contao/Leaflet/Definition/Layer/OverpassLayer.php b/src/Netzmacht/Contao/Leaflet/Definition/Layer/OverpassLayer.php new file mode 100644 index 0000000..cd94ff7 --- /dev/null +++ b/src/Netzmacht/Contao/Leaflet/Definition/Layer/OverpassLayer.php @@ -0,0 +1,190 @@ + + * @copyright 2016 netzmacht David Molineus. All rights reserved. + * @filesource + * + */ + +namespace Netzmacht\Contao\Leaflet\Definition\Layer; + +use Netzmacht\JavascriptBuilder\Encoder; +use Netzmacht\JavascriptBuilder\Type\AnonymousFunction; +use Netzmacht\JavascriptBuilder\Type\ConvertsToJavascript; +use Netzmacht\JavascriptBuilder\Type\Expression; +use Netzmacht\LeafletPHP\Definition\AbstractLayer; +use Netzmacht\LeafletPHP\Definition\HasOptions; +use Netzmacht\LeafletPHP\Encoder\EncodeHelperTrait; + +/** + * Class OverpassLayer provides implementation of https://github.com/kartenkarsten/leaflet-layer-overpass. + * + * @package Netzmacht\LeafletPHP\Plugins\OverpassLayer + */ +class OverpassLayer extends AbstractLayer implements HasOptions, ConvertsToJavascript +{ + use EncodeHelperTrait; + + /** + * {@inheritdoc} + */ + public static function getType() + { + return 'OverpassLayer'; + } + + /** + * {@inheritdoc} + */ + public static function getRequiredLibraries() + { + $libs = parent::getRequiredLibraries(); + $libs[] = 'osmtogeojson'; + + return $libs; + } + + /** + * OverpassLayer constructor. + * + * @param string $identifier Indicator of the layer. + * @param array $options Options. + */ + public function __construct($identifier, array $options = []) + { + parent::__construct($identifier); + + $this->setOptions($options); + } + + /** + * Set the debug mode. + * + * @param bool $debug Debug mode. + * + * @return $this + */ + public function setDebug($debug) + { + return $this->setOption('debug', (bool) $debug); + } + + /** + * Get debug mode. + * + * @return bool + */ + public function getDebug() + { + return $this->getOption('debug', false); + } + + /** + * Set the query. + * + * @param string $query Query. + * + * @return $this + */ + public function setQuery($query) + { + return $this->setOption('query', $query); + } + + /** + * Get query. + * + * @return bool + */ + public function getQuery() + { + return $this->getOption('query', '(node(BBOX)[organic];node(BBOX)[second_hand];);out qt;'); + } + + /** + * Set the endpoint. + * + * @param string $endpoint Endpoint. + * + * @return $this + */ + public function setEndpoint($endpoint) + { + return $this->setOption('endpoint', $endpoint); + } + + /** + * Get endpoint. + * + * @return bool + */ + public function getEndpoint() + { + return $this->getOption('endpoint', '//overpass-api.de/api/'); + } + + /** + * Set point to layer function. + * + * @param Expression|AnonymousFunction $function The function callback. + * + * @return $this + */ + public function setPointToLayer($function) + { + return $this->setOption('pointToLayer', $function); + } + + /** + * Set on each feature function. + * + * @param Expression|AnonymousFunction $function The function callback. + * + * @return $this + */ + public function setOnEachFeature($function) + { + return $this->setOption('onEachFeature', $function); + } + + /** + * Set the minZoom. + * + * @param int $minZoom MinZoom. + * + * @return $this + */ + public function setMinZoom($minZoom) + { + return $this->setOption('minZoom', (int) $minZoom); + } + + /** + * Get minZoom. + * + * @return bool + */ + public function getMinZoom() + { + return $this->getOption('minZoom', 15); + } + + /** + * {@inheritdoc} + */ + public function encode(Encoder $encoder, $flags = null) + { + $buffer = sprintf ( + '%s = new L.OverPassLayer(%s)%s', + $encoder->encodeReference($this), + $encoder->encodeArray($this->getOptions(), JSON_FORCE_OBJECT), + $encoder->close($flags) + ); + + $buffer .= $this->encodeMethodCalls($this->getMethodCalls(), $encoder, $flags); + + return $buffer; + } +} diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php index afd093c..36fb44d 100644 --- a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php @@ -10,12 +10,12 @@ namespace Netzmacht\Contao\Leaflet\Mapper\Layer; +use Model; +use Netzmacht\Contao\Leaflet\Definition\Layer\OverpassLayer; use Netzmacht\Contao\Leaflet\Filter\Filter; use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper; -use Netzmacht\Contao\Leaflet\Mapper\OptionsBuilder; use Netzmacht\JavascriptBuilder\Type\Expression; use Netzmacht\LeafletPHP\Definition; -use Netzmacht\LeafletPHP\Plugins\OverpassLayer\OverpassLayer; /** * Class OverpassLayerMapper @@ -36,7 +36,7 @@ class OverpassLayerMapper extends AbstractLayerMapper * * @var string */ - protected static $definitionClass = 'Netzmacht\LeafletPHP\Plugins\OverpassLayer\OverpassLayer'; + protected static $definitionClass = 'Netzmacht\Contao\Leaflet\Definition\Layer\OverpassLayer'; /** * {@inheritdoc} @@ -47,8 +47,8 @@ class OverpassLayerMapper extends AbstractLayerMapper $this->optionsBuilder ->addOption('query', 'overpassQuery') - ->addOption('minzoom', 'minZoom') - ->addOption('debug') + ->addOption('minZoom') + ->addOption('boundsMode') ->addOption('overpassEndpoint', 'endpoint'); } @@ -57,7 +57,7 @@ class OverpassLayerMapper extends AbstractLayerMapper */ protected function build( Definition $definition, - \Model $model, + Model $model, DefinitionMapper $mapper, Filter $filter = null, Definition $parent = null @@ -66,17 +66,12 @@ class OverpassLayerMapper extends AbstractLayerMapper return; } - $minZoomIndicatorOptions = $definition->getMinZoomIndicatorOptions(); - $minZoomIndicatorOptionsBuilder = new OptionsBuilder(); - $minZoomIndicatorOptionsBuilder - ->addOption('position', 'minZoomIndicatorPosition') - ->addOption('minZoomMessageNoLayer', 'minZoomIndicatorMessageNoLayer') - ->addOption('minZoomMessage', 'minZoomIndicatorMessage'); + if ($model->pointToLayer) { + $definition->setPointToLayer(new Expression($model->pointToLayer)); + } - $minZoomIndicatorOptionsBuilder->build($minZoomIndicatorOptions, $model); - - if ($model->overpassCallback) { - $definition->setCallback(new Expression($model->overpassCallback)); + if ($model->onEachFeature) { + $definition->setOnEachFeature(new Expression($model->onEachFeature)); } } } From f462a11c1d2014269ce1eb75f61b5a2ba02f6ec3 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 11:35:09 +0100 Subject: [PATCH 08/14] Implement amenity icons mapping. --- assets/maps/contao-leaflet.js | 2 +- assets/maps/src/OverpassLayer.js | 19 +- module/config/leaflet_amenities.php | 213 ++++++++++++++++++ module/config/services.php | 3 +- module/dca/tl_leaflet_layer.php | 44 +++- .../Contao/Leaflet/Dca/LayerCallbacks.php | 34 ++- .../Mapper/Layer/OverpassLayerMapper.php | 43 ++++ 7 files changed, 344 insertions(+), 14 deletions(-) create mode 100644 module/config/leaflet_amenities.php diff --git a/assets/maps/contao-leaflet.js b/assets/maps/contao-leaflet.js index c6ac251..7770339 100644 --- a/assets/maps/contao-leaflet.js +++ b/assets/maps/contao-leaflet.js @@ -1 +1 @@ -L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===a.status||n(a.status)?o.call(a,null,a):o.call(a,a,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var r=t.match(/^\s*https?:\/\/[^\/]*/);e=r&&r[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var a=new window.XMLHttpRequest;if(e&&!("withCredentials"in a)){a=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in a?a.onload=i:a.onreadystatechange=function(){4===a.readyState&&i()},a.onerror=function(t){o.call(this,t||!0,null),o=function(){}},a.onprogress=function(){},a.ontimeout=function(t){o.call(this,t,null),o=function(){}},a.onabort=function(t){o.call(this,t,null),o=function(){}},a.open("GET",t,!0),a.send(null),s=!0,a}}); \ No newline at end of file +L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===r.status||n(r.status)?o.call(r,null,r):o.call(r,r,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var a=t.match(/^\s*https?:\/\/[^\/]*/);e=a&&a[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var r=new window.XMLHttpRequest;if(e&&!("withCredentials"in r)){r=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in r?r.onload=i:r.onreadystatechange=function(){4===r.readyState&&i()},r.onerror=function(t){o.call(this,t||!0,null),o=function(){}},r.onprogress=function(){},r.ontimeout=function(t){o.call(this,t,null),o=function(){}},r.onabort=function(t){o.call(this,t,null),o=function(){}},r.open("GET",t,!0),r.send(null),s=!0,r}}); \ No newline at end of file diff --git a/assets/maps/src/OverpassLayer.js b/assets/maps/src/OverpassLayer.js index 2018903..df909f9 100644 --- a/assets/maps/src/OverpassLayer.js +++ b/assets/maps/src/OverpassLayer.js @@ -18,7 +18,8 @@ L.OverPassLayer = L.FeatureGroup.extend({ options: { minZoom: 0, endpoint: '//overpass-api.de/api/', - query: '(node(BBOX)[organic];node(BBOX)[second_hand];);out qt;' + query: '(node(BBOX)[organic];node(BBOX)[second_hand];);out qt;', + amenityIcons: {} }, /** * Initialize the layer. @@ -87,6 +88,7 @@ L.OverPassLayer = L.FeatureGroup.extend({ }, pointToLayer: function (feature, latlng) { var type = 'marker'; + var icon = null; var marker = L.marker(latlng, feature.properties.options); if (feature.properties) { @@ -95,11 +97,18 @@ L.OverPassLayer = L.FeatureGroup.extend({ } if (feature.properties.icon) { - var icon = this._map.getIcon(feature.properties.icon); + icon = this._map.getIcon(feature.properties.icon); - if (icon) { - marker.setIcon(icon); - } + } else if (feature.properties.tags + && feature.properties.tags.amenity + && this.options.amenityIcons[feature.properties.tags.amenity] + ) { + console.log(this.options.amenityIcons[feature.properties.tags.amenity]); + icon = L.contao.getIcon(this.options.amenityIcons[feature.properties.tags.amenity]); + } + + if (icon) { + marker.setIcon(icon); } L.contao.bindPopupFromFeature(marker, feature); diff --git a/module/config/leaflet_amenities.php b/module/config/leaflet_amenities.php new file mode 100644 index 0000000..07e5210 --- /dev/null +++ b/module/config/leaflet_amenities.php @@ -0,0 +1,213 @@ + + * @copyright 2014-2016 netzmacht David Molineus + * @license LGPL 3.0 + * @filesource + * + */ + +return [ + 'administration', + 'advertising', + 'alm', + 'animal_boarding', + 'animal_breeding', + 'animal_shelter', + 'architect_office', + 'arts_centre', + 'artwork', + 'atm', + 'audiologist', + 'baby_hatch', + 'bank', + 'bar', + 'bbq', + 'bench', + 'bicycle_parking', + 'bicycle_rental', + 'bicycle_repair_station', + 'bicycle_trailer_sharing', + 'biergarten', + 'bikeshed', + 'boat_rental', + 'boat_sharing', + 'boat_storage', + 'brothel', + 'bts', + 'bureau_de_change', + 'bus_station', + 'cafe', + 'canoe_hire', + 'car_rental', + 'car_repair', + 'car_sharing', + 'car_wash', + 'casino', + 'charging_station', + 'childcare', + 'cinema', + 'citymap_post', + 'clinic', + 'clock', + 'club', + 'coast_guard', + 'coast_radar_station', + 'college', + 'community_center', + 'community_centre', + 'compressed_air', + 'concert_hall', + 'conference_centre', + 'courthouse', + 'coworking_space', + 'crematorium', + 'crucifix', + 'crypt', + 'customs', + 'dancing_school', + 'dead_pub', + 'dentist', + 'disused', + 'dive_centre', + 'doctors', + 'dog_bin', + 'dog_waste_bin', + 'dojo', + 'drinking_water', + '_driving_school', + 'education', + 'embassy', + 'emergency_phone', + 'emergency_service', + 'events_venue', + 'ev_charging', + 'exhibition_centre', + 'fast_food', + 'ferry_terminal', + 'festival_grounds', + 'financial_advice', + 'fire_hydrant', + 'fire_station', + 'first_aid', + 'fish_spa', + 'food_court', + 'fountain', + 'fuel', + 'gambling', + 'game_feeding', + 'garages', + 'grave_yard', + 'grit_bin', + 'harbourmaster', + 'hospice', + 'hospital', + 'hotel', + 'hunting_stand', + 'ice_cream', + 'internet_cafe', + 'jobcentre', + 'kindergarten', + 'kiosk', + 'kitchen', + 'Kneippbecken', + 'kneipp_water_cure', + 'language_school', + 'lavoir', + 'library', + 'lifeboat_station', + 'life_ring', + 'loading_dock', + 'love_hotel', + 'marae', + 'marketplace', + 'milk_dispenser', + 'mobile_library', + 'monastery', + 'money_transfer', + 'mortuary', + 'motorcycle_parking', + 'motorcycle_rental', + 'music_school', + 'music_venue', + 'nameplate', + 'nightclub', + 'nursery', + 'nursing_home', + 'park', + 'parking', + 'parking_entrance', + 'parking_space', + 'pharmacy', + 'photo_booth', + 'place_of_worship', + 'planetarium', + 'police', + 'post_box', + 'post_office', + 'preschool', + 'printer', + 'prison', + 'prison_camp', + 'proposed', + 'pub', + 'public_bath', + 'public_bookcase', + 'public_building', + 'public_hall', + 'ranger_station', + 'recycling', + 'refugee_housing', + 'register_office', + 'rescue_box', + 'rescue_station', + 'research_institute', + 'restaurant', + 'retirement_home', + 'sanatorium', + 'sanitary_dump_station', + 'sauna', + 'school', + 'scout_hut', + 'shelter', + 'shop', + 'shower', + 'ski_school', + 'smoking_area', + 'social_centre', + 'social_facility', + 'spa', + 'stables', + 'stripclub', + 'studio', + 'swimming_pool', + 'swingerclub', + 'table', + 'taxi', + 'telephone', + 'theatre', + 'ticket_booth', + 'ticket_validator', + 'toilets', + 'townhall', + 'trolley_bay', + 'university', + 'vacuum_cleaner', + 'vehicle_inspection', + 'vending_machine', + 'veterinary', + 'vivarium', + 'wash_center', + 'waste_basket', + 'waste_disposal', + 'waste_transfer_station', + 'water', + 'watering_place', + 'water_point', + 'weighbridge', + 'winery', + 'yacht_club', + 'youth_centre', +]; diff --git a/module/config/services.php b/module/config/services.php index 56c5585..8ed2ab0 100644 --- a/module/config/services.php +++ b/module/config/services.php @@ -242,7 +242,8 @@ $container['leaflet.dca.layer-callbacks'] = $container->share( $container[Services::DATABASE_CONNECTION], $container[Services::TRANSLATOR], $GLOBALS['LEAFLET_LAYERS'], - $GLOBALS['LEAFLET_TILE_PROVIDERS'] + $GLOBALS['LEAFLET_TILE_PROVIDERS'], + require TL_ROOT . '/system/modules/leaflet/config/leaflet_amenities.php' ); } ); diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index fa7710a..fd9f175 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -153,6 +153,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'default' => array( 'title' => array('title', 'alias', 'type'), 'config' => array(), + 'style' => array(), 'expert' => array(':hide'), 'active' => array('active'), ), @@ -217,9 +218,12 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'overpass extends default' => array( 'config' => array( 'overpassQuery', - 'overpassEndpoint', + 'boundsMode', 'minZoom', - 'boundsMode' + 'overpassEndpoint', + ), + 'style' => array( + 'amenityIcons' ), '+expert' => array( 'onEachFeature', @@ -871,5 +875,41 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'eval' => array('tl_class' => 'w50 m12'), 'sql' => "char(1) NOT NULL default ''" ), + 'amenityIcons' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_marker']['icon'], + 'exclude' => true, + 'inputType' => 'multiColumnWizard', + 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\MarkerCallbacks', 'getIcons'), + 'eval' => array( + 'columnFields' => array( + 'amenity' => array( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_marker']['icon'], + 'exclude' => true, + 'inputType' => 'select', + 'options_callback' => \Netzmacht\Contao\Leaflet\Dca\LayerCallbacks::callback('getAmenities'), + 'eval' => array( + 'mandatory' => true, + 'tl_class' => 'w50', + 'style' => 'width: 200px', + 'chosen' => true, + ), + ), + 'icon' => array( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_marker']['icon'], + 'exclude' => true, + 'inputType' => 'select', + 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\MarkerCallbacks', 'getIcons'), + 'eval' => array( + 'mandatory' => true, + 'tl_class' => 'w50', + 'style' => 'width: 200px', + 'chosen' => true, + ), + ), + ), + ), + 'sql' => "blob NULL", + ), ) ); diff --git a/src/Netzmacht/Contao/Leaflet/Dca/LayerCallbacks.php b/src/Netzmacht/Contao/Leaflet/Dca/LayerCallbacks.php index 402985c..727a474 100644 --- a/src/Netzmacht/Contao/Leaflet/Dca/LayerCallbacks.php +++ b/src/Netzmacht/Contao/Leaflet/Dca/LayerCallbacks.php @@ -66,6 +66,17 @@ class LayerCallbacks extends Callbacks */ private $translator; + /** + * OSM amenities. + * + * @var array + */ + private $amenities; + /** + * @var Manager + */ + private $manager; + /** * Construct. * @@ -74,23 +85,26 @@ class LayerCallbacks extends Callbacks * @param Translator $translator Translator. * @param array $layers Leaflet layer configuration. * @param array $tileProviders Tile providers. + * @param array $amenities OSM amenities */ public function __construct( Manager $manager, \Database $database, Translator $translator, array $layers, - array $tileProviders + array $tileProviders, + array $amenities ) { parent::__construct($manager); + \Controller::loadLanguageFile('leaflet_layer'); + $this->database = $database; $this->layers = $layers; $this->tileProviders = $tileProviders; - - \Controller::loadLanguageFile('leaflet_layer'); - - $this->translator = $translator; + $this->manager = $manager; + $this->translator = $translator; + $this->amenities = $amenities; } /** @@ -359,6 +373,16 @@ class LayerCallbacks extends Callbacks ->getOptions(); } + /** + * Get all know osm amenities as options. + * + * @return array + */ + public function getAmenities() + { + return $this->amenities; + } + /** * Generate a button. * diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php index 36fb44d..398c354 100644 --- a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php @@ -14,6 +14,7 @@ use Model; use Netzmacht\Contao\Leaflet\Definition\Layer\OverpassLayer; use Netzmacht\Contao\Leaflet\Filter\Filter; use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper; +use Netzmacht\Contao\Leaflet\Model\IconModel; use Netzmacht\JavascriptBuilder\Type\Expression; use Netzmacht\LeafletPHP\Definition; @@ -66,6 +67,9 @@ class OverpassLayerMapper extends AbstractLayerMapper return; } + $amenityIconsMap = $this->buildAmenityIconsMap($model); + $definition->setOption('amenityIcons', $amenityIconsMap); + if ($model->pointToLayer) { $definition->setPointToLayer(new Expression($model->pointToLayer)); } @@ -74,4 +78,43 @@ class OverpassLayerMapper extends AbstractLayerMapper $definition->setOnEachFeature(new Expression($model->onEachFeature)); } } + + /** + * Build the amenity icons map. + * + * @param Model $model Definition model. + * + * @return array + */ + protected function buildAmenityIconsMap(Model $model) + { + $amenityIconsConfig = deserialize($model->amenityIcons, true); + $amenityIconsMap = []; + foreach ($amenityIconsConfig as $config) { + if (!$config['amenity'] || !$config['icon']) { + continue; + } + + $amenityIconsMap[$config['amenity']] = $config['icon']; + } + + if ($amenityIconsMap) { + $collection = IconModel::findMultipleByIds(array_unique($amenityIconsMap)); + $icons = []; + + if ($collection) { + foreach ($collection as $iconModel) { + $icons[$iconModel->id] = $iconModel->alias ?: $iconModel->id; + } + + foreach ($amenityIconsMap as $amenity => $iconId) { + if (isset($icons[$iconId])) { + $amenityIconsMap[$amenity] = $icons[$iconId]; + } + } + } + } + + return $amenityIconsMap; + } } From cb370f67230068f5aa3601951eee2fc8c882c6e4 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 11:50:20 +0100 Subject: [PATCH 09/14] Support popups. --- assets/maps/contao-leaflet.js | 2 +- assets/maps/src/OverpassLayer.js | 8 ++++++-- module/dca/tl_leaflet_layer.php | 15 +++++++++++++++ .../Leaflet/Mapper/Layer/OverpassLayerMapper.php | 4 ++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/assets/maps/contao-leaflet.js b/assets/maps/contao-leaflet.js index 7770339..2d42c8e 100644 --- a/assets/maps/contao-leaflet.js +++ b/assets/maps/contao-leaflet.js @@ -1 +1 @@ -L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===r.status||n(r.status)?o.call(r,null,r):o.call(r,r,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var a=t.match(/^\s*https?:\/\/[^\/]*/);e=a&&a[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var r=new window.XMLHttpRequest;if(e&&!("withCredentials"in r)){r=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in r?r.onload=i:r.onreadystatechange=function(){4===r.readyState&&i()},r.onerror=function(t){o.call(this,t||!0,null),o=function(){}},r.onprogress=function(){},r.ontimeout=function(t){o.call(this,t,null),o=function(){}},r.onabort=function(t){o.call(this,t,null),o=function(){}},r.open("GET",t,!0),r.send(null),s=!0,r}}); \ No newline at end of file +L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===r.status||n(r.status)?o.call(r,null,r):o.call(r,r,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var a=t.match(/^\s*https?:\/\/[^\/]*/);e=a&&a[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var r=new window.XMLHttpRequest;if(e&&!("withCredentials"in r)){r=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in r?r.onload=i:r.onreadystatechange=function(){4===r.readyState&&i()},r.onerror=function(t){o.call(this,t||!0,null),o=function(){}},r.onprogress=function(){},r.ontimeout=function(t){o.call(this,t,null),o=function(){}},r.onabort=function(t){o.call(this,t,null),o=function(){}},r.open("GET",t,!0),r.send(null),s=!0,r}}); \ No newline at end of file diff --git a/assets/maps/src/OverpassLayer.js b/assets/maps/src/OverpassLayer.js index df909f9..9eaf599 100644 --- a/assets/maps/src/OverpassLayer.js +++ b/assets/maps/src/OverpassLayer.js @@ -110,8 +110,10 @@ L.OverPassLayer = L.FeatureGroup.extend({ if (icon) { marker.setIcon(icon); } + } - L.contao.bindPopupFromFeature(marker, feature); + if (this.options.overpassPopup) { + marker.bindPopup(this.options.overpassPopup(feature, marker)); } this._map.fire('point:added', {marker: marker, feature: feature, latlng: latlng, type: type}); @@ -122,7 +124,9 @@ L.OverPassLayer = L.FeatureGroup.extend({ if (feature.properties) { L.Util.setOptions(layer, feature.properties.options); - L.contao.bindPopupFromFeature(layer, feature); + if (this.options.overpassPopup) { + layer.bindPopup(this.options.overpassPopup(feature, layer)); + } this._map.fire('feature:added', {feature: feature, layer: layer}); } diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index fd9f175..9082c3f 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -221,6 +221,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'boundsMode', 'minZoom', 'overpassEndpoint', + 'overpassPopup' ), 'style' => array( 'amenityIcons' @@ -911,5 +912,19 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array ), 'sql' => "blob NULL", ), + 'overpassPopup' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['overpassPopup'], + 'exclude' => true, + 'inputType' => 'textarea', + 'eval' => array( + 'preserveTags' => true, + 'decodeEntities' => true, + 'allowHtml' => true, + 'rte' => 'ace|javascript', + 'tl_class' => 'clr' + ), + 'sql' => "mediumtext NULL" + ), ) ); diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php index 398c354..95ccca8 100644 --- a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/OverpassLayerMapper.php @@ -77,6 +77,10 @@ class OverpassLayerMapper extends AbstractLayerMapper if ($model->onEachFeature) { $definition->setOnEachFeature(new Expression($model->onEachFeature)); } + + if ($model->overpassPopup) { + $definition->setOption('overpassPopup', new Expression($model->overpassPopup)); + } } /** From 3f05bd8783ad288ed9fc3da9cc3759f7cd6fc136 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 13:30:38 +0100 Subject: [PATCH 10/14] Load icon stylesheets dynamically. --- .../Leaflet/Subscriber/BootSubscriber.php | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php b/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php index 2f4aaed..57b5cb7 100644 --- a/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php +++ b/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php @@ -24,7 +24,6 @@ use Netzmacht\Contao\Leaflet\Mapper\Mapper; use Netzmacht\Contao\Leaflet\Model\IconModel; use Netzmacht\Contao\Toolkit\Boot\Event\InitializeSystemEvent; use Netzmacht\Contao\Toolkit\DependencyInjection\Services; -use Netzmacht\Contao\Toolkit\View\Assets\AssetsManager; use Netzmacht\LeafletPHP\Assets; use Netzmacht\LeafletPHP\Definition\Type\ImageIcon; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -101,7 +100,7 @@ class BootSubscriber implements EventSubscriberInterface InitializeDefinitionMapperEvent::NAME => 'initializeDefinitionMapper', InitializeEventDispatcherEvent::NAME => 'initializeEventDispatcher', InitializeLeafletBuilderEvent::NAME => 'initializeLeafletBuilder', - GetJavascriptEvent::NAME => array(array('loadAssets'), array('loadIcons')), + GetJavascriptEvent::NAME => array(array('loadIcons'), array('loadAssets')), ); } @@ -190,6 +189,7 @@ class BootSubscriber implements EventSubscriberInterface public function loadAssets() { $this->assets->addJavascript('assets/leaflet/maps/contao-leaflet.js', ContaoAssets::TYPE_FILE); + $this->assets->addJavascript('assets/leaflet/js/icons.js', ContaoAssets::TYPE_FILE); } /** @@ -217,20 +217,37 @@ class BootSubscriber implements EventSubscriberInterface 'type' => lcfirst($icon->getType()), 'options' => $icon->getOptions(), ); + + foreach ($icon::getRequiredLibraries() as $library) { + if (!isset($this->libraries[$library])) { + continue; + } + + $assets = $this->libraries[$library]; + + if (!empty($assets['css'])) { + list ($source, $type) = (array) $assets['css']; + $this->assets->addStylesheet($source, $type ?: Assets::TYPE_FILE); + } + + if (!empty($assets['javascript'])) { + list ($source, $type) = (array) $assets['javascript']; + $this->assets->addJavascript($source, $type ?: Assets::TYPE_FILE); + } + } } if ($icons) { $buffer = sprintf('L.contao.loadIcons(%s);', json_encode($icons)); } - $file = new \File('assets/leaflet/js/icons.js'); - $file->write($buffer); - $file->close(); - // @codingStandardsIgnoreStart // TODO: Cache it. // codingStandardsIgnoreEnd - $this->assets->addJavascript('assets/leaflet/js/icons.js', ContaoAssets::TYPE_FILE); + + $file = new \File('assets/leaflet/js/icons.js'); + $file->write($buffer); + $file->close(); } } From d95f45d35ace7c464cbe94d6d5abdfd2702add05 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 13:31:19 +0100 Subject: [PATCH 11/14] Implement the extra markers icons. --- assets/maps/contao-leaflet.js | 2 +- assets/maps/src/Contao.js | 9 +- assets/maps/src/OverpassLayer.js | 1 - module/config/config.php | 3 +- module/dca/tl_leaflet_icon.php | 93 ++++++++++++++++++- .../Mapper/Type/ExtraMarkersIconMapper.php | 66 +++++++++++++ 6 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 src/Netzmacht/Contao/Leaflet/Mapper/Type/ExtraMarkersIconMapper.php diff --git a/assets/maps/contao-leaflet.js b/assets/maps/contao-leaflet.js index 2d42c8e..68b2814 100644 --- a/assets/maps/contao-leaflet.js +++ b/assets/maps/contao-leaflet.js @@ -1 +1 @@ -L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===r.status||n(r.status)?o.call(r,null,r):o.call(r,r,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var a=t.match(/^\s*https?:\/\/[^\/]*/);e=a&&a[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var r=new window.XMLHttpRequest;if(e&&!("withCredentials"in r)){r=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in r?r.onload=i:r.onreadystatechange=function(){4===r.readyState&&i()},r.onerror=function(t){o.call(this,t||!0,null),o=function(){}},r.onprogress=function(){},r.ontimeout=function(t){o.call(this,t,null),o=function(){}},r.onabort=function(t){o.call(this,t,null),o=function(){}},r.open("GET",t,!0),r.send(null),s=!0,r}}); \ No newline at end of file +L.Contao=L.Class.extend({includes:L.Mixin.Events,statics:{ATTRIBUTION:' | netzmacht'},maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images/",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,o){return this.maps[t]=o,this.fire("map:added",{id:t,map:o}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,o){return this.icons[t]=o,this.fire("icon:added",{id:t,icon:o}),this},loadIcons:function(t){for(var o=0;o=200&&t<300||304===t}function i(){void 0===a.status||n(a.status)?o.call(a,null,a):o.call(a,a,null)}var s=!1;if("undefined"==typeof window.XMLHttpRequest)return o(Error("Browser not supported"));if("undefined"==typeof e){var r=t.match(/^\s*https?:\/\/[^\/]*/);e=r&&r[0]!==location.protocol+"//"+location.hostname+(location.port?":"+location.port:"")}var a=new window.XMLHttpRequest;if(e&&!("withCredentials"in a)){a=new window.XDomainRequest;var p=o;o=function(){if(s)p.apply(this,arguments);else{var t=this,o=arguments;setTimeout(function(){p.apply(t,o)},0)}}}return"onload"in a?a.onload=i:a.onreadystatechange=function(){4===a.readyState&&i()},a.onerror=function(t){o.call(this,t||!0,null),o=function(){}},a.onprogress=function(){},a.ontimeout=function(t){o.call(this,t,null),o=function(){}},a.onabort=function(t){o.call(this,t,null),o=function(){}},a.open("GET",t,!0),a.send(null),s=!0,a}}); \ No newline at end of file diff --git a/assets/maps/src/Contao.js b/assets/maps/src/Contao.js index 243addd..5912337 100644 --- a/assets/maps/src/Contao.js +++ b/assets/maps/src/Contao.js @@ -89,7 +89,14 @@ L.Contao = L.Class.extend({ */ loadIcons: function (icons) { for (var i = 0; i < icons.length; i++) { - var icon = L[icons[i].type](icons[i].options); + var icon; + + if (icons[i].type === 'extraMarkers.icon') { + icon = L.ExtraMarkers.icon(icons[i].options); + } else { + icon = L[icons[i].type](icons[i].options); + } + this.addIcon(icons[i].id, icon); } }, diff --git a/assets/maps/src/OverpassLayer.js b/assets/maps/src/OverpassLayer.js index 9eaf599..dbba683 100644 --- a/assets/maps/src/OverpassLayer.js +++ b/assets/maps/src/OverpassLayer.js @@ -103,7 +103,6 @@ L.OverPassLayer = L.FeatureGroup.extend({ && feature.properties.tags.amenity && this.options.amenityIcons[feature.properties.tags.amenity] ) { - console.log(this.options.amenityIcons[feature.properties.tags.amenity]); icon = L.contao.getIcon(this.options.amenityIcons[feature.properties.tags.amenity]); } diff --git a/module/config/config.php b/module/config/config.php index 11c0100..f729f1b 100644 --- a/module/config/config.php +++ b/module/config/config.php @@ -154,6 +154,7 @@ $GLOBALS['LEAFLET_MAPPERS'][] = function () { $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\UI\PopupMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Type\ImageIconMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Type\DivIconMapper'; +$GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Type\ExtraMarkersIconMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\Style\FixedStyleMapper'; $GLOBALS['LEAFLET_MAPPERS'][] = function () { return new \Netzmacht\Contao\Leaflet\Mapper\UI\MarkerMapper( @@ -301,7 +302,7 @@ $GLOBALS['LEAFLET_CONTROLS'] = array('zoom', 'layers', 'scale', 'attribution', * * Supported leaflet icon types. Register you type for the database driven definition here. */ -$GLOBALS['LEAFLET_ICONS'] = array('image', 'div'); +$GLOBALS['LEAFLET_ICONS'] = array('image', 'div', 'extra'); /* diff --git a/module/dca/tl_leaflet_icon.php b/module/dca/tl_leaflet_icon.php index ad7659a..e1c61f6 100644 --- a/module/dca/tl_leaflet_icon.php +++ b/module/dca/tl_leaflet_icon.php @@ -150,7 +150,21 @@ $GLOBALS['TL_DCA']['tl_leaflet_icon'] = array 'active' => array( 'active' ) - ) + ), + + 'extra extends default' => array( + 'config' => array( + 'icon', + 'prefix', + 'shape', + 'markerColor', + 'number', + 'iconColor', + ), + 'active' => array( + 'active' + ) + ), ), 'fields' => array @@ -351,5 +365,82 @@ $GLOBALS['TL_DCA']['tl_leaflet_icon'] = array ), 'sql' => "mediumtext NULL" ), + 'icon' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_icon']['icon'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => array( + 'maxlength' => 64, + 'tl_class' => 'w50', + 'nullIfEmpty' => true, + ), + 'sql' => "varchar(64) NULL" + ), + 'prefix' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_icon']['prefix'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => array( + 'maxlength' => 64, + 'tl_class' => 'w50', + 'nullIfEmpty' => true, + ), + 'sql' => "varchar(64) NULL" + ), + 'shape' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_icon']['shape'], + 'exclude' => true, + 'inputType' => 'select', + 'default' => 'circle', + 'options' => ['circle', 'square', 'star', 'penta'], + 'eval' => array( + 'tl_class' => 'w50', + ), + 'sql' => "varchar(64) NULL" + ), + 'iconColor' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_icon']['iconColor'], + 'exclude' => true, + 'inputType' => 'text', + 'eval' => array( + 'maxlength' => 64, + 'tl_class' => 'w50', + 'nullIfEmpty' => true, + ), + 'sql' => "varchar(16) NULL" + ), + 'markerColor' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_icon']['markerColor'], + 'exclude' => true, + 'inputType' => 'select', + 'default' => 'circle', + 'options' => [ + 'blue', + 'red', + 'orange-dark', + 'orange', + 'yellow', + 'blue-dark', + 'cyan', + 'purple', + 'violet', + 'pink', + 'green-dark', + 'green', + 'green-light', + 'black', + 'white' + ], + 'eval' => array( + 'tl_class' => 'w50', + 'nullIfEmpty' => true, + ), + 'sql' => "varchar(16) NULL" + ), ), ); diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Type/ExtraMarkersIconMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Type/ExtraMarkersIconMapper.php new file mode 100644 index 0000000..a78aed7 --- /dev/null +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Type/ExtraMarkersIconMapper.php @@ -0,0 +1,66 @@ + + * @copyright 2014-2016 netzmacht David Molineus + * @license LGPL 3.0 + * @filesource + * + */ + +namespace Netzmacht\Contao\Leaflet\Mapper\Type; + +use Netzmacht\Contao\Leaflet\Filter\Filter; +use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper; +use Netzmacht\LeafletPHP\Definition; +use Netzmacht\LeafletPHP\Definition\Type\DivIcon; + +/** + * Class DivIconMapper maps the icon model to the div icon definition. + * + * @package Netzmacht\Contao\Leaflet\Mapper\Type + */ +class ExtraMarkersIconMapper extends AbstractIconMapper +{ + /** + * Class of the definition being created. + * + * @var string + */ + protected static $definitionClass = 'Netzmacht\LeafletPHP\Plugins\ExtraMarkers\ExtraMarkersIcon'; + + /** + * Layer type. + * + * @var string + */ + protected static $type = 'extra'; + + /** + * {@inheritdoc} + */ + protected function initialize() + { + parent::initialize(); + + $this->optionsBuilder->addOptions(['icon', 'iconColor', 'markerColor', 'shape', 'number', 'prefix']); + } + + /** + * {@inheritdoc} + */ + protected function build( + Definition $definition, + \Model $model, + DefinitionMapper $mapper, + Filter $filter = null, + Definition $parent = null + ) { + parent::build($definition, $model, $mapper, $filter); + + if ($definition instanceof DivIcon && $model->iconSize) { + $definition->setIconSize(explode(',', $model->iconSize, 2)); + } + } +} From 5cf75b76b73e95a889c422d69f85df38ea8f28ca Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 13:36:32 +0100 Subject: [PATCH 12/14] Add the color picker. --- module/dca/tl_leaflet_icon.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module/dca/tl_leaflet_icon.php b/module/dca/tl_leaflet_icon.php index e1c61f6..b9ef4fc 100644 --- a/module/dca/tl_leaflet_icon.php +++ b/module/dca/tl_leaflet_icon.php @@ -406,9 +406,12 @@ $GLOBALS['TL_DCA']['tl_leaflet_icon'] = array 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_icon']['iconColor'], 'exclude' => true, 'inputType' => 'text', + 'wizard' => array( + \Netzmacht\Contao\Toolkit\Dca\Callback\CallbackFactory::colorPicker() + ), 'eval' => array( 'maxlength' => 64, - 'tl_class' => 'w50', + 'tl_class' => 'w50 wizard', 'nullIfEmpty' => true, ), 'sql' => "varchar(16) NULL" From 324e65e2172c92574505bfa0ba759176c2bf194d Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 13:37:03 +0100 Subject: [PATCH 13/14] Translate new icon options. --- module/languages/en/tl_leaflet_icon.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/module/languages/en/tl_leaflet_icon.php b/module/languages/en/tl_leaflet_icon.php index 3c3fce2..cd63188 100644 --- a/module/languages/en/tl_leaflet_icon.php +++ b/module/languages/en/tl_leaflet_icon.php @@ -52,3 +52,13 @@ $GLOBALS['TL_LANG']['tl_leaflet_icon']['active'][0] = 'Activate the i $GLOBALS['TL_LANG']['tl_leaflet_icon']['active'][1] = 'Activate the icon.'; $GLOBALS['TL_LANG']['tl_leaflet_icon']['className'][0] = 'Class name'; $GLOBALS['TL_LANG']['tl_leaflet_icon']['className'][1] = 'A custom class name to assign to both icon and shadow images. Empty by default.'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['icon'][0] = 'Icon CSS class'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['icon'][1] = 'Icon CCS class, e.g fa-envelope'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['prefix'][0] = 'Icon prefix class'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['prefix'][1] = 'Icon prefix class, e.g fa'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['shape'][0] = 'Marker shape'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['shape'][1] = 'The shape of the marker'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['markerColor'][0] = 'marker color'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['markerColor'][1] = 'Choose a predefined color of the marker.'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['iconColor'][0] = 'Icon color'; +$GLOBALS['TL_LANG']['tl_leaflet_icon']['iconColor'][1] = 'Define a custom icon color here.'; From 9f950b0f31b0cb66a714738e35c6f4027d63f86e Mon Sep 17 00:00:00 2001 From: David Molineus Date: Mon, 14 Nov 2016 13:45:30 +0100 Subject: [PATCH 14/14] Add translations for overpass layer. --- module/dca/tl_leaflet_layer.php | 6 +++--- module/languages/en/leaflet.php | 2 ++ module/languages/en/tl_leaflet_layer.php | 14 +++++++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index 9082c3f..bd36502 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -878,14 +878,14 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array ), 'amenityIcons' => array ( - 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_marker']['icon'], + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['amenityIcons'], 'exclude' => true, 'inputType' => 'multiColumnWizard', 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\MarkerCallbacks', 'getIcons'), 'eval' => array( 'columnFields' => array( 'amenity' => array( - 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_marker']['icon'], + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['amenity'], 'exclude' => true, 'inputType' => 'select', 'options_callback' => \Netzmacht\Contao\Leaflet\Dca\LayerCallbacks::callback('getAmenities'), @@ -897,7 +897,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array ), ), 'icon' => array( - 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_marker']['icon'], + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['amenityIcon'], 'exclude' => true, 'inputType' => 'select', 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\MarkerCallbacks', 'getIcons'), diff --git a/module/languages/en/leaflet.php b/module/languages/en/leaflet.php index 9285a61..bcd3324 100644 --- a/module/languages/en/leaflet.php +++ b/module/languages/en/leaflet.php @@ -27,6 +27,8 @@ $GLOBALS['TL_LANG']['leaflet_layer']['markercluster'][0] = 'Marker cluster'; $GLOBALS['TL_LANG']['leaflet_layer']['markercluster'][1] = 'Marker cluster layer based on Leaflet.markercluster