# `Rover.Marker`
[🔗](https://github.com/nseaSeb/rover/blob/v0.4.0/lib/rover/marker.ex#L1)

A point on the map.

You rarely build one by hand. `Rover.Components.map/1` runs every entry of its
`markers` list through `new!/1`, so plain maps and your own Ecto schemas work
as-is provided they carry an id and a coordinate:

    %{id: 1, lat: 45.75, lon: 4.85, label: "Lyon"}
    %Client{id: 1, latitude: 45.75, longitude: 4.85, name: "Lyon"}

For the second form, tell Rover which fields to read:

    Rover.Marker.new!(client, lat: :latitude, lon: :longitude, label: :name)

## Fields

| Field | Type | Meaning |
|---|---|---|
| `:id` | term | **Required.** Stable identity used to diff the map. |
| `:lat` / `:lon` | float | **Required.** See `Rover.Geo`. |
| `:label` | string | Text drawn next to the marker. |
| `:color` | string | CSS colour of the default pin, e.g. `"#e11d48"`. |
| `:emoji` | string | An emoji drawn in place of the pin, e.g. `"🏠"`. |
| `:icon` | string | URL of an image to use instead of the default pin. |
| `:scale` | float | Size multiplier applied to the pin or icon. |
| `:tooltip` | string | Shown on hover. Defaults to `:label`. |
| `:draggable` | boolean | Lets the user move the marker (see `on_marker_drag_end`). |
| `:data` | map | Echoed back verbatim in marker events. |

The identity is `:id`. Changing anything else updates that marker in place;
changing the id removes one marker and adds another.

> #### Ids travel through JSON {: .warning}
>
> Integers and strings round-trip unchanged, so an event handler matching on
> `%{"id" => 1}` works. **Atoms do not**: `:depot` is delivered back as
> `"depot"`, and a handler matching `id == :depot` will never fire. Use
> integers or strings for ids you intend to match on.

# `id`

```elixir
@type id() :: String.t() | integer() | atom()
```

# `t`

```elixir
@type t() :: %Rover.Marker{
  color: String.t() | nil,
  data: map() | nil,
  draggable: boolean(),
  emoji: String.t() | nil,
  icon: String.t() | nil,
  id: id(),
  label: String.t() | nil,
  lat: float(),
  lon: float(),
  scale: float() | nil,
  tooltip: String.t() | nil
}
```

# `dump`

```elixir
@spec dump(t()) :: map()
```

Renders a marker as the compact map handed to the JavaScript runtime.

`nil` fields are dropped so that the payload sent over the wire stays small.

## Examples

    iex> Rover.Marker.new!(%{id: 1, lat: 45.75, lon: 4.85}) |> Rover.Marker.dump()
    %{id: 1, lat: 45.75, lon: 4.85}

# `new!`

```elixir
@spec new!(
  t() | map(),
  keyword()
) :: t()
```

Normalises `source` into a `Rover.Marker`.

`opts` maps Rover fields onto keys of `source`, for schemas that name things
differently. Every option takes a key (atom or string) or a 1-arity function.

## Examples

    iex> Rover.Marker.new!(%{id: 1, lat: 45.75, lon: 4.85, name: "Lyon"}) |> Rover.Marker.dump()
    %{id: 1, lat: 45.75, lon: 4.85, label: "Lyon"}

    iex> Rover.Marker.new!(%{ref: "a", lat: 45.75, lng: 4.85}, id: :ref).id
    "a"

    iex> Rover.Marker.new!(%{id: 1, lat: 45.75, lon: 4.85}, label: fn m -> "client " <> to_string(m.id) end).label
    "client 1"

# `new_all!`

```elixir
@spec new_all!(
  Enumerable.t(),
  keyword()
) :: [t()]
```

Normalises a list of markers. Nil entries are dropped.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
