toubiz-map
=
https://newland.atlassian.net/wiki/spaces/TBMAP/pages/116883564/Version+1.0.0
https://newland.atlassian.net/wiki/spaces/TBMAP/pages/197361700/Anforderungen+1.1.0

Based on https://github.com/nimius/location-manager

@todo Add description

### Installation

```
npm install @nimius/toubiz-map
```

### How to use

#### Getting started
Import ToubizMap Module

```
import ToubizMap from 'PATH_TO/toubiz-map'
```

On page load, load google maps api (for example using `google-maps-api-loader`) and initialize the map afterwards

```
import GoogleMapsApiLoader from 'google-maps-api-loader'
import { onPageLoadComplete } from '@nimius/event-utility'

onPageLoadComplete(() => {
    GoogleMapsApiLoader({
        libraries: ['places'],
        apiKey: 'APIKEY'
    })
    .then(google => {
    	// initialize map here
    }, error => {
    	console.error(error)
    })
})
```

Prepare the markup for the map (map will be rendered in the specified mapContainer, which is either a selector like in the example below, or the actual node itself)

```
<div data-toubiz-map><div>
```

Initialize a new map instance, passing options (example with default settings below)

```
const options = {
    // custom map style object
    style: null,

    // selectors which will be used when parsing the markup and for attaching event listeners
    selectors: {
        map: '[data-toubiz-map]',
        marker: '[data-toubiz-location]',
        markerContent: '[data-toubiz-location-content]',
        category: '[data-toubiz-map-category]',
        categoryGroup: '[data-toubiz-map-category-group]',
        menuItem: '[data-toubiz-map-menu-item]'
    },

    // attributes to look for when parsing the markup
    dataAttributes: {
        map: {
            lat: 'data-toubiz-map-lat',
            lng: 'data-toubiz-map-lng',
            clusterIcon: 'data-toubiz-map-cluster-icon',
            markerIcon: 'data-toubiz-map-marker-icon',
            type: 'data-toubiz-map-type'
        },
        group: {
            id: 'data-toubiz-map-category-group',
            title: 'data-toubiz-map-category-group-title',
            icon: 'data-toubiz-map-category-group-icon'
        },
        category: {
            id: 'data-toubiz-map-category',
            group: 'data-toubiz-map-category-group',
            title: 'data-toubiz-map-category-title',
            icon: 'data-toubiz-map-category-icon',
            menuTitle: 'data-toubiz-map-category-menu-title',
            menuIconOpen: 'data-toubiz-map-category-menu-icon-open',
            menuIconClose: 'data-toubiz-map-category-menu-icon-close',
            menuIconExpand: 'data-toubiz-map-category-menu-icon-expand',
            menuIconSelectAll: 'data-toubiz-map-category-menu-icon-select-all',
            selectAllLabel: 'data-toubiz-map-category-menu-select-all-label'
        },
        marker: {
            lat: 'data-toubiz-location-lat',
            lng: 'data-toubiz-location-lng',
            icon: 'data-toubiz-location-icon',
            category: 'data-toubiz-location-category',
            title: 'data-toubiz-location-title'
        }
    },

    // default labels to display (will be overwritten by those configured via markup)
    labels: {
        categoryMenu: {
            title: 'Categories',
            selectAllLabel: 'All places'
        }
    },

    // default icons to display (will be overwritten by those configured via markup)
    icons: {
        categoryMenu: {
            open: 'bars',
            close: 'times',
            expand: 'angle-down',
            selectAll: 'map-marker'
        }
    },

    // options passed to the maps constructor
    mapOptions: {
        center: {
            lat: 47.920130,
            lng: 7.705250
        },
        zoom: 10,
        mapTypeId: 'roadmap',
        zoomControlOptions: {
            position: google.maps.ControlPosition.RIGHT_BOTTOM
        }
    },

    // options passed to the markerclusterer constructor
    clusterer: {
        gridSize: 60,
        zoomOnClick: true,
        styles: [{
            url: './Cluster.png',
            width: 32,
            height: 32,
            textColor: '#fff',
            textSize: 14
        }]
    },

    // default marker URL
    marker: {
        iconUrl: './Marker.png'
    },

    // log debug information
    debug: false,

    // center map on markers
    centerOnMarkers: false
}

let mapInstance = new ToubizMap(options)
```

