view release on metacpan or search on metacpan
Changelog for ASP4x::Linker:
2012-05-07 v1.002
- DEPRECATED
- ASP4 has been marked as deprecated, and so this module follows suit.
2012-03-16 v1.002
- Disabled some failing tests temporarily until we can fix them.
2012-02-03 v1.001
- Added chained widget-attribute-setters.
$widget->set(foo => 'bar', ...)->uri();
$widget->set(%args)->set(%more_args)->uri();
- Thanks to eric.hayes++ for the suggestion.
2011-05-01 v1.000
- $widget->set( non_existent_attribute => "value" ) will result in an exception.
- Simplified the documentation for ASP4x::Linker - the simplified style of
$linker->widget(...)->get/set(...) interface is very much preferred.
- API has otherwise remained unchanged for over a year. Time to go v1.000!!!
2010-05-13 v0.003
- Now, $linker->uri({foo => 'bar'}) returns a uri with foo=bar in there someplace.
- Upgrade recommended.
2010-04-01 v.0.002
- Added vars() method.
- Updated docs.
- Removed AUTOLOAD behavior from Widget and Linker.
- Added $widget->get( $attr ) and $widget->set( $attr => $value )
- Added $widget->on_change( $attr => sub { ... } )
- Added several tests.
2010-04-01 v0.001
- Initial release.
- No joke!
inc/Module/Install.pm view on Meta::CPAN
#line 1
package Module::Install;
# For any maintainers:
# The load order for Module::Install is a bit magic.
# It goes something like this...
#
# IF ( host has Module::Install installed, creating author mode ) {
# 1. Makefile.PL calls "use inc::Module::Install"
# 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
# 3. The installed version of inc::Module::Install loads
# 4. inc::Module::Install calls "require Module::Install"
# 5. The ./inc/ version of Module::Install loads
# } ELSE {
# 1. Makefile.PL calls "use inc::Module::Install"
# 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
# 3. The ./inc/ version of Module::Install loads
# }
BEGIN {
require 5.004;
}
use strict 'vars';
use vars qw{$VERSION};
BEGIN {
inc/Module/Install.pm view on Meta::CPAN
*inc::Module::Install::VERSION = *VERSION;
@inc::Module::Install::ISA = __PACKAGE__;
}
# Whether or not inc::Module::Install is actually loaded, the
# $INC{inc/Module/Install.pm} is what will still get set as long as
# the caller loaded module this in the documented manner.
# If not set, the caller may NOT have loaded the bundled version, and thus
# they may not have a MI version that works with the Makefile.PL. This would
# result in false errors or unexpected behaviour. And we don't want that.
my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
unless ( $INC{$file} ) { die <<"END_DIE" }
Please invoke ${\__PACKAGE__} with:
use inc::${\__PACKAGE__};
not:
inc/Module/Install/Metadata.pm view on Meta::CPAN
}
return 1;
}
sub all_from {
my ( $self, $file ) = @_;
unless ( defined($file) ) {
my $name = $self->name or die(
"all_from called with no args without setting name() first"
);
$file = join('/', 'lib', split(/-/, $name)) . '.pm';
$file =~ s{.*/}{} unless -e $file;
unless ( -e $file ) {
die("all_from cannot find $file from $name");
}
}
unless ( -f $file ) {
die("The path '$file' does not exist, or is not a file");
}
inc/Module/Install/Metadata.pm view on Meta::CPAN
return $self->{values}{no_index};
}
sub read {
my $self = shift;
$self->include_deps( 'YAML::Tiny', 0 );
require YAML::Tiny;
my $data = YAML::Tiny::LoadFile('META.yml');
# Call methods explicitly in case user has already set some values.
while ( my ( $key, $value ) = each %$data ) {
next unless $self->can($key);
if ( ref $value eq 'HASH' ) {
while ( my ( $module, $version ) = each %$value ) {
$self->can($key)->($self, $module => $version );
}
} else {
$self->can($key)->($self, $value);
}
}
lib/ASP4x/Linker.pm view on Meta::CPAN
{
my ($s, $name) = @_;
my ($widget) = grep { $_->name eq $name } $s->widgets
or return;
return $widget;
}# end widget()
sub reset
{
map { $_->reset } shift->widgets;
}# end reset()
sub uri
{
my ($s, $args) = @_;
my $vars = $s->vars( $args );
no warnings 'uninitialized';
my ($uri) = split /\?/, $s->base_href;
lib/ASP4x/Linker.pm view on Meta::CPAN
}# end if()
}# end foreach()
}# end foreach()
# Also add any non-ref values that were passed in as $args:
map { $vars{$_} = $args->{$_} }
grep { ! ref($args->{$_}) }
sort keys %$args;
my $res = \%vars;
$s->reset();
return $res;
}# end _prepare_vars()
sub DESTROY { my $s = shift; undef(%$s); }
1;
=pod
lib/ASP4x/Linker.pm view on Meta::CPAN
# Add a widget:
$linker->add_widget(
name => "widgetA",
attrs => [qw( page_size page_number sort_col sort_dir )]
);
# If the page size is changed, go back to page 1:
$linker->widget("widgetA")->on_change( page_size => sub {
my ($s) = @_;
$s->set( page_number => 1 );
});
# Add another widget:
$linker->add_widget(
name => "widgetB",
attrs => [qw( keywords tag start_date stop_date )]
);
# Chained accessor goodness:
# New as of v1.001
my $fancy_uri = $linker->widget('widgetA')->set( %args )->uri;
=head2 Setting Variables
Since the C<$linker> starts out with only the variables found in C<$ENV{REQUEST_URI}>
or in the C<base_href> argument, calling C<< $linker->uri() >> on a new linker object
will return the same uri that you are currently on (eg: C</some-page.asp>
To generate links that contain specific attributes, set the attributes for those
widgets and then call C<< $linker->uri() >> to get the resultant uri to match.
$linker->widget("widgetA")->set( page_number => 2 );
$uri = $linker->uri;
# $uri is now "/some-page.asp?widgetA.page_number=2"
=head1 DESCRIPTION
C<ASP4x::Linker> aims to solve the age-old problem of:
B<How do I change one widget on the page without losing my settings for all the other widgets on the page?>
OK - say you have one data grid on your web page that allows paging and sorting. You can move forward and backward between
pages, change the sorting - life's great. B<THEN> your boss says:
We need to have two of those on the same page. One for Albums and one for Genres.
Now you have 2 options.
=over 4
lib/ASP4x/Linker.pm view on Meta::CPAN
Returns undef if no widget by that name is found.
=head2 uri( [$properties] )
Returns the uri for all widgets based on the intersect of:
=over 4
=item * The incoming form data from the original request
=item * Individually-set values for each widget in the collection.
=item * Any properties provided as an argument to C<uri()>.
=back
=head2 hidden_fields( [$properties] )
Returns a string of XHTML hidden input fields (<input type="hidden" name="$name" value="$value" />).
Useful if your persistence logic involves repeated form submissions rather than hyperlinks.
The C<$properties> argument is the same as in the C<uri()> method.
=head2 vars( [$properties] )
Returns a hashref representing the intersect of all widgets' names and attributes.
Supposing you setup your linker like this:
my $linker = ASP4x::Linker->new();
$linker->add_widget(
name => 'albums',
attrs => [qw( page sort )]
);
$linker->add_widget(
name => 'artists',
lib/ASP4x/Linker.pm view on Meta::CPAN
And you would get the same thing:
$VAR1 = {
'albums.page' => 2,
'albums.sort' => undef,
'artists.page' => undef,
'artists.sort' => 'desc',
};
=head2 reset( )
Resets all widgets to their original values from the original request (as specified in the C<base_href> value used by C<new()>).
=head1 SEE ALSO
L<ASP4>, L<ASP4x::Router>, L<Router::Generic>
=head1 AUTHOR
John Drago <jdrago_999@yahoo.com>
=head1 LICENSE
lib/ASP4x/Linker/Widget.pm view on Meta::CPAN
};
return bless \%args, $class;
}# end new()
sub attrs { sort @{ shift->{attrs} } }
sub name { shift->{name} }
sub set
{
my ($s, %args) = @_;
while( my ($attr, $val) = each %args )
{
confess "widget '$s->{name}' does not have any attribute named '$attr'"
unless exists($s->{vars}->{$attr});
$s->{vars}->{$attr} = $val;
if( my $triggers = $s->{triggers}->{$attr} )
{
map { $_->( $s ) } @$triggers
}# end if()
}# end while()
# $val;
$s;
}# end set()
sub get
{
my ($s, $key) = @_;
exists( $s->{vars}->{ $key } ) or return;
$s->{vars}->{$key};
}# end get()
sub vars
{
my $s = shift;
return $s->{vars};
}# end filters()
sub reset
{
my $s = shift;
%{ $s->{vars} } = %{ $s->{original_vars} };
}# end reset()
sub linker
{
my $s = shift;
@_ ? $s->{linker} = shift : $s->{linker};
}# end linker()
sub uri { shift->linker->uri }
lib/ASP4x/Linker/Widget.pm view on Meta::CPAN
# Add a widget:
$linker->add_widget(
name => 'albums',
attrs => [qw( page_number page_size sort_col sort_dir )]
);
# Get the widget:
my $widget = $linker->widget('albums');
# Change some attributes:
$widget->set( page_size => 10 );
$widget->set( page_number => 4 );
# Get the value of some attributes:
$widget->get( 'page_size' ); # 10
$widget->get( 'page_number' ); # 4
# Make page_number reset to 1 if the page_size is changed:
$widget->on_change( page_size => sub {
my $s = shift;
$s->set( page_number => 1 );
});
$widget->set( page_size => 20 );
print $widget->get( 'page_number' ); # 1
# Set multiple values at once:
$widget->set( %args );
# Set multiple values at once and get the uri:
warn $widget->set( %args )->uri();
# Set multiple values by chaining and get the uri:
warn $widget->set( foo => 'bar' )->set( baz => 'bux' )->uri();
=head1 DESCRIPTION
C<ASP4x::Linker::Widget> provides a simple, simple interface to a "thing" on your
web page (which we'll call a "widget").
A "widget" can be anything. My experience generally means that a widget is a data grid
that supports paging and sorting through multiple records. However a widget could
represent anything you want it to, as long as you can describe it with a B<name> and
and arrayref of B<attrs> (attributes). The B<attrs> arrayref for a data grid might
lib/ASP4x/Linker/Widget.pm view on Meta::CPAN
=head2 vars
Returns a hashref of all name/value pairs of attributes and their current values.
=head2 attrs
Returns an B<array> of the names of the widget's attributes.
=head1 PUBLIC METHODS
=head2 reset( )
Restores the widget's C<vars> to its original state - as it was when the widget
was first instantiated.
=head2 set( $attr => $value )
Changes the value of an attribute to a new value.
B<NOTE:> As of version , attempts to apply a value to a non-existant attribute will result in a runtime exception.
=head2 get( $attr )
Returns the current value of the attribute.
=head2 on_change( $attr => sub { ... } )
Adds a trigger to the widget that will be called when the given attribute's value is changed via C<set()>.
=head2 uri()
Just a wrapper around the widget's parent C<ASP4x::Linker> object.
=head1 SEE ALSO
L<ASP4x::Linker>
=head1 AUTHOR
t/010-basic/030-vars.t view on Meta::CPAN
'widgetD.type' => undef,
'widgetA.page_number' => undef,
'widgetA.sort_col' => undef,
'widgetB.sort_col' => undef,
'widgetC.color' => undef,
'widgetA.sort_dir' => undef,
'widgetB.page_size' => undef
}, "Default";
$linker->widget('widgetA')->set( page_size => 10 );
is_deeply
$linker->vars(undef, 1), {
'widgetB.page_number' => undef,
'widgetC.type' => undef,
'widgetD.size' => undef,
'widgetA.page_size' => 10,
'widgetB.sort_dir' => undef,
'widgetC.size' => undef,
'widgetD.color' => undef,
'widgetD.type' => undef,
t/010-basic/030-vars.t view on Meta::CPAN
'widgetD.type' => undef,
'widgetA.page_number' => undef,
'widgetA.sort_col' => undef,
'widgetB.sort_col' => undef,
'widgetC.color' => undef,
'widgetA.sort_dir' => undef,
'widgetB.page_size' => undef
}, "Default";
$linker->widget('widgetA')->set( page_size => 10 );
is_deeply
$linker->vars(undef, 1), {
'widgetB.page_number' => undef,
'widgetC.type' => undef,
'widgetD.size' => undef,
'widgetA.page_size' => 10,
'widgetB.sort_dir' => undef,
'widgetC.size' => undef,
'widgetD.color' => undef,
'widgetD.type' => undef,
t/010-basic/040-links.t view on Meta::CPAN
},
widgetC => {
color => 'red'
},
widgetD => {
color => 'orange'
}
}) => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=10&widgetC.color=red&widgetD.color=orange&widgetD.type=hat'
);
$linker->widget('widgetB')->set( page_size => 20 );
is(
$linker->uri() => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=20&widgetC.color=blue&widgetD.type=hat',
'widgetB.page_size = 20'
);
is(
$linker->uri({
widgetB => {
page_size => 10
},
t/010-basic/040-links.t view on Meta::CPAN
color => 'orange'
}
}) => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=10&widgetC.color=red&widgetD.color=orange&widgetD.type=hat'
);
is(
$linker->uri() => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat',
'/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat'
);
$linker->reset();
is(
$linker->uri() => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat',
'/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat'
);
};
WITH_VARS_AND_ROUTER_POSTED: {
last;
t/010-basic/040-links.t view on Meta::CPAN
},
widgetC => {
color => 'red'
},
widgetD => {
color => 'orange'
}
}) => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=10&widgetC.color=red&widgetD.color=orange&widgetD.type=hat'
);
$linker->widget('widgetB')->set( page_size => 20 );
is(
$linker->uri() => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=20&widgetC.color=blue&widgetD.type=hat',
'/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=20&widgetC.color=blue&widgetD.type=hat'
);
is(
$linker->uri({
widgetB => {
page_size => 10
},
t/010-basic/040-links.t view on Meta::CPAN
color => 'orange'
}
}) => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=10&widgetC.color=red&widgetD.color=orange&widgetD.type=hat'
);
is(
$linker->uri() => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat',
'/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat'
);
$linker->reset();
is(
$linker->uri() => '/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat',
'/foo/bar/baz/?widgetA.page_number=24&widgetB.page_size=100&widgetC.color=blue&widgetD.type=hat'
);
is(
$linker->uri({
widgetB => {
page_size => 10
},
t/010-basic/050-hidden-fields.t view on Meta::CPAN
);
is
$linker->hidden_fields() =>
q(<input type="hidden" name="albums.page_size" value="" />
<input type="hidden" name="artists.page_number" value="" />
<input type="hidden" name="albums.page_number" value="" />
<input type="hidden" name="artists.page_size" value="" />),
"Hidden Fields look right";
$linker->widget('albums')->set( page_number => 1 );
is
$linker->hidden_fields() =>
q(<input type="hidden" name="albums.page_size" value="" />
<input type="hidden" name="artists.page_number" value="" />
<input type="hidden" name="albums.page_number" value="1" />
<input type="hidden" name="artists.page_size" value="" />),
"Hidden Fields look right";
is
$linker->hidden_fields() =>
q(<input type="hidden" name="albums.page_size" value="" />
<input type="hidden" name="artists.page_number" value="" />
<input type="hidden" name="albums.page_number" value="" />
<input type="hidden" name="artists.page_size" value="" />),
"Auto-reset works";
my $args = {
albums => { page_size => 20, page_number => 4 },
artists => { page_size => 5, page_number => 10 }
};
is
$linker->hidden_fields($args) =>
q(<input type="hidden" name="albums.page_size" value="20" />
<input type="hidden" name="artists.page_number" value="10" />
<input type="hidden" name="albums.page_number" value="4" />
<input type="hidden" name="artists.page_size" value="5" />),
"Auto-reset works";
t/010-basic/060-widget-triggers.t view on Meta::CPAN
my $linker = ASP4x::Linker->new();
my $widget = $linker->add_widget(
name => 'artists',
attrs => [qw( page_number page_size )]
);
ok( $widget, "Got widget" );
# Reset the page number to '1' when the page size is updated:
$widget->on_change( page_size => sub {
my $s = shift;
$s->set( page_number => 1 );
});
is( $linker->uri => '/?artists.page_number=4&artists.page_size=10' );
$widget->set( page_size => 20 );
is( $linker->uri => '/?artists.page_number=1&artists.page_size=20' );
t/010-basic/070-chaining.t view on Meta::CPAN
$api->ua->get('/?artists.page_size=10&artists.page_number=4');
my $linker = ASP4x::Linker->new();
my $widget = $linker->add_widget(
name => 'artists',
attrs => [qw( page_number page_size )]
);
my $uri = $widget->set(page_number => 1, page_size => 2)->uri();
is( $uri => '/?artists.page_number=1&artists.page_size=2' );
t/conf/asp4-config.json view on Meta::CPAN
"system": {
"post_processors": [
],
"libs": [
"@ServerRoot@/lib"
],
"load_modules": [
],
"env_vars": {
},
"settings": {
}
},
"errors": {
"error_handler": "ASP4::ErrorHandler",
"mail_errors_to": "you@your-server.com",
"mail_errors_from": "root@localhost",
"smtp_server": "localhost"
},
"web": {
"application_name": "ASP4xLinker",