Group
Extension

HTML-FormFu-Role-JQueryValidation/lib/HTML/FormFu/Role/JQueryValidation.pm

package HTML::FormFu::Role::JQueryValidation;
{
  $HTML::FormFu::Role::JQueryValidation::VERSION = '1.01';
}
use Moose::Role;

use JSON::Any;
use Scalar::Util qw( refaddr reftype );

sub jquery_validation_profile {
    my ( $self ) = @_;

    my %js = (
        rules    => {},
        messages => {},
    );

    for my $field ( @{ $self->get_fields } ) {

        my $name        = $field->nested_name;
        my $constraints = $field->get_constraints;

        if ( $field->can('field_type') && 'url' eq $field->field_type ) {
            $js{rules}{$name}{url} = 1;

            my @regex =
                grep { 'URI' eq $_->common->[0] }
                grep { 'ARRAY' eq reftype $_->common }
                grep { $_->common }
                grep { 'Regex' eq $_->type }
                    @$constraints;

            if ( 1 == @regex ) {
                $js{messages}{$name}{url} = $regex[0]->fetch_error_message;
            }
        }

        for my $constraint ( @$constraints ) {
            my $type = $constraint->type;

            if ( 'Required' eq $type ) {
                $js{rules}{$name}{required}    = 1;
                $js{messages}{$name}{required} = $constraint->fetch_error_message;
            }
            elsif ( 'Email' eq $type ) {
                $js{rules}{$name}{email}    = 1;
                $js{messages}{$name}{email} = $constraint->fetch_error_message;
            }
            elsif ( 'Integer' eq $type ) {
                $js{rules}{$name}{digits}    = 1;
                $js{messages}{$name}{digits} = $constraint->fetch_error_message;
            }
            elsif ( 'Length' eq $type ) {
                $js{rules}{$name}{rangelength}    = [ $constraint->min, $constraint->max ];
                $js{messages}{$name}{rangelength} = $constraint->fetch_error_message;
            }
            elsif ( 'MaxLength' eq $type ) {
                $js{rules}{$name}{maxlength}    = $constraint->max;
                $js{messages}{$name}{maxlength} = $constraint->fetch_error_message;
            }
            elsif ( 'MinLength' eq $type ) {
                $js{rules}{$name}{minlength}    = $constraint->min;
                $js{messages}{$name}{minlength} = $constraint->fetch_error_message;
            }
            elsif ( 'MaxRange' eq $type ) {
                $js{rules}{$name}{max}    = $constraint->max;
                $js{messages}{$name}{max} = $constraint->fetch_error_message;
            }
            elsif ( 'MinRange' eq $type ) {
                $js{rules}{$name}{min}    = $constraint->min;
                $js{messages}{$name}{min} = $constraint->fetch_error_message;
            }
            elsif ( 'Number' eq $type ) {
                $js{rules}{$name}{number}    = 1;
                $js{messages}{$name}{number} = $constraint->fetch_error_message;
            }
            elsif ( 'Range' eq $type ) {
                $js{rules}{$name}{range}    = [ $constraint->min, $constraint->max ];
                $js{messages}{$name}{range} = $constraint->fetch_error_message;
            }
        }
    }

    return \%js;
}

sub jquery_validation_json {
    my ( $self ) = @_;

    return JSON::Any->objToJson( $self->jquery_validation_profile );
}

sub jquery_validation_errors {
    my ( $self )= @_;

    my %message;

    for my $error (@{ $self->get_errors }) {
        my $name = $error->parent->nested_name;
        $message{$name} ||= [];
        push @{ $message{$name} }, $error->message;
    }

    return \%message;
}

sub jquery_validation_errors_join {
    my $self = shift;

    my $errors = $self->jquery_validation_errors;

    for my $name ( keys %$errors ) {
        if ( 2 == @_ ) {
            $errors->{$name} =
                join '',
                map {
                    $_[0] . $_ . $_[1]
                } @{ $errors->{$name} };
        }
        else {
            my $str = ( @_ && defined $_[0] ) ? $_[0]
                    :                           "";

            $errors->{$name} = join $str, @{ $errors->{$name} };
        }
    }

    return $errors;
}

1;

__END__

=head1 NAME

HTML::FormFu::Role::JQueryValidation - Client-side JS constraints

=head1 SYNOPSIS

    $form->roles('JQueryValidation');

In your L<TT|Template> template:

    <!DOCTYPE HTML>
    <html>
    <body>
        [% form %]
        
        <script src="//js/jquery.min.js" />
        <script src="//js/jquery.validate.min.js" />
        <script>
            $("#form").validate( [% form.jquery_validation_json %] );
        </script>
    </body>
    </html>

=head1 DESCRIPTION

Experimental support for client-side constraints with JQuery Validation
L<http://jqueryvalidation.org>.

=head1 CONSTRAINTS

Adds constraints for the following elements:

=over

=item L<HTML::FormFu::Element::Email>

=item L<HTML::FormFu::Element::URL>

=back

Supports the following constraints on any element:

=over

=item L<HTML::FormFu::Constraint::Email>

=item L<HTML::FormFu::Constraint::Integer>

=item L<HTML::FormFu::Constraint::Length>

=item L<HTML::FormFu::Constraint::MaxLength>

=item L<HTML::FormFu::Constraint::MinLength>

=item L<HTML::FormFu::Constraint::MaxRange>

=item L<HTML::FormFu::Constraint::MinRange>

=item L<HTML::FormFu::Constraint::Number>

=item L<HTML::FormFu::Constraint::Range>

=item L<HTML::FormFu::Constraint::Required>

=back

=head1 METHODS

=head2 jquery_validation_profile

Returns a hash-ref with C<rules> and C<messages> keys.

=head2 jquery_validation_json

Returns L<jquery_validation_profile|/jquery_validation_profile> passed through
L<JSON::Any/objToJson>.

=head2 jquery_validation_errors

Returns a hash-ref whose keys are field names with errors, and values are
arrayrefs of error messages.

=head2 jquery_validation_errors_join

Arguments: $join_string

Arguments: $start_string, $end_string

Processes the return value of
L<jquery_validation_errors|/jquery_validation_errors>, changing each arrayref
of error messages into a single string.

Given 1 argument, it is used as a separator to join the error messages.
Given 2 arguments, they are used to start and end each messages.

Example: if L<jquery_validation_errors|/jquery_validation_errors> returned
the following:

    {
        foo => [
            'Error 1',
            'Error 2',
        ],
    }

    # jquery_validation_errors_join( "<br/>" )
    # outputs
    {
        foo => "Error 1<br/>Error 2"
    }

    # jquery_validation_errors_join( "<li>", "</li>" )
    # outputs
    {
        foo => "<li>Error 1</li><li>Error 2</li>"
    }

=head1 SEE ALSO

L<HTML::FormFu>

L<http://jqueryvalidation.org>

=head1 AUTHORS

Carl Franks

=head1 LICENSE

This library is free software, you can redistribute it and/or modify it under
the same terms as Perl itself.

=cut


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.