The following data attributes are available for configuring the map via markup:

- `data-toubiz-map-lat`: Optional. Map center latitude
- `data-toubiz-map-lng`: Optional. Map center longitude
- `data-toubiz-map-cluster-icon`: Optional. Path to custom cluster icon
- `data-toubiz-map-marker-icon`: Optional. Path to custom marker icon
- `data-toubiz-map-type`: Optional. Map overlay type (`roadmap` (default) || `hybrid` || `terrain` || `satellite` || `openstreetmap`)
- `data-toubiz-map-category-menu-title`: Optional. Title shown for category menu (e.g. `Kategorie wählen`)
- `data-toubiz-map-category-menu-title`: Optional. Label shown for select-all-categories button in category menu (e.g. `Alle Orte`)

#### Adding markers
Add markers via markup and use the following available data-attributes:

- `data-toubiz-location-lat`: Required. Latitude
- `data-toubiz-location-lng`: Required. Longitute
- `data-toubiz-location-category`: Optional. Category to be associated with this marker (unique String/ID)
- `data-toubiz-location-title`: Optional. Give a title directly to the map marker (usually not needed)
- `data-toubiz-location-icon`: Optional. If a certain location requires a custom marker icon, add the path to the marker image here

```
<div data-toubiz-map>
    <div data-toubiz-location
         data-toubiz-location-category="hiking-tour"
         data-toubiz-location-lat="47.920130"
         data-toubiz-location-lng="7.705250">
    </div>
    [...]
</div>
```

Adding info windows (that open when clicking on the marker icon) is similar, just add markup like below within `data-toubiz-location`. The HTML within an element flagged by `data-toubiz-location-content` will be rendered inside the info window.

```
<div data-toubiz-map>
    <div data-toubiz-location
         data-toubiz-location-category="hiking-tour"
         data-toubiz-location-lat="47.920130"
         data-toubiz-location-lng="7.705250">

        <div data-toubiz-location-content>
            <h2>Info Window</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsam asperiores repellendus hic, deserunt maxime, delectus dolore saepe laudantium voluptatem aliquam alias error iure ab ut. Error, sequi excepturi quasi laborum!</p>
        </div>
    </div>
    [...]
</div>
```

#### Adding (grouped) categories
Map locations can be associated with categories for filtering markers via the category menu. Categories can be configured on the root level of `data-toubiz-map` like in the following example. Use these attributes for settings:

- `data-toubiz-map-category`: category id (unique string)
- `data-toubiz-map-category-title`: Optional but recommended. Title to be shown for this category in the category menu.
- `data-toubiz-map-category-icon`: Optional but recommended. Icon to be shown for this category in the category menu.
- `data-toubiz-map-category-group`: Optional. Add a group id here to associate this category with a category group.

```
<div data-toubiz-map-category="categoryA"
     data-toubiz-map-category-title="Kategorie A"
     data-toubiz-map-category-icon="plane"
     data-toubiz-map-category-group="groupA">
</div>
```

Configure category groups with these attributes:
- `data-toubiz-map-category-group`: group id (unique string)
- `data-toubiz-map-category-group-title`: Optional but recommended. Title to be shown for this group in the category menu.
- `data-toubiz-map-category-group-icon`: Optional but recommended. Icon to be shown for this group in the category menu.

#### Applying custom map style
To apply a custom map style configuration, e.g. from https://snazzymaps.com/ or https://mapstyle.withgoogle.com, pass them as property `style` in the ToubizMap options. A map style example can be found in `example/map-style.json`.

If you apply a custom map style, the setting for map type will not take effect.

#### Setting the map type
Add data attribute `data-toubiz-map-type` to use one of the common settings `roadmap`, `satellite`, `hybrid` or `terrain` or set it to `openstreetmap` to activate open street map layer.

### Workflows

Start styleguide to see components:

```
npm start
```

Generate documentation using jsdoc (Can be configured via `jsdoc.json`).

```
npm run docs
```


### Todo/Roadmap

- Improve default marker clusterer image assignment in MarkerClusterer?
- Add fallback to default google maps markers?
