$HTML::FormFu::Role::Element::Input::VERSION
=
'2.07'
;
'HTML::FormFu::Role::Element::FieldMethods'
=>
{
-excludes
=>
'nested_name'
},
'HTML::FormFu::Role::Element::Coercible'
;
mk_attr_accessors
mk_attr_bool_accessors
)
;
has
field_type
=> (
is
=>
'rw'
, );
has
datalist_id
=> (
is
=>
'rw'
);
has
_datalist_options
=> (
is
=>
'rw'
,
default
=>
sub
{ [] },
lazy
=> 1,
isa
=>
'ArrayRef'
,
);
__PACKAGE__->mk_attr_accessors(
qw(
alt autocomplete
checked maxlength
pattern placeholder
size
)
);
__PACKAGE__->mk_attr_bool_accessors(
qw(
autofocus
multiple
required
)
);
my
@ALLOWED_OPTION_KEYS
=
qw(
value
value_xml
value_loc
label
label_xml
label_loc
)
;
sub
datalist_options {
my
(
$self
,
$arg
) =
@_
;
my
(
@options
,
@new
);
return
$self
->_datalist_options
if
@_
== 1;
croak
"datalist_options argument must be a single array-ref"
if
@_
> 2;
if
(
defined
$arg
) {
croak
"datalist_options argument must be an array-ref"
if
reftype(
$arg
) ne
'ARRAY'
;
@options
=
@$arg
;
for
my
$item
(
@options
) {
push
@new
,
$self
->_parse_option(
$item
);
}
}
$self
->_datalist_options( \
@new
);
return
$self
;
}
sub
_parse_option {
my
(
$self
,
$item
) =
@_
;
if
( reftype(
$item
) eq
'HASH'
) {
return
$self
->_parse_option_hashref(
$item
);
}
elsif
( reftype(
$item
) eq
'ARRAY'
) {
return
{
value
=>
$item
->[0],
label
=>
$item
->[1],
};
}
else
{
croak
"each datalist_options argument must be a hash-ref or array-ref"
;
}
}
sub
_parse_option_hashref {
my
(
$self
,
$item
) =
@_
;
my
@keys
=
keys
%$item
;
for
my
$key
(
@keys
) {
croak
"unknown option argument: '$key'"
if
none {
$key
eq
$_
}
@ALLOWED_OPTION_KEYS
;
}
if
(
defined
$item
->{label_xml} ) {
$item
->{label} = literal(
$item
->{label_xml} );
}
elsif
(
defined
$item
->{label_loc} ) {
$item
->{label} =
$self
->form->localize(
$item
->{label_loc} );
}
if
(
defined
$item
->{value_xml} ) {
$item
->{value} = literal(
$item
->{value_xml} );
}
elsif
(
defined
$item
->{value_loc} ) {
$item
->{value} =
$self
->form->localize(
$item
->{value_loc} );
}
if
( !
defined
$item
->{value} ) {
$item
->{value} =
''
;
}
return
$item
;
}
sub
datalist_values {
my
(
$self
,
$arg
) =
@_
;
croak
"datalist_values argument must be a single array-ref of values"
if
@_
> 2;
my
@values
;
if
(
defined
$arg
) {
croak
"datalist_values argument must be an array-ref"
if
reftype(
$arg
) ne
'ARRAY'
;
@values
=
@$arg
;
}
my
@new
=
map
{ {
value
=>
$_
,
label
=>
ucfirst
$_
, } }
@values
;
$self
->_datalist_options( \
@new
);
return
$self
;
}
around
prepare_id
=>
sub
{
my
(
$orig
,
$self
,
$render
) =
@_
;
$self
->
$orig
(
$render
);
return
if
!@{
$self
->_datalist_options };
if
(
defined
$render
->{datalist_id} ) {
$render
->{attributes}{list} =
$render
->{datalist_id};
}
elsif
(
defined
$self
->auto_datalist_id
&&
length
$self
->auto_datalist_id )
{
my
$form_name
=
defined
$self
->form->id
?
$self
->form->id
:
$EMPTY_STR
;
my
$field_name
=
defined
$render
->{nested_name}
?
$render
->{nested_name}
:
$EMPTY_STR
;
my
%string
= (
f
=>
$form_name
,
n
=>
$field_name
,
);
my
$id
=
$self
->auto_datalist_id;
$id
=~ s/%([fn])/
$string
{$1}/g;
if
(
defined
(
my
$count
=
$self
->repeatable_count ) ) {
$id
=~ s/
%r
/
$count
/g;
}
$render
->{attributes}{list} =
$id
;
}
else
{
croak
"either 'datalist_id' or 'auto_datalist_id' must be set when using a datalist"
;
}
return
;
};
around
render_data_non_recursive
=>
sub
{
my
(
$orig
,
$self
,
$args
) =
@_
;
my
$render
=
$self
->
$orig
(
{
field_type
=>
$self
->field_type,
placeholder
=>
$self
->placeholder,
$args
?
%$args
: (),
} );
if
( @{
$self
->_datalist_options } ) {
$render
->{datalist_options} = Clone::clone(
$self
->_datalist_options );
}
$self
->_quote_options(
$render
->{datalist_options} );
return
$render
;
};
sub
_quote_options {
my
(
$self
,
$options
) =
@_
;
foreach
my
$opt
(
@$options
) {
$opt
->{label} = xml_escape(
$opt
->{label} );
$opt
->{value} = xml_escape(
$opt
->{value} );
}
}
sub
_string_field {
my
(
$self
,
$render
) =
@_
;
my
$html
=
""
;
if
(
$render
->{datalist_options} ) {
$html
.=
sprintf
qq{<datalist id="%s">\n}
,
$render
->{attributes}{list};
for
my
$option
( @{
$render
->{datalist_options} } ) {
$html
.=
sprintf
qq{<option value="%s">%s</option>\n}
,
$option
->{value},
$option
->{label};
}
$html
.=
sprintf
qq{</datalist>\n}
;
}
$html
.=
"<input"
;
if
(
defined
$render
->{nested_name} ) {
$html
.=
sprintf
qq{ name="%s"}
,
$render
->{nested_name};
}
$html
.=
sprintf
qq{ type="%s"}
,
$render
->{field_type};
if
(
defined
$render
->{value} ) {
$html
.=
sprintf
qq{ value="%s"}
,
$render
->{value};
}
$html
.=
sprintf
"%s />"
, process_attrs(
$render
->{attributes} );
return
$html
;
}
around
clone
=>
sub
{
my
(
$orig
,
$self
) =
@_
;
my
$clone
=
$self
->
$orig
(
@_
);
$clone
->_datalist_options( Clone::clone(
$self
->_datalist_options ) );
return
$clone
;
};
1;