if match?({:module, _}, Code.ensure_compiled(Cldr.Territory)) do
defmodule Cldr.HTML.Territory do
@moduledoc """
Implements an HTML Form select specifically
localised territory display.
"""
@type select_options :: [
{:territories, [atom() | binary(), ...]}
| {:locale, Cldr.Locale.locale_name() | Cldr.LanguageTag.t()}
| {:collator, function()}
| {:mapper, (Cldr.Locale.territory_code() -> String.t())}
| {:backend, module()}
| {:selected, atom() | binary()}
]
@typedoc """
Territory type passed to a collator for ordering in the select box.
The default collator orders by `:name` using Elixir standard
comparison which is by codepoint and is therefore not Unicode
aware.
"""
@type territory :: %{
territory: Cldr.Locale.territory_code(),
name: String.t(),
flag: String.t()
}
@omit_from_select_options [:territories, :locale, :mapper, :collator, :backend, :style]
@doc """
Generate an HTML select tag for a territory list
that can be used with a `Phoenix.HTML.Form.t`.
## Arguments
* A `t:Phoenix.HTML.Form.t/0` form
* A `t:Phoenix.HTML.Form.field/0` field
* A `t:Keyword.t/0` list of options
## Options
For select options see `Phoenix.HTML.Form.options_for_select/2`
* `:territories` defines the list of territories to be
displayed in the the `select` tag. The list defaults to
the territories returned by `Cldr.Territory.country_codes/0`.
* `:style` is the format of the territory name to be used.
The options are `:standard` (the default), `:short` and `:variant`.
Not all territories have `:short` or `:variant` names in which
case `:standard` is used for those territories.
* `:locale` defines the locale to be used to localise the
description of the territories. The default is the locale
returned by `Cldr.get_locale/1`
* `:backend` is any backend module. The default is
`Cldr.default_backend!/0`
* `:collator` is a function used to sort the territories
in the selection list. It is passed a list of maps where
each map represents a territory and has the keys `:territory`,
`:name` and `:flag`. See `t:territory`. The default collator
sorts by `name_1 < name_2`. As a result, default collation
sorts by code point which will not return expected results
for scripts other than Latin.
* `:mapper` is a function that creates the text to be
displayed in the select tag for each territory. It is
passed the territory definition as a `t:territory` map
containing the keys `:territory_code`, `:name` and
`:flag`. The default function is
`&({&1.flag <> " " <> &1.name, &1.territory_code})`
* `:selected` identifies the territory that is to be selected
by default in the `select` tag. The default is `nil`. This
is passed unmodified to the form generator.
* `:prompt` is a prompt displayed at the top of the select
box. This is passed unmodified to the form generator.
# Examples
Cldr.HTML.Territory.select(:my_form, :territory, selected: :AU)
Cldr.HTML.Territory.select(:my_form, :territory, selected: :AU, locale: "ar")
Cldr.HTML.Territory.select(:my_form, :territory, territories: [:US, :AU, :JP],
mapper: &({&1.name, &1.territory_code}))
"""
@spec select(
form :: Phoenix.HTML.Form.t(),
field :: Phoenix.HTML.Form.field(),
select_options
) ::
Phoenix.HTML.safe()
| {:error, {Cldr.UnknownTerritoryError, binary()}}
| {:error, {Cldr.UnknownLocaleError, binary()}}
def select(form, field, options \\ [])
def select(form, field, options) when is_list(options) do
select(form, field, validate_options(options), options[:selected])
end
# Invalid options
defp select(_form, _field, {:error, reason}, _selected) do
{:error, reason}
end
# Selected territory
defp select(form, field, options, _selected) do
select_options =
options
|> Map.drop(@omit_from_select_options)
|> Map.to_list()
options = build_territory_options(options)
to_select(form, field, options, select_options)
end
if function_exported?(Phoenix.HTML.Form, :select, 4) do
defp to_select(form, field, options, select_options) do
Phoenix.HTML.Form.select(form, field, options, select_options)
end
else
defp to_select(form, field, options, select_options) do
{selected, select_options} = Keyword.pop(select_options, :selected)
safe_options =
options
|> Phoenix.HTML.Form.options_for_select(selected)
|> Phoenix.HTML.safe_to_string()
safe_attrs =
[
id: Phoenix.HTML.Form.input_id(form, field),
name: Phoenix.HTML.Form.input_name(form, field)
]
|> Keyword.merge(select_options)
|> Enum.sort()
|> Phoenix.HTML.attributes_escape()
|> Phoenix.HTML.safe_to_string()
[""]
|> IO.iodata_to_binary()
|> Phoenix.HTML.raw()
end
end
@doc """
Generate a list of options for a territory list
that can be used with `Phoenix.HTML.Form.options_for_select/2` or
to create a