jifty-1.10518+dfsg.orig/0000755000175000017500000000000011625457665012517 5ustar fsfsjifty-1.10518+dfsg.orig/inc/0000755000175000017500000000000011625457665013270 5ustar fsfsjifty-1.10518+dfsg.orig/inc/Module/0000755000175000017500000000000011565006013014471 5ustar fsfsjifty-1.10518+dfsg.orig/inc/Module/Install.pm0000644000175000017500000003013511565005324016443 0ustar fsfs#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 # } use 5.005; use strict 'vars'; use Cwd (); use File::Find (); use File::Path (); use vars qw{$VERSION $MAIN}; BEGIN { # All Module::Install core packages now require synchronised versions. # This will be used to ensure we don't accidentally load old or # different versions of modules. # This is not enforced yet, but will be some time in the next few # releases once we can make sure it won't clash with custom # Module::Install extensions. $VERSION = '1.01'; # Storage for the pseudo-singleton $MAIN = undef; *inc::Module::Install::VERSION = *VERSION; @inc::Module::Install::ISA = __PACKAGE__; } sub import { my $class = shift; my $self = $class->new(@_); my $who = $self->_caller; #------------------------------------------------------------- # all of the following checks should be included in import(), # to allow "eval 'require Module::Install; 1' to test # installation of Module::Install. (RT #51267) #------------------------------------------------------------- # 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: use ${\__PACKAGE__}; END_DIE # This reportedly fixes a rare Win32 UTC file time issue, but # as this is a non-cross-platform XS module not in the core, # we shouldn't really depend on it. See RT #24194 for detail. # (Also, this module only supports Perl 5.6 and above). eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006; # If the script that is loading Module::Install is from the future, # then make will detect this and cause it to re-run over and over # again. This is bad. Rather than taking action to touch it (which # is unreliable on some platforms and requires write permissions) # for now we should catch this and refuse to run. if ( -f $0 ) { my $s = (stat($0))[9]; # If the modification time is only slightly in the future, # sleep briefly to remove the problem. my $a = $s - time; if ( $a > 0 and $a < 5 ) { sleep 5 } # Too far in the future, throw an error. my $t = time; if ( $s > $t ) { die <<"END_DIE" } Your installer $0 has a modification time in the future ($s > $t). This is known to create infinite loops in make. Please correct this, then run $0 again. END_DIE } # Build.PL was formerly supported, but no longer is due to excessive # difficulty in implementing every single feature twice. if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" } Module::Install no longer supports Build.PL. It was impossible to maintain duel backends, and has been deprecated. Please remove all Build.PL files and only use the Makefile.PL installer. END_DIE #------------------------------------------------------------- # To save some more typing in Module::Install installers, every... # use inc::Module::Install # ...also acts as an implicit use strict. $^H |= strict::bits(qw(refs subs vars)); #------------------------------------------------------------- unless ( -f $self->{file} ) { foreach my $key (keys %INC) { delete $INC{$key} if $key =~ /Module\/Install/; } local $^W; require "$self->{path}/$self->{dispatch}.pm"; File::Path::mkpath("$self->{prefix}/$self->{author}"); $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self ); $self->{admin}->init; @_ = ($class, _self => $self); goto &{"$self->{name}::import"}; } local $^W; *{"${who}::AUTOLOAD"} = $self->autoload; $self->preload; # Unregister loader and worker packages so subdirs can use them again delete $INC{'inc/Module/Install.pm'}; delete $INC{'Module/Install.pm'}; # Save to the singleton $MAIN = $self; return 1; } sub autoload { my $self = shift; my $who = $self->_caller; my $cwd = Cwd::cwd(); my $sym = "${who}::AUTOLOAD"; $sym->{$cwd} = sub { my $pwd = Cwd::cwd(); if ( my $code = $sym->{$pwd} ) { # Delegate back to parent dirs goto &$code unless $cwd eq $pwd; } unless ($$sym =~ s/([^:]+)$//) { # XXX: it looks like we can't retrieve the missing function # via $$sym (usually $main::AUTOLOAD) in this case. # I'm still wondering if we should slurp Makefile.PL to # get some context or not ... my ($package, $file, $line) = caller; die <<"EOT"; Unknown function is found at $file line $line. Execution of $file aborted due to runtime errors. If you're a contributor to a project, you may need to install some Module::Install extensions from CPAN (or other repository). If you're a user of a module, please contact the author. EOT } my $method = $1; if ( uc($method) eq $method ) { # Do nothing return; } elsif ( $method =~ /^_/ and $self->can($method) ) { # Dispatch to the root M:I class return $self->$method(@_); } # Dispatch to the appropriate plugin unshift @_, ( $self, $1 ); goto &{$self->can('call')}; }; } sub preload { my $self = shift; unless ( $self->{extensions} ) { $self->load_extensions( "$self->{prefix}/$self->{path}", $self ); } my @exts = @{$self->{extensions}}; unless ( @exts ) { @exts = $self->{admin}->load_all_extensions; } my %seen; foreach my $obj ( @exts ) { while (my ($method, $glob) = each %{ref($obj) . '::'}) { next unless $obj->can($method); next if $method =~ /^_/; next if $method eq uc($method); $seen{$method}++; } } my $who = $self->_caller; foreach my $name ( sort keys %seen ) { local $^W; *{"${who}::$name"} = sub { ${"${who}::AUTOLOAD"} = "${who}::$name"; goto &{"${who}::AUTOLOAD"}; }; } } sub new { my ($class, %args) = @_; delete $INC{'FindBin.pm'}; { # to suppress the redefine warning local $SIG{__WARN__} = sub {}; require FindBin; } # ignore the prefix on extension modules built from top level. my $base_path = Cwd::abs_path($FindBin::Bin); unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) { delete $args{prefix}; } return $args{_self} if $args{_self}; $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $args{base} ||= $base_path; $class =~ s/^\Q$args{prefix}\E:://; $args{name} ||= $class; $args{version} ||= $class->VERSION; unless ( $args{path} ) { $args{path} = $args{name}; $args{path} =~ s!::!/!g; } $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm"; $args{wrote} = 0; bless( \%args, $class ); } sub call { my ($self, $method) = @_; my $obj = $self->load($method) or return; splice(@_, 0, 2, $obj); goto &{$obj->can($method)}; } sub load { my ($self, $method) = @_; $self->load_extensions( "$self->{prefix}/$self->{path}", $self ) unless $self->{extensions}; foreach my $obj (@{$self->{extensions}}) { return $obj if $obj->can($method); } my $admin = $self->{admin} or die <<"END_DIE"; The '$method' method does not exist in the '$self->{prefix}' path! Please remove the '$self->{prefix}' directory and run $0 again to load it. END_DIE my $obj = $admin->load($method, 1); push @{$self->{extensions}}, $obj; $obj; } sub load_extensions { my ($self, $path, $top) = @_; my $should_reload = 0; unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) { unshift @INC, $self->{prefix}; $should_reload = 1; } foreach my $rv ( $self->find_extensions($path) ) { my ($file, $pkg) = @{$rv}; next if $self->{pathnames}{$pkg}; local $@; my $new = eval { local $^W; require $file; $pkg->can('new') }; unless ( $new ) { warn $@ if $@; next; } $self->{pathnames}{$pkg} = $should_reload ? delete $INC{$file} : $INC{$file}; push @{$self->{extensions}}, &{$new}($pkg, _top => $top ); } $self->{extensions} ||= []; } sub find_extensions { my ($self, $path) = @_; my @found; File::Find::find( sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; my $subpath = $1; return if lc($subpath) eq lc($self->{dispatch}); $file = "$self->{path}/$subpath.pm"; my $pkg = "$self->{name}::$subpath"; $pkg =~ s!/!::!g; # If we have a mixed-case package name, assume case has been preserved # correctly. Otherwise, root through the file to locate the case-preserved # version of the package name. if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) { my $content = Module::Install::_read($subpath . '.pm'); my $in_pod = 0; foreach ( split //, $content ) { $in_pod = 1 if /^=\w/; $in_pod = 0 if /^=cut/; next if ($in_pod || /^=cut/); # skip pod text next if /^\s*#/; # and comments if ( m/^\s*package\s+($pkg)\s*;/i ) { $pkg = $1; last; } } } push @found, [ $file, $pkg ]; }, $path ) if -d $path; @found; } ##################################################################### # Common Utility Functions sub _caller { my $depth = 0; my $call = caller($depth); while ( $call eq __PACKAGE__ ) { $depth++; $call = caller($depth); } return $call; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _read { local *FH; open( FH, '<', $_[0] ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_NEW sub _read { local *FH; open( FH, "< $_[0]" ) or die "open($_[0]): $!"; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_OLD sub _readperl { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s; $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg; return $string; } sub _readpod { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; return $string if $_[0] =~ /\.pod\z/; $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg; $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg; $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg; $string =~ s/^\n+//s; return $string; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _write { local *FH; open( FH, '>', $_[0] ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_NEW sub _write { local *FH; open( FH, "> $_[0]" ) or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_OLD # _version is for processing module versions (eg, 1.03_05) not # Perl versions (eg, 5.8.1). sub _version ($) { my $s = shift || 0; my $d =()= $s =~ /(\.)/g; if ( $d >= 2 ) { # Normalise multipart versions $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg; } $s =~ s/^(\d+)\.?//; my $l = $1 || 0; my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g; $l = $l . '.' . join '', @v if @v; return $l + 0; } sub _cmp ($$) { _version($_[0]) <=> _version($_[1]); } # Cloned from Params::Util::_CLASS sub _CLASS ($) { ( defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s ) ? $_[0] : undef; } 1; # Copyright 2008 - 2011 Adam Kennedy. jifty-1.10518+dfsg.orig/inc/Module/Install/0000755000175000017500000000000011625457665016123 5ustar fsfsjifty-1.10518+dfsg.orig/inc/Module/Install/AutoInstall.pm0000644000175000017500000000363211565005325020705 0ustar fsfs#line 1 package Module::Install::AutoInstall; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub AutoInstall { $_[0] } sub run { my $self = shift; $self->auto_install_now(@_); } sub write { my $self = shift; $self->auto_install(@_); } sub auto_install { my $self = shift; return if $self->{done}++; # Flatten array of arrays into a single array my @core = map @$_, map @$_, grep ref, $self->build_requires, $self->requires; my @config = @_; # We'll need Module::AutoInstall $self->include('Module::AutoInstall'); require Module::AutoInstall; my @features_require = Module::AutoInstall->import( (@config ? (-config => \@config) : ()), (@core ? (-core => \@core) : ()), $self->features, ); my %seen; my @requires = map @$_, map @$_, grep ref, $self->requires; while (my ($mod, $ver) = splice(@requires, 0, 2)) { $seen{$mod}{$ver}++; } my @build_requires = map @$_, map @$_, grep ref, $self->build_requires; while (my ($mod, $ver) = splice(@build_requires, 0, 2)) { $seen{$mod}{$ver}++; } my @configure_requires = map @$_, map @$_, grep ref, $self->configure_requires; while (my ($mod, $ver) = splice(@configure_requires, 0, 2)) { $seen{$mod}{$ver}++; } my @deduped; while (my ($mod, $ver) = splice(@features_require, 0, 2)) { push @deduped, $mod => $ver unless $seen{$mod}{$ver}++; } $self->requires(@deduped); $self->makemaker_args( Module::AutoInstall::_make_args() ); my $class = ref($self); $self->postamble( "# --- $class section:\n" . Module::AutoInstall::postamble() ); } sub auto_install_now { my $self = shift; $self->auto_install(@_); Module::AutoInstall::do_install(); } 1; jifty-1.10518+dfsg.orig/inc/Module/Install/Metadata.pm0000644000175000017500000004312311565005325020165 0ustar fsfs#line 1 package Module::Install::Metadata; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } my @boolean_keys = qw{ sign }; my @scalar_keys = qw{ name module_name abstract version distribution_type tests installdirs }; my @tuple_keys = qw{ configure_requires build_requires requires recommends bundles resources }; my @resource_keys = qw{ homepage bugtracker repository }; my @array_keys = qw{ keywords author }; *authors = \&author; sub Meta { shift } sub Meta_BooleanKeys { @boolean_keys } sub Meta_ScalarKeys { @scalar_keys } sub Meta_TupleKeys { @tuple_keys } sub Meta_ResourceKeys { @resource_keys } sub Meta_ArrayKeys { @array_keys } foreach my $key ( @boolean_keys ) { *$key = sub { my $self = shift; if ( defined wantarray and not @_ ) { return $self->{values}->{$key}; } $self->{values}->{$key} = ( @_ ? $_[0] : 1 ); return $self; }; } foreach my $key ( @scalar_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} = shift; return $self; }; } foreach my $key ( @array_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} ||= []; push @{$self->{values}->{$key}}, @_; return $self; }; } foreach my $key ( @resource_keys ) { *$key = sub { my $self = shift; unless ( @_ ) { return () unless $self->{values}->{resources}; return map { $_->[1] } grep { $_->[0] eq $key } @{ $self->{values}->{resources} }; } return $self->{values}->{resources}->{$key} unless @_; my $uri = shift or die( "Did not provide a value to $key()" ); $self->resources( $key => $uri ); return 1; }; } foreach my $key ( grep { $_ ne "resources" } @tuple_keys) { *$key = sub { my $self = shift; return $self->{values}->{$key} unless @_; my @added; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @added, [ $module, $version ]; } push @{ $self->{values}->{$key} }, @added; return map {@$_} @added; }; } # Resource handling my %lc_resource = map { $_ => 1 } qw{ homepage license bugtracker repository }; sub resources { my $self = shift; while ( @_ ) { my $name = shift or last; my $value = shift or next; if ( $name eq lc $name and ! $lc_resource{$name} ) { die("Unsupported reserved lowercase resource '$name'"); } $self->{values}->{resources} ||= []; push @{ $self->{values}->{resources} }, [ $name, $value ]; } $self->{values}->{resources}; } # Aliases for build_requires that will have alternative # meanings in some future version of META.yml. sub test_requires { shift->build_requires(@_) } sub install_requires { shift->build_requires(@_) } # Aliases for installdirs options sub install_as_core { $_[0]->installdirs('perl') } sub install_as_cpan { $_[0]->installdirs('site') } sub install_as_site { $_[0]->installdirs('site') } sub install_as_vendor { $_[0]->installdirs('vendor') } sub dynamic_config { my $self = shift; unless ( @_ ) { warn "You MUST provide an explicit true/false value to dynamic_config\n"; return $self; } $self->{values}->{dynamic_config} = $_[0] ? 1 : 0; return 1; } sub perl_version { my $self = shift; return $self->{values}->{perl_version} unless @_; my $version = shift or die( "Did not provide a value to perl_version()" ); # Normalize the version $version = $self->_perl_version($version); # We don't support the reall old versions unless ( $version >= 5.005 ) { die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n"; } $self->{values}->{perl_version} = $version; } 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"); } $self->{values}{all_from} = $file; # Some methods pull from POD instead of code. # If there is a matching .pod, use that instead my $pod = $file; $pod =~ s/\.pm$/.pod/i; $pod = $file unless -e $pod; # Pull the different values $self->name_from($file) unless $self->name; $self->version_from($file) unless $self->version; $self->perl_version_from($file) unless $self->perl_version; $self->author_from($pod) unless @{$self->author || []}; $self->license_from($pod) unless $self->license; $self->abstract_from($pod) unless $self->abstract; return 1; } sub provides { my $self = shift; my $provides = ( $self->{values}->{provides} ||= {} ); %$provides = (%$provides, @_) if @_; return $provides; } sub auto_provides { my $self = shift; return $self unless $self->is_admin; unless (-e 'MANIFEST') { warn "Cannot deduce auto_provides without a MANIFEST, skipping\n"; return $self; } # Avoid spurious warnings as we are not checking manifest here. local $SIG{__WARN__} = sub {1}; require ExtUtils::Manifest; local *ExtUtils::Manifest::manicheck = sub { return }; require Module::Build; my $build = Module::Build->new( dist_name => $self->name, dist_version => $self->version, license => $self->license, ); $self->provides( %{ $build->find_dist_packages || {} } ); } sub feature { my $self = shift; my $name = shift; my $features = ( $self->{values}->{features} ||= [] ); my $mods; if ( @_ == 1 and ref( $_[0] ) ) { # The user used ->feature like ->features by passing in the second # argument as a reference. Accomodate for that. $mods = $_[0]; } else { $mods = \@_; } my $count = 0; push @$features, ( $name => [ map { ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_ } @$mods ] ); return @$features; } sub features { my $self = shift; while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) { $self->feature( $name, @$mods ); } return $self->{values}->{features} ? @{ $self->{values}->{features} } : (); } sub no_index { my $self = shift; my $type = shift; push @{ $self->{values}->{no_index}->{$type} }, @_ if $type; 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); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; $self->admin->write_meta; return $self; } sub version_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->version( ExtUtils::MM_Unix->parse_version($file) ); # for version integrity check $self->makemaker_args( VERSION_FROM => $file ); } sub abstract_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix' )->parse_abstract($file) ); } # Add both distribution and module name sub name_from { my ($self, $file) = @_; if ( Module::Install::_read($file) =~ m/ ^ \s* package \s* ([\w:]+) \s* ; /ixms ) { my ($name, $module_name) = ($1, $1); $name =~ s{::}{-}g; $self->name($name); unless ( $self->module_name ) { $self->module_name($module_name); } } else { die("Cannot determine name from $file\n"); } } sub _extract_perl_version { if ( $_[0] =~ m/ ^\s* (?:use|require) \s* v? ([\d_\.]+) \s* ; /ixms ) { my $perl_version = $1; $perl_version =~ s{_}{}g; return $perl_version; } else { return; } } sub perl_version_from { my $self = shift; my $perl_version=_extract_perl_version(Module::Install::_read($_[0])); if ($perl_version) { $self->perl_version($perl_version); } else { warn "Cannot determine perl version info from $_[0]\n"; return; } } sub author_from { my $self = shift; my $content = Module::Install::_read($_[0]); if ($content =~ m/ =head \d \s+ (?:authors?)\b \s* ([^\n]*) | =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s* .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s* ([^\n]*) /ixms) { my $author = $1 || $2; # XXX: ugly but should work anyway... if (eval "require Pod::Escapes; 1") { # Pod::Escapes has a mapping table. # It's in core of perl >= 5.9.3, and should be installed # as one of the Pod::Simple's prereqs, which is a prereq # of Pod::Text 3.x (see also below). $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $Pod::Escapes::Name2character_number{$1} ? chr($Pod::Escapes::Name2character_number{$1}) : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) { # Pod::Text < 3.0 has yet another mapping table, # though the table name of 2.x and 1.x are different. # (1.x is in core of Perl < 5.6, 2.x is in core of # Perl < 5.9.3) my $mapping = ($Pod::Text::VERSION < 2) ? \%Pod::Text::HTML_Escapes : \%Pod::Text::ESCAPES; $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $mapping->{$1} ? $mapping->{$1} : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } else { $author =~ s{E}{<}g; $author =~ s{E}{>}g; } $self->author($author); } else { warn "Cannot determine author info from $_[0]\n"; } } #Stolen from M::B my %license_urls = ( perl => 'http://dev.perl.org/licenses/', apache => 'http://apache.org/licenses/LICENSE-2.0', apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1', artistic => 'http://opensource.org/licenses/artistic-license.php', artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php', lgpl => 'http://opensource.org/licenses/lgpl-license.php', lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php', lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html', bsd => 'http://opensource.org/licenses/bsd-license.php', gpl => 'http://opensource.org/licenses/gpl-license.php', gpl2 => 'http://opensource.org/licenses/gpl-2.0.php', gpl3 => 'http://opensource.org/licenses/gpl-3.0.html', mit => 'http://opensource.org/licenses/mit-license.php', mozilla => 'http://opensource.org/licenses/mozilla1.1.php', open_source => undef, unrestricted => undef, restrictive => undef, unknown => undef, ); sub license { my $self = shift; return $self->{values}->{license} unless @_; my $license = shift or die( 'Did not provide a value to license()' ); $license = __extract_license($license) || lc $license; $self->{values}->{license} = $license; # Automatically fill in license URLs if ( $license_urls{$license} ) { $self->resources( license => $license_urls{$license} ); } return 1; } sub _extract_license { my $pod = shift; my $matched; return __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?) (=head \d.*|=cut.*|)\z /xms ) || __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?) (=head \d.*|=cut.*|)\z /xms ); } sub __extract_license { my $license_text = shift or return; my @phrases = ( '(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1, '(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1, 'Artistic and GPL' => 'perl', 1, 'GNU general public license' => 'gpl', 1, 'GNU public license' => 'gpl', 1, 'GNU lesser general public license' => 'lgpl', 1, 'GNU lesser public license' => 'lgpl', 1, 'GNU library general public license' => 'lgpl', 1, 'GNU library public license' => 'lgpl', 1, 'GNU Free Documentation license' => 'unrestricted', 1, 'GNU Affero General Public License' => 'open_source', 1, '(?:Free)?BSD license' => 'bsd', 1, 'Artistic license 2\.0' => 'artistic_2', 1, 'Artistic license' => 'artistic', 1, 'Apache (?:Software )?license' => 'apache', 1, 'GPL' => 'gpl', 1, 'LGPL' => 'lgpl', 1, 'BSD' => 'bsd', 1, 'Artistic' => 'artistic', 1, 'MIT' => 'mit', 1, 'Mozilla Public License' => 'mozilla', 1, 'Q Public License' => 'open_source', 1, 'OpenSSL License' => 'unrestricted', 1, 'SSLeay License' => 'unrestricted', 1, 'zlib License' => 'open_source', 1, 'proprietary' => 'proprietary', 0, ); while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) { $pattern =~ s#\s+#\\s+#gs; if ( $license_text =~ /\b$pattern\b/i ) { return $license; } } return ''; } sub license_from { my $self = shift; if (my $license=_extract_license(Module::Install::_read($_[0]))) { $self->license($license); } else { warn "Cannot determine license info from $_[0]\n"; return 'unknown'; } } sub _extract_bugtracker { my @links = $_[0] =~ m#L<( https?\Q://rt.cpan.org/\E[^>]+| https?\Q://github.com/\E[\w_]+/[\w_]+/issues| https?\Q://code.google.com/p/\E[\w_\-]+/issues/list )>#gx; my %links; @links{@links}=(); @links=keys %links; return @links; } sub bugtracker_from { my $self = shift; my $content = Module::Install::_read($_[0]); my @links = _extract_bugtracker($content); unless ( @links ) { warn "Cannot determine bugtracker info from $_[0]\n"; return 0; } if ( @links > 1 ) { warn "Found more than one bugtracker link in $_[0]\n"; return 0; } # Set the bugtracker bugtracker( $links[0] ); return 1; } sub requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->requires( $module => $version ); } } sub test_requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->test_requires( $module => $version ); } } # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to # numbers (eg, 5.006001 or 5.008009). # Also, convert double-part versions (eg, 5.8) sub _perl_version { my $v = $_[-1]; $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e; $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e; $v =~ s/(\.\d\d\d)000$/$1/; $v =~ s/_.+$//; if ( ref($v) ) { # Numify $v = $v + 0; } return $v; } sub add_metadata { my $self = shift; my %hash = @_; for my $key (keys %hash) { warn "add_metadata: $key is not prefixed with 'x_'.\n" . "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/; $self->{values}->{$key} = $hash{$key}; } } ###################################################################### # MYMETA Support sub WriteMyMeta { die "WriteMyMeta has been deprecated"; } sub write_mymeta_yaml { my $self = shift; # We need YAML::Tiny to write the MYMETA.yml file unless ( eval { require YAML::Tiny; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.yml\n"; YAML::Tiny::DumpFile('MYMETA.yml', $meta); } sub write_mymeta_json { my $self = shift; # We need JSON to write the MYMETA.json file unless ( eval { require JSON; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.json\n"; Module::Install::_write( 'MYMETA.json', JSON->new->pretty(1)->canonical->encode($meta), ); } sub _write_mymeta_data { my $self = shift; # If there's no existing META.yml there is nothing we can do return undef unless -f 'META.yml'; # We need Parse::CPAN::Meta to load the file unless ( eval { require Parse::CPAN::Meta; 1; } ) { return undef; } # Merge the perl version into the dependencies my $val = $self->Meta->{values}; my $perl = delete $val->{perl_version}; if ( $perl ) { $val->{requires} ||= []; my $requires = $val->{requires}; # Canonize to three-dot version after Perl 5.6 if ( $perl >= 5.006 ) { $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e } unshift @$requires, [ perl => $perl ]; } # Load the advisory META.yml file my @yaml = Parse::CPAN::Meta::LoadFile('META.yml'); my $meta = $yaml[0]; # Overwrite the non-configure dependency hashs delete $meta->{requires}; delete $meta->{build_requires}; delete $meta->{recommends}; if ( exists $val->{requires} ) { $meta->{requires} = { map { @$_ } @{ $val->{requires} } }; } if ( exists $val->{build_requires} ) { $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } }; } return $meta; } 1; jifty-1.10518+dfsg.orig/inc/Module/Install/Fetch.pm0000644000175000017500000000462711565005332017502 0ustar fsfs#line 1 package Module::Install::Fetch; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, <<"END_FTP"); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit END_FTP foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; jifty-1.10518+dfsg.orig/inc/Module/Install/WriteAll.pm0000644000175000017500000000237611565005332020173 0ustar fsfs#line 1 package Module::Install::WriteAll; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } sub WriteAll { my $self = shift; my %args = ( meta => 1, sign => 0, inline => 0, check_nmake => 1, @_, ); $self->sign(1) if $args{sign}; $self->admin->WriteAll(%args) if $self->is_admin; $self->check_nmake if $args{check_nmake}; unless ( $self->makemaker_args->{PL_FILES} ) { # XXX: This still may be a bit over-defensive... unless ($self->makemaker(6.25)) { $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL'; } } # Until ExtUtils::MakeMaker support MYMETA.yml, make sure # we clean it up properly ourself. $self->realclean_files('MYMETA.yml'); if ( $args{inline} ) { $self->Inline->write; } else { $self->Makefile->write; } # The Makefile write process adds a couple of dependencies, # so write the META.yml files after the Makefile. if ( $args{meta} ) { $self->Meta->write; } # Experimental support for MYMETA if ( $ENV{X_MYMETA} ) { if ( $ENV{X_MYMETA} eq 'JSON' ) { $self->Meta->write_mymeta_json; } else { $self->Meta->write_mymeta_yaml; } } return 1; } 1; jifty-1.10518+dfsg.orig/inc/Module/Install/Base.pm0000644000175000017500000000214711565005325017320 0ustar fsfs#line 1 package Module::Install::Base; use strict 'vars'; use vars qw{$VERSION}; BEGIN { $VERSION = '1.01'; } # Suspend handler for "redefined" warnings BEGIN { my $w = $SIG{__WARN__}; $SIG{__WARN__} = sub { $w }; } #line 42 sub new { my $class = shift; unless ( defined &{"${class}::call"} ) { *{"${class}::call"} = sub { shift->_top->call(@_) }; } unless ( defined &{"${class}::load"} ) { *{"${class}::load"} = sub { shift->_top->load(@_) }; } bless { @_ }, $class; } #line 61 sub AUTOLOAD { local $@; my $func = eval { shift->_top->autoload } or return; goto &$func; } #line 75 sub _top { $_[0]->{_top}; } #line 90 sub admin { $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new; } #line 106 sub is_admin { ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin'); } sub DESTROY {} package Module::Install::Base::FakeAdmin; use vars qw{$VERSION}; BEGIN { $VERSION = $Module::Install::Base::VERSION; } my $fake; sub new { $fake ||= bless(\@_, $_[0]); } sub AUTOLOAD {} sub DESTROY {} # Restore warning handler BEGIN { $SIG{__WARN__} = $SIG{__WARN__}->(); } 1; #line 159 jifty-1.10518+dfsg.orig/inc/Module/Install/Scripts.pm0000644000175000017500000000101111565005332020060 0ustar fsfs#line 1 package Module::Install::Scripts; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub install_script { my $self = shift; my $args = $self->makemaker_args; my $exe = $args->{EXE_FILES} ||= []; foreach ( @_ ) { if ( -f $_ ) { push @$exe, $_; } elsif ( -d 'script' and -f "script/$_" ) { push @$exe, "script/$_"; } else { die("Cannot find script '$_'"); } } } 1; jifty-1.10518+dfsg.orig/inc/Module/Install/Include.pm0000644000175000017500000000101511565005325020022 0ustar fsfs#line 1 package Module::Install::Include; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub include { shift()->admin->include(@_); } sub include_deps { shift()->admin->include_deps(@_); } sub auto_include { shift()->admin->auto_include(@_); } sub auto_include_deps { shift()->admin->auto_include_deps(@_); } sub auto_include_dependent_dists { shift()->admin->auto_include_dependent_dists(@_); } 1; jifty-1.10518+dfsg.orig/inc/Module/Install/Can.pm0000644000175000017500000000333311565005325017145 0ustar fsfs#line 1 package Module::Install::Can; use strict; use Config (); use File::Spec (); use ExtUtils::MakeMaker (); use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # check if we can load some module ### Upgrade this to not have to load the module if possible sub can_use { my ($self, $mod, $ver) = @_; $mod =~ s{::|\\}{/}g; $mod .= '.pm' unless $mod =~ /\.pm$/i; my $pkg = $mod; $pkg =~ s{/}{::}g; $pkg =~ s{\.pm$}{}i; local $@; eval { require $mod; $pkg->VERSION($ver || 0); 1 }; } # check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { next if $dir eq ''; my $abs = File::Spec->catfile($dir, $_[1]); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } # can we locate a (the) C compiler sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } # Fix Cygwin bug on maybe_command(); if ( $^O eq 'cygwin' ) { require ExtUtils::MM_Cygwin; require ExtUtils::MM_Win32; if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { *ExtUtils::MM_Cygwin::maybe_command = sub { my ($self, $file) = @_; if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { ExtUtils::MM_Win32->maybe_command($file); } else { ExtUtils::MM_Unix->maybe_command($file); } } } } 1; __END__ #line 156 jifty-1.10518+dfsg.orig/inc/Module/Install/Makefile.pm0000644000175000017500000002703211565005325020163 0ustar fsfs#line 1 package Module::Install::Makefile; use strict 'vars'; use ExtUtils::MakeMaker (); use Module::Install::Base (); use Fcntl qw/:flock :seek/; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub Makefile { $_[0] } my %seen = (); sub prompt { shift; # Infinite loop protection my @c = caller(); if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; } # In automated testing or non-interactive session, always use defaults if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) { local $ENV{PERL_MM_USE_DEFAULT} = 1; goto &ExtUtils::MakeMaker::prompt; } else { goto &ExtUtils::MakeMaker::prompt; } } # Store a cleaned up version of the MakeMaker version, # since we need to behave differently in a variety of # ways based on the MM version. my $makemaker = eval $ExtUtils::MakeMaker::VERSION; # If we are passed a param, do a "newer than" comparison. # Otherwise, just return the MakeMaker version. sub makemaker { ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0 } # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified # as we only need to know here whether the attribute is an array # or a hash or something else (which may or may not be appendable). my %makemaker_argtype = ( C => 'ARRAY', CONFIG => 'ARRAY', # CONFIGURE => 'CODE', # ignore DIR => 'ARRAY', DL_FUNCS => 'HASH', DL_VARS => 'ARRAY', EXCLUDE_EXT => 'ARRAY', EXE_FILES => 'ARRAY', FUNCLIST => 'ARRAY', H => 'ARRAY', IMPORTS => 'HASH', INCLUDE_EXT => 'ARRAY', LIBS => 'ARRAY', # ignore '' MAN1PODS => 'HASH', MAN3PODS => 'HASH', META_ADD => 'HASH', META_MERGE => 'HASH', PL_FILES => 'HASH', PM => 'HASH', PMLIBDIRS => 'ARRAY', PMLIBPARENTDIRS => 'ARRAY', PREREQ_PM => 'HASH', CONFIGURE_REQUIRES => 'HASH', SKIP => 'ARRAY', TYPEMAPS => 'ARRAY', XS => 'HASH', # VERSION => ['version',''], # ignore # _KEEP_AFTER_FLUSH => '', clean => 'HASH', depend => 'HASH', dist => 'HASH', dynamic_lib=> 'HASH', linkext => 'HASH', macro => 'HASH', postamble => 'HASH', realclean => 'HASH', test => 'HASH', tool_autosplit => 'HASH', # special cases where you can use makemaker_append CCFLAGS => 'APPENDABLE', DEFINE => 'APPENDABLE', INC => 'APPENDABLE', LDDLFLAGS => 'APPENDABLE', LDFROM => 'APPENDABLE', ); sub makemaker_args { my ($self, %new_args) = @_; my $args = ( $self->{makemaker_args} ||= {} ); foreach my $key (keys %new_args) { if ($makemaker_argtype{$key}) { if ($makemaker_argtype{$key} eq 'ARRAY') { $args->{$key} = [] unless defined $args->{$key}; unless (ref $args->{$key} eq 'ARRAY') { $args->{$key} = [$args->{$key}] } push @{$args->{$key}}, ref $new_args{$key} eq 'ARRAY' ? @{$new_args{$key}} : $new_args{$key}; } elsif ($makemaker_argtype{$key} eq 'HASH') { $args->{$key} = {} unless defined $args->{$key}; foreach my $skey (keys %{ $new_args{$key} }) { $args->{$key}{$skey} = $new_args{$key}{$skey}; } } elsif ($makemaker_argtype{$key} eq 'APPENDABLE') { $self->makemaker_append($key => $new_args{$key}); } } else { if (defined $args->{$key}) { warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n}; } $args->{$key} = $new_args{$key}; } } return $args; } # For mm args that take multiple space-seperated args, # append an argument to the current list. sub makemaker_append { my $self = shift; my $name = shift; my $args = $self->makemaker_args; $args->{$name} = defined $args->{$name} ? join( ' ', $args->{$name}, @_ ) : join( ' ', @_ ); } sub build_subdirs { my $self = shift; my $subdirs = $self->makemaker_args->{DIR} ||= []; for my $subdir (@_) { push @$subdirs, $subdir; } } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), ); } sub realclean_files { my $self = shift; my $realclean = $self->makemaker_args->{realclean} ||= {}; %$realclean = ( %$realclean, FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [ shift ]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } sub _wanted_t { } sub tests_recursive { my $self = shift; my $dir = shift || 't'; unless ( -d $dir ) { die "tests_recursive dir '$dir' does not exist"; } my %tests = map { $_ => 1 } split / /, ($self->tests || ''); require File::Find; File::Find::find( sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 }, $dir ); $self->tests( join ' ', sort keys %tests ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; # Check the current Perl version my $perl_version = $self->perl_version; if ( $perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; } # Make sure we have a new enough MakeMaker require ExtUtils::MakeMaker; if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) { # MakeMaker can complain about module versions that include # an underscore, even though its own version may contain one! # Hence the funny regexp to get rid of it. See RT #35800 # for details. my $v = $ExtUtils::MakeMaker::VERSION =~ /^(\d+\.\d+)/; $self->build_requires( 'ExtUtils::MakeMaker' => $v ); $self->configure_requires( 'ExtUtils::MakeMaker' => $v ); } else { # Allow legacy-compatibility with 5.005 by depending on the # most recent EU:MM that supported 5.005. $self->build_requires( 'ExtUtils::MakeMaker' => 6.42 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.42 ); } # Generate the MakeMaker params my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name; $args->{NAME} =~ s/-/::/g; $args->{VERSION} = $self->version or die <<'EOT'; ERROR: Can't determine distribution version. Please specify it explicitly via 'version' in Makefile.PL, or set a valid $VERSION in a module, and provide its file path via 'version_from' (or 'all_from' if you prefer) in Makefile.PL. EOT $DB::single = 1; if ( $self->tests ) { my @tests = split ' ', $self->tests; my %seen; $args->{test} = { TESTS => (join ' ', grep {!$seen{$_}++} @tests), }; } elsif ( $Module::Install::ExtraTests::use_extratests ) { # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness. # So, just ignore our xt tests here. } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { $args->{test} = { TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ), }; } if ( $] >= 5.005 ) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = join ', ', @{$self->author || []}; } if ( $self->makemaker(6.10) ) { $args->{NO_META} = 1; #$args->{NO_MYMETA} = 1; } if ( $self->makemaker(6.17) and $self->sign ) { $args->{SIGN} = 1; } unless ( $self->is_admin ) { delete $args->{SIGN}; } if ( $self->makemaker(6.31) and $self->license ) { $args->{LICENSE} = $self->license; } my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->requires) ); # Remove any reference to perl, PREREQ_PM doesn't support it delete $args->{PREREQ_PM}->{perl}; # Merge both kinds of requires into BUILD_REQUIRES my $build_prereq = ($args->{BUILD_REQUIRES} ||= {}); %$build_prereq = ( %$build_prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->configure_requires, $self->build_requires) ); # Remove any reference to perl, BUILD_REQUIRES doesn't support it delete $args->{BUILD_REQUIRES}->{perl}; # Delete bundled dists from prereq_pm, add it to Makefile DIR my $subdirs = ($args->{DIR} || []); if ($self->bundles) { my %processed; foreach my $bundle (@{ $self->bundles }) { my ($mod_name, $dist_dir) = @$bundle; delete $prereq->{$mod_name}; $dist_dir = File::Basename::basename($dist_dir); # dir for building this module if (not exists $processed{$dist_dir}) { if (-d $dist_dir) { # List as sub-directory to be processed by make push @$subdirs, $dist_dir; } # Else do nothing: the module is already present on the system $processed{$dist_dir} = undef; } } } unless ( $self->makemaker('6.55_03') ) { %$prereq = (%$prereq,%$build_prereq); delete $args->{BUILD_REQUIRES}; } if ( my $perl_version = $self->perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; if ( $self->makemaker(6.48) ) { $args->{MIN_PERL_VERSION} = $perl_version; } } if ($self->installdirs) { warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS}; $args->{INSTALLDIRS} = $self->installdirs; } my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_} ) } keys %$args; my $user_preop = delete $args{dist}->{PREOP}; if ( my $preop = $self->admin->preop($user_preop) ) { foreach my $key ( keys %$preop ) { $args{dist}->{$key} = $preop->{$key}; } } my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); } sub fix_up_makefile { my $self = shift; my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); local *MAKEFILE; open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; eval { flock MAKEFILE, LOCK_EX }; my $makefile = do { local $/; }; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; # Module::Install will never be used to build the Core Perl # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; # XXX - This is currently unused; not sure if it breaks other MM-users # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; seek MAKEFILE, 0, SEEK_SET; truncate MAKEFILE, 0; print MAKEFILE "$preamble$makefile$postamble" or die $!; close MAKEFILE or die $!; 1; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 541 jifty-1.10518+dfsg.orig/inc/Module/Install/Share.pm0000644000175000017500000000464311565005332017511 0ustar fsfs#line 1 package Module::Install::Share; use strict; use Module::Install::Base (); use File::Find (); use ExtUtils::Manifest (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub install_share { my $self = shift; my $dir = @_ ? pop : 'share'; my $type = @_ ? shift : 'dist'; unless ( defined $type and $type eq 'module' or $type eq 'dist' ) { die "Illegal or invalid share dir type '$type'"; } unless ( defined $dir and -d $dir ) { require Carp; Carp::croak("Illegal or missing directory install_share param: '$dir'"); } # Split by type my $S = ($^O eq 'MSWin32') ? "\\" : "\/"; my $root; if ( $type eq 'dist' ) { die "Too many parameters to install_share" if @_; # Set up the install $root = "\$(INST_LIB)${S}auto${S}share${S}dist${S}\$(DISTNAME)"; } else { my $module = Module::Install::_CLASS($_[0]); unless ( defined $module ) { die "Missing or invalid module name '$_[0]'"; } $module =~ s/::/-/g; $root = "\$(INST_LIB)${S}auto${S}share${S}module${S}$module"; } my $manifest = -r 'MANIFEST' ? ExtUtils::Manifest::maniread() : undef; my $skip_checker = $ExtUtils::Manifest::VERSION >= 1.54 ? ExtUtils::Manifest::maniskip() : ExtUtils::Manifest::_maniskip(); my $postamble = ''; my $perm_dir = eval($ExtUtils::MakeMaker::VERSION) >= 6.52 ? '$(PERM_DIR)' : 755; File::Find::find({ no_chdir => 1, wanted => sub { my $path = File::Spec->abs2rel($_, $dir); if (-d $_) { return if $skip_checker->($File::Find::name); $postamble .=<<"END"; \t\$(NOECHO) \$(MKPATH) "$root${S}$path" \t\$(NOECHO) \$(CHMOD) $perm_dir "$root${S}$path" END } else { return if ref $manifest && !exists $manifest->{$File::Find::name}; return if $skip_checker->($File::Find::name); $postamble .=<<"END"; \t\$(NOECHO) \$(CP) "$dir${S}$path" "$root${S}$path" END } }, }, $dir); # Set up the install $self->postamble(<<"END_MAKEFILE"); config :: $postamble END_MAKEFILE # The above appears to behave incorrectly when used with old versions # of ExtUtils::Install (known-bad on RHEL 3, with 5.8.0) # So when we need to install a share directory, make sure we add a # dependency on a moderately new version of ExtUtils::MakeMaker. $self->build_requires( 'ExtUtils::MakeMaker' => '6.11' ); # 99% of the time we don't want to index a shared dir $self->no_index( directory => $dir ); } 1; __END__ #line 154 jifty-1.10518+dfsg.orig/inc/Module/Install/Win32.pm0000644000175000017500000000340311565005332017342 0ustar fsfs#line 1 package Module::Install::Win32; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.01'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # determine if the user needs nmake, and download it if needed sub check_nmake { my $self = shift; $self->load('can_run'); $self->load('get_file'); require Config; return unless ( $^O eq 'MSWin32' and $Config::Config{make} and $Config::Config{make} =~ /^nmake\b/i and ! $self->can_run('nmake') ); print "The required 'nmake' executable not found, fetching it...\n"; require File::Basename; my $rv = $self->get_file( url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', local_dir => File::Basename::dirname($^X), size => 51928, run => 'Nmake15.exe /o > nul', check_for => 'Nmake.exe', remove => 1, ); die <<'END_MESSAGE' unless $rv; ------------------------------------------------------------------------------- Since you are using Microsoft Windows, you will need the 'nmake' utility before installation. It's available at: http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe or ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe Please download the file manually, save it to a directory in %PATH% (e.g. C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to that directory, and run "Nmake15.exe" from there; that will create the 'nmake.exe' file needed by this module. You may then resume the installation process described in README. ------------------------------------------------------------------------------- END_MESSAGE } 1; jifty-1.10518+dfsg.orig/inc/Module/AutoInstall.pm0000644000175000017500000005423111565005325017300 0ustar fsfs#line 1 package Module::AutoInstall; use strict; use Cwd (); use ExtUtils::MakeMaker (); use vars qw{$VERSION}; BEGIN { $VERSION = '1.03'; } # special map on pre-defined feature sets my %FeatureMap = ( '' => 'Core Features', # XXX: deprecated '-core' => 'Core Features', ); # various lexical flags my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS ); my ( $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps ); my ( $PostambleActions, $PostambleUsed ); # See if it's a testing or non-interactive session _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN ); _init(); sub _accept_default { $AcceptDefault = shift; } sub missing_modules { return @Missing; } sub do_install { __PACKAGE__->install( [ $Config ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) : () ], @Missing, ); } # initialize various flags, and/or perform install sub _init { foreach my $arg ( @ARGV, split( /[\s\t]+/, $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || '' ) ) { if ( $arg =~ /^--config=(.*)$/ ) { $Config = [ split( ',', $1 ) ]; } elsif ( $arg =~ /^--installdeps=(.*)$/ ) { __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); exit 0; } elsif ( $arg =~ /^--default(?:deps)?$/ ) { $AcceptDefault = 1; } elsif ( $arg =~ /^--check(?:deps)?$/ ) { $CheckOnly = 1; } elsif ( $arg =~ /^--skip(?:deps)?$/ ) { $SkipInstall = 1; } elsif ( $arg =~ /^--test(?:only)?$/ ) { $TestOnly = 1; } elsif ( $arg =~ /^--all(?:deps)?$/ ) { $AllDeps = 1; } } } # overrides MakeMaker's prompt() to automatically accept the default choice sub _prompt { goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault; my ( $prompt, $default ) = @_; my $y = ( $default =~ /^[Yy]/ ); print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] '; print "$default\n"; return $default; } # the workhorse sub import { my $class = shift; my @args = @_ or return; my $core_all; print "*** $class version " . $class->VERSION . "\n"; print "*** Checking for Perl dependencies...\n"; my $cwd = Cwd::cwd(); $Config = []; my $maxlen = length( ( sort { length($b) <=> length($a) } grep { /^[^\-]/ } map { ref($_) ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} ) : '' } map { +{@args}->{$_} } grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} } )[0] ); # We want to know if we're under CPAN early to avoid prompting, but # if we aren't going to try and install anything anyway then skip the # check entirely since we don't want to have to load (and configure) # an old CPAN just for a cosmetic message $UnderCPAN = _check_lock(1) unless $SkipInstall; while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) { my ( @required, @tests, @skiptests ); my $default = 1; my $conflict = 0; if ( $feature =~ m/^-(\w+)$/ ) { my $option = lc($1); # check for a newer version of myself _update_to( $modules, @_ ) and return if $option eq 'version'; # sets CPAN configuration options $Config = $modules if $option eq 'config'; # promote every features to core status $core_all = ( $modules =~ /^all$/i ) and next if $option eq 'core'; next unless $option eq 'core'; } print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n"; $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' ); unshift @$modules, -default => &{ shift(@$modules) } if ( ref( $modules->[0] ) eq 'CODE' ); # XXX: bugward combatability while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) { if ( $mod =~ m/^-(\w+)$/ ) { my $option = lc($1); $default = $arg if ( $option eq 'default' ); $conflict = $arg if ( $option eq 'conflict' ); @tests = @{$arg} if ( $option eq 'tests' ); @skiptests = @{$arg} if ( $option eq 'skiptests' ); next; } printf( "- %-${maxlen}s ...", $mod ); if ( $arg and $arg =~ /^\D/ ) { unshift @$modules, $arg; $arg = 0; } # XXX: check for conflicts and uninstalls(!) them. my $cur = _load($mod); if (_version_cmp ($cur, $arg) >= 0) { print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n"; push @Existing, $mod => $arg; $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { if (not defined $cur) # indeed missing { print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n"; } else { # no need to check $arg as _version_cmp ($cur, undef) would satisfy >= above print "too old. ($cur < $arg)\n"; } push @required, $mod => $arg; } } next unless @required; my $mandatory = ( $feature eq '-core' or $core_all ); if ( !$SkipInstall and ( $CheckOnly or ($mandatory and $UnderCPAN) or $AllDeps or _prompt( qq{==> Auto-install the } . ( @required / 2 ) . ( $mandatory ? ' mandatory' : ' optional' ) . qq{ module(s) from CPAN?}, $default ? 'y' : 'n', ) =~ /^[Yy]/ ) ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } elsif ( !$SkipInstall and $default and $mandatory and _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', ) =~ /^[Nn]/ ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { $DisabledTests{$_} = 1 for map { glob($_) } @tests; } } if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) { require Config; print "*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n"; # make an educated guess of whether we'll need root permission. print " (You may need to do that as the 'root' user.)\n" if eval '$>'; } print "*** $class configuration finished.\n"; chdir $cwd; # import to main:: no strict 'refs'; *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main'; return (@Existing, @Missing); } sub _running_under { my $thing = shift; print <<"END_MESSAGE"; *** Since we're running under ${thing}, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } # Check to see if we are currently running under CPAN.pm and/or CPANPLUS; # if we are, then we simply let it taking care of our dependencies sub _check_lock { return unless @Missing or @_; my $cpan_env = $ENV{PERL5_CPAN_IS_RUNNING}; if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) { return _running_under($cpan_env ? 'CPAN' : 'CPANPLUS'); } require CPAN; if ($CPAN::VERSION > '1.89') { if ($cpan_env) { return _running_under('CPAN'); } return; # CPAN.pm new enough, don't need to check further } # last ditch attempt, this -will- configure CPAN, very sorry _load_cpan(1); # force initialize even though it's already loaded # Find the CPAN lock-file my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" ); return unless -f $lock; # Check the lock local *LOCK; return unless open(LOCK, $lock); if ( ( $^O eq 'MSWin32' ? _under_cpan() : == getppid() ) and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore' ) { print <<'END_MESSAGE'; *** Since we're running under CPAN, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } close LOCK; return; } sub install { my $class = shift; my $i; # used below to strip leading '-' from config keys my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } ); my ( @modules, @installed ); while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) { # grep out those already installed if ( _version_cmp( _load($pkg), $ver ) >= 0 ) { push @installed, $pkg; } else { push @modules, $pkg, $ver; } } return @installed unless @modules; # nothing to do return @installed if _check_lock(); # defer to the CPAN shell print "*** Installing dependencies...\n"; return unless _connected_to('cpan.org'); my %args = @config; my %failed; local *FAILED; if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) { while () { chomp; $failed{$_}++ } close FAILED; my @newmod; while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) { push @newmod, ( $k => $v ) unless $failed{$k}; } @modules = @newmod; } if ( _has_cpanplus() and not $ENV{PERL_AUTOINSTALL_PREFER_CPAN} ) { _install_cpanplus( \@modules, \@config ); } else { _install_cpan( \@modules, \@config ); } print "*** $class installation finished.\n"; # see if we have successfully installed them while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { if ( _version_cmp( _load($pkg), $ver ) >= 0 ) { push @installed, $pkg; } elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) { print FAILED "$pkg\n"; } } close FAILED if $args{do_once}; return @installed; } sub _install_cpanplus { my @modules = @{ +shift }; my @config = _cpanplus_config( @{ +shift } ); my $installed = 0; require CPANPLUS::Backend; my $cp = CPANPLUS::Backend->new; my $conf = $cp->configure_object; return unless $conf->can('conf') # 0.05x+ with "sudo" support or _can_write($conf->_get_build('base')); # 0.04x # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $conf->get_conf('makeflags') || ''; if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) { # 0.03+ uses a hashref here $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST}; } else { # 0.02 and below uses a scalar $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); } $conf->set_conf( makeflags => $makeflags ); $conf->set_conf( prereqs => 1 ); while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) { $conf->set_conf( $key, $val ); } my $modtree = $cp->module_tree; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { print "*** Installing $pkg...\n"; MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; my $success; my $obj = $modtree->{$pkg}; if ( $obj and _version_cmp( $obj->{version}, $ver ) >= 0 ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $cp->install( modules => [ $obj->{module} ] ); if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation cancelled.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _cpanplus_config { my @config = (); while ( @_ ) { my ($key, $value) = (shift(), shift()); if ( $key eq 'prerequisites_policy' ) { if ( $value eq 'follow' ) { $value = CPANPLUS::Internals::Constants::PREREQ_INSTALL(); } elsif ( $value eq 'ask' ) { $value = CPANPLUS::Internals::Constants::PREREQ_ASK(); } elsif ( $value eq 'ignore' ) { $value = CPANPLUS::Internals::Constants::PREREQ_IGNORE(); } else { die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n"; } } else { die "*** Cannot convert option $key to CPANPLUS version.\n"; } } return @config; } sub _install_cpan { my @modules = @{ +shift }; my @config = @{ +shift }; my $installed = 0; my %args; _load_cpan(); require Config; if (CPAN->VERSION < 1.80) { # no "sudo" support, probe for writableness return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) ) and _can_write( $Config::Config{sitelib} ); } # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $CPAN::Config->{make_install_arg} || ''; $CPAN::Config->{make_install_arg} = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); # don't show start-up info $CPAN::Config->{inhibit_startup_message} = 1; # set additional options while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) { ( $args{$opt} = $arg, next ) if $opt =~ /^force$/; # pseudo-option $CPAN::Config->{$opt} = $arg; } local $CPAN::Config->{prerequisites_policy} = 'follow'; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; print "*** Installing $pkg...\n"; my $obj = CPAN::Shell->expand( Module => $pkg ); my $success = 0; if ( $obj and _version_cmp( $obj->cpan_version, $ver ) >= 0 ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $args{force} ? CPAN::Shell->force( install => $pkg ) : CPAN::Shell->install($pkg); $rv ||= eval { $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, ) ->{install} if $CPAN::META; }; if ( $rv eq 'YES' ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation failed.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _has_cpanplus { return ( $HasCPANPLUS = ( $INC{'CPANPLUS/Config.pm'} or _load('CPANPLUS::Shell::Default') ) ); } # make guesses on whether we're under the CPAN installation directory sub _under_cpan { require Cwd; require File::Spec; my $cwd = File::Spec->canonpath( Cwd::cwd() ); my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} ); return ( index( $cwd, $cpan ) > -1 ); } sub _update_to { my $class = __PACKAGE__; my $ver = shift; return if _version_cmp( _load($class), $ver ) >= 0; # no need to upgrade if ( _prompt( "==> A newer version of $class ($ver) is required. Install?", 'y' ) =~ /^[Nn]/ ) { die "*** Please install $class $ver manually.\n"; } print << "."; *** Trying to fetch it from CPAN... . # install ourselves _load($class) and return $class->import(@_) if $class->install( [], $class, $ver ); print << '.'; exit 1; *** Cannot bootstrap myself. :-( Installation terminated. . } # check if we're connected to some host, using inet_aton sub _connected_to { my $site = shift; return ( ( _load('Socket') and Socket::inet_aton($site) ) or _prompt( qq( *** Your host cannot resolve the domain name '$site', which probably means the Internet connections are unavailable. ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/ ); } # check if a directory is writable; may create it on demand sub _can_write { my $path = shift; mkdir( $path, 0755 ) unless -e $path; return 1 if -w $path; print << "."; *** You are not allowed to write to the directory '$path'; the installation may fail due to insufficient permissions. . if ( eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt( qq( ==> Should we try to re-execute the autoinstall process with 'sudo'?), ((-t STDIN) ? 'y' : 'n') ) =~ /^[Yy]/ ) { # try to bootstrap ourselves from sudo print << "."; *** Trying to re-execute the autoinstall process with 'sudo'... . my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; return unless system( 'sudo', $^X, $0, "--config=$config", "--installdeps=$missing" ); print << "."; *** The 'sudo' command exited with error! Resuming... . } return _prompt( qq( ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/; } # load a module and return the version it reports sub _load { my $mod = pop; # class/instance doesn't matter my $file = $mod; $file =~ s|::|/|g; $file .= '.pm'; local $@; return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 ); } # Load CPAN.pm and it's configuration sub _load_cpan { return if $CPAN::VERSION and $CPAN::Config and not @_; require CPAN; # CPAN-1.82+ adds CPAN::Config::AUTOLOAD to redirect to # CPAN::HandleConfig->load. CPAN reports that the redirection # is deprecated in a warning printed at the user. # CPAN-1.81 expects CPAN::HandleConfig->load, does not have # $CPAN::HandleConfig::VERSION but cannot handle # CPAN::Config->load # Which "versions expect CPAN::Config->load? if ( $CPAN::HandleConfig::VERSION || CPAN::HandleConfig->can('load') ) { # Newer versions of CPAN have a HandleConfig module CPAN::HandleConfig->load; } else { # Older versions had the load method in Config directly CPAN::Config->load; } } # compare two versions, either use Sort::Versions or plain comparison # return values same as <=> sub _version_cmp { my ( $cur, $min ) = @_; return -1 unless defined $cur; # if 0 keep comparing return 1 unless $min; $cur =~ s/\s+$//; # check for version numbers that are not in decimal format if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) { if ( ( $version::VERSION or defined( _load('version') )) and version->can('new') ) { # use version.pm if it is installed. return version->new($cur) <=> version->new($min); } elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) ) { # use Sort::Versions as the sorting algorithm for a.b.c versions return Sort::Versions::versioncmp( $cur, $min ); } warn "Cannot reliably compare non-decimal formatted versions.\n" . "Please install version.pm or Sort::Versions.\n"; } # plain comparison local $^W = 0; # shuts off 'not numeric' bugs return $cur <=> $min; } # nothing; this usage is deprecated. sub main::PREREQ_PM { return {}; } sub _make_args { my %args = @_; $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing } if $UnderCPAN or $TestOnly; if ( $args{EXE_FILES} and -e 'MANIFEST' ) { require ExtUtils::Manifest; my $manifest = ExtUtils::Manifest::maniread('MANIFEST'); $args{EXE_FILES} = [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ]; } $args{test}{TESTS} ||= 't/*.t'; $args{test}{TESTS} = join( ' ', grep { !exists( $DisabledTests{$_} ) } map { glob($_) } split( /\s+/, $args{test}{TESTS} ) ); my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; $PostambleActions = ( ($missing and not $UnderCPAN) ? "\$(PERL) $0 --config=$config --installdeps=$missing" : "\$(NOECHO) \$(NOOP)" ); return %args; } # a wrapper to ExtUtils::MakeMaker::WriteMakefile sub Write { require Carp; Carp::croak "WriteMakefile: Need even number of args" if @_ % 2; if ($CheckOnly) { print << "."; *** Makefile not written in check-only mode. . return; } my %args = _make_args(@_); no strict 'refs'; $PostambleUsed = 0; local *MY::postamble = \&postamble unless defined &MY::postamble; ExtUtils::MakeMaker::WriteMakefile(%args); print << "." unless $PostambleUsed; *** WARNING: Makefile written with customized MY::postamble() without including contents from Module::AutoInstall::postamble() -- auto installation features disabled. Please contact the author. . return 1; } sub postamble { $PostambleUsed = 1; return <<"END_MAKE"; config :: installdeps \t\$(NOECHO) \$(NOOP) checkdeps :: \t\$(PERL) $0 --checkdeps installdeps :: \t$PostambleActions END_MAKE } 1; __END__ #line 1071 jifty-1.10518+dfsg.orig/doc/0000755000175000017500000000000011625457665013264 5ustar fsfsjifty-1.10518+dfsg.orig/doc/declarative-test-design0000644000175000017500000000574411447473535017724 0ustar fsfs# -*- mode: cperl -*- # A ``setup'' block indicates tests that must pass for any of the # remaining tests to continue. setup { BTDT::Test->log_in; expect_url(qr{/todo}); follow_link 'Groups'; expect_url(qr{/groups}); expect_content('alpha'); # These are custom local methods; not Test::WWW::Whatever ones. make_and_verify_group($mech, name => 'my folks', desc => 'stuff'); make_and_verify_group($mech, name => 'blue pants', desc => 'some description'); make_and_verify_group_trimming($mech, name => ' leading and trailing spaces ', desc => ' more spaces here '); make_and_verify_group($mech, name => 'other folks'); } # Each ``test'' block is its own test. If anything fails, we abort the # current test block, and continue with the next one. test { follow_link 'Groups'; follow_link 'New Group'; submit_action 'newgroup', { name => 'my folks' }; expect_url { not => qr{groups/\d+/members} }; expect_url qr{/groups/create}; find_input { value => "my folks" }; expect_content qr{Sorry, but someone else beat you to that name}; }; test { follow_link 'my folks'; follow_link 'Members'; expect_url qr{/groups/\d+/members}; expect_content 'Manage group members'; expect_content 'my folks'; expect_content qr{Good Test *organizer} }; test { follow_link 'my folks'; follow_link 'My tasks'; follow_link 'Braindump'; expect_content 'See more syntax for braindump'; fill_action 'quickcreate', { text => 'Buy new computer [personal money]' }; click { button => 'Create' }; expect { content => 'Buy new computer' }; expect_content_not 'See more syntax for braindump'; follow_link 'my folks' => 'My tasks' => 'Braindump'; submit_action 'quickcreate', { text => 'Buy new computer [personal money]' }, { button => 'Create' }; click 'Edit'; submit_action find_action('BTDT::Action::UpdateTask'), { owner_id => 'otheruser@example.com' }; } test { new_session { log_in 'otheruser@example.com', 'something'; click 'unaccepted'; page { content => 'Pay off Mafia' }; click 'Pay off Mafia'; # Manual submit_action find_element { name => qr{J:A-(?:\d+)?accept} }; submit_form { 'J:A:F-accepted-accept' => 1 }; page { content => 'Task accepted', content_lacks => 'denied' }; }; }; # Various ways of specifying tests should only run under certain # platforms with ('javascript') => test { }; test { browser 'iexplore'; }; test { browser 'WWW::Mechanize'; }; test { need_feature 'XMLHTTPRequest'; }; run_all; # A syntax idea from jesse: flow "Check to see if the user can login" => test { get '/'; element '//body' matches /You're not logged in/; follow link 'Login'; my $login_form = element id 'login-form' fill $login_form => { email => 'jesse@fsck.com', password => 'I hate you' } click button 'Login!'; } jifty-1.10518+dfsg.orig/doc/jifty-dispatcher.graffle0000644000175000017500000015535011447473535020072 0ustar fsfs ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 CreationDate 2006-07-09 18:16:50 -0400 Creator Audrey Tang DisplayScale 1 cm = 1 cm GraphDocumentVersion 5 GraphicsList Bounds {{1835, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 56 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Partial orders between mounted dispatchers} Bounds {{1835, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 54 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 plugin} Bounds {{809, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 123 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Topic} Bounds {{1673, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 121 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Flow control} Bounds {{1565, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 117 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Goto (for "before/on" stage)} Bounds {{1457, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 111 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 =request params initially} Bounds {{1349, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 109 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Stash manipulation} Bounds {{1727, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 131 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 already_run} Bounds {{1619, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 119 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 next_rule/last_rule/abort} Bounds {{1511, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 113 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 show/redirect/dispatch} Bounds {{1403, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 106 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 get/set/default/del} Bounds {{1295, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 2 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 when/under} Bounds {{1295, 279}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 103 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 \{child; child\}} Bounds {{1187, 279}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 101 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 [child, child]} Bounds {{1241, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 99 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Numerous children} Bounds {{1133, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 89 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 run \{...\} \\&sub 'sub'} Bounds {{1025, 360}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 70 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 /foo/*/\{bar,baz\}} Bounds {{1025, 279}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 85 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 (may be compiled from shellglob)} Bounds {{1025, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 68 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Regex on PATH} Bounds {{917, 198}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 82 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 GET/POST/etc} Bounds {{1565, 36}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 105 Shape Rectangle Style fill GradientColor w 0.666667 MiddleColor w 0.333333 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Body actions} Bounds {{1187, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 72 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Body} Bounds {{971, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 79 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Condition} Bounds {{1079, 36}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 78 Shape Rectangle Style fill GradientColor w 0.666667 MiddleColor w 0.333333 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Rule} Bounds {{539, 36}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 45 Shape Rectangle Style fill GradientColor w 0.666667 MiddleColor w 0.333333 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Stages} Bounds {{809, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 50 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 after} Bounds {{701, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 129 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Display new Actions} Bounds {{593, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 48 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 on} Bounds {{485, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 125 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 Run prev Actions} Bounds {{377, 117}, {72, 45}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 46 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10002\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc \f0\fs24 \cf0 \expnd0\expndtw0\kerning0 before} Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 46 ID 8 Points {538.553, 76.7236} {449.447, 121.276} Style stroke HeadArrow 0 TailArrow 0 Tail ID 45 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 48 ID 47 Points {590.277, 81.416} {613.723, 116.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 45 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 50 ID 49 Points {611.479, 69.4437} {808.521, 128.556} Style stroke HeadArrow 0 TailArrow 0 Tail ID 45 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 79 ID 80 Points {1084.6, 81.3} {1037.4, 116.7} Style stroke HeadArrow 0 TailArrow 0 Tail ID 78 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 82 ID 81 Points {991.723, 162.416} {968.277, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 79 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 68 ID 83 Points {1022.28, 162.416} {1045.72, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 79 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 85 ID 84 Points {1061, 243.5} {1061, 278.5} Style stroke HeadArrow 0 TailArrow 0 Tail ID 68 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 70 ID 86 Points {1061, 324.5} {1061, 359.5} Style stroke HeadArrow 0 TailArrow 0 Tail ID 85 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 72 ID 87 Points {1145.4, 81.3} {1192.6, 116.7} Style stroke HeadArrow 0 TailArrow 0 Tail ID 78 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 89 ID 88 Points {1207.72, 162.416} {1184.28, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 72 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 99 ID 98 Points {1238.28, 162.416} {1261.72, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 72 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 101 ID 100 Points {1261.72, 243.416} {1238.28, 278.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 99 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 103 ID 102 Points {1292.28, 243.416} {1315.72, 278.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 99 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 106 ID 107 Points {1564.55, 76.7236} {1475.45, 121.276} Style stroke HeadArrow 0 TailArrow 0 Tail ID 105 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 109 ID 108 Points {1423.72, 162.416} {1400.28, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 106 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 111 ID 110 Points {1454.28, 162.416} {1477.72, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 106 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 113 ID 112 Points {1585.72, 81.416} {1562.28, 116.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 105 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 117 ID 116 Points {1562.28, 162.416} {1585.72, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 113 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 119 ID 118 Points {1616.28, 81.416} {1639.72, 116.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 105 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 121 ID 120 Points {1670.28, 162.416} {1693.72, 197.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 119 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 123 ID 122 Points {845, 162.5} {845, 197.5} Style stroke HeadArrow 0 TailArrow 0 Tail ID 50 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 125 ID 124 Points {559.723, 81.416} {536.277, 116.584} Style stroke HeadArrow 0 TailArrow 0 Tail ID 45 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 129 ID 128 Points {611.447, 76.7236} {700.553, 121.276} Style stroke HeadArrow 0 TailArrow 0 Tail ID 45 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 131 ID 130 Points {1637.45, 76.7236} {1726.55, 121.276} Style stroke HeadArrow 0 TailArrow 0 Tail ID 105 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 54 ID 132 Points {1637.48, 69.4437} {1834.52, 128.556} Style stroke HeadArrow 0 TailArrow 0 Tail ID 105 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 56 ID 135 Points {1871, 162.5} {1871, 197.5} Style stroke HeadArrow 0 TailArrow 0 Tail ID 54 Class LineGraphic FontInfo Font LiHeiPro Size 24 Head ID 2 ID 137 Points {1564.52, 69.4437} {1367.48, 128.556} Style stroke HeadArrow 0 TailArrow 0 Tail ID 105 GridInfo GuidesLocked NO GuidesVisible YES HPages 4 ImageCounter 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo LayoutTarget 3 LineLength 0.10000000149011612 Spring 1.8235714435577393 LinksVisible NO MagnetsVisible NO MasterSheet Master 1 MasterSheets ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 cm = 1 cm GraphicsList GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo LayoutTarget 3 Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle Master 1 UniqueID 1 VPages 1 ModificationDate 2006-07-09 19:23:03 -0400 Modifier Audrey Tang NotesVisible NO Orientation 2 OriginVisible NO OutlineStyle Basic PageBreaks YES PrintInfo NSBottomMargin float 0 NSLeftMargin float 0 NSRightMargin float 0 NSTopMargin float 0 ReadOnly NO RowAlign 1 RowSpacing 36 SheetTitle Canvas 1 SmartAlignmentGuidesActive YES SmartDistanceGuidesActive YES UniqueID 1 UseEntirePage VPages 1 WindowInfo CurrentSheet 0 DrawerOpen DrawerTab Outline DrawerWidth 209 FitInWindow Frame {{500, 4}, {586, 742}} ShowRuler ShowStatusBar VisibleRegion {{1496, 4}, {571, 628}} Zoom 1 jifty-1.10518+dfsg.orig/doc/building_a_par0000644000175000017500000000573011447473535016147 0ustar fsfsIncomplete instructions $ pp `find lib/ -name \*pm |perl -ne '$_ =~ s/.pm$//;print "-M ". join("::",grep { ! /(?:lib|\-)/ } split("/",$_)) '` -I lib bin/jifty use warnings; use strict; use Cwd qw(cwd); use Module::CoreList; use File::Copy; use File::Path qw(mkpath); use File::Spec::Functions qw(splitdir catfile catdir); use CPAN; use CPAN::Config; use YAML; use Time::Local; @INC = grep {! /local/} @INC; # don't want cpan.pm to make decisions based locally installed modules; use vars qw/$INSTALLED $FAILED $SKIP_DEPS_FOR/; $INSTALLED = {}; $FAILED = {}; $SKIP_DEPS_FOR = { }; process_cpan(); sub process_cpan { # my $self = shift; my $path = cwd(); my @modules = @ARGV; # We install Scalar::Util first to break a scary dependency loop. mkdir "$path/.cpan"; mkdir "$path/.cpan/build"; print join "\n", @modules, "\n"; unshift @INC, '$path/lib'; $ENV{'PERL5LIB'} = "$path/lib"; $CPAN::Config->{build_dir} = "$path/.cpan/build"; $CPAN::Config->{cpan_home} = "$path/.cpan/build"; $CPAN::Config->{histfile} = "$path/.cpan/histfile;"; $CPAN::Config->{keep_source_where} = "$path/.cpan/sources"; $CPAN::Config->{prerequisites_policy} = "follow"; $CPAN::Config->{makepl_arg} = "PREFIX=$path PERL5LIB=$path/lib LIB=$path/lib INSTALLMAN1DIR=$path/man/man1 INSTALLMAN3DIR=$path/man/man3 INSTALLBIN=$path/bin INSTALLSCRIPT=$path/bin"; $CPAN::Config->{make_install_arg} =~ s/UNINST=1//; my @objs = map { CPAN::Shell->expand( 'Module', $_ ) } @modules; for my $i ( 0 .. $#objs ) { delete $objs[$i] if grep { $_->{RO}->{CPAN_FILE} eq $objs[$i]->{RO}->{CPAN_FILE} } @objs[ $i + 1 .. $#objs ]; } foreach my $mod (@modules) { #foreach my $mod ( grep { defined $_ } @objs ) { install_mod($mod); } print YAML::Dump($FAILED); } sub install_mod { my $mod_name = shift; my $version = shift; my $mod = CPAN::Shell->expand( 'Module', $mod_name ); my $first_in = Module::CoreList->first_release($mod_name => $version); if ( defined $first_in and $first_in <= 5.00803 ) { print "Skipping $mod_name. It's been core since $first_in\n"; return } if ( $mod->distribution->isa_perl ) { print "Skipping $mod_name. It's only in the core. OOPS\n";return} if ( $INSTALLED->{ $mod->cpan_file } ) { print "Skipping $mod_name. We've already installed it\n";return} if ( $FAILED->{ $mod->cpan_file } >= 3 ) { print YAML::Dump($INSTALLED); print YAML::Dump($FAILED); die "We've tried to install " . $mod->distribution->as_string . " twice"; } # Install to local unless ( $SKIP_DEPS_FOR->{$mod_name} ) { $mod->make; my $deps = $mod->distribution->prereq_pm; foreach my $dep ( keys %$deps ) { install_mod($dep => $deps->{$dep}); } } #$mod->force(); $mod->install; $INSTALLED->{ $mod->cpan_file } = 1; } 1; jifty-1.10518+dfsg.orig/doc/command_naming0000644000175000017500000000057611447473535016162 0ustar fsfsCurrent commands are all nouns. we should be moving to simple active verbs jifty server -> jifty run jifty fastcgi -> jifty run --fastcgi jifty action -> jifty create --action= jifty app -> jifty create --app= jifty model -> Jifty create --model= jifty schema -> jifty setup --schema jifty po -> jifty setup --lexicon / jifty create --lexicon jifty-1.10518+dfsg.orig/doc/packaging0000644000175000017500000000505611447473535015135 0ustar fsfsFor Jifty: * It should be possible for Jifty's developers to package bin/jifty as a single platform-specifc "runnable" application, including lib/ share/ and all non-core perl dependencies. (+ libraries?) For any Jifty application: * It should be possible for an end-user to package the source code of a Jifty application as a single platform-specific "runnable" application. * Ideally, it should be possible to turn a packaged application into an unpacked copy of the application's source code and dependent libraries. * It should be possible to install a Jifty application on a local disk such that multiple instances of the application can run with only a site_config.yml file. (or without it) * It should be possible for an end user of one of these installed applications to snapshot the application and all its assets, internal libraries and dependencies to a private directory) In all cases: * --with-deps includes the installed versions of our dependencies. * plugins are treated as CPAN dists for the purposes of dependency management jifty package --file /tmp/myapp.exe --with-deps * Takes multiple forms of targets * Defaults to the zipped form * --file is the path of the output file jifty dist --with-deps * make a source distribution of this application, suitable for handing to a developer jifty isolate --with-deps * needs a better name * Pull in all dependencies, as well as jifty. jifty install/uninstall * some sort of management. will also work on plugins # A dist blib builder # A dist blib packager (->zip with a makefile.pl - it works as a par and as a dist) # Package multiple dists as a single dist. # Pony: an automatic deps-writer that will design a list of deps for the systemwide currently installed modules. # Must include shared libs (expat, svn, etc) # Some way to deal with systemwide shared libs, like Pg # an alien extractor that analyzes already-built XS libs (in either blib/ or sitelib) with platform-specific tools (ldd, xtools, etc) and pull in shared libraries, similar to how Alien::* currentl does it in a case-by-case basis. # A dist blib upgrader # A cpan workalike for jifty dists # An installation scheme for {$INSTALL_DIR,$APP_DIR}/share/jifty/deps/{`archname`,noarch} # one blib/ directory for the tuple of (dist, version, `arch` or "noarch" , perl version?) # an @INC populator pushes a glob for arch-independent (rename this: blib-noarch/* pushes a glob for per-arch libs blib-`arch`/* jifty-1.10518+dfsg.orig/doc/jifty-dispatcher.svg0000644000175000017500000004727411447473535017270 0ustar fsfs 2006-07-11 00:19ZCanvas 1Layer 1beforeRun prev ActionsonDisplay new ActionsafterStagesRuleConditionBodyBody actionsGET/POST/etcRegex on PATH(may be compiled from shellglob)/foo/*/{bar,baz}run {...} \&sub 'sub'Numerous children[child, child]{child; child}when/underget/set/default/delshow/redirect/dispatchnext_rule/last_rule/abortalready_runStash manipulation(=request params initially)Goto (for "before/on" stage)Flow controlpluginPartial orders between mounted dispatchers jifty-1.10518+dfsg.orig/doc/edit-in-place0000644000175000017500000000117511447473535015622 0ustar fsfs# These are dispatcher rules that halos and error handling need to be # able to edit files in place. These should become a plugin of some # sort, when we have that infrastructure. before '*', run { Jifty->api->allow(qr/^Jifty::Action::Devel/) if Jifty->config->framework('DevelMode'); }; on qr'^/__jifty/edit/(.*?)/(.*)$', run { my $editor = Jifty->web->new_action( class => 'Jifty::Action::Devel::FileEditor', moniker => 'editpage', arguments => { source_path => $2, file_type => $1, } ); set editor => $editor; show '/__jifty/edit_file'; }; jifty-1.10518+dfsg.orig/doc/examples/0000755000175000017500000000000011625457665015102 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/0000755000175000017500000000000011565006014017303 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/share/0000755000175000017500000000000011625457665020430 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/share/web/0000755000175000017500000000000011565006014021162 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/share/web/templates/0000755000175000017500000000000011565006014023160 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/share/web/templates/index.html0000644000175000017500000000117011447473535025173 0ustar fsfs<%args> $counter => 0 <%init> my $request; $request = Jifty::Request->new( path => Jifty->web->request->path ); $request->argument( counter => $counter + 1 ); my $up = Jifty::Continuation->new( request => $request ); $request = Jifty::Request->new( path => Jifty->web->request->path ); $request->argument( counter => $counter - 1 ); my $down = Jifty::Continuation->new( request => $request ); <&| /_elements/wrapper, title => "Continuations counter demo" &>

The counter is: <% $counter %>

<% Jifty->web->link(call => $down, label => '--') %> <% Jifty->web->link(call => $up, label => '++') %> jifty-1.10518+dfsg.orig/doc/examples/CounterDemo/t/0000755000175000017500000000000011565006011017543 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/t/00-counter-test.t0000644000175000017500000000257411447473535022633 0ustar fsfs#!/usr/bin/env perl use strict; use warnings; =head1 DESCRIPTION Basic continuation counter test. =cut use Jifty::Test tests => 20; use Jifty::Test::WWW::Mechanize; my $server = Jifty::Test->make_server; my $URL = $server->started_ok(); ok($URL, "Started the test server"); my $mech = Jifty::Test::WWW::Mechanize->new(); $mech->get_ok($URL, "Got the home page"); $mech->content_contains('The counter is: 0', "Counter starts at 0"); ok($mech->find_link(text => "++"), "Found the increment link"); $mech->follow_link_ok(text => "++"); $mech->content_contains('The counter is: 1', "Incremented the counter"); $mech->follow_link_ok(text => "++"); $mech->content_contains('The counter is: 2', "Incremented the counter"); $mech->follow_link_ok(text => "--"); $mech->content_contains('The counter is: 1', "Decremented the counter"); $mech->follow_link_ok(text => "--"); $mech->follow_link_ok(text => "--"); $mech->follow_link_ok(text => "--"); $mech->follow_link_ok(text => "--"); $mech->content_contains('The counter is: -3', "Decremented the counter 4 times"); $mech->back; $mech->back; $mech->content_contains('The counter is: -1', "Back at -1"); $mech->follow_link_ok(text => "--"); $mech->content_contains('The counter is: -2', "Going back then following links DTRT"); $mech->get($URL); $mech->content_contains('The counter is: 0', "Loading the initial page again resets the counter"); jifty-1.10518+dfsg.orig/doc/examples/CounterDemo/etc/0000755000175000017500000000000011625457665020101 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/etc/config.yml0000644000175000017500000000126111447473535022065 0ustar fsfs--- framework: AdminMode: 0 ApplicationClass: CounterDemo ApplicationName: CounterDemo Database: Database: counterdemo Driver: SQLite Host: localhost Password: '' RecordBaseClass: Jifty::DBI::Record::Cachable User: '' Version: 0.0.1 DevelMode: 1 L10N: PoDir: share/po LogLevel: INFO Mailer: Sendmail MailerArgs: [] Plugins: [] Web: BaseURL: http://localhost DataDir: var/mason Globals: [] MasonConfig: autoflush: 0 default_escape_flags: h error_format: text error_mode: fatal Port: 8888 ServeStaticFiles: 1 StaticRoot: share/web/static TemplateRoot: share/web/templates jifty-1.10518+dfsg.orig/doc/examples/CounterDemo/Makefile.PL0000644000175000017500000000015311447473535021273 0ustar fsfsuse inc::Module::Install; name('CounterDemo'); version('0.01'); requires('Jifty' => '0.60615'); WriteAll; jifty-1.10518+dfsg.orig/doc/examples/CounterDemo/bin/0000755000175000017500000000000011625457665020076 5ustar fsfsjifty-1.10518+dfsg.orig/doc/examples/CounterDemo/bin/jifty0000755000175000017500000000070011447473535021142 0ustar fsfs#!/usr/bin/env perl eval 'exec /usr/bin/env perl -S $0 ${1+"$@"}' if 0; # not running under some shell use warnings; use strict; use File::Basename qw(dirname); use UNIVERSAL::require; BEGIN { Jifty::Util->require or die $UNIVERSAL::require::ERROR; my $root = Jifty::Util->app_root; unshift @INC, "$root/lib" if ($root); } use Jifty::Script; $SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; }; Jifty::Script->dispatch(); jifty-1.10518+dfsg.orig/doc/notes-on-distributed-operations0000644000175000017500000002623211447473535021453 0ustar fsfsAsynchrony Synchrony Syncrony Syncron client-server sync is easy consistent distributed replication is ... harder how do we guarantee a coherent model of the world after sync? two possible models: - undo local transactions and replay them in globally unique order (This is the bayou model) - calculate big deltas to bring local and remote into sync svk pull -l, svk push -l - replay remote transactions locally until we conflict or are exhausted then batch until we resolve the conflict automatically or require external intervention, then turn around and do the other side? svk pull, svk push How do we deal with "on transaction" behaviour? Some rules should apply only on "this" replica - Send email when we get an update that matches Some rules should apply only when a record is created or modified by a local update (isn't syncced) - When we create a bug report, create a log entry Some rules should apply only when a record is synced - when we sync in a bug report, extract it's associated patches to the local filesystem in ~/patches/to-apply Getting toward a consistent result: All bayou replicas move toward 'eventual consistency' using anti-entropy syncs of deltas. " The Bayou system guarantees that all servers eventually receive all Writes via the pair-wise anti-entropy process and that two servers holding the same set of Writes will have the same data contents." " Two important features of the Bayou system design allows servers to achieve eventual consistency. First, Writes are per- formed in the same, well-defined order at all servers. Second, the conflict detection and merge procedures are deterministic so that servers resolve the same conflicts in the same manner." Merge behaviour: Bayou style: 'dependency checks' on write -- "Do any of the preconditions for my attempted write fail? (BayouConflictsSOSPPreprint.pdf) on conflict, run a "merge program" - merge programs are application specific. bayou defines standard categories of merge programs that developers can treat as templates when unresolvable conflicts hit, punt it to the user. Svn-style: textual merge is fine for simple property databases, but won't deal with "conflicting appointments" Access control: * Authentication All updates should be signed by an identity. Jesse resolves task 1: "Task 1, status changed from open to resolved" - Signed by 0xAAAA (Jesse) When propagating updates delivered to a replica by another identity, updates should carry their full pedigrees. Jesse syncs to clkao: "Task 1, status changed from open to resolved" - Signed by 0xAAAA (Jesse) Clkao syncs to audrey: "Task 1, status changed from open to resolved" - Signed by 0xAAAA (Jesse) - Propagated by 0xBBBB (Clkao) to 0xCCCC (Audreyt) at $TIME Hm. $TIME can't be a timestamp. we don't trust timestamps. Is there any reason to carry full pedigrees? It feels "right" to know how updates get carried around. When propagating lumped updates, we probably want to carry the components pedigrees. clkao understands all of this stuff a lot better than I do. I'm probably 80% wrong. * Authorization Defining characteristics of Bayou: (from eurosigops-96) • Clients can read from and write to any server. • Servers propagate writes among themselves via a pairwise anti-entropy protocol that permits incremental progress. • A new database replica, i.e. server, can be created from any existing replica. • New conflict detection and resolution procedures can be introduced at any time by clients and their applications. Bayou propagation of updates: a replica has a history of all changes. Changes are defined as 'committed' or 'tentative'. Tentative changes might get rolled back on conflict....so there's a log of all updates. the database can get rolled back and replayed based on new updates. the order of playback is globally consistent. we really don't want the distinction between tentative and committed. this would mean that 'lightweight' clients can't be used as a vector to decrease interserver entropy....it also means that clients can't sync with each other. this is a showstopper. sosp-97/AE.pdf describes the bayou anti-entropy replication protocol including an explanationf how to deal with servers which have truncated their write logs. The rollback and insert new transactions scheme described by AE.pdf sounds an awful lot like what Sam Vilain has been doing with splicing perl history, though presents additional challenges not present in a pure software version control system. the splice can introduce new data that needs to propagate forward. While bayou servers are weakly connected, they appear to propagate knowledge of all servers to all other servers. In an internet-scale system, this feels like it would be a poor choice. Bayou's global ordering The big thing about bayou that scares me is their single global order based on time syncronization. How do we actually ensure that random clients are globally synced timewise. There's a protocol floating around in my head. I haven't thoguht it through enough to know if it works. And yes, this text buffer is too small to explain it adequately. Connecting to any server: Cool thing about Bayou: Fluid transition between synchronous and asynchronous modes of operations. Multiple collaborators can connect to distinct servers for typical asynchronous operation, or connect to the same server for âtighterâ synchronous operationn Partial Replication: How do we deal with letting a client sync only part of the system? None of the bayou papers dealt with it at all. "The Dangers of Replication and a Solution ", Microsoft, et al. (gray96danger.pdf) Proposes a two-tier solution. It loses because we don't get mobile to mobile sync mobile nodes maintain two copies of every record: a local version and a best-known master. online-connected servers are all closely timesynced and transactions are always applied in order. I haven't read far enough into their paper yet, but I can presume that one server is the designated Master and that in the case of disconnect between Master and other online-connected nodes, the Master wins on any conflict that can't be resolved. but in general, updates are resolved actively. "Certainly, there are replicated databases: bibles, phone books, check books, mail systems, name servers, and so on. But up- dates to these databases are managed in interesting ways — typically in a lazy-master way. Further, updates are not record- value oriented; rather, updates are expressed as transactional transformations such as “Debit the account by $50†instead of “change account from $200 to $150â€. " "The two-tier replication scheme begins by assuming there are two kinds of nodes: Mobile nodes are disconnected much of the time. They store a replica of the database and may originate tentative trans- actions. A mobile node may be the master of some data items. Base nodes are always connected. They store a replica of the database. Most items are mastered at base nodes. Replicated data items have two versions at mobile nodes: Master Version: The most recent value received from the ob- ject master. The version at the object master is the master version, but disconnected or lazy replica nodes may have older versions. Tentative Version: The local object may be updated by tenta- tive transactions. The most recent value due to local up- dates is maintained as a tentative value. Similarly, there are two kinds of transactions: Base Transaction: Base transactions work only on master data, and they produce new master data. They involve at most one connected-mobile node and may involve several base nodes. Tentative Transaction: Tentative transactions work on local tentative data. They produce new tentative versions. They also produce a base transaction to be run at a later time on the base nodes. More about authz: AKA: I CAST PKI. YOUR PROJECT FAILS Authorization is performed using cryptographically signed assertions: Every database has a base "trusted authorizers" property: the public keys of principals allowed to make assertions about it. Every database has a list of signed authorization assertions: $PRINCIPAL_KEY_ID has the right $RIGHTNAME for the database with UUID $UUID $RIGHTNAME is one of: manage_access (make authz assertions) change_db_model (send cryptographically signed database schema update assertions) create_records (each of these four CRUD rights can optionally take a table name to check) read_records (bad idea: allow these signed assertions to include a code chunk used to decide applicability) update_records delete_records We need to protect against Mallory, the malicious user, who will hang on to his authz assertion even after revocation. So, revocations of signed authz assertions should be kept and propagated like regular authz assertions. Servers must never discard revocations or Mallory's malicious transactions could later be reinjected. How do we handle Mallory's pre-revocation non-malicious transactions? Presumably all pre-revocation transactions on the replica where the revocation was generated are cryptographically signed by Audrey, the trusted authorizer generating the revocation certificate. On every sync, every client should propagate its trust database to the peer. While a local user could modify the "trusted authorizers" property to allow an unauthorized user to commit transactions, i it would not compromise system integrity as this property would not change on upstream replicas and transactions from unauthorized users, as well as authz assertions by unknown masters would be discarded. It should be possible for a trusted user (Tony) to sign existing transactions generated by his collaborator Ursula, such that they could be passed to tony's upstream replica with a trusted authorizers list whcih does not include ursula Application behaviour: * Application-specific behaviours are side effects. * Some side effects run when an update is replicated in * Some side effects run when an update is created locally * Some side effects run when an update first enters the system, regardless of whether it's locally created or replicated * Some side effects only cause other database updates. These can _potentially_ be rolled back when the transaction is created * Some side effects perform an external action. These can never be rolled back. They cascade. Once a side effect has taken place, we're stuck with the transaction. jifty-1.10518+dfsg.orig/doc/plugins-restated-assumptions0000644000175000017500000000330711447473535021063 0ustar fsfs* Plugins should be able to provide * New actions * New templates * New models? * Plugins should be configurable * should be able to be told about your * actions * templates * models * Plugins should be able to add dispatcher rules * The application should be able to spec what order dispatcher rules are run in. This gets sticky. * If you don't spec explicit dispatcher rule ordering, what do you get? for each of (before, on, after) { run the plugin rules in the order plugins are defined run my app's rules } before plugin Jifty::Login => { before 'login' => { ..... } } Plugins provide templates. auto/Jifty/Plugin/Login/share (module::sharedir. wherever it puts stuff) plugins have a default path they expose templates at. so, Plugin::Login would expose templates at /=/Login/ That path is 100% overridable by the app when it loads the plugin An app's content always overrides a plugin's content. If two plugins provide PO files or (templates to the same location, either a built in location or an app-driven location), the most recently loaded plugin's content override the older plugin's content. Anatomy of a plugin - In the end, plugins are apps. and apps are plugins. Jifty::Plugin:: t/ lib/ Jifty/ Plugin/ .pm / Dispatcher.pm Action/ Model/ share/ po/ web/ static/ templates/ ~ We're defining mount points for templates jifty-1.10518+dfsg.orig/doc/jifty-plugins-2.00000644000175000017500000000752711447473535016317 0ustar fsfs* Plugins and actions need to work better * Plugins should be able to create model classes * So should applications * Plugins can add columns to model classes * Plugins can add logic to model classes (before_*, after_* hooks) * Plugins should be able to add properties to columns * The app always overrides plugins * Plugins are loaded and evaluated in order * Models should become mixins when appropriate - But if the app doesn't define one, they can create classes/tables #' The plugins we want in our ponyverse: * ::Users * ::Users::Identity::EmailedToken * ::UsernamePassword * ::OpenID * ::Certs * ::{Assertion,Kerberos,...} * ::ResetIdentity (change password for any identity once logged in / add identity) * ::Users::Signup * ::Users::Login * ::Users::EmailAddress ::Users * unique ID * created_date, update_date, created_by, updated_by * display_name field (which you can force to something -- e.g. email, openid, name from cert) * (Jifty::Record _brief_description returns this?) * last_login (?) * Do superuser and nobody live in the database? (That's authz) Where do identity plugins hook? * Add columns * Get credentials, return: * These are valid * These are invalid * Other auth error ``I don't know'' * bounce trips go through continuations * load_by_unique_id * ::Login * /login => * list of identity types * for each, fields for login columns declared by the ::Identity::Foo plugin * submit button * Login action * load_by_unique_id * if the user doesn't exist, callback (to signup) or error * Passes credentials to the identity plugin's auth method * Identities that need confirmation error here if needed * frob the session as appropriate * frob CurrentUser * Adds Dispatcher variables * Logout action * frob the session and current user * dispatcher rule on /logout redirects * ::Signup * Signup action * verifies credentials - validates fields (inc. uniqueness) * Creates a record * Add a message, and push the user to the login page with a filled-out login action * What do ``mixins'' *mean*? * We want injection, not actual mixins ----- Where is this going to be hard? ----- * Mixing columns into users * Getting the autogenerated actions to DTRT * hooks look kinda like Plagger * If there are multiple plugin models with no app model, they all get mixed into the null model ----- Username/password plugin ------ # Model (Jifty::Plugin::User::Identity::UsernamePassword::Model::User) column 'username' => type is 'text', is unique; column 'password' => type is 'text', render_as 'Password', filters are qw(Jifty::DBI::Filter::SaltHash); sub password_is { my $self = shift; my $pass = shift; return undef unless $self->_value('password'); my ($hash, $salt) = @{$self->_value('password')}; return 1 if ( $hash eq Digest::MD5::md5_hex($pass . $salt) ); return undef; } # ``exports'' sub load_by_unique_id { my $self = shift; my %args = (username => undef, @_); return $self->load_by_columns(username => $args{username}); } sub validate_credentials { my $self = shift; my %args = (username => undef, @_); return unless $self->id; return $self->password_is($args{password}); } # Jifty::Plugin::User::Identity::UsernamePassword::Action::Login param username => render_as 'Text'; param password => render_as 'Password'; # Login plugin Action::Login sub check_credentials { my $self = shift; my $userobj = MyApp::Model::User->new; my $user; foreach my $identity_type ($userobj->identity_plugins) { if($userobj->($identity_type . "::load_by_unique_id")($self->argument_values)) { if($userobj->($identity_type . "::validate_credentials")($self->argument_values)) { ... } else { ... } } } } jifty-1.10518+dfsg.orig/doc/pubsub/0000755000175000017500000000000011565006014014541 5ustar fsfsjifty-1.10518+dfsg.orig/doc/pubsub/system_architecture.png0000644000175000017500000027502011447473535021362 0ustar fsfs‰PNG  IHDR¢ûAWºØiCCPICC Profilexœ­Wi4Õ×=¿;¯y&×,sæyN(2]ó<7.2—DQdÌT#"’Hõ+I†D*ÉôW)"îûÁó¾ÿµÞµžõ|yö§}öZç¬sΗ½6á›'™‚€Ð0J„ÍC¢#ɉˆŸZÀ+°§w$ÙÀÊêü[lM0&ëI&‡$r®KöÚ‰Ÿ-J‹Aå©üû>`Œp$9 D`÷ßçÊÀîµÏM€=†B¦ .Àîàé€@&ÂÖÆ)‚ÿ>¿¯}þÑÞþä9Ž5Ì'0 ÿ§ëãé @ À)or€P²¡¡á>„At$9÷×tŽPîÀµþ£Eö´øñ&QÀÍИô¶a œ#‘~JŠ€0`ßQ©âø\€Ý*õO%•º[€~ ð8Ä;*"ú_?BPJÿ©Þ¿ó_@#(°GDfTZC‹YÂ>ÆáShbh}éHôN $F7‚/SsË9Ö¶Vö§+\XnQÞ¾Lþ;³‚4D%!wáL‘NÑeñG%“6IÍÉpÊšÊÅË7)Ì*2+*“U*TGÔö4¤4í´’µëuÆté000ô3:o\{¸ßä“)˜ñ›«µ:`‘t¼À²ÞªËzÜfùÄŽ“½°ƒŠãÉ)Ä9É%ÛµÒ­Í}ÐcÆó«7âÃî+é§íoàt)¸2ä^èÓ°wáë'±Ü‘Ò(Ëh˜ðSɱãŠãkš;’º“OŸM?;‘:qn{9*Ç/×!Ï$_¥@¤¥zeµhªøIÉíÒ’²Ô«aׯ–KW°WìV.T W·Õ\½q®6¤îÄMÍzb¾áË­ñÆÎ¦òÛiÍÁ-6wÔZî¢ï.·½¸w·½¤ãô}ßΣr>Ü}ôñ¯Á®¦Çùݱ=îOŒ{¥ú˜û6ûgÖ ]xöÌæ¹Ú0ß0õÅüHÿËúÑ‹¯ÂÇlÆU&¸&~Mμ~8uíMò´çŒá[ÑYììÒ»§ïo}¸<õÑiÞàÓÁ¶…½ÅÏK³Ë/WúÿîZ}øùÑ—î¯Ckß¾ÿÚ`ý!¿i¹ù³d»ïׯÑ»Ý {ÝT*HC/R€"¡9П0åØHœ#^ƒ†—K»J7M?Ê0ÀØCxÂÔÃÜÇ2Ì:Æ6ϾÁ±ÇÅÆ-ΣÍkÇGæ¿ pã@à'!¬°°ˆ‰h€X¦x£Ä¨ä¦¯´¶Œ‡lŠ\|ŸÂ¢"NIRÙXÅK5I­XýŽÆæ;­:x]½ƒú&†6FÎÆ>‡CM"Ęƛ%›Ÿ9zæØ‹ÓÇ“-“¬â­cm¢OPlOÚ…Ú9ø;ú’¼œ<Ý]\]]Ý\Ü]<\=ݼܽ=}¼|ýü‚üCÈQAqÁ‰!)¡iaÃ/“ NG\¬ TG݈¾Sª!¶!®!¾>¡.±&©"ùêéâ3y)—ΞKM:GI N÷\sè†@-]íϺO7G뻚n•5f4ÅÞl&µ˜ÝÑh•¾ËßF¸‡ÜÛh_꘹ÿ²³ïÁƒ‡-nþUÑUò8¿;»'óIzoZß¹þ´ôÁ̡짅Ϯ=¯¾ó¢kdøåìè×1Ô8ׄܤÉkÏ©„7%Ó÷g¦ßî¼|oô!`.ëãÝù™dQbÉbùäJÁßí«¯?o~eY“ú¦ÿýĺ÷FøØÍ¤­Ó?“·ãQ~ýqݱÜÕß“£òP© g"Òˆ2D¡ý14˜J¬vW‰·¦AÓ´Ó†ÒIÐÍÓW2ø0Š3®š˜¢™X,3¬µlQì&ü«œ]\ùÜ<ú¼<¼ßøù+âØ ÊqÄ9¡Ná\‘Ñ#b‚b[âÃU’±-¥D¤¶¤‡dJdƒä4åiä'*…*ª+Ò€r–Š­*ê¬Z¹º†˜Æ¢æ -m íj]o=!½÷úW \ y §Œ®Ûæ8u6Ö+N?^0~7a&±#© 9âôñ3R)¸”¹³S Ï‘ÓÌÒEÒwÎO\hÌHËt»¨z‰pi)«+»èòÉó\Ñܽ¼©üÖ‚ìÂà+¦EâŘâù’ÞÒš²ô«Á׬®«– T`+Ö*§«ªïÕܸQT{±.åf\}TCÄ­ˆÆ¨¦„ÛéÍ-uwº[ß·aî)´{w\¿¿ð@åáåGÛ]a7zÒzeúæn eµ~¢þ5’A·CÔCûÂíÈ+ÉÛS?ã®&˜$~O.?cs–&õqZÂy­ »™=—2³r$rçÞ*Ê( .³¾¦Y.QÉUÍpSõp ÓDßÌuGü®ú½ã©«þê}¼ô„¾OaÀ~(þÙõáÑÝq®IÙ)Ýió·Öïl?Ø|4ÿ¤»(»Ìµ²·úáK×Zé÷¨c›Ä­õíÁߥ;Á{T*  ôÀ ü Š –àpJ àüF8EÄ C²‘fd ù‰âG¢‚Py¨G¨4Ú‰®BO`h0:˜HL=f+€%a ±8œ®÷/ÇwÒàhliªi¶hÍi+hÑ k¦g¢'Ó1h0T020Æ2.œ#L&L]ÌZÌ,Z,]¬‡Y‡ÙÙØ£8p%œ‡8‡¸|¸û:ÏGÞt>Y¾IþÓ2Ó2µ¿k„\„9…GE²D-ĘÄ^‰I¸K”Ü<Ø+U  £+Ë%».÷R¾E¡àP‚¢¯’²¡ŠŠª´š¨:Qƒ¨)¢uP[IG_×JÏG?Þ À°ÕhÜxÛ„xä¨iœÙ-ó¹c¼öÇ ,§¬ØøŸ¸k‡±wph$᜼œ»]EÜÒÝ×*¾µþ|¹AôÁ願°T2þdf$+¥4Z<¦5Ö0n,Á/q'9ïŒtJªW¤—_ÐÏøx1-K*{$'*?ÿIap{ñ£R¿«L×:Ê=+éªZk\j±uõö {5·-šÜ)½kضҞ}_µsöaê_2]ã݉O$z_õ'Ê ½{–3|äõåƒWñãz“ø×oêfRf½Þ›ÏiÌ+,È/©­˜¯ú~ÉX»ÿýû¥­¤íá?b»ç©T@-°À .À èƒE„Q@HÈY¤ybAFÅ¡ZQ_ÐRè@t=ú+F“€Àr`}±í8Fœ/® /€O¤1£i¥¢Í¥ÃÑ%Óý¡§§2¤3²1V4¯˜È̬Ì,>¬l¬lÉìÚì»=œ™\ŽÜ¹wy&y[ørø#H e‰üBa”ðo‘¢ßľ‰¯KlIîJá¥ÙeDd•åLåÝNÊW¼£4¦¼©Ê§f¤ªQ¬9 µ­#­ë¡wEÿ¥!ƒ‘¹qÆáá#¬¦$³*óµcz9Ç­t­‹m¶mìº$ œ°Îq.ënáîkž¯]Ÿ ?>ÿ–À£AË!a áoN¦GªS>GWŸr‹ã›x=Ù÷ŒLÊVjwZÖy— ™ÌÝK#Ù•9Qy¦…ß‹úJJÊ®”³W,Vµ×¤×Úݪ_½ÕÚÓ¬Öò£µ±Í³©££ÓùÁÏG—ºøWö=)ê£é'ŒI={Ö3Œy¡?ByY>:ðje5Á5)ñZaJåÊ´ÂŒä[ÞYºÙïÞ¾ïúP1—ô‘4¯ð ÷éõBÝbÔ’á2íò«•¿VùWß~.ûâø•ãëÈÚùoß¶¿ß^÷ÙàÞxþ#ióÐæ‡­Ë? ~nl×ü²ýùÝúÇc‡°Ó¹ë³GØk£:Q©ûiß@¼=C½þ7_0¸¦D„Þñ‹. Õ´¢ëz€P°7ü—@ñ=E0 'ÇFúPˆdrˆ/Ñ(<”Eñ!š…yËÉ”ö3Ž Ìà±€ïéÿ?÷Æ?â!Gd¢ IDATxœìÝ\Tç7üÏ‘4ƒ 4S´h“2¤P I”8˜M iÖJ“(4’n€õîا‘Å»Ò,¶¡´2¼RÈ Ì&Юcâ“H0134Îl„;B…TØ ÄeÎyþ80"‚?‘Qø¼_¯6Ù3ç|ç0Îg®ë\—àt:ADDDDDD³Å³©T*yÚcÞÜ1áwÍ_=Ýn÷åÝ¿4)Æ<šQrkÞø~›î®ˆˆh: Êç·‘‘¹5ÏÝÑ çêšëzàú½ó@7‚+×¹¸næÀä˜G3Jþƒ''=yfwWDD4ä3›œñÀ«üÙNÎur¿\WË­«ý–ýué‘ÇòÅØhOÆ|Ã`Ì£™çê·)ÿ¿»Ë!"šN®“›|®sw9tÉ¿_W×\ùnLWØså=&=š^˜ñÏÃÃÃÃÃcÞðK`Ì£™4a(ù/¢{K""š^ãÏle“­®t7<<,I’»ë¢9ª¯¯O¡PÈaÀ¼yóä <Ý]¹cÍ×…ÎÅ=[Ü]ÑtrÜÆ·äÈxÉ5›Œ;ZEyi°›.¹ƒ ƒƒƒã/«\]:ÝZ¹c¹ ÿѬē۬7þ+KùnÌÁÁA9æ¹…Ãáñôô”ûsÊ6ùíÒǘGDDDtÕä›rÆäL°äFòL®»õxo1æ]×]yòü‡ãܹsî.Šæ®sçÎÉoÂX,܉1ˆˆˆèêÈý6å›CCC‡Ãáp¸»(š»‡bŒ$I …‚½Ç‰)Ÿˆˆˆè*¸¦RGaEqhhˆ6ÉìvûÐÐ<k,t7Ç1æ]WÆ“oÏ““ž»‹¢¹KÎx’$ÉŸIfN`Ì#"""º®‘6å½ÁÁAwWDs×àà Ü”'I’üÉtwEä~ŒyDDDD×büz’$¹»š»\B×tDŒyDDDDWÇ5ñýðð°kÔMwEs—ü ”?Š®§»‹"7cÌ#"""ºj®f×léæ.ùfÑñHwWDîǘGDDDt¥&\L»2c¹‘ü ÿ™óޜǘGDDDDD4«0æÑ åèéééééŸÉ¡ mµÕ-ç)¶õ÷ôôôØ8}1ÍŒyDt£tÙ-xùùùùùù(…èâ#7|—RWå®D¯åëbWz¥äê‘@êiÚ'xûøùùùy{ ‰ùÕ6°H &ˆ.¶Áv åÂå¡qÅÕmpX!å@Ëù}Ùš!ñ@‹Í²wâv„èFl–â KSò+{nø! """‚ÂÝÑ,%µü"*ÉÛPÕ™ø Zê~k÷3›£Ö¯è>í{wY8«¢4ëƒîÀL½ß`½sçýÿõ|x¶5§¡=5ÔGq²îe­>Kš÷o °uš‘\ÔrßйÑIçߤl'ÍÈ(7§„@ÄSenRìò¯·Û7g 6ïßl ÖzŽ.ªÖ.Gï;@rUÃÓ ÏO޼ðn¯ÑG¥õæÈÛ!=ÿ·j]|ü—‹ÌSBnÜ! """cÝ ŽÖ†2ÀødŒ¿€zÓó/·x®¯×_µ­¥úç[cKê O6ìúÍÖ¢¥rÇî¿ÞdI:ò|·»²ÞÝ¡`«Ü–øÁªßìÞ´¼©27)>Û mFÑhµÔ–ŸôV¯:ššmêK ““—í³\dÕgoôÿÞ3O<Õüõ{ÿ{¡ûÿ‡6.."Ð@ÈúíõymUóG‹Ô…=|aá6ºe!!Á£a,$l×k¹Æ–/ìÿ’h@Aú‘®­ëý€ã½7²¡+}Ð_/mØÃŠ‹7}øª`•¼¡r]fÞ xC7Ñ8ŒyDtC¨–G&z¿Ð¬¼m?|÷Ê÷@Oíꕱ‹sÊ͆»^OˆÒ®utß.öž(ÉÌEBŽñûáÏoµæ§ƒÐÿÉ®ãVóþ¶Êÿ_b06¬¾í“ðuëNÁ|p“x´¬ÌXV–œWºú.õØ>½ü“‘õÌíYŒ\£Z¿>-€cñ ˜Óµq§r}äÛÚ»×l/^È)¬®å½ÆÆ3Cr+œÿoߤ€^ÇW6É»8N¼õjt¿ø¦F­y,鯾Ӽ~Kl'ÊJQ¥S6%`núscãXkž¸ÐÿÛaò†pªóKÛ ˆ@ßÉÿïÍ:hÿyÁLþˆˆˆhnbÌ#¢Cür{ê‚—Ò3“rºŒÒ7voùâ…fätîÜä¬8dÌ]ªÿ°ãgË`…®Èº?E Ü–…ueG ƒ¾0h…Ö`?ËÜùsÐ mNUw_wgggww»1O’WmþÃL˜3{leÙHÎmG }ã¶S›6V‘ÖØÜ)o¨¹¦¨«úƒ°Ñ ǘGD7DséZ?ïÜ~Ph|ƒb¶ä”êÐð׿‹ƒÐºEÑjµÛûÚkªêŸÔªÇ¿P“…ºýûJÿ?X …ralE»Õnïnn¨ú·‡F_ ^8MƒÃ’(:àµÐóÞ‡¶ÿ¶æÚSÿcòñó>Ð!P©}CÖlzn›½ƒò+C9iñ‹ùùj|ýýý}}¿÷ÃVy=EÐ?æE»ÿ½¨yO¯9ßB ¯I7„ÅK–úË Žþ‘A‹ò¿üíê%ÑÕaÌ#¢båc™@vR~uC’¶–ê=IuØøoÞõ-̯¼×ܯVãØþôu±¿ýbâœz‹ô©éuú"¿Šå%£ àv•Zl/Z[Ö>ù.U‹ïòÞ8òå9à\Gãá× ]ñõ;³€ÍI¹M]6Irô´yi·ËîSYÝ)‹Åbir±t\<¿Ÿ" X‡ºn›üŒïúòdcn¦? ל_É|êØ¸í46Y\Šç‡\Qx.ÆbÏɃ%Ñ4â½yDtC(‚6™+Ú´ñ±Æ±›Ü’ 5Ѿj<[•gŠÕúÉ KMÝ!*X.|­6æi-Œ¥Æ¨@±þEsÖjírùn9mNó‹1 X('œÁüj.¯ÔF-ÛL¹ùGjh²Ûkzׯ È]¬Ï1—nRÁ¦ 6kÇÝ›­¡ïx’Úxåï¶Æl üëP‚¼ Açwî D]°!]ƒµöðVŽ‹uêÔ½QՕ♃GDDDt]§Óéîhös:ÃÃâ(ÚíösçÎÙl¶3gÎôõõõöö>õÔSüÎfŽþ®/­¢Réãã¯V_ÜÓ'A­ñU_éwMRO·¤Pk4—{…ä°¼™õ*ž~aSȸ5¥þ®N«¨\àíã«QMýb¢ë"¾}û/^ìãã³hÑ"µZ½páB///¥Réáá!‚» ¤iÀ¿ht³á™‡&ÅÖ<"º‘Tÿ@Íd‹}¯²EKq¥¯P¨VÆfüžÝ“×ADDD41æÑl£Ð¹»""""7â,DDDDDD³ cѬ˜GDDDDD4«0æÍ*ŒyDDDDDD³ cѬ˜GDDDDD4«0æÍ*ŒyDDDDDD³ cѬ˜GDDDDD4«0æÍ*ŒyDDDDDD³ cѬ˜GDDDDD4«0æÍ*ŒyDDDDDD³ cѬ˜GDDDDD4«0æÑLA×Ù¼yüøÑ,4oÞ¼ñç:Œ;Í ^gÓŒšpÑ£P(Ü]ÑtR(LwDDävŒy4ÓAððð˜7ož‡‡‡‡‡‡»Ë!"šNò™M>Å1ã‘»°-…fÎø¯·åk ¹5WBD4k( 9æoÓswQ4{H›¤P«n–Ë7GO Ph|57KED4†ÿ*iFÉ—>Ê1ûöí;sæÌÙ³gÏž=k·Û‡††$I’$Éétº»Xºúúú$Iòóósw!³PEEÅ£>êíííîBf9¹Û¹B¡˜?¾——×m·ÝvÛm·-Z´Èur“[óx2]3›¥Ð;Öãi'óµáŽgvdGõ®¥±ÙÈiz‡éÂÂ.yg;¸zs™Ùõ³.Ù`øÍÖ+Kd®½«§X¡ãÈÞ¤¨¤º±mÕ—¦¬ ¼¢7&õ7}xjÙýaÓ »ª£b‘SS»3úJV·F'8^<¾=ìü"G“Î+<ÎÔ—®ÅÕU5ï‚èÆàg“fŽ+ãÉíxJ¥ÒÓÓÓÓÓÓËËkddÄét*Š¡¡¡¡¡!§Óɘ7+={¶¹¹Ùb±X­V//¯””wW4 Í›7oáÂ…Œy7šÜX7þüùóç{zz.X°ÀËËK>§)•J¹MI®—–<œoÄ7ÿÏldUÙwFÀ’»sû¥/ãlfd”›SB b ÇôÒº$-–ŠÅë¯ôâÏ åTOI-¿ˆJò6Tu&>¨–ºßÚýÌæ¨õ+ºGû^ÉvO…G…›ìÎëH–·Êëd—ZžQ]~}€êÂ÷¤Z¶³¢Âw‰0_eUÓö.ˆn~6i†ÈÝ–æÍ›çê®9þ|•JµpáB§Ó9oÞ<…Báp8DQEQN}î.™¦ÍÐÐPssóG}ôå—_ ‚ I’B¡Ø²eË¢E‹Ü]Ú,äáá!7+¹»YNÎorÃJ¥òòòZ°`ÁÂ… U*Õüùó]]7åŒÇ~›t=¬§ÍŸ`ùÝݦ/›ý5ÃÇ™¾·M“0ðzëc/?¿>@Gõ®¤ÿ 2oßþ¦[Y`Ø]öJ»ÍÑöÒÿïÊßîߤ†£m×Ï…þöåõ¶C¿û…>³@Fi}î–5€SÿQ¸-)½H06®Ö¸6ëhm(ŒOÆøk¨7=ÿrÛ‰çúzÿvàOý÷„z~ÿuã·œàÿÂ#áÂ#¶™ßß¢ìØ›“ž”k„.¡<7oS„¿£­ò™ü®Ø°S›S t y¿øið[Yú‚:$5ü>%âÂËÖŽ×SË’ó _f¦<ú»h_-•;vÿõî KÒÑU¦ƒiËåÿ«>³Ðf•¾”½eÞæÚƒ»>MÏ.©Ó%•R¶Ï>ø`è[÷|âRUè8Rœ•Zè’ {~õXÅãcëÿù§Ÿ™x<ÁÛϼԫm‰O:e²\ÑYýó­±%uÐ'v]qƒ*ÑuâçŒfˆëWÆóôô”$ixx€Ü¸çåå%Š¢Üc“1ovúÓŸþTSS3oÞ¼¡¡!y¡‡‡Ç}÷Ý·råJ÷Ö6[)ŠÛo¿}ñâÅî.d–s ,'=///•JåjÓs%=ÞžG×Ïzªì—ƒQÿÏúGõ(0êóâtkW’ëÒ¶>}Ç;É?ÙyøÙõiتó³ë"k&ô±ìu|%A’’h;YUkƲ;¼Ä3uF£g¶â™:c™gváýõ»õ™_V™[zk×EyõeÝî $ÕæÔ›þ²;Rÿøªñ8UË#½_hVÞ¶‡ ¾{å΃ûYR·ùÂz·üùÆ CvÝ+y;7,ñê/~dijoF•É<ôçúÈ€ùí⣽e%éeú¼úúŠ’¨øueÈ*­ªÙzl]|äýÙ·Ÿo³³Yªs¡3¥%ŸnK×—þéÙèM*@ì=Q’™‹„ãê;ó¨Ïì-o0µ½¹9*0Üú€§ÆìÏ FSý?ÿžmM÷Áh_XŠãÌÈéܹÉXqȘ»TÿaÇÏÖò œn8~ÈhFÉ]˜ä˜'7ÙÉWH*•ÊÕ]sxx˜­y³Éïÿû”””¯¾úJþÑÓÓsÆ AAAî­jóððX´h[ón4¹5Oî™évEnÇ“oÏS*•®N›DWÌÑßcWûj€4à€vü gâ €A€]̃" ~$ Io™ºBæW™‘¥ ¾ 1oÐ m–ñÐOC!J’Ÿ€ pœàº”ïâ þᮜƒÚØ•eô†ìá°›¿¥Æèî`¿eÉÖoó OÛ½?mwiOGãáWb“’~ñàšâë ¸hË’@´Ë·Ê!~¹—k³úA6ß­% VÄ vÀa./¯,]PVÓ¶fc8mÌ*5QìVùÉDµ~g1€¦÷¡½w‰¼¾RµŽñoéU9VmÖ=.oËwMZñÀÑ4ºþè½~OÀâÛG{j ;@Èv=ÑÞkGàTCÛMÆ<š!ãçQàt:Çwy’$É•ñFFFäÜ]2M…B±dÉ»Ý>88@©T¦¦¦zyy]ö…tm …Z­Öh4—_•®ƒë~cWÒsuàt5åM˜Yè²lM%>ᯘìÇÃT8ýI5ðøå^á¿Ñ  /*ûº:W—×pñH—‹ï\èábΈ’ü“Ÿl¶›^¶>»ßvâØ»Åë6'}}õû±¦œ¸¡¹t­6}cŸs§ oPÌ–œÒ×rwÿõï@Ä„z.Þòñ4P*!ŠV@[ÓÙ¥%%Nû@üÆ XßwíW.Hbãt½[Y}EîPŠPÂôjxҮÿ٘6q½Ñ &Ù»§?2qɸ Š“mvŠªþᯟ¢®£G^§ßrèe“&퉅òú“Ï Ž÷`'´†nÓV•]RJ_müÚ¦ò:ú~7ùz"€3Ý6I­Vhõ[‘Ÿ T´†^Ñ>¼­LŸ|戸çœ$y'^YYiè4¥…Eÿà¡4LµÏ1+ËDúæ¤üU/§=¬½õÝÒ¤:äüâ›&Ô3É–Eu-'{ÂVDè‘^úÖ±RÖØ,´Q›sú2\É{°½•Ÿ‹¬šòè2XšhH*H?Ò±u‰kõŠë‘´³Tÿ[œ(‹JJ7˜“–L±¹±·7eU?y,úm‡~òî÷ü¾|A«ÏͪßîZå$Çsü»ë[:˜_y¯ùÉ!ê#…éëÒa¶¯QwÕæïýbËŽMßà•8Ý0üpÑÌóä[VFFFäö&´ã_æ­TŽßÆ&sE›6>Ö8vã_²¡&#Ú€âÂz&Ù²Wg¤›µY¿ÜPäU– ú¼š¬Ý×~ÇíPœ¿jí9¶§E†ó7"ªµd¯V7ïw(^nøÐ/r©W:}Ž1)DÝ^7n‹cÿ]x*•ðZt‰ªÈ®È:®_îÚ Ó³÷ëõþÅÇS>b ”àýlUž)V;:Ol©©;D…³g,¿üåÁïÿlÓ7n›ìwD4^OÓ “ûdÊ¡Î5‹ü@^ŸÉÙaß¾}999{÷î]³f»k™[|ðÁ¢¢¢w2'¸"œ+Ô /wk4ýœNçðð°(Šv»ýܹs6›íÌ™3}}}½½½O=õÔ´ü sô÷|iðþZ fêïÄ$‡CR(T еCè­h-Þx÷<;úûmPøjÆäèêøRT.øš¿ï•~çèïúÒ**•>>þê󯹸ž‹·,9PÉ}3¶®>‡—Z£Q߈¶G ª+Üøeª²õ÷8 wÐί?ÙñœXGŸµÆ÷F¼KAöíÛ·xñbŸE‹©Õê… zyyÉ øMÓœÅÖ<ši®‹ùö<ñÍw®°G·®‘‘‘¬¬¬Ã‡¿÷Þ{jeæÉ÷‰yzzº»¹ÂuNs5Üï¹@t TßÀËÝ]«P©€£¥ò‰•ñF$7Ç]ÝÉV¥¹8Bªü/¾¹ï2[ñ¿°Ð)ê¹xËŠó½:Tjÿ×û@¥¹âÐzÙªÔ_õëOv<'ÖáÅuM ÆøàK/½¤PðôârÎÕF4(ü#RÒ"Ü]Åy7[=Ds»”Ñô8zôhddä3Ï>>++‹7ãÝlæÍ›Çù'‰æ©¥$Y5©š„dĽ“³å »bÞ©Û]e ‰ Ó8ú¡Ó¢òã¿=ÿ€@VUgJŒ?$_}j‰uÀ~òý×\Qš£ú}"N1m‹RWe4…?¢Qô „ÇÇ–këÿðü ØU”©­:iÓÿ9לU©j)ɼ–÷­‰É^­k]¿eù{od#¡b•ÒiOJƒV$”Wnߨ^ÌÛä€ÍR Ô¼±=Ìaóg{ŽSëPÑš¤BØžœLcYuó£L,øÒ¾÷ȽÐz~?"èüÕ³£§åd/”€Ò{y?¯ªé¦ÂÖ<"ºj¯¼òʆ ^{í5f¼›[óˆæ ž•¹ëüA__;Ös¥¯Uàì&ù ‚ÒËge¶Ë)X;Ô ˆÕ³ÇÖiïýæh’úâè;žäç%(•~Ú$À[ ƒÀO¾¥F[­8ÛÛÜyûh Ö]xož£¿§_î* 8 ½ÄÞ7tÆÝïô;šËJ“üÐø¾Ÿ" ]5:‡ŸRµ£•dûT!Ïïßù­y¿ÜKAÈ0(NR0`ó 8nû¶¥+µ+W®\¹ry{rÒ͆1ˆ®ÂððpFFF~~þ|ðÿøî.‡&Á˜G4÷8þT’‰ä"“Ùl2™Í&£u¥j¹²×Úö'èK«hï³:ÖR¬®V5qôÞ»AP†Â|f4ã(Þ9Õæ¤®w"7go®2[íN§Ý¤ƒÕ•‹&iìk8Ó{AMM%>~kÍ8ýI5p©ZýV˜_y©ð%#âWùN|z,=Šçÿs¢w4A¶íÍßûÙY+ ­é´‹V«Ýn5×WeëWLYð…Ôa?³ŽJÓ\ne¢ƘGDWꫯ¾Šmiiùè£V¬XáîrhrŒyDsNÏѼ2R6……„„……„„­OËBYÞ¡H ò‹j?¿ä‹% w3P£î8r ©pˆ“­¦Xù`2²³µô;zš²ÃÓïIד¬}¾¹b©ZÑè…Ÿ×ç“ Õ"Þ¶,N‡ô¥8:ª³2Íã‡`Q¯ø¶æ?m“¤®£ï×ÉIÓñymNÎÏ/Ú˜"pAgÎÎ,Ñæ$_nõ]ßÒÂøê› Ž#{žIÊüpáÊ=Ì¥o“ÔjÛÉ·´Q±‡¿˜¬àÑÿé¶V¡u ÈÝXŒyDtE>ûì³ï~÷»ßúÖ·>¼hÑ"w—CSbÌ#škÚþô†iÏß‹·jcÌ™ïu|õÉË™{>þû¯óhVoË(K aéO›r2tu™É6eà©mÍ’›Ò7¾X• _éãå~\ àž;&ŠDüˆAøåÞ‚Ò§àtd‚¶nÝÃ{Îv¼ôV*5[ËjŒéK½¯¥±u¸põª¼}æºåJe@j™ÎøF’ÎX~ùË—ÿ>ɼ šÇ¶fØ¿êü²à|cá¸Ç¾Ñ‡ªò 6k•‚WTz¡fGÐí/7•¥Fy ‚Ÿv³>¯&+BƒI †r‘?½|õöϤ[¯ˆèòÞyç„„„¼¼¼¤¤$w×B—±víÚçž{níÚµî.„hvr:ÃÃâ(ÚíösçÎÙl¶3gÎôõõõöö>õÔS·èe•£¿Ç&)4¾$›Íî¥V_Ü_±ÇRý§S~Ö‡©€ž#;ü¢î´:Ó¦åEêïé–>¾$‡MR¨USô”l=Ý6…¿f²Æ0GÏ—Öï¯NúìuqØzl’Z£9_—ÃÖÕçðRk4“¼õqõ:’B¡RÜ\ƒ­‚°o߾ŋûøø,Z´H­V/\¸ÐËËK©Tzxx‚àîÉ=n®)Ý„ òòòþó?ÿóÁtw-tylÍ#¢«¥ÒøŽ%)…Z=yvSˆæÍúL}VÑ[6§$—›§ÉS¡ñõ{¨ºTnR¨}ý§ÜŒJãxƒîxS©}U—øO]‰‹B5U`%ºéð³JDSúõ¯}ðàÁÆÆÆo|ãî.‡®cÝš°íæï¼UõÁ±¯òúöMkÝ]] cMî‹/¾Ø°aƒ¿¿ÿ‡~¸`Áw—CWŠ1ˆnÿè”hwWADW„C°Ñ$L&ÓªU«bcc+++™ñn-ŒyD4½ý=]]]]]=“Œ~BD7+Æ<"š¨¼¼<&&æ÷¿ÿýÎ;Ý] ]µyóæŒŒ¸» "šzl‹öòñ ðóâ*-ýS¬)uX-S BéhŠ¢¯c„JGÇ‘]‰qÑÑÑ);Š[F'NG[mqbttt\Je“k2øþCù)qqq‰ÛŠ[\»³µíݵ-1..q[aSÏ$“%ÍJŒyDtÞÈÈȳÏ>›ýî»ï®_¿ÞÝåе`kM“þâ8¿Í(­1w[­Ýí&C‚1^ë³·eÒ¸&Uk#µoœ¼Ä攓MÀp%¤®Úˆ¥QÙx`kÆ4¤®ôy¶MBcáòu© âþùŸ£âÃýöZl€T»c­>ódlBÂݧRWzïh“tíò^žT }êÓwO÷Ëî¸Æ*ˆn1ŒyD4Jžýü“O>ùøãï½÷^w—C׈1ˆ¦EÏ‘—S(oþ¯-Ñ!¾jµo`XÚþnƒI¿~ËH=»âBAB+›zZd¥È ßQÙت SAa[q­ ½QwxÏ®hA„èüC-ò.l-Õ)Ñ‚ q)…–~ @K厔ü½ù‰B\a“«’ÎKÍÈéÛ¿}ãú-»ÿP¯EÁŸ›ÿçͬtäÔ§mÚ”¶¿>G›´ó­³]ÿµ.×\Ñú_)7î¬lMFî+õ]=G^ÉFrûñÝcÖ?ÿNkQN Ä¾§470æ477¯ZµêÞ{ï­®®ÖhnÐÖ4óˆhZüí/ÕÐbƒÇÏ<à«{\óßíèÈö‹Ì¶n6µšK#Ëâߊx4€>o㪀ÆB}lzCyCss}QAê:}a5nÚÚ`ª2¬ÈÔ¯,¶ØÐS»zeìI]¹Ù\OCºvíïz±÷DIfR&rž^}§k¯>¡Ûªêãåéú?û‹\øåûu0<ö-y…ÛýãÔßû¿hôß P€Âï~ü·¿ýÅ|ùFþ¶PAˆû_‡øiJдÏÂGtSâH›D„·ß~ûé§Ÿ~ñÅüã»»º^/¿üòí·ßîî*ˆè–·À;ðœäJÑüÅß>©ÎjÞØæ‹0ƒù³ƒBÀÚu:tÆÆ†}­=1½.§¾{S„/ÜZþþò¼÷mÉ«;ÒæÿجBÄ‹E¯”ì©:ùÀ¢B3r:wnòV2æ.ÕØñ³e°BWdÝŸ2~;u`XL [ãÜÈ͹H.ðÉV­°ô8¤B¡ôŒ_Ù ‹UJ¥§(Ë´ä«*ê2ãµ>Ÿ6Û‹ƒ™ôh`kÑ\÷üóϧ¤¤¼ýöÛÌx³Ã’%Kn»í¶ë܈£­¶º…›ˆæ´k'Ìg&œÄA+´wúz YÁ¾UÈóûw†¨ÄAƒ"D±ÀüÑx¶æO»%:íR9]©WmÖÊ€ìAÁk©@{¯]„6fÕÅó”;ÚªïÈ͹9å öâM£}N”£{±u~y“ÐÝ>L=^‡Ø€œÎý;×ÇlÜýn%‡NL5Š Ñ¬Â˜G4w <þøã‡2™LßýîwÝ]Žû8š…ñB]7“\Ķ7Nˆ.¶\ørK¢ YΞmÊ„üI/,…Ñ¡ùM“=sl–½ÂD×5r¤þ¦#Mý†“º*w%z-_»Ò+%ÿPÀv 1ô¢=ÿOS± „Vw}Ï‘|A­íùjÒõm°ía›ÅuÙ8:øž­8ú¢w&…M¼#r§»¾d¶Œ?ËtT¦×i7~û6À‰^ù_¿Ô¶7oÛ…qpтѰõå¿í½~ uÝ£[r˜šˆƒÐºEÑjµÛûÚkªêŸÔ^œïýO,5g”¶Û;7E¨¨G§NõÉÏÿÍ|‹=JO ÷Üè9ÉöY6ÞÿMqÐ ­ßèvվˀEJöe£9t¢9êóÏ?_¿~ý}÷Ý÷Þ{ïyzzº»7³åõ)a·‹¢xêè~}꺯ß×·=b’{­-’ÄÓÀ (ª–<\aĤ#ɉTÊë.Ó $W5<½phhlÉ»¯uä:À©ð¨p“Ý©9ÿ§@ªÎˆ?œUQšõAwà@¦Þo°Þ¹ó>[§ÉE )÷ ÝõüÛƒ¾¾¢7©åï´Æl 8Þ+Ë„Îðm_7'[ìò­ á…ß9~†e¯CCƒ¨T~u,|]jFiÍÓÚÛDܹbŠ >"š¾kò´™IZ=ê_þáªØNþû3Ú\èjRïWCÔ"ýÕ7-/lZñážg’2W´þL^ôžé¶©#×!uçý¤Ú› âË“¬¼ØŸíí.Ýó“Œ0d/»ë+̯¼×üäÆõ‘Âôué0Û×LZ‰åÍ\#tUO¯‘Ú-€òÎÁúû¸¥v»ë'{wggggß„—ôuww÷ÙÇ/±÷uwvw['nú Ù»;/*ÌÞ×ÙÞÞyá^DëÅ{ž=óhRì´I4‡8Ž”””ãÇôÑGî.ç&¢2£2]?ëóþø€/N®®íÊÑǃV §~÷–5U|¸4þãžg}•Ò€¢íé©\°>ëæGN/Qàô`'’ûÓÖx1//ÉG‹1µ­¹1A*„íÉÉ4–U7oÜ$ÊòŒÈînÖÿmB?OO $6²Äõ³Î`ªM Kʺ²#†A_)3#ë!RYB‰®È”¶> ˆ0U…ï©ëj5€¬ªÎ”H¾úÔë€GØ÷t:|8n͸N›ª¸ß4°5=·(ËÖ&WýñŘ xz©‘çK1˜úÒ4uHLðj]ëú-Ëß{# «4¦Z_À:è»>»A—™y`ÓþM—èÈzÛ£sËesDtã©}ý'ïæ¨Rû^8d¥JåúYåëïñ+4¾¾·¡ñd½+¥òõ¿èo™Jã8±Ë½B­ñeWMšc8 Ñ\qúôéÕ«W }øá‡ÌxØ€¬ Sgg{kkkk{§xpû„‰•ÎÇ‘^d¬ú†üðkߺ¨þëÄAPÔJJu%IËý¼åÚ×?éQ( Ú{—ŒnJµo×Cür/A! À õ=Ûó’sãÃ}”‚×ã»ÛÎ).ü*nÐÕº(«M ðÀ“E0¾vÂaûàÕ]Ñ“þŽÓ3êRÃåLÂSXì À Ü E@¬’@´_°…&8­¸¶¯ÞœWš·¬$vCi?0h…ÖpAÃZZ˜|¸Ñ 3î~§ßÑ\V‚œä‡äÃ6õúÀàT/W$—m~æHÛ@ÀUþ¦ˆˆˆèJ0æÍ õõõßùÎwžxâ‰×_ÝËëºF형¬Àÿ°Âß?0((((Ð\¸rÈc¶ÙzÆFë^ŒÚÏzåçì=Ÿ1wOü†Øf]´Æ(Š}íÍU¥å¦®; S76 Ü`'ŠV@[Ói­V»Ýj®¯ÊÖ¯l}Kø+Q´¶šë‹BOnŽ*è˜0 ¦v’!^T!1Y¨Û¿¯ôÿ‘ñƒ•P(ÆVQ´[íöîæ†ª{h´Fqtsƒã^®ߢæ°$ Âx-ô¼÷á„í¿-…¹ö”M~ß“·¼iõ[a~å¥Â—ŒHˆ_uþ{ú©Ö—müUž¶.jCr¼¯h"""š€1höûýï_VVöóŸÿÜݵÜÄDé¢%2MýRÓÏÖåÊmbð†9=§¶Ã!õ[^ˆÊEÖw.޳û¹•ËËÌšÀà˜ÇÖN|v”zE„æÒ·ŽIjµíä[Ú¨ØÃ_HR»qår¿ÿê@PÈš˜G#‹†C6Ÿ:f±4il²ôK7é RÓëôE:ËKFAÁ:ì*µØ^´22¶¬}Š·  ®ådÏù%ªÅwyoùòp®£ñðkÐÆÊƒÒÕ²XÆíºÉ2š@ë :svf‰6'iüŒÃS­?‘á›öÇr˜ÍSRÃÞü¢Úϧ^ˆˆˆ¦Ä{óˆf³ÁÁÁ­[·~ôÑG Ë–-sw97/oÀó¢™”Ôa‹Ò“Â}’ÝØxnž€VuK½@—Óœ X–`¬Q,@Ðÿ®ÈZ.$€6¹tCˆú‹ºó›m¼RG¼ÜPäU– ú¼š¬O–&¿¢_î-¯’UÑ|açZO  J;îŽ7謵jhcžÖÂøXjŒÜ)sý‹æ¬ÕÚåÞ™ Íi~1FKÀ¸÷è)7.z-ŠÔb³öá ëñˆÑö>ÿŸšË+µQKG·¯-7ÿH ¨€‚ÍìYkè;ž¦Íc[3Òë ¶Å¯:è&_? À2ÏÑ  ÚÔ`x32}üTzŸìød_æžØ‡S£¿"""ºJ‚Óétw DtCtuuÅÅÅîÛ·oÁ‚î.ç%õ÷ôC¥Ñ¨/’­¿Û?_ÍT_•I¶žÎ¾åÿKßõï°uõ9¼Ôl¿¿§Ë:o¿ ;½úÊ»%…zbé­æp@¥RLXfy3ëU<ý¦~H4ÓéEÑn·Ÿ;wÎf³9s¦¯¯¯··÷©§žâeÍ϶I¾l3YÚ>ýôÓOO:öJjzfúI«x~+Ž–ÿ™mÓíÜùxeRÔ÷ò\°K? Øzºí‰Í.è¸h:ÁË=KDDDnÇþBD·6‡Ã‘ššú—¿ü¥±±‘3ãÍý«Bä©ÀC~µ+½Dÿ;½^ÔðÜçóã'¾k:S†äæwžV@ðšM¥ _›\ß’3~bñæiÚÔ2ú±%—š‘Ó·»ظ&¨Ö'êÏÍ9)wÜ(?ß_]ÐihH 9?h§eßÖätÜé ¬k8ãù˦´Ú0Õ= ØþðL@’qª·?ɳ-•;~ÝrúÌ’º ƒñþ-Ûâ3ÍЗ›K7…h]/d&g—™„ óï6†L2x)M#¶æÝÂ>ÿüóx`ppðÃ?dÆ›A§zú’Ãápôùãa@÷M¿ &%°BŸ½Ç”€Üôâ¦q‹mÇöµ†9ãA’‡:|ëñãÏ_8¥AHÊ~§Ói6èNu¦ô ÝVU/g¸þÏþb{¹Ö·'¥×e•¥EL,Sw—¼aÍ=éPwì¤íŠŸUo9ètÚM:Lj’gÅÞeÙ©maÛkʳ ÒõëâfÖÔe7'ìï‡ã[#³m[›Û[9ñÚ‡›¦è$JDDDÓ…1èVU[[»jÕªÄÄÄ×_³ŸÏ,óº/¥————OTjIBQ®vâÔwVø…ý®*˘^ÛžÞ£‹cñè#[a¸Rž»V„bË$w¸ë u`XÌš`lvøD¦#¹<¬/FOmBª1¯~Û…sä9,Uuº¸±º”JoàÌù–—~öš Z‘l,N‰‰þÑ“z §¾tStôORŠ`>xÊ&ÚN_óT.XŸõsCÙ2ö#!""ºÁóˆnI¿ýío7mÚôÆolÛ¶ÍݵÌEå¦öÎööÖÖÖönëþ”ˆ‹c‹h‡o̳E:¬û×½8Ÿ{r|S'Vµ·¶¶·7µÀ xùˆåh«N¼#7çæ”7Ø‹7¹æO·ü±ÐŒœ„5ºAªîºugι~¶Ú»ÔWöìµí½K@­À¢… öѨªÞPRª+IZîç%(×¾þI‚1ˆˆècÌ#ºÅ <ùä“8vìØÚµkÝ]Îܤ ¾'Ð?00(((Ð÷éHó“R£¶$i]R–Pߣ3g¾Ú"€Æ?0((ÐçL»ùJvØßøÄòXsFi»Ý¹sSĸ>ž=SúÒ8ÿ‹^q{ Ùö¤vstã'o¸ô³×èÂa>Ç=¶Y­1Šb_{sUéc¹©ëLÖzIDDDÓˆ1èVò׿þ5""ÂÓÓóèÑ£wÝu—»Ë™»DñòëP®/-r ¤‚5 Û’•ó-]6Éak;²wudú•lÇòf®º¼§×Hí‹Åb±´ôÈ™ªË” ühÍ ×šŽÏksr|.aÅC?2_ªí€Ô±ç_“ ‹û¦úJŸ^"ºŸ[¹<±Ì¬ Žyìaí4ožˆˆˆ&Á˜GtËxçw"##ÿå_þeïÞ½žžžî.g.ó^ œ¸H¡TÞ¯ö“ßf¹’L·©BoÌÔx+½¼—G%m¬0æhᩜ¤%müÔÅj—/_©ÕjµZíÊ×OØôñx¾yO:cùå/_þ»ªà- EÉÙë– Ê¥éÆ„†?¤ù^ñ³®.u.xV9aùùwä­TýïŠ,cR¸ ‚ß:$—n¹®¢DDDtY‚Óétw DtN§óùçŸÿ÷ÿ÷7ÞxãÁtw9t¤þžn»¨Tûù^OÉK³õtõ ˆÞšÉvtég§—dëéìP.ðñ¿T7W¢[€ÓéEÑn·Ÿ;wÎf³9s¦¯¯¯··÷©§žâeÍY—\ÿJ¦–´nDFscŠhð9¹´à§ úìÈÊÇåW%""r‡YuItëJNN~ñÅ=ª×ëÝ]Î4“ºEfš+2¢ÿµ9ÚºƒŸØ8NT•A«C‰±Ñ ÿ¯Õfl~$X²žnúä´£¥òm&ù½mÎÀ©ÿ(Ü&‚ $j韰ý–C…Ñ‚ BhÜŽÆ®)â…ÔQœ·ëÐYëé¦ONŸ_>YÇ;G[ebJáâm‚ D'æ×6Ú-‚RÜ(oÝÖR-‚—Rh¹°ÝÊÑV½Ãbà8´#.1¿V`kÚ½­ÉoàWsCAvmkºxk-•;wç§D ‚šRØ6!MHmù‰‰ùÅ…qrÓ¨£cïŽ8A„èÄ]r ))ùÅù)ò19ÒåÐr`Û¶–Ñ#v`Û¶-¼QwxÏ®hA„èüC-®=̬§ÍŸœÐV['‚ D§¶ØLþ.\µíz$@xÄ6‹ ROÓ.y½ÐÑÚ.:ÎùŠw‚ q•£¿Y[uaŠ ‚ l+®•[Ø&­³ãÈÞÑÂóÇ~ ý‡òSB!:qÇkUu‹Uh©Ür`ôÓߘX=–Ím‡6.O ~ýBµ c¡Pê:°+QÞ{Jþ¡yYOÓ®ÄhAÝV¸·pǶCm¨B~SªÿÅÛÓf‰ˆˆ¦‰“ˆÜíôéÓßùÎw~øÃÚl6w×rCXMy€¡Ïét:Ýõ9€Þ,:í&e6WŒûQ×Ðç´™ò€‚nk»Ñ $T4´ö›‹@ŸSoj0$ZƒuÜÆÅÖråõ­­&C /µ_°k´Evg·A ÃlÝ~ŸÓi*X’grÚMkSßî1¯¾¾"UZUSñÿ³wÿUÕ÷ÿÀŸî…‹v±‹ƒÔÐÐ× ô£¹¤.º&³¼æt•Â&¹ÀYl3¿¸äÓW|°šâú8Ð5týÀLš…m KavY\V—%NÜÂä½É½pœï®WÅßèîóñG]ï=?^çr/Üç}ÿÊP`sÊ-åFÀ”UdµVecN‹çÎN‹ ȱØeÑšéM²l¯ÎÒ›–D0”W—¤(jøhÖ<3sNIuy 0åZÎxB•oRr ,--y&À˜^f±–昔4‰}õ'æÙ-Y&éM¢lÉ5"§Z9@ßm§R¹¤ÚR–› ÏjwX ÜcqÈ–ÑÈ9 \NFIuScU€ÄÑ9ÐUxWš sJªÚŦ æKccYn"€"›ý´ëPê4e”WWå˜û~²Õ¹&ÀXTm³UåA¹öêtÚŠ¤ä•76Vgd5Ëby†0æ–U•å¥0çY”S”µÈ²,7•¤)¢ûôý¯1Ks»5ȵ˲5טJ,6[u‰ È(o–å¦ ¦¬*Ky–r-í²,;­y@¢ÍóÒÉ;ôööŠ¢ØÙÙÙÖÖö¯ýëã?Þ¿ÿž={¶oßÎU¤ Û·oß³gÏþýû?þøãýë_mmm¢(öööª]©†¿ˆTVQQñõ¯}ýúõjrYóL0æõ}Ào¯2Evk®)e²Ü”äÙì¶3Œ¹í²ì°n6:dY´) M Æ*»,˲hḚ̈ ¶ÛJK«í²,:Û«rMÊAÜìÖ<Àœž CùDî>þ1ÏÞÜhµÙlVkc‹S9cµ]–eÙ’k‚¹H”eY´š\K»5Ï d5˲,ËΦR¥MÎæF›Õf³ZmíNg‘¦<›ØT0–µˆÖ#ÒËe§Å d•·È8šhÍ5!±HÉ#–£1Ç";[lV›Íf³56‹N‹H/m’eÙi+PÒ´š³sžÕnÍRlÊþ-åF ×b·äšŒ9}qѪÜvZLJp•eY¶ça̱xļ{¢s,²½Úd”XÚEÙÙb«¶4Š]…ç³'‹VLQö|e¹=×cŽåì繪]–ûR“ÙÒbM²ªú‚scQ"Œ¹öê´äa.rz¼¨ lgô3Y–å²ts-²Ü”$–4ʲ³ÀcÐí{ñØr\§¬|Ëk—åky™¥E–Eg»-ËcNµg‘Ê3¦Ä<¹½ÊSõi¹•¼c 5Œy4 vÚ$RÓúõë-ZTTT´jÕ*µk¹V ‘‹÷j>({Éšþ€Ÿ“‚WÿTY]^jZz—ÁcC§X»Dèß¡ï¿vÏãi4ÚÿTf ‚6 (.­cýÏê†Yº±@Ûù‡ß*œoŒŠŠ2'äÕ)g¼UZÀ© ‰ý'Ö™a‚ BÀ83€¦¶Ö Qƨ(£1jë'Ω‰‰•eÕ–Þ3e•ä%Z«,–ʽ֌ùÑJéc®×áGsŠ€qJ¤r!ZÝXŽO ¢ŒQQQQQ €?>èb¸pB€ ‚– @yÎŒ1aÊþúëÇÀi½ [?¯ì¿i2ŽÓ)ÛMYlàyÑßödNJöÂØ ­ðà†Ã'5š®â´gOˆNx>@@¨ÐýŒ·‡hήÓwìDT¶tö?GG€_î©a:O´)7n›óTþ®  ߊŒ{#ug_£ÇŽDó–9%MívY¶˜`W^MÖƒ-ÊUHŸUîCØaš:Ñ0𑈈ˆTŘG¤‚O>ùdòäÉ7ÞxcUUÕM7ݤv9WÝÍwLƒõTúºõ®x0΋€ÐØYFHœ2QÚn"€-Ž¢™gó‹Øàæo„ãXÍsæ‹3g?4ŽŸ½¦*6מ³íE£Ó+.¸‚ÚÍw˜`}é=[‡^ƒ;Òf&¼ð¹„þ½õ@>9 °Â8ùÖàˆ©wV˜çݦ¿„£ X`ÿN *ú‰SͰüñ ¤×;ýÑ—ðÖçà¬Î~³pTlZ[‰Ä{oÓ°¾TvØ%Û÷ÛeV„'¶µJh­Ý•\Š¥³Æ+‡íî?¾ÔT5!äí£ˆˆž1û{Ó€'­9íÙT6jÕß|‡…/î®—€cû¶/«ÄrÓÄó?Ïâuã4!mmñQÐQ»qa!|[?@‘Sæ¤ 3åÍàØ›bEº)öŽy&¤­-8ê‚ëèÞŒÕV%Êê"¾›c¬LKÛbÎ[z¾,”ìšxë-áýÑ}ÅÉ•€KÔß|+Pøâkµ.©covZiÿ¦®&kåyŽDDD¤*.îJt­½öÚk=öØ /¼ð£ýHíZ®‘àè8 á`ëŠø`0L¼Ë Ø—N îx© i3O¥¼hÐŽ Ò&Ü5æX!pZwÂ@­Çdþg=b‚yœ6@JF ²ÓÜtWÅŠÏD xÆO‹RV/Ž}q–5°ïø}jo‚Òötºþ3z<  Mpüª²K‚1D¹·ÀÒ}fQè=9&ÍŽ61)@ç§éûà¯Õ\ðhõÇhámå8ú©[«óB¦Å.sNyÆTƒ³²ÍQÙ€ÜòæHsÒMiæ «S¢î5âŒÖäm2€Äܪå1W=€ÀÑýtѤ¼dž ¤Bd”ØÂ!ž}§U0fš‹³"ìu»J³&˜)yÕK£Ï »gþd K «Þ‹Ðw=«fµgש‰ùߢô{ÌQJa¦kf8 Ë Ë†Í¦ÎÜ7}fðÜÕ)«oydö@½Rýϲ€á®•éiɱ…É€1%+Ý”¹:¥æ§uÍUy q±‹†÷/>­fßrŽôNDD¤.A–eµk ò’$=ùä“»wï~ã7&MštáF×Τ€ÍwY+R£/i7Éå’4æB_HIŽÖ—.(X¯ƒäpHn‘»r®ŽÖv zC°~0Îu¥Gs9޵»ôƒ^ÀQ»)0Ùß^·Ôu¬Clp§PÉÑÚ!é †3žŸŽÖVI£÷ØîL­Çì 1\l}’ËN@rt´´Ûµ7œçøg_Oë±v!¡Ïó]§£õX{'‚ÂBOÕ%9Z[š PϳÕçÇ_ý‘½bÉÅ„2WG«CÒ‚ H‡3@Ûþö®ºIóç†ë€Ž}“‚âÖ5‹sC;Ö !Ϊ–gg_øˆ4²È²ÜÓÓ#Š¢ÓéøàƒÉ“'Ïš5kÏž=Þ—ñÁ³›-Orq5ék!àæY%e³Ô.cHÐNJXZTn[s¹s¥h"·¶ØJüú§oˆ.(oßj<ßÒ¼‚³¯ÑÅÖ<¢«nÓ¦MÏ<óÌöíÛgÏž­v-j ‰Äæ/:—?ÿùϾ¾¾ fÇ«]ÈР ›ºâ ¡ Ž\¹Àãžàh6äÑÆ˜Gtuvv>úè£6›­¦¦fܸqj—C^áý÷ß÷ññ‰gÌ#""ò^ì´Itµ:thÊ”)~~~û÷ïgÆ£kF8·‘·cÌ#º*vïÞ=}úôôôô‚‚îâ'$ºRŒyDDDÄN›Dƒ¬§§ç©§ž*...++›ŒyD×€2™¡’èüýý{zz$IêííAiÙ“$©»»»§§§§§‡oI,ʫγ Y§Ó5Êݦ§ Òãd›Æ<¢ zçw’’’Ö¬Y“žž®v-DÆ)Xˆ®¥Çfoo¯V«íééñ÷÷—eYif èîî–$IÉxì´IƒÈÝ[Xy±)Còt:N§;»ß¦ÚÅ’ÊóˆÎIY5!??ÿ7ÞøÎw¾£v9D…­yD׆òi[–e???ô7³hµZw_M¥gOOÚ•Òˆ¢4Öy¶é)aÏßß_³ÇŒG Æ<¢µ··?üðÃN§óoûWM a„1èjSzĹÛUüüüÜãô”Æ=7Ì£Aç~í)‰ÎöÜMyÊ£ì·IŒyD°X,óçÏðÁ³³³}}}Õ.‡è0æ]Êhå„{º %æ)ƒôdYVújʲ̷$ wxS‚œ{ %ï)ó¯pl)óˆÎ´uëÖŒŒŒ­[·>ðÀj×BtÉóˆ®å¦ts7î)Ÿ³•€çÎxîÿ]9%¼¹“ž;ì¹ì¹—R`Ì#Æ<¢SœNçc=VSSsàÀ‰'ª]Ñå`Ì#º6”éŽÿüç?çÏŸÛm·ø ,Ë}ôÑ×¾ö5µË!º|“'OÖétv»Ý}ÏèÑ£gÏž­bIDDD¤öß%ïUSSóío{Ú´iùË_˜ñh¸5jÔüùó=GeŒ;6&&FÅ’ˆˆˆH-Œyä¥6oÞ|ß}÷mÞ¼ù™gžáxe{ì1÷ìA?ýéOÕ­‡ˆˆˆÔ±yäu:;;SSS­Vëo¼qË-·¨]Ñ` ;vìÿ#GŽ|ýë_W»""""R1È»:tè¿þë¿|||ª««™ñhäyì±Çt:€˜˜f<"""¯Å˜G^d÷îÝÓ§O_±bÅöíÛÔ.‡hð%''˲|Ýu×ýìg?S»"""R ;m’WèééY³fÍË/¿¼k׮ɓ'«]ÑU4}úôtvvò» """¯Åhäûâ‹/~øÃêtº>ú(((Hírˆ®®ììì¿þõ¯ÌxDDDÞŒ­y4ÂUWWÿà?xôÑG3339£&y¶æÑH–››ûì³Ïnß¾‹D‘÷ðö˜ç٘Ɇ͑ääÉ“?ùÉO:TSSóo|£··W튈ˆˆˆÎI„o]oŒyîOüîJÀcÌ1.\øï|ç½÷Þó÷÷—$I튈ˆˆˆÎG‰vî€çiÂ!'ty¼klž’ëdY–e¹··Wùgoo¯r˜ôF„7ÞxcåÊ•¿úÕ¯Õ®…ˆˆˆèÂÜO%×ùøøøøøýÀ&>ºD^ÔšçuŠžž÷ wðS¶dئ$IúŸÿùŸwÞy§¤¤äöÛoïììT»""""¢óñl¾S¯¯¯’ñÜ7”ì'Ë2“]ëjFJéŽs<Ÿ““ì‚«¡tY%J³gGè³9kuiá^Û÷¦0–·ì޾FOÑÈÀÖ<""oá2Êlí-ÍÍÍ-ÍÕF¬~±Ìåú¬ÞŠÊe±Ê¼,±ËJ1Ö€¦{§(éÊ`Zj:ãP§ÆÕµ!}Ê7”›7Üq'°÷Ÿgö®ÔÏßR`Ú’fF©(¶7ÙÊ æd/›Y\ï€þ9>•㊢0–7;E»Ýé´[«Ê2ͯÚ3ADD4Â1æyÉ}Kìà¯ÑL˜“‚_?êÔéŦ¼¨i …M…϶JÒ±Ú]*±`òͬ.­í:jŸ˜™­4ú!Ö´¬Š£.©£þ¹¸ldL6œyÆ–§£&$Z ᑳçÌ2ž£,ýÄ©fX þxPÒë‡þhŒKxëó¾RÅÁ}ˆˆˆ¼c‘—ОC²o¼Ãë²Ê£ÒÜç­m«' B`T¦1Ëöüle#Ó¡ä­6,vñØŒÒUñ¡ú˜y‰HŽ ÒÅ6÷÷âôŒfÌ  2wš x IDATf›²l™ñ€ö&Z-DˆøeIFir¬ BÈL¤ÌÖ{®¥Ðw[?uku^ᲸA1.6ç”gLUcà(®¼@DDt‰Y–Õ®áê’e¹§§GE§ÓyòäI‡Ãqâĉööö¶¶¶ÿøÇ#þò‰ˆ.ŽÔÑÚ"iôƒ^ÀUð‹ç·9[Ðô›u@×·Õ©-.„Î5¯—ähmnïÔŽ >ï*}.DZvW€þÌãyA¶oß>vìØ   1cÆèõúÑ£Gët:???___AÔ.†þ%""Cp詉b%*OŠÐ‚ugn6À¬—½!ô¼ñM£¿˜UØuúÐ󈈈ˆ.;mÑYn)/)‹àRuDDDÃ[óˆˆè,šàø³Õ.‚ˆˆˆ.[󈈈ˆˆˆFÆ<"""""¢…1ˆˆˆˆˆhDaÌ#"""""Q󈈈ˆˆˆFÆ<"""""¢eäÇóÌ3fëÖ­j—C.—K§Ó©]]&þøˆˆÐßãLIzZ­V™BBéÀ© Ïã,ty¼"æy¾4 <úpJ’¤Ä¼ÞÞ^¥Ç&Ƽ3üýïÿÅ/~qÿý÷ÿô§?eŸ:¦L™²ÿ~eqvbbbjkkÕ®‚ˆHeJxSZ#”Oª ¥O¹í9 ÑEòŠ˜‡þ·2_ˆ;õ){ž}5óÎöÊ+¯üú׿ÎÎΞ9s¦ÚµÆÇÇçºë®ó÷÷W»ºLì@DäŽyžmJËž{Ý<÷ÒylУ‹çE1OŒ‡³bž²Pž;ã1¯_WWWFFƇ~¸gÏž[n¹EírˆÎäëë«L<­v!t™®»î:µK¸*bcc-‹ÚUÑðàNnîž™î¶;÷ ÷4›DÏ[bejM÷—%J®óÇ€çöïÿ{Ñ¢E·ÜrË{ï½7zôhµË!€N§c̾FêÏ®¹¹y¤^]%îÆ:w¢s<÷¨<6åÑ%ñ¢˜@yÛ(ë¡»cúÓ3ž[yyùüãU«V¥¥¥©] Ñ9)}ZØisøÁ?»|iDt•œ‘åÜÍwlÇ£Ëã]1Oáù¶ñŒvŒyŠœœœÜÜÜ×^{-..NíZˆÎÇs^%ŽFðÏn_]%žul¸£+çí‡øŽòôÕW_ýèG?úÏþS[[ªv9D ÑhÜcn‡¸üã‘‘‘6›-22RíZ†añ³»<#øÒˆˆhXàß!êóücòäÉ!!!UUUÌx4,xv½â~ó›ßøùùýæ7¿Q»"""ò Œy¥¥¥wÝuדO>™——ÇUÈh¸.1O’¤íÛ·wwwÿá$Iír誋ˆˆP»""òvŒyÞ®··wíÚµ?ûÙÏÊÊÊyäµË!º¾¾¾===jWqaeeeîõo¿ý¶ÚåÐU×ØØ¨v DDäíó¼Ú—_~9gΜ}ûöY,–É“'«]Ñ¥.­y/¾ø¢Ãáàp8^|ñEµË!""¢‘1Ï{Y­Ö˜˜˜Ûn»­¼¼<88Xírˆ.Ù°ˆymmmï¾û®ûŸï½÷^[[›zåÐEsÕ& ž&­Ì¯p ¼©cÛ¿þŒ{ësMÆõµpÕš!·¶c€Ýê7 “6ã˜DDDW„1ÏK½üòËñññÏ>ûì /¼àëë«v9D—cXtÚ,,,ôœ[_£ÑìØ±CÅzèâ9€ô¢*›ÍjµZJóâ7.›ùÛšÒ€.ûwŠÊÿtã×–”ÄߤøVp04] Œy^G’¤'žxâ©§žz÷Ýwzè!µË!º|â5/==½³³ÓýÏÎÎÎçŸ^ÅzèâÙñÑS"#£££cæ¦>W`BÑ{ŸºŠç¥+MpîÛþ¨Ü¼>uÞ$A’ÖóœgGr|úÁÍv Rë›ëS•–Á•Ûö¹ú>òʦ•‚ BÒ› gH""¢Ëàíëæy›ÖÖÖ… Ž5Êb±\ýõj—CtE†EÌÛ°aÃüñ¼ÿþûÜyçjE%p}Ù)È%¡ý“]*1ç©[ÄΚÒ-ò@ì<î¾ kᨕå–ÿJž¹8,àFym|ßQ\Ç_ݸ1!)3¶jƒyõeÖÆ°Ö·Œ3ã"Ú3®÷6&WdUYªÿ¶ašùÁ)öºçhõ#""º4Œy^äÃ?|à’““Ÿ~úi.ÝK#À7Þ¨v –žžžžž@„W_}UírèèÕqa«Ýÿ6ç욌C€ûo§¶ïv—Ȫڰd€7KŒ[øa«;æiÀhû×'€Ú€¨øÍÖ©m€€±jÇÚzÜù˼´¨²CŽ1ÌyDD4øYß[üþ÷¿¿ï¾ûþïÿþ/++‹F†}ûöMœ8Qí*hÄr%–ææ¦ÆÆÆÆ¦fq÷“ºÓ685¬® éS¾¡Ü¼áŽ;½ÿßǶy‚ ¬¬wõïàªâkŽüø³N ›jžQ–ˆˆèbðûïaï?ÿùÏ‚ BBB)Ü‚”’9Ê:¦˜»§ÆDž¾½CùŸ5sæ¶…Î%‘î%4áÑSÃHZ30>vzt4W[ "¢+Ř7ŒmÛ¶mÕªU\¼–>øBÓ×]}°ÖÄÔU(mÎi‘f/J÷ß{û['ú[ópý3¢ À”‡ó½lßÑåsÃ5­ß*…©jf„ç*Þ«©9qªõïÛwFÐe‡¹ ê‘OãÌQÏÝ+¯ =ãì’h :Æ<""ºRŒyÃ’$I?ÿùÏËÊÊÞÿýo~ó›j—CD4"è¢7[JV'/,´¦ô‚‚ç–„z p™¹ðÔvf‹}·A}ôì à÷•s—LxïÕL$–L1€ °qÙ´§vȵ´¯0hØ»‚çfV›²§­.^´c»ÑÕÂ)X†ŸãÇ÷»ß=tèÐÁƒ™ñˆˆQhÌ‚uö\“1« ““_ªàr,íò)»cúÚ‘ÃäšJ7ü©Ãe+Ü‚¬”»•f¸.;Œ¹íå1†¾tuB7ukIJáâG÷î Så"‰ˆÈ 0æ 3uuu“'O¾óÎ;÷ìÙ3f̵Ë!:×ኽ ® o7$GGkkkGÇ œÎÑÑÚÚÚê¸F…Óâ¨Ï&mrA ŒŸ·dÅóYƶ"; Ó ¸‹Ñ¼Ö—^Üôb)N vß?çk©‹Xð«ceÜü”B²Eˆˆ®Ƽáäµ×^›9sæsÏ=÷ì³ÏúøðgGC˜tl纤€ 3¢R׿Ùê± Âáâ•§OïØvútõ©ëßì{ì̉ìçåWèd{×§jƒBBB‚‚„yëj[%ŽúM¤MŽS›9¶Å ñùõœqÓ^e3©µvÝvJd¤@tôîÿøiæ7Dxüê:R³ÆÜEñ‘z@Ÿk-ê|ÑÑ.áü“pšb¦EFDˆŒ—ƒÕ{›Ú€ ÿÔÁ8oÞÔð`ÑsŸ¬Ê9\æwUž ª4SSóÅ>¾*ÈøFû‚¾µîbvÈòŽsï±`ƒ,oð¸C¿h‡¼h R+äTN]±[^áño]ô9–!""ºdŒyC]CCÃ}÷Ýwß}÷½ð ¾¾¾j—Ct1BS÷èõèš6C7wîŠþö°ƒ%É0—¤,ÿfEšqçÇbf»§”Ý;ë¢M@yuÓ’qÊ#§z|NJx«_=îD„G†»ñ¬iñçþä»b¢&F-Ú‘¸)ˆ *ËÞ¬¸­âÉCÉ[ ”.0ÒØ‰°¦çÉJüÞ½ß6Þ:ãÉüƒðlÐ0£1D¯²5ê#¸Z cß5¤íٳ箻îÊÌÌܸq#3 ºyÿkËMi^]˜iž LJÝ{ØRÖLd¬¸[§‰JLAvޟΑĂÂM°Ú;Ï~@É‚ZHÇ7Ô74Ô×7t¸¿¶±¼ %°:mqBlÔ¸@­°ng}ßçéà\ºzæã¯\¹zYv)€¦ÃÍ€nÁÿµ”æeØ+2&L›$IG9‹7 dÈ#"¢á1oèzæ™g–/_^VVö£ýHíZˆ.ƹ"¿¢½*7%§ gü–„ù@ë7 ì™!‚ ]¸(ýÃÁÖv–šß¯Äâ©ãxHì ÂQ8!Êe4Fmý¤ÃÑÑ·$w,Ú›mÕ¹)ÆÌ…iµJ‚´~Üì1û‹?ÐæÜóÝ×ÕÕÕÕɲ½4ØWÚ©£C77õÙŠ:Ùio±V% g&oÿjž“ & Ò‘ˆˆˆˆ.€1o(r:=ôЛo¾yðàÁ)S¦\x¢!ÅUŸ$ÅG0ÚÿöY‰O¾PkŇëÏ[V#%ÏbµZ,V«¥ÔŒÊ‚?7ôïsjVùÖª7 1ýó×kÝ}Ë¥Êi€éf½a…½Ï1ømPHà¯k@£œºâ7•Ÿµ» ¨>átïÝ|  î¼Yù×X÷õ“b¦ŸÛ– Àâ£>8zÆ¢§WšÑÖuÝ =+‡¤#Ñ2àª!ƒ¸¼ÑåaÌrþýïOŸ>]«ÕVUUÝpà j—Ctétcor^Ý÷ÅIàäÑš·þcÂD×þœBä¦.Š‰ŽŽ‰‰ŽŽ™»"…9o*íy•Gê7Ô×ÖVì\2s5ÒK#uè›Èþ£Ã õõ5ÛÖ,0oDVùÒP@§ï£áÎV'oÛwT’$WÇÑ/þ 0¿A§?Õ ë´¤M‡;\.ÇÑâUn"BûúâUÖZê7Ô74ÔVlK^¸)1aú3€ÅÉٵǒäj=¼ïÅ ¥ÿµ‹¹b~¬A¤£õ5õG/b)W ´å=ˆˆˆ®ˆLCÉ|pã7>ÿüójBtEÚ­EÃâŒEÖöÆ¢ ½Q<µÝ’ ¤©µ ñ´_J)9%-ÊfNËiÍye¶N&6¤›<¶3T7÷ÂVêù@^ßýöóig4g5‹²,ËΦòÏá|æ,kû…¯µ,'ÅsK‹xÁ}ÎÁžgDŽå§†ê g€Ë…6Ë2cFIAFzN^ €¬*Y–Û«sä•ÛìN{‹­<€©À)Ëvk.k?µ»=ÏS®E¹”[c£Íf­*É^Út¯ˆˆ¼ÃÐü+ë¥^z饯}ík{÷îU»¢Á :­EééEÖË=—ÄÙÞÒÔÔÔÜÒ~æéÄö¦¦¦¦¦¦û€ûMloVŽä¼˜­Ïõ±þ²8óTg+JW{F‰M–íe¹}>=¯üôWP{.Qå” ò,N§­4·Ä"ʲ%×ã©8ç´%¦ä5‹ˆy¦<÷÷ö(÷].¨0$ôôôüüç?ûí·?øàƒ[o½UírˆƒF•þ8®Ío!8Ü0`†ð8!ôv8ת}¡©vgvòÂL+Œéy²RãõÒáõÉ?ïš2ýÓ—VZ‘^`ynIŒZk2MÉ.µ¦ääŠÛ/¥Vt7Lý^"6šsL «ÙdNHk+ª¶Åt¿7³®Ë½$:εjÈà-ïADDteÔΙ$···ÇÇÇß{ï½_~ù¥Úµ '_~ùåW_}¥n ÍåY`JÉ-*³Øšìý‰%)rK«-åyÌyVÙnQúŠæ•U•å¥(°9eÑ–À”Q^]ž“¹lÍS™³ÀSžUvZ¬ªåÞÆ¢DÏf:Y–Åv[nJ§`cJYc߃å)æS9-«Ä*+6·æõu!6ƾ½r«Øi“ˆˆ®§`Q™Íf›± @—Qlà××s¬·x¬Ï1àª!ƒ·¼ÑaÌSÓ[o½÷ôÓO?÷Üs>>üY]ŸÞÞ^ukøc}ëgõVT.‹UæNŒ]VбþìÀazЄ%áDt‹oQ¦ÿÔŒSc̨¾˜÷Åß߇ñöwäW é´å=®ÉÕÑÆh¡šœœœG}tÏž=IIIj×B4, ˜wŽõöÞQ@zi£(:íNg‹­ºìîî[ÉAìkÐéêû'€ú¶¾ûZj­Ð]ã+P,Ëj—0 mh;ÑâÐЄ´µÅG]@GíÆ……Xðm½{«W ÑÞò*]<œ‚E]]]K—.=tèЇ~ªv9DÕ¯¯oOOª%ô¬¿óÍÄ;Ã$Góåc}ØísR`Þøúã¦'#а1jZfJ™8%äìýõ7ß ¤å¿¶ò¹EFÛΗ¶¹×þ"è4†)Ë­Ëîò·X «Þ‹° Ì9«fxlú¸µh§1n\ß?EÖêOü'19n\rßý¦‚êÍÑ:@7u‡­Ôež”¦Àû+ÿ žm+ÍÚ¸8V+h ßà?d¾}sÔ矶n÷¤¤âšcoêªâkNŸMò«úëp¸"ž ‚Ÿº©ÁÀ«¿ÏJš$‚°¦¸VÙÅѰ75^a^ê¦ú €ëXÍ:e#!ig}ë©ê¤Ãëî;ue½RkmßfçixlCxÄYóðáÃ׿ìDDDç˜w<óÌ3iiiþóŸçÏŸ¯v-D#ÄhÍᎴ¶»$—ËåêØ·ë-ÀtKˆ®óxÅÆÏ:•‡;Wlüì=™fY^m)˸Ú•ïÑÓ~¤ð¿ŽÃUûèÌe·•T75VMÛ’µ|§èÊoÍÜP]Vž½8¶ø° ­wE%2Y­U·U§ïùu+\»–OËt,·55–f5/4ΪuÏFª ™“ž sÖο)àhfHl¦c±¥±±l)O +n¸²î W`„ jšˆˆHÁN›WËåR&\9xðà7Þ¨v9D#cÞÕgvª/fb^µQ+Æû{Zjûo7¶WDê0õù¼—¶l.;´8Á½ßØhøA•=çf¶ØÌÿÖ'@Vù_–ÄCeNÞxü„³þ/›¬Èj^»(˜øfiö8ó£)Ž#À4í¨°¹¯[ïýì¦S¸ô1ß7™°{Ö¼[~6ŒÕ;žŒÑ+6å¾T˜óæ¡E‘1×äY"""rØšwu}þùçwß}wOOOUU3Ñà1O:¼sïÙ=ô\­­­­­ƒ;3ƒ§& IDATˆ:Š,MÍMMM-ö©SÏøj°õóÊþ›&ã8¥Û©~ÊbãÒßödNJöÂØ ­ðà†Ã'5ÀŒ¹^’Ø¿RœÈ AÆ™4µùÎßR`Ú’—ZžŽšTh5„GΞ3ë̆B@eáVýÍwQøâîz 8¶oû²J,7M„ë'""ž86ïªxæ™g~ûÛßþå/ùÖ·¾¥v-D#–*1OŒ×‡è5šúƒÀÒ¥‹îm9.¦®hö¿ñO’ ®¦êB ôáÙ¡úEÏn=üÉÓímèÏsH;L·ÆFFh rÔrÓÆev'4}Ð#N\›«:§ÀQg­w0qNº)ÍcIr>8üœÏˆÆ=öY£7„ê¹þ8Çæ ›Í6uêÔøøøW^y…èP{¦MýŒ%ÏÊíUééy%y)™ Û\’£Ã»bÃYÛ[Ë 2*7&?µó0úF¸ øÍZ3Œyöºººº:Y–›«ò*3*€I:‰ˆˆH5ŒyƒãÏþs\\\VVÖºuëAP»"¯ j§M×›+…yù‡¡÷ ?}AêJÐrÂi+¸'$0»4†àˆÙK² L¨þçqhµaÀç-§¦ˆì<ц±7tÊÐô¹ºlÑðƘ7òóó“’’vïÞ˜˜¨v-D^DÕÖ<Ýøñ¦ÒeÅõGO­õÕ•À-7DÍY d&¯ßÛê’$—£aïæäJ,˜| tÍ)ÈNHÜYß*I®ú7×M[mMüÉÝz„µá£†††ú††ú}늭„ÙtÛ°éyèêPÖd.%""B86ïŠôööþâ¿xûí·÷ïßË-·¨]‘wQ·Óftò֜݌ HÌ«ž®Ó`‘µä°qaBéê¾ÍRrËÓãƒ,ø¿¦ÜÎq ûç4ç”m] þz`c\ÔÆ¾LéåYÑÃbéè¶UÉÉûWHO̱nz"Ú ©ßŸèz¾îɘ«wæ¯êóôƬÎÃã‰"""ºæó.ßW_}õðÃwvvVWW_ýõj—CäuÔiúˆ'+ääúâGïWðÜCÿoÓèkeçãǾ°‹ZmPP¨ÞC4á+vˆÿª¹À¨ ÷jãÑKvÈKv t­ÿùgèTYkþ½ã–UšKª¿w[ˆ£ùàsQ3V]{Ý îõÓ¯ªÏNr#Ñ9°Óæeúì³Ïîºë®¯ýëï¼ó3‘*TjÍk³®Ž”Z¬tR ŽNx!}¦áŒoÌt†ÐðððPŒ×G|¡y4]õ©BÀ2+0ÐêäC£öåe•(iܹ`j„^¯Œ®±Ä„#Ÿ9 E µb÷ºÔxAâSóºÀq¸bͼI‚ “æmÚ{€ëðΤÔõÅùkA„y;:4ì\“´.}j¼ “R7Vb®ëè¶5óAⓊk޹kàTWDDDç˜w9,Ëý×%%%mÙ²E£a‹(‘:T‰yß|pW]]Ý««âûƒš!"ü¢ÆÑ566^Âi4ßøy]]]ÝÇKî¼ô¯…Cïï†1wfÄ©_€šˆu¢õ€¿¥™ŸÞžn©*–eÉ[jGÁ„™ÙúåÖÆÆò•ãÓ­q@ìl+ܲzñ«(¯®Ê1—.|p‡Û>)Ì\¶?byuyÁØ-in©:ò¿?.ù­ñekélÇâia;²ˆˆèQ.Ù®]»RSSÿûßßÿýj×BäÕTé´9ú†ã —³ãĉe÷jà¤s«Ñx9§¹V´þ€õu5#¥tÇŠ¹žÏÉIvКÊJ-±÷F4­“€ºþMU¯?;ÀéëòVË9Vh»ìH,Úùä ð|Άd\ ¥Ë*QÒ˜=;B‡˜ÍY«K ÷ÚfO¿&IDD4l1æ]š^x!77÷OúÓ·¿ýmµk!òvj¯›çÝü×iÍj®£Å[öF'-ãí7)÷iuc•ñ…íu)!æþ`hÖ@°ôÐ×5Õ®Ü0N‰Ôxî+À î󘻆jOV""¢!ƒ6/VOOÏã?¾}ûö0ã Œy*š8m°zWý©u޽›¿8mó—Ê·‡ýSÇ(L:ö§i‹3—YíNYvZL°»ƒÚß5ž¾¯(Úcy³S´ÛN»µª,Ó<ñ*\ш˜wQNž<9oÞ¼O?ýôƒ> S»"óT¥‹œ“kÂ2£¹¸ö¨Ëå8¼o[BB6RÖNh ¢dopËÄqzMÇ›Ïý¢8é`|Ý€tú‰SͰüñ ¤×;ýÑ—ðÿÙ»ÿ¸&ë½àï 6ØÐ@ ¥¦v£¹QGú¡9ð”d9*ÉD(QŽ™€ç¹é$÷ù¢'Â~dx °2¡Ê€ÄcÁí;6 J8І覲± ®ïNDLØ5àõüÃÇvyíº^ÛØv½¯Ïë‹3Ýí¼§0 ̻±_ýuîܹãÇß¿¿Lv£ùñÀ\¾ Âhç².¿&1¸e¹÷d©Ô~Ú¼Ð)±¹Mï.‘õ¼–[âñh²Š§Ù3b§¤_|‚¥~ ¶_ ¢«†Ú‹Å}<–dsv”§fGÌ“2Œ«b¹*±8v_JÚÁ°€ë`nbJ€QéèÑ£‹-Šˆˆˆ: \e÷îÝ{÷îݽ{·ÐAú…aFæ÷­®­Y×nK\ÿRål[s+rrq”«×±"™äfª4½ît«^*st” ƒÚn¤¾×0Œ ƒßK}ýõ×AAA)))Ï=÷œÐY 7tÚ´2GY¿®(!rtq»|SrÓÅšDææ†Îý…N›×•‘‘¼wï^Ôx– 6ú„Ö¼¾mܸq×®]eeewß}·ÐY ohÍèZózëèèþúë¯+**PãX2”yfÇÊÜÕÐ{ŽL}sssss[Sg€@Pæ]åܹs>úh{{{iiém·Ý&tø=è´9¤4)¾™Mf€ç–*"ÒÕ—DûŠç….Ÿ,H+©å×i8”éËH]]]]]ÄŒoÚ¡""}UÓÛ–ª6Òkz-÷ Ùtè´ž_¾«öʾuU! ²«V§É¼fK¾:ÒiÒz- ß’×L¤¯Íd˜MÍ.† ¯Õ÷ñ¤F tÚ¼âÔ©S .\´hQbb"Ã0BÇ€@kÞ2i F²%""¶vÍ4?JLkÙ9q•w„ß RkÃg4¾:/Ô>¹°1ä!ÛôÙÖ—Ï[<½©ÚWF:¢àÔüµ÷Žïèèà·å6EFdÔEå”…{3ÉxîxÚZÕ<mõšåQäŸøÕëAüd.ÍG¾È&*œ?Z¾" +,_9¦Ãt‘¼1wK»oe”©}Æ‘‘¨ù§B¿ÀÀßÔ?h åÎvDtÏøßŸø`DC™×íèÑ£þþþë×¯ŽŽ: ô ʼ¡¥oi±%2hÕd¤¶ÓÙ¤PoX£ùöˆ|ÍÆE·¹ž³ëëʳ‰ò—-ts$"YÐk;êü{k‹Žd¤%òäñ9WÿÄèIK4E>ÛïÀ䛣ÒýhÔ‹ I¦¤ÈC§×,véîŽ#eÆCn":C¤ðZ0gN¯ß*‘Ê{¶üò–ä9ʘDƒQ2ý^eK…l’R¥(úÀr¡Ì#"úæ›ož}öÙmÛ¶=ûì³Bg€þB§Í!uÇ#ÑËs˜8euâO$³S‘:8ü¯”ߘØÄ. '"b}‚‰T®ž±‰Ñ ñö¸{ÆÆ}YDDz²'ú×Áý÷ž¿ÜšGãfÍ•;ÙoþÕ;µ‰Õ7îÍI"U†»„dŠEQùþW5‹WÈI÷cv:E*eD:1‘ºê늊˭yÆ1n÷yMåÛüŽ7þ¦›îDF¢Öc_î)%Åj;" X~·˜ì|—{àç F5nÔÛ½{·‹‹Kii©ÐAàæ+•J¡Sô×pÿ¾m¬Ì Vtÿp(£2N9ŽãÚO”'G›~P”QMǵW÷þ©QUjû\N‰å­üöˤHlå¸Ö²x"e¹–ã8N«Níµ¾2¹²ÏåDJµQ¨×¦·áþ^À0Ú§`ÙºuëúõëKJJæÏŸ/t¸9è´iNn^K²ªµÉJE|F2%…†îÔ°º6“÷º­Yglmª+̈-M }5¯žˆtD‰•­=~köyɈ_[XÓÚÔØØØÔXW« ˜m…üT)ÞÏÄ:¦¢YW‘GaQÞÝ×B7%÷ÜPÉ:¯Ë‰ù5MMM5Å©D¥…ß5›ÿe°L£·Ìã8îÏþó?ÿùÏòòòY³f n:mšN“Æx¦èIL4%`ź7ã-ç5ó]íÚˆˆDŽ.S®ˆÏPRùΑ–H"–^»-ÑWwG777·©s–­Q’úl;‰¦þ1‘(uë{©é”¸rî•.— êcCDDÎ'»¹¸¹¹¹¸xø>›¬ œÿ;5èO`˜¥ƒ:::žþùÓ§O>|xܸqBÇ€[Ö<³‘:òã*%‘¬¹As8NíœL3ÅPäòÐ-³w¬[àHíußd„–Rü«w²'ú¡ò[ 3»·`7aº‡óÊöŒ"²½ü;ä²8',fy QÔ[ÞŽWö­>~D£syCFß­ó1‰º§ÓÙ:“³­x¨ž?Àp3Ë<­V«R©œ8`kk+t¸E(óÌF"_UžZåã­ "šœMªÄº0/‘ÄK[¯ôÏé^-,¹8Ê×…ô§dDé¡~é=¶ L®, ÛõüÝ™0KIêˆÒ†O’‘Ç—*)Ÿžze[¢¤yФž[*×–Ì$"²÷(ëdîTº»ðt¸ÜmpŸ9ÀðÄp't³jllô÷÷W*•III¸8À°VQQ±nÝºŠŠ ¡ƒô à ûï[¶MóW'ÅCuÚ%SeW–êÛNÿ¦5ŠÅNNn2\ªŽˆFÄ{ ÃÝèjÍûùçŸ,Xµ~ýz¡³À@alž™‰å­©“õ¬ñˆHâè6Éñ:aŒ¢2¯²²òñÇã7žþy¡³À @§Mósó˜*t¸±ÑRæ/]º433ó‰'ž: ”yÃz6 QqA…¼¼¼eË–íÛ·5ÀH‚N›}ùe^ZZÚºuë¾þúë‡~Xè,0˜ÐšЧÞióÿøÇûï¿øðá)S¦Ê<€>Ø2ã¸èèèÒÒÒo¿ývüøñBÇ€Á‡N›}™e˲/¼ðÂÉ“'ËÊÊ„ŽC­y}eÞ¥K—6nܨÓé8 ‘àb½#Ê<€>´)X´Zíc=ÖÚÚúé§Ÿ¢ÆÙÐi O#ªÌkiiQ*•žžžÖÖÖBÇ€¡…Ö<€>œ2ïÌ™3óæÍ{ì±Ç¶mÛ&t0”y}!eÞÉ“'zè¡ààà×^{Mè,0´Î;7iÒ$''§™3gž={ÖÞÞÞÎÎÎÛÛ[è\–b$LÁrìØ1__ߘ˜˜µk× †Ü¸qãD"Q[[·££ÃÊÊjúô馰þ5O£ÑÌ›7oÓ¦M¨ñF¿üå/cÆŒ1ݵ³³{ùå—Ì`QŽã„Îpëþýï/Z´hÛ¶mBgó9þüøñã ×ÅÅ¥©©IØH7Ä0ÃûûvÐàd?5.†q§ÍC‡=õÔS|ðÁ¢E‹„ÎfåààðøãïÛ·ã8›_|QèD7Ʋ¬Ð,Çq[·nåo¿ýöÛDdee%h(€‘f¸žqüꫯ‚‚‚rss•J¥ÐY@ß|óÍ“O>yá‰D¢Ñh¦M›&t"è—œœœàà`Žã†!¢ŽŽŽ={öŒ¤NhÍÁ ËŸ¢ÂÂÂ+Väççûøø„ÁqÜ„ šššî¹çž£G úëâÅ‹ÎÎΦ·D$‘HZ[[¥R©€©E]]ݱcLjèñÇß¿?MŸ>' @Ã¯Óæ_|ºÿþûï¿_è, †aÖ¬Y³eË–5kÖn˜1cž|òÉO>ù„?ÉheeõÌ3ÏŒ€ˆ¦OŸ.•JmllÆŽ»lÙ2Žã´Zíp<— #À0›ió³Ï> ýâ‹/Pã@DDÄ¥K—‚ƒƒ…7gÍš5cÇŽåoÛÙÙ˜B}íÚµF£ñüùó.\8þü¥K—FÌS€ag8uÚ,((X½zuaa!®ƒ 0|qçêêzöìY"š0a¯¿þ*t¢ÁqôèÑ?üáíííü]©TZQQ!—Ë…M£Ó°iÍûôÓOW¯^ýå—_¢ÆÖ† ³±±‘H$úÓŸ„Ž3hfÍš5qâDÓ]777Ôx ”áQæíÝ»7""⫯¾ºï¾û„εjÕ*†aºººV®\)t–ÁôÒK/ÙÙÙ‘ÝÚµk…Ž£×0è´™——÷ÒK/8p@¡PÇäÉ“mmmúé'¡ƒ ¦––wwwƒÁ`ccsúôiggg¡À(eé­y{öìY»ví×_`$Q«Õÿþ÷¿…N1Èœyä"zä‘GP ,ºÌ;räÈ /¼ðå—_bxÀcoo/“É„N1øÖ®]+‰Ðc„e¹6 T*Uyyùœ9s„ÎÐ/ƒ!33sÅŠ¶¶¶Bg€ÑËB˼åææÎŸ?_è,É%–yeeeÏ<óLAAÁ<`†Ýõ|,ðՀрa˜>oÜ‘Ðz«¨¨X²dÉž={†´Æëêêêuƒ/ðPæ€ øÒÎTàYYYõºÐ–Õš÷ý÷ß?úè£~øáÂ… ‡h|]ÇqÇq]]]]]]ü þu0U}æÄ—s ÃXYYñÿò7x„&>¸Ôš÷ã?úûû§¥¥ u×uYgggggg¯b7Dz1Õr= lþkÖ™fÚäô ƒ™ô‡Á`à›òøcW~ü‘С`Ø0w™WRRòòË/—””ÜyçfÞ5¯ç=–eÉðûLÇ«¨îà˜u –Ÿ~úiÙ²e{÷î5k–9÷Ëã?!|¿MÓ¬›æpCüÁ*ÔjºN:@?™¯Ìkmm]´hQbbâÃ?l¶öbjì6]-]¨$¿ƒŸWÂtì*tfÌTæƧŸ~ú™gžY±b…yöØS¯êÎTã¡ÌËĬö:|E½ýd¦2ïOúÓ¸qã̳;€QËS°lݺõÈ‘#‡¶²òjì£Á—y………‰‰‰GŽ;vìPï †¶Ìûá‡BBB¾øâ‹;î¸cHw¼!ìEÙÒÒòÄO¼÷Þ{sæÌº½@OCUæq÷üóÏ?óÌ3C´ ¸ÖP•y¯¿þú¹sç^ýõ!Ú>ôiHÆæÒÌßד“Ðã¿Ùª¼Mž Ã0žÑi%|)X_’À0 Ãø†§Ôêú^¢«/y%€\@JQwSaá´OOOÏ-)[£Óؾ·ßƒ–”w{{Lõðððš³8|’òµíDµ»¢£wiø5jwEGïªí3\Ï M‘ÒÒÒ²råʼ¼~Dª•ñáì—×l?\Þ#œ=•~·¯dª/œù÷ƈÒàŒdG¢ãgK’ôÏm%"¢Küm}Õ5–`Ž/€ë´_É5kÖ,_¾ü¡‡¬ À`Ð’½çsÁQ>›¾Úä¡;´W­X³@N¤6µ}²)]™Z¹n±ÑœÊÔBïí¥mAsˆˆHl?iN\SꔘŒg{/!±²0¿ÒûQ¹£¨ù’'Q5ûêC ËÍX·PDÔZnpòÙ'îsûárÇ+ÙdDéÑå "µZMDΧu$'rV˜_CÌß6¯É×58½+sss«««7oÞ<([€Á¤¥»ýž&uä‘¶¶oßORE/p·#""ý/5•Fxó xG䓳-ÉfnH Kôv3Ò¥[ë/ŠD×.!ºÔZê*eÄbWE(‘½˜tGö•*ûÜaÇ™ënÿ*¤HÕVWWWWs×X–Zç_zúªYXšÏ”Q©†üUÆ¡Ìkjjz饗²²²$ÉÀ·ƒ¬Å uœª¤Ío¼±)ŸV.š*ºd "‰íˆ¢òëŒÆvm{{SMyáÿ{DªküÌf£Q[§.Kõ<¶|^Rý¹k–œüÊgyÜòBµ¶ãÚ+•¤5¯aíî IDAT’t’'©Ïómn$3ázÛ—]?¦ÛìÙJ¢gtDD¾½Nwì r–{MªLÉ p}ƒPæ½øâ‹aaa³gÏø¦`Œ$Y¸&ª4!A­HžëBÝ%’hÚ¢0JJú¤¡]"3žHáãŸ}‚=‘?cšëþš*Ÿ»ð1"ê,,ÌÂk<ø]"G·^‹]Üo°¤Ç£D™ˆX£z¹*F›úì¤ÚåIa9jÙµkÞD(™‹Kïeצ€>Ýz™WZZúÝwß½ÿþûƒ˜†)G¯ êû?+<|¤VšSv"h.ºUæË<£ÑøÒK/%''K¥ÒÁ Ô›Ü7\î+t ¸Õ™6ß{ゥS§ªTªÁMt+­yZ­öÿøGqqñ §€º•Ö¼ÄÄÄE‹Íš5kÐÓÀÝtkÞ™3gRSSøá‡¡HtÓ­yo¿ýöòåË'L˜0i`€n®5¯¥¥åŸÿü§F£¢40@7ך—’’²lÙ2ww÷!Jt­yéé饥¥C—è&ZóòòòfÍšåáá1ti`€n¢ÌÛ¾}{ddäÐE€ëo™W__ìØ1ÿ!MÔß2/''ç¹çž³¶¶Ò40@ý‚å£>ÊÎÎÒ(0pýjÍ«¯¯?w·÷P§€êW™·ÿþÇ|¨£ÀÀõ«Ì+**zòÉ'‡: \¿Ê¼êêêûî»o¨£ †a†1ݰêAèh}èyÈj:ˆåinèÆuιsçΟ??iÒ$3¤j¦zˆ¬­­Qæ€e²²²2ÍrênÖëµZ­P(Ìe¨ñžçED¢þN4 `N"‘¨gkÚ'à¦Ü¸ÎÑh4r¹Ü Q̆/𬭭ù2gGÀÒ˜ŽWÑWnÁè*óøÓ!ÖÖÖÖÖÖ666666ÙÙÙçÏŸ×ét/^ÔëõƒeÙÎÎNŽã„ #Ã0|9gkk+‘HÆŒ#“ÉøƒUþÀÕ4B666¦qz|ã߇“oÇCS S4 _}õÕúõë…ÎÐÛ¸qㄎ`¡zŽ-êYìõš‚ý6¡ÿn\æyxxüðÃ=ôÒ )þü‡µµ5õ¸T:_æñƒô8Žã ÚPÖÀè”››k4óóóãââp4–ÆÞÞ^èŠÿÆ6ͳÂO»ÂWw¦‹¤ó‡¯hЃ~ºq™÷_ÿõ_?ýô“¢ 5†aøÁxÔ£qÿðð_ÝæÖ<£ÑxàÀ___‰D"t°ÿû¿ÿëââ2eÊ¡ƒ@¿´´´9r„ˆºººªªªæÏŸ/t"€«Œ;VèÊÔ!ÓTÑ™ú õ\"tLNúUæ•••™!ŠðP{~xLÍw¦ênÔÖxDôý÷߇††fdd<óÌ3Bg‹ðì³ÏÞu×]ß}÷ÐA _òóóù .\øðÃýýý…Np©T*tËej¬3Ut¦ÏT¢)úoµæñø …žÃQãQvv6Ã0Û¶m : O­V3 S__òäÉéÓ§ n,--­½½¿}àÀŽŽ™L&l$ ÇqÜš5k^yå•;î¸Cè,£‚­­­Ð,Z¯ZÎÔ|‡v<¸7.ó¦M›ÖÖÖö믿Þ~ûífd=?6=K»Ñ\æ±,»wï^Žã~øá‡“'OÞu×]B'íÙ³§££ƒˆ¶mÛöî»ï nàûï¿ojj2Ý‹Å{÷î]µj•€‘,ßwß}÷þûïOž<ùoû›ÐYF…3q7ÀéÙX‡†; ¦?…ÍêÕ«gΜ‰yÛF¶Ï?ÿ<((H§Ó‰Åâ—_~ù­·Þ:ìöÛo?sæ I¥Ò³gÏÚÙÙ ~OXXØûï¿ßÙÙiZ¢P(ª««Œdù–-[¶{÷nww÷S§N eäãGÈ nŒa˜Gyä›o¾: H¿š€Ÿ}öÙ={ö uÖîÝ»%‰‹‹Ë¸qã>ýôS–e…NBúþûïu:ÛÊÊ*''GØëÙéîèÑ£¿üò‹Yv®;´'‰%%%Õ\qr”û¹S:¢6MA¸/Ã0LÈ+»N³¤¯Í ñ ÙôJ¸'ãé²EÓFDº¢-ឌgÀ’ÈR¢)Ìõe0³:Àp+?oK—.}衇V¯^Ý«7 ºÏ¶$Pìº%sär//¹Üë™dRGj½#@I‘3ô¤o(ŠQ;KHvÇÝDÙi{ªXb5y;16oB™#[ggçˆiÊ;tèÁ`pppÉd2™ÌÁÁÁ`0˜k¾MÙÞ RǸ3ž!Ñ[Zï[¹ãµ%2]U¨B•¯NX¼½ÊhlÉ.ÍŽ+w^¯(ÍŽÙVXßPç“î¶d •š%'ôËæÍ›÷îÝ+t ¨›ì²½”R“g›ÈF½_t&/»øˆ»ßdi$¿\eKä²°&?~†Ê;i9)ˆÈö–þ``øB™7?~Ä”.Cm$•y‹-úî»ï:::>üðË/®X±¢³³ó±Ç3ÏÞ}7V”ÏHß¶}gvRLvR )Îä)ìÆ:•îü×9¥-‘¢ì“׿:jJâ²m:\˜DŸ¶ÑMÿhµÔÇßê^m°"­——dµo7éDNnŽ—{gz,ÞhÔF4éÈÉÍ=6G!–eùAùBgþ:zô¨Ð†‘Tæ‘•••éõz³xDD¤¯Èû¸ÞiQVɺ,ÒmRùÇýrq)©;þŸÿܾ*9Qo?KJLjœÇˆˆôW®XHJW~x ‘½Ãï: ‚[?t³±±ùôÓO[[[—,Y²ì fÁˆd.nWj¼ËPã^˜…F0[[Û?þX背eY³÷²1Öl]î7-¥¨¢¶öGõÏ¥DöŽã‰(ØÿéÐàç}Ûtíye[ùÃ**x¯¨ªbo¾Ú¼‰F¼¡·µµýâ‹/~ûí7±XÜÖÖ6X™Àr Ì³Dúª¦'Ïè´’ëMŠ¥IV*¶T‘^Â0©š fÍiñÄbñO3føÄd+R‹“ï½{IeNlvÄ×ÖÝ=Ž5þBd0û\gdÓiÒ®.ŠCvUœî{ÕËÅðM*Ähôæ :Hé‰*r›»µ„Ó¶¶65µ¶«Ã}'‘WÐk\»¶©©µËò$‘ÉÃ9nŸ—ŒH"Ïâ¸}á^"G¯­ÕÆÖÖÖvnß>ŽÛîeæØÐ§×_}Ïž=B§€œñ6o½õÖßÿþ÷¹sç~ùå—ƒ²A §kknnnÖ Ï#€¾°mÍÍÍÍÍmz‹è|«¯/)ªíý⎸×|Ø@™g™´DSä³=<är¹×âð72””sðg"j8”À0 Ãø†lÑ´õøDúé“RËÔ5jµº²8ÙG½ÜgMß%ÜUÅð/-âñ¦ 8àPæèèââ(éùÇ&‘¹¸8þn·‘£ãï¯æ6oÞ¼™3g jЦU ),,\µjÕÿ÷ †ÁÚ¬¥a›«60öN®®®®öR&dKÑõ:Jé4)Œgʯ-XµEÁÄ—_'J[Õ¡ª6–H_¥d˜äª[ì4««/ aÄN®®®®®NRqxJ‰Žˆôš†IÑ í¥»û’õÄžÎÛ"æç?C¾¥ ™%ºîk®Ë `|Sz<\_À0i¾v×UgîßÌ빇~@™g™ì‰ôçZ‰ÕëõúÓU{¶–Ò¢ûïÒ×îš{ºèáiþê°dõÿ„L–±ÇJ3¼U~—n«ÉzÚ¨%²¥¡½Rí5½ÇØ¢8÷À/bs3b7Mº£r5”q¸ÎkînÐö~¼–È`d¤#Rä–ï¾ÏŒÆKUûâ—ûÏЖ̹•WPæY(QÌ<÷Ó}UâÞ]~LI$UNr¸¯„hã7eyNó¾ªR˜Ò‚onÕ³NÄRû‘½_)ïr•T¤<îÙ’S^ãÕqpÆ<¿jCeI˜Ð1C@@€L†ï;€Ñn'IwuuÍËËÛ¸qã¢E‹6nÜØÕÕ5¸ÛZû¯Õ¤˜3ÉE"s”/ÞP–v‡ ‘¾~S@@^½Žˆ¿RP¯'±-©wÇG‡0 ÃøF—4èˆHºbSˆ'Ã0 ’§áÇ7·láO'{¾’yHOT›÷Jø–Ì-!L@J•öõ÷¿\"}í¦ðWv奸2 Ãø¦Õ[¿éQo"òž­iÓý|øp£–¥¾úkÕæ½²)mK¸/Ã0žá)õWõSb÷¿á¯¦øÆ´ur7G™ÌÅkñuFXã‘£:"{¢ÝïÇóa_ÙÕÝhV[Àg`<^©8}í³õ[B6¥láYÅ÷{ÒÕ…û2 ħ\Õ—ì ÝÏ »-nÉÜ»=¼\“ŸQbek{M…¥×Õ•Ç+ˆ(¾‘ãø­©sË‹3”DÊäÊOG›ªìµÄôD+ƒ‰ˆÅå…QD”S×n¬Ë!¢¨œ²ººÊä`"UF{ŸÛ×òi)µ°¬05Œˆ2jÚ¹¦b‘2>G­.‹U)›8®2i¾<±çÞù—78168>¿î¯ùµáÛ+•DÉݯ¼"9¿¸¬¸¸¸0'JI¤Lnâ8ŽÓe,¦ùI}=_¸¾'žx¢  @èp5þ¯]­íµ47Œ(¾¼ûž¶\A”Q£íþ µWÎ'Jªl½f[#ÿmœSy¢ñĉºººMZŽëþ®Ž/ï~AÚkR‰Âêtݯ’NýÑüJ±O÷W´‰"*µX{uÕÝê`¢÷ÔJÚܨ+;N.oÒV&_}X¡,×6%Eà8ŽãÊâDTØÔ–|u˲2¹òòccOpÇi“‰(±¼2YÕë@%yTþÝ (::ú­·Þ: ÔPÊ?~|~~þÇrÿý÷¿ñÆwÝu×íËŒ$KÞmÊ÷Úš´=.0)Žˆˆ‚‹OìðODÔ}]lºm Š:‘µnÑœ¬ò<{Ÿ/ÔlùØŠíÜÇ~¢~ô—‰¬f]LilacÐ7š3=¿¾¥Õ¨'Ò’2U›.#ª:ä,¿<<$¾xÇb¹ ÉS’·go/üµz½RIûÌud«ˆÈ–èÇ‚>úky´œ“·a‰ˆèÍÄ­¡WÏ:`KÔ¢ï{æ=Q|ñ×+|]ˆµS…&=ßNS¼òóË•‹çHõm÷ÍVÒNm;]»}1QlacøB7b]TéÚK횃)jŠoÜäF4½ ?a²ê»†õ¯yy^¯I¦5‘ ¥DÙqŠ°Â½o.œ*ëû5ŸÔGf{¢ËÏO¹1ZADjµšˆèø©6ÖÅqìŠ|nEÞgè6-—±W‡dö¢0R…þk±%„©)Jé!kcÝÒcæ$·k&úp°ëþüíè¿H1ÛuøLTÃOµî5Îh4ÿ6Káwû½­æ8^»æ Oµªûq{%ççP«Ó䦜/jη-¥ªÛÃåW^_‡œ°˜åIGêߘ4µé›85©2æ»XŸ™BäœÚ^nZO§9BDD ¯f>Ÿµb²­’”±×º}Ü:Ò¤("¨\»ýíÍïÁ7nœÐ)` ¹Óf/Ï=÷ÜÏ?ÿ|ÿý÷ÿሉ‰¹xñâînè±mm’ÅᯕTsíÚ&uYN°"Û/ôƒËý|ºìM«+¦8ñ7Äâ)DD’§Ó3”é¡Ó\¥ŒxþGß7‹8c#ÑWþGL²xcÚ /£ g÷ú]Ó’òÑÙ.DDä¨\¥$"bDd¼rø}¡ÏþZF"Ål>™XâÜëùZˆ$W Àk«-HÉ<¤'Ò9Œ“ð;âÁ‰Dâ_KìF,ušYJζ"¢>·¯%šà.#"¹û+øÒKFçÎ0 ÃH'«ˆèDK•ƒÈÑc]ZIkYrXbFâ”tÿ§3Ú®ÿš÷¾À’î\>)˜Âå(++ª««««9ÎØZFIÙƒ«}Ü"”y–ÉžÈVÜ»(™´øõœ(RͰg{ÿç\uÜ$2 ±O$"ñиµd½ Ù”¥JŠÜ¸«AOÔV•˜MKîëõÅÛa¾t7M°©V¥Ó‰"UË#÷©§„f¤­ó‹·G>àë¾KGäñǧDùÔ¬Ž#ŠŠPvÿ6•nï^ÏÓ7óò,_ ¥";ô¿«tÆk ºÑû÷*¨%K–,X°@è0PC[æ‘­­mllìÑ£GÏž={÷Ýwoݺu2ê*\íw5°D$‘¹Èçý=ZE-ÖHDtþò™õ+3ƒ¨Mmgb-‘^ë07ßhl=QS˜±(!Âo׉L¿cì¡Ì”‚ÚëM˜Yzª•ß¾¾r_©éülc6‘ót*mº<†Êxé8‘+¢úrŠkÎâJ'-"udVý•%úâ¨"?4-¸ª­ ö“?G$ÉÊêšÚ9®1?ŠZ.ϧÚçö/¿üJFC#)’›ŒF­¶½½õDqaÙ2Å5?èzMÃìj éÛ{ox+ƒÔ%ǽÎkN2ïeéÎ#¦±4ºÿü›ÈÙæšC‘£â%µœÇè²[„2ÏI¼öq\¸üÚ£bÇ ­ÕÚ¦Æ'µÆ’%rG"’G–ª7xñW*‹”5XË`o×»bp\•]œ1YÊ0NÞIªÄº¿Î½º¶cÁ{‚Mµ*òx·©<>XIù1 WqtA÷ï…³ýô)ãÇï>}âX""—9k””}ðpÅweDÊçæ˜:`8O?eüøñîŠéc/¿#Ñof'*òC>9kÍî,Çq]=tvv²0tvvvvvö|ï8Žú¯ `h™éGl„ ;wîT«Õñññ ùË_^zé¥1cƘgïƒF6!–hyh‚Gv”ÂUÜÖpdÛÖ|šò¬Tê0¨òûŸõsf~ZJ@DdK—·xë÷’”¥¶CqéïâiºŒÊ}+¼.Z  ²›ö¼ŠB7f¨>C{u£ IDAT^c÷cö¼ÐÈduè5]‰ˆì‰_Ënz7ب޻µ”–¼zÏ•ÖköšÎ¯rþZ_ýÎó-X[H þÓBnW'¾8]Æ~“±>0›â‹IèÔµk DtÇ“\ètŪ$R&÷ÿ"vwÌR’zçÁšeKä²C)‘~‘¤nŸÛ{%‰óÝD‰»=ô5TüëCR,~ûu^s"ûÉž¤ŽˆË¼7>Ø›m([çCŠÄ;º{[j«5vd4—¦…–Rü«w±å™oçs¾×›¼ú€)X†™‹º¹õ$“‡s\øµËEns³¸ö·O·Iêêæ(""’guùEp\„YSÞ$¡¦Ze›5ûvD¼ý&Ýñu{yLÂû‡6l""zþ­´S{®è¸`M.÷I' Îñ4u&U=Ÿ–¶Â´’NCDd°›¾.#9Æ;4’Hå;¨q?«\¯¡/ü~…S6466ŠD¢ñãÇ dp0 Óó†éjKVVVü[fe5äm‚0ë¹J…B‘——÷ã?nÚ´iòäÉÑÑÑQQQvvvæÌ00“âN·,öóvë^ ŠWgID;#ÐGA¤TRÎTI3’ˆˆ•SEŽËèÍ„)Â2ž–ßü;WŸÉÒH"RÅç‡Êe'J¯ì¯çÙgå±PWq()cóÿêëFl»‚–+LmÊžHd+OZüzNÔ|Õ þt¨’ï¯Õó¢×ö~¹-lªÌyÑ{¹"»ûh!±°fƒ¯ éϸ_ybw""Ñô+•¤š,N ¢°Ø0Jˆ\šòpÏ¡÷¦¾a=K¶Dz"ß¿&Vú+\ù…•Mr izÇq[«ÎÉSÌ›Ü}W‘£~VFŽ}¿æD“o­Ì ïPŸ¤P~õXõ¿6¸éŶDêå>¦cEb¾z½¯Ñ…ï?ˆÙî¿eÞMAkŒh77¡3Ü ~ªÕµ:··³$’Nšä&"]Z‘Z¹th§Ze[*Cƒcco“NöX¾oçšä` 2 ÷©ÂæN’L}d©‚ÒÕD±¡óùH"Ê/Þ’fp "2d÷ɉˆ —Œ¯ÐTUdDþà†L|ã©)ˆ:;;{Þ¥TæmÛ¶ÍÁÁ!**êÆ«¦2ÏÊÊÊÊÊŠaþÂ’¦»]]]¨ô`Db„úVúé§Ÿ6oÞ\TTôüóϯ]»vÊ”)‚ĸ%lÛéF­QlgïäâxeĹ¾­MG"Ç«O£³ºæ6½Dæ"“\YÐØzIlçäæ"»òÐfIeשºõU¾Ò¿¼Ù^2³½YG’»`õz’H®z”®ùtë%rrw»ÞÆúÜA[sk»Q,su¹Á£X]s“^âä"“«Ó±R™äfNèÛš[Y’9þî^X½fOìû´ò yµú~͉Hßvú7­‘H<¾é`lÞ¼Y¯×oÞ¼Yè p™¾ÊWê Ö®»ªã®>/\8±œÛ8‡ˆHWáiï]£U|¹x…á-õ:RJ½*[#½ú˜¦å¦ö]´é9ÿ8¾ Så×}¬¼ô±½"´çÉ•­ë¼‰t™!ö¡ÙÁ•Ú,/]¾Ûc=eòÉdÛ;©jm¸\¦¯Ï“N T¥Vî ÷""Mfˆ"TW©ÝçemÓ|ÇÿË÷ý›>}:ÕÖÖò5ÞÌ™39Ž;zô(¿þ¬Y³ˆhøÞÝ¿dd¤­­­E¥È]++«{ˆjkkùˆ¬­­­­­ùf=þ_Y+óx'Ož|÷ÝwwîÜùðÃGFF*•JÃX.]cïS¦åæZÀ¯°m ä>ÕÑ‚‡ÅŒ&o½õÖéÓ§ßzë-¡ƒ{(sÏÁA“®údè››uD"G|`F¾Ì뮦®h(Ÿ¬*ϯù×b*zåaÿßÜÖ–då –yDDlCAhšMÆk GÃ_]ÏÁxF£±³³ÓÊÊ sQ_nnnGµ¶¶‹ÅÖÖÖV—™ÚýFO]Üy牉‰§NzüñÇ×®]+—ËwîÜyáÂaSYé]Ź…S¥7^qd9NBg9ÐiS(:MÃ0 ãY¡#]}I´¯x^èòÉ‴’Z~…†C™¾ŒÔÕÕÕÕÕIÌø¦j "ÒW0LšæÊ…¾k3ß4‘&3œé)`“¦%]…/Ã0 “R52® ~[ŸWTß{™®­¹¹¹­­ÿÊ-—°S­Š&=þÏÿYp³_Óõõ½ß‘aÁ4¯ñX–ÕëõÆ_šÅ¿‰|Ñnu)t(€Af-ÔR©4,,ì‡~HJJÚ¿ÿĉCCCÿõ¯ Ëbˆ\|—,tCáB@™'Q|¶Â[Z»fšßÙ…Éa E|²w„ߌ4ŽØÚWç…Ú'6¶jµMu9±1oqI3‘–ÈÐã’zFƒ–ZøíýF[^SWSSSYžulX0)ƹÊD¢GJˆV­ ZFDlÉb WÐ5ª)*G]£V«ÕåÅî鑊ÿÞÏJ¦lÌÍõˆsÇ#Ê<áIäÛ+såIj*õwûFg6°D"'Ê“£ 1¡~> w'±otfó 6$#JŒ^­Z£&j<Õ8òNžMœéMù×M[+Ïדۊu+¦JhÂ,%©#í}ÃSvUÕ6ge¥…ÿ~Ox[{*-,(9t¨¤¤(í•¢¨% "¬QÈÔiÓh4vttðýý„·næÌ™ü›ØÑÑѳӦй™E—y<©TºtéÒüüü“'Oúûû¿ûî»ãÇ_¹råçŸ>j¿gõµ_Ĩ•ÉÉQ””ª¾|˜Æ6Wl ðd†ñ É«j®ÝAD1Þ¯äÕjQÿË%"b›«6…t¯³«â4éëóB·ìJ{…Ÿ“!¯¶ˆH_·%<¼ î‘¾$9:¾ Žß…rŠ\î!—Ëås|WlHVPù «ûùðáF-Û÷v¨­(%Ü“a|Ã7¥myeKA­Ù_*(”y–ÀÍkIVµ6Y©ˆÏH¦¤ÐÐVצsò^·5‹ãŒ­Mu…±¥I¡¯æÕ_®Bú¬`I‘ª­®®®®æ8®±,µ4οôôð’w-ǹQe±Iqéù *)ÃlÊÓ‘›ïƺâŒ0ûòÈåþÞ3&Û‹»—ýÎåÃócüÖ®ŽŽ‰HÈ'¢õfÈ}ì¡Ì] ½ß.}sssssÛH{- ßÔÃ×|y t(ž5ži–Tz0 ƒ2Ïdܸq«V­*..®­­õòòzóÍ7ÇÿÜsÏíÙ³g´MÎy$7”TkÂÖ¬TQ~ÞáÓDDÔçê§]^Y§ÎðÉô~­cÎcÁD¤J\2Û]{<ûjÏ5ĹzÇé–WÖÕ®¢å>î»juÆK-Ùé1ËwSqyY¢*?pi–ŽˆH{8=ý¸–ˆØ“%I¥Ç»¯²Þ¢?Ç«×ëuÍšÂ5M¹Mª?»;)I­mïs;[žñ,..ºç—ˆ˜„¢â5ü ÌœN“Æx¦èIL4%`ź7ã-ç5ó]íÚˆˆDŽ.S®ˆÏPRùÎ’XìNt¦éJ+Ý¥ó-äÜÇfÝfÏV83òÚódsW¼Æµ–EE¥æ¦†Å*2kõº¶f×y+ÒöUsFmcMyr˜".0²{nQõ=Š$[¢=‘AKŠäJ®»*ÖæÇ*"ç図{:¦Zµ¦i{VzO<ñ„йàÖUUUuttðÓlòК#Òp*óL&L˜°víÚo¾ùæØ±c ,ÈÌÌtss[¼xñ|ÐÜ|£^K#[›G±ë‘ˆf‡QBêW:"¦(¨x÷¯©òÉêØ`'Æ}¾Ÿ’”þþ^“dDÎr²ÑiŠHQžµÁkêÔ…ëR’”XpŒˆˆeŸ¼æ;gîºM©¤.9¦#’xås\¤×X¢±+ò¹ÒH/"²µ'uÌ<1#–J¥ö®Š˜|eÎ&þòè¶ÝÉ®ÞN³f[LiTaá ß9‹×½›Ö=Û /˜‚Epb"RG~\uŒHÖÜ ù"Ní,¡‹bˆâB·5ëYV¯«-ÚZJKî¿‹$ÓUa”àœ§ifY½¦`“OŒ:xõ#2""{R×~_[[«©­ÕÚôœw)©”3á*j–D_ͤՓÌF:åÁ%áÑJ¢¦ó¿¾çäjÿv‘Hææ1gÝë[‰JiÕ“‘ˆÊÏ›Îc°ß•Ò’îàï9Ûš.? óôò!:£5ësÁT«–Â4 ?<WSºLMy¦yh̓‘DzfÚ¼Y...«W¯^½zµV«ýüóÏ÷íÛ·nݺ{î¹ç‰'žX¼xñ¬Y³„8$š¿+È&"?ׄîi^1› D±.DD$‘¿–%'Ò}KÝSÆ]f Z~w÷0:©›‚Ÿ)Î@´j–#Q÷˜“ëÆ´¤ˆÍ/XëIF–eÉÉ}ª£„H¼ÇÆ{oGG4ەߟhâT„«U:hÍK$“¯*O­òñVMÎ&Ub]˜—Hâ¥Î­WúçÇt¯–\åëBDKÞ=‘|ir ¢{¦UbᎠ""[QÒ¼IÝPF×ÅË-uºÈ[%™2E™±K³à!"jÖÔ”­™pûøD%Å„f>Pü€;«kü|Ûf"Õ”ñ™ýEú„¤Ôe„¹‹~Û·4(ÇMÆ•VUjêÅd$ãéò¿¦SX®;‘y? ˜jÕRð5€©ÞûøãûÿX&Í^qå¾"8'=1hŽ[«ê«|¥IЖÌéñ>^ФʇÕíYÆ…·>‹ó¹æQš©ÂW­]×Ç56[_ oÖ…ª-2ojå6ôu’‰mÐTjígÊ'ɪ¶\çùXWW—éR ¦·uÐ÷ ¸á]æ™ØÛÛÆo¾ùæóÏ?òÉ'9Ž{â‰'T*Õܹs%’s,£?Ca©•k$#‰éøFoUÆÚÙDôc Kn"¢ÿÏÞýÇ5uÞýãM$ ‰ Ú;hÑ‚ºrØ`Ö­¶‰ÖB] ³:;»RW`nÝwõÆMÚÁ&ƒþ€ðhmÀ»F'°µ`ocÛAûi`7Þu0¾ÖÂ*T脵d$5GIð=ß?NˆÂ/r=˜\纮sNÈuÞçºÎuqmG^;µf÷Óƒ7e4Y8k÷tËŸŒñ{°àÞ…ÁŠà ȇcm€Oÿj¼W¾1á®±CL%$Ìó&¾ Z‘RÌþðg/øÓ·Ú¶„8/¯"¶ìçí?ëúÚÆŠÅþþ ©ëGN¼ûû£_wöðóèO¿ã¿ã˜§bÄ>¸snÂD$Ê;J‡@. ­ –ˆ~^ªûgBÒÚÅIÎTJ]ýÁ Yq¬Y¯W‡ú§ hë;·‡HÖG”$Ñ%Î Ô™eÙ[¼ÓdöOµ }g^7³=8çT«™yë[¾ÿÄ1`ä)LµâöòWÝŸZ› ÓÜ1S­N÷·\!ÁMDÚ:Ó£we͵Åñ+wEØO w“Eì;ô½‹W8Ü¿>_³©±6ÀbOM O5ÉÂõz “WM¯LÍ3ò{¢»¿·jùòåEEE7}* bº˜–ƒ6G ‹üqFsáÂ…>ø`Ñ¢E999±±±¦¥eúOb>W MÊö¨ˆˆ¨¨ˆˆ¨M»3QšwÒ±èAúÃï4qpœ:ø|ÒÞ?CÄ¡=—n<£#]ô Ò×O4q@ש£©µØ¥\:´€ãË#Ùù5_:®þH¾¶æË›¨);oIœ©ùGÛGÇ©¢µ¹XrÇÄÚ3 ó¼†Li¾TŠðÌ”HñBsë!o¡KäŠàà`…[Œç$ vÅxÃr4¥P¾©¦;hIiÈž¾ÛT¦N¯°°ü±”""ÅŽ‚»¥»½½½³ÛÂò5;úûR¤a›jXK{{{{{{·Oq¾/ÝqÂ}$âÀvafNñí»–îG¦Zõ6÷HOèÍÿè>õêåaQªÝ¿Îôït´”gd”;§j)ÏÈ(o CísTEQ*÷yËæ®ÙÔÚjŠãúW6ja@¼}8[˜am_y〒m9qq•mLÿëÄ“m³¦9ºœ“´Q‰•MæþZ¡†œùd¾óÉÏŒ#§„[ §ŠU®JZáh«LÌ(®<’AQqgþy±ñìEÀQŸ’‘_´/.’¢¨ÄœJ3pK³ÇY˜øàÒ¥KÇþùçï»ï¾ûî»/99ùøñã—.]òv½nFkY2ÞÊÞxÇfÔ¨h··Wå¹N«ÆÐÎó¼Q›€Î3š ‹È3ò<ߪÏv¥IÖÖ³-<ϼù"òŒŽ†÷›>dáCäw2E¼ÿŽ6“ˆÅbžç9މfÄÏÅÔ!š{Odä=7±á}÷Ýçp8Æz¾Dó—EFÞD)SÍÒ-oéûÝÛß})i€ùMZüøÏŒÆDˆç?p× ešŠe }ösÉÂT«ÿñVÒ%¶Y÷¶ÅÂï—»¦Zý]nÁÿ‚دªUgGŸjuäoYTTÔùóç…®]»`éÒ¥2™lR zLë‚nŒRLÐÖÓR˜°€îi)îÝ èšÿ°%L‚¯hß*9Xu>>ֵ݂Ìs±,xEVw³úbàd>Þ¡ ç§N*ü×%»ðð½5\ÿq ºîø5r¬ÎÑÎ3IÌ`¥Ø/hSæqÓ†‹ E¸0¶>ø …Ø7\µ»Ó´¢G†óo@©;˜¢’¯ÕiüþdíÚÐ}B€ËMMκ؀ôª‚-+€'õç«ÿÌíß½N‰ÎØØ¨`iã Ùã¤Àî"Í[¥y'Ï?;´þ»£ÆùWÉ“®<âN7=b› –žž^UUe6›÷ïßoµZŸ}öÙÀÀÀíÛ·ÿîw¿ëîîövoDàŒñœoH$ƒp‘T®b¼É®õ“øu¡þ9GÊóS¢Õ%Ê‚„¨"¦.2ÙæôÂó~ò“Ÿøøø (ê©§žš7oÞ$8y\lÏôVU›ƒë:õfªÉÙÏ&b~ÄÌÁÜøn’;×/R^íß„kׇ‡þ±!kbžX ŒîøÎ_ Ï~îs2;©v˜T,º_ M,5ɃÃb6®wu#Ž¥†Ÿ½º^gñUD©žz4€ÏêéÈÍ8Ùf嘖—iõÞÏëë:>2˜Ò jºœµE›‘‹ô0)naö¸›B~-‰;é]€¢¨åË—/_¾|ß¾}v»½®®îã?þéOúÅ_<öØcëׯ߰a÷¾õ-oWs‰D"Ž#‹ä0oz!aÞØMé0Ï9Õê§F[q”Ô9ÕªÔÃT«G]Š‚Çöl¢£)Å—.ò&sªÕçž{.77ÀܹswíÚ5‰%Ý.ñññ===£§»Aæ7dŽÖ¥Ó•iêPß½Â,e®À†6%Š“$hêvEÉMdsû¯×$?Ò%¿¥u¯È¬høˆ…â `ÀÕ($£"3|ëJßT@©„+倡2±8ä™á[£©$ “u›#¤¿1Õ[`Pg­  «’$ÚPgUdžS‡ún|a.~6à D¸Š.]T H7þi“X¾+Á”ûˆ±T Tïê³CÕ´Ð ¬­ß!µ7 ­ÿ°¿üå/Ÿ|òÉ86 ˆé‰"ƒ’ÇÂl6 †?þø£>º~ýúúõëׯ_ÿÄOx»jìòåË÷Þ{¯kt AˆŠŠúïÿþ﨨(oW„Š¢®_¿N"½±xõÕW»ºº^}õUoWÄŽé2ÿ ð[B‡É'ï–,gm1]è…øÞ¥á é$Þù}衇Μ9ðõ×_O£/'ÏóW¯^íëë³Ûí—/_¶ÙlV«µ§§'55uœaÞ08Æl½1qš‹ÕlæDÒž¢·š»l½ùÊÇvÖV+Q€|”YJ8ÆÜiéûù+\k±Œµ†Ž®Ž¯Y±ß=Š×[ŒÕì€døB™b•ìím¦v.î¶r7¾æ‡C4pfޱºÏw‹:::>ùä“ øûûÏŸ?Þ¼y~~~‰D,OÝû>1~¤7oLžyæ™gžyÞoFô IDATÀùóç?þøãÿùŸÿùÙÏ~¶dÉ’ 6<þøãkÖ¬F¤Lwb±˜õ8²„˜ÁÈ,ÓËK/½4.£½k*O!+’*¢¢Æ7£Œà¿þë¿233çÏŸ?¶bäaQ“> €Ý»w''''''ß_Λ˜‚Å3‘Ôãíbùh7‘åŠq6‰|Lá‘H,òÖ˜j(Q é@–ÊGY¸³¯µ1½"‘T103‰dÈJ R¹B:)_TÒÛAÜÁȳyã¶téÒŸüä'Ç·X,o¼ñ†¯¯ï‹/¾x÷ÝwÇÄļöÚkSüiþQ‘A›ÄPdÐæôòâ‹/z» ÓÆ”´y³>,¬^0¥lݺÕn·?ÿüóÞ®1uøn¬Ó6-»ý?ôÐC·¿P‚¸ý¦è]ÌiaÖ¬Y«W¯^½zõK/½téÒ¥ššš>úè7Þèííæð|üñǽ]Íñ™={v{{»·kAL-$Ì#îTwd˜75wÊÇLJt›‰BÖl ñv%îŒîe‚ðˆôæMŒùóçÿà?xóÍ7ÛÚÚ>ùä“U«V?~|Ù²eßýîw÷ìÙc0®^½:z.SâE‹¼]bj!aq§Z·n]llìè馕©æÝaâãã')gã #j&Û_þòoW næM¼ûï¿?55õÝwßíééyã7æÎûÒK/Ý}÷Ý›7o>|øð´_˜yH˜GÜ©„Þ®Å#aÞ´e=’é+ó}­Á:A^Ö*©üFO¹9•¥ñøÑx³šœµñT£•¸1¡H˜7‰fÏž½zõê_|ñÔ©S.\øÁ~ðá‡.]ºô¡‡ÊÎÎnllôv bLÈ,10ï6˜°)XÜqO”˜² í{VLØ\#}ÃÍ*Y²¿¢Bµp”‰7Ç”Õĸ½6ú‚7Â<2–˜¸ƒ‘0î«Å^Ÿ4r¹<>>þ÷¿ÿ½ÙlÎÍÍýæ›ožyæ™{ï½799Y¯×_¹reòŠ&ˆ[$‘HÈW” ¦ Žã„E5ˆÉ3 ±SùBšÈÊH;ù÷Ïòó‹‹â(ª¨ÑÊ™s#)Š¢"˺8Ú*SŠÊ‹3(ŠR%æ×4œÌPQE¥7 ”|ÇUGu~JF~Ѿ¸HŠ¢s*Í8æóO>é´q޶ÊÄ”üòâ}EQT\e‹Ð_g­.J‰¤(UJNqþ¾ü“-ýY ¬qKuŠŠ¢(*.¥¨ÉÊ9Z*ã"3ú{"™ÊŒ¸Œò€k¬ÌjŸQ\ÃàÚòãrŠò…}Ê8ÒÈqm9¢D¯ÈhbÐVSGQE©RŠZL†‡zÈÛß a¹_”NÊÎ3É ‚åúõëƒ^N·çjÍš5kÖ¬ùíoÛÚÚúþûïÄÇǯY³æÉ'ŸÜ¸qãÂ… oCbì|||®\¹B¦`%ˆiAøS%°‚çyÎ͵k×®]»&\ŽOtQ¾>‡ÂÍþÝ‘²+‡KKõ¥¥ÉyºGY³£sÕyÆÖw»?x)vešmO±=¥%i¥ê¼ººŠ’µ[ו"SWeØufÝÖ•«µïs­F0oý¯ ÏÞEuœ.)Ô#½¢¾9³yÛÊ­ëQw.cîÛ……±‰Y‹{JKö–*3 õuÍ]»uÛ1۹ݟå?»·Gg¨÷ÿÛauZ‰R³e3+·5ÈÍ5„Ç.È.3iý>a-ý˜£»!VjÚzØð³[B`=›S¨ße:ÖVùÓè­%}ý#óÎF¯[w¦ÛÙÓ¥z}©^[UßQ›¹Ò¼1]“UûVÞþÍ ©Æ§×¥®¬¨×|÷jqèÚð^{lËd\ª^¿~ýZ?×ù¥(ï¯&-L ãšfÖ¬Yƒ^ÄØyÿ }› ?Í®¾»AwM&á‡{L.]ºd0ªªª>üðÃûî»/..î?øAHˆ×' "ÈÏÏ·Ûídš~‚˜233sss½]‹;„kyt‡Ãqùòe†a¾ùæ‹Å’––f±X&¸0®I%N{…­‰âã|£—èÛ 63MÅ2ú`½íÜ )kQ¤ÿ[ñÆÿ‹=ãz³±H]ócöÄv×'¦UFËîÁ !2Å*Yjd_ ãdÆbõ¿uÛ×ÿÐ7:ÎhyNüŽŒ>Xg9·FGS±/]eìÎ)¤ï®ê,ˆQÜÉñþoÏíŽTÙ¦â8:5º“߯'}«õíì¼bñºÏtö;¾>™²X½ “¡4Ò¿z—±&% @cq\ôA•¥á‘$ßèª:Ä(ÀµÄ‰ÃUFËnú¢sßí *ÙÊ•Æâ¢|­-çþ!ŽŽ ™ð0ïÂ… µµµþþþr¹\&“Í›7Ï××wŠ,.„s”›Y³f¹^ƒL JŒÇÌêÍ¢8÷žq???oWj0«Õzîܹ_ýêWÞ®A ðÊ+¯x» AŒÉ믿îí*Üá|||&>SŽÀÚ1lÀ’%þ€> ~™ó:_ H¼)hU˜ÇÚ†Ï[¹Ä¹¼Ó=Ë"ß}Á¬ïÿ¤Øù X°`€åB‘¢…!4³”YAT–ëÿí=öäiAÿî3ÇÓ-‡K”Z“Âq±É„ÚÔh*ÕUX¡Œ{ƒ¤ Š¥qÉ}ߥìÉKŽÝ @™\ö«}+ÆvðÆ¥¹¹yçΓñÄëíí½~ýú¬Y³„`oÖ¬Y<Ï“H£æ¹úë\=õ˜–©ÙŸÉóü'Ÿ|RQQQYY)—ËŸy晄„„Å‹{»^ÄL¤ÕjÏž=«Õj½]‚ ˆƒå!öj²p‹ §X.|,.àX`˜0l×ü)L×ç@̲s¯ ¸äXà#vŽÏ¼ò wyª]_'hM·q—ÄΉ¹¯O7|AK%¢˜L¤;ª;§GúÁpˆZý€t}ëËOÙ98ÚÏÍó¥è½±w@Ÿ[žb18Ʋøé_³?¥£ùìLJ_Œ_[ø0[<ÑתO>ùäÔ¼ö„¢¨¾¾>‘H$ô1Κ5Kù¼]/bÚ˜Aß×@MaöÕ«W§òZvE=òÈ#æâÅ‹‡2›ÍßûÞ÷yä­VkµNÚŒÆá YP Â+¤‹¤Qúú‰&è:u4µ»”KÇ›‰ ¦´‚š.gmÑfä"=l„6ÙyKâ”HÍ?ÚÆ8:N­Íʼn‡d‹TÂôÖÿ6[¥Rœ9–¶.öÕ¯8Á[´êÂÔ´ZµV©Aº1……Ç;ì)Û® _[Ú>L©j[Λ¹v}xhà;±&払À¤ôGM|¦“C¸X.\¯÷Ïý3-bTb*˜)½y®OèÇ»ÚÏÛõEQ«V­ZµjÕ«¯¾Z]]]ZZºgÏ•J• V«ÅbñèYÄ­!aAÄm$ @€ê]}v¨š.$këwFHíMÝŸtÐVÃ^ו® *¤ÿ´I„¦…®.;Ú=™L,–ï>nºô4*K” 4:=e z¡*ÏK;Ç‚êŒÝ cž£¡ß˜# ÊÜôŠ)ó:T¶èìæWbDh |ÄÎzú‘¾óWÒˆ§××Û>Ö%¿¥• ŸfV4å€Ý¹ìvûœ9sxžŸ3gŽëÙ<Ò¡GŒÑL™‚eP?žÃឨŸvG€a˜ãÇ—––šL¦¤¤¤çŸ>44ÔÛ•"îdï½÷^IIÉ{ï½çíŠAL AAAßIÁ1Ön‹M,»'@î©gmL±Jöö6ÓG;w[¹Àùh7ø •ï^ùn¬*D%ÄxnÏà)XœI­f ©<@:R¦œÕÜ͉¤rùˆ©À9HD¬æ.[/dþ£lq§£(ª¹¹Y"‘øøøH$’9sæˆÅâY³fÍž=›<žGŒÅ º tå ‘˲}}}W®\ñv¥n†T*ݱcÇÇ|úôižçW¯^½nݺwÞy‡eYoW¸3‘Þ<‚ /IåŠàà›Šñ ¯µ—zE"©bô€ÄúIüºPÿœ#åù)ÑêeA=lRy€"`ä€H =bIœÏB VÌðOpåÊ•¾¾>–e]Kz%õˆ±›Aažç¯]»Æ²¬Ð¡7ݯ\CCCóóó;;;SRRŠ‹‹-Z´ÿþ¯¿þÚÛõ"î4$Ì#‚pw;»òn™ïÆ:½aÓ²±oó²¥^¯Ãçûfá.cçU nyÝnw8W¯^eYVˆñ¼]#b:™)º®%ò„>=¡7ÏáÃìTSžX,þáøÃþ°­­íµ×^ Û¼yóüÇ<ðÀÞ®q‡ðóóëííõv-‚ ˆ› Y³i|ëðŠä+6íX±i’êã}·yÌí­p8sæÌ™3gŽã ÓÅÏž=›,«@ŒÅ êÍs-¥ ÚdYöÎó\BBBÞxã¶¶¶ûï¿_¥R=ù䓃ÁÛ•"î¤7 b|ŒƒëÙVSÝ2øzƒ±šÍf33Õ.C¸¶Êê¶É/Æa6›Íf+7zÊQpŒÕl6[­®ãÈ9¦Ü1½%‡C¸duM¶ 2Ó&1f3(̃ÛÂèB‡Þù0›¿¿ÿ/~ñ‹/¿ürË–-ééé+W®$Áq‹H˜Gán”ù¹–D_ÙGݸ®ÊœDßÐu±á¾)ù'ÍpæÆœ8Jæ(ó¥ó«`ŽÄQª¢Æ™8ã(ª¸‰q´”S¨Ž4t (ÎѨ¤(M£çÅ–8k[CcÛ*®éd‘Jº56421§¡Ã ¥<Žàȸœ†.!'¦<1’DUÌ€9¢¢âŠ›F(¦ãÔåè/¦Tŧ:ÜwÖ•¬åH¥*f€¦#ê@Åå49ÃCku~ŠXæèïïKÅå4š9Àú²Ì·xHP=ÈtéÊ \¬^»vM¸|%æã2SmºsŸˆÅÛu™,sæÌyî¹çž{î¹?üá?ùÉO Åo~ó›‡~ØÛõ"¦%æAŒ]ÃkÛJÓ Ç¨Þ´õƒÌ ]æ'ÝÁ½{Õ}uüþU<eË®oOô¯=D«c±°ùØö >Ûà|l@˱`º¢þíïÎËö6žÈŽ_™n«YáZüN²dEEÀÂaûx|e4ìüž‘/ø˜Æƒ´ú-mYÞÒ3ó£|SW.¾ØÎ³Ì×@féßïË~sáØ‹ê•AµuÝ5kÀtš¬­OùÎÕ+ε©æÜ"ú€ }Ã_\q-¿\›$ÓTu&>,åºß+x>~í¦¥ÝçTRçκ²}6çšî}_™õÍ;çƒí½ôù±d5´È~b‡½áPìÞ­¡yûê Gû™_†¯‹¶-²×ìøY}¶øË›ùý#îït1hòoW‡˜ffP˜'üy\wÃq·>^`ª{æ™g¶nÝzìØ±øøø°°°DEyž™ †CÂ<‚ w#tq]'Wî5U´¯˜Ïs‘Y—µEñ‡žKÏ<ÛüoßþÛ\öž·"8@Ħ=uymUsF-pÉ·¢ÃBD柕de8¸&¢ä˜Ï?ùäêw¾¿”9ñ|þ±QßħæêŠfÝ÷ax’Þ àÉŒ…ú‚í–SGÒÖ&éeBž¦èçnón¶Ÿ©vîܾ¡û_lÊîNŸ{?âl ƒ—G„I "ª¦Ôâµ5üå”Q®ˆ XOÀ‚áwÃÑZ_ è£n?p¨í³—,= FX¯6(—ÝØû]ÊÂT›¸ÐP Z³]&¤a*©¬÷uÆÂA±"5§R¬¹=a ¦«+O´Ic4ƒÂ<ô/’.¼zÀo%·Y³fM¯;+~ø¡·kALWäiowE‘æ– ˆ¡ì_µšuÁ"ÀW‘Œ´µÏß•‰¾•k$›6íàX°¦4:îBv¾K/[³§x HûPûÇšoæ½úÕ{ùIPj¢Ýg¿tüëíÂÂØÄ¬‡Å=¥%{K•™†úº¿æ®Ýºí˜åÿÔéšäÚ´Þ]Ϭ ZʯMJÖZ×Ï-ß¼’öïëä÷+úóXø@4öBNòûF"vìÞ@|Éý+9'j”…oýÍz`9€Ú–ÿmh¸tõêU!‘⻫Bä£IèÊ@™™—±þÑè°eáûO„%Ò‡#CíŸOÔ„øƒ½üÕ_÷§Ö&è4rÀþ ¦4™êSÍðHTøÒðíÇŠ…ôq%ý®ñÀš˜árœFS°Ï ¯§×5'1̈0Ïݹ&Ût™l§‘Ë—/ÿâ¿øýïÿ›ßüæÇ?þ1¹p'ÆhΜ9—/_ž3gô{Î3ùÛ!£ö3Õ ·‰@÷Ûf v¥åÖ¥YtrÕ»¯Ä„H·¼Ñ­*(<˜µµ0 `h?¤ ö•ìFøcJÛŸA0™LpáVîÆx"ðqþ‡®;~`«s´{éª Øýä†oƒöùþŠÏò7C]¦IQI€ýª«ô_ûQKúŽ0g?š|Mzξ6)(ñÍEv…iÿ–ˆ¡UûÈ„>2 0ueá4FËnOËò1]mí6V̲â{—†„j¯_^øzÚÞ¤\€2]÷vÁŽûݤ@ÉÖŒzºïü£“A„Bµ¿Õ°(¿¨ -¾DHw£Î>@ÍçVÄŒuNî—¬®‹ØiwñIxËÌš‚…˜7ožF£ùøã9òÐCMÓâ‰ÛŒÛ$‚pe –~"yØîâK&9O—·¤$v³Î Îj•lJ9PsŽ·ÛºMue t麤£Ì8­óôª%B¨¢46œ;wîÜ9žg-Ædþç;Íž ìv>(lì,`êcÁœ©6)c#œýr¾w-º{Ý]‘®Ùq€·Ô¥§k+´ÉY[é#ž&21wè±än_ ÏZcäÝìŽòU/ÝL‡‡‡Ót¨öÇXÿèÝÇxžµt·Vé2k “~YÙçÓ|û:Akmνç;ë´µY±µ]c5®ÝQ|âÏÚ:›ë5ÉtÖÖ´F~'¦‘ú1¦KWAÜ"æM?³fÍ<½Õ8EFFž>}ú¯ýë¼yón1+bÖ¬Yxj¦,›Ív×]wy»“ËýTAܶ¯ÿ•£)‘¢Ê;à;×çÛëö¼ªƒ©æÂ?þ²ò€D±fûKjôôqFÇ)kß:ã»É|ñW`Áœ!ÁŠHN¯R¢çÒ°k™Þˆ,EmwÿVlï ÐÏ•Öq2ƒŠ+nƒtŽï’Õ[R2”@÷¥!·ö˜F].\±âˆ=å3à}z÷ÿÙl6›ÍfÏ\Ѭ{,P–kö# $fG¶N‰ú/þ±8øªûÆÈÕÞK=òS,_®Ú¿úÇ›þ²×@$U„­ØýÛ ö¢ÅàëæÓ qçϾ@£™ƒ6ï0Óq°èŒr¼GNÍ´F‘q˜AŒÍÝA‹\ SH,òÞ>õð* ÿ÷;ÐÛ–þÛ½™@|RnXi:(¶vœy½@%?ôd‹#aJÍ:òì„h®£n÷ʽ ó9ÇTö´œkò›–e/Ô'Õ"û—‹ÆROÖùïR7#Z¾1êä“[ÿoSªs“MHW†¹MÖ¹D©O-oZÿ0sSs-°ë^_@SÇg--óY¶·÷±du)ŒÛ#„' k/455áÆ¤åât„?€ÚFcc ÐËö¿,í¶/|ã^¤Å'å/?´{½öÖ?é’j‘ýËû!‘ª“±56!Êôv\¸´ù/¯ÜkJ({T 2˜Zζ´°Ìû×ÖB­y`É7yJìM:²êdª Žé|ÿõ_ê%÷H ÌÒ¹änß±žL‚¸sñ3Àõë×Y–ííííééùòË/?ýôÓÓ§O¿ÿþûG½•#à­£7CÎÚtá~:È©™ÖÆuúȹ&³î*†nžçy‹©Œ¾qÁE—™,<ÏÛÛ ÉnïBm²875êÒÝ’gšl<ÏóöfÝÀ 7:OobÝK´›€7MŒÍ¤­±ñ<Ïó6“Pí¼½µh·”¥» VV¸JØZó”7ÊHÐÖ³<߬KPpBv]»]H]–0ä‚’ÖXx›N=ôÍLÙîŸ'k B…y¶]ã–§:¯J(ɤX’2ÝÐjãyžg;uéJ÷tõκ©¡ÔšF8E …bEå[=mÖT¤ŠÌo¼ÅJª(UÃ0Õ£jpM M €Æ|šÊ®¿™8kã©F+Y éæ8ã(ª¸‰q&®«&Žò•ù¾fëµV秈eþþþ¾T\N£™œ ‚ ‚ð>æ„w0@zY]s³Éd2굪ÂÔuo6xކúlCÞâØ‹@ËJ®¯Ð¯÷¸: @2ÌÚµã!¾µµ‡F¨!ÀUÓ+é·ÏX¸>_ÿýûnª„ Ñk£/ÈâfÙ€>–»qšlÓ#½ÙösùجµáPìÞ­¡Ùf·u7’õYÑÛJI§qÇ#ÝAÓÚ´˜f“ n óÂ;lÀ’ˆåaaQ›R^Ö)Qö¿Ÿ;ZÊãRÊ…þ3×kjæ§ÄER•¸¯¼‹»ñP-g»Øxö"GWCNb$EQ•XÙd †ÌTs"'EEQ”*¥¸cà¥÷Ðô-ååÎ>ÖòŒŒò2Ô~p0GEQ¥Ê?Ùœùd~ŠÐ™qä”kÇ©bEQ¥J)j±ÂÑV™˜Q\y$ƒ¢âÎüS¨¡£:?%#¿hŸ°9•f ¥<3ÀÞè}•-¶‹¦³{pæFgÅ"˺8Ú*SòË‹÷QEQq•-nÁ0×–³!@ôŠŒ&ÆÃ¶Ä _$GÛÉ-ÛÒ€Âÿúö—ýödé>UJ¹ó [RT‰Õn_¦ Õ 5ÛUaR‰4 L¥1•%,í³p¸ÆÊœH÷žj®-?11¿¸(Ž¢~qàçª ç÷ÖÆ UâÉGöÅQE©ÜN}ÿ©ñÖz• ‚ b¦!aAx‡ p|cçp8]ïÔbã÷îg{ÿ¥/ù—Ѓâþ¦R¿¸£AgÊÊ­qeÂÙZr_¼`‡ãÝ]+³˜]Íí­úìέôúFà#…>ëóo§ëÊP’šTâ>€ÓCúÞÕ^ì>îýWMáÅK¤@VšqW½±J³t¯:¼¸‰1ר÷~]ej54…Ik³OY™¦#‹×¦i ÍF}PIZøë§ØÞžÒÂÔ­I4e»ÿíªPC¶ãtIáÞ4{BIs½Î”µu}Ω{V<‘@·eyíBé‹-ÿ:²£³˜xckkÕNį *oaØÞžÒ’½ñoÃP_—§ÖoÝvìÆ¿(pcº óöo^èëaÛÉ=…wá‹ÄF>·3HHظVÝ`¿û`pmI|ƒ: ‡Kjý–ÝXèêÞ•0¥ÉT)EåÕ-løöcÅ) Ú*½5k§¾ÞhØU˜º.±¸ öK§KK÷¦¦Ý“§{<*°¶0ïŒç©âÂZ¿oÙ‹Ÿ\œôÁ’*£IÃį ªìàÜ¿H‹n­W™ &é"bê#3m„wH½kƒöºþ¯Î{wuή?K±óuŸ È®+رÀÉŠ?/ÞúWó ë[‰}ˆÁ2€•>b¿ M™ÇM..áb_'’õÇvoðJ^^Ò€Þ<é/` qÉÎ×€®ù[Â$XñŠö­’ƒUç ü Bì®ÚÝiZÑ#Ãù·  ÔLQI×ê4~²ömè>¡ Àå¦&ç®Ø€ôª‚-+€'õç«ÿÌíß½N‰ÎØØ¨`i#D`ÓT ºþØž()°»HóViÞÉóOÅ ëŽX#Çêí^ºê<³»Ý[iÔ“J%N¬[#j.ºíö°¨I8uw"á‹$ ~r÷Ÿï¯¡%%ØE¢ûÒ²ÿm‹ÙT{°„Ϋqk7ªý­†EùEiñ%Â;Ù¦ý[Ï)Qj»7E+ŒÚªèƒµÖg®o/Ø ®-™ïý¹CµéžÚÂ:¯>¨UŸZ‹ŠÖܘ ¢fïÕ—V7?±®/AÄD™.Ë£Ä-"½yá YaììlommmmïdOì ‘ Hp㹺¤/w>·vσ«€ê/wSI7—è”%I¡¾”ø±ßŸ5‹D`úÛ YIŒšÞù«Úþ—Jz±P-éòx@ØÓ9ÙêÒØð 1Eí:ÜÀúQgªMÊmÑBذfwñþM>ü"IV IDAT°à®»@¹$йË"ê/¶@ë–¤ˆ_æ á|4 ÞÜù 8ÄÀG9kn[ÂÆjfúº“ üÈÎÂyJnØàD²ô`Ã|VP‹ŒM‘ƒ² \»£øÄ9žµu6×k’鬭iæ‹M&Ô¦F ƒ{£SõXàa ò…$dÓ…‡Ï8˜sµØ¿-Z8µ[C})Š¢¨ ,¸¾¾HAAŒŠ„yá6àÞo-U(‚CBBB‚nq–s2{ÆühÀÔ|Þ#|f7Äô3.Œmþ=ËZÚ›«tsSו71Ð߃ÇbléS¶0ç?Àçµum·3¤t˜N›0ŒßöC6»­Óh(»§0-I×¼`)j;ÌB"kÓÉü#§ú†ÙåWñ]÷B¨h“¥?éq»Ù:òÀ±x¤m‰˜7ýsÿl‘ØÈÄÃ]±ØøcÔþ·NWlBæ†0÷¨Ëú¦ ìµFIa+vÿ¶¨½h»î¤ë[YÖn³Û»›ë«~õ¨ól³Î3´|kô¥Gu‡M´f]°ˆemmè´³6›Ýn3ÕUe©—NÊÞÄD S°Lk¤+˜!H˜GÞÙǰWßhå¬?_—+ô@SZvM‡ƒ³6½¼6™ß“Þ¬û¥ðÐÄR“<8,fãzzô‚=§7½UÕæàºN½™jrvòȀ؟1s07¾›¤ÇÎõK>{+4t½Î⫈R=õhŸÕÓ‘›q²ÍÊ1-/Ó꽟Ãǵ+n|d0¥Ôt98k‹6#éaRpèAÏ¥nWߤtу4J_?ÑÄ]§Ž¦Öb—Òõ>;ø?µ-çÍcÜ–0_‰ÜÒ*+¸¦w×B¾xhÀ}ãÀ„<žGצ¥•¨µ[®ø,_•§ÄÞ¤#§:8ŽsX;*_ÿ5 ^ôíÉ(,<Þa—HÙvmøÊØÒöAÙKÂ6dÓúÔ´’äýå€té 5Lº÷ÎpR)sþ=zmì_q7*BAÄ8‘góÂ;d€Ï^iÔmBZR´ T:ßôh5Ö-öevs– hZˆþ®–!¿¨È ßM%¬Û!½1îÒ}ü§“‡ô¿teš:Ôw/ L á ½hSR 8 @‚¦nW”œ[`Pg­ § í(‚³*2Ï©Cý€N7¾° ?d~®R#\å–® *¤ÿ´I,ß•`J}ÄÇX*„†ªwõÙ¡jº¬­ß!µ7"W™Ø}|篤O¯±ºípf“nþ•6um¼I<€d]}´¸&áh»ØÒ€M{“÷Æ—<3øšŸ—êþ™´vq’ó ¥®þ`„DñŠ)ó:T¶èìæWbDh pã;¯ˆËHÈJbÖ…€tÅ¡zmàʵ¥© Î3d®Û›0à‹DSé"bê£xž÷v&Ïó×®]cYÖn·_¹r…a˜K—.Y,–žžžgŸ}ö¦Eyçèy«\Â#÷Ó1A§†³š­ÈåÒA ÇX» wo†cÌ–^±Ÿ¿"`Lá‡ôc¶rR¹\2° «Ù̉¤r×h=GWÇ׬ØïE€ë-Æjv@ ®h¦X%{{›é£‹»­œû^8‘d@cí¶ØÄ²{ÜJeWyŒÛÆuú¦ýŸ¡ÃÚe±A<ò·åÆm*VÑoÿ»­f‡ÇÔ«ùk[¯ØO6ðûÉYÍÝœH:ø«O  ¢u~%”™†úº<5@k,¶v½&H¨¨oízнj\§o†üxá‘B¡˜àmF% kµóÎÆT­Õ$€ÖXxžçíej¨³5 €Æha[ˤ—Õµ¶5 €Zgg[“„²fžçùnƒðËïÊØCzž7>‘gäíF%YQßÞZ— ¡‚už±µµJ“ ¬Ù­a¶€Öê«téÊZížò· -szE}s½Žèì:ÞSó4B³>°©š¡=zôý÷ß?}úô§Ÿ~úå—_öôô\¹r…eÙëׯ{»vÄ40#®TH˜çÛ­×f*iW¼Ÿ`h·ó¼]§„Rkây¾Ûd¨2vóÈìä-y4”Zg aÔªAk,öbL•0O`7ªl!üâ-tž‘1… Ï›4J$” ܘGÓyF›I ÐÎðÊnT aÞ`ž#Ûšì<Œvt^½½Y ¢U;³µÖ䞿ݤÔFÏ6k@kížNñ¤Ÿ‘0 ¯±ÔÑPí<ï óꛫh ª›çmu4 7Õ;ÚÂv}2îÞÂyLïlšmõJ ³Âhay{ws½±ÕjÒtÿ-Wg#r#/÷&†5©‡­M«Ò«„Úõé@^·§æÉs³>¤©šÌã>¥‘0¸EdÐæÌÄY­’M)jÎñv[·©®,.]—t”Û  ÂåÿI ¤(±¯x– Kæ‹Ø€%KüÀ-åtT0àDz׸18ÄÜ$QP, .Ÿ9QKû~çø”«_ Ê)ìéœluilx˜¢vn`ý¤€È ¢(Š¢|«´÷ØÙ>Ð1Ë…•WÿH ýï>s0Ÿ.Qj¤p\l2¡65ZªÇŸ{q²A¹a¹°¹\¹Séþ Ð˂ĒÀöÞùa94É’8ÀÃè‡Q’M>ã`ÎÔbÿ¶háQ­¡¾EQTP„¯G°óA¹³tÀÀΦ>Öó)&‚˜‰˜ ÿŸ îÏÌ1~‹ÎP¢ì;ÌgÞ5A³fé|aœ¼H$þgm®Œ¢Ä¾þkÓj±ÀGDnÊ@íÁÏæÌá:ï™`·œ=¦w’>°'/9wk´¿˜òÝVÐvE4}@ü2籯‚ à‡ ˜—8Ö6bþÊ%Â&÷,‹ª¿`<6Ožšõ¡MÕD#S°3 óf$Æè(+ïàH¤k¶¿”¡FOŸÛ€}æX‚ºdcE»ÅÆó6¶¾þOF~þÛt©ÿ•Ø ^˜±Û>GÂtÉÙ¦‰æÞ;¸ŽŒßöC6»­Óh(»§0-Igbû:AkºYÖf³Û-톪ºÑIDL&jÕý·éO…C$öÒõ­,k·ÙíÝÍõU¿zT:–½˜ÞjÿaöÎab–I1´y¶YÚT1~$Ì›‘¤÷fñI¹] Ç9Ìm§^/ÐcÉݾàЃžKÝ 8 Ëî–K;N•'ÕŽA?¶®”î|€½¹'[¦¦h-6<0BÿŒ(üáddežl±:ÌYÑi€Ì½ŒÏÞ ]¯³ø*¢TO=š‹TÂôÖÿ6[¥Rœ9–¶.öÕ¯kÁ[´êÂÔ´ZµV©Aº1……Ç;ì)Û® _[Ú~ÓÇlº[”š9®«ñÝ‚ZlùÞ¢K-J_§ÑÁY«sÓô s%a²i}jZIòþr@ºt…&Ý{g8©”9ÿ½6öƒ!§B›Í¸ÔÍpCO1AÄ´0áÝA’Å´µ-n#*8(ÝF›J kñ܆W+ÌöXt_pº^Vb)â´ %iiz:ïñ÷ë†I\»><4ð‰XóÄJs?H£ôõMÐuêhj-v)—Ž\sùûÈ`J+¨érpÖmF.Òäžš§14ë“‚LÁBÌÃÝg'îlÁY톞M뢃²œo¨³Mºí`ù®Sjì#>F]FzZRti@'g§+³ö&7$• ß¹+å¹=QîYçªÃsCg˜MηÅA€s[ø xË+Uy»bÃý(iÀôÀÝn³þGþ»Aµ.HœH0´?ü@Už1–vŽÑ»#näïDǵ/pí½6~÷Àî?GWÇ׬ØïE€+3‡Õlá • ®Í»iîæDR¹|Ì[Œ‡ûéðÖWâG£Ê÷?_±×<`73ÈG{ÚÍÑqòÝs‘›7Kë©Hÿµ9ì&…Çã4¶Ãè`º,ßÑRq'ID"§Ø[Æuú¼® ‚¸³˜kö®óíæ÷Œš”cÌ݉€TŽa8_©DtTR‹s –s*ùØÒ÷³š»l½ùº~·9ÆÚm±‰e÷ŒÞ{ÎG7ÈÞÞfúhçân+ a¤æiüÍúLAQÔÑ£G,Xàïï?þ|©T:wî\‰D2gΜٳgSåí Sù“šÉDrEðÐæ@"qþ¬Kä®+o‘Tê!`p¥ìç€ÉÁA ½‘ bMñê½êLíƒ[âS “ËLCÊ(‚ƒ¿%PŒ%w·rƽÅôŲµ¨½ÂºŸ»‰ìñjµ2]÷ã0C|ªI­]ã9ÆÃX£DªPŒ>“ŠÛݧ˜ b P½ ¡ýÔì,Pöc+’ôÿÒŠ¤R'sžWg•"Óà!Æó~y€B>8¹\!õ˜ÑëÃôÕ¢6¦W$’Þ¸¾y³~«‚‚‚ȸMb& a1a|­¯¨‚ïè äQ{:Mß{¯ê“3-¾euíÛ×Ëý[æ{¿¡¢*dìç@v¨»YýîÉÆ¿µDè –ž¯‚ ˆÉ'ßõ±©î7±¡haä:­.þ©Õ„×馸n¬Ó?°là{ãlž‚¸e3bÜ´ILž©5h“¸dÐ&AcDºƒˆÛ€ Ú$n™i“ nŽqôÏ ÆµUV· ùØj6›­V ×ywꈰôÆíÀXÍf³™™€cà0›Íf³ÕUqÎÁÜÁkhAL ¼ÕÓï±Ã*ül»&ðæÑÄLFÂ<‚¸ª3ĉh¸¦“E*qèÖØÐÈÄœ†¡ ³V秈eþþþ¾T\N£™À4Q‘EnKV0GT”ª¸ `Ž$RîRŠª®lÆ|šÊ®÷\ÎÚxªÑ:† ‡i«ÉP‰×&Å/Ç×´¸}b-Ž£(*£Å•‰£q`âŠkœqlKyŠû‘q9 ]ÊæÌ9q”Ì?000PæK%æ {ĉ£TE7Ò9ã(ª¸‰q´”(Riè’tœ:¢¢|ýÅ”ªøT€Ö£jqNÃèûL13±+ÏѨ¤(M£õæ¶æÌûTÎy™82±¨åF@×q$Cåë/ül˨Äü&+X_–ù·H nÞŒó„Ë@× Á¬Y³H7q{8ZŽÄ&ü6!Œi­`ß­,¾•îânXhžÊøéc‘¬b°I1}Ä6Å' `“`ìð$Ã6UR±DÐef8ÎûÇ Ç†A†ëûG:Μ9çž™rιîŸðÉ|Ý@Ve[GG[›³©¦¤"wuáÑ.ÿ-ç¯,­ýûOݤ8§“R“Nß6æ)í[­øh•=Ëb)²'å¬X²¯uøš¬tÕçÔ(;êèÑ6wY•õmmN§³¹º9+m;Ú @v49ÛœN§£©6ÍU˜2ï‘ã=£öÛ§“ ]EÍgÎ{\½ÎÚ’ªüÕ[µð¹F—ËødE–Ý€¥¦¹­£­­Íé¨.ŠÌLÉ8á”ö¤fFÚëº{]®óÕÈI]ÛЃ„²Û SwñŽˆhLŒ wÖԤͿý$[7ànÉœ›TŒ‚¦¶n—ë|[SõªÜ%ÅÇ=ûYYYÓÜár¹ºÛêóªò-ïíCÌwš‹r–ühôåb<Œû²‡wv¿ÊÛWƒ)ó4£òÞ´iÓ‚]"š ú~¶%ÓZ¾=A‡3'€§žÚ°vþÂ/f?Ý]iÿ‚âÅéÇ`±oHK0M1 ivguÆb_ïíb˜51%!>>!Á¼|Ý·K€wÎ\ðÕuÖùöÙ~(¥›Òwí)Ý´T’$iÛÁEéÜõH€¤äm­n(=-»ÄkK7i )õ¹*X¶oßòå…–ô-;Õå‹#‡W0r¼°¶¢’ äxM+¦ ølÒ²„³Ùœ¼aç‘æk™í' ,qËÌ f³9qùÚÝ gòИº»áÚOãùË;°¤§'ÇÅMQæµÛ›J²˜~Û/váß$%Ä'$$˜7lHûÜŠ·£¹ øÆ?®Š2™bâ7<ýl‘ÍÒ{Á £ù?+mëðvÝ$¢ ¨ýжm‡Zý·ÃÛ¾+{Ç¡Ã{Ò$I’ÒöŒtõï:~0]ôanõBûá›ví+ÍN“$iiöžÎk«³¼çN Ÿç¥M‡[EhRZï§þmûD^gþáÝf·³~Fq¿ÿúëÝ.e eh9TT…¬¶—Ÿ^žk2Å$,ßPÙl·¼ÔÔî…»å9¨é8¼.9Þd2Å&¤ý¨£ÆŠÓg݈JÎ)Báîëê§1O»w vqh²Q§EQ<O___ww÷{ï½÷Ö[o½üòËÏ?ÿüdüö¦Î¯6)øÿ7þi\+PÙáQUµ·©@^Q–­ Ö3òzw}X³ìÕu޶3.yä}N;`wùí¨Ü «Ý¡ª®J`+©ojª¯¯+/°¨í–ýé(3£äMÕå°ÊëšêʳT¶õ8j퀥¤¦©W>SÀVâè訳g¨nó;šÇi,YyXëüw.wdõç{›‹k³x‡ÇaìŽ^¿w—‹WåVXÊýö«:ìVX콪?OMØòŠjêš;ºµµ¬m8| —³°Økë›êëëëªó¬€Õ~^UU¹-,%•õÍÎîÞ«%÷8ËŒ6z3ë/+ÀSMjƒáÎOwÂa· ¤ùšÇq·Õ:ÛêË3”;]ž¶jYåõÍEEݪê,·°•Ô4×WZqí9SõTÛ[yÛ™ŽÚ"+`qxÔŽš,öÚfG}9[¹SœZ jšÏt4Ȩ‘¯Æíx(qô~ü2¸Ê-°hÏȲÇã‘eyäÃ^E¸Êi·"¯n|¿jUU_zé¥`ü¿f,žþù—_~ù­·Þzï½÷º»»/^¼èñxE÷¯…BÏ”[PATŠèF<ûì³/^t¹\W®\ñx<>Ÿo``@Quä6N|MCCCƒƒƒbºNY–|>ß[o½ÜÏB“ƒr嬖yFQËóš*=©™Å@Ex1Šjœ;×™cÓvvÔ?PºgwîÆ ññ<Xn¾ÛÚü§-Àét8ÓÙXÿ)¢Í˜=Ôug¯Š…cË©põOK|ÔjÅ‘•éËumûŠai~n{¢ غǾ¿ªäè© ‰Ã;0š÷:jò3×W«çé­y••?Ú§CŸãÅ XËb¢ôkl(|¾±+yí VÂú\oˆoOû© ÐúÈEñ±ëþ×ùÚÄÝe{ ×—2êÏ<›v£%6"‘jbgîÎmŒ|8ýç>%&*áÙ3ÍËÊ~’›ŸY °æU¾°{s `œÿ ^¸$ã´ûç?ÿyƒÁ0}út½^¯×ë§M›6mÚ4­wÍøƒˆ‚J܈{EQÄ ÀÀÀÀÛo¿=Þ‡Š¶Œœ2õ~‹êŸ]kŽy}oÕÞºSËP[µ=;Íì|µéðœÔ—Ûó’|.dTÞ¾NôõI¯§« |·rIR> ¤WýúŒk³Ÿ^›ý´×Ýsêíß•~gãŠÌ‡\  £¿Í‹µ°ü¿ £p€Õq¢!ÑJ_Ëÿ˜“ôÏ¿üÆËæ»ç$mÝýÜÖÝ•}=]'^Ú¿:3ó_Z¾o]<Â#¢ñÄ©¾äÄñ¹a7 ZÒWbÆ<¢P¢ÕóŠ{€ñgþíoûî´ç¯˜ .XY&Ö²>eÝïí?yÌi}Â<|ªŸ½8߯ȀeÙð…BoŒÆ5ËôXEå )™‹*2KAùî‚¥hu¢1'IÊÙĺ¦Ïl/ÉZ½>©€5«úßv$_ÿÌðÖ—?~à‚WÔþ™6ÕYãN~gí›OV`ˆ¼×t§÷vª8fÞô”9J7ÿoWÁ9þ·ªaaaF£Ñh4 QO'’ž¸Kï£Ý1’H$½3f„‡‡kÅÓR¨N¢;1…bž¸ýEâÉh4ú|>Y–‡††D=Ѝ¥Máâ]þ1Od<íN.¸‡& ýŒH@ÄïÑmá:Ž<5=|á×eÙšSqþÒ_~ºäÁü‡º=:SlBòÖÿÜ[±âl¯w±  ù’)Jé~³ëþí±Ûhƒ LKS€¿º€Çyøêó/•^´¸µö*ˆÒÀ…n`ÙÕ Ü­û"3|žw²€…é›·®ùóþÌK2ÜŽ²2g^uÓ7Ì2ôWÞûEêúœ×Ï=µjŽØ©v>QŸËŠ0áš!ƒÜ-•Ű–›ïK|Üå÷Iz“Û!ÍM©>#oˆÓM1æåþuÛ/«vû˜’Ò­™ûOº·&ŠïÀý§?ÑÓ¯;oé¢,_°¢ùR[åÖÜu½êÎ(è¢bâWm.ªüyñî?}ÄpÁš¼xÜ*…#ü“cQà*++333ƒ] `dÝ]­)O´ÛK’4}úíGlFqVwŸz ÑO‰§ÿÜ«$›t€×q¤«†¢£ñ|ÿðörÿi }†¸ÚÉA½S·kÖòZYVº;N4þ|u抸ä?Ìòj;~ôè<ï™w=³Âݽ ¾öïò÷žéj{û•?ܘZ–Ü—7ê™/¹7t¿ ¦Ï¬²:ó´/9A‡¨Ø¸(À}¢V´á-NI2Õúílóp…á¹W÷mÌ}©iS6€ÛÞ€%mÜÇTÛl¶eË–‰¸Ö 'NàAŒyaaa¢0ƒaÆŒ3fÌÐJ8ªx¼ÄК*1/,,lppPÜ………éõzóü3žˆ|ZqñF­Ã†xÉçóy½^Q³ÜOD“…qÅŠÆönob¼qáBkmΡ֕_ÐÓÚÖlùÄ'ï/±"?óàŽf|ažâîþÍOþ°-¼ßhŠL¶!7eÓžŽÊ¬yºUøDPk×ÐÆGk§2äsÍÿ¼¾Y5w:q˜  ±ýTO⟳ ÷'G¶ÿhùüñŸå4¢Ü¾XÛJÀ™û|‹0õtµ¾^茶£óÿhDÖÞÇ—×ÙšõY(.¹mÕ“ˆþèx»SÓ/_rü¢8³ EõOÅ g×»íí³d¹¿ÿôsY¶*d86˜˜LZ+à' €™Å Uy–¹ú¾®“?Ù]‹…‡‘ –™Sxðo‹2’”®¦­)ù°”<0ü¾ íï´Î˜Y–O7îËlDÑX—Ü™¥ËžÝº2 žŽW+3QôƒxÏ8Çá÷¼*"""<<Ü¿ÎU¯×‹Ë0¯ÁD¸xñbTÔøvÓ#ó´¦<ŸÏ'’žÑ8N¿ý8÷×uf- ?ùÓ'İêH`ýÓUçÿW†ìüÕîF¬ûÁ¢e Y°e]ÿûµ 8VœåDž5Átáå[ìõü¿.Yä®tÙœ¸jÍJ Š1íÁ5Y°•½øëöx´—-I)̪sÏ~‰%·¶ÃµÖ¼\÷Õ”yÿ\;ꙑFã²5· Xž±ù«—¬‹wîýö’9è:ùâc©¹Ã»KXc·"Çb39*ûÌœî“/>¶ºY5Ë¢@ö¹°ð¾ðÀ¿ÜëøŸÀµzº öÕõƒâ:"úmjIOOËxLztç¦JÌDœÓëõŠ¢FEQÅ“ƒa``@–e10oTÌ£ò¼^¯¨Va§MºSÆ…éœ<Õ»!>ÖœùlÉ‘E–EP d”7§Çuß«ªüKFfê‚‘ºkkeó^³0&?×Vk[b[4gørXÞܽ!ÞȆH "Ó2<”¶‚êî¢uþÌ#-}úy€a¤‘Í *[Ãg¥X°Ñ²2Þõίj‹Ù,e€¬òæ§ÌW{_ÍO5—·¤$Y`Al%Y‹?Za)jJ¸z¤„'Š,+~þFß“ËL@Efêp‰,¶òº¶ì´XzÃý@qÊ’âáW2ŠšŽ~?qt/ϸÂ3õÖ®HšW8ò‘Šœ•Œ@ÜÚÝŽJ$e¦”‰oÇRàüýöXÀ«7Î)ÚàEKI­ó{i±:lpÖtZÖ¯®Í~!Ë^Ÿ—àÃ÷ßV=8¦ÉÀo("""""Bë]#®ÄÚð¼q; Ñ”4gΜ`TUÕ†lhõ¼aaaÏ<óLaaáíßǯɳæÚ…çÖ ´%嬧2çê3X j¿ŸkÄVç=l[)^¬qÆþëÎ\×O>þÿ«)X²>IÊKVåc樘gœYE急¨í™U3MI•Yûm‹ÄnQPÓöisô¨gâ Ï z}ÜÚ[ vÕyGÍ·’Ö[FNÍE5µëvÙ zµµ¶Í»å‰I ÄK¶‚šWŠÖÀÝZ×h]m÷HýòË/Ûívq÷ï‘ô˜'îQµzZÕF€óæ“>ISÆùw¼ôù|âdíñxÄ´+bæ•ÁÁÁ¡þoÏëõö÷÷_¾|ùòåË{÷î Ê·'ISåW›üŽ›ý4= ;æ®?¯îc,zZ}ëÀôÊ­‹òKfÞ¾ž]ýú‘sc¢®©}Qúºº]f̉‹·ˆ¢x½0uwßù^—>òþ˜¨\I•¾Öïϱ|©Ãµ.~üâÑÍKÕw®Û%ëgDÎUoß¹]2 ¿?.öŽ®÷â zýœ9±¦á7ôì’æzšÎ?½<æfoúXY’$mÙ²eæÌ™3gÎôïZØG¸'Ÿ|2ð©°Ç…ˆyZ=¯Çã¹råÊåË—8péÒ¥q>˜âîéSLQQFq 𶤅ÿó3ž†ÏxzÜ0ÆD]= »{ÎõöcμXÓÕÕ+îžîÞ~ýŒ9±W¯"J_ÏyEgŠŠºº¾žs®~DΙ«=wý3c.ƒvP¬7͹þ]î¾·GÖ‡_=ÿ+]‡õ ª®#×Õ Êét>ûì³&“iæÌ™£FÁ+G…“Dˆ¤§…=QBQHm^PÊI“ËT ×Ï–éõzE´Óf×8ÅöþoTEK†—/_v»Ý.—«´´”1î$æ}{–Î9½»{wZ¬øggâã&D—¤Û:×ÞiJ¸!ï®êiØ6wÅ'{Õí·øÒ?nÌÛ¾}{dd䨎Ý% ÜÊ•+_yå•`—TUÕfØÖ2žËåzà¾õ­oÝÝc»OH‘)M.uùd?ÿŽ‘÷Pzø/ÓÛŽlN÷]ÿñ¬®®'pÑ{S«§ ÖqÕ…"pФ'"ŸhÐ#ôX™HwnªtÚÔÖCWUU§Ó©ªj4µ)7µAz¢5ׯ<Ñ/ßçó‰îšâ^PQ¸Ì2ݹ¨-¯8›þ|õŸñ7Z*`bŠMˆvÆCÌcŽîeã¬g̘1sæLóD×MóXÏJ¸Ù³g»ÀHÌÓF剦žÁÁAƒaô4Àã/üÁúšºø»1.mr¶6W¦Æ`µZsssÅ \뺩­¬p7Žx[âª!ZóDÒ›6mšèÀ©¼àNC“ÑT‰yðûÿôŸŽE´×‰†;mIA±™ó´ùâ¤ïóùnz$¢ëèbÌi7í-Hw]Œùæ5ÇJô¥‰ˆˆ˜9s¦V̘G4."##ƒ]À/æy½^Ä Ž»2Óæ(º˜´u«îúQ&.SbZòí·I’Ä'&“iT=Ý]:èm‹$ˆ»Sqé­þå¿.+8ÿ ݱ©óTUÕþ€EˆN§«ä]?$O{ úyŠ[7ÑŽ':pçcÑÄ`4EÒ›1Bô«aÌ# ÜÌ™3ƒ]PUu``@ü]c$ãy½Þ-[¶<ùä“Á.Ño¼qìØ1£Ñ(NÝ¢žNù”"iW mžèƒæ¿n{Wo§Ij Å<aaaCCC¢FD¬£ ºqj åi1O£Å<ñ§%VVðz½þ6{챈ˆˆçž{î^~" .ƒÁ0*é…‡‡3拈ˆˆ`TUÕfæÐêßÕè^’$IœÀµ¤§Mhôå²´õ´UXµÔǦ<ú¸¦VÌÃÈß{Ó¦MÓzijŒšƒAÄ<íü.:I‹“¾ØàòåËG WU•{DS‡èK#ÆNh³¢1æ‹{1øí¨ª*î°‡†† ƒÏç³bTUU»h4vb!rqÒ¾þÄ‚ù_;´Œ'þÉv<ƒ)óÿ?›[d<Œœâ(Šâ?Í‘v"¨ªª2’$?~<55õžŸˆ‚O›ÃIË{ÚÒFŒyDÒëo°úÚ½§õô™>}º’§M‰ì¢ÑØ%''ÛívñSj¿©vnÙF%½ –„BÏS·ù‹m}a7"6xæ™g®\¹vðàAÆ<¢©ã†§­wM°KG4¹M¶ q0ªNGLÉì¢Q@´žYâ—Ãy8%…ž§nÿ3´ÿB›œM»Kög"¢ñ7ª­^’$m”¾¸×è¨×“e¹¾¾^\¹dYþío»sçÎ`* þ7´ž·ÚÏ'êé$.¨@!Š1³ÃÐÐÐôéÓ‡††ŒF£X2U4멪zß}÷Ýwß}ãÞaÿAO3*àª>¤»G¤¡ÝÐk1Ïÿ'ðoÖãO31ùÿ”7 {ÚÀKÿ!|þ}~D³ž˜«M,¢Àn?D!IôÙñÿë}|t:ÝàŒTÈb’Ÿðëêê´%a†††~ûÛßþÇü‡˜sn2Ò’›v†×ªìµŽúâÖÓQHbÌ»SþI#½8Ä ßàà`ttôœ9sîÆ09Q©¦^;¥‡¸œh/…À¥eRðÏÚ3"ã‰ûÑš§ýüi&¬Q?¥6øÀ¨šÝQaOT‹¾š"ì1ã…¼°°°¡¡!-ÿh÷þðµ+rPK¨êêê+W®hÿ {ã7Ö¬YÄ"hTý¬êü+õ$ެ¦Řw{þ7y¢‹¦v¦PEļ9sæÌš5ë.åýãܨtÇqïù_3n60€?ͤp}ó¬\ŒtÇÕ‹ÛmnÑŽ'û·þõ3Ñ]¡%=ñ@üW¼2¡]¸pá7Þ0ZÅå•+WJJJÖ­[ì¢m5FÎíSM!1[7Q“§¥>Q™'úåGEEEFFÞÕÊ<ÿ+Šxàßjt7ŽH7äß”w³møÓL ×ÿ”£nü_õïÛ)rÿºyìóCò´Ù¶´¿ôQýÉ~Âÿä'?ù›ßüæÌ™3n·ûwÞIMM°råJщiòuª÷vÁ“6…6Ƽ;âß5TÌ ÙÍš5kÆŒbã{p¢uˆÉ~i™\F]Fý“?Í$rëŸòúçµö:­··Ÿ[ìˆB†6Õ 'üG}4ØE<3ӔŘw§´~Z¾¨ÆˆŒŒœ1cFœâ‰è†üký;üŒêáIDSãM(ŒyC˜ß¼ùþýò}>_ddädïÕ@D·¦%=ñÏöð$"""š$6@B|{"òñ›$ mþUõ¬¶'º{´ ®((ÚÚÚ¾ûÝï¾òÊ+Á.„­y‘$i``@¯×s /M¬0 ”ÛíŽu»ÝÁ.Q(`kQà8¤$P•GDDDDDc^ |>ŸÁ`v)ˆˆˆˆˆˆ†1抭yDDD2Þ{ï½´´´`—‚ˆŘ(¶æф˜(Æ<""" ó7ÓÐÐìRQ óÅN›DDDDD4¡0抭yDDDDD4¡0æŠ1ˆˆˆBÆ©S§~øá`—‚ˆŘ(vÚ$""""¢ …1/PlÍ#""¢±xñâW_}5Ø¥ ¢@1抭yDDDDD4¡0抭yDDDDD4¡0æŠ1ˆˆˆBFgggjjj°KADbÌ ;mф˜(¶æQȈojj v)ˆ(PŒybÌ#""""¢ …1/Pì´IDDDDD c^ ØšGDDD!ãOúÓòå˃] " c^ ØšGDDDDD c^ ØšGDDD!ãÁ<~üx°KADbÌ cM(Œyb§M"""""šPóÅÖ<""" gΜùÒ—¾ìRQ óŘGDDDDD c^ Øi“ˆˆˆBÆ‚ ^ýõ`—‚ˆŘ(¶æф˜(¶æф˜(¶æQÈøàƒ¾ð…/»D(Ƽ@1æQÈ$IUÕ`—‚ˆŘ(vÚ$""¢ñÀ477»D(Ƽ@±5ˆˆh¥¦¦»DD“c^ 󈈈ÆÑk¯½ì"MzŒyb§M""" gÏžMNNv)ˆ(PŒybk…:÷¡MK%?iÙ{Zû”;}sëié÷m¹OºVvéáž±ºuOÚÒÒ–±¾{êâ,D¡AìLzlÍ#"¢çîv"¯Ú™m†ŒþÇOVdZ°@Þ·öNo#œÐßñ±*›œ)³!=ïÕ­X¿þÃYÎ#Ùæ1”Yo¼cxßT7oÞ¼·Þz+Ø¥ ¢@±5/PlÍ#"¢©ÀºÐlN0›Íæä´ÍÛí4Ÿq{;w¥§ît€·sWú¦£^(=GK³E[ܶƒÇGrÖéç÷l“$I’6mïÓöéíj(ÝÓpm³%-Ç1§­Û^mÅiŸ,6=¸#]’$)mÓ¡çx;oÊ.=´o‡$I’”~xx·}GK³—JRÚ¦?¯kŒ6â¦ïݶïðÁm’”Þr'팓Š×í½Ó–V" ]ŒyQUUQ½þÎë(‰ˆˆ&¥ Þ‹ ¯×ëîi­kpbá}áò¥ÆÚÚ?]R@¾ÔX[Õ~ÉÓÓ´Û–ÿa³ÃYo/ËL-:Þ€²Ì†9MŽf{F•í‰ç´`%_øC~î<×çt÷‡n¯Ûív»»Zÿ²–ûf}û]ùÒÂ:‡³v•{cʼÃ]ŠÜ¡ª"ã ¨on*±Õ®â97”†Ûò›ŸªkÚþÐ…âZDpÓ÷–å¬ÏðO}. €xÝ…ËšOÌ6‰òÌK°Â‹›¼@ôlãÝýÒîÅýþë¯w».þ~n-P¸-wïîí9ò“¶ÿôÙô¥ÙÇ{D/N÷áméÛµÃÛQš}´ã2àm°o+:Ú!vãm)ßiµÛóPVîiTzNìJ_*I’´tÓá–žöCbÏ;·»Î:ß>Û@éiÙµix›[u©½z\"ºëó˜GDDSDô'æÇÅÆÅÅÅÇÇÇG‰€$À%yx ˜ àvÏØð¬ËãêvÔWß_–›Y鯬%|•½¹ÙᬯÎòêŽæææ¯-ñ,zþ‚Ø˜ØØØ˜˜„´ÇíTÿß?˲ °Ôw{d—Ëãq9›ê m‹ÅŽn0ÌÈ@ŠþKÜ⽡ÃûÑ eeN—ú¹¯¦ûέ¥}5€­äÉG>¿³¢âwÐsr}Ym‚yàz½¢â´ €òACYãiñÓádM&l[²¶|ÆÚïŸtÎM)tmtt8+SªÖ'==<¼çuËæ¹NWý°ý# «pnR¡{££££î)lL™w¨Ý}£.µð;.ÝuŒyá4›DD4u…ÏZ 8Þ~ß ÷Ñ¢ÌFÀ»û-ZYÙ›˜ö_θñûdèâÌÉɉæ/š ¿˜˜˜œœ5ÙdYÛPgˆF´AoZœlƒ³ò×'“É}ê×–ÔÕ/ýõ“ŒÈ3¦[‘»³²Ë o×±‚|g´·x¯|ý.&) KXiµ"ú¡ô4ËÒ+¬°®^¿ô%–ªÿzÍ t½ù·Êl‚1±VUsg37ת¹‰ ´W¢`ë—º%Y(.Ù ¸[õ/lOŒ7o¶; 2æHóÞsœ ˆ6cº»õX1,ÍÏmOŒ_µuÝ‚’£§–¦ŸNK^¾uW9œ §Üð;.Ýu\P! lÍ#"¢©Ày£guñÛj –¬O ϬV½né×ëm…+æésõg>×ïañ[¤6s™ À0ÞèU¦yh|¡î\öög›Ë禤V倭¤¾ 9ÊÓŠëvµ¥ªþä¼ ÂÅÑa3¦ä¿‘3&çjŠ»Ïð(Óºœ*2Ù˜d†»§.]» ù»ßuoøó KIsÜMvÛóæÑ*+æ?ñó“=›—Á$Č槟3î7 u||ÀÆOw• µˆŸóº.µDto1æ„­yDD4˜6Q7ßè…„uO{z¿ï†.&Ê4ò\ÚÕs®ëCY?ãþØ#lUßÙ‘9[U³¯î×|õ¥ë_LžS7ˆ‡ÉÙªgù^o¸)*ʤõÞ«oŒM{Nvýø¼[7'6j$ÅÜལ4™8+Ná]ï IDATÊ}Ê¥n5Ao.Ün{cÂ#EȲÊßù"dèqzg’­òwí˼{AA¬P:þøøò­_ýV@k¯Ñ{¡X6ü ï2‰‚ˆ6ÂÖ<""šâŒQQ~oø¹Ø¸¸¸áŒ7ŽG2ÅÆÆˆœv+:SLìÕŒ÷ñÞ;è ?žêñº;_ýy#RbgÝh+páÒy7Ħ—gTäæÖZJ¾oï‹J>ðJóÁÒò†ÐóFIìÙÍæÄD³9qíÖT•õ>ð9 jü²U÷øÞoeæ¿ ÿžÀôÀç,¨úÉ‘V8wüg9Øb½ÁèGùšãÑ]ǘÆ<"""º—ÌvåY*’æ†G.ZÝh³ïHôóÃ5«øF-Û’á,\ýPi €%ÿ°Ñdl[-z_Bùèg?ÌoýÈxßþYþÞ?|Ôù»œÈ[c¹×—­+‡3ÿµþ/­+)ÛhÑK᩹öúñº«{>^LÚ¯j‹ÊÖ[ô’4/5'«¼ù)³ ¸¾K­ÿq‰è®“TU v&±ãÇïØ±ãøñãÁ.MJϹóý²~^\Ì-(½^¯ÎhÔè:,-ØUßûNZÔÍ·¾¯»Ç­˜¢¢´ùR¯îY+»ï|¯KyÌè†T" ¶ædÖ¬Y_ùÊW‚] ""¢ ÄÛÙp¬óî*]LllÜ-3£Ñ¨ƒ÷è®MÒ‚õ(Ø=ÆŒÀhЉ‰òOuFã¨2 3EÅÆÅ1ãMŒy±X,………Á.ÑÄ œ;¼kSø¢«—„g—íQ¸‰…³ý¥íûKË>IZzìÜÕuzŽ—JÒÒ†ÅÝzpôöRÚ 7ZfK’´çDßÈ;ÜÓ¥ô}­-{Ò¯Û^J+m ÆçŸ€tó—®(¯¬ë.J vIˆèž …±Èóº½:Óèj)"""úX”c…óÖ¿TPSYðúù¸þ|Û\_“ºóoÝÝNd•7gÿíÀ•±ÝôÙñŸ\|!9Õ/w¬Úœð¾V•«ýïbtø« ȪkþFÄÀÀÈž#>޳¾~¹)EkäÝñ:ð¹pÚ'/¶íjN.ÐÏзÿ"scqJã;så~ý} ïýçŸt‰k7'»DtïM±lãmIOZítm”jJB¯ºÝt®aݼµ(é•¿uúÍÓ ¿uû¯¤o_úœœÚ¼6ywÂÍ6VúZÄÞ”kxRº£77qÌ]%ˆˆˆ&÷ûÅ(h*\ûü…KOþSÛ'?ûߢµÎšøåäÄ„k7ŽÍ,ÀŠÝ/ïÙœÀýnU²jÖDn°$®LNu=;ü¿eßúñ“ Û“Å?¢Sœ99f¼±–ćÍì8HD4å:mºŸ¬篬©]ÀõßµÈks}/ §“R“N+·Ý”®úœZeG=7ßjdoÆ…;kjÒæ›n¾%QhÍBqê·J÷ן?ÛmLX»u]¢ˆjí¯8qâ¸Ðp¼³O°ìËáÌ=Þ¥è9ùR-¬+â@8[^Ѷ?ÞÐÒ):jvÃVÙÖTÒ˜Ÿr¸ól. /ÆÂÜÓ¥´=~]R½-é’´¯Õ}ó·ÜŽ·%MJ;À\n)•¤Ò>Q¼}­틈ÆÃ”‹y‚â:ÛòöYoçÑuOäeÿòå?x$ @Rò¶£U;Ò² wüï;‘¶éX×5ãÈ/ì…­¨$ù^Ó.2]Ç÷¥‰ÁÙ{Ú{:wì­µÏýþë¯w»]ÇŠÑi›J[ûí‡wlÚµ¯4;M’¤¥Ù{:½àí8šmÿà'ÑDbLÿÏ6{Vw~qU¡m‘´4ûX§€!(ËIIIIV¤¾tÚ Àd^Uhì”×^(DÆ–eÃ_ @ÅjmûÔÿüÒéá#œö-Xþ½jÖ?¶× ýÔ\ÑÈçýŒ¨Âp·úð€Þ®U __<" Š)óÚ‹xZ»ôOekRmyvÀR²ó±¿û\\cÅÆ=ÐU ¢qÆây~½?”Îù[s¾õ"Tìu¸ÀÝzpAjμòú6Gí¼ŠÜ%åkFö6_úè…²2§Ëãm?´ 5óþòúŽŽf«3ß2§ø _x·ª0çø-Íõ•ѹߪh xÎUT4|Ä)ʈˆh²ÑE%lÝ×ÐÛdÏ*©,YX±ú±Ê>Àç‚ÅîPýlÈ·În­ÝýrŸ·­ªEY_¹Üú{¯ßö [¯.“¡Ûðl½Å™[|ìÝéóp!Ÿr‚òvÞ”]zhßI’$)ýp{ï¹»†§ÀÙt¸µ@û¡mÛ ·¶µÚ¶íP;€H4¾´wWš˜¼æh;(=GK³Å|6Ûw%×Tj÷ÁÛyxÓ¶}‡n“¤ô“9ÛòöY†H4î-ÍN_*IÒ¦‡†'ÙñvÜ‘.ªº8wï¿¢)hŠÆ3²71±°x÷h lÕöì´øøä¯6YPør»>2ªo_—œ¶ù™Ë/Ì4ç¨jmâÌ`|-DDDcæmÝ$I‡ºaøìÊŒíÿ³ΆÓnˆ†þ†ï°Ø¶À¹ÿ'{~R‹ŒõËbü^À­Ú–bÒª*3ŠW'm¬Â©٢w#rÿ…ªŠü/ ¾¹©ÄV»þ‰çÜðþjKJ¡{KÛ™ŽÚ¢îõ–•-^ôÔPv¶_¼¥ÿ£†²³—˜€Â\Ç–fG}q¾mɾVwOÓn[þ‡uÎg½½,3µèxßèJퟗû/T•å¬ÏKDwÝ”˜‚ÅÝ×SŒI‘׾䑸dÀ¨Èd`ŠÛd·&í=±÷« »±mïR¿Í•ãÏWΤHiø‰ÇŠÖn8yÌi}"I ¿‹Y¾ußrÀÛ2¼·áëÚå“ÇœÖ'F…‡Ï^œïWdÀ²lx½1lÁ#"¢ÉËýi ä…ã_ú€®¿ÿ9,O,6á$Ðxºµµ²<2nNm1Çé]Ü »u}n¾ÓRTŸà?qŠóôÉÖÖˆ‘íeè?m1ûʼ¹¤hwU¡ð*ÄèO‘Ðî ,M/>½< _ÜUžo©;åÎtŸR úóÖ¼è|äì|N#Ú2rw¢yÜ T¶=¿.ÁˆägÊ÷Wì­;õå¹ï&èפmív&_ˆÄ©†+µMÀ›ì3^íó€¥þü‘´\nm 6‹švo^àhÍ› ÖÿáÏë?ÈiDMGñªx#÷å×Vk[—m¾ÑG!¢q3ZóÜ?3·øÍ>Ðé]@¤þ¦áV¯€Ï¬ù&ÿ«²rŸø_vÜŽ²2g^u“Óép8M5¨Íyýœ½]ÃÓ±ôµ-éÛ ¿Zw©‹^ŒÆóÕgûOsg耫'æP2NDD!/ö;Îjä§.HÍÉM]”’{¡ºêq`š”m´X,IšŒÚ‘ù>¢Ölɰmý2¿ý€²T¿íS’rß÷†HD_=V^U%“Á¿0 GU熠Ñí—°|aaàžú\0|SáLUTZ+2Í —ôÿâíݵw@=myhµ,7<¦e-¾¶«ÈVµzÉ<½$m9pBž!®ÔÞ¹ÖѳGMlzyË>%Þÿ¹/ÇN_€õ‹Â%I’¤y…ìDtwM…˜‡YVWÕõAiýåFX—,¸Ñ¼—2€ÆöS=Œñ_)±4ææVØÊ×ÅúmÒù4"+ûñåfsb¢Ù¼|Ý׳€ò—OqMŠ·íìSÜí?²Øò߇Ñooã²5Y(Ì:ÚîÜÇŠ³œÈ³&ÜxúMï EE‡Î±;M6Qæ ïÈgu^^µSVßÙ`ŽLžSG{g«¶ÊPüºÝªªnö»&šÌÙ×½¡!Ùóæ#jC¶éêf›UU}ίQÈœ}D=²9Ôç¶6%¥[÷ŸÔæÅtÿé@ôô‘üvmŽs»f-¯•åÞ3mu•kŠsVrE6vŸz ÑÃ!­ñüð½Î7œÜîžuy\ÝŽúêûËr3+Û®¯Ô¾qËi4Þ2ééyXµpº °Ôw{d—Ëãq9›ê m‹Çá› ¢[š 1ÏôØ¿•£bãIoÙX–UY<\¥],€ðY)l´¬<á³6? À7VYüöã>¾·ÂR”á·V^ÂE–ÚŸ¿¾¶°¦ Ú¶hŽ>rI±%Ïñý/øíM?0èõqkÿ³:¶%‘’¹º8ºÆY‡kF*h•K­?üá³eN""šŒtÆ%«ó¾³zÉ” ‘ –™Sxð„[Qú:¶¤äòê×`Ÿÿ×%‹6U9£âV­Y©ÝÓ8÷×uz•sÇšãÌ ¬þÞÁ=-¿Ê¬ÅS+¾»Ñ¢••½á±‰iÿðå †ë+µ ÃGU>8s‹º¼J_ëR‹Qðÿ<°8Ùgå¯O*&“ûÔ¯-©«_ú++³‰î¾ë*ÌB”§·»ûL÷y×-7’=YæÑG> ‹áï“ã•V½·õ'¹EMç7$Ç Õ¿_Tò{wÖC 꺳WÅB‰±åT¸ú=@ÔæZu3`¦9GUs¸À¹bÞÕ¾ŸåÍœˆ6c:ô¸~?§~ÿsdÕTn]¥z›}sRŽèïõwE4E1æÝFô'æÇÅÆÝbƒk¾AEvýðìÊE'fßŲÑTäuV—X¯¯~¢ª¾sùWåî«uÍÆµ;÷p·NŸ Hb;Yî>=}øæe^âCp¶œWrŸ˜gݼÕ\ºåÁ«gކGQt‘sãb®™‘îºý\>y¤Ñ’þÌðñþ:Ÿˆî Çæ'yæÂt+rJÖéövß“ZŒ…Æ`—‰ˆˆˆB˹WWÁVÓìt:N§£2»^žEs¸ªY9~pÏÑöϬ9kÆpìúð¿ËgçŠÉÃcæ|·9¸5á3q±qqñññ£2Þ°köcŒ[ ç%Y<£‹øÄ|:"Œy·bˆ¼áÓúùZ“ÅÿùH½>jë‹Î¢îœE‘á RdXລ$""¢)ÄýëÒbl]—l6'&šÍ‰_Ûd‡3÷xïƒ_·!wge—Wéi©JÍÌ=#ë ¸tÞ=2í‰iáVäî<ÔåúZÊÖWaÝßÝd…(¥ù`iyü4:7²Y¾ó¢ê–|) …GÛû¼=-…I¹@äÇx7€6oÁ´ùÈp¯ôkÍÏ©*`«úÎȦælUͼ'~Óú¥g{Õø(@9š­ßɱyDDD4ŽzNîmD¹}™ö„ÉòHpàØŸ?ÛüæÜ”á¹lEµ™f“¾3È]ôЬsU€@ÔSUM¿Ÿ—º <l%ß_´Î úá{BÄÄÞ·–¿wõÊœ´O)—ZøÃ#ÿ½ &ˆœqÝ躑'ô×ï'nÝ3u%[V/™ÀjœŸ¹o\Vu ¢Û‘ÔáÄBããØ6iuŠ*« o–äWD×w¿œË,MDDt§$‰7'ðöõ¸aŒŠ2 ß~(^¯¢Óuþw#Þžs½2ÂçÆFÝí{”žÖc¿;=÷±µ‰F çøŽ¹©Ÿp©[oÒ~HDã‰6RSS3êR´ê™Ëxå‡~Ïûà–Žê˜ñˆˆˆè2FÅÄh€Îh¼6ã0ÆÄÆÆÞýŒ@';7Ú’žÜ±ïоmsS‹³ª­ÌxD÷+ÌÆNQ£Ñ¨(\擈ˆhܰ5/ÄœkmøuÝëíñ,{,{Ãò[Í^NDãˆgÒ±»råÊܹs¯\¹ì‚…Æ<"¢À±ÓæØ LŸ>=Ø¥ """7W®\ùô§?ìRQ óÆÎçó †`—‚ˆˆˆhܰ5•(40æc…˜3fœ:u*Ø¥ ¢@1æ;mÑĘ7vlÍ#""""¢ ˆ1oìØšGDDD!Æãñ,Z´(Ø¥ ¢@1æ[󈈈(Äp ¢ÐÀ˜7vŒyDDDbŒFcggg°KADbÌ;vÚ$""""¢ ˆ1oìØšGDDDDDcÞØ1æQˆñù|>ø`°KADbÌ;vÚ$""""¢ ˆ1oìØšGDDD!Æ`0üéO v)ˆ(PŒycÇÖ<"""""š€óÆŽ­yDDDDD41æc…Y–,XìRQ óÆŽ6‰ˆˆˆˆhbÌ;¶æQˆÑëõgΜ v)ˆ(PŒycǘGDDDDDcÞØ±Ó&M@ŒycÇÖ<""" 1ƒƒƒŸúÔ§‚] " cÞØ±5ˆˆˆˆˆ& Ƽ±ck…˜iÓ¦}ðÁÁ.Š1oì󈈈ˆˆhbÌ;vÚ$""""¢ ˆ1oìØšGDDD!FUÕùóç»D(]° 0‰1æ—ãÇïÚµË`0DDDüÃ?ü€ðððòòò9sæ»hDD“cÞØ±Ó&ÑxyõÕW_{íµ¿ùÍoÄ“¥¥¥Œy÷˜$IgÏž v)ˆ(Pì´9vlÍ#""/ßüæ7%Iò&11qÁ‚A*ÑäÆ˜7vlÍ#""/Ÿüä'—-[¦ýsæÌ™[·n byˆˆ&5Ƽ±ckÑ8úîw¿k2™ÄcEQÖ­[ÜòLY±±±Á.Š1oì󈈈ƑÍf IÒÚµk#""‚]¢)jTïY"šŒóÆŽ6‰ˆˆÆ‘Á`xâ‰'¦M›±eË–`gêêîîvˆ(PŒycÇÖ<""¢ñ•““£ÓéÂÃÃSSSƒ]"¢IŒ1oì󈈈Æ×ç?ÿyŸÏ÷è£²ß Q ¸nÞØ±Ó&ѸSU5ØE "šô¦\Ìó¿xx!ù—ù½^?44p¡ˆˆˆˆˆh‚Õ¿`Rt7¦B™–Ä´âSO…ÏNDDDDDÐr$Iâ±ÿƒ`–ìæB¼5Oä:UUUUDÀcCÝš4",,,,,L{ìÿ‚[Âë…rÌ)nhÄàààààਰ'»¤DDDDD4á\ð¦M›6mÚ4UUµgTUhI/dcžÖ^78BQ”9sæ»\DDDDD4‰õööN›6M§Óétº°°°¡¡¡°° ·~A(ÇŸO–eÑmPLúˆ –ñÂ1# £+Š"ô|>_°KDDDDDD“›+¶ÞµT’$ié¶} nJgé¦ô]{J7-•$IÚv°EQ:w=’ )y[«Ûÿ@.X?”Ÿ˜¼6{‹µ.Ð~xGvéÁÒMRúžÀ}lÏp£ŸØû¡mi;ŽzôµlKK?ØÒàÜñ=éÙ‡ÜJÏÑÒ‘÷ÜíDzÓ$I’Ò³÷ˆÖÂk÷ODD4žØšGDD“ç/ïÀj_ë÷”yó¾Þá\¤¸Ú‹hø~!ºÿ¤õöÚæ‡f¾´bÅi8lߨª­­ª-¯kÚØUµ:3iiJÏš<{aãþ’Í¿¦0oiˆŸùò_ÿ°3§1£Òœ½ðnE~12Šjúĉ=¶Õ¹ª›Û^[’ºâŸã…ÏÍiÜXÓýôÚ¹ï¿RÖXk}å¿7'.wVåÖÎoò6í¶åXçì˜×ó’eEjx|ïÓ ÿ÷¡%«£‹ªö~‘‘jyØ{þí²ßþïÝ—JDDScMPà‚W¾Õz=ú^ÜUa-wl]›$;Êë’ö6öýÓC 꺳WÅB‰±åT¸ú§%>jµâÈÊôå×tÚ„ ¨X¿­Ù8Îÿ¿½;ŽâLï8þ¬wgwÖfì[’õìD&‡Qâ-µE^ amtŠ•rK¯¡ôÀ)1Wˆe]âät B:PkT¥N“Ê kœ¤1WÑëU!Ueò‡qÎár ni½¾W€×%¦^oÉ®™Ýþ1ö°ØŽcÀönÆßÏ_ÃÌøõ3ïZB¿}Þ™‘þ«?&"Ã<0üÖ³Z¢÷骮–îÍÕ~‘¥—Ž.o=­žþf@öüûµÿÖÙD¤ëäG±—w’}ბ×E4Q¼ËjžïTJï¿ìHKÿîÍ%"KÞ9ñÊ¢Ð/¯~ÿküÙ›AÀ|Å¢M@ŽQ•Ì=C}ïì[y[â¿{#ÒÕXe®“¬j"'Vi"¢ëý"↥•«%òá€wyS@~ñ«žÞþx_Çê å¢ CIDATOƒ]çzõŠ„‚Ë}KÿxoK¨½nY©âp4½qVÏ×D4‘=¥‡Ãáð. ‰È•Áøíñ˜iÄ<@nò–=)‘æ·.ßÞ“èü«Pó?\¢KÉyáÄ%]ÇãÎtüåã£ñI}fæHÆéŠ2~€L%«VE®|·¿(4æ}úëÓøíb—öø‹õm¡]àÚÚMÁµõ!©ÿ“%ªÄbù›<îwûj[sш>Ò/}º><G¯tvt'@¾Ì"b 7¹Ö}¯C¤­üéW{¯ %b×Oîß¾±]Z~øäøg`ºÊŸÜ!mm?»W5ýÊeÖµ_™|H]Dºú.^¿so¡Dúþ£¯¯¯·¯¯÷ý½ZÕ%¡àrßíãÚ#›‚Ò¼û'W"CçÛ6¶ËS¿«‰,z¬N$"ÁÚ%ªoÕ† DdG¨Zùèpyùº#QoIeÍúÇëED^”ÈáŸ_Ò49÷VsmÝëŸðÊÀlâÞ<@Žr•<1>¶½jK }§¹§µãÂË5~I|òŒuå*DÄõ­×"»VÊ wŠˆZ.¼ö„KzKE<Êès‘„ˆx‹ È–ÀºÅÃ=ÕV;Í£‰´­YÖ6úÏà —Z*Té½]ˆï»íݧK×,ò6Šˆ„Z/½ô˜ˆ¨eÕ»D>ÚPEY½Adð¾Q&"¿óg¡=µ¥J³ˆˆÔw^Yî/[ÞÑ® ›Ã Ü9>3ÌaF¶k˜a†a¤R)]×ãñøÍ›7c±Ø7¢ÑèàààÖ­[íw½`w‰¡ëѸ®hÅ~mª/'“C×’.Íç›ò,I&¢ª÷ð-gâúµ¨.Þâß4~8qíꧺ’ÿÕ¿Õ{L ]&EóM}€œæp8Ž=ê÷û}>_QQ‘¦iªªºÝn§Óép8²]à(þ«ä8Õç/ñ}ñi.Ÿ¿ä‹Ï—z/>Wý%Óôä’²²ñ»¦W÷{óÀVˆy`+Ä<°bØ 1l…˜¶BÌ[!怭óÀVˆy`+Ä<°bØ 1l…˜¶BÌ[!怭óÀVˆy`+6Œy‡ÃápXy²]€/7+\8ƘÛÙ®ëvN>VÞ§ÓIÌpŸ\.—#C¶Ë™œm“9ã™­<—Ë•í¢|¹™ $«¡—›Í$û'3à9N3æålàû\.—Ëå²b^¶Ë™œcž9õN§ÓétºÝn·ÛÝÞÞ~ãÆX,vóæÍD"122’L&S©”aÙ.@q8f¯ÈívççççççkšVXXèñxEQ%ó½l;žmc^fÆ3?Çãñx¼^¯a‡ÃÜCÌ0QfÌSUÕëõæç竪j6Ìžžõ\KzöŒyyyy©TÊ\)k~fÀK&“†a˜ŸÖÈÈÈ­[·R©T*•Êv½À\ÈÍÖÓJ§ÓYù½ÖÂ@Ç£ªjAAAAA×ëu»ÝŠ¢˜Ϻ=/§&Öž1OÆþ‚ÍDçñxR©T2™L§ÓVO×u3æ¥Óiºy˜¶mÛæv»³]Å];|ø°®ësüKÍüf® 4“ž×ëõz½ªªš==+éÍqaÓaÛ˜g~$étZQ”T*åñx ÃÈËËSÅëõÞºuK×u3ã±hóDNuœ¦ïÁL&“süKͦѸ¤çv»Í¤§(Šõ,–ì‘Ú6æÉXÒ3 ÃüÆÂüœEÑuÝÌxfÌËV ˜c™i$Ö{°0Ð8þŒ/­þõß<Ž6Wúæ´²)-\¸0+wZY/N°Bù¼sy ù–Ìxbטg½ÞLzn·ÛºOÏlî™k8Í>­<Ì™D[²>|f¥(ùÿÛ÷Fí–S:¬úŠ®+Þáÿü½¯=¤e±È‰ŠŠŠ²Ò›±n3ï3Ÿ¹b>‚Å9Æ w;ò‡~è÷û‹‹‹g£l±kÌ“±¿`§Ó)¯J7cžy“žaæß Ý<ÌwôÔ’ÊêIä/éYõÊJU$ù›oü"µò—ÄÞÞþ굺ʷ4¶ë[ø½¥ÿº+ÔÖ%;œù»g«]"±¾“?hª;Ô%¡ûöþuS…ÏJ±“æ[ª^œÙœt§\>yô¬ûÑo×,U§,[Ó´¬ôf¬g«XÏð·òž.¬WçÝmC¯¢¢Â0Œµk×>÷ÜsëׯWef+·gÌÛºuë›o¾iƤóe}ÓÙ¸‡óïêg¤ž©ÍàõNs>§yuÌçôO›Õñ³;ŸSb>™Ï{þE3RÏÔ‡f{>‘SFn¢‹¨"‰ÿ9ÞÖV÷ôž?PÛ5·‡Z»»zhÍÆÚvÙu¤£³é\íÆGÿñø3|°zYÝ-Ç"ûþÇú5µ‰ž—ý£ã)Ñó u"GZŸ ­«ô¹>o§ÈÿõlÙØ "»œøî·¿¹Ø?yÜ[°`AVbžãNÖjAk1§cì1›wkáÂ…ƒƒƒï½÷^8N§Óõõõ+W®œ±Êí½dÑ\Âk6î¬Û𬵚֊Mk&nL}t–ΟúÐÜ×3OêŸÎÔOý“Öœ;õ̇úï¶lê§þIk¦þ98?Óðð°ˆN<4g±öËûg¯þóçÏ/X°`ÜåÄzއ‡OUj"‰óAoÕ†pt›òO…¿?3ÜS­Éùý5U§þ\{³+Ù»A Ô„£Ás ƪ~cw‰Hâê;ÞE¡Wôo•Ýî! ]íí8þ£-;‰È ­Ç¶mª«(óMº3»öËwÿùõÍ'Dõ-­/n^[¹x\Ú«©©‰ÇãÙOsÛÚÈLwÖöôÇ÷Ýw?ûì3kÓéôx<ÅÅÅÛ¶mÛ½{·Ü7›Ç<“µ,ÓÚ0¯z>\;@ŽørÅT»ž¿bÅ ó¶¦LŸóÞ* $¢ÆË>‘Þý5õòZÏó•’8_ã­ÚŽÏ=hlÏd_xøùʉwô%ûNþí²º"31~þN‰]~ÿåk‰´œ‰î®¾cmgwwwæ“6çx>ÇÄ ósãÆohh0¿þ°¨ªšH$ÊËË/^¼(÷Íž‹6DZâu^^Þ¤Ÿ0ÜåZÕL ºˆ$î8 ôK`ß@¸I'•ä§œýME`|ƺÚÛqü-;ÛD;Z÷~Ýû¹;͆ޡ½Íí"Áú–'¿>~¨Õ«WßMÙ3lܤÍÈ:äíÛ·›yyy^¯·¨¨¨©©é™gž)--½ÿÁežÄ¼L“vcLßÃ+‚9üó ßyªB{sm³DâùDzÅåSGÿâņöˆHpDZÎHÝš ŸK.Ÿ:úý ;cWϾÚöÊζ"–#—Bkû&¹=/7_A~?¢ÑhAAA:Þ´iScccuuõÌŽ?ïb€ ¬;'•‡D<æƒ c»nŸ¦”Šˆ¸ü5/u´†ë£ï8¨¸Î†þíÅÙr,Ò±¾¢D›r§\<¾kçÇÁŽð¾µ•eS?lÓf~IEND®B`‚jifty-1.10518+dfsg.orig/doc/pubsub/system_architecture.graffle0000644000175000017500000011433211447473535022202 0ustar fsfs ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 CreationDate 2006-10-24 12:01:34 -0700 Creator Jesse Vincent DisplayScale 1 in = 1 in GraphDocumentVersion 5 GraphicsList Bounds {{756, 39.835}, {211, 137}} Class ShapedGraphic ID 82 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Jifty Push System Architecture.\ A. Tang and J. Vincent - \ October 2006} Bounds {{330.451, 150.979}, {256, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 80 Line ID 24 Position 0.62390816211700439 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 (With a kill-me-when-republish-to-nobody flag)} Class LineGraphic ID 78 Points {822.47, 460.7} {822.329, 431.61} Style stroke HeadArrow FilledArrow Pattern 2 TailArrow 0 Tail ID 77 Bounds {{748.211, 461.2}, {149, 97.8}} Class ShapedGraphic ID 77 Shape Rectangle Style stroke Pattern 2 Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Publish unsubscription from 'ping' events \ ($SUB into $DEL-SUBS)\ \ (May also happen \ upon session GC)} Bounds {{45.4648, 366.851}, {907.535, 54}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 1 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Message Bus} Bounds {{241.567, 505}, {149, 54}} Class ShapedGraphic ID 75 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Publish subscription to 'ping' events \ ($SUB into $ADD-SUBS)} Bounds {{105, 505}, {133, 54}} Class ShapedGraphic ID 74 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Start ping server} Bounds {{398.5, 285.356}, {49, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 72 Line ID 71 Position 0.51288449764251709 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Send\ [$SUB]} Class LineGraphic ID 71 Points {423, 349.516} {423, 251.716} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{784.411, 610.503}, {77, 42}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 69 Line ID 68 Position 0.42627021670341492 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Jifty::Action:\ Unsubscribe\ Action::Ping} Class LineGraphic Head ID 77 ID 68 Points {823, 685} {822.792, 559.5} Style stroke HeadArrow FilledArrow Pattern 2 TailArrow 0 Bounds {{323.771, 263.402}, {83, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 62 Line ID 61 Position 0.27589595317840576 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Poll\ $ADD-SUBS } Class LineGraphic ID 61 Points {364.995, 247.455} {365.995, 356} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{982.555, 751.48}, {61, 14}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 60 Line ID 59 Position 0.89849430322647095 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Time >>>} Class LineGraphic ID 59 Points {30.8634, 757} {1124.02, 758.647} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{652.329, 607.255}, {84, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 55 Line ID 54 Position 0.51953768730163574 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Push+Render\ $EVENT} Class LineGraphic ID 54 Points {694.329, 546.643} {694.329, 690.255} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{655.57, 439.363}, {49, 24}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica-Bold Size 10 ID 56 Line ID 52 Position 0.45289328694343567 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\b\fs20 \cf0 Send\ $EVENT} Class LineGraphic ID 52 Points {680.07, 424.383} {680.07, 483.957} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{603.273, 452.914}, {52, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 51 Line ID 50 Position 0.41240772604942322 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Poll\ [$SUB] } Class LineGraphic ID 50 Points {629, 489.057} {629.661, 435.363} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{532.773, 447.813}, {52, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 49 Line ID 48 Position 0.41240772604942322 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Poll\ [$SUB] } Class LineGraphic ID 48 Points {558.5, 483.957} {559.161, 430.263} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{432.043, 446.396}, {52, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 47 Line ID 46 Position 0.36850014328956604 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Poll\ [$SUB] } Class LineGraphic ID 46 Points {458, 481} {458.117, 425.087} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{558.5, 256.36}, {57, 42}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 45 Line ID 44 Position 0.24552829563617706 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Publish \ $EVENT\ to $SUB} Class LineGraphic ID 44 Points {587, 249.615} {587, 362.615} Style stroke HeadArrow FilledArrow TailArrow 0 Class LineGraphic ID 42 Points {315.076, 504.5} {312.334, 428.426} Style stroke HeadArrow FilledArrow TailArrow 0 Tail ID 75 Bounds {{55.0165, 435.416}, {163, 42}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 41 Line ID 40 Position 0.48351499438285828 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Add \ Subscription Channel $SUB:\ Action::Ping} Class LineGraphic ID 40 Points {137, 482.62} {136, 428.426} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{383.843, 121.654}, {149, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 38 Line ID 24 Position 0.42278197407722473 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Publishes Event $EVENT:\ PING 127.0.0.1 1ms} Bounds {{30.8634, 623.165}, {71, 28}} Class ShapedGraphic FitText YES FontInfo Color w 0 Font Helvetica Size 12 ID 36 Line ID 34 Position 0.38565847277641296 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Jifty Action:\ Ping} Class LineGraphic ID 34 Points {65, 690} {68.5352, 553} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{39, 693.868}, {1051.46, 54}} Class ShapedGraphic ID 31 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Client Browser} Bounds {{470.033, 293.501}, {88.9045, 42}} Class ShapedGraphic FitText Vertical FontInfo Color w 0 Font Helvetica Size 12 ID 29 Line ID 28 Position 0.59332269430160522 RotationType 0 Shape Rectangle Style shadow Draws NO stroke Draws NO Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Publishes to \ Channel \ "$SERVER"} Wrap YES Class LineGraphic ID 28 Points {514.486, 247.455} {514.486, 360.455} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{44.4648, 205.059}, {907.535, 36}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 27 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Republisher} Class LineGraphic ID 24 Points {458.117, 88.7247} {458.652, 199.725} Style stroke HeadArrow FilledArrow TailArrow 0 Bounds {{174, 29.3902}, {410.773, 59.5743}} Class ShapedGraphic FontInfo Color w 0 Font Helvetica NSKern 0.0 Size 12 ID 4 Shape Rectangle Style fill GradientColor w 0.666667 Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Server $SERVER} Class LineGraphic Head ID 4 ID 22 Points {129.731, 504.727} {-23, 405} {344.348, 89.2904} Style stroke HeadArrow FilledArrow LineType 1 TailArrow 0 Tail ID 74 Bounds {{65, 502}, {340.944, 59.5743}} Class ShapedGraphic ID 79 Shape Rectangle Bounds {{45.4648, 490.194}, {907.535, 54}} Class ShapedGraphic ID 32 Shape Rectangle Text Text {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410 {\fonttbl\f0\fswiss\fcharset77 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\fs24 \cf0 Jifty Server} GridInfo GuidesLocked NO GuidesVisible YES HPages 2 ImageCounter 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo LayoutTarget 3 LinksVisible NO MagnetsVisible NO MasterSheet Master 1 MasterSheets ActiveLayerIndex 0 AutoAdjust CanvasColor w 1 CanvasOrigin {0, 0} CanvasScale 1 ColumnAlign 1 ColumnSpacing 36 DisplayScale 1 in = 1 in GraphicsList GridInfo HPages 1 IsPalette NO KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo LayoutTarget 3 Orientation 2 OutlineStyle Basic RowAlign 1 RowSpacing 36 SheetTitle Master 1 UniqueID 1 VPages 1 ModificationDate 2006-10-24 15:25:32 -0700 Modifier Jesse Vincent NotesVisible NO Orientation 2 OriginVisible NO OutlineStyle Basic PageBreaks YES PrintInfo NSBottomMargin float 0 NSLeftMargin float 0 NSRightMargin float 0 NSTopMargin float 0 ReadOnly NO RowAlign 1 RowSpacing 36 SheetTitle Canvas 1 SmartAlignmentGuidesActive YES SmartDistanceGuidesActive YES UniqueID 1 UseEntirePage VPages 1 WindowInfo CurrentSheet 0 DrawerOpen DrawerTab Outline DrawerWidth 209 FitInWindow Frame {{0, 0}, {1680, 1072}} ShowRuler ShowStatusBar VisibleRegion {{-250, -92}, {1665, 958}} Zoom 1 jifty-1.10518+dfsg.orig/doc/pubsub/backend_message_types0000644000175000017500000000037511447473535021027 0ustar fsfsPayload Types: ClientAction --> Republisher #subscription - Add Subscription (IP) - Remove Subscription (IP) Republisher --> ClientRender #pong-$IP - Pong (IP, IS_ALIVE) Server --> Republisher #pong - Pong (IP, IS_ALIVE) jifty-1.10518+dfsg.orig/doc/pubsub/subscriptions0000644000175000017500000000500611447473535017413 0ustar fsfsSubscriptions we want to support Create,Read,Update,Delete Class: MyApp::Record::Foo For hiveminder: NEWS * on every page, we have a little box with the 3 most recent news entries:

News

<%perl> my $sub = Jifty::ClientSubscription->new( query_class => 'BTDT::Model::News', query => ['id_not' => undef], # Ordering? on_add => [ { render_with => '/fragments/news/item', render => after => 'news.entries.last_child' }, { # how do we remove something if there are more than 3? } ]); For hiveminder: My page is: list of: tasks matching 'owner me, complete is not true' each item is rendered as '/fragments/tasklist/view, with args %ARGS and record => $found Subscribe to: * creation of things that match 'owner me, complete is not true' * update, delete to anything that matches 'owner me, complete is not true' after the changes * update, delete to anything that matches 'owner me, complete is not true' before the changes "Render this component as": wrapper list of items matching the subscription 'owner me, complete is not true' render each item with '/fragments/tasklist/view', args => %ARGS, item $found my $subscription = Jifty::ClientSubscription->new( on_add => { args => \%ARGS, render_with => '/fragments/tasklist/view', render => after => '.parent.last_child' # before, after, replacing }, on_remove => { args => \%ARGS, render => replacing => 'self' render_with => '/fragments/tasklist/fade_away' }, query_class => 'BTDT::Model::Task', query => [ owner => 'me', complete_not => 'true' ] ); # Session::ClientSide-ish encoding of SIDs to subscribe # Each request carries IDs of its existing subs (stashed into ->subs) my $sid = Jifty->subs->add( query_class => 'Ping', query => [ host => '127.0.0.1' ], render_with => '/fragments/pong', ); Jifty->subs->cancel($sid); # This actually just calls the fragments with Publisher-msg structures as %ARGS # Print-on-void-context, return-on-other-contexts Jifty->subs->render; jifty-1.10518+dfsg.orig/doc/plugin-requirements0000644000175000017500000000505311447473535017225 0ustar fsfs21:36 so. what would people like to see out of a jifty plugin framework? 21:39 I'd like to see that a dispatcher plugin cannot affect an action plugin 21:43 What do you mean? I'd expect that a plugin would be able to install dispatcher rules and actions 21:43 so we could make the "EditFile" thing a plugin 21:44 I'd like to see JiftyX::EditFile::Dispatch 21:44 er Dispatcher 21:44 JiftyX::EditFile::Action 21:44 as separate namespaces (maybe inside the same EditFile.pm) 21:44 of course, JiftyX is better spelled as Jifty::Plugin 21:44 Jiftyhashi? 21:45 Java has coffee beans 21:45 maybe Jifty has tea bags 21:45 Jif::Tea::Bag 21:45 *groan* 21:46 so. about plugins 21:46 I guess there are two different things here 21:46 1) plugins for parts of jifty should be in the right namespaces 21:46 2) should a plugin be able to install dispatcher rules directly? 21:46 ie, "use this plugin and it adds rules at these trigger points" 21:48 I want "Login" and "Signup" to become plugins 21:48 so I can stop cargo culting them between apps 21:48 so sorta like rt callbacks 21:48 yeah. was thinking more like plagger's system. it looks pretty 21:48 named points. so even if they move between files, you don't lose 21:48 yup 21:49 so. this means I need to be able to: 21:49 install actions 21:49 install dispatcher rules at all stages 21:49 install static content 21:49 install templates 21:49 possibly install widgets (aka form fields) 21:49 install javascript libs and css files 21:50 (special cases of static content) 21:50 (but also hooks to add those things to the generated header) 21:50 right 21:50 what else am I missing? ;) 21:50 oh. new jifty commands? 21:51 po files are considered templates? 21:51 # ./bin/jifty fooplugin 21:51 no. pofiles are anotehr item for the list 21:51 declare dependency? (normal cpan semantics?) 21:51 another 21:51 yeah. I'd just use perl require lines 21:51 partial ordering? (run this before that) 21:52 in dispatchers? 21:52 or actions? 21:52 or what? 21:57 sorry 21:57 from callbacks 21:57 nod. I worry a little bit about the complexity. when would we want it for callbacks other than the dispatcher rules? 21:58 if all your login etc are in well known places jifty-1.10518+dfsg.orig/doc/jifty-model-svk0000644000175000017500000000711611447473535016234 0ustar fsfs=head1 name Jifty SVK Model docs =head1 SUMMARY =head1 IMPLEMENTATION =head2 Reading and writing from the data store - Upon each mount, read everything, expiry-keyed by revnum - Build in-memory index for common accesses - Encourage ->begin and ->commit to take advantage of svk txns - Otherwise it's autocommit - svn:author is $ApplicationClass-$ApplicationUser =head2 Implementation plan =head3 Functionality =over =item create objects =item read objects =item find objects =item update objects =item delete objects =back =head3 API - First step is a memory-only, svn-compatible layout backend store - Composed of alternate implementation of APIs of: - Jifty::Record - Jifty::Collection =head4 Jifty::Record Methods: =over =item create =item set =item value (get) =item delete =item =back =head4 Jifty::Collection =over =item next =item items_array_ref =item unlimit =item search This is a new API. It replaces Jifty::DBI::Record's "limit" My $tasks = MyApp::Model::TaskCollection->new(); grep { $_->summary =~ 'foo'} grep { $_->owner # Tasks with a summary matching 'patch' AND with patches (computed) $tasks->with( summary => qr/patch/)->with( sub { $_->has_patches() } ) # Tasks with a summary matching 'patch' or with patches (computed) $tasks->in( $tasks->with(summary => qr/patch), $tasks->with(sub {$_->has_patches})) # Tasks with a summary that doesn't match 'patch' with patches $tasks->without( summary => qr/patch/)->with( sub { $_->has_patches() } ) =back =head2 Data storage format (In SVN) - Subversion based object store, using headless YAML::Syck for now - Each object is a /UUID/ directory - Optionally encoded as /U/UUID/ or /U/UU/UUID/ etc - Each field is a /UUID/field_name file - If it has a jifty:class then it's going to be blessed into that - Type the object is encoded as the dirprop jifty:table - It's blessed into the "class" name defined in the jifty-table repository - Time of creation object is encoded as the dirprop jifty:created - A simple floating number of Time::HiRes::time() - The jifty:table themselves are but UUIDs of table-objects - Also stored in the data store - They are of the builtin table "Jifty::Model::Table" - "class" : [ "Perl::Land::Class" ] # Record Class - They are of the builtin table "Jifty::Model::Column" - "table" : the Table it's associated of - "name" : field name - "type" : jifty type-tag - ...other column info... - J::M::T and J::M::C (recursively defined) are always present in any data store - Consequently, jifty model --create must do a uuidgen when backending SVN. =head3 Runtime storage format (in memory) - In-memory structure looks like this: {$type-uuid} [objects-sorted-by-timestamp] - inside-out objects comprised of a single UUID as payload {$object-uuid} - real stuff, blessed hashes of field => value-or-object '.' => UUID '.created' => timestamp '.table' => table name - Column/schema info is encoded in the store itself as {$type-uuid-of-Jifty::Model::Type}{*} - Introspect/modifiable as any regular model =head2 Limitations =head3 Runtime Typecasting my $uuid = $typed_record->id; # concat of time and uuid # ...somebody retypes it and stores it... $typed_record->load_by_id($uuid); # oops =head3 Performance =head3 Search =head3 Scalability jifty-1.10518+dfsg.orig/doc/ajax-upgraded-links0000644000175000017500000000237011447473535017037 0ustar fsfsWhen I click "next page", If I don't have ajax, reload the whole page, with the changed helper parameters. To reload the whole page, I'm going to need: * All args to the current page. * Which args should go away * Which new args should be added. Basically, this is BASE PATH: framework->current_url PARAMS: framework->current_request_args with this_element->new_version_params replacing this_element->current_version_params if I have ajax, refetch the enclosing div, with the changed parameters. To reload just that section of the page, I'm going to need: * The path to the bit I want to replace. * The name of the surrounding div to replace it with? * The moniker? of the section to replace. * The parameters I should pass to that section. Are those the same as the things for the next-page link? Basically, this would be: BASE PATH this_element->direct_url (no params?) and replace this_element->current_version_params with this_element->new_version_params jifty-1.10518+dfsg.orig/doc/plugin-syntax0000644000175000017500000000206211447473535016025 0ustar fsfs# Login plugin package Login::Dispatcher; on 'login' => 'login'; on 'logout' => 'logout'; on 'signup' => 'a_moment'; after 'logout' => run {...clear_cookie...}; before 'login' => run {...check_for_already_logged_in...}; # RequiredAuth plugin package RequiredAuth::Dispatcher; before '*' => [ plugin Login, run { ...check for auth, otherwise 401... } ], on 'auth_required' => run {...} # Dummy application package Dummy::Dispatcher; ## implicit from config.yml: ## plugins: ## - RequireAuth: ## prefix: /blah ## args: vals ## - Login: ## prefix: /blah ## args: vals # trigger RequireAuth; after plugins 'Login::*' => [ on "logout" => show '/my/logout', ] before plugins '*' => [ on "logout" => show '/my/logout', ] on 'logout' => [ show '/my/logout', plugin Login, ] after 'login' => [ ] after PUT 'login' => [ ] after plugin Login => ( before plugin Login => ( on "logout" => show '/my/logout', ); on 'logout' => [ before_plugin Login, show '/my/logout', ] jifty-1.10518+dfsg.orig/doc/jifty-web-form-etc0000644000175000017500000000722211447473535016620 0ustar fsfsThe Jifty::Web::Form::* classes are currently a bit of a mess. This is an effort to document their internals so they make some sense to whoever finally gets motivates to fix them (which may well be me). C is the base of *every* class in the hierarchy. Virtually any widget that Jifty renders, be it a link, button, or form field, comes from some subclass of C C itself deals essentially only with writing out javascript event handlers for widgets. Its method walks the C argument to all those buttons and links, building up a data structure that is eventually serialized using JSON and passed to jifty.js's C function in an C wrapper. Form fields (usually created by C calls on a C are all subclasses of C, (C). C takes care of most of the work of rendering form fields. It renders the label, autocompletion, placeholders, hints, validation errors and warnings, and so on. Subclasses override methods as appropriate to add or alter details of the rendering. Note that subclasses need *not* concern themselves with making sure that the field is rendered as the correct kind of widget (field, select, etc.), assuming they represent a standard, single, HTML C tag (as opposed to, say, C). That is dealt with by the C magic: Whenever you create a C, it has a C. Normally, this represents the C property on the C tag. In order to make the system extensible, however, it *also* indicates what perl class this widget will be. C blesses the returned object into C<'Jifty::Web::Form::Field::' . ucfirst $type>. The stock rendering renders an input field with C, but subclasses can override C to render something else -- see C for an example of doing this. Simple links are instances of C. This class is fairly simple -- it merely renders as a HTML C tag with the appropriate attributes. The only detail that remains is the non-javascript state-variable emulation of AJAX support on links and buttons. This is C's job. C is also a C, which means it inherits the Javascript hooks. Its constructor builds up a list of state variables that need to be B from the previous request, while its C method walks the javascript hooks inherited from C and generates new state variables that will need to be sent by this button to simulate the AJAX effects given in the C. If the clickable needs to submit actions, C creates it as a button, and otherwise it creates a link. It does this by creating a *new* C or C object, and serializing all the state variables it's built up onto that object appropriately (in the name, if it's a button, as GET parameters if it's a link). This final step, where a C (which is not renderable) clones itself into a different class that can be rendered, makes use of the C method defined in C. Every subclass of C keeps a list of the accessors defined on that class (typically these are defined using C, but not always). When C needs to clone itself, it walks the list C<< ($self->accessors) >>, building up a hash of all the accessor key-value pairs on itself, and passes these to C on C or C, which calls accessors on itself for every C value> pair in its argument list. jifty-1.10518+dfsg.orig/doc/client_side_continuations0000644000175000017500000001545611447473535020455 0ustar fsfs01:01 I think DNS is your programming language of choice ;) 01:01 *snicker* 01:01 . o O {You must have seen the cname on quit.fsck.com } 01:02 rofl 01:02 mm, instead of passing cookies 01:02 and maintain url transparency across post and get 01:03 just pass the J:C and session token in DNS!] 01:03 *groan* 01:03 deadbeef18405930.hiveminder.com/ 01:03 alex and I were talking about client-side continuation serialization today 01:03 We're about to do continuation garbage collection 01:03 instead of passing it as part of request_uri 01:03 in pathinfo 01:04 this guarantees auth zone separation etc 01:04 (very bad idea.) 01:04 laugh 01:04 definitely "Worst Impractical" 01:04 this is not unlike .NET Passport 01:05 where you visit something.microsoft.com that redispatch to your domain 01:05 but there is a reason why it failed. 01:05 *nod* OpenId seems to be doing a bit better at it 01:05 right 01:05 so, client side CC 01:05 in hidden fields 01:05 I worry about the amount of content you might need to pass around. and the fact that you lose GET support 01:05 HMAC_SHA1 with server digest 01:06 for small continuations (practically everything) 01:06 you can embed it as part of pathuri 01:06 except our continuations aren't that small. and when deeply nested you totally lose 01:06 /=/deadbeefdeadbeefbeefbeef1982398102957190824091840984124/moose.html 01:06 yeah. in which case you fallback to cookie storage. 01:07 oh. you mean having a continuation id in the url and a cookie with the content? 01:07 yeah 01:07 the id is the cookie key 01:07 you can have multipel cookies 01:07 they can expire using normal cookie expiry semantics 01:07 and then every GET or POST pushes all the cookies to the server 01:07 not neccessarily 01:08 using the path restriction in the cookie? 01:08 the path component protects you 01:08 the path component protects yothat's what cookies are for 01:08 ys 01:08 hm. 01:08 self validating 01:08 in a sense. 01:08 you have a compelling argument, madam. 01:08 hm 01:08 I believe it's somewhat original 01:08 or at least independent invention :) 01:08 :) 01:09 So. the first step is that alex is getting continuations into their own database table 01:09 alex really wanted to sign them, rather than do digest validation 01:09 because he wants _no_ server state for a continuation 01:09 a private key is a state. 01:09 same as a server secret. 01:09 er. sorry. no unique state 01:09 same. 01:10 if you do HMAC_SHA1, only the server secret is required 01:10 not nonce 01:10 global shared secret 01:10 ahhh. 01:10 cheaper than signing. 01:10 I missed that. sorry 01:10 equally strong. 01:10 np :) 01:11 It's certainly an interesting argument for "how jifty can scale up" 01:12 if we have the cookie and url scheme, is there a reason to complicate it with sometimes having hidden form fields? 01:12 only if you want per-form, as in region, continuation 01:13 regions have their own paths ;) 01:13 good then 01:14 so, cookie is specced to be min 4k 01:14 I will admit that I get twitchy about how easily this is remotely 0wnable if you capture the server secret. 01:14 and at least 20 per thing 01:14 that gives 80k min storage 01:14 in practice the 20 limit is not enforced 01:14 so you get effectively unlimited storage with splitting 01:15 I'll note that if you get server secret then you can set up fake forms. 01:15 both requires owner permission on the share/ 01:16 and really there's little point in worrying at that stage. 01:16 that also requires dHa willing dispatcher 01:16 Alex's proposed attack was: 01:16 nod. 01:16 push a results message at the user containing "You must change your password. click here" 01:16 phishing attack with a valid url 01:17 I'd probably be mollified with a randomly generated session key 01:17 and actually have the session key stored server-side and ~nothing else 01:18 (Does that make sense?) 01:19 thinking 01:19 how is it any different than the old cookie sessionid scheme? 01:19 I mean the attack 01:20 persumably the action will always need old passwd as input 01:20 so it can't be automated 01:21 I fail to see why client side state has anything to do with this. 01:21 jifty action results contain messages. 01:21 jifty apps display those messages 01:21 the messages are defined to be able to contain html 01:21 you mean rogue action classes? 01:21 imagine an attack that pushes a mini form submitting to a third party into that html 01:22 no, someone who redirects you back to hiveminder with a continuation constructed to make it appear that you needed to change your pw 01:22 it is clearly result-message scrubbing thing... 01:22 anyway. back 01:22 if you want to have login/logout 01:22 and continuations never work across logouts 01:23 then the server secret is just the session id. 01:23 i.e. nonce. 01:23 which you don't give the user in entirety 01:23 just as you observed 01:23 nod 01:23 I think that works 01:23 and for public non-currentuser-related requests 01:23 it may make sense to have a sessionless form 01:24 where bookmarks may be shared. 01:24 The case that didn't work in my head was with a global nonce. 01:24 but I think the use case is rarer 01:24 I think per-session makes most sense. 01:24 indeed. It's been my conjecture that even anonymous users can be given sessions. 01:24 if Inever logout, my bookmarks always work 01:25 if I logout, they only work if I-or the server- explicitly requested affinity 01:25 and the server has the option to deny that request 01:25 otherwise it's thrown away, and the logout link should reset the continuation cookies. 01:25 yes. 01:25 ok, very good design, I think. 01:25 I'm reasonably happy with that, I think 01:26 woot :) 01:26 now I must run to $job 01:26 shall we throw this log in jifty/doc? 01:26 already horribly late ;) 01:26 sure, please do 01:26 oops. so sorry. jifty-1.10518+dfsg.orig/doc/jifty-action-record-search0000644000175000017500000000240211447473535020320 0ustar fsfs-*- mode: outline; outline-regexp: "\\s *\\*+" -*- Jifty::Action::Record::Search should take arguments and return a FooCollection as the q{search} field of its q{content}. It will generate arguments for each field, according to the SQL type of the field: * text * I, I_not * Do substring searching on the given field * This is case sensitive. * I * ? Does exact matching ? * time, date, or datetime * T_after, I_before * T for exact matching? * int * I * Exact matching * I * I * Less than/greater than * I * I * These are perhaps superfluous, but could be convenient. * (I want auto-loaded arguments ...) * boolean * I * Can be true, false, or undefined * refers_to an object * I * I * Accept ids * ? Generate valid_values for this ? * refers_to a collection * Do nothing? * I_contains ? * I_lacks ? ******* * Validators and canonicalizers * Never use validators * Use canonicalizers on any "exact match" fields * What's the right behaviour on substring/comparison match? * valid_values * valid_values should remain valid_values for any exact match fields, * become available_values otherwise jifty-1.10518+dfsg.orig/doc/js-refactor0000644000175000017500000000167411447473535015432 0ustar fsfsbps_util.js focusElementById removed custom onload hook code removed buttonToLink, updateParentField, createCalendarLink, createDateTimeLink moved to Jifty.Utils removing JSAN usage wherever I can removing JSAN core and now-unused libraries formatDate not used in the last 3 years === What's left? grep 'XXX TODO JS' use DatePicker from jQuery UI instead of YUI removes YUI calendar most (all?) of our calendar handler JS Jifty.Utils has a bunch of methods probably redundant with those in jQuery, but we need to check compat with what uses them update libraries jQuery iAutocompleter (and iUtil) jQuery 1.4 http://jquery14.com/day-01/jquery-14#backwards we can replace css_browser_selector and our own browser stuff with jQuery.browser now === Unused (but still useful??) DUBIOUS - rico.js - not even the full library, just corner rounding, and hacked ones at that UNCLEAR - jsTrace.js jifty-1.10518+dfsg.orig/AUTHORS0000644000175000017500000000271711447473535013572 0ustar fsfsIn order of first commit: Jesse Vincent David Glasser Alex Vandiver Thomas Sibley Kevin Riggle Audrey Tang Eric Wilhelm Nelson Elhage Sean E Millichamp Kenichi Ishigaki Chia-Liang Kao Dobrica Pavlinusic Bart Bunting Norman Nunley, Jr. Mark Fowler Liang-Bin Hsueh Wolfgang Kinkeldei Paul Fenwick Edmund von der Burg Yves Agostini Agent Zhang Pawel Murias Kevin Falcone Andrew Sterling Hanenkamp Edgar Whipple Christian Ternus David Brunton Marc Mims Alexander Klink Andreas Koenig sunnavy Shawn M Moore Edward Funnekotter Cornelius Lin Todd Chapman Jason May Stanislav Sinyagin Tomohiro Hosaka Kazuhiro Osawa jifty-1.10518+dfsg.orig/share/0000755000175000017500000000000011625457665013621 5ustar fsfsjifty-1.10518+dfsg.orig/share/po/0000755000175000017500000000000011625457665014237 5ustar fsfsjifty-1.10518+dfsg.orig/share/po/zh_CN.po0000644000175000017500000006377111447473536015613 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2007-08-24 10:33+08\n" "Last-Translator: sunnavy \n" "Language-Team: Simplified Chinese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" "\n" "您 (或自称是您的æŸäºº) è¦æ±‚é‡è®¾ %1 的密ç .\n" "\n" "å¦‚æžœæ‚¨ä¸æƒ³é‡è®¾å¯†ç ï¼Œè¯·å¿½ç•¥è¿™å°ä¿¡\n" "\n" "如果您è¦é‡è®¾å¯†ç ï¼Œè¯·ç‚¹å‡»ä»¥ä¸‹é“¾æŽ¥:\n" "\n" "%2\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" "\n" "您(或自称是您的æŸäººï¼‰åœ¨ %1 申请注册.\n" "\n" "请点击以下链接,以确认您的电å­é‚®ç®±:\n" "\n" "%2\n" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:43 msgid "" " id is 'facebook_link' };\n" " span { _(\"Login to Facebook now to link it with your current account!\") };\n" " a {{ href is $plugin->get_link_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:26 msgid "" " id is 'facebook_login' };\n" " span { _(\"Login to Facebook now to get started!\") };\n" " a {{ href is $plugin->get_login_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "å¯ä½¿ç”¨ !=>< 符å·" #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 #. ($appname, Jifty->config->framework('AdminEmail') msgid "%1 <%2>" msgstr "%1 <%2>" #: lib/Jifty/Action/Record/Search.pm:143 #. ($label) msgid "%1 after" msgstr "%1 晚于" #: lib/Jifty/Action/Record/Search.pm:146 #. ($label) msgid "%1 before" msgstr "%1 早于" #: lib/Jifty/Action/Record/Search.pm:133 #. ($label) msgid "%1 contains" msgstr "%1 包å«" #: msgid "%1 entries" msgstr "å…± %1 æ¡è®°å½•" #: lib/Jifty/Action/Record/Search.pm:166 #. ($label) msgid "%1 greater or equal to" msgstr "%1 至少为" #: lib/Jifty/Action/Record/Search.pm:160 #. ($label) msgid "%1 greater than" msgstr "%1 大于" #: lib/Jifty/Action/Record/Search.pm:121 #. ($label) msgid "%1 is not" msgstr "%1 ä¸ç­‰äºŽ" #: lib/Jifty/Action/Record/Search.pm:136 #. ($label) msgid "%1 lacks" msgstr "%1 ä¸åŒ…å«" #: lib/Jifty/Action/Record/Search.pm:169 #. ($label) msgid "%1 less or equal to" msgstr "%1 至多为" #: lib/Jifty/Action/Record/Search.pm:163 #. ($label) msgid "%1 less than" msgstr "%1 å°äºŽ" #: share/web/templates/__jifty/error/mason_internal_error:31 share/web/templates/__jifty/error/mason_internal_error:35 share/web/templates/__jifty/error/mason_internal_error:39 #. ($path, $line) #. ($file, $line) msgid "%1 line %2" msgstr "%1 第 %2 行" #: lib/Jifty/Plugin/SQLQueries.pm:186 share/web/templates/__jifty/halo:122 #. ($_->[3]) msgid "%1 seconds" msgstr "%1 ç§’" #: lib/Jifty/Action/Record/Search.pm:149 #. ($label) msgid "%1 since" msgstr "%1 自" #: lib/Jifty/Action/Record/Search.pm:152 #. ($label) msgid "%1 until" msgstr "%1 至" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "(ä»»æ„)" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr ". 现已æˆåŠŸç¡®è®¤æ‚¨çš„ç”µå­é‚®ç®±." #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "é‡è®¾å¯†ç çš„链接已å‘é€åˆ°æ‚¨çš„电å­é‚®ç®±." #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 #. ($appname) msgid "A notification from %1!" msgstr "从 %1 逿¥çš„æ¶ˆæ¯!" #: msgid "Actions" msgstr "æ“作" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "管ç†ç•Œé¢" #: lib/Jifty/View/Declare/Page.pm:180 share/web/templates/_elements/wrapper:11 msgid "Administration mode is enabled." msgstr "ç³»ç»Ÿç®¡ç†æ¨¡å¼å¼€å¯ä¸­." #: lib/Jifty/View/Declare/Page.pm:177 share/web/templates/_elements/wrapper:11 msgid "Alert" msgstr "请注æ„" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "系统无法执行此项æ“作, 请ç¨åŽå†è¯•" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "ä»»æ„字段包å«" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:131 msgid "Anyway, the software has logged this error." msgstr "系统已记录该错误." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "" #: msgid "Back to the admin console" msgstr "回到管ç†ç•Œé¢" #: msgid "Back to the application" msgstr "回到应用程åº" #: lib/Jifty/Plugin/SQLQueries.pm:175 share/web/templates/__jifty/halo:120 msgid "Bindings" msgstr "å¿«æ·é”®" #: share/web/templates/helpers/calendar.html:4 #. (_ &>web->current_user->user_object->facebook_name) msgid "Hi %1!" msgstr "" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 #. (DateTime::Locale->load($lang) msgid "Hi, we speak %1." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:31 share/web/templates/_elements/sidebar:4 #. ($u->username) #. (Jifty->web->current_user->username) msgid "Hiya, %1." msgstr "您好, %1." #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "首页" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "How should I display your name to other users?" msgstr "您在本系统中的åå­—?" #: lib/Jifty/Action.pm:1214 msgid "I changed $field for you" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "我也ä¸çŸ¥é“怎么回事." #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "内部错误" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:53 msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "该账å·ä¸å­˜åœ¨." #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:107 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "å·²ç»æœ‰äººä½¿ç”¨äº†è¿™ä¸ªåœ°å€ï¼Œæˆ–许您还有å¦å¤–一个账å·ï¼Ÿ" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "æ‚¨å·²ç»æœ‰äº†ä¸€ä¸ªè´¦å·äº†ï¼Œæˆ–许您是想登录?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "两次输入的密ç ä¸åŒ. å†è¯•一次?" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "您的账å·å·²ç»é€šè¿‡éªŒè¯äº†." #: msgid "Jifty Administrative Console" msgstr "Jifty 管ç†ç•Œé¢" #: msgid "Jifty Developer Documentation Online" msgstr "Jifty åœ¨çº¿å¼€å‘æ–‡æ¡£" #: msgid "Jifty Pod Online" msgstr "Jifty 在线 POD 文档" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "" #: lib/Jifty/View/Declare/Page.pm:198 share/web/templates/_elements/wrapper:18 msgid "Loading..." msgstr "正在加载..." #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:132 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "登录" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "使用密ç ç™»å½•" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "登录!" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:151 msgid "Logout" msgstr "注销" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "忘记密ç ?" #: msgid "Manage %1 records" msgstr "ç®¡ç† %1 记录" #: msgid "Manage records:" msgstr "管ç†è®°å½•:" #: msgid "Manage records: [_1]" msgstr "管ç†è®°å½•: [_1]" #: share/web/templates/__jifty/error/mason_internal_error:1 msgid "Mason error" msgstr "Mason 系统错误" #: msgid "Models" msgstr "模型" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "新密ç " #: lib/Jifty/View/Declare/CRUD.pm:654 msgid "Next Page" msgstr "下一页" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:48 msgid "Nickname" msgstr "昵称" #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "还没有账å·ï¼Ÿæ‚¨å¯ä»¥å¾ˆå®¹æ˜“就注册一个. " #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "没有字段包å«" #: msgid "No items found" msgstr "未找到记录" #: lib/Jifty/View/Declare/CRUD.pm:569 msgid "No items found." msgstr "" #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "没有å¯å¤„ç†çš„请求" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "" #: msgid "Online Documentation" msgstr "在线文档" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "在线文档" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:621 #. ($page, $collection->pager->last_page) msgid "Page %1 of %2" msgstr "第 %1 页, å…± %2 页" #: share/web/templates/__jifty/halo:3 msgid "Page info" msgstr "页é¢ä¿¡æ¯" #: share/web/templates/__jifty/halo:75 msgid "Parent" msgstr "父组件" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "密ç " #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "密ç é•¿åº¦è‡³å°‘为6ä½" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "æƒé™ä¸è¶³" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "请给我们å‘邮件!" #: lib/Jifty/View/Declare/CRUD.pm:643 msgid "Previous Page" msgstr "å‰ä¸€é¡µ" #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Really delete?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "éžå¸¸éžå¸¸æŠ±æ­‰" #: msgid "Record created" msgstr "æˆåŠŸå»ºç«‹è®°å½•." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "è®°ä½æˆ‘?" #: share/web/templates/__jifty/halo:72 #. ($frame->{'render_time'}) msgid "Rendered in %1s" msgstr "页é¢ç”Ÿæˆæ—¶é—´: %1 ç§’" #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "é‡è®¾å¯†ç " #: msgid "Run the action" msgstr "执行动作" #: share/web/templates/__jifty/halo:114 msgid "SQL Statements" msgstr "SQL 语å¥" #: lib/Jifty/View/Declare/CRUD.pm:425 msgid "Save" msgstr "ä¿å­˜" #: msgid "Schema" msgstr "纲è¦" #: lib/Jifty/View/Declare/CRUD.pm:314 msgid "Search" msgstr "查找" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "å‘é€" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "å‘é€é‡è®¾å¯†ç çš„链接" #: msgid "Send a password reminder" msgstr "å‘é€å¯†ç æç¤º" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "注册" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "现在就注册!" #: msgid "Signup" msgstr "注册" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 #. ($msg) msgid "Something bad happened and we couldn't create your account: %1" msgstr "出了一点问题,我们ä¸èƒ½åˆ›å»ºæ‚¨çš„è´¦å·: %1" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Something went awry" msgstr "出了一点岔å­" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:125 share/web/templates/dhandler:1 msgid "Something's not quite right" msgstr "系统错误" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Sorry about this." msgstr "éžå¸¸æŠ±æ­‰" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "" #: lib/Jifty/Action/Record/Execute.pm:55 msgid "Start" msgstr "" #: msgid "Table of Contents" msgstr "目录" #: lib/Jifty/Plugin/Feedback/View.pm:23 #. (Jifty->config->framework('ApplicationName') msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:100 #. ($new_email) msgid "That %1 doesn't look like an email address." msgstr "%1 䏿˜¯åˆæ³•的电å­é‚®ç®±" #: lib/Jifty/Action.pm:1056 msgid "That doesn't look like a correct value" msgstr "字段格å¼é”™è¯¯." #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "䏿˜¯åˆæ³•的电å­é‚®ç®±." #: lib/Jifty/Action/Record.pm:359 msgid "That doesn't look right, but I don't know why" msgstr "字段内容错误." #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:50 msgid "The OpenID '$openid' has been linked to your account." msgstr "" #: lib/Jifty/Action/Record.pm:227 msgid "The passwords you typed didn't match each other" msgstr "密ç ä¸åŒ¹é…." #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "系统执行错误, 请ç¨å€™å†è¯•." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "è®¾ç½®å¯†ç æ—¶å‡ºçŽ°é”™è¯¯." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "" #: msgid "This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records." msgstr "您å¯åˆ©ç”¨æ­¤ç•Œé¢æ¥ç®¡ç†æ•°æ®åº“的内容. 请选择表格åç§°, 进行增删或者编辑." #: msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)." msgstr "如果想ç¦ç”¨ç®¡ç†ç•Œé¢, 请在é…置文件 (etc/config.yml) çš„ \"framework:\" é…置项内加上 \"AdminMode: 0\" å³å¯." #: lib/Jifty/View/Declare/CRUD.pm:533 msgid "Toggle search" msgstr "åˆ‡æ¢æœç´¢é¡µé¢" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:175 share/web/templates/__jifty/error/mason_internal_error:6 msgid "Try again" msgstr "é‡è¯•" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "请ç¨åŽå†è¯•,éžå¸¸æŠ±æ­‰." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "å†è¾“入一次?" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "æˆåŠŸæ›´æ–°é¡¹ç›®." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "" #: share/web/templates/__jifty/halo:96 msgid "Variables" msgstr "å˜é¡¹" #: lib/Jifty.pm:29 msgid "W00t" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "系统已将确认信å‘é€åˆ°æ‚¨çš„电å­é‚®ç®±." #: lib/Jifty/I18N.pm:31 #. ('Bob', 'World') msgid "Welcome %1 to the %2" msgstr "%2, 欢迎æ¥åˆ° %1" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 #. ($user->name) msgid "Welcome back, %1." msgstr "欢迎回æ¥, %1." #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 #. ($appname) msgid "Welcome to %1!" msgstr "欢迎æ¥åˆ° %1!" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 #. (Jifty->config->framework('ApplicationName') msgid "Welcome to %1, %2." msgstr "%2, 欢迎æ¥åˆ° %1" #: msgid "Welcome to %1, %2. " msgstr "%2, 欢迎æ¥åˆ° %1" #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:1 msgid "Welcome to your new Jifty application" msgstr "欢迎光临您崭新的 Jifty 应用程åº" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "该账å·ä¸å­˜åœ¨." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:130 msgid "You got to a page that we don't think exists." msgstr "此页é¢ä¸å­˜åœ¨." #: share/web/templates/dhandler:5 msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "抱歉, 此页é¢ä¸å­˜åœ¨, 系统已记录该错误." #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "您的账å·å·²ç»é€šè¿‡éªŒè¯äº†." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "您忘记了密ç . é‡ç½®å¯†ç çš„链接将被å‘é€åˆ°ä»¥ä¸‹çš„电å­ä¿¡ç®±ä¸­:" #: msgid "You lost your password. A reminder will be send to the following mail:" msgstr "您忘记了密ç . å¯†ç æé†’å°†è¢«å‘é€åˆ°ä»¥ä¸‹çš„电å­ä¿¡ç®±ä¸­:" #: msgid "You may have mistyped your email address or password. Give it another shot." msgstr "您或许输错了电å­é‚®ç®±æˆ–密ç ï¼Œè¯·é‡è¯•." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "您或许输错了电å­é‚®ç®±æˆ–密ç ï¼Œè¯·é‡è¯•." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "" #: lib/Jifty/Action.pm:948 msgid "You need to fill in this field" msgstr "此字段éžç©º." #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:3 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461') msgid "You said you wanted a pony. (Source %1)" msgstr "æ‚¨ä¸æ­£æƒ³è¦ä¸€åŒ¹å°é©¬å—? (å‚è§ %1)" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "您已ç»ç™»å½•了." #: lib/Jifty/Plugin/SkeletonApp/View.pm:34 share/web/templates/_elements/sidebar:6 msgid "You're not currently signed in." msgstr "您目å‰å°šæœªç™»å½•." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 #. (Jifty->web->current_user->user_object->facebook_name) msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "ä¸‹æ¬¡å¼€å¯æµè§ˆå™¨æ—¶, 是å¦ä¿æŒç™»å½•状æ€?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "您的密ç å·²è¢«é‡è®¾. 欢迎回æ¥." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "密ç é•¿åº¦è‡³å°‘为6ä½" #: msgid "asc" msgstr "å‡åº" #: msgid "desc" msgstr "é™åº" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "电å­é‚®ç®±" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Action/Record.pm:452 msgid "no value" msgstr "" #: msgid "text of the link" msgstr "链接文字" #: msgid "text of the link that hides" msgstr "éšè—链接文字" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "釿–°è¾“入密ç " #: lib/Jifty/Action.pm:1174 msgid "warning" msgstr "警告" #: lib/Jifty/Action/Record/Bulk.pm:113 msgid "yatta" msgstr "" jifty-1.10518+dfsg.orig/share/po/jifty.pot0000644000175000017500000004441011447473536016110 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #. ($appname,$confirm_url) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" #. ($appname,$confirm_url) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "" #. ($appname,Jifty->config->framework('AdminEmail')) #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 msgid "%1 <%2>" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:143 msgid "%1 after" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:146 msgid "%1 before" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:133 msgid "%1 contains" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:166 msgid "%1 greater or equal to" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:160 msgid "%1 greater than" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:121 msgid "%1 is not" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:136 msgid "%1 lacks" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:169 msgid "%1 less or equal to" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:163 msgid "%1 less than" msgstr "" #. ($_->[3]) #: lib/Jifty/Plugin/SQLQueries.pm:186 msgid "%1 seconds" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:149 msgid "%1 since" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:152 msgid "%1 until" msgstr "" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "" #. ($appname) #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 msgid "A notification from %1!" msgstr "" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "" #: lib/Jifty/View/Declare/Page.pm:197 msgid "Administration mode is enabled." msgstr "" #: lib/Jifty/View/Declare/Page.pm:194 msgid "Alert" msgstr "" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:115 msgid "Anyway, the software has logged this error." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "" #: lib/Jifty/Plugin/SQLQueries.pm:175 msgid "Bindings" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Cancel" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:94 msgid "Confirmation resent." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:65 msgid "Continue" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:845 msgid "Create" msgstr "" #. (ref($record),$msg) #: lib/Jifty/Action/Record/Create.pm:104 msgid "Create of %1 failed: %2" msgstr "" #: lib/Jifty/Action/Record/Create.pm:131 msgid "Created" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:608 msgid "Default" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:457 msgid "Delete" msgstr "" #: lib/Jifty/Action/Record/Delete.pm:82 msgid "Deleted" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:379 msgid "Edit" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:53 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:32 msgid "Email" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:53 msgid "Email address" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:55 msgid "Email address confirmed?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:182 msgid "Fill in your address below, and we'll send out another confirmation email to you. " msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:27 msgid "For one reason or another, you got to a web page that caused a bit of an error. And then you got to our 'basic' error handler. Which means we haven't written a pretty, easy to understand error message for you just yet. The message we do have is:" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:122 msgid "Go back home..." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:35 msgid "Go for it!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:69 msgid "Hashed Password" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:44 msgid "Head on back home" msgstr "" #. (Jifty->web->current_user->user_object->facebook_name) #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:103 msgid "Hi %1!" msgstr "" #. (DateTime::Locale->load($lang)->native_name) #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 msgid "Hi, we speak %1." msgstr "" #. ($cu->username) #: lib/Jifty/Plugin/SkeletonApp/View.pm:30 msgid "Hiya, %1." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:50 msgid "How should I display your name to other users?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:108 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "" #: lib/Jifty/View/Declare/Page.pm:215 msgid "Loading..." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:156 msgid "Logout" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:774 msgid "Next Page" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "Nickname" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "" #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:689 msgid "No items found." msgstr "" #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "" #. ($page,$collection->pager->last_page) #: lib/Jifty/View/Declare/CRUD.pm:741 msgid "Page %1 of %2" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:763 msgid "Previous Page" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:460 msgid "Really delete?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:438 msgid "Save" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:327 msgid "Search" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:142 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "" #. ($msg) #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Something bad happened and we couldn't create your account: %1" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Something went awry" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:110 msgid "Something's not quite right" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:116 msgid "Sorry about this." msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "" #. (Jifty->config->framework('ApplicationName')) #: lib/Jifty/Plugin/Feedback/View.pm:22 msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "" #. ($new_email) #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:101 msgid "That %1 doesn't look like an email address." msgstr "" #: lib/Jifty/Action.pm:1063 msgid "That doesn't look like a correct value" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "" #: lib/Jifty/Action/Record.pm:362 msgid "That doesn't look right, but I don't know why" msgstr "" #: lib/Jifty/Action/Record.pm:220 msgid "The passwords you typed didn't match each other" msgstr "" #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:653 msgid "Toggle search" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Try again" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "" #. ($user->name) #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 msgid "Welcome back, %1." msgstr "" #. ($appname) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 msgid "Welcome to %1!" msgstr "" #. (Jifty->config->framework('ApplicationName'),$u->name) #. (Jifty->config->framework('ApplicationName'),$record->name) #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 msgid "Welcome to %1, %2." msgstr "" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:114 msgid "You got to a page that we don't think exists." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "" #: lib/Jifty/Action.pm:949 msgid "You need to fill in this field" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:33 msgid "You're not currently signed in." msgstr "" #. (Jifty->web->current_user->user_object->facebook_name) #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:556 msgid "asc" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:565 msgid "desc" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Action/Record.pm:459 msgid "no value" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "" #: lib/Jifty/Action/Record/Bulk.pm:114 msgid "yatta" msgstr "" jifty-1.10518+dfsg.orig/share/po/ro.po0000644000175000017500000006504611447473536015227 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2008-09-05 17:42+(UTC+0200)\n" "Last-Translator: Doru MIHALACHI \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:43 msgid "" " id is 'facebook_link' };\n" " span { _(\"Login to Facebook now to link it with your current account!\") };\n" " a {{ href is $plugin->get_link_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:26 msgid "" " id is 'facebook_login' };\n" " span { _(\"Login to Facebook now to get started!\") };\n" " a {{ href is $plugin->get_login_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "!=>< permis`" #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 #. ($appname, Jifty->config->framework('AdminEmail') msgid "%1 <%2>" msgstr "%1 <%2>" #: lib/Jifty/Action/Record/Search.pm:143 #. ($label) msgid "%1 after" msgstr "%1 după" #: lib/Jifty/Action/Record/Search.pm:146 #. ($label) msgid "%1 before" msgstr "%1 înainte" #: lib/Jifty/Action/Record/Search.pm:133 #. ($label) msgid "%1 contains" msgstr "%1 conÅ£ine" #: lib/Jifty/Action/Record/Search.pm:166 #. ($label) msgid "%1 greater or equal to" msgstr "%1 mai mare sau egal ca" #: lib/Jifty/Action/Record/Search.pm:160 #. ($label) msgid "%1 greater than" msgstr "%1 mai mare decât" #: lib/Jifty/Action/Record/Search.pm:121 #. ($label) msgid "%1 is not" msgstr "%1 nu e" #: lib/Jifty/Action/Record/Search.pm:136 #. ($label) msgid "%1 lacks" msgstr "%1 lipseste" #: lib/Jifty/Action/Record/Search.pm:169 #. ($label) msgid "%1 less or equal to" msgstr "%1 mai mic sau egal ca" #: lib/Jifty/Action/Record/Search.pm:163 #. ($label) msgid "%1 less than" msgstr "%1 mai mic decât" #: share/web/templates/__jifty/error/mason_internal_error:31 share/web/templates/__jifty/error/mason_internal_error:35 share/web/templates/__jifty/error/mason_internal_error:39 #. ($path, $line) #. ($file, $line) msgid "%1 line %2" msgstr "%1 linia %2" #: lib/Jifty/Plugin/SQLQueries.pm:186 share/web/templates/__jifty/halo:122 #. ($_->[3]) msgid "%1 seconds" msgstr "%1 secunde" #: lib/Jifty/Action/Record/Search.pm:149 #. ($label) msgid "%1 since" msgstr "" #: lib/Jifty/Action/Record/Search.pm:152 #. ($label) msgid "%1 until" msgstr "%1 până când" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "(orice)" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "- nimic -" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr ". Adresa dvs. de mail a fost confirmată" #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "V-am trimis un link pentru a resetq parola la adresa dvs. de mail" #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 #. ($appname) msgid "A notification from %1!" msgstr "O notificare de la %1!" #: msgid "Add a comment" msgstr "Adaugă un comentariu" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "Administrare" #: lib/Jifty/View/Declare/Page.pm:180 share/web/templates/_elements/wrapper:11 msgid "Administration mode is enabled." msgstr "Modul de administrare este activat" #: lib/Jifty/View/Declare/Page.pm:177 share/web/templates/_elements/wrapper:11 msgid "Alert" msgstr "Alertă" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "Eroare. ÃŽncercati mai târziu" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "Orice câmp conÅ£ine" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:131 msgid "Anyway, the software has logged this error." msgstr "Oricum, softul a înregistrat aceasta eroare" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "Jeton de Autentificare" #: lib/Jifty/Plugin/SQLQueries.pm:175 share/web/templates/__jifty/halo:120 msgid "Bindings" msgstr "" #: msgid "By %1 %2" msgstr "De %1 %2" #: share/web/templates/helpers/calendar.html:4 #. (_ &>web->current_user->user_object->facebook_name) msgid "Hi %1!" msgstr "Salut %1!" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 #. (DateTime::Locale->load($lang) msgid "Hi, we speak %1." msgstr "Salut, limba folosită: %1." #: lib/Jifty/Plugin/SkeletonApp/View.pm:31 share/web/templates/_elements/sidebar:4 #. ($u->username) #. (Jifty->web->current_user->username) msgid "Hiya, %1." msgstr "Salut, %1." #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "How should I display your name to other users?" msgstr "Numele afiÅŸat celorlalÅ£i utilizatori?" #: lib/Jifty/Action.pm:1214 msgid "I changed $field for you" msgstr "$field a fost modificat" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "Problemă neindentificată." #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "Dacă acest nume de utilisator intră in conflict cu numele existente sau conÅ£ine caractere invalide, va trebui să-l schimbaÅ£i." #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "Eroare internă" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:53 msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "URL OpenID invalid. VerificaÅ£i daca este corect. (@{[$csr->err]})" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "Acest cont pare a fi utilizat deja." #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:107 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "Această adresă pare a fi utilizată de altcineva. AveÅ£i cumva alt cont?" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "Acest OpenID pare a fi utilizat de altcineva." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "Acest cont există deja. DoriÅ£i să vă conectaÅ£i?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "Parolele diferă. ÃŽncercaÅ£i din nou?" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "AÅ£i confirmat deja." #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "Limba" #: lib/Jifty/View/Declare/Page.pm:198 share/web/templates/_elements/wrapper:18 msgid "Loading..." msgstr "Se incarcă" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:132 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "Identificare" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "Conexiunea la Facebook incepe!" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "IdentificaÅ£i-vă în Facebook acum pentru a asocia cu contul curent!" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "Indentificare cu o parolă" #: msgid "Login with your Ldap account" msgstr "Identificare cu un cont Ldap" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "Indeitificare cu OpenID" #: msgid "Login with your ldap account" msgstr "Identificare cu un cont Ldap" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "Identificare!" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:151 msgid "Logout" msgstr "Deconectare" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "AÅ£i uitat parola?" #: share/web/templates/__jifty/error/mason_internal_error:1 msgid "Mason error" msgstr "Eroare Mason" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "Parola nouă" #: lib/Jifty/View/Declare/CRUD.pm:654 msgid "Next Page" msgstr "Pagina următoare" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:48 msgid "Nickname" msgstr "Identitate(nume)" #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "ÃŽncă nu aveÅ£i un cont? E simplu ÅŸi uÅŸor." #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "Nici un câmp(field) nu conÅ£ine" #: lib/Jifty/View/Declare/CRUD.pm:569 msgid "No items found." msgstr "Nicio înregistrare găsită." #: msgid "No one has made a comment yet." msgstr "Niciun comentariu deocamdată." #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "Nicio cerere de tratat" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "Nicio valoare incă" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "DocumentaÅ£ii in linie" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "URL OpenID" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "Verificarea OpenID-ului a eÅŸuat. Se pare că a-Å£i anulat cererea de verificare a OpenIDului." #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "Verificarea OpenID-ului a eÅŸuat: " #: lib/Jifty/View/Declare/CRUD.pm:621 #. ($page, $collection->pager->last_page) msgid "Page %1 of %2" msgstr "Pagina %1 din %2" #: share/web/templates/__jifty/halo:3 msgid "Page info" msgstr "Pagina info" #: share/web/templates/__jifty/halo:75 msgid "Parent" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "Parola" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "Parola trebuie sa fie de minimum ÅŸase caractere" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "AutorizaÅ£ie interzisă" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "ContactaÅ£i-ne prin email, vă rugăm!" #: msgid "Preview" msgstr "Previzualizare" #: lib/Jifty/View/Declare/CRUD.pm:643 msgid "Previous Page" msgstr "Pagina precedentă" #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Really delete?" msgstr "ConfirmaÅ£i ÅŸtergerea?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "Regretăm." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "Memorează?" #: share/web/templates/__jifty/halo:72 #. ($frame->{'render_time'}) msgid "Rendered in %1s" msgstr "Realizat în %1s" #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "Schimbare parolă" #: share/web/templates/__jifty/halo:114 msgid "SQL Statements" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:425 msgid "Save" msgstr "ÃŽnregistrare" #: lib/Jifty/View/Declare/CRUD.pm:314 msgid "Search" msgstr "Căutare" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "Trimitere link pentru schimbarea parolei" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "AÅŸteptă; opiniile dvs.!" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "ÃŽnregistraÅ£i-vă" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "ÃŽnregistraÅ£i-vă pentru a crea un cont!" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 #. ($msg) msgid "Something bad happened and we couldn't create your account: %1" msgstr "Eroare, contul:%1, nu a putut fi creat!" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Something went awry" msgstr "Eroare" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:125 share/web/templates/dhandler:1 msgid "Something's not quite right" msgstr "Ceva nu e corect" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Sorry about this." msgstr "Ne cerem scuze." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "Scuze, datorită unei probleme, nu va pute; crea contul. ÃŽncercaÅ£i mai târziu." #: lib/Jifty/Action/Record/Execute.pm:55 msgid "Start" msgstr "" #: msgid "Submit" msgstr "Trimite" #: lib/Jifty/Plugin/Feedback/View.pm:23 #. (Jifty->config->framework('ApplicationName') msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "ComunicaÅ£i-ne ce e bun, rău ÅŸi ce a-Å£i dori să adăugăm la %1!" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:100 #. ($new_email) msgid "That %1 doesn't look like an email address." msgstr "Această adresa: %1 nu pare a fi o adresă validă." #: lib/Jifty/Action.pm:1056 msgid "That doesn't look like a correct value" msgstr "Această valoare nu pare a fi corectă" #: msgid "That doesn't look like a valid login." msgstr "Acest login nu pare a fi valid." #: msgid "That doesn't look like a valid ticket." msgstr "Nu pare a fi un tichet valid." #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "Nu pare a fi o adresă email." #: lib/Jifty/Action/Record.pm:359 msgid "That doesn't look right, but I don't know why" msgstr "Nu pare corect, dar nu ÅŸtiu cauza" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:50 msgid "The OpenID '$openid' has been linked to your account." msgstr "OpenID-ul '$openid' a fost asociat contului dvs." #: lib/Jifty/Action/Record.pm:227 msgid "The passwords you typed didn't match each other" msgstr "Parolele date nu corespund una cu cealaltă" #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "Datorita unei probleme, cererea dvs. nu a fost finalizată. Vă rugăm incercaÅ£i mai târziu." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "Eroare la schimbarea parolei dvs." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "Eroare ne-repertoriată" #: lib/Jifty/View/Declare/CRUD.pm:533 msgid "Toggle search" msgstr "Căutare" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:175 share/web/templates/__jifty/error/mason_internal_error:6 msgid "Try again" msgstr "ÃŽncercaÅ£i din nou" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "ÃŽncercaÅ£i din nou, mai târziu. Vă cere; scuze." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "ConfirmaÅ£i?" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "Modificare inregistrată" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "" #: share/web/templates/__jifty/halo:96 msgid "Variables" msgstr "Variabile" #: lib/Jifty.pm:29 msgid "W00t" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "Trebuie sa alegeÅ£i un nume de utilizare sau să-l verificaÅ£i pe cel asociat OpenID-ului dvs. Acest nume se va afiÅŸa când puneÅ£i intrebări sau faceti sugestii" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "Un mesaj de confirmare a fost trimis la adresa dvs. email" #: lib/Jifty/I18N.pm:31 #. ('Bob', 'World') msgid "Welcome %1 to the %2" msgstr "Bine aÅ£i venit %1 la %2" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "Bine aÅ£i revenit" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 #. ($user->name) msgid "Welcome back, %1." msgstr "Bine aÅ£i revenit" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 #. ($appname) msgid "Welcome to %1!" msgstr "Bine ai venit %1!" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 #. (Jifty->config->framework('ApplicationName') msgid "Welcome to %1, %2." msgstr "Bine ai venit %1, %2." #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:1 msgid "Welcome to your new Jifty application" msgstr "Bine aÅ£i venit la noua dvs. aplicaÅ£ie Jifty" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "Bine aÅ£i venit, " #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "SunteÅ£i deja conectat" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "Contul dvs. nu exista." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:130 msgid "You got to a page that we don't think exists." msgstr "CăutaÅ£i o pagină caer nu există." #: share/web/templates/dhandler:5 msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "Aceasta pagină nu există. Eroarea a fost inregistrată." #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "Contul dvs. a fost deja confirmat." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "AÅ£i pierdut parola. Un link pentru modificarea parolei va fi trans;is la adresa email următoare:" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "AÅ£i greÅŸit adresa email sau parola. Re-încercaÅ£i." #: msgid "You may have mistyped your login or password. Give it another shot?" msgstr "AÅ£i greÅŸit adresa email sau parola. Re-încercaÅ£i?" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "Trebuie să fiÅ£i conectat pentru a putea asocia contul dvs. utilisator la contul Facebook." #: lib/Jifty/Action.pm:948 msgid "You need to fill in this field" msgstr "Infor;aÅ£ie obligatorie" #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:3 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461') msgid "You said you wanted a pony. (Source %1)" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "SunteÅ£i deja conectat" #: lib/Jifty/Plugin/SkeletonApp/View.pm:34 share/web/templates/_elements/sidebar:6 msgid "You're not currently signed in." msgstr "Nu sunteÅ£i conectat încă." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 #. (Jifty->web->current_user->user_object->facebook_name) msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "Contul dvs. a fost asociat cu contul dvs. Facebook %1!" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "Navigatorul dvs. vă poate memora loginul pentru o conectare ulterioară" #: msgid "Your comment has been added. If it does not immediately appear, it may have been flagged for moderation and should appear shortly." msgstr "Co;entariul dvs. a fost adăugat. Dacă nu apare imediat, este in aÅŸteptare de moderare si va apărea curând." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "Parola dvs. a fost resetată. Bine v-aÅ£i întors." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "Parola trebuie sa conÅ£ină ÅŸase caractere" #: msgid "[%1] Moderate comment: %2" msgstr "[%1] Comentariu moderat: %2" #: msgid "[%1] New comment: %2" msgstr "Nou omentariut: %2" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "adresă email" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Action/Record.pm:452 msgid "no value" msgstr "" #: msgid "publish" msgstr "publicaÅ£i" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "re-scrieÅ£i parola" #: msgid "unpublish" msgstr "nu publicaÅ£i" #: lib/Jifty/Action.pm:1174 msgid "warning" msgstr "atenÅ£ie" #: lib/Jifty/Action/Record/Bulk.pm:113 msgid "yatta" msgstr "" jifty-1.10518+dfsg.orig/share/po/ru.po0000644000175000017500000006315311447473536015232 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Ruslan Zakirov . # #, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.01\n" "POT-Creation-Date: 2007-05-01 03:09+0400\n" "PO-Revision-Date: 2007-05-01 03:09+0400\n" "Last-Translator: Ruslan Zakirov \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:43 msgid "" " id is 'facebook_link' };\n" " span { _(\"Login to Facebook now to link it with your current account!\") };\n" " a {{ href is $plugin->get_link_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:26 msgid "" " id is 'facebook_login' };\n" " span { _(\"Login to Facebook now to get started!\") };\n" " a {{ href is $plugin->get_login_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "допуÑтимы !=><" #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 #. ($appname, Jifty->config->framework('AdminEmail') msgid "%1 <%2>" msgstr "" #: lib/Jifty/Action/Record/Search.pm:143 #. ($label) msgid "%1 after" msgstr "%1 поÑле" #: lib/Jifty/Action/Record/Search.pm:146 #. ($label) msgid "%1 before" msgstr "%1 до" #: lib/Jifty/Action/Record/Search.pm:133 #. ($label) msgid "%1 contains" msgstr "%1 Ñодержит" #: lib/Jifty/Action/Record/Search.pm:166 #. ($label) msgid "%1 greater or equal to" msgstr "%1 больше или равно" #: lib/Jifty/Action/Record/Search.pm:160 #. ($label) msgid "%1 greater than" msgstr "%1 больше чем" #: lib/Jifty/Action/Record/Search.pm:121 #. ($label) msgid "%1 is not" msgstr "%1 не" #: lib/Jifty/Action/Record/Search.pm:136 #. ($label) msgid "%1 lacks" msgstr "%1 не Ñодержит" #: lib/Jifty/Action/Record/Search.pm:169 #. ($label) msgid "%1 less or equal to" msgstr "%1 меньше или равно" #: lib/Jifty/Action/Record/Search.pm:163 #. ($label) msgid "%1 less than" msgstr "%1 меньше чем" #: share/web/templates/__jifty/error/mason_internal_error:31 share/web/templates/__jifty/error/mason_internal_error:35 share/web/templates/__jifty/error/mason_internal_error:39 #. ($path, $line) #. ($file, $line) msgid "%1 line %2" msgstr "%1 Ñтрока %2" #: lib/Jifty/Plugin/SQLQueries.pm:186 share/web/templates/__jifty/halo:122 #. ($_->[3]) msgid "%1 seconds" msgstr "%1 Ñекунд" #: lib/Jifty/Action/Record/Search.pm:149 #. ($label) msgid "%1 since" msgstr "%1 поÑле" #: lib/Jifty/Action/Record/Search.pm:152 #. ($label) msgid "%1 until" msgstr "%1 до" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "(любое)" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr ". Ваш Ð°Ð´Ñ€ÐµÑ Ð±Ñ‹Ð» подтвержден." #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "СÑылка Ð´Ð»Ñ ÑброÑа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð±Ñ‹Ð»Ð° отправлена на ваш почтовый Ñщик." #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 #. ($appname) msgid "A notification from %1!" msgstr "Уведомление от %1!" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "ÐдминиÑтрирование" #: lib/Jifty/View/Declare/Page.pm:180 share/web/templates/_elements/wrapper:11 msgid "Administration mode is enabled." msgstr "Режим админиÑÑ‚Ñ€Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð¾Ð²Ð°Ð½." #: lib/Jifty/View/Declare/Page.pm:177 share/web/templates/_elements/wrapper:11 msgid "Alert" msgstr "Внимание" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "Произошла ошибка. Попробуйте позже" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "Любой поле Ñодержит" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:131 msgid "Anyway, the software has logged this error." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "" #: lib/Jifty/Plugin/SQLQueries.pm:175 share/web/templates/__jifty/halo:120 msgid "Bindings" msgstr "" #: share/web/templates/helpers/calendar.html:4 #. (_ &>web->current_user->user_object->facebook_name) msgid "Hi %1!" msgstr "" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 #. (DateTime::Locale->load($lang) msgid "Hi, we speak %1." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:31 share/web/templates/_elements/sidebar:4 #. ($u->username) #. (Jifty->web->current_user->username) msgid "Hiya, %1." msgstr "Ðлоха, %1." #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "How should I display your name to other users?" msgstr "Как Ð²Ð°Ñ Ð¿Ñ€ÐµÐ´ÑтавлÑть другим пользователÑм?" #: lib/Jifty/Action.pm:1214 msgid "I changed $field for you" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "Я не уверен, как Ñто произошло." #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:53 msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "КажетÑÑ Ð² ÑиÑтеме нет Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем." #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:107 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "Кто другой уже иÑпользует Ñтот адреÑ. Может быть у Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ?" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "Видимо у Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ. Возможно вы хотите войти?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "Ð’Ñ‹ ввели разные пароли в оба полÑ. Может еще разок?" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "Ð’Ñ‹ уже подтверждали" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "" #: lib/Jifty/View/Declare/Page.pm:198 share/web/templates/_elements/wrapper:18 msgid "Loading..." msgstr "Загрузка..." #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:132 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "Вход" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:151 msgid "Logout" msgstr "Выход" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "Забыли пароль?" #: share/web/templates/__jifty/error/mason_internal_error:1 msgid "Mason error" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "Ðовый пароль" #: lib/Jifty/View/Declare/CRUD.pm:654 msgid "Next Page" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:48 msgid "Nickname" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "Ðет учетной запиÑи? Это быÑтро и легко. " #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:569 msgid "No items found." msgstr "" #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "Online документациÑ" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:621 #. ($page, $collection->pager->last_page) msgid "Page %1 of %2" msgstr "" #: share/web/templates/__jifty/halo:3 msgid "Page info" msgstr "Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñтранице" #: share/web/templates/__jifty/halo:75 msgid "Parent" msgstr "Родитель" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "Пароль" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "Пароль должен быть не менее шеÑти Ñимфолов" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "ДоÑтуп запрещен" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:643 msgid "Previous Page" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Really delete?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "Очень Ñожалеем." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "Запомнить?" #: share/web/templates/__jifty/halo:72 #. ($frame->{'render_time'}) msgid "Rendered in %1s" msgstr "Сгенерировано за %1 Ñек." #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "" #: share/web/templates/__jifty/halo:114 msgid "SQL Statements" msgstr "SQL запроÑÑ‹" #: lib/Jifty/View/Declare/CRUD.pm:425 msgid "Save" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:314 msgid "Search" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "Отправить" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "Отправить ÑÑылку ÑброÑа паролÑ" #: msgid "Send a password reminder" msgstr "Отправить напоминание паролÑ" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "ЗарегиÑтроватьÑÑ" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "ЗавеÑти учетную запиÑÑŒ!" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 #. ($msg) msgid "Something bad happened and we couldn't create your account: %1" msgstr "Что-то неправильное ÑлучилоÑÑŒ и мы не Ñмогли Ñоздать вашу учетную запиÑÑŒ: %1" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Something went awry" msgstr "Что-то пошло наперекоÑÑк" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:125 share/web/templates/dhandler:1 msgid "Something's not quite right" msgstr "Что-то не ÑовÑем верно" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Sorry about this." msgstr "Сожалеем об Ñтом." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "" #: lib/Jifty/Action/Record/Execute.pm:55 msgid "Start" msgstr "" #: lib/Jifty/Plugin/Feedback/View.pm:23 #. (Jifty->config->framework('ApplicationName') msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:100 #. ($new_email) msgid "That %1 doesn't look like an email address." msgstr "Строка %1 не похожа на Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ñ‡Ñ‚Ñ‹" #: lib/Jifty/Action.pm:1056 msgid "That doesn't look like a correct value" msgstr "Ðе похоже на допуÑтимое значение" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "Ðе похоже на почтовый адреÑ" #: lib/Jifty/Action/Record.pm:359 msgid "That doesn't look right, but I don't know why" msgstr "Ðеправильно, но неизвеÑтно почему" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:50 msgid "The OpenID '$openid' has been linked to your account." msgstr "" #: lib/Jifty/Action/Record.pm:227 msgid "The passwords you typed didn't match each other" msgstr "Введенные пароли не Ñовпадают" #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "Во Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа произошла ошибка. ПожалуйÑта попробуйте позже." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "Ðе получилоÑÑŒ уÑтановить пароль." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:533 msgid "Toggle search" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:175 share/web/templates/__jifty/error/mason_internal_error:6 msgid "Try again" msgstr "Попробовать еще" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "Попробуйте еще позже. Мы очень-очень Ñожалеем." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "Введите еще раз" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "Обновленно" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "" #: share/web/templates/__jifty/halo:96 msgid "Variables" msgstr "Переменные" #: lib/Jifty.pm:29 msgid "W00t" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "Мы поÑлали Ñообщение Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð½Ð° ваш Ñлектронный адреÑ." #: lib/Jifty/I18N.pm:31 #. ('Bob', 'World') msgid "Welcome %1 to the %2" msgstr "" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 #. ($user->name) msgid "Welcome back, %1." msgstr "Рады Ð²Ð°Ñ Ð²Ð¸Ð´ÐµÑ‚ÑŒ Ñнова, %1." #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 #. ($appname) msgid "Welcome to %1!" msgstr "Добро пожаловать на Ñайт %1!" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 #. (Jifty->config->framework('ApplicationName') msgid "Welcome to %1, %2." msgstr "Добро пожаловать на Ñайт %1, %2." #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:1 msgid "Welcome to your new Jifty application" msgstr "Добро пожаловать в ваше новое Jifty-приложение" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "Ð’Ñ‹ не ÑущеÑтвуете." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:130 msgid "You got to a page that we don't think exists." msgstr "Ð’Ñ‹ поÑлали на Ñтраницу, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ ÑущеÑтвует." #: share/web/templates/dhandler:5 msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "Ð’Ñ‹ уже подтверждали учетную запиÑÑŒ." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "Ð’Ñ‹ забыли пароль. СÑылка Ð´Ð»Ñ ÑброÑа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð±ÑƒÐ´ÐµÑ‚ отправлена на адреÑ: %1" #: msgid "You lost your password. A reminder will be send to the following mail:" msgstr "Ð’Ñ‹ забыли пароль. Ðапоминание будет отправлено на адреÑ: %1" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "Должно быть вы ввели неправильно Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ пароль. Попробуйте еще разок." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "" #: lib/Jifty/Action.pm:948 msgid "You need to fill in this field" msgstr "Ð’Ñ‹ должны заполнить Ñто поле" #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:3 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461') msgid "You said you wanted a pony. (Source %1)" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "Ð’Ñ‹ уже вошли." #: lib/Jifty/Plugin/SkeletonApp/View.pm:34 share/web/templates/_elements/sidebar:6 msgid "You're not currently signed in." msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 #. (Jifty->web->current_user->user_object->facebook_name) msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "Ваш браузер может запомнить ваш логин за ваÑ" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "ваш пароль был Ñброшен. Мы рады Ð²Ð°Ñ Ñнова видеть." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "Ваш пароль должен ÑоÑтоÑть из шеÑти иÑмволов минимум" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ñ‡Ñ‚Ñ‹" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Action/Record.pm:452 msgid "no value" msgstr "" #: msgid "text of the link" msgstr "текÑÑ‚ ÑÑылки" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "введите ваг пароль Ñнова" #: lib/Jifty/Action.pm:1174 msgid "warning" msgstr "предупреждение" #: lib/Jifty/Action/Record/Bulk.pm:113 msgid "yatta" msgstr "" jifty-1.10518+dfsg.orig/share/po/ja.po0000644000175000017500000007226411447473536015201 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kenichi Ishigaki \n" "Language-Team: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #. ($appname,$confirm_url) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" "\n" "%1 用ã®ãƒ‘スワードをリセットã—ã¾ã™ã€‚\n" "\n" "ã‚‚ã—ã“ã®ãƒ¡ãƒ¼ãƒ«ã«å¿ƒå½“ãŸã‚ŠãŒãªãã€ãƒ‘スワードをリセットã™ã‚‹\n" "å¿…è¦ãŒãªã„å ´åˆã¯ç„¡è¦–ã—ã¦ãã ã•ã„。\n" "\n" "本当ã«ãƒªã‚»ãƒƒãƒˆã™ã‚‹å ´åˆã¯ä¸‹ã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ãã ã•ã„。\n" "\n" "%2\n" #. ($appname,$confirm_url) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" "\n" "%1 ã¸ã®ã”登録ã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚\n" "\n" "ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒæ­£ã—ã„ã‹ç¢ºèªã•ã›ã¦ã„ãŸã ãã¾ã™ã€‚下ã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ãã ã•ã„。\n" "\n" "%2\n" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "! = > < ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“" #. ($appname,Jifty->config->framework('AdminEmail')) #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 msgid "%1 <%2>" msgstr "%1 <%2>" #. ($label) #: lib/Jifty/Action/Record/Search.pm:143 msgid "%1 after" msgstr "%1 より後" #. ($label) #: lib/Jifty/Action/Record/Search.pm:146 msgid "%1 before" msgstr "%1 よりå‰" #. ($label) #: lib/Jifty/Action/Record/Search.pm:133 msgid "%1 contains" msgstr "%1 ã‚’å«ã‚€" #: msgid "%1 entries" msgstr "%1 ä»¶" #. ($label) #: lib/Jifty/Action/Record/Search.pm:166 msgid "%1 greater or equal to" msgstr "%1 ã¨åŒã˜ã‹ãれ以上" #. ($label) #: lib/Jifty/Action/Record/Search.pm:160 msgid "%1 greater than" msgstr "%1 より大ãã„" #. ($label) #: lib/Jifty/Action/Record/Search.pm:121 msgid "%1 is not" msgstr "%1 以外" #. ($label) #: lib/Jifty/Action/Record/Search.pm:136 msgid "%1 lacks" msgstr "%1 ã‚’å«ã¾ãªã„" #. ($label) #: lib/Jifty/Action/Record/Search.pm:169 msgid "%1 less or equal to" msgstr "%1 ã¨åŒã˜ã‹ãれ以下" #. ($label) #: lib/Jifty/Action/Record/Search.pm:163 msgid "%1 less than" msgstr "%1 よりå°ã•ã„" #: msgid "%1 line %2" msgstr "%1 %2行目" #. ($_->[3]) #: lib/Jifty/Plugin/SQLQueries.pm:186 msgid "%1 seconds" msgstr "%1 ç§’" #. ($label) #: lib/Jifty/Action/Record/Search.pm:149 msgid "%1 since" msgstr "%1 ã¨åŒã˜ã‹ãれ以é™" #. ($label) #: lib/Jifty/Action/Record/Search.pm:152 msgid "%1 until" msgstr "%1 ã¨åŒã˜ã‹ãれ以å‰" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "(指定ãªã—)" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "- ãªã— -" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr "メールアドレスã®ç¢ºèªãŒå®Œäº†ã—ã¾ã—ãŸã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "ãŠä½¿ã„ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒ‘スワードをリセットã™ã‚‹ãƒªãƒ³ã‚¯ã‚’é€ä¿¡ã—ã¾ã—ãŸã€‚" #. ($appname) #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 msgid "A notification from %1!" msgstr "%1 ã‹ã‚‰ã®ãŠçŸ¥ã‚‰ã›ã§ã™!" #: msgid "Actions" msgstr "æ“作" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "管ç†" #: lib/Jifty/View/Declare/Page.pm:197 msgid "Administration mode is enabled." msgstr "管ç†ãƒ¢ãƒ¼ãƒ‰ãŒæœ‰åйã«ãªã£ã¦ã„ã¾ã™ã€‚" #: lib/Jifty/View/Declare/Page.pm:194 msgid "Alert" msgstr "注æ„" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ãå¾…ã£ã¦ã‹ã‚‰å†åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "検索ã—ãŸã„文字列" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:115 msgid "Anyway, the software has logged this error." msgstr "エラーã¯è¨˜éŒ²ã—ã¾ã—ãŸã€‚" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³" #: msgid "Back to the admin console" msgstr "管ç†ç”»é¢ã«æˆ»ã‚‹" #: msgid "Back to the application" msgstr "ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã«æˆ»ã‚‹" #: lib/Jifty/Plugin/SQLQueries.pm:175 msgid "Bindings" msgstr "ãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°" #: msgid "Calendar" msgstr "カレンダー" #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Cancel" msgstr "キャンセル" #: msgid "Children" msgstr "å­" #: msgid "Close window" msgstr "é–‰ã˜ã‚‹" #: msgid "Confirm delete?" msgstr "本当ã«å‰Šé™¤ã—ã¾ã™ã‹?" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:94 msgid "Confirmation resent." msgstr "確èªãƒ¡ãƒ¼ãƒ«ã‚’å†é€ã—ã¾ã—ãŸã€‚" #: lib/Jifty/Plugin/OpenID/View.pm:65 msgid "Continue" msgstr "次" #: lib/Jifty/View/Declare/CRUD.pm:845 msgid "Create" msgstr "作æˆ" #. (ref($record),$msg) #: lib/Jifty/Action/Record/Create.pm:104 msgid "Create of %1 failed: %2" msgstr "%1 ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %2" #: lib/Jifty/Action/Record/Create.pm:131 msgid "Created" msgstr "作æˆã—ã¾ã—ãŸ" #: msgid "Database Administration" msgstr "データベース管ç†" #: lib/Jifty/View/Declare/CRUD.pm:608 msgid "Default" msgstr "デフォルト" #: lib/Jifty/View/Declare/CRUD.pm:457 msgid "Delete" msgstr "削除" #: lib/Jifty/Action/Record/Delete.pm:82 msgid "Deleted" msgstr "削除ã—ã¾ã—ãŸ" #: lib/Jifty/View/Declare/CRUD.pm:379 msgid "Edit" msgstr "編集" #: msgid "Edit %1" msgstr "%1 を編集" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:53 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:32 msgid "Email" msgstr "メール" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:53 msgid "Email address" msgstr "メールアドレス" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:55 msgid "Email address confirmed?" msgstr "ç¢ºèªæ¸ˆ?" #: lib/Jifty/Plugin/Authentication/Password/View.pm:182 msgid "Fill in your address below, and we'll send out another confirmation email to you. " msgstr "メールアドレスをã”記入ãã ã•ã„。å†åº¦ç¢ºèªãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã™ã€‚" #: msgid "Foo cannot contain -, *, +, or ?." msgstr "-ã€*ã€+ã€?ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。" #: msgid "Foo cannot contain uppercase letters." msgstr "大文字ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。" #: msgid "Foo values are always in lowercase." msgstr "ã‹ãªã‚‰ãšå°æ–‡å­—ã§è¨˜å…¥ã—ã¦ãã ã•ã„。" #: msgid "For one reason or another, you got to a web page that caused a bit of an error. And then you got to our 'basic' error handler. Which means we haven't written a pretty, easy to understand error message for you just yet. The message we do have is :" msgstr "ãªã‚“らã‹ã®ç†ç”±ã§ãƒšãƒ¼ã‚¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ç¾æ™‚点ã§ã¯ã‚ã‹ã‚Šã‚„ã™ã„綺麗ãªã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã§ãã¾ã›ã‚“。実際ã®ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯æ¬¡ã®é€šã‚Šã§ã™: " #: lib/Jifty/Plugin/ErrorTemplates/View.pm:27 msgid "For one reason or another, you got to a web page that caused a bit of an error. And then you got to our 'basic' error handler. Which means we haven't written a pretty, easy to understand error message for you just yet. The message we do have is:" msgstr "ãªã‚“らã‹ã®ç†ç”±ã§ãƒšãƒ¼ã‚¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ç¾æ™‚点ã§ã¯ã‚ã‹ã‚Šã‚„ã™ã„綺麗ãªã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã§ãã¾ã›ã‚“。実際ã®ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯æ¬¡ã®é€šã‚Šã§ã™: " #: lib/Jifty/Plugin/ErrorTemplates/View.pm:122 msgid "Go back home..." msgstr "ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã«æˆ»ã‚‹â€¦" #: lib/Jifty/Plugin/OpenID/View.pm:35 msgid "Go for it!" msgstr "登録ã™ã‚‹!" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:69 msgid "Hashed Password" msgstr "パスワードãƒãƒƒã‚·ãƒ¥" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:44 msgid "Head on back home" msgstr "ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã«æˆ»ã‚‹" #: msgid "Hello, %1!" msgstr "%1 ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯!" #. (Jifty->web->current_user->user_object->facebook_name) #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:103 msgid "Hi %1!" msgstr "%1 ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯!" #. (DateTime::Locale->load($lang)->native_name) #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 msgid "Hi, we speak %1." msgstr "ã„ã¾ã®è¨€èªžã¯ %1 ã§ã™" #. ($cu->username) #: lib/Jifty/Plugin/SkeletonApp/View.pm:30 msgid "Hiya, %1." msgstr "%1 ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯" #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "ホーム" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:50 msgid "How should I display your name to other users?" msgstr "ã»ã‹ã®ãƒ¦ãƒ¼ã‚¶ã«å…¬é–‹ã™ã‚‹åå‰ã‚’決ã‚ã¦ãã ã•ã„。" #: msgid "I changed $field for you" msgstr "$fieldを変更ã—ã¾ã—ãŸ" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "原因ã¯ä¸æ˜Žã§ã™ã€‚" #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "ユーザåãŒæ—¢ã«ç™»éŒ²ã•れã¦ã„ã‚‹å ´åˆã€ã¾ãŸã¯åˆ©ç”¨ã§ããªã„文字ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã¯æ–°ã—ã„ユーザåを登録ã—ã¦ã„ãŸã ãã¾ã™ã€‚" #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "Livejournalãªã©ã®OpenIDã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ãŠæŒã¡ã®å ´åˆã¯ã€ã‚µã‚¤ãƒ³ã‚¢ãƒƒãƒ—ã¯ä¸è¦ã§ã™ã€‚ログインã—ã¦ãã ã•ã„。" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "内部エラー" #: msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "OpenID URLãŒæ­£ã—ãã‚りã¾ã›ã‚“。ã”確èªãã ã•ã„。(@{[$csr->err]})" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "ãã®ã‚ˆã†ãªã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯å­˜åœ¨ã—ãªã„よã†ã§ã™ã€‚" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:108 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "ãã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯æ—¢ã«ä½¿ã‚れã¦ã„るよã†ã§ã™ã€‚別ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ãŠæŒã¡ã§ã¯ã‚りã¾ã›ã‚“ã‹?" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "ãã®OpenIDã¯æ—¢ã«ä½¿ã‚れã¦ã„るよã†ã§ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "æ—¢ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ãŠæŒã¡ã®ã‚ˆã†ã§ã™ã€‚ログインã—ã¦ãã ã•ã„。" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "パスワードãŒä¸€è‡´ã—ã¾ã›ã‚“。もã†ä¸€åº¦å…¥åŠ›ã—ã¦ãã ã•ã„。" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "ç¢ºèªæ¸ˆã¿ã®ã‚ˆã†ã§ã™ã€‚" #: msgid "Jifty Developer Documentation Online" msgstr "開発者å‘ã‘オンラインドキュメント" #: msgid "Jifty Pod Online" msgstr "オンラインドキュメント" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "言語" #: lib/Jifty/View/Declare/Page.pm:215 msgid "Loading..." msgstr "読込ã¿ä¸­â€¦" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "ログイン" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "Facebookã‚’å§‹ã‚よã†!" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "ãŠä½¿ã„ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’Facebookã«ãƒªãƒ³ã‚¯ã•ã›ã¾ã—ょã†!" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "パスワードã§ãƒ­ã‚°ã‚¤ãƒ³" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "OpenIDã§ãƒ­ã‚°ã‚¤ãƒ³" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "ログイン!" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:156 msgid "Logout" msgstr "ログアウト" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "パスワードをãŠå¿˜ã‚Œã§ã™ã‹?" #: msgid "Mason error" msgstr "Mason エラー" #: msgid "Models" msgstr "モデル" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "æ–°ã—ã„パスワード" #: lib/Jifty/View/Declare/CRUD.pm:774 msgid "Next Page" msgstr "次ã®ãƒšãƒ¼ã‚¸" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "Nickname" msgstr "ニックãƒãƒ¼ãƒ " #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "登録ã¯ãŠæ¸ˆã¿ã§ã™ã‹?" #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "排除ã—ãŸã„文字列" #: msgid "No items found" msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" #: lib/Jifty/View/Declare/CRUD.pm:689 msgid "No items found." msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "処ç†ã§ãるリクエストãŒã‚りã¾ã›ã‚“" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "値ãŒã‚りã¾ã›ã‚“" #: msgid "Online Documentation" msgstr "オンラインドキュメント" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "オンラインドキュメント" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "OpenID URL" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "OpenIDã®ç¢ºèªã«å¤±æ•—ã—ã¾ã—ãŸã€‚確èªã‚’キャンセルã•れã¾ã›ã‚“ã§ã—ãŸã‹ã€‚" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "OpenIDã®ç¢ºèªã«å¤±æ•—ã—ã¾ã—ãŸ: " #. ($page,$collection->pager->last_page) #: lib/Jifty/View/Declare/CRUD.pm:741 msgid "Page %1 of %2" msgstr "%1 / %2 ページ" #: msgid "Page info" msgstr "ページ情報" #: msgid "Parent" msgstr "親" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "パスワード" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã¯æœ€ä½Ž6文字以上ã«ã—ã¦ãã ã•ã„" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "権é™ãŒã‚りã¾ã›ã‚“" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "メールをãŠé€ã‚Šãã ã•ã„!" #: lib/Jifty/View/Declare/CRUD.pm:763 msgid "Previous Page" msgstr "å‰ã®ãƒšãƒ¼ã‚¸" #: lib/Jifty/View/Declare/CRUD.pm:460 msgid "Really delete?" msgstr "本当ã«å‰Šé™¤ã—ã¾ã™ã‹?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "本当ã«ç”³ã—訳ãªã„ã§ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "記憶ã—ã¾ã™ã‹?" #: msgid "Rendered in %1s" msgstr "æç”»æ™‚é–“: %1ç§’" #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "パスワードをリセットã™ã‚‹" #: msgid "Run the action" msgstr "実行" #: msgid "SQL Statements" msgstr "SQLæ–‡" #: lib/Jifty/View/Declare/CRUD.pm:438 msgid "Save" msgstr "ä¿å­˜" #: msgid "Schema" msgstr "スキーマ" #: lib/Jifty/View/Declare/CRUD.pm:327 msgid "Search" msgstr "検索" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "é€ä¿¡" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "パスワードをリセットã™ã‚‹URLã‚’é€ä¿¡ã™ã‚‹" #: msgid "Send a password reminder" msgstr "通知メールをé€ä¿¡ã™ã‚‹" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "ã”æ„è¦‹ã”æ„Ÿæƒ³ã‚’ãŠå¯„ã›ãã ã•ã„!" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:142 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "サインアップ" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "サインアップã™ã‚‹" #. ($msg) #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Something bad happened and we couldn't create your account: %1" msgstr "å•題ãŒç™ºç”Ÿã—ãŸãŸã‚アカウントを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ: %1" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Something went awry" msgstr "å•題ãŒç™ºç”Ÿã—ã¾ã—ãŸ" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:110 msgid "Something's not quite right" msgstr "åŽŸå› ä¸æ˜Žã®ã‚¨ãƒ©ãƒ¼ã§ã™" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:116 msgid "Sorry about this." msgstr "申ã—訳ãªã„ã§ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "å•題ãŒç™ºç”Ÿã—ãŸãŸã‚ã€ãƒ¦ãƒ¼ã‚¶ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚ãŠæ‰‹æ•°ã§ã™ãŒã‚ã¨ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。" #: msgid "Table of Contents" msgstr "目次" #. (Jifty->config->framework('ApplicationName')) #: lib/Jifty/Plugin/Feedback/View.pm:22 msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "%1ã¸ã®ã”æ„見ã€ã”感想ã€ã”è¦æœ›ã‚’ãŠå¯„ã›ãã ã•ã„。" #. ($new_email) #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:101 msgid "That %1 doesn't look like an email address." msgstr "%1ã¯æ­£ã—ã„メールアドレスã§ã¯ãªã„よã†ã§ã™ã€‚" #: lib/Jifty/Action.pm:1063 msgid "That doesn't look like a correct value" msgstr "値ãŒä¸é©åˆ‡ãªã‚ˆã†ã§ã™" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "æ­£ã—ã„メールアドレスã§ã¯ãªã„よã†ã§ã™ã€‚" #: lib/Jifty/Action/Record.pm:362 msgid "That doesn't look right, but I don't know why" msgstr "åŽŸå› ä¸æ˜Žã®ã‚¨ãƒ©ãƒ¼ã§ã™" #: msgid "The OpenID '$openid' has been linked to your account." msgstr "OpenID '$openid'ã‚’ãŠä½¿ã„ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒªãƒ³ã‚¯ã•ã›ã¾ã—ãŸã€‚" #: lib/Jifty/Action/Record.pm:220 msgid "The passwords you typed didn't match each other" msgstr "パスワードãŒä¸€è‡´ã—ã¾ã›ã‚“" #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "リクエストã®å‡¦ç†ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚ã¨ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "パスワードã®è¨­å®šä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "ã“ã®ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ã¿ãªã•ã‚“ã«ã¯ã‚ã¾ã‚Šæ„味ãŒãªã„ã‹ã‚‚ã—れã¾ã›ã‚“ãŒã€ä½•ã‚‚ãªã„よりã¯å¤šå°‘ãªã‚Šã¨ã‚‚何ãŒèµ·ã“ã£ã¦ã„ã‚‹ã‹ãŠçŸ¥ã‚‰ã›ã—ãŸæ–¹ãŒå®‰å¿ƒã—ã¦ã„ãŸã ã‘ã‚‹ã¨æ€ã£ã¦ã„ã¾ã™ã€‚ã“ã®ã‚¨ãƒ©ãƒ¼ã¯è¨˜éŒ²ã—ã¾ã—ãŸã®ã§ã€ä»Šåº¦ã¯ã‚ã‹ã‚Šã‚„ã™ã„メッセージを用æ„ã—ãŸã‚Šå•題を解決ã§ãるよã†ã«ã„ãŸã—ã¾ã™ã€‚" #: msgid "This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records." msgstr "ã“ã“ã§ã¯ Jifty データベースã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’管ç†ã§ãã¾ã™ã€‚下ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ†ãƒ¼ãƒ–ルãŒä¸€è¦§ã•れã¦ã„ã‚‹ã¯ãšã§ã™ã®ã§ã€è‡ªç”±ã«è¡¨ç¤ºãƒ»ä½œæˆãƒ»å‰Šé™¤ãƒ»ä¿®æ­£ã—ã¦ãã ã•ã„。" #: msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)." msgstr "ã“ã®ç®¡ç†ç”»é¢ã‚’無効ã«ã™ã‚‹ã«ã¯ã€è¨­å®šãƒ•ァイル(etc/config.yml)㮠\"framework:\" ã®é …ç›®ã®ä¸‹ã« \"AdminMode: 0\" を追加ã—ã¦ãã ã•ã„。" #: lib/Jifty/View/Declare/CRUD.pm:653 msgid "Toggle search" msgstr "検索ã®åˆ‡ã‚Šæ›¿ãˆ" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Try again" msgstr "ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„ã€‚ãŠæ‰‹æ•°ã‚’ãŠã‹ã‘ã—ã¦ç”³ã—訳ãªã„ã§ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "ã‚‚ã†ä¸€åº¦å…¥åŠ›ã—ã¦ãã ã•ã„。" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "æ›´æ–°ã—ã¾ã—ãŸ" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "ユーザå" #: msgid "Variables" msgstr "変数" #: msgid "W00t" msgstr "OK" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "ユーザåを設定ã™ã‚‹ã‹ã€ãŠä½¿ã„ã®OpenIDã«é–¢é€£ã¥ã‘られãŸãƒ¦ãƒ¼ã‚¶åã‚’ã™ãã«ç¢ºèªã—ã¦ãã ã•ã„。ã“ã®ãƒ¦ãƒ¼ã‚¶åã¯è³ªå•ã‚„ææ¡ˆã‚’ã™ã‚‹ã¨ãã«è¡¨ç¤ºã•れã¾ã™" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "ãŠä½¿ã„ã®ãƒ¡ãƒ¼ãƒ«ãƒœãƒƒã‚¯ã‚¹ã«ç¢ºèªã®ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã—ãŸã€‚" #: msgid "Welcome %1 to the %2" msgstr "%1ã•ã‚“ã€%2ã¸ã‚ˆã†ã“ã" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "ãŠã‹ãˆã‚Šãªã•ã„" #. ($user->name) #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 msgid "Welcome back, %1." msgstr "%1ã•ã‚“ã€ãŠã‹ãˆã‚Šãªã•ã„" #. ($appname) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 msgid "Welcome to %1!" msgstr "%1ã¸ã‚ˆã†ã“ã!" #. (Jifty->config->framework('ApplicationName'),$u->name) #. (Jifty->config->framework('ApplicationName'),$record->name) #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 msgid "Welcome to %1, %2." msgstr "%2ã•ã‚“ã€%1ã¸ã‚ˆã†ã“ã" #: msgid "Welcome to your new Jifty application" msgstr "Jifty ã®æ–°è¦ã‚¢ãƒ—リケーションã¸ã‚ˆã†ã“ã" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "よã†ã“ã" #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "ログイン済ã¿ã§ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "ãã®ã‚ˆã†ãªãƒ¦ãƒ¼ã‚¶ã¯å­˜åœ¨ã—ã¾ã›ã‚“。" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:114 msgid "You got to a page that we don't think exists." msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã¯å­˜åœ¨ã—ã¾ã›ã‚“。" #: msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã¯å­˜åœ¨ã—ã¾ã›ã‚“。エラーã¨ã—ã¦è¨˜éŒ²ã—ã¦ãŠãã¾ã—ãŸã€‚ã”ä¸ä¾¿ã‚’ãŠè©«ã³ã„ãŸã—ã¾ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "アカウントã¯ç¢ºèªæ¸ˆã¿ã§ã™ã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "アカウントã®ç¢ºèªãŒæ¸ˆã‚“ã§ã„ã¾ã›ã‚“" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "パスワードをリセットã—ã¾ã™ã€‚ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«é€šçŸ¥ã‚’é€ã‚Šã¾ã™:" #: msgid "You lost your password. A reminder will be send to the following mail:" msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«é€šçŸ¥ã‚’é€ã‚Šã¾ã™:" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "メールアドレスã‹ãƒ‘スワードãŒé–“é•ã£ã¦ã„るよã†ã§ã™ã€‚ã‚‚ã†ä¸€åº¦å…¥åŠ›ã—ã¦ãã ã•ã„。" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "Facebookアカウントã¨ãƒªãƒ³ã‚¯ã•ã›ã‚‹ã«ã¯ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" #: lib/Jifty/Action.pm:949 msgid "You need to fill in this field" msgstr "必須項目ã§ã™" #: msgid "You said you wanted a pony. (Source %1)" msgstr "ã“ã‚“ãªã®ãŒæ¬²ã—ã‹ã£ãŸã‚“ã§ã—ょã†ï¼Ÿï¼ˆå‡ºå…¸ï¼š%1)" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "ログイン済ã¿ã§ã™ã€‚" #: lib/Jifty/Plugin/SkeletonApp/View.pm:33 msgid "You're not currently signed in." msgstr "サインインã—ã¦ã„ã¾ã›ã‚“。" #. (Jifty->web->current_user->user_object->facebook_name) #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "アカウントをFacebookã®ãƒ¦ãƒ¼ã‚¶%1ã«ãƒªãƒ³ã‚¯ã•ã›ã¾ã—ãŸ!" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "ãŠä½¿ã„ã®ãƒ–ラウザã¯ãƒ­ã‚°ã‚¤ãƒ³ã‚’記憶ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "パスワードをリセットã—ã¾ã—ãŸã€‚ãŠã‹ãˆã‚Šãªã•ã„" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã¯æœ€ä½Ž6文字以上ã«ã—ã¦ãã ã•ã„" #: lib/Jifty/View/Declare/CRUD.pm:556 msgid "asc" msgstr "昇順" #: lib/Jifty/View/Declare/CRUD.pm:565 msgid "desc" msgstr "é™é †" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "メールアドレス" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "。ã”ä¸ä¾¿ã‚’ãŠã‹ã‘ã—ã¦ç”³ã—訳ãªã„ã§ã™ã€‚" #: lib/Jifty/Action/Record.pm:459 msgid "no value" msgstr "値ãŒã‚りã¾ã›ã‚“" #: msgid "text of the link" msgstr "リンクテキスト" #: msgid "text of the link that hides" msgstr "éš ã™ãƒªãƒ³ã‚¯ãƒ†ã‚­ã‚¹ãƒˆ" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "ã‚‚ã†ä¸€åº¦ãƒ‘スワードを入力ã—ã¦ãã ã•ã„" #: msgid "warning" msgstr "警告" #: lib/Jifty/Action/Record/Bulk.pm:114 msgid "yatta" msgstr "OK!" jifty-1.10518+dfsg.orig/share/po/en.po0000644000175000017500000005165411447473536015211 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:43 msgid "" " id is 'facebook_link' };\n" " span { _(\"Login to Facebook now to link it with your current account!\") };\n" " a {{ href is $plugin->get_link_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:26 msgid "" " id is 'facebook_login' };\n" " span { _(\"Login to Facebook now to get started!\") };\n" " a {{ href is $plugin->get_login_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "" #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 #. ($appname, Jifty->config->framework('AdminEmail') msgid "%1 <%2>" msgstr "" #: lib/Jifty/Action/Record/Search.pm:143 #. ($label) msgid "%1 after" msgstr "" #: lib/Jifty/Action/Record/Search.pm:146 #. ($label) msgid "%1 before" msgstr "" #: lib/Jifty/Action/Record/Search.pm:133 #. ($label) msgid "%1 contains" msgstr "" #: lib/Jifty/Action/Record/Search.pm:166 #. ($label) msgid "%1 greater or equal to" msgstr "" #: lib/Jifty/Action/Record/Search.pm:160 #. ($label) msgid "%1 greater than" msgstr "" #: lib/Jifty/Action/Record/Search.pm:121 #. ($label) msgid "%1 is not" msgstr "" #: lib/Jifty/Action/Record/Search.pm:136 #. ($label) msgid "%1 lacks" msgstr "" #: lib/Jifty/Action/Record/Search.pm:169 #. ($label) msgid "%1 less or equal to" msgstr "" #: lib/Jifty/Action/Record/Search.pm:163 #. ($label) msgid "%1 less than" msgstr "" #: share/web/templates/__jifty/error/mason_internal_error:31 share/web/templates/__jifty/error/mason_internal_error:35 share/web/templates/__jifty/error/mason_internal_error:39 #. ($path, $line) #. ($file, $line) msgid "%1 line %2" msgstr "" #: lib/Jifty/Plugin/SQLQueries.pm:186 share/web/templates/__jifty/halo:122 #. ($_->[3]) msgid "%1 seconds" msgstr "" #: lib/Jifty/Action/Record/Search.pm:149 #. ($label) msgid "%1 since" msgstr "" #: lib/Jifty/Action/Record/Search.pm:152 #. ($label) msgid "%1 until" msgstr "" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "" #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 #. ($appname) msgid "A notification from %1!" msgstr "" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "" #: lib/Jifty/View/Declare/Page.pm:180 share/web/templates/_elements/wrapper:11 msgid "Administration mode is enabled." msgstr "" #: lib/Jifty/View/Declare/Page.pm:177 share/web/templates/_elements/wrapper:11 msgid "Alert" msgstr "" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:131 msgid "Anyway, the software has logged this error." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "" #: lib/Jifty/Plugin/SQLQueries.pm:175 share/web/templates/__jifty/halo:120 msgid "Bindings" msgstr "" #: share/web/templates/helpers/calendar.html:4 #. (_ &>web->current_user->user_object->facebook_name) msgid "Hi %1!" msgstr "" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 #. (DateTime::Locale->load($lang) msgid "Hi, we speak %1." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:31 share/web/templates/_elements/sidebar:4 #. ($u->username) #. (Jifty->web->current_user->username) msgid "Hiya, %1." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "How should I display your name to other users?" msgstr "" #: lib/Jifty/Action.pm:1214 msgid "I changed $field for you" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:53 msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:107 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "" #: lib/Jifty/View/Declare/Page.pm:198 share/web/templates/_elements/wrapper:18 msgid "Loading..." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:132 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:151 msgid "Logout" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "" #: share/web/templates/__jifty/error/mason_internal_error:1 msgid "Mason error" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:654 msgid "Next Page" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:48 msgid "Nickname" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "" #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:569 msgid "No items found." msgstr "" #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:621 #. ($page, $collection->pager->last_page) msgid "Page %1 of %2" msgstr "" #: share/web/templates/__jifty/halo:3 msgid "Page info" msgstr "" #: share/web/templates/__jifty/halo:75 msgid "Parent" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:643 msgid "Previous Page" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Really delete?" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "" #: share/web/templates/__jifty/halo:72 #. ($frame->{'render_time'}) msgid "Rendered in %1s" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "" #: share/web/templates/__jifty/halo:114 msgid "SQL Statements" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:425 msgid "Save" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:314 msgid "Search" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 #. ($msg) msgid "Something bad happened and we couldn't create your account: %1" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Something went awry" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:125 share/web/templates/dhandler:1 msgid "Something's not quite right" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Sorry about this." msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "" #: lib/Jifty/Action/Record/Execute.pm:55 msgid "Start" msgstr "" #: lib/Jifty/Plugin/Feedback/View.pm:23 #. (Jifty->config->framework('ApplicationName') msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:100 #. ($new_email) msgid "That %1 doesn't look like an email address." msgstr "" #: lib/Jifty/Action.pm:1056 msgid "That doesn't look like a correct value" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "" #: lib/Jifty/Action/Record.pm:359 msgid "That doesn't look right, but I don't know why" msgstr "" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:50 msgid "The OpenID '$openid' has been linked to your account." msgstr "" #: lib/Jifty/Action/Record.pm:227 msgid "The passwords you typed didn't match each other" msgstr "" #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:533 msgid "Toggle search" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:175 share/web/templates/__jifty/error/mason_internal_error:6 msgid "Try again" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "" #: share/web/templates/__jifty/halo:96 msgid "Variables" msgstr "" #: lib/Jifty.pm:29 msgid "W00t" msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "" #: lib/Jifty/I18N.pm:31 #. ('Bob', 'World') msgid "Welcome %1 to the %2" msgstr "" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 #. ($user->name) msgid "Welcome back, %1." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 #. ($appname) msgid "Welcome to %1!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 #. (Jifty->config->framework('ApplicationName') msgid "Welcome to %1, %2." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:1 msgid "Welcome to your new Jifty application" msgstr "" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "" #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:130 msgid "You got to a page that we don't think exists." msgstr "" #: share/web/templates/dhandler:5 msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "" #: lib/Jifty/Action.pm:948 msgid "You need to fill in this field" msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:3 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461') msgid "You said you wanted a pony. (Source %1)" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "" #: lib/Jifty/Plugin/SkeletonApp/View.pm:34 share/web/templates/_elements/sidebar:6 msgid "You're not currently signed in." msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 #. (Jifty->web->current_user->user_object->facebook_name) msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Action/Record.pm:452 msgid "no value" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "" #: lib/Jifty/Action.pm:1174 msgid "warning" msgstr "" #: lib/Jifty/Action/Record/Bulk.pm:113 msgid "yatta" msgstr "" jifty-1.10518+dfsg.orig/share/po/zh_TW.po0000644000175000017500000006630611447473536015642 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kang-min LIu \n" "Language-Team: Traditional Chinese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" "\n" "您 (或自稱是您的æŸäºº) è¦æ±‚é‡è¨­æ‚¨åœ¨ %1 的密碼.\n" "\n" "å¦‚æžœæ‚¨ä¸æƒ³é‡è¨­å¯†ç¢¼, 請忽略這å°ä¿¡.\n" "\n" "è‹¥è¦é‡è¨­å¯†ç¢¼, 請點擊以下éˆçµ:\n" "\n" "%2\n" #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 #. ($appname,$confirm_url) msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" "\n" "您 (或自稱是您的æŸäºº) 在 %1 申請註冊.\n" "\n" "請點擊以下éˆçµ, ä»¥ç¢ºèªæ‚¨çš„電郵帳號:\n" "\n" "%2\n" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:43 msgid "" " id is 'facebook_link' };\n" " span { _(\"Login to Facebook now to link it with your current account!\") };\n" " a {{ href is $plugin->get_link_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:26 msgid "" " id is 'facebook_login' };\n" " span { _(\"Login to Facebook now to get started!\") };\n" " a {{ href is $plugin->get_login_url };\n" " img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' " msgstr "" #: lib/Jifty/Action/Record/Search.pm:172 msgid "!=>< allowed" msgstr "å¯ä½¿ç”¨ !=>< 符號" #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 #. ($appname, Jifty->config->framework('AdminEmail') msgid "%1 <%2>" msgstr "%1 <%2>" #: lib/Jifty/Action/Record/Search.pm:143 #. ($label) msgid "%1 after" msgstr "%1 晚於" #: lib/Jifty/Action/Record/Search.pm:146 #. ($label) msgid "%1 before" msgstr "%1 æ—©æ–¼" #: lib/Jifty/Action/Record/Search.pm:133 #. ($label) msgid "%1 contains" msgstr "%1 包å«" #: msgid "%1 entries" msgstr "å…± %1 ç­†" #: lib/Jifty/Action/Record/Search.pm:166 #. ($label) msgid "%1 greater or equal to" msgstr "%1 至少為" #: lib/Jifty/Action/Record/Search.pm:160 #. ($label) msgid "%1 greater than" msgstr "%1 大於" #: lib/Jifty/Action/Record/Search.pm:121 #. ($label) msgid "%1 is not" msgstr "%1 ä¸ç­‰æ–¼" #: lib/Jifty/Action/Record/Search.pm:136 #. ($label) msgid "%1 lacks" msgstr "%1 ä¸åŒ…å«" #: lib/Jifty/Action/Record/Search.pm:169 #. ($label) msgid "%1 less or equal to" msgstr "%1 至多為" #: lib/Jifty/Action/Record/Search.pm:163 #. ($label) msgid "%1 less than" msgstr "%1 å°æ–¼" #: share/web/templates/__jifty/error/mason_internal_error:31 share/web/templates/__jifty/error/mason_internal_error:35 share/web/templates/__jifty/error/mason_internal_error:39 #. ($path, $line) #. ($file, $line) msgid "%1 line %2" msgstr "%1 第 %2 列" #: lib/Jifty/Plugin/SQLQueries.pm:186 share/web/templates/__jifty/halo:122 #. ($_->[3]) msgid "%1 seconds" msgstr "%1 ç§’" #: lib/Jifty/Action/Record/Search.pm:149 #. ($label) msgid "%1 since" msgstr "%1 自" #: lib/Jifty/Action/Record/Search.pm:152 #. ($label) msgid "%1 until" msgstr "%1 至" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "(ä¸é™)" #: lib/Jifty/Plugin/AutoReference.pm:95 msgid "- none -" msgstr "- ç„¡ -" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr ". ç¾å·²æˆåŠŸç¢ºèªæ‚¨çš„電郵地å€." #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "é‡è¨­å¯†ç¢¼çš„通知信已é€åˆ°æ‚¨çš„電郵地å€." #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 #. ($appname) msgid "A notification from %1!" msgstr "%1 æŽä¾†çš„訊æ¯!" #: msgid "Actions" msgstr "æ“作" #: msgid "Add a comment" msgstr "發表迴響" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "管ç†ä»‹é¢" #: lib/Jifty/View/Declare/Page.pm:180 share/web/templates/_elements/wrapper:11 msgid "Administration mode is enabled." msgstr "ç³»çµ±ç®¡ç†æ¨¡å¼é–‹å•Ÿä¸­." #: lib/Jifty/View/Declare/Page.pm:177 share/web/templates/_elements/wrapper:11 msgid "Alert" msgstr "請注æ„" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "系統無法執行此項æ“作, è«‹ç¨å¾Œå†è©¦" #: lib/Jifty/Action/Record/Search.pm:177 msgid "Any field contains" msgstr "ä»»æ„æ¬„ä½åŒ…å«" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:131 msgid "Anyway, the software has logged this error." msgstr "總之,軟體已經記錄此錯誤。" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "驗證碼" #: msgid "Back to the admin console" msgstr "回到管ç†ä»‹é¢" #: msgid "Back to the application" msgstr "回到應用程å¼" #: lib/Jifty/Plugin/SQLQueries.pm:175 share/web/templates/__jifty/halo:120 msgid "Bindings" msgstr "快速éµ" #: share/web/templates/helpers/calendar.html:4 #. (_ &>web->current_user->user_object->facebook_name) msgid "Hi %1!" msgstr "你好 %1!" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:44 #. (DateTime::Locale->load($lang) msgid "Hi, we speak %1." msgstr "嗨,我們ç¾åœ¨èªª %1" #: lib/Jifty/Plugin/SkeletonApp/View.pm:31 share/web/templates/_elements/sidebar:4 #. ($u->username) #. (Jifty->web->current_user->username) msgid "Hiya, %1." msgstr "%1 您好." #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "首é " #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "How should I display your name to other users?" msgstr "您在本系統的代號" #: lib/Jifty/Action.pm:1214 msgid "I changed $field for you" msgstr "我為你修改了 $field" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "我ä¸å¤ªç¢ºå®šé€™å¦‚何發生" #: lib/Jifty/Plugin/OpenID/View.pm:59 msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "如果æä¾›çš„使用者åç¨±èˆ‡ç¾æœ‰çš„使用者å稱產生è¡çªæˆ–者包å«äº†ä¸åˆæ³•字元,你需è¦è¼¸å…¥ä¸€å€‹æ–°çš„å稱" #: lib/Jifty/Plugin/OpenID/View.pm:27 msgid "If you have a Livejournal or other OpenID account, you don't even need to sign up. Just log in." msgstr "如果你有使用 LiveJournal 或者其他 OpenID 帳號,你ä¸éœ€è¦è¨»å†Šï¼Œè«‹ç›´æŽ¥ç™»å…¥å³å¯ã€‚" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "內部錯誤" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:53 msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "䏿­£ç¢ºçš„ OpenID ç¶²å€. (@{[$csr->err]})" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "這個帳號並ä¸å­˜åœ¨" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:107 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "已經有其他人使用這個電郵地å€. 您是å¦å·²ç¶“有其他帳號了?" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:45 msgid "It looks like someone is already using that OpenID." msgstr "已經有其他人使用此 OpenID." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "您似乎已經有帳號了.按這裡登入." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "兩組密碼ä¸åŒ.è«‹å†è©¦ä¸€æ¬¡." #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "您的帳號已通éŽèªè­‰." #: msgid "Jifty Administrative Console" msgstr "Jifty 管ç†ä»‹é¢" #: msgid "Jifty Developer Documentation Online" msgstr "Jifty 線上開發文件" #: msgid "Jifty Pod Online" msgstr "Jifty 線上 POD 文件" #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:12 msgid "Language" msgstr "語言" #: lib/Jifty/View/Declare/Page.pm:198 share/web/templates/_elements/wrapper:18 msgid "Loading..." msgstr "è«‹ç¨å€™..." #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:132 lib/Jifty/Plugin/Authentication/Password/View.pm:88 msgid "Login" msgstr "登入" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:24 msgid "Login to Facebook now to get started!" msgstr "登入 Facebook 並開始使用!" #: lib/Jifty/Plugin/Authentication/Facebook/View.pm:41 msgid "Login to Facebook now to link it with your current account!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:82 msgid "Login with a password" msgstr "使用密碼登入" #: lib/Jifty/Plugin/OpenID/View.pm:17 msgid "Login with your OpenID" msgstr "以您的 OpenID 登入" #: lib/Jifty/Plugin/Authentication/Password/View.pm:57 msgid "Login!" msgstr "登入!" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:151 msgid "Logout" msgstr "登出" #: lib/Jifty/Plugin/Authentication/Password/View.pm:90 msgid "Lost your password?" msgstr "忘記密碼了?" #: msgid "Manage %1 records" msgstr "ç®¡ç† %1 記錄" #: msgid "Manage records:" msgstr "管ç†è¨˜éŒ„:" #: share/web/templates/__jifty/error/mason_internal_error:1 msgid "Mason error" msgstr "Mason 系統錯誤" #: msgid "Models" msgstr "模型" #: lib/Jifty/Plugin/Authentication/Password/View.pm:115 msgid "New password" msgstr "新的密碼" #: lib/Jifty/View/Declare/CRUD.pm:654 msgid "Next Page" msgstr "下一é " #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:48 msgid "Nickname" msgstr "暱稱" #: lib/Jifty/Plugin/Authentication/Password/View.pm:79 msgid "No account yet? It's quick and easy. " msgstr "還沒有註冊帳號嗎? " #: lib/Jifty/Action/Record/Search.pm:178 msgid "No field contains" msgstr "沒有欄ä½åŒ…å«" #: msgid "No items found" msgstr "未找到記錄" #: lib/Jifty/View/Declare/CRUD.pm:569 msgid "No items found." msgstr "未找到記錄" #: msgid "No one has made a comment yet." msgstr "尚無人發表評論" #: lib/Jifty/Web.pm:305 msgid "No request to handle" msgstr "沒有å¯è™•ç†çš„è¦æ±‚" #: lib/Jifty/Plugin/UUID/Widget.pm:37 msgid "No value yet" msgstr "" #: msgid "Online Documentation" msgstr "線上文件" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26 msgid "Online docs" msgstr "線上文件" #: lib/Jifty/Plugin/OpenID/Action/AuthenticateOpenID.pm:27 msgid "OpenID URL" msgstr "OpenID ç¶²å€" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:48 msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "OpenID 確èªå¤±æ•—ã€‚æ‚¨ä¼¼ä¹Žä¸­é€”å–æ¶ˆäº†ç¢ºèª OpenID çš„è¦æ±‚。" #: lib/Jifty/Plugin/OpenID/Action/VerifyOpenID.pm:57 msgid "OpenID verification failed: " msgstr "OpenID 確èªå¤±æ•—: " #: lib/Jifty/View/Declare/CRUD.pm:621 #. ($page, $collection->pager->last_page) msgid "Page %1 of %2" msgstr "第 %1 é , å…± %2 é " #: share/web/templates/__jifty/halo:3 msgid "Page info" msgstr "é é¢è³‡è¨Š" #: share/web/templates/__jifty/halo:75 msgid "Parent" msgstr "上層元件" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "密碼" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "å¯†ç¢¼è‡³å°‘éœ€è¦æœ‰å…­å€‹å­—" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:182 lib/Jifty/Action/Record/Update.pm:195 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "權é™ä¸è¶³." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "請寫信通知我們!" #: msgid "Preview" msgstr "é è¦½" #: lib/Jifty/View/Declare/CRUD.pm:643 msgid "Previous Page" msgstr "上一é " #: lib/Jifty/View/Declare/CRUD.pm:447 msgid "Really delete?" msgstr "真的è¦åˆªé™¤å—Žï¼Ÿ" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "å二è¬åˆ†æŠ±æ­‰." #: msgid "Record created" msgstr "æˆåŠŸå»ºç«‹é …ç›®." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "è¨˜ä½æˆ‘?" #: share/web/templates/__jifty/halo:72 #. ($frame->{'render_time'}) msgid "Rendered in %1s" msgstr "é é¢ç¹ªè£½æ™‚é–“: %1 ç§’" #: lib/Jifty/Plugin/Authentication/Password/View.pm:108 lib/Jifty/Plugin/Authentication/Password/View.pm:112 msgid "Reset lost password" msgstr "é‡è¨­å¯†ç¢¼" #: msgid "Run the action" msgstr "執行動作" #: share/web/templates/__jifty/halo:114 msgid "SQL Statements" msgstr "SQL 陳述å¼" #: lib/Jifty/View/Declare/CRUD.pm:425 msgid "Save" msgstr "儲存" #: msgid "Schema" msgstr "ç¶±è¦" #: lib/Jifty/View/Declare/CRUD.pm:314 msgid "Search" msgstr "æœå°‹" #: lib/Jifty/Plugin/Authentication/Password/View.pm:152 msgid "Send" msgstr "寄出" #: lib/Jifty/Plugin/Authentication/Password/View.pm:147 msgid "Send a link to reset your password" msgstr "寄é€é‡è¨­å¯†ç¢¼çš„éˆçµ" #: msgid "Send a password reminder" msgstr "é‡è¨­å¯†ç¢¼" #: lib/Jifty/Plugin/Feedback/View.pm:21 msgid "Send us feedback!" msgstr "給我們回應ï¼" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:42 lib/Jifty/Plugin/Authentication/Password/View.pm:47 msgid "Sign up" msgstr "註冊" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "Sign up for an account!" msgstr "ç¾åœ¨å°±è¨»å†Š!" #: msgid "Signup" msgstr "註冊" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 #. ($msg) msgid "Something bad happened and we couldn't create your account: %1" msgstr "發生了ä¸å¥½çš„事以至於我們無法建立你的帳號: %1" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:149 msgid "Something went awry" msgstr "å¥½åƒæžéŒ¯ä»€éº¼äº†" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:125 share/web/templates/dhandler:1 msgid "Something's not quite right" msgstr "系統錯誤" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132 msgid "Sorry about this." msgstr "éžå¸¸æŠ±æ­‰." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm:62 msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "ä¸å¥½æ„æ€ï¼Œç™¼ç”Ÿäº†å¥‡æ€ªçš„事(我們無法替您建立帳號)。請ç¨å€™å†è©¦ã€‚" #: lib/Jifty/Action/Record/Execute.pm:55 msgid "Start" msgstr "é–‹å§‹" #: msgid "Submit" msgstr "é€å‡º" #: msgid "Table of Contents" msgstr "目錄" #: lib/Jifty/Plugin/Feedback/View.pm:23 #. (Jifty->config->framework('ApplicationName') msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "è«‹å‘Šè¨´æˆ‘å€‘çš„å¥½å£žï¼Œæˆ–æ˜¯ä½ æƒ³è¦ %1 æä¾›çš„功能ï¼" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:100 #. ($new_email) msgid "That %1 doesn't look like an email address." msgstr "那個 %1 看起來ä¸å¤ªåƒæ˜¯å€‹é›»å­éƒµä»¶åœ°å€ã€‚" #: lib/Jifty/Action.pm:1056 msgid "That doesn't look like a correct value" msgstr "æ¬„ä½æ ¼å¼éŒ¯èª¤." #: msgid "That doesn't look like a valid login." msgstr "看起來ä¸åƒæ˜¯æœ‰å€‹æœ‰æ•ˆçš„登入帳號" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "看起來ä¸åƒæ˜¯é›»å­éƒµä»¶åœ°å€" #: lib/Jifty/Action/Record.pm:359 msgid "That doesn't look right, but I don't know why" msgstr "欄ä½å…§å®¹éŒ¯èª¤." #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:50 msgid "The OpenID '$openid' has been linked to your account." msgstr "OpenID '$openid' 已經連çµè‡³æ‚¨çš„帳號。" #: lib/Jifty/Action/Record.pm:227 msgid "The passwords you typed didn't match each other" msgstr "兩組密碼ä¸ç¬¦åˆ." #: lib/Jifty/Web.pm:426 msgid "There was an error completing the request. Please try again later." msgstr "系統執行錯誤, è«‹ç¨å€™å†è©¦." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "在設置您的密碼時發生了錯誤。" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "" #: msgid "This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records." msgstr "您å¯åˆ©ç”¨æ­¤ä»‹é¢ä¾†ç®¡ç†è³‡æ–™åº«çš„內容. 請點é¸è¡¨æ ¼å稱, 進行增刪åŠç·¨è¼¯." #: msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)." msgstr "如欲åœç”¨ç®¡ç†ä»‹é¢, 請在設定檔 (etc/config.yml) çš„ \"framework:\" 設定內加上 \"AdminMode: 0\" å³å¯." #: lib/Jifty/View/Declare/CRUD.pm:533 msgid "Toggle search" msgstr "åˆ‡æ›æœå°‹ç•«é¢" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:175 share/web/templates/__jifty/error/mason_internal_error:6 msgid "Try again" msgstr "å†è©¦ä¸€ä¸‹" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "è«‹ç¨å€™å†è©¦ã€‚è«‹æŽ¥å—æˆ‘們å二è¬åˆ†æ­‰æ„。" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "è«‹å†è¼¸å…¥ä¸€æ¬¡" #: lib/Jifty/Action/Record/Update.pm:222 msgid "Updated" msgstr "æˆåŠŸæ›´æ–°é …ç›®." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "使用者å稱" #: share/web/templates/__jifty/halo:96 msgid "Variables" msgstr "變數" #: lib/Jifty.pm:29 msgid "W00t" msgstr "喔耶" #: lib/Jifty/Plugin/OpenID/View.pm:53 msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "系統已將確èªä¿¡å¯„é€åˆ°æ‚¨çš„電郵信箱." #: lib/Jifty/I18N.pm:31 #. ('Bob', 'World') msgid "Welcome %1 to the %2" msgstr "歡迎 %1 蒞臨 %2" #: lib/Jifty/Plugin/OpenID/Dispatcher.pm:66 msgid "Welcome back, " msgstr "歡迎回來," #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 #. ($user->name) msgid "Welcome back, %1." msgstr "歡迎回來, %1." #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 #. ($appname) msgid "Welcome to %1!" msgstr "歡迎光臨 %1!" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 #. (Jifty->config->framework('ApplicationName') msgid "Welcome to %1, %2." msgstr "歡迎光臨 %1, %2!" #: msgid "Welcome to %1, %2. " msgstr "歡迎光臨 %1, %2. " #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:1 msgid "Welcome to your new Jifty application" msgstr "歡迎光臨您嶄新的 Jifty 應用程å¼" #: lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm:94 msgid "Welcome, " msgstr "歡迎," #: lib/Jifty/Plugin/OpenID/View.pm:42 msgid "You already logged in." msgstr "您已經登入了。" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "您ä¸å­˜åœ¨." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:130 msgid "You got to a page that we don't think exists." msgstr "æ­¤é é¢ä¸å­˜åœ¨." #: share/web/templates/dhandler:5 msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "抱歉, æ­¤é é¢ä¸å­˜åœ¨, 系統已留下紀錄." #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "您已經確èªéŽé€™å€‹å¸³è™Ÿã€‚" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "æ‚¨é‚„æœªç¢ºèªæ‚¨çš„帳號。" #: lib/Jifty/Plugin/Authentication/Password/View.pm:148 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "您忘記密碼了.我們會寄é€ä¸€å€‹é‡è¨­å¯†ç¢¼çš„連çµåˆ°ä¸‹é¢çš„電郵地å€:" #: msgid "You lost your password. A reminder will be send to the following mail:" msgstr "您忘記密碼了.我們會寄é€ä¸€ä»½æç¤ºåˆ°ä¸‹é¢çš„電郵地å€:" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "ä½ å¯èƒ½æ‰“錯了電郵或密碼.è«‹å†è©¦ä¸€æ¬¡" #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:40 msgid "You must be logged in to link your user to your Facebook account." msgstr "" #: lib/Jifty/Action.pm:948 msgid "You need to fill in this field" msgstr "此欄ä½ä¸èƒ½ç•™ç©º." #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:3 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461') msgid "You said you wanted a pony. (Source %1)" msgstr "您å¯ä¸æ­£æ˜¯æƒ³è¦ä¸€åŒ¹å°é¦¬å—Ž? (åƒè¦‹ %1)" #: lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "You're already logged in." msgstr "您已經登入了." #: lib/Jifty/Plugin/SkeletonApp/View.pm:34 share/web/templates/_elements/sidebar:6 msgid "You're not currently signed in." msgstr "您目å‰å°šæœªç™»å…¥." #: lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm:72 #. (Jifty->web->current_user->user_object->facebook_name) msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "下次開啟ç€è¦½å™¨æ™‚, 是å¦ä¿ç•™æ‚¨çš„登入狀態?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "æˆåŠŸé‡è¨­æ‚¨çš„密碼. 歡迎回來." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "您的密碼必須至少有六個字" #: msgid "asc" msgstr "éžå¢ž" #: msgid "desc" msgstr "éžæ¸›" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "電郵地å€" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Action/Record.pm:452 msgid "no value" msgstr "無資料" #: msgid "text of the link" msgstr "é€£çµæ–‡å­—" #: msgid "text of the link that hides" msgstr "éš±è—é€£çµæ–‡å­—" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "è«‹å†æ¬¡éµå…¥æ‚¨çš„密碼" #: lib/Jifty/Action.pm:1174 msgid "warning" msgstr "警告" #: lib/Jifty/Action/Record/Bulk.pm:113 msgid "yatta" msgstr "太棒了!" jifty-1.10518+dfsg.orig/share/po/fr.po0000644000175000017500000010046211447473536015206 0ustar fsfs# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # AGOSTINI Yves , 2006. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2006-10-24 18:00+ZONE\n" "PO-Revision-Date: 2009-06-30 23:17+ZONE\n" "Last-Translator: AGOSTINI Yves \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: msgid "" "\n" "View Comment: %1\n" "\n" "On Post: %2\n" "Subject: %3\n" "From: %4\n" "Date: %5\n" "\n" "%6\n" msgstr "" "\n" "Commentaire: %1\n" "\n" "A propos de: %2\n" "Sujet: %3\n" "Par: %4\n" "Sujet: %5\n" "\n" "%6\n" #. ($appname,$confirm_url) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38 msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "request to reset your password for %1.\n" "\n" "If you don't want to reset your password just ignore this message.\n" "\n" "To reset your password, click on the link below:\n" "\n" "%2\n" msgstr "" "\n" "Vous avez demandé le changement de votre mot de passe sur %1.\n" "\n" "Pour effectuer ce changement cliquez sur le lien ci-dessous :\n" "\n" "%2\n" "\n" "Si vous ne voulez pas changer votre mot de passe, ignorez simplement ce message.\n" #. ($appname,$confirm_url) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41 msgid "" "\n" "You're getting this message because you (or somebody claiming to be you)\n" "wants to use %1. \n" "\n" "We need to make sure that we got your email address right. Click on the link below to get started:\n" "\n" "%2\n" msgstr "" "\n" "Ce message vous permet de confirmer votre adresse mail, si vous voulez utiliser\n" " %1\n" "\n" "Pour confirmer votre adresse mail, cliquez sur le lien ci-dessous :\n" "\n" "%2\n" #: lib/Jifty/Action/Record/Search.pm:176 msgid "!=>< allowed" msgstr "!=>< autorisés" #. (Jifty->config->framework('ApplicationName') #. (Jifty->config->framework('ApplicationName')) #: lib/Jifty/Plugin/REST/Dispatcher.pm:333 msgid "%1 - REST API" msgstr "" #. ($appname, Jifty->config->framework('AdminEmail') #. ($appname,Jifty->config->framework('AdminEmail')) #: lib/Jifty/Notification.pm:108 lib/Jifty/Notification.pm:125 msgid "%1 <%2>" msgstr "" #. ($label) #: lib/Jifty/Action/Record/Search.pm:147 msgid "%1 after" msgstr "%1 après" #. ($label) #: lib/Jifty/Action/Record/Search.pm:150 msgid "%1 before" msgstr "%1 avant" #. ($label) #: lib/Jifty/Action/Record/Search.pm:137 msgid "%1 contains" msgstr "%1 contient" #: msgid "%1 entries" msgstr "%1 enregistements" #. ($label) #: lib/Jifty/Action/Record/Search.pm:170 msgid "%1 greater or equal to" msgstr "%1 supérieur ou égal à" #. ($label) #: lib/Jifty/Action/Record/Search.pm:164 msgid "%1 greater than" msgstr "%1 supérieur à" #. ($label) #: lib/Jifty/Action/Record/Search.pm:125 msgid "%1 is not" msgstr "%1 n'est pas" #. ($label) #: lib/Jifty/Action/Record/Search.pm:140 msgid "%1 lacks" msgstr "%1 ne contient pas" #. ($label) #: lib/Jifty/Action/Record/Search.pm:173 msgid "%1 less or equal to" msgstr "%1 inférieur ou égal" #. ($label) #: lib/Jifty/Action/Record/Search.pm:167 msgid "%1 less than" msgstr "%1 inférieur à" #: msgid "%1 line %2" msgstr "%1 ligne %2" #: msgid "%1 seconds" msgstr "%1 secondes" #. ($label) #: lib/Jifty/Action/Record/Search.pm:153 msgid "%1 since" msgstr "%1 depuis le" #. ($label) #: lib/Jifty/Action/Record/Search.pm:156 msgid "%1 until" msgstr "%1 depuis" #. ($appname) #: lib/Jifty/Plugin/SetupWizard/View.pm:217 msgid "%1 works with a number of different databases. MySQL, PostgreSQL, and SQLite are all supported. You should choose the database that you or your local database administrator knows best." msgstr "" #. ($step+1, $step_info->{header}) #. ($step+1,$step_info->{header}) #: lib/Jifty/Plugin/SetupWizard/View.pm:28 msgid "%1. %2" msgstr "" #. ($count, $seconds) #. ($count,$seconds) #: lib/Jifty/Plugin/SQLQueries.pm:51 msgid "%quant(%1,query,queries) taking %2s" msgstr "" #. ($seconds, $query) #. ($seconds,$query) #: lib/Jifty/Plugin/SQLQueries/View.pm:15 msgid "(%1s) %2" msgstr "" #: lib/Jifty/Action/Record/Search.pm:81 msgid "(any)" msgstr "" #: msgid "- none -" msgstr "- aucun -" #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58 msgid ". Your email address has now been confirmed." msgstr ". Votre adresse mail est confirmée." #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96 msgid "A link to reset your password has been sent to your email account." msgstr "Une URL pour changer votre mots de passe, vous a été transmis par mail. " #. ($appname) #: lib/Jifty/Notification.pm:110 lib/Jifty/Notification.pm:127 msgid "A notification from %1!" msgstr "Message de %1 !" #: msgid "Add a comment" msgstr "Ajouter un commentaire" #: lib/Jifty/Plugin/AdminUI/Dispatcher.pm:34 msgid "Administration" msgstr "" #: lib/Jifty/Plugin/ViewDeclarePage/Page.pm:584 lib/Jifty/View/Declare/Page.pm:197 msgid "Administration mode is enabled." msgstr "Mode d'administration activé." #: lib/Jifty/Plugin/ViewDeclarePage/Page.pm:581 lib/Jifty/View/Declare/Page.pm:194 msgid "Alert" msgstr "Alerte" #: lib/Jifty/Action/Record/Create.pm:105 msgid "An error occurred. Try again later" msgstr "Erreur. Ré-essayez plus tard" #: lib/Jifty/Action/Record/Search.pm:181 msgid "Any field contains" msgstr "Un champs contient" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:122 msgid "Anyway, the software has logged this error." msgstr "Cette erreur a été enregistrée par le logiciel." #: lib/Jifty/Plugin/SetupWizard/View.pm:152 msgid "At any time you may close the wizard; your progress will be saved for next time. You may also skip around, doing these steps in whatever order suits you." msgstr "Vous pouvez arrêter cet assistant dès que vous le souhaitez; l'état courant est sauvegardé. Vous pouvez passer des étapes ou les suivre dans l'ordre de votre choix." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:54 msgid "Authentication token" msgstr "Token d'authentification" #: msgid "Back to the admin console" msgstr "Retour à l'interface d'admin" #: msgid "Back to the application" msgstr "Retour à l'application" #: lib/Jifty/Plugin/SetupWizard/View.pm:160 msgid "Begin" msgstr "Démarrage" #: lib/Jifty/Action/Record/Bulk.pm:157 msgid "Bulk update successful" msgstr "Mise à jour groupée réussie" #: msgid "By %1 %2" msgstr "Par %1 %2" #: msgid "Calendar" msgstr "Calendrier" #: lib/Jifty/View/Declare/CRUD.pm:528 msgid "Cancel" msgstr "Annuler" #: msgid "Close window" msgstr "Fermer la fenêtre" #: lib/Jifty/Plugin/Config/Dispatcher.pm:33 msgid "Configuration" msgstr "" #: msgid "Confirm delete?" msgstr "Confirmer la suppression ?" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:94 msgid "Confirmation resent." msgstr "Confirmation transmise." #: lib/Jifty/Plugin/SetupWizard/Action/TestDatabaseConnectivity.pm:72 msgid "Connection successful" msgstr "Connexion réussie" #: msgid "Continue" msgstr "Continuer" #: lib/Jifty/View/Declare/CRUD.pm:938 lib/Jifty/View/Declare/Helpers.pm:185 msgid "Create" msgstr "Enregistrer" #. (ref($record) #. (ref($record),$msg) #: lib/Jifty/Action/Record/Create.pm:104 msgid "Create of %1 failed: %2" msgstr "La création de %1 a échoué : %2" #: lib/Jifty/Action/Record/Create.pm:146 msgid "Created" msgstr "Création réussie" #: msgid "Database Administration" msgstr "Administration de la Base de Données" #: lib/Jifty/Plugin/SetupWizard/View.pm:236 msgid "Database Engine" msgstr "Moteur de base de données" #: lib/Jifty/Plugin/SetupWizard/View.pm:247 msgid "Database Name" msgstr "Nom de la base de données" #: lib/Jifty/View/Declare/CRUD.pm:687 msgid "Default" msgstr "Défaut" #: lib/Jifty/View/Declare/CRUD.pm:538 msgid "Delete" msgstr "Effacer" #: lib/Jifty/Action/Record/Delete.pm:82 msgid "Deleted" msgstr "Suppression réussie" #: msgid "Done?" msgstr "Fini ?" #: lib/Jifty/View/Declare/CRUD.pm:460 msgid "Edit" msgstr "Editer" #: msgid "Edit %1" msgstr "Editer %1" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:53 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:32 msgid "Email" msgstr "Mail" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:53 msgid "Email address" msgstr "Adresse mail" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:55 msgid "Email address confirmed?" msgstr "Adresse mail confirmée ?" #: lib/Jifty/Plugin/Authentication/Password/View.pm:166 msgid "Fill in your address below, and we'll send out another confirmation email to you. " msgstr "Renseignez le champs ci-dessous avec votre adresse mail et nous vous transmettrons un nouveau mail de confirmation." #: lib/Jifty/Action.pm:1323 msgid "Foo cannot contain -, *, +, or ?." msgstr "Cette donnée ne doit pas contenir -, *, +, ou ?." #: lib/Jifty/Action.pm:1317 msgid "Foo cannot contain uppercase letters." msgstr "Cette donnée ne doit pas contenir de majuscule." #: lib/Jifty/Action.pm:1296 msgid "Foo values are always in lowercase." msgstr "Cette donnée doit toujours être en minuscule." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:27 msgid "For one reason or another, you got to a web page that caused a bit of an error. And then you got to our 'basic' error handler. Which means we haven't written a pretty, easy to understand error message for you just yet. The message we do have is:" msgstr "" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:129 msgid "Go back home..." msgstr "Retour..." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:69 msgid "Hashed Password" msgstr "Mot de passe chiffré" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:44 msgid "Head on back home" msgstr "Retour accueil" #. ('World') #: lib/Jifty/I18N.pm:18 lib/Jifty/I18N.pm:22 msgid "Hello, %1!" msgstr "Bonjour, %1" #: msgid "Hi %1!" msgstr "Bonjour %1" #. (DateTime::Locale->load($lang) #. (DateTime::Locale->load($lang)->native_name) #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:77 msgid "Hi, we speak %1." msgstr "Bonjour, langue utilisée : %1." #. ($cu->username) #: lib/Jifty/Plugin/SkeletonApp/View.pm:30 lib/Jifty/Plugin/ViewDeclarePage/Page.pm:562 msgid "Hiya, %1." msgstr "Bonjour, %1" #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:31 msgid "Home" msgstr "Accueil" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:50 msgid "How should I display your name to other users?" msgstr "Nom affiché" #: lib/Jifty/Action.pm:1228 msgid "I changed $field for you" msgstr "$field a été changé" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64 msgid "I'm not sure how this happened." msgstr "Problème non identifié." #: msgid "If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one." msgstr "Si ce nom d'utilisateur entre en conflit avec un nom existant ou contient des caractères non autorisés, vous devrez le changer." #: lib/Jifty/Plugin/SetupWizard/View.pm:229 msgid "If your preferred database is not listed in the dropdown below, that means we could not find a database driver for it. You may be able to remedy this by using CPAN to download and install $drivers." msgstr "Si votre base de données préférée n'apparait pas dans la liste ci-dessous, c'est que nous ne trouvons pas le pilote nécessaire. Vous pouvez certainement l'installer depuis CPAN." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:64 msgid "Internal error" msgstr "Erreur interne" #: msgid "Invalid OpenID URL. Please check to make sure it is correct. (@{[$csr->err]})" msgstr "URL OpenID incorrecte. Vérifiez la. (@{[$csr->err]}) " #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:122 lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:75 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79 msgid "It doesn't look like there's an account by that name." msgstr "Il ne semble pas y avoir de compte sous ce nom." #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:108 msgid "It looks like somebody else is using that address. Is there a chance you have another account?" msgstr "Cette adresse semble utilisée par quelqu'un d'autre. Vous avez peut-être un autre compte ?" #: msgid "It looks like someone is already using that OpenID." msgstr "Cette URL OpenID est déjà utilisée par un autre utilisateur." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:75 msgid "It looks like you already have an account. Perhaps you want to log in instead?" msgstr "Votre compte existe déjà . Vous voulez peut-être plutôt vous connecter ?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:75 msgid "It looks like you didn't enter the same password into both boxes. Give it another shot?" msgstr "Les mots de passe sont différents. Ré-essayer ?" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:79 msgid "It looks like you're already confirmed." msgstr "Votre adresse a déjà été confirmée." #: lib/Jifty/Plugin/I18N/Action/SetLang.pm:24 msgid "Language" msgstr "Langue" #: lib/Jifty/Plugin/SetupWizard/View.pm:282 msgid "Leave blank to use the default value for your database" msgstr "Ne pas renseigner pour utiliser les valeurs par défaut de votre base de données" #: lib/Jifty/Plugin/ViewDeclarePage/Page.pm:592 lib/Jifty/View/Declare/Page.pm:215 msgid "Loading..." msgstr "Chargement..." #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:137 lib/Jifty/Plugin/Authentication/Password/View.pm:72 msgid "Login" msgstr "Identification" #: msgid "Login to Facebook now to get started!" msgstr "Connection à Facebook démarrée !" #: msgid "Login to Facebook now to link it with your current account!" msgstr "Votre connection à Facebook doit maintenant être liée à votre compte courant !" #: lib/Jifty/Plugin/Authentication/Password/View.pm:66 msgid "Login with a password" msgstr "S'identifier avec un mot de passe" #: msgid "Login with your Ldap account" msgstr "S'identifier avec votre compte Ldap" #: msgid "Login with your OpenID" msgstr "S'identifier avec votre OpenID" #: msgid "Login with your ldap account" msgstr "S'identifier avec votre compte Ldap" #: lib/Jifty/Plugin/Authentication/Password/View.pm:41 msgid "Login!" msgstr "Identification" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:156 msgid "Logout" msgstr "Déconnexion" #: lib/Jifty/Plugin/Authentication/Password/View.pm:74 msgid "Lost your password?" msgstr "Vous avez oublié votre mot de passe ?" #: msgid "Mason error" msgstr "Erreur Mason" #: msgid "Models" msgstr "Modèles" #: lib/Jifty/Plugin/SetupWizard/View.pm:221 msgid "MySQL and PostgreSQL are well-supported production-quality database engines. " msgstr "MySQL et PostgreSQL sont des moteurs de bases de données de qualités. " #: lib/Jifty/Plugin/Authentication/Password/View.pm:99 msgid "New password" msgstr "Nouveau mot de passe" #: lib/Jifty/Plugin/ViewDeclarePage/Page.pm:156 msgid "News" msgstr "Actualités" #: lib/Jifty/View/Declare/CRUD.pm:859 msgid "Next Page" msgstr "Page Suivante" #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:49 msgid "Nickname" msgstr "Nom" #: lib/Jifty/Plugin/Authentication/Password/View.pm:63 msgid "No account yet? It's quick and easy. " msgstr "Pas encore de compte ? C'est facile et rapide. " #: lib/Jifty/Action/Record/Search.pm:182 msgid "No field contains" msgstr "Aucun champs contient" #: lib/Jifty/Plugin/SetupWizard/Action/TestDatabaseConnectivity.pm:66 msgid "No handle created" msgstr "" #: msgid "No items found" msgstr "Aucun enregistrement" #: lib/Jifty/View/Declare/CRUD.pm:770 msgid "No items found." msgstr "Aucun enregistrement." #: msgid "No one has made a comment yet." msgstr "Aucun commentaire pour l'instant." #: lib/Jifty/Web.pm:307 msgid "No request to handle" msgstr "Aucune requête à traiter" #: msgid "No value yet" msgstr "Aucune réponse" #: msgid "Online Documentation" msgstr "Documentation en ligne" #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:25 msgid "Online docs" msgstr "Documentation en ligne" #: msgid "OpenID URL" msgstr "URL OpenID" #: msgid "OpenID verification failed. It looks like you cancelled the OpenID verification request." msgstr "Échec de la vérification OpenID. Il semblerait que vous avez annulé votre demande de vérification." #: msgid "OpenID verification failed: " msgstr "Échec de la vérification OpenID: " #. ($page, $collection->pager->last_page) #. ($page,$collection->pager->last_page) #: lib/Jifty/View/Declare/CRUD.pm:826 msgid "Page %1 of %2" msgstr "Page %1 / %2" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:64 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:60 msgid "Password" msgstr "Mot de passe" #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:136 msgid "Passwords need to be at least six characters long" msgstr "Il faut au minimum six caractères" #: lib/Jifty/Action/Record/Delete.pm:61 lib/Jifty/Action/Record/Update.pm:183 lib/Jifty/Action/Record/Update.pm:196 lib/Jifty/Record.pm:508 lib/Jifty/Record.pm:567 lib/Jifty/Record.pm:70 msgid "Permission denied" msgstr "Autorisation refusée" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66 msgid "Please email us!" msgstr "Envoyez nous un mail !" #: msgid "Preview" msgstr "Aperçu" #: lib/Jifty/View/Declare/CRUD.pm:848 msgid "Previous Page" msgstr "Page précédente" #: lib/Jifty/View/Declare/CRUD.pm:541 msgid "Really delete?" msgstr "Confirmer l'effacement ?" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65 msgid "Really, really sorry." msgstr "Vraiment désolé." #: msgid "Record created" msgstr "Enregistrement créé" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:72 msgid "Remember me?" msgstr "S'en rappeler" #: lib/Jifty/Plugin/Authentication/Password/View.pm:92 lib/Jifty/Plugin/Authentication/Password/View.pm:96 msgid "Reset lost password" msgstr "Changement de mot de passe" #: msgid "Run the action" msgstr "Exécuter l'action" #: lib/Jifty/Plugin/SetupWizard/View.pm:219 msgid "SQLite is a small database engine that does not need a server or any configuration. We recommend it for testing, demonstration, and development, but it is not quite right for a high-volume production server." msgstr "SQLite est un petit moteur de base de données qui ne nécessite pas de serveur ni de configuration. Utilisez le pour des tests, pour développer ou pour des démonstations. Il n'est pas adapté pour un serveur de production." #: lib/Jifty/Plugin/Config/View.pm:32 lib/Jifty/Plugin/SetupWizard/View.pm:34 lib/Jifty/View/Declare/CRUD.pm:519 msgid "Save" msgstr "Enregistrer" #: lib/Jifty/Plugin/Config/View.pm:34 msgid "Save and Restart" msgstr "Enregistrer et Redémarrer" #: msgid "Schema" msgstr "Schéma" #: lib/Jifty/View/Declare/CRUD.pm:404 msgid "Search" msgstr "Chercher" #: lib/Jifty/Plugin/Authentication/Password/View.pm:136 msgid "Send" msgstr "Enregistrer" #: lib/Jifty/Plugin/Authentication/Password/View.pm:131 msgid "Send a link to reset your password" msgstr "Recevoir un lien pour changer votre mot de passe" #: msgid "Send us feedback!" msgstr "Envoyez nous votre avis !" #. ($appname) #: lib/Jifty/Plugin/SetupWizard/View.pm:400 msgid "Setup finished. Welcome to %1!" msgstr "Configuration terminée. Bienvenue sur %1 !" #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:142 lib/Jifty/Plugin/Authentication/Password/View.pm:26 lib/Jifty/Plugin/Authentication/Password/View.pm:31 msgid "Sign up" msgstr "S'enregistrer" #: lib/Jifty/Plugin/Authentication/Password/View.pm:64 msgid "Sign up for an account!" msgstr "Enregistrez vous pour avoir un compte !" #: msgid "Signup" msgstr "Enregistrement" #. ($msg) #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Something bad happened and we couldn't create your account: %1" msgstr "Un problème nous empêche de créer votre compte: %1" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:139 msgid "Something went awry" msgstr "Problème" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:117 msgid "Something's not quite right" msgstr "Problème" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:123 msgid "Sorry about this." msgstr "Désolé." #: msgid "Sorry, something weird happened (we couldn't create a user for you). Try again later." msgstr "Désolé, un problème nous empêche de créer cet utilisateur. Ré-essayer plus tard." #: lib/Jifty/Action/Record/Execute.pm:55 msgid "Start" msgstr "Démarrer" #: msgid "Submit" msgstr "Soumettre" #: msgid "Table of Contents" msgstr "Table des matières" #: msgid "Tell us what's good, what's bad, and what else you want %1 to do!" msgstr "Dites nous ce qui vous plaît, vous déplaît, ou tout autre avis %1" #: lib/Jifty/Plugin/SetupWizard/View.pm:329 msgid "Test connectivity" msgstr "Test de connection" #. ($new_email) #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:101 msgid "That %1 doesn't look like an email address." msgstr "%1 ne ressemble pas à une adresse mail." #: lib/Jifty/Action.pm:1060 msgid "That doesn't look like a correct value" msgstr "Valeur incorrecte" #: msgid "That doesn't look like a valid login." msgstr "Ce compte ne semble pas valide." #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:68 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70 msgid "That doesn't look like an email address." msgstr "Cela ne ressemble pas à une adresse mail." #: lib/Jifty/Action/Record.pm:374 msgid "That doesn't look right, but I don't know why" msgstr "Problème" #: msgid "The OpenID '$openid' has been linked to your account." msgstr "L'openID '$openid' a été attaché à votre compte." #: lib/Jifty/Plugin/SetupWizard/View.pm:273 msgid "The domain name of your database server (for example, db.example.com)" msgstr "" #: lib/Jifty/Action/Record.pm:232 msgid "The passwords you typed didn't match each other" msgstr "Les mots de passe tapés ne sont pas identiques" #. ($appname) #: lib/Jifty/Plugin/SetupWizard/View.pm:383 msgid "The root URL for the web server (examples: http://%1.yourcompany.com, http://business.com/%1)" msgstr "URL du serveur web (exemple : http://%1.yourcompany.com, http://business.com/%1)" #: lib/Jifty/Web.pm:429 msgid "There was an error completing the request. Please try again later." msgstr "Problème lors de l'exécution de cette requête. Ré-essayez plus tard." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81 msgid "There was an error setting your password." msgstr "Problème pendant l'enregistrement de votre mot de passe." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it." msgstr "Il y a de fortes chances pour que ce message d'erreur ne veuille rien dire pour vous, mais nous préférons vous afficher ce laïus plutôt que rien. Nous avons enregistré cette erreur, nous n'avons plus qu'à écrire un message clair pour vous expliquer le problème et comment le régler. " #: msgid "This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records." msgstr "Cette page vous permet de gérer vos enregistrements dans la base. Vous trouverez ci-dessous la listes des tables. Vous pouvez ajouter, effacer ou modifier les enregistrements." #. ($appname) #: lib/Jifty/Plugin/SetupWizard/View.pm:136 msgid "This installer will help you configure %1 by walking you through the following steps." msgstr "Cet assistant vous aidera à configurer %1 en vous guidant étape par étape." #: lib/Jifty/Plugin/SetupWizard/View.pm:156 msgid "This setup wizard was activated by the presence of SetupMode: 1 in one of your configuration files. If you are seeing this erroneously, you may restore normal operation by adjusting the etc/site_config.yml file to have SetupMode: 0 set under framework." msgstr "Cet assistant de configuration a été activé par la présence de SetupMode: 1 dans votre fichier de configuration etc/site_config.yml. Vous pouvez le désactiver en mettant SetupMode: 0 sous la rubrique framework." #: msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)." msgstr "Pour désactiver cette console d'administration, ajoutez \"AdminMode: 0\" dans la rubrique \"framework:\" du fichier de configuration (etc/config.yml)." #: lib/Jifty/View/Declare/CRUD.pm:732 msgid "Toggle search" msgstr "Rechercher" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:156 msgid "Try again" msgstr "Ré-essayer" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108 msgid "Try again later. We're really, really sorry." msgstr "Ré-essayez, nous sommes vraiment désolés." #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53 msgid "Type that again?" msgstr "Confirmez" #: lib/Jifty/Action/Record/Update.pm:223 msgid "Updated" msgstr "Modification enregistrée" #: lib/Jifty/Plugin/ViewDeclarePage/Page.pm:243 msgid "Updated this week" msgstr "Mis à jour cette semaine" #: lib/Jifty/Plugin/SetupWizard/View.pm:321 msgid "Use SSL?" msgstr "Utiliser SSL ?" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:44 msgid "Username" msgstr "Nom d'utilisateur" #: lib/Jifty.pm:29 msgid "W00t" msgstr "" #: msgid "We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions" msgstr "Vous devez préciser un nom d'utilisateur ou vérifier celui associé à votre OpenID. Votre nom d'utilisateur sera présenté lorsque rédigez un commentaire" #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114 msgid "We've sent a confirmation message to your email box." msgstr "Nous vous avons envoyé un mail de confirmation." #. ('Bob', 'World') #: lib/Jifty/I18N.pm:30 msgid "Welcome %1 to the %2" msgstr "Bienvenue %1 sur %2" #: msgid "Welcome back, " msgstr "Re-bonjour, " #. ($user->name) #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:258 msgid "Welcome back, %1." msgstr "Re-bonjour, %1." #. ($appname) #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40 lib/Jifty/Plugin/SetupWizard/View.pm:8 msgid "Welcome to %1!" msgstr "Bienvenue sur %1 !" #. (Jifty->config->framework('ApplicationName') #. (Jifty->config->framework('ApplicationName'),$record->name) #. (Jifty->config->framework('ApplicationName'),$u->name) #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113 msgid "Welcome to %1, %2." msgstr "Bienvenue sur %1, %2." #: msgid "Welcome to %1, %2. " msgstr "Bienvenue sur %1, %2. " #: lib/Jifty/Plugin/SkeletonApp/View.pm:73 msgid "Welcome to your new Jifty application" msgstr "Bienvenue sur votre nouvelle application Jifty" #: msgid "Welcome, " msgstr "Bienvenue, " #: msgid "You already logged in." msgstr "Vous êtes déjà connecté." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63 msgid "You don't exist." msgstr "Votre compte n'existe pas." #: lib/Jifty/Plugin/ErrorTemplates/View.pm:121 msgid "You got to a page that we don't think exists." msgstr "Vous voulez une page qui n'existe pas." #: msgid "You got to a page that we don't think exists. Anyway, the software has logged this error. Sorry about this." msgstr "Cette page n'existe pas." #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44 msgid "You have already confirmed your account." msgstr "Votre compte à déjà été confirmé." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:215 msgid "You haven't confirmed your account yet." msgstr "Vous n'avez pas encore confirmé votre compte." #: lib/Jifty/Plugin/Authentication/Password/View.pm:132 msgid "You lost your password. A link to reset it will be sent to the following email address:" msgstr "Vous avez perdu votre mot de passe. Un lien pour changer ce mot de passe sera envoyé à l'adresse suivante :" #: msgid "You lost your password. A reminder will be send to the following mail:" msgstr "Vous avez perdu votre mot de passe. Un lien pour changer ce mot de passe sera envoyé à l'adresse suivante :" #: lib/Jifty/Plugin/SetupWizard/View.pm:374 msgid "You may change web server settings." msgstr "Vous pouvez changer la configuration du serveur web." #: lib/Jifty/Plugin/SetupWizard/View.pm:215 msgid "You may choose a database engine." msgstr "Vous pouvez choisir un moteur de base de données." #: lib/Jifty/Plugin/SetupWizard/View.pm:394 msgid "You may finalize your configuration." msgstr "Vous pouvez terminer votre configuration." #: msgid "You may have mistyped your email address or password. Give it another shot." msgstr "Vous vous êtes trompé dans votre mail ou votre mot de passe. Ré-essayez." #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:199 msgid "You may have mistyped your email or password. Give it another shot." msgstr "Vous vous êtes trompé dans votre mail ou votre mot de passe. Ré-essayez." #: msgid "You may have mistyped your login or password. Give it another shot?" msgstr "Vous vous êtes trompé dans votre compte ou votre mot de passe. Ré-essayez." #: lib/Jifty/Plugin/SetupWizard/View.pm:172 msgid "You may select a different language." msgstr "Vous pouvez choisir une langue différente." #: msgid "You must be logged in to link your user to your Facebook account." msgstr "Vous devez être connecté pour lier votre compte d'utilisateur à votre compte Facebook." #. ($field) #: lib/Jifty/Action.pm:946 msgid "You need to fill in the '%1' field" msgstr "Le champ '%1' doit être complété" #: msgid "You need to fill in this field" msgstr "Information obligatoire" #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461') #: lib/Jifty/Plugin/SkeletonApp/View.pm:73 msgid "You said you wanted a pony. (Source %1)" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/View.pm:80 msgid "You're already logged in." msgstr "Vous êtes déjà connecté." #: lib/Jifty/Plugin/SkeletonApp/View.pm:33 lib/Jifty/Plugin/ViewDeclarePage/Page.pm:565 msgid "You're not currently signed in." msgstr "Vous n'êtes pas encore connecté." #: msgid "Your account has been successfully linked to your Facebook user %1!" msgstr "Votre compte a bien été lié à votre compte Facebook %1" #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:73 msgid "Your browser can remember your login for you" msgstr "Votre navigateur peut mémoriser cette identification" #: msgid "Your comment has been added. If it does not immediately appear, it may have been flagged for moderation and should appear shortly." msgstr "Votre commentaire a été ajouté. S'il n'apparaît pas immédiatement, c'est qu'il est en attente de modération." #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87 msgid "Your password has been reset. Welcome back." msgstr "Votre mot de passe à été changé." #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:63 msgid "Your password should be at least six characters" msgstr "Votre mot de passe doit contenir au moins six caractères" #: msgid "[%1] Moderate comment: %2" msgstr "[%1] Commentaire modéré : %2" #: msgid "[%1] New comment: %2" msgstr "[%1] Nouveau commentaire : %2" #: lib/Jifty/View/Declare/CRUD.pm:635 msgid "asc" msgstr "" #: lib/Jifty/Plugin/Config/Action/Config.pm:70 msgid "can't write to etc/config.yml: $1" msgstr "" #: lib/Jifty/View/Declare/CRUD.pm:644 msgid "desc" msgstr "" #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31 msgid "email address" msgstr "adresse mail" #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46 msgid "for now, and try to forget that we let you down." msgstr "" #: lib/Jifty/Plugin/Config/Action/Config.pm:59 msgid "invalid yaml" msgstr "" #: msgid "mark as %1" msgstr "marqué comme %1" #: lib/Jifty/Action/Record.pm:471 msgid "no value" msgstr "" #: msgid "publish" msgstr "publier" #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37 msgid "type your password again" msgstr "confirmez votre mot de passe" #: msgid "unpublish" msgstr "ne pas publier" #: lib/Jifty/Action.pm:1180 msgid "warning" msgstr "attention" jifty-1.10518+dfsg.orig/share/web/0000755000175000017500000000000011565006006014354 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/transform_templates0000644000175000017500000000027711447473536020415 0ustar fsfs#!/usr/bin/perl use warnings; use strict; my $lines = (join('',)); $lines =~ s/\<(\w*?) (?:class="(.*?)")? (?:id="(.*?)")?\>/with { class => $2, id => $3 }, $1 { /g; print $lines; jifty-1.10518+dfsg.orig/share/web/templates/0000755000175000017500000000000011625457665016374 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/__jifty/0000755000175000017500000000000011625457665020017 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/__jifty/autocomplete.xml0000644000175000017500000000144511447473536023243 0ustar fsfs<%init> # Note: the only point to this file is to set the content_type; the actual # behavior is accomplished inside the framework. It will go away once we # have infrastructure for serving things of various content-types. Jifty->web->response->content_type('text/xml; charset=UTF-8'); unless (Jifty->web->response->result('autocomplete')) { print ""; return; } my $ref = Jifty->web->response->result('autocomplete')->content; my @options = @{$ref->{'completions'}||[]};
    % foreach my $item ( @options) { % if (!ref($item)) {
  • <% $item %>
  • % } elsif (exists $item->{label}) {
  • <% $item->{label} %><% $item->{value} %>
  • % } else {
  • <% $item->{value} %>
  • % } %}
jifty-1.10518+dfsg.orig/share/web/templates/__jifty/webservices/0000755000175000017500000000000011565006013022314 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/__jifty/webservices/xml0000644000175000017500000001107611447473536023065 0ustar fsfs<%init> my $output = ""; my $writer = XML::Writer->new( OUTPUT => \$output, UNSAFE => 1 ); Jifty->web->response->content_type('text/xml; charset=utf-8'); $writer->xmlDecl( "UTF-8", "yes" ); $writer->startTag("response"); if (my $ext = Jifty->web->request->argument('_webservice_external_redirect')) { $writer->startTag("redirect"); $writer->cdataElement(url=> $ext); $writer->endTag(); $writer->endTag(); Jifty->web->out($output); $m->abort; } FRAGMENT: for my $fragment ( Jifty->web->request->fragments ) { # Set up the form if need be Jifty->web->form->_init; Jifty->web->form->is_open(1) if $fragment->in_form; # Set up the region stack local Jifty->web->{'region_stack'} = []; my @regions; do { push @regions, $fragment; } while ($fragment = $fragment->parent); for my $current (reverse @regions) { my $new = Jifty->web->get_region( join '-', grep {$_} Jifty->web->qualified_region, $current->name ); # Arguments can be complex mapped hash values. Get their # real values by mapping. my %defaults = %{$current->arguments || {}}; for (keys %defaults) { my ($key, $value) = Jifty::Request::Mapper->map(destination => $_, source => $defaults{$_}); delete $defaults{$_}; $defaults{$key} = $value; } $new ||= Jifty::Web::PageRegion->new( name => $current->name, path => URI::Escape::uri_unescape($current->path), region_wrapper => $current->wrapper, parent => Jifty->web->current_region, defaults => \%defaults, ); # It's possible that the pageregion creation could fail -- no # name, for instance. In that case, bail on this fragment. next FRAGMENT unless $new; $new->enter; } # Stuff the rendered region into the XML $writer->startTag( "fragment", id => Jifty->web->current_region->qualified_name ); my %args = %{ Jifty->web->current_region->arguments }; $writer->dataElement( "argument", $args{$_}, name => $_) for sort keys %args; if (Jifty->config->framework('ClientTemplate') && Jifty->web->current_region->client_cacheable) { $writer->cdataElement( "cacheable", Jifty->web->current_region->client_cache_content, type => Jifty->web->current_region->client_cacheable ); } $writer->cdataElement( "content", Jifty->web->current_region->as_string ); $writer->endTag(); # Clean up region stack and form Jifty->web->current_region->exit while Jifty->web->current_region; Jifty->web->form->is_open(0); } my %results = Jifty->web->response->results; for (keys %results) { $writer->startTag("result", moniker => $_, class => $results{$_}->action_class); $writer->dataElement("success", $results{$_}->success); $writer->dataElement("message", $results{$_}->message) if $results{$_}->message; $writer->dataElement("error", $results{$_}->error) if $results{$_}->error; my %warnings = $results{$_}->field_warnings; my %errors = $results{$_}->field_errors; my %fields; $fields{$_}++ for keys(%warnings), keys(%errors); for (sort keys %fields) { next unless $warnings{$_} or $errors{$_}; $writer->startTag("field", name => $_); $writer->dataElement("warning", $warnings{$_}) if $warnings{$_}; $writer->dataElement("error", $errors{$_}) if $errors{$_}; $writer->endTag(); } # XXX TODO: Hack because we don't have a good way to serialize # Jifty::DBI::Record's yet, which are technically circular data # structures at some level (current_user of a # current_user->user_object is itself) my $content = stripkids($results{$_}->content); $writer->raw(XML::Simple::XMLout($content, NoAttr => 1, RootName => "content", NoIndent => 1)) if keys %{$content}; $writer->endTag(); } $writer->endTag(); Jifty->web->response->content_type('text/xml; charset=UTF-8'); Jifty->web->out($output); <%once> use Scalar::Util qw(blessed); use XML::Simple; sub stripkids { my $top = shift; if ( not ref $top ) { return $top } elsif ( blessed($top) and ( $top->isa("Jifty::DBI::Record") or $top->isa("Jifty::DBI::Collection") ) ) { return undef; } elsif ( ref $top eq 'HASH' ) { foreach my $item ( keys %$top ) { $top->{$item} = stripkids( $top->{$item} ); } } elsif ( ref $top eq 'ARRAY' ) { for ( 0 .. $#{$top} ) { $top->[$_] = stripkids( $top->[$_] ); } } return $top; } jifty-1.10518+dfsg.orig/share/web/templates/__jifty/webservices/json0000644000175000017500000000043611447473536023234 0ustar fsfs% Jifty->web->response->content_type("text/x-json"); <% Jifty::JSON::encode_json(\%results) |n%> <%INIT> my %results = Jifty->web->response->results; for (values %results) { $_ = $_->as_hash; # backwards compatibility :( $_->{_content} = delete $_->{content}; } jifty-1.10518+dfsg.orig/share/web/templates/__jifty/webservices/yaml0000644000175000017500000000042711447473536023225 0ustar fsfs% Jifty->web->response->content_type("text/x-yaml"); <% Jifty::YAML::Dump(\%results) |n%> <%INIT> my %results = Jifty->web->response->results; for (values %results) { $_ = $_->as_hash; # backwards compatibility :( $_->{_content} = delete $_->{content}; } jifty-1.10518+dfsg.orig/share/web/templates/__jifty/halo0000644000175000017500000001175311447473536020671 0ustar fsfs % foreach my $item (@stack) { <& .frame, frame => $item &> % } <%args> @stack <%init> for my $id (0..$#stack) { my @kids; my $looking = $id; while (++$looking <= $#stack and $stack[$looking]->{depth} >= $stack[$id]->{depth} + 1) { push @kids, {id => $stack[$looking]{id}, path => $stack[$looking]{path}, render_time => $stack[$looking]{render_time}} if $stack[$looking]->{depth} == $stack[$id]->{depth} + 1; } $stack[$id]{kids} = \@kids; if ($stack[$id]{depth} > 1) { $looking = $id; $looking-- while ($stack[$looking]{depth} >= $stack[$id]{depth}); $stack[$id]{parent} = {id => $stack[$looking]{id}, path => $stack[$looking]{path}, render_time => $stack[$looking]{render_time}}; } } my $depth = 0; <%def .frame> <%args> $frame <%init> my $id = $frame->{id}; my @args; while (my ($key, $value) = splice(@{$frame->{args}},0,2)) { push @args, [$key, ref($value), $value]; } @args = sort {$a->[0] cmp $b->[0]} @args; my $prev = ''; my @stmts = @{$frame->{'sql_statements'} || []}; jifty-1.10518+dfsg.orig/share/web/templates/__jifty/empty0000644000175000017500000000000011447473536021063 0ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/__jifty/validator.xml0000644000175000017500000000624411447473536022531 0ustar fsfs<%init> Jifty->web->response->content_type('text/xml; charset=UTF-8'); my $output = ""; use XML::Writer; my $writer = XML::Writer->new( OUTPUT => \$output ); $writer->xmlDecl( "UTF-8", "yes" ); $writer->startTag("validation"); for my $ra ( Jifty->web->request->actions ) { my $action = Jifty->web->new_action_from_request($ra); unless ($action ){ warn "Couldn't turn $ra into an action"; next; } $writer->startTag( "validationaction", id => $action->register_name ); for my $arg ( $action->argument_names ) { if ( not $action->arguments->{$arg}->{ajax_validates} ) { $writer->emptyTag( "ignored", id => $action->error_div_id($arg) ); $writer->emptyTag( "ignored", id => $action->warning_div_id($arg) ); } elsif ( (not defined $action->argument_value($arg) or length $action->argument_value($arg) == 0) and not $action->result->ajax_force_validate($arg) ) { $writer->emptyTag( "blank", id => $action->error_div_id($arg) ); $writer->emptyTag( "blank", id => $action->warning_div_id($arg) ); } elsif ( $action->result->field_error($arg) ) { $writer->dataElement( "error", $action->result->field_error($arg), id => $action->error_div_id($arg) ); $writer->emptyTag( "ok", id => $action->warning_div_id($arg) ); } elsif ( $action->result->field_warning($arg) ) { $writer->dataElement( "warning", $action->result->field_warning($arg), id => $action->warning_div_id($arg) ); $writer->emptyTag( "ok", id => $action->error_div_id($arg) ); } else { $writer->emptyTag( "ok", id => $action->error_div_id($arg) ); $writer->emptyTag( "ok", id => $action->warning_div_id($arg) ); } } $writer->endTag(); $writer->startTag( "canonicalizeaction", id => $action->register_name ); for my $arg ( $action->argument_names ) { if (($ra->arguments->{$arg} || "") eq ($action->argument_value($arg) || "")) { # if the value doesn't change, it can be ignored. # canonicalizers can change other parts of the action, so we want to send all changes $writer->emptyTag( "ignored", name => $action->form_field_name($arg) ); } elsif ( not defined $action->argument_value($arg) or length $action->argument_value($arg) == 0 ) { $writer->emptyTag( "blank", name => $action->form_field_name($arg) ); } else { $writer->dataElement( "update", $action->argument_value($arg), name => $action->form_field_name($arg) ); } if ( $action->result->field_canonicalization_note($arg) ) { $writer->dataElement( "canonicalization_note", $action->result->field_canonicalization_note($arg), id => $action->canonicalization_note_div_id($arg) ); } } $writer->endTag(); } $writer->endTag(); $m->out($output); $m->abort(); jifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/0000755000175000017500000000000011625457665021150 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/dhandler0000644000175000017500000000030411447473536022646 0ustar fsfs<&|/_elements/wrapper, title => 'Something went awry' &> <& _elements/error_text, error => $m->dhandler_arg &> <%init> Jifty->log->error("Unhandled web error ". $m->dhandler_arg); jifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/autohandler0000644000175000017500000000006311447473536023375 0ustar fsfs<%flags> inherit => undef % $m->call_nextjifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/_elements/0000755000175000017500000000000011625457665023123 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/_elements/error_text0000644000175000017500000000142111447473536025236 0ustar fsfs

Sorry, something went awry

For one reason or another, you got to a web page that caused a bit of an error. And then you got to our "basic" error handler. Which means we haven't written a pretty, easy to understand error message for you just yet. The message we do have is:

<% $error %>

There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it.

For now <% Jifty->web->link( url =>"/", label => 'head on back home')%> and try to forget that we let you down.

<%args> $error jifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/_elements/wrapper0000644000175000017500000000126711524323602024511 0ustar fsfs Mason error

Mason error

% if (Jifty->admin_mode) {
Alert: Jifty <% Jifty->web->tangent( label => 'administration mode' , url => '/__jifty/admin/')%> is enabled.
% } <% Jifty->web->render_messages %> <% $m->content |n%>
<%doc> This exists as a fallback wrapper, in case the mason error in question is caused by the Jifty application's wrapper, for instance. jifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/error.css0000644000175000017500000000030111500012563022755 0ustar fsfsh1 { color: red; } <%init> Jifty->web->response->content_type("text/css"); <%doc> This exists as fallback CSS, in case the Jifty application's CSS is causing the error. jifty-1.10518+dfsg.orig/share/web/templates/__jifty/error/mason_internal_error0000644000175000017500000000345011447473536025314 0ustar fsfs<&| $wrapper, title => _("Mason error") &> Error in <& .line, file => $file, line => "@lines" &>
<% $msg %>
<% Jifty->web->return( label => _("Try again") ) %>

Call stack

    % for my $frame (@stack) { % next if $frame->filename =~ m{/HTML/Mason/};
  • <& .line, file => $frame->filename, line => $frame->line &>
  • % }
<%def .line> <%args> $file $line % my $path; % if (-w $file) { % $path = $file; % for (map {$_->[1]} @{Jifty->handler->mason->interp->comp_root}) { % last if $path =~ s/^\Q$_\E//; % } % if ($path ne $file) { template <% Jifty->web->tangent( url =>"/__jifty/edit/mason_component$path", label => _("%1 line %2", $path, $line), parameters => { line => $line } ) %> % } else { <% Jifty->web->tangent( url =>"/__jifty/edit/library$path", label => _("%1 line %2", $path, $line), parameters => { line => $line } ) %> % } % } else { <% _("%1 line %2", $file, $line) %> % } <%init> my $wrapper = "/_elements/wrapper"; my $cont = Jifty->web->request->continuation; $wrapper = "/__jifty/error/_elements/wrapper" if $cont and $cont->request->path eq "/__jifty/error/mason_internal_error"; # If we're not in devel, bail if ( not Jifty->config->framework("DevelMode") or not $cont ) { $m->comp( $wrapper, content => sub { $m->comp( "_elements/error_text", error => "mason internal error" ); }, title => "Something went awry" ); $m->abort; } my $e = $cont->response->error; my $msg = $e->message; $msg =~ s/, <\S+> (line|chunk) \d+\././; my $info = $e->analyze_error; my $file = $info->{file}; my @lines = @{ $info->{lines} }; my @stack = @{ $info->{frames} }; jifty-1.10518+dfsg.orig/share/web/templates/=/0000755000175000017500000000000011625457665016550 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/=/subs0000644000175000017500000000264111524323602017427 0ustar fsfs<%args> $forever => 1 <%init> Jifty->web->response->content_type("text/html; charset=utf-8"); Jifty->web->response->header('Pragma' => 'no-cache'); Jifty->web->response->header('Cache-control' => 'no-cache'); Jifty->handler->send_http_header; my $writer = XML::Writer->new; $writer->xmlDecl( "UTF-8", "yes" ); my $begin = <<'END'; END chomp $begin; if ($forever) { my $whitespace = " " x ( 1024 - length $begin ); $begin =~ s/$/$whitespace/s; } $m->print($begin); $m->flush_buffer; Jifty->handler->buffer->flush_output; $writer->startTag("body"); local $SIG{PIPE} = sub { die "ABORT"; }; my $loops; while (Jifty->config->framework('PubSub')->{'Enable'}) { Jifty->web->out(" ") if ++$loops % 10 == 0; my $sent = write_subs_once($writer); Jifty->handler->buffer->flush_output; flush STDOUT; last if ( $sent && !$forever ); sleep 1; } $writer->endTag(); return; sub write_subs_once { my $writer = shift; Jifty::Subs::Render->render( Jifty->web->session->id, sub { my ( $mode, $name, $content, $attrs ) = @_; $writer->startTag( "pushfrag", mode => $mode, %{$attrs || {}} ); $writer->startTag( "fragment", id => $name ); $writer->dataElement( "content", $content ); $writer->endTag(); $writer->endTag(); } ); } jifty-1.10518+dfsg.orig/share/web/templates/index.html0000644000175000017500000000033711447473536020371 0ustar fsfs<&|/_elements/wrapper, title => _('Welcome to your new Jifty application') &> <%_('You said you wanted a pony. (Source %1)','http://hdl.loc.gov/loc.pnp/cph.3c13461')%> jifty-1.10518+dfsg.orig/share/web/templates/autohandler0000644000175000017500000000057411447473536020630 0ustar fsfs<%init> # XXX FIXME See Jifty::View::Mason::Handler for the source of this puke. use vars qw/ $jifty_internal_request /; if (!$jifty_internal_request && $m->base_comp->path =~ m|/_elements/|) { # Requesting an internal component by hand -- naughty $m->redirect('/__jifty/error/requested_private_component'); } $m->comp('/_elements/nav'); $m->call_next(); return; jifty-1.10518+dfsg.orig/share/web/templates/helpers/0000755000175000017500000000000011625457665020036 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/helpers/calendar.html0000644000175000017500000000476711447473536022510 0ustar fsfs<& /_elements/header, title => _('Calendar'_ &> <% _('Close window')%>
% foreach my $wday (@weekdays) { % } % foreach my $week (@cal) { % foreach my $day (@{$week}) { % } #foreach $day % } # foreach $week
<% $months[$DisplayedMonth-1] %> <% _($DisplayedYear) %>
<%_($wday)%>
% if ($day) { % my $datestr = sprintf('%04d-%02d-%02d', $DisplayedYear, $DisplayedMonth, $day); <% $day %> % } else {   % }
% my $datestr = sprintf('%04d-%02d-%02d', $today[5]+1900,$today[4]+1, $today[3]); Today % my @tomorrow = localtime(time()+86400); % $datestr = sprintf('%04d-%02d-%02d', $tomorrow[5]+1900,$tomorrow[4]+1, $tomorrow[3]); Tomorrow
% $m->abort(); <%init> my @today = localtime(time()); my @weekdays; push @weekdays, $_ for qw(Sun Mon Tue Wed Thu Fri Sat); my @months; push @months, $_ for qw(January February March April May June July August September October November December); unless ($DisplayedYear) { $DisplayedMonth = $today[4] + 1; $DisplayedYear = ($today[5] + 1900); } my ($prev_year, $next_year, $prev_month, $next_month); $prev_month = $next_month = $DisplayedMonth; $prev_year = $next_year = $DisplayedYear; $next_month++; $prev_month--; if ($DisplayedMonth == 12) { $next_year++; $next_month = 1; } elsif ($DisplayedMonth == 1) { $prev_month = 12; $prev_year--; } use Calendar::Simple; my @cal = Calendar::Simple::calendar($DisplayedMonth, $DisplayedYear); <%args> $field => 'none' $DisplayedMonth => undef $DisplayedYear => undef jifty-1.10518+dfsg.orig/share/web/templates/_elements/0000755000175000017500000000000011625457665020347 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/templates/_elements/keybindings0000644000175000017500000000003511447473536022573 0ustar fsfs
jifty-1.10518+dfsg.orig/share/web/templates/_elements/header0000644000175000017500000000056311524323602021503 0ustar fsfs <% _($title) %> <% Jifty->web->include_css %> <% Jifty->web->include_javascript %> <%args> $title => "" <%init> Jifty->web->response->content_type('text/html; charset=utf-8'); jifty-1.10518+dfsg.orig/share/web/templates/_elements/menu0000644000175000017500000000121611447473536021233 0ustar fsfs<%args> $menu => undef <%init> # Default to the app menu $menu = Jifty->web->navigation if not defined $menu; % my @children = $menu->children; % if ( @children ) { % } <%def .menu> <%args> $item <%init> my @kids = $item->children;
  • active ? 'class="active"' : '' |n %>><% $item->as_link |n %><% @kids ? '' : '
  • ' |n %> % if (@kids) { % } jifty-1.10518+dfsg.orig/share/web/templates/_elements/paging0000644000175000017500000000327011447473536021536 0ustar fsfs<%args> $collection $page => 1 $argument => 'page' $hide_single_page => 1 $allow_all => 0 <%init> return if $collection->count == 0; $page ||= 1; my $last = $collection->pager->last_page; my $prev = $collection->pager->previous_page; my $next = $collection->pager->next_page; return if $last == 1 && $hide_single_page;
    Page % my $last_num = 0; % foreach my $goto_page (1 .. $last) { % # only show page numbers that are: 1, (within 3 of the current page), last % next if (($goto_page > 1) && ($goto_page < $last) && (abs($goto_page-$page) > 2)); % if ( ($goto_page - $last_num) > 1) { … % } <% Jifty->web->link( label => $goto_page, onclick => { args => { $argument => $goto_page, }, }, ) %> % $last_num = $goto_page; % } % if ($prev) { <% Jifty->web->link( label => "Back", class => "prev", onclick => { args => { $argument => $prev, }, }, ) %> % } % if ($next) { <% Jifty->web->link( label => "Next", class => "next", onclick => { args => { $argument => $next, }, }, ) %> % } % if ($allow_all && $last > 1) { <% Jifty->web->link( label => "All", class => "all", onclick => { args => { $argument => 'all', }, }, ) %> % }
    jifty-1.10518+dfsg.orig/share/web/templates/_elements/sidebar0000644000175000017500000000042111447473536021675 0ustar fsfs
    % my $u = Jifty->web->current_user; % if ($u->id and $u->user_object) { <%_('Hiya, %1.',$u->username)%> % } else { <%_("You're not currently signed in.")%> % }
    jifty-1.10518+dfsg.orig/share/web/templates/_elements/wrapper0000644000175000017500000000242111447473536021746 0ustar fsfs
    <%Jifty->web->link( url => "/", label => _(Jifty->config->framework('ApplicationName')))%>

    <% _($title) %>

    <& sidebar &>
    % if (Jifty->admin_mode) {
    <%_('Alert')%>: <% Jifty->web->tangent( label => _('Administration mode is enabled.') , url => '/__jifty/admin/')%>
    % } <% Jifty->web->render_messages %> <% $m->content |n%> <& /_elements/keybindings &>
    % Jifty::View::Mason::Halo->render_component_tree() if Jifty->config->framework('DevelMode') && !Jifty->config->framework('HideHalos'); %# This is required for jifty server push. If you maintain your own %# wrapper, make sure you have this as well. % if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list ) { % } % Jifty->handler->stash->{'in_body'} = 0; <%args> $title => "" <%init> # First we set up the header. $m->comp( 'header', title => $title); # now that we've printed out the header, we're inside the body, so it's safe to print # halo markers. Jifty->handler->stash->{'in_body'} = 1; jifty-1.10518+dfsg.orig/share/web/templates/_elements/page_nav0000644000175000017500000000022111447473536022042 0ustar fsfs% if ( @{Jifty->web->page_navigation->children} ) { % } jifty-1.10518+dfsg.orig/share/web/templates/_elements/nav0000644000175000017500000000014511447473536021053 0ustar fsfs%# Navigation frobbing now handled in Dispatcher plugins %# This exists for backwards compatibility jifty-1.10518+dfsg.orig/share/web/static/0000755000175000017500000000000011625457665015665 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/0000755000175000017500000000000011625457665016455 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/jquery.jgrowl.css0000755000175000017500000000744611447473536022024 0ustar fsfs div.jGrowl { padding: 10px; z-index: 9999; } /** Special IE6 Style Positioning **/ div.ie6 { position: absolute; } div.ie6.top-right { right: auto; bottom: auto; left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); } div.ie6.top-left { left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); } div.ie6.bottom-right { left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); } div.ie6.bottom-left { left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); } div.ie6.center { left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); width: 100%; } /** Normal Style Positions **/ body > div.jGrowl { position: fixed; } body > div.jGrowl.top-left { left: 0px; top: 0px; } body > div.jGrowl.top-right { right: 0px; top: 0px; } body > div.jGrowl.bottom-left { left: 0px; bottom: 0px; } body > div.jGrowl.bottom-right { right: 0px; bottom: 0px; } body > div.jGrowl.center { top: 0px; width: 50%; left: 25%; } /** Cross Browser Styling **/ div.center div.jGrowl-notification, div.center div.jGrowl-closer { margin-left: auto; margin-right: auto; } div.jGrowl div.jGrowl-notification, div.jGrowl div.jGrowl-closer { background-color: #000; color: #fff; opacity: .85; filter: alpha(opacity = 85); zoom: 1; width: 235px; padding: 10px; margin-top: 5px; margin-bottom: 5px; font-family: Tahoma, Arial, Helvetica, sans-serif; font-size: 12px; text-align: left; display: none; -moz-border-radius: 5px; -webkit-border-radius: 5px; } div.jGrowl div.jGrowl-notification { min-height: 40px; } div.jGrowl div.jGrowl-notification div.header { font-weight: bold; font-size: 10px; } div.jGrowl div.jGrowl-notification div.close { float: right; font-weight: bold; font-size: 12px; cursor: pointer; } div.jGrowl div.jGrowl-closer { height: 15px; padding-top: 4px; padding-bottom: 4px; cursor: pointer; font-size: 11px; font-weight: bold; text-align: center; } jifty-1.10518+dfsg.orig/share/web/static/css/ordered-list.css0000644000175000017500000000101511447473536021556 0ustar fsfsdiv.ordered-list-container div { float: left; } div.ordered-list-container ul.unselected { opacity: 0.6; } div.ordered-list-container ul { list-style-type: none; margin: 0; padding: 5px; margin-right: 10px; background: #eee; } div.ordered-list-container ul.unselected li.head { background: #736F6E; text-align: center; } div.ordered-list-container ul.selected li.head { background: #4AA02C; text-align: center; } div.ordered-list-container .hidden { display: none; } jifty-1.10518+dfsg.orig/share/web/static/css/uploads.css0000644000175000017500000000006311447473536020632 0ustar fsfs.uploads input, .uploads a { display: block; } jifty-1.10518+dfsg.orig/share/web/static/css/base.css0000644000175000017500000000252511513670745020075 0ustar fsfsbody { } body.calpopup { } .error { color: #a00000; } .warning { color: #00a0a0; } .canonicalization_note { color: #009966; } hr { clear: both; } .messages .message { display: block; } div#messages, div#errors { background-color: rgb(240,234,183); border: 1px solid rgb(230,224,173); margin-top: 10px; margin-bottom: 10px; padding: 5px; font-size: 1.2em; } div.spacer { clear: both; } .next-page, .prev-page { display: block; float: left; margin: 0.5em 0; padding: 0.2em 0.5em 0.5em 0.5em; border-top: 1px solid gray; } .next-page { padding-right: 1em; } .prev-page { padding-left: 1em; } div#jifty-wait-message { background: #fff url(/static/images/css/spinner.gif) no-repeat scroll center center; position:fixed; top: 5px; right: 5px; height: 24px; width: 24px; padding: 5px; text-indent: 10em; z-index: 42; border-radius: 15px; -moz-border-radius: 15px; -webkit-border-radius: 15px; } div#jifty-region, div#jifty-region-lazy { display: inline; } div.warning { position: absolute; top: 0; left: 50%; right: 0; background-color: red; color: white; padding: .5em; border-bottom: 1px solid #000; } div.warning a { color: white; } ul.menu { display: block; } h1.title { border-bottom: 1px solid black; } jifty-1.10518+dfsg.orig/share/web/static/css/calendar.css0000644000175000017500000000067611447473536020746 0ustar fsfs.calendar { text-align: center; margin: 2em 0 0 0; } .calendar td, .calendar th { padding: 0.1em 0.25em 0.1em 0.25em; } .calendar caption .month { padding: 0 1em 0 1em; font-size: 1.5em; } .select-free { overflow: hidden; z-index:10; } .select-free iframe { display:none; display/**/:block; position:absolute; top:0; left:0; z-index:-1; filter:mask(); width:3000px; height:3000px; } jifty-1.10518+dfsg.orig/share/web/static/css/datetime.css0000644000175000017500000000007411447473536020761 0ustar fsfs.time { width: 80px; } .datetime { width: 270px; } jifty-1.10518+dfsg.orig/share/web/static/css/app-late.css0000644000175000017500000000000011447473536020655 0ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/keybindings.css0000644000175000017500000000055511447473536021477 0ustar fsfsdiv#keybindings { color: #666666; margin-top: 2em; } dl.keybindings .keybinding { display: inline; } dl.keybindings dt { margin: 0; font-weight: bold; display: inline; } dl.keybindings dt:after { content: ":"; } dl.keybindings dd { margin-right: 1.5em; margin-left: 0.5em; display: inline; white-space: nowrap; } jifty-1.10518+dfsg.orig/share/web/static/css/autohandler0000644000175000017500000000013411447473536020701 0ustar fsfs<%init> Jifty->web->response->content_type('text/css'); $m->call_next(); return(); jifty-1.10518+dfsg.orig/share/web/static/css/jquery.autocomplete.css0000644000175000017500000000143511447473536023206 0ustar fsfs.ac_results { padding: 0px; border: 1px solid black; background-color: white; overflow: hidden; z-index: 99999; } .ac_results ul { width: 100%; list-style-position: outside; list-style: none; padding: 0; margin: 0; } .ac_results li { margin: 0px; padding: 2px 5px; cursor: default; display: block; /* if width will be 100% horizontal scrollbar will apear when scroll mode will be used */ /*width: 100%;*/ font: menu; font-size: 12px; /* it is very important, if line-height not setted or setted in relative units scroll will be broken in firefox */ line-height: 16px; overflow: hidden; } .ac_loading { background: white url('indicator.gif') right center no-repeat; } .ac_odd { background-color: #eee; } .ac_over { background-color: #0A246A; color: white; } jifty-1.10518+dfsg.orig/share/web/static/css/main.css0000644000175000017500000000122311447473536020106 0ustar fsfs@import "app-base.css"; @import "base.css"; @import "nav.css"; @import "context-menus.css"; @import "calendar.css"; @import "combobox.css"; @import "keybindings.css"; @import "forms.css"; @import "crud.css"; @import "halos.css"; @import "app.css"; @import "autocomplete.css"; @import "yui/calendar/calendar-core.css"; @import "yui/calendar/calendar.css"; @import "yui/menu/menu-core.css"; @import "yui/menu/menu.css"; @import "notices.css"; @import "jquery.autocomplete.css"; @import "jquery.jgrowl.css"; @import "jquery.timepickr.css"; @import "facebox.css"; @import "datetime.css"; @import "ordered-list.css"; @import "uploads.css"; @import "app-late.css"; jifty-1.10518+dfsg.orig/share/web/static/css/halos.css0000644000175000017500000000501211447473536020270 0ustar fsfs.halo { border-color: #ffd700; border-style: solid; border-width: 0; margin: 0; padding: 0; } .halo-header { display: none; border-bottom: 1px solid #ffd700; background: #fff; margin: 3px; } .halo-rendermode { float: right; } .halo-source { font-family: monospace; } .halo-argument { position: absolute; left: 200px; border: 1px solid black; background: #ccc; padding: 1em; padding-top: 0; width: 300px; height: 500px; overflow: auto; } .halo_actions { position: fixed; border: 1px solid black; background: #ccc; } .halo_actions h1 { color: #fff; background-color: #600; border-bottom: 1px solid black; padding: 0.25em; margin: 0; cursor: pointer; font-size: 120%; } .halo_actions h1 a { color: #fff; } .halo_actions .resize { border: 5px solid #ccc; border-bottom-color: #000; border-right-color: #666; border-left-color: #aaa; cursor: pointer; color: #ccc; display: block; height: 0; width: 0; overflow: hidden; } .halo_actions .section { color: #ccc; background-color: #300; border-top: 1px solid black; margin-top: 0.5em; font-size: 120%; font-weight: bold; } .halo_actions .section a { text-align: center; color: #ccc; } .halo_actions .body { font-size: 110%; margin:0; padding:0 1em; } .halo_actions .body ul { margin:0; padding:0; margin-left: 1em; } .halo_actions .body .path { font-family: monospace; font-size: 120%; text-align: center; } .halo_actions .body .time { font-style: italic; text-align: center; } .halo_actions .body .fixed { font-family: monospace; } .halo_button { color: yellow; position: absolute; z-index: 9999; font-size:2em; } #render_info_tree { position: fixed; background: white; border: 1px solid yellow; right: 1em; bottom: 1em; border: 2px solid #fc0; padding: 1em; } #render_info_tree ul { list-style: none; padding-left: 1em; } #render_info { position: fixed; right:.5em; bottom:0; } a.inline_edit { display: block; width: 0; padding-left: 22px; min-height: 20px; background: no-repeat left center; background: url(/static/images/silk/pencil.png) no-repeat 0 0; } a.inline_create { display: block; width: 0; padding-left: 22px; min-height: 20px; background: no-repeat left center; background: url(/static/images/silk/pencil_add.png) no-repeat 0 0; } jifty-1.10518+dfsg.orig/share/web/static/css/combobox.css0000755000175000017500000000135111447473536020777 0ustar fsfs/* %# ComboBox styles... some properties like height and width must be dynamically %# set in the JS (at least for now). .combobox { %# border: 2px inset #333; %# padding-left: 0.5em; %# padding-bottom: 0.1em; } */ .combobox .combo-button { /*%# padding: 0 2px 0 2px;*/ padding-top: 2px; margin: 0; background: ButtonFace; color: ButtonText; border-right: 2px outset ButtonHighlight; border-bottom: 2px outset ButtonHighlight; border-top: 1px inset #000; border-left: 0px inset #fff; margin-left: 0; padding-left: 0; cursor: default; font-size: 8pt; } .combobox .combo-text { border: 1px inset #333; margin: 0; padding: 0; } .combobox .combo-list { z-index: 200; } jifty-1.10518+dfsg.orig/share/web/static/css/app-base.css0000644000175000017500000000000011447473536020642 0ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/app.css0000644000175000017500000000000011447473536017732 0ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/jquery.timepickr.css0000644000175000017500000000133611447473536022474 0ustar fsfs/* ui.dropslide */ .ui-dropslide { position:absolute; } .ui-dropslide ol { margin-top:2px; list-style:none; } .ui-dropslide li { float:left; } .ui-dropslide span { font-size:.7em; padding:4px 6px 4px 6px; margin-left:2px; text-align:center; cursor:pointer; -moz-border-radius:3px; -webkit-border-radius:3px; display:block; text-align:center; } .ui-timepickr ol li.hour, .ui-timepickr ol li.minute, .ui-timepickr ol li.second { width:30px; } /* dark theme */ .ui-timepickr.dark span { border:0; color:#ccc; background:#333; font-weight:bold; border:1px solid #555; } .ui-timepickr.dark span:hover { color:#eee; background:#333; border:1px solid #777; } jifty-1.10518+dfsg.orig/share/web/static/css/autocomplete.css0000644000175000017500000000017011447473536021663 0ustar fsfs/* Autocomplete */ .ac_value { font-style: italic; text-align: right; color: #AAA; font-size: .9em; } jifty-1.10518+dfsg.orig/share/web/static/css/forms.css0000644000175000017500000000554011447473536020316 0ustar fsfsdiv.form { background-color: #f6f6f6; padding: 0.2em; margin: 0 auto; } div.form_field { clear: both; padding-top: 0.5em; } .twocolumn { width: 49%; float: left; } div.form_field label.label, div.form_field span.label { float: left; width: 15%; text-align: right; font-size: 80%; padding: 0.2em 0.5em 0 0; } div.form_field .hints { width: 83%; font-size: 80%; padding-top: 0.2em; float: right; text-align: left; color: #999999; } div.form_field .error, div.form_field .warning, div.form_field .canonicalization_note { float: right; width: 88%; text-align: left; } div.form_field span.formw { float: right; width: 88%; text-align: left; } input.text, input.date, input.password, textarea, select { border-top: 1px solid #7c7c7c; border-left: 1px solid #c3c3c3; border-right: 1px solid #c3c3c3; border-bottom: 1px solid #ddd; background: #fff url(/static/images/css/fieldbg.gif) repeat-x top; padding: 0.2em; } form input.ajaxautocompletes { background: #fff url(/static/images/css/fieldbg-autocomplete.gif) repeat-x top right; padding-right: 18px; } input.date { width: 10em; } .submit_button { display: block; clear: both; } .submit_button input { clear: both; margin: 0.5em 0 0 16%; } input.button { padding: 0.15em 1em; font-weight: bold; } h2.inline input { font-size: 115%; } /* These styles are meant to be placed after (and hence override) the current CSS for forms. Some of the rules aren't needed if previous behavior doesn't need to be overridden. ".inline" is our inline form class. */ div.inline .submit_button { } div.inline div.form_field { float: left; /* to counter previous rules */ clear: none; /* aesthetic */ margin-right: 0.5em; } div.inline div.form_field label.label, div.inline div.form_field span, div.inline .hints, div.inline .error { display: block; /* to counter previous rules */ float: none; width: auto; text-align: left; } div.inline .hints { display: none; } div.inline div.form_field label.label { /* aesthetic */ padding-bottom: 0.1em; } /* So the admin ui is one row per line */ .jifty_admin.item.inline { clear: both; } .jifty_admin .editlink { float: right; } .jifty_admin_header { display: inline; } .jifty_admin_header a { color: black; display: block; font-size: 0.6em; height: 100%; text-decoration: none; font-family : sans-serif; } div.subline { display: inline; float: left; } option.selected { background: #dddddd; } input.placeholder, textarea.placeholder { color: #666; } form div.mandatory .label { font-weight: bold; } form ul.checkboxlist { display: block; float: left; } form ul.checkboxlist li.checkboxlistitem{ list-style-type: none; } jifty-1.10518+dfsg.orig/share/web/static/css/nav.css0000644000175000017500000000344611447473536017757 0ustar fsfs/* from http://www.456bereastreet.com/lab/csstabs/nested/# */ div#navigation { width:598px; height:45px; position:relative; } div#navigation ul { width:598px; font-family:Tahoma,"Trebuchet MS", sans-serif; font-size:11px; line-height:11px; color:#000; } ul.menu { margin:0; padding:6px 0 5px 0; background-color:#202F66; list-style-type:none; border-bottom:2px solid #000; } ul.menu li { display:inline; margin:0; padding:0; } ul.submenu { margin:0; padding:5px 0; background-color:#24568E; list-style-type:none; position: absolute; top: 22px; left:0; } ul.submenu li { display:inline; margin:0; padding:0; } ul.submenu li+li { border-left:1px solid #ccc; } div#navigation a:link, div#navigation a:visited, div#navigation a:hover { color:#fff; text-decoration:none; padding:5px; background-color:#202F66; } div#navigation ul.menu a:link, div#navigation ul.menu a:visited, div#navigation ul.menu a:hover { font-weight:bold; border:1px solid #000; text-transform:uppercase; } div#navigation ul.menu a:hover { background-color:#24568E; } div#navigation ul.menu li.active a:link, div#navigation ul.menu li.active a:visited, div#navigation ul.menu li.active a:hover { background-color:#24568E; font-weight: bold; border-bottom-color:#24568E; } div#navigation ul.submenu a:link, div#navigation ul.submenu a:visited, div#navigation ul.submenu a:hover { font-weight:normal; padding:0 5px; background-color:#24568E; border:0; } div#navigation ul.submenu a:hover { text-decoration:underline; } jifty-1.10518+dfsg.orig/share/web/static/css/facebox.css0000644000175000017500000000276611447473536020606 0ustar fsfs/* This file has been changed for Jifty. Please see the commit log for its * changes before upgrading */ #facebox .b { background:url(/static/images/facebox/b.png); } #facebox .tl { background:url(/static/images/facebox/tl.png); } #facebox .tr { background:url(/static/images/facebox/tr.png); } #facebox .bl { background:url(/static/images/facebox/bl.png); } #facebox .br { background:url(/static/images/facebox/br.png); } #facebox { position: absolute; top: 0; left: 0; z-index: 100; text-align: left; } #facebox .popup { position: relative; } #facebox table { border-collapse: collapse; } #facebox td { border-bottom: 0; padding: 0; } #facebox .body { padding: 10px; background: #fff; width: 370px; } #facebox .loading { text-align: center; } #facebox .image { text-align: center; } #facebox img { border: 0; margin: 0; } #facebox .footer { border-top: 1px solid #DDDDDD; padding-top: 5px; margin-top: 10px; text-align: right; } #facebox .tl, #facebox .tr, #facebox .bl, #facebox .br { height: 10px; width: 10px; overflow: hidden; padding: 0; } #facebox_overlay { position: fixed; top: 0px; left: 0px; height:100%; width:100%; } .facebox_hide { z-index:-100; } .facebox_overlayBG { background-color: #000; z-index: 99; } * html #facebox_overlay { /* ie6 hack */ position: absolute; height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); } jifty-1.10518+dfsg.orig/share/web/static/css/yui/0000755000175000017500000000000011565006013017237 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/yui/menu/0000755000175000017500000000000011625457665020227 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/yui/menu/menu-core.css0000644000175000017500000001165511447473536022640 0ustar fsfs/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.4.1 */ /* Menu & MenuBar styles */ .yuimenubar { visibility: visible; position: static; } .yuimenu .yuimenu, .yuimenubar .yuimenu { visibility: hidden; position: absolute; top: -10000px; left: -10000px; } .yuimenubar li, .yuimenu li { list-style-type: none; } .yuimenubar ul, .yuimenu ul, .yuimenubar li, .yuimenu li, .yuimenu h6, .yuimenubar h6 { margin: 0; padding: 0; } .yuimenuitemlabel, .yuimenubaritemlabel { text-align: left; white-space: nowrap; } /* The following style rule trigger the "hasLayout" property in IE (http://msdn2.microsoft.com/en-us/library/ms533776.aspx) for a MenuBar instance's
      element, allowing both to clear their floated child
    • elements. */ .yuimenubar ul { *zoom: 1; } /* Remove the "hasLayout" trigger for submenus of MenuBar instances as it is unnecessary. */ .yuimenubar .yuimenu ul { *zoom: normal; } /* The following style rule allows a MenuBar instance's
        element to clear its floated
      • elements in Firefox, Safari and and Opera. */ .yuimenubar>.bd>ul:after { content: "."; display: block; clear: both; visibility: hidden; height: 0; line-height: 0; } .yuimenubaritem { float: left; } .yuimenubaritemlabel, .yuimenuitemlabel { display: block; } .yuimenuitemlabel .helptext { font-style: normal; display: block; /* The value for the left margin controls how much the help text is offset from the text of the menu item. This value will need to be customized depending on the longest text label of a menu item. */ margin: -1em 0 0 10em; } /* PLEASE NOTE: The
        element used for a menu's shadow is appended to its root element via JavaScript once it has been rendered. The code that creates the shadow lives in the menu's public "onRender" event handler that is a prototype method of YAHOO.widget.Menu. Implementers wishing to remove a menu's shadow or add any other markup required for a given skin for menu should override the "onRender" method. */ .yui-menu-shadow { position: absolute; visibility: hidden; z-index: -1; } .yui-skin-sam .yui-menu-shadow-visible { top: 2px; right: -3px; left: -3px; bottom: -3px; visibility: visible; } /* There are two known issues with YAHOO.widget.Overlay (the superclass class of Menu) that manifest in Gecko-based browsers on Mac OS X: 1) Elements with scrollbars will poke through Overlay instances floating above them. 2) An Overlay's scrollbars and the scrollbars of its child nodes remain visible when the Overlay is hidden. To fix these bugs in Menu (a subclass of YAHOO.widget.Overlay): 1) The "overflow" property of a Menu instance's shadow element and child nodes is toggled between "hidden" and "auto" (through the application and removal of the "hide-scrollbars" and "show-scrollbars" CSS classes) as its "visibility" configuration property is toggled between "false" and "true." 2) The "display" property of elements that are child nodes of the Menu instance's root element is set to "none" when it is hidden. PLEASE NOTE: 1) The "hide-scrollbars" and "show-scrollbars" CSS classes classes are applied only for Gecko on Mac OS X and are added/removed to/from the Overlay's root HTML element (DIV) via the "hideMacGeckoScrollbars" and "showMacGeckoScrollbars" methods of YAHOO.widget.Overlay. 2) There may be instances where the CSS for a web page or application contains style rules whose specificity override the rules implemented by the Menu CSS files to fix this bug. In such cases, is necessary to leverage the provided "hide-scrollbars" and "show-scrollbars" classes to write custom style rules to guard against this bug. ** For more information on this issue, see: + https://bugzilla.mozilla.org/show_bug.cgi?id=187435 + SourceForge bug #1723530 */ .hide-scrollbars * { overflow: hidden; } .hide-scrollbars select { display: none; } /* The following style rule (".yuimenu.show-scrollbars") overrides the ".show-scrollbars" rule defined in container-core.css which sets the "overflow" property of a YAHOO.widget.Overlay instance's root HTML element to "auto" when it is visible. Without this override, a Menu would have scrollbars when one of its submenus is visible. */ .yuimenu.show-scrollbars, .yuimenubar.show-scrollbars { overflow: visible; } .yuimenu.hide-scrollbars .yui-menu-shadow, .yuimenubar.hide-scrollbars .yui-menu-shadow { overflow: hidden; } .yuimenu.show-scrollbars .yui-menu-shadow, .yuimenubar.show-scrollbars .yui-menu-shadow { overflow: auto; } /* MenuBar style rules */ .yuimenubar { background-color: #f6f7ee; } /* Menu style rules */ .yuimenu { background-color: #f6f7ee; border: solid 1px #c4c4be; padding: 1px; } .yui-menu-shadow { display: none; } .yuimenu ul { border: solid 1px #c4c4be; border-width: 1px 0 0 0; padding: 10px 0; } .yuimenu .yui-menu-body-scrolled { overflow: hidden; } /* Group titles */ .yuimenu h6, .yuimenubar h6 { font-size: 100%; font-weight: normal; border: solid 1px #c4c4be; color: #b9b9b9; } .yuimenubar h6 { float: left; padding: 4px 12px; border-width: 0 1px 0 0; } .yuimenubar .yuimenu h6 { float: none; } .yuimenu h6 { border-width: 1px 0 0 0; padding: 5px 10px 0 10px; } .yuimenu ul.first-of-type, .yuimenu ul.hastitle, .yuimenu h6.first-of-type { border-width: 0; } /* Top and bottom scroll controls */ .yuimenu .topscrollbar, .yuimenu .bottomscrollbar { height: 16px; background-position: center center; background-repeat: no-repeat; } .yuimenu .topscrollbar { background-image: url(/static/images/yui/menu/menu_up_arrow.png); } .yuimenu .topscrollbar_disabled { background-image: url(/static/images/yui/menu/menu_up_arrow_disabled.png); } .yuimenu .bottomscrollbar { background-image: url(/static/images/yui/menu/menu_down_arrow.png); } .yuimenu .bottomscrollbar_disabled { background-image: url(/static/images/yui/menu/menu_down_arrow_disabled.png); } /* MenuItem and MenuBarItem styles */ .yuimenuitem { /* For IE: Used to collapse superfluous white space between
      • elements that is triggered by the "display" property of the elements being set to "block." */ *border-bottom: solid 1px #f6f7ee; } .yuimenuitemlabel, .yuimenubaritemlabel { font-size: 85%; color: #000; text-decoration: none; } .yuimenuitemlabel { padding: 2px 24px; } .yuimenubaritemlabel { border-width: 0 0 0 1px; border-style: solid; border-color: #c4c4be; padding: 4px 24px; } .yuimenubar li.first-of-type .yuimenubaritemlabel { border-width: 0; } .yuimenubaritem-hassubmenu { background: url(/static/images/yui/menu/menubaritem_submenuindicator.png) right center no-repeat; } .yuimenuitem-hassubmenu { background: url(/static/images/yui/menu/menuitem_submenuindicator.png) right center no-repeat; } .yuimenuitem-checked { background: url(/static/images/yui/menu/menuitem_checkbox.png) left center no-repeat; } .yuimenuitemlabel .helptext { margin-top: -1.1em; *margin-top: -1.2em; /* For IE*/ } /* MenuItem states */ /* Selected MenuItem */ .yuimenubaritem-selected, .yuimenuitem-selected { background-color: #8c8ad0; } .yuimenubaritemlabel-selected, .yuimenuitemlabel-selected { text-decoration: underline; color: #fff; } .yuimenubaritem-hassubmenu-selected { background-image: url(/static/images/yui/menu/menubaritem_submenuindicator_selected.png); } .yuimenuitem-hassubmenu-selected { background-image: url(/static/images/yui/menu/menuitem_submenuindicator_selected.png); } .yuimenuitem-checked-selected { background-image: url(/static/images/yui/menu/menuitem_checkbox_selected.png); } /* Disabled MenuItem */ .yuimenubaritemlabel-disabled, .yuimenuitemlabel-disabled { cursor: default; color: #b9b9b9; } .yuimenubaritem-hassubmenu-disabled { background-image: url(/static/images/yui/menu/menubaritem_submenuindicator_disabled.png); } .yuimenuitem-hassubmenu-disabled { background-image: url(/static/images/yui/menu/menuitem_submenuindicator_disabled.png); } .yuimenuitem-checked-disabled { background-image: url(/static/images/yui/menu/menuitem_checkbox_disabled.png); } jifty-1.10518+dfsg.orig/share/web/static/css/yui/tabview/0000755000175000017500000000000011565006010020675 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/yui/tabview/tabview-core.css0000644000175000017500000000531111447473536024022 0ustar fsfs/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.4.1 */ /* default space between tabs */ .yui-navset .yui-nav li, .yui-navset .yui-navset-top .yui-nav li, .yui-navset .yui-navset-bottom .yui-nav li { margin:0 0.5em 0 0; /* horizontal tabs */ } .yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li { margin:0 0 0.5em; /* vertical tabs */ } /* default width for side tabs */ .yui-navset .yui-navset-left .yui-nav, .yui-navset .yui-navset-right .yui-nav, .yui-navset-left .yui-nav, .yui-navset-right .yui-nav { width:6em; } .yui-navset-top .yui-nav, .yui-navset-bottom .yui-nav { width:auto; } .yui-navset .yui-navset-left, .yui-navset-left { padding:0 0 0 6em; } /* map to nav width */ .yui-navset-right { padding:0 6em 0 0; } /* ditto */ .yui-navset-top, .yui-navset-bottom { padding:auto; } /* core */ .yui-nav, .yui-nav li { margin:0; padding:0; list-style:none; } .yui-navset li em { font-style:normal; } .yui-navset { position:relative; /* contain absolute positioned tabs (left/right) */ zoom:1; } .yui-navset .yui-content { zoom:1; } .yui-navset .yui-nav li, .yui-navset .yui-navset-top .yui-nav li, /* in case nested */ .yui-navset .yui-navset-bottom .yui-nav li { display:inline-block; display:-moz-inline-stack; *display:inline; /* IE */ vertical-align:bottom; /* safari: for overlap */ cursor:pointer; /* gecko: due to -moz-inline-stack on anchor */ zoom:1; /* IE: kill space between horizontal tabs */ } .yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li { display:block; } .yui-navset .yui-nav a { position:relative; } /* IE: to allow overlap */ .yui-navset .yui-nav li a, .yui-navset-top .yui-nav li a, .yui-navset-bottom .yui-nav li a { display:block; display:inline-block; vertical-align:bottom; /* safari: for overlap */ zoom:1; } .yui-navset-left .yui-nav li a, .yui-navset-right .yui-nav li a { display:block; } .yui-navset-bottom .yui-nav li a { vertical-align:text-top; /* for inline overlap (reverse for Opera border bug) */ } .yui-navset .yui-nav li a em, .yui-navset-top .yui-nav li a em, .yui-navset-bottom .yui-nav li a em { display:block; } /* position left and right oriented tabs */ .yui-navset .yui-navset-left .yui-nav, .yui-navset .yui-navset-right .yui-nav, .yui-navset-left .yui-nav, .yui-navset-right .yui-nav { position:absolute; z-index:1; } .yui-navset-top .yui-nav, .yui-navset-bottom .yui-nav { position:static; } .yui-navset .yui-navset-left .yui-nav, .yui-navset-left .yui-nav { left:0; right:auto; } .yui-navset .yui-navset-right .yui-nav, .yui-navset-right .yui-nav { right:0; left:auto; } jifty-1.10518+dfsg.orig/share/web/static/css/yui/tabview/tabview.css0000644000175000017500000000371211447473536023077 0ustar fsfs/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.4.1 */ /* default space between tabs */ .yui-navset .yui-nav li { margin-right:0.5em; /* horizontal tabs */ } .yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li { margin:0 0 0.5em; /* vertical tabs */ } /* default width for side tabs */ .yui-navset-left .yui-nav, .yui-navset-right .yui-nav { width:6em; } .yui-navset-left { padding-left:6em; } /* map to nav width */ .yui-navset-right { padding-right:6em; } /* ditto */ /* core */ .yui-nav, .yui-nav li { margin:0; padding:0; list-style:none; } .yui-navset li em { font-style:normal; } .yui-navset { position:relative; /* contain absolute positioned tabs (left/right) */ zoom:1; } .yui-navset .yui-content { zoom:1; } .yui-navset .yui-nav li { display:inline-block; display:-moz-inline-stack; *display:inline; /* IE */ vertical-align:bottom; /* safari: for overlap */ cursor:pointer; /* gecko: due to -moz-inline-stack on anchor */ zoom:1; /* IE: kill space between horizontal tabs */ } .yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li { display:block; } .yui-navset .yui-nav a { outline:0; /* gecko: keep from shifting */ } .yui-navset .yui-nav a { position:relative; } /* IE: to allow overlap */ .yui-navset .yui-nav li a { display:block; display:inline-block; vertical-align:bottom; /* safari: for overlap */ zoom:1; } .yui-navset-left .yui-nav li a, .yui-navset-right .yui-nav li a { display:block; } .yui-navset-bottom .yui-nav li a { vertical-align:text-top; /* for inline overlap (reverse for Op border bug) */ } .yui-navset .yui-nav li a em { display:block; } /* position left and right oriented tabs */ .yui-navset-left .yui-nav, .yui-navset-right .yui-nav { position:absolute; z-index:1; } .yui-navset-left .yui-nav { left:0; } .yui-navset-right .yui-nav { right:0; } jifty-1.10518+dfsg.orig/share/web/static/css/yui/tabview/border_tabs.css0000644000175000017500000000307411447473536023725 0ustar fsfs/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.4.1 */ .yui-navset .yui-nav li a, .yui-navset .yui-content { border:1px solid #000; /* label and content borders */ } .yui-navset .yui-nav .selected a, .yui-navset .yui-nav a:hover, .yui-navset .yui-content { background-color:#f6f7ee; /* active tab, tab hover, and content bgcolor */ } .yui-navset .yui-nav li em { padding:.5em; } /* tab padding */ /* defaults to orientation "top" */ .yui-navset .yui-nav .selected a { border-bottom-width:0; /* no bottom border for active tab */ padding-bottom:1px; /* to match height of other tabs */ } .yui-navset .yui-content { margin-top:-1px; /* for active tab overlap */ } /* overrides for other orientations */ .yui-navset-bottom .yui-nav .selected a { border-width:0 1px 1px; /* no top border for active tab */ padding:1px 0 0; /* to match height of other tabs */ } .yui-navset-bottom .yui-content { margin:0 0 -1px; /* for active tab overlap */ } .yui-navset-left .yui-nav li.selected a { border-width:1px 0 1px 1px; /* no right border for active tab */ padding:0 1px 0 0; /* to match width of other tabs */ } .yui-navset-left .yui-content { margin:0 0 0 -1px; /* for active tab overlap */ } .yui-navset-right .yui-nav li.selected a { border-width:1px 1px 1px 0; /* no left border for active tab */ padding:0 0 0 1px; /* to match width of other tabs */ } .yui-navset-right .yui-content { margin:0 -1px 0 0; /* for active tab overlap */ }jifty-1.10518+dfsg.orig/share/web/static/css/yui/calendar/0000755000175000017500000000000011625457665021034 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/css/yui/calendar/calendar.css0000644000175000017500000001256211447473536023322 0ustar fsfs/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.4.1 */ .yui-calcontainer { position:relative; padding:5px; background-color:#F7F9FB; border:1px solid #7B9EBD; float:left; _overflow:hidden; /* IE6 only, to clip iframe shim */ } .yui-calcontainer iframe { position:absolute; border:none; margin:0;padding:0; z-index:0; width:100%; height:100%; left:0px; top:0px; } /* IE6 only */ .yui-calcontainer iframe.fixedsize { width:50em; height:50em; top:-1px; left:-1px; } .yui-calcontainer.multi { padding:0; } .yui-calcontainer.multi .groupcal { padding:5px; background-color:transparent; z-index:1; float:left; position:relative; border:none; } .yui-calcontainer .title { font:100% sans-serif; color:#000; font-weight:bold; margin-bottom:5px; height:25px; position:absolute; top:3px;left:5px; z-index:1; } .yui-calcontainer .close-icon { position:absolute; right:3px; top:3px; border:none; z-index:1; } .yui-calcontainer .calclose { background: url("/static/images/yui/calendar/calx.gif") no-repeat; width:17px; height:13px; cursor:pointer; } /* Calendar element styles */ .yui-calendar { font:100% sans-serif; text-align:center; border-spacing:0; border-collapse:separate; position:relative; } .yui-calcontainer.withtitle { padding-top:1.5em; } .yui-calendar .calnavleft { position:absolute; cursor:pointer; top:2px; bottom:0; width:9px; height:12px; left:2px; z-index:1; background: url("/static/images/yui/calendar/callt.gif") no-repeat; } .yui-calendar .calnavright { position:absolute; cursor:pointer; top:2px; bottom:0; width:9px; height:12px; right:2px; z-index:1; background: url("/static/images/yui/calendar/calrt.gif") no-repeat; } .yui-calendar td.calcell { padding:.1em .2em; border:1px solid #E0E0E0; text-align:center; } .yui-calendar td.calcell a { color:#003DB8; text-decoration:none; } .yui-calendar td.calcell.today { border:1px solid #000; } .yui-calendar td.calcell.oom { cursor:default; color:#999; background-color:#EEE; border:1px solid #E0E0E0; } .yui-calendar td.calcell.selected { color:#003DB8; background-color:#FFF19F; border:1px solid #FF9900; } .yui-calendar td.calcell.calcellhover { cursor:pointer; color:#FFF; background-color:#FF9900; border:1px solid #FF9900; } .yui-calendar td.calcell.calcellhover a { color:#FFF; } .yui-calendar td.calcell.restricted { text-decoration:line-through; } .yui-calendar td.calcell.previous { color:#CCC; } .yui-calendar td.calcell.highlight1 { background-color:#CCFF99; } .yui-calendar td.calcell.highlight2 { background-color:#99CCFF; } .yui-calendar td.calcell.highlight3 { background-color:#FFCCCC; } .yui-calendar td.calcell.highlight4 { background-color:#CCFF99; } .yui-calendar .calhead { border:1px solid #E0E0E0; vertical-align:middle; background-color:#FFF; } .yui-calendar .calheader { position:relative; width:100%; text-align:center; } .yui-calendar .calheader img { border:none; } .yui-calendar .calweekdaycell { color:#666; font-weight:normal; text-align:center; width:1.5em; } .yui-calendar .calfoot { background-color:#EEE; } .yui-calendar .calrowhead, .yui-calendar .calrowfoot { color:#666; font-size:9px; font-style:italic; font-weight:normal; width:15px; } .yui-calendar .calrowhead { border-right-width:2px; } /* CalendarNavigator */ .yui-calendar a.calnav { _position:relative; padding-left:2px; padding-right:2px; text-decoration:none; color:#000; } .yui-calendar a.calnav:hover { border:1px solid #003366; background-color:#6699cc; background: url(/static/images/yui/calendar/calgrad.png) repeat-x; color:#fff; cursor:pointer; } .yui-calcontainer .yui-cal-nav-mask { position:absolute; z-index:2; display:none; margin:0; padding:0; left:0; top:0; width:100%; height:100%; _width:0; /* IE6, IE7 Quirks - width/height set programmatically to match container */ _height:0; background-color:#000; opacity:0.25; *filter:alpha(opacity=25); } .yui-calcontainer .yui-cal-nav { position:absolute; z-index:3; display:none; padding:0; top:1.5em; left:50%; width:12em; margin-left:-6em; border:1px solid #7B9EBD; background-color:#F7F9FB; font-size:93%; } .yui-calcontainer.withtitle .yui-cal-nav { top:3.5em; } .yui-calcontainer .yui-cal-nav-y, .yui-calcontainer .yui-cal-nav-m, .yui-calcontainer .yui-cal-nav-b { padding:2px 5px 2px 5px; } .yui-calcontainer .yui-cal-nav-b { text-align:center; } .yui-calcontainer .yui-cal-nav-e { margin-top:2px; padding:2px; background-color:#EDF5FF; border-top:1px solid black; display:none; } .yui-calcontainer .yui-cal-nav label { display:block; font-weight:bold; } .yui-calcontainer .yui-cal-nav-mc { width:100%; _width:auto; /* IE6 doesn't like width 100% */ } .yui-calcontainer .yui-cal-nav-y input.yui-invalid { background-color:#FFEE69; border: 1px solid #000; } .yui-calcontainer .yui-cal-nav-yc { width:3em; } .yui-calcontainer .yui-cal-nav-b button { font-size:93%; text-decoration:none; cursor: pointer; background-color: #79b2ea; border: 1px solid #003366; border-top-color:#FFF; border-left-color:#FFF; margin:1px; } .yui-calcontainer .yui-cal-nav-b .yui-default button { /* not implemented */ } /* Specific changes for calendar running under fonts/reset */ .yui-calendar .calbody a:hover {background:inherit;} p#clear {clear:left; padding-top:10px;} jifty-1.10518+dfsg.orig/share/web/static/css/yui/calendar/calendar-core.css0000644000175000017500000000467311447473536024254 0ustar fsfs/* Copyright (c) 2007, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.4.1 */ /** * CORE * * This is the set of CSS rules required by Calendar to drive core functionality and structure. * Changes to these rules may result in the Calendar not functioning or rendering correctly. * * They should not be modified for skinning. **/ /* CALENDAR BOUNDING BOX */ .yui-calcontainer { position:relative; float:left; _overflow:hidden; /* IE6 only, to clip iframe shim */ } /* IFRAME SHIM */ .yui-calcontainer iframe { position:absolute; border:none; margin:0;padding:0; z-index:0; width:100%; height:100%; left:0px; top:0px; } /* IFRAME SHIM IE6 only */ .yui-calcontainer iframe.fixedsize { width:50em; height:50em; top:-1px; left:-1px; } /* BOUNDING BOX FOR EACH CALENDAR GROUP PAGE */ .yui-calcontainer.multi .groupcal { z-index:1; float:left; position:relative; } /* TITLE BAR */ .yui-calcontainer .title { position:relative; z-index:1; } /* CLOSE ICON CONTAINER */ .yui-calcontainer .close-icon { position:absolute; z-index:1; } /* CALENDAR TABLE */ .yui-calendar { position:relative; } /* NAVBAR LEFT ARROW CONTAINER */ .yui-calendar .calnavleft { position:absolute; z-index:1; } /* NAVBAR RIGHT ARROW CONTAINER */ .yui-calendar .calnavright { position:absolute; z-index:1; } /* NAVBAR TEXT CONTAINER */ .yui-calendar .calheader { position:relative; width:100%; text-align:center; } /* CalendarNavigator */ .yui-calcontainer .yui-cal-nav-mask { position:absolute; z-index:2; margin:0; padding:0; width:100%; height:100%; _width:0; /* IE6, IE7 quirks - width/height set programmatically to match container */ _height:0; left:0; top:0; display:none; } /* NAVIGATOR BOUNDING BOX */ .yui-calcontainer .yui-cal-nav { position:absolute; z-index:3; top:0; display:none; } /* NAVIGATOR BUTTONS (based on button-core.css) */ .yui-calcontainer .yui-cal-nav .yui-cal-nav-btn { display: -moz-inline-box; /* Gecko */ display: inline-block; /* IE, Opera and Safari */ } .yui-calcontainer .yui-cal-nav .yui-cal-nav-btn button { display: block; *display: inline-block; /* IE */ *overflow: visible; /* Remove superfluous padding for IE */ border: none; background-color: transparent; cursor: pointer; } /* Specific changes for calendar running under fonts/reset */ .yui-calendar .calbody a:hover {background:inherit;} p#clear {clear:left; padding-top:10px;}jifty-1.10518+dfsg.orig/share/web/static/css/notices.css0000644000175000017500000000220111447473536020623 0ustar fsfs/* IE can't handle this nicely w/ AJAX validation */ html>body .message { background: url(/static/images/silk/information.png) no-repeat center left; padding-left: 20px; } html>body .error { background: url(/static/images/silk/error.png) no-repeat center left; padding-left: 20px; } .error { color: #a00000; } div#messages, div#errors { background-color: rgb(240,234,183); border: 1px solid rgb(230,224,173); margin-top: 10px; margin-bottom: 10px; padding: 5px 20px 5px 5px; font-size: 1.2em; position: relative; } #dismiss_messages, #dismiss_errors { padding-left: 16px; background: url(/static/images/silk/cancel_grey.png) no-repeat; position: absolute; top: 0.4em; right: 2px; width: 0; display: block; text-indent: -9999em; } #jGrowl .result-message .message { background: url(/static/images/silk/information.png) no-repeat center left; padding-left: 20px; } #jGrowl .result-error { background: #a00000; } #jGrowl .result-error .message { background: url(/static/images/silk/error.png) no-repeat center left; padding-left: 20px; } jifty-1.10518+dfsg.orig/share/web/static/css/crud.css0000644000175000017500000000303211447473536020117 0ustar fsfs.crud-ui { } .crud-search { } .crud-pages { } .crud-paging { } .crud-table { display: table; } .crud-column-headers { display: table-header-group; } .crud-column-header, .crud-field { display: table-cell; padding-left: .2em; padding-right: .2em; } .crud-list { background: #FFFFFF; } /* this is the fallback for when you do not have css 3 */ .crud-list div.odd { background: #DDFFFF; } /* this is more robust as it permits adding/removing rows */ /* XXX: it's not ready yet because there are intermittent script tags only * in the original CRUD, not in region updates. argh */ /*.crud-list > div:nth-child(odd) { background: #DDFFFF; }*/ .crud-list { display: table-row-group; } .crud-create { } .crud-item { display: table-row; } .field { float: left; margin: 0.15em 0.5em 0.15em 0.15em; font-weight: bold; } .crud-sort-menu { float: left; } .crud-column-header img { vertical-align:middle; border: 0; } .crud-column-headers a { color: black; float: left; font-size: 0.8em; height: 100%; text-decoration: none; font-family : sans-serif; } .crud-column-header ul { list-style-type:none; margin: 0; padding: 0; border: 1px solid #ccc; } .crud-column-header li { float:left; } .paging-nav { font-size: 0.8em; } .paging-nav a, .paging-nav a:active, .paging-nav a:hover, .paging-nav a:visited { color: #0000FF; } .paging-nav .current { font-weight: bold; } .paging-prev, .paging-next, .paging-all { font-size: 0.8em; } jifty-1.10518+dfsg.orig/share/web/static/css/context-menus.css0000644000175000017500000000401511447473536021775 0ustar fsfsul.context_menu { clear: none; float: left; } ul.context_menu, ul.context_menu ul { list-style: none; margin-left: 0; padding-left: 0; } .context_menu li.toplevel { float: left; margin: 0 0.5em 0 0; padding: 0.2em; border: 1px solid #ccc; border-top-color: white; border-left-color: white; color: #793300; } .context_menu li.toplevel ul li { color: gray; } .context_menu li.toplevel .title { font-weight: bold; } .context_menu li.toplevel ul { font-size: 0.9em; display: none; padding: 0.1em 0.2em 0.5em 0.1em; background: white; border-top: 1px dotted lightgrey; border-left: 1px solid lightgrey; border-right: 1px solid grey; border-bottom: 1px solid grey; } .context_menu li.toplevel ul a { width: 100%; display: block; } .context_menu .open span.expand a { background-image: url(/static/images/silk/bullet_arrow_up.png); } .context_menu span.expand a { background: url(/static/images/silk/bullet_arrow_down.png) no-repeat center center; padding-left: 16px; border: 1px solid transparent; color: white; margin-left: 0.3em; min-height: 1em; } .context_menu li.toplevel:hover .expand a { border-top: 1px solid grey; border-left: 1px solid grey; border-right: 1px solid lightgrey; border-bottom: 1px solid lightgrey; } .context_menu li.open a { border-bottom-color: transparent; } .context_menu li.open, .context_menu li.closed:hover { border-top: 1px solid lightgrey; border-left: 1px solid lightgrey; border-right: 1px solid grey; border-bottom-color: transparent; } .context_menu li.closed:hover { border-bottom-color: grey; } .context_menu li.toplevel span.expand a:active { border-top: 1px solid white; border-left: 1px solid white; border-right: 1px solid grey; border-bottom: 1px solid grey; position: relative; top: 1px; left: 1px; } .context_menu li ul li { padding: 0.2em; } .context_menu li.open ul li:hover { background: #eee; } jifty-1.10518+dfsg.orig/share/web/static/js/0000755000175000017500000000000011625457665016301 5ustar fsfsjifty-1.10518+dfsg.orig/share/web/static/js/app_behaviour.js0000644000175000017500000001062211447473536021461 0ustar fsfs/* This file is intended for you to add application-specific Javascript behaviours. Behaviour lets you apply javascript to elements of the DOM using CSS selectors. A simple example: var myrules = { "h2.rounded": function(element) { doRounding(element); } }; Behaviour.register(myrules); In general, you'll rarely if ever have to worry about calling Behaviour.apply() yourself -- Jifty will take care of it on DOM load and on any AJAX updates that it does. Some Notes About Writing Behaviours =================================== * Jifty's Behaviour.js uses the jQuery[1] library to do our DOM lookups by CSS selector. jQuery is very powerful, but can be slower as the DOM size grows. For best performance, follow these guidelines when writing behaviours, whenever possible: * Prefer selectors that begin with '#id'. jQuery will use document.getElementByID to get the ID in question, meaning we only have to search a small fragment of the DOM by hand * Barring that, prefer selectors of the form 'element.class' over simply '.class' selectors. This lets us filter for that element specifically using DOM calls, again hugely reducing the amount of DOM walking we have to do. [1] http://jquery.com * Behaviour has something of a reputation for leaking memory. The reason for this is a common idiom used in constructing behaviours. Code like: Behaviour.register({ 'a.help': function(e) { e.onclick = function() { openInHelpWindow(this); return false; } } }); will leak memory in Internet Explorer, thanks to how IE handles garbage collection (See the footnote for details). To avoid this, you can use one of the following two idioms: (a) Use jQuery to bind events like onclick: Behaviour.register({ 'a.help': function(e) { jQuery(e).click(function() { openInHelpWindow(this); return false; }); } }); (b) Declare the onclick function elsewhere: function openHelpLink() { openInHelpWindow(this); return false; } Behaviour.register({ 'a.help': function(e) { e.onclick = openHelpLink; } }); (c) Set the element to 'null' at the end of the Behaviour function: Behaviour.register({ 'a.help': function(e) { e.onclick = function() { openInHelpWindow(this); return false; } e = null; } }); * Jifty has recently gained built-in support for limited profiling of Behaviours via the ProfileBehaviour plugin (in the Jifty svn tree). After installing the module, add it to your config.yml, using, e.g: Plugins: - ProfileBehaviour: {} Once you do this, all pages in your application should have a ``Behaviour profile'' link at the bottom left hand corner of the screen. Click it to get a breakdown of how much time your javascript is spending in which behaviours, and whether the time is spent in looking up the CSS Selector you passed (jQuery time), or in applying the Behaviour function (function time). ** Footnote ** The reason that code leaks in IE is that Internet Explorer uses reference counting to manage memory in its Javascript engine, which means that circular references are never freed. When you write this code: Behaviour.register({ 'a.help': function(e) { // <-- FUNCTION A e.onclick = function() { // <-- FUNCTION B openInHelpWindow(this); return false; } } }); You are in fact creating a circular data structure because function `B', when it is created, stores a reference to the environment in which it was created, which includes the variable `e'. `e', however, also references function `B' through its `onclick' property, and this a circular chain of references is created, which IE will never garbage collect. Solution (b) addresses this by moving function `b' outside of the scope where `e' is defined. Solution (c) addresses it by setting `e' to null in the environment around `b', which means that that environment no longer contains a reference to that DOM node, and the loop no longer exists. */ jifty-1.10518+dfsg.orig/share/web/static/js/datetime.js0000644000175000017500000001103411447473536020427 0ustar fsfsif ( typeof Jifty == "undefined" ) Jifty = { }; Jifty.DateTime = { registerDateTimeWidget: function(id) { jQuery(id).bind("focus", Jifty.DateTime.toggleDateTime) .bind("blur", Jifty.DateTime.doBlur); return true; }, dateRegex: /^(\d{4})\W(\d{2})\W(\d{2})/, Options: { OUT_OF_MONTH_SELECT: true }, toggleDateTime: function() { var calId = "cal_" + this.id; var wrapId = calId + "_wrap"; var wrap = document.getElementById(wrapId); if ( Jifty.DateTime.openDateTime == wrapId ) { Jifty.DateTime.hideOpenDateTime(); return; } Jifty.DateTime.hideOpenDateTime(); /* We need to delay Jifty's canonicalization until after we've selected a value via the calendar */ Jifty.Form.Element.disableValidation(this); wrap = document.createElement("div"); wrap.setAttribute( "id", wrapId ); wrap.setAttribute( "class", "select-free" ); wrap.style.position = "absolute"; wrap.style.left = Jifty.Utils.findRelativePosX( this ) + "px"; wrap.style.top = Jifty.Utils.findRelativePosY( this ) + this.offsetHeight + "px"; wrap.style.zIndex = 40; this.parentNode.insertBefore( wrap, this.nextSibling ); var cal; var start_weekday = jQuery(this).hasClass('calendar-starts-monday') ? 1 : 0; if (Jifty.DateTime.dateRegex.test(this.value) ) { var bits = this.value.match(Jifty.DateTime.dateRegex); cal = new YAHOO.widget.Calendar( calId, wrapId, { pagedate: bits[2]+"/"+bits[1], selected: bits[2]+"/"+bits[3]+"/"+bits[1], start_weekday: start_weekday } ); } else { cal = new YAHOO.widget.Calendar( calId, wrapId, { start_weekday: start_weekday } ); } cal.cfg.applyConfig( Jifty.DateTime.Options ); cal.cfg.fireQueue(); cal.selectEvent.subscribe( Jifty.DateTime.handleSelect, { input: this, calendar: cal }, true ); cal.changePageEvent.subscribe( function() { setTimeout( function() { Jifty.DateTime._blurredDateTime = null; }, 75 ) }, null, false ); cal.render(); Jifty.DateTime.openDateTime = wrapId; Jifty.Utils.scrollToShow( wrapId ); /*Jifty.DateTime.preventStutter = wrapId;*/ }, handleSelect: function(type, args, obj) { // args = [ [ [yyyy, mm, dd] ] ] var year = args[0][0][0], month = args[0][0][1], day = args[0][0][2]; if (month < 10) month = "0" + month; if (day < 10) day = "0" + day; jQuery(obj.input).val(year + "-" + month + "-" + day ); Jifty.DateTime.hideOpenDateTime(); jQuery(obj.input).next().trigger( 'focus' ); }, openDateTime: "", hideOpenDateTime: function() { if ( Jifty.DateTime.openDateTime && document.getElementById( Jifty.DateTime.openDateTime ) ) { /* Get the input's ID */ var inputId = Jifty.DateTime.openDateTime; inputId = inputId.replace(/^cal_/, ''); inputId = inputId.replace(/_wrap$/, ''); // XXX: jQuery(Jifty.DateTime.openDateTime).remove() doesn't work for some reason var cal = document.getElementById(Jifty.DateTime.openDateTime); cal.parentNode.removeChild(cal); var input = document.getElementById( inputId ); /* Reenable canonicalization, and do it */ Jifty.Form.Element.enableValidation(input); Jifty.Form.Element.validate(input); Jifty.DateTime.openDateTime = ""; } }, _doneBlurOnce: false, _blurredDateTime: null, doBlur: function(ev) { if ( Jifty.DateTime.openDateTime && !Jifty.DateTime._doneBlurOnce ) { Jifty.DateTime._doneBlurOnce = true; Jifty.DateTime._blurredDateTime = Jifty.DateTime.openDateTime; setTimeout( Jifty.DateTime.doBlur, 200 ); return; } else if ( Jifty.DateTime._doneBlurOnce && Jifty.DateTime._blurredDateTime == Jifty.DateTime.openDateTime ) { Jifty.DateTime.hideOpenDateTime(); } Jifty.DateTime._doneBlurOnce = false; Jifty.DateTime._blurredDateTime = null; } }; jifty-1.10518+dfsg.orig/share/web/static/js/jquery.autocomplete.js0000644000175000017500000005264511447473536022667 0ustar fsfs/* * jQuery Autocomplete plugin 1.1 * * Copyright (c) 2009 Jörn Zaefferer * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ * * 2010-03-22 Shawn M Moore: let extraParams itself be a function * 2010-03-23 Shawn M Moore: add more options httpMethod, contentType, mungeData */ ;(function($) { $.fn.extend({ autocomplete: function(urlOrData, options) { var isUrl = typeof urlOrData == "string"; options = $.extend({}, $.Autocompleter.defaults, { url: isUrl ? urlOrData : null, data: isUrl ? null : urlOrData, delay: isUrl ? $.Autocompleter.defaults.delay : 10, max: options && !options.scroll ? 10 : 150 }, options); // if highlight is set to false, replace it with a do-nothing function options.highlight = options.highlight || function(value) { return value; }; // if the formatMatch option is not specified, then use formatItem for backwards compatibility options.formatMatch = options.formatMatch || options.formatItem; return this.each(function() { new $.Autocompleter(this, options); }); }, result: function(handler) { return this.bind("result", handler); }, search: function(handler) { return this.trigger("search", [handler]); }, flushCache: function() { return this.trigger("flushCache"); }, setOptions: function(options){ return this.trigger("setOptions", [options]); }, unautocomplete: function() { return this.trigger("unautocomplete"); } }); $.Autocompleter = function(input, options) { var KEY = { UP: 38, DOWN: 40, DEL: 46, TAB: 9, RETURN: 13, ESC: 27, COMMA: 188, PAGEUP: 33, PAGEDOWN: 34, BACKSPACE: 8 }; // Create $ object for input element var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); var timeout; var previousValue = ""; var cache = $.Autocompleter.Cache(options); var hasFocus = 0; var lastKeyPressCode; var config = { mouseDownOnSelect: false }; var select = $.Autocompleter.Select(options, input, selectCurrent, config); var blockSubmit; // prevent form submit in opera when selecting with return key $.browser.opera && $(input.form).bind("submit.autocomplete", function() { if (blockSubmit) { blockSubmit = false; return false; } }); // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { // a keypress means the input has focus // avoids issue where input had focus before the autocomplete was applied hasFocus = 1; // track last key pressed lastKeyPressCode = event.keyCode; switch(event.keyCode) { case KEY.UP: event.preventDefault(); if ( select.visible() ) { select.prev(); } else { onChange(0, true); } break; case KEY.DOWN: event.preventDefault(); if ( select.visible() ) { select.next(); } else { onChange(0, true); } break; case KEY.PAGEUP: event.preventDefault(); if ( select.visible() ) { select.pageUp(); } else { onChange(0, true); } break; case KEY.PAGEDOWN: event.preventDefault(); if ( select.visible() ) { select.pageDown(); } else { onChange(0, true); } break; // matches also semicolon case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: case KEY.TAB: case KEY.RETURN: if( selectCurrent() ) { // stop default to prevent a form submit, Opera needs special handling event.preventDefault(); blockSubmit = true; return false; } break; case KEY.ESC: select.hide(); break; default: clearTimeout(timeout); timeout = setTimeout(onChange, options.delay); break; } }).focus(function(){ // track whether the field has focus, we shouldn't process any // results if the field no longer has focus hasFocus++; }).blur(function() { hasFocus = 0; if (!config.mouseDownOnSelect) { hideResults(); } }).click(function() { // show select when clicking in a focused field if ( hasFocus++ > 1 && !select.visible() ) { onChange(0, true); } }).bind("search", function() { // TODO why not just specifying both arguments? var fn = (arguments.length > 1) ? arguments[1] : null; function findValueCallback(q, data) { var result; if( data && data.length ) { for (var i=0; i < data.length; i++) { if( data[i].result.toLowerCase() == q.toLowerCase() ) { result = data[i]; break; } } } if( typeof fn == "function" ) fn(result); else $input.trigger("result", result && [result.data, result.value]); } $.each(trimWords($input.val()), function(i, value) { request(value, findValueCallback, findValueCallback); }); }).bind("flushCache", function() { cache.flush(); }).bind("setOptions", function() { $.extend(options, arguments[1]); // if we've updated the data, repopulate if ( "data" in arguments[1] ) cache.populate(); }).bind("unautocomplete", function() { select.unbind(); $input.unbind(); $(input.form).unbind(".autocomplete"); }); function selectCurrent() { var selected = select.selected(); if( !selected ) return false; var v = selected.result; previousValue = v; if ( options.multiple ) { var words = trimWords($input.val()); if ( words.length > 1 ) { var seperator = options.multipleSeparator.length; var cursorAt = $(input).selection().start; var wordAt, progress = 0; $.each(words, function(i, word) { progress += word.length; if (cursorAt <= progress) { wordAt = i; return false; } progress += seperator; }); words[wordAt] = v; // TODO this should set the cursor to the right position, but it gets overriden somewhere //$.Autocompleter.Selection(input, progress + seperator, progress + seperator); v = words.join( options.multipleSeparator ); } v += options.multipleSeparator; } $input.val(v); hideResultsNow(); $input.trigger("result", [selected.data, selected.value]); return true; } function onChange(crap, skipPrevCheck) { if( lastKeyPressCode == KEY.DEL ) { select.hide(); return; } var currentValue = $input.val(); if ( !skipPrevCheck && currentValue == previousValue ) return; previousValue = currentValue; currentValue = lastWord(currentValue); if ( currentValue.length >= options.minChars) { $input.addClass(options.loadingClass); if (!options.matchCase) currentValue = currentValue.toLowerCase(); request(currentValue, receiveData, hideResultsNow); } else { stopLoading(); select.hide(); } }; function trimWords(value) { if (!value) return [""]; if (!options.multiple) return [$.trim(value)]; return $.map(value.split(options.multipleSeparator), function(word) { return $.trim(value).length ? $.trim(word) : null; }); } function lastWord(value) { if ( !options.multiple ) return value; var words = trimWords(value); if (words.length == 1) return words[0]; var cursorAt = $(input).selection().start; if (cursorAt == value.length) { words = trimWords(value) } else { words = trimWords(value.replace(value.substring(cursorAt), "")); } return words[words.length - 1]; } // fills in the input box w/the first match (assumed to be the best match) // q: the term entered // sValue: the first matching result function autoFill(q, sValue){ // autofill in the complete box w/the first match as long as the user hasn't entered in more data // if the last user key pressed was backspace, don't autofill if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) { // fill in the value (keep the case the user has typed) $input.val($input.val() + sValue.substring(lastWord(previousValue).length)); // select the portion of the value not typed by the user (so the next character will erase) $(input).selection(previousValue.length, previousValue.length + sValue.length); } }; function hideResults() { clearTimeout(timeout); timeout = setTimeout(hideResultsNow, 200); }; function hideResultsNow() { var wasVisible = select.visible(); select.hide(); clearTimeout(timeout); stopLoading(); if (options.mustMatch) { // call search and run callback $input.search( function (result){ // if no value found, clear the input box if( !result ) { if (options.multiple) { var words = trimWords($input.val()).slice(0, -1); $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") ); } else { $input.val( "" ); $input.trigger("result", null); } } } ); } }; function receiveData(q, data) { if ( data && data.length && hasFocus ) { stopLoading(); select.display(data, q); autoFill(q, data[0].value); select.show(); } else { hideResultsNow(); } }; function request(term, success, failure) { if (!options.matchCase) term = term.toLowerCase(); var data = cache.load(term); // recieve the cached data if (data && data.length) { success(term, data); // if an AJAX url has been supplied, try loading the data now } else if( (typeof options.url == "string") && (options.url.length > 0) ){ var extraParams = { timestamp: +new Date() }; if (typeof options.extraParams == "function") { extraParams = options.extraParams(); } else { $.each(options.extraParams, function(key, param) { extraParams[key] = typeof param == "function" ? param() : param; }); } var data = $.extend({ q: lastWord(term), limit: options.max }, extraParams); if (typeof options.mungeData == "function") { data = options.mungeData(data, term); } $.ajax({ // try to leverage ajaxQueue plugin to abort previous requests mode: "abort", // limit abortion to this input port: "autocomplete" + input.name, dataType: options.dataType, url: options.url, data: data, type: options.httpMethod, contentType: options.contentType, success: function(data) { var parsed = options.parse && options.parse(data) || parse(data); cache.add(term, parsed); success(term, parsed); } }); } else { // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match select.emptyList(); failure(term); } }; function parse(data) { var parsed = []; var rows = data.split("\n"); for (var i=0; i < rows.length; i++) { var row = $.trim(rows[i]); if (row) { row = row.split("|"); parsed[parsed.length] = { data: row, value: row[0], result: options.formatResult && options.formatResult(row, row[0]) || row[0] }; } } return parsed; }; function stopLoading() { $input.removeClass(options.loadingClass); }; }; $.Autocompleter.defaults = { inputClass: "ac_input", resultsClass: "ac_results", loadingClass: "ac_loading", minChars: 1, delay: 400, matchCase: false, matchSubset: true, matchContains: false, cacheLength: 10, max: 100, mustMatch: false, extraParams: {}, selectFirst: true, formatItem: function(row) { return row[0]; }, formatMatch: null, autoFill: false, width: 0, multiple: false, multipleSeparator: ", ", highlight: function(value, term) { return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); }, scroll: true, scrollHeight: 180 }; $.Autocompleter.Cache = function(options) { var data = {}; var length = 0; function matchSubset(s, sub) { if (!options.matchCase) s = s.toLowerCase(); var i = s.indexOf(sub); if (options.matchContains == "word"){ i = s.toLowerCase().search("\\b" + sub.toLowerCase()); } if (i == -1) return false; return i == 0 || options.matchContains; }; function add(q, value) { if (length > options.cacheLength){ flush(); } if (!data[q]){ length++; } data[q] = value; } function populate(){ if( !options.data ) return false; // track the matches var stMatchSets = {}, nullData = 0; // no url was specified, we need to adjust the cache length to make sure it fits the local data store if( !options.url ) options.cacheLength = 1; // track all options for minChars = 0 stMatchSets[""] = []; // loop through the array and create a lookup structure for ( var i = 0, ol = options.data.length; i < ol; i++ ) { var rawValue = options.data[i]; // if rawValue is a string, make an array otherwise just reference the array rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; var value = options.formatMatch(rawValue, i+1, options.data.length); if ( value === false ) continue; var firstChar = value.charAt(0).toLowerCase(); // if no lookup array for this character exists, look it up now if( !stMatchSets[firstChar] ) stMatchSets[firstChar] = []; // if the match is a string var row = { value: value, data: rawValue, result: options.formatResult && options.formatResult(rawValue) || value }; // push the current match into the set list stMatchSets[firstChar].push(row); // keep track of minChars zero items if ( nullData++ < options.max ) { stMatchSets[""].push(row); } }; // add the data items to the cache $.each(stMatchSets, function(i, value) { // increase the cache size options.cacheLength++; // add to the cache add(i, value); }); } // populate any existing data setTimeout(populate, 25); function flush(){ data = {}; length = 0; } return { flush: flush, add: add, populate: populate, load: function(q) { if (!options.cacheLength || !length) return null; /* * if dealing w/local data and matchContains than we must make sure * to loop through all the data collections looking for matches */ if( !options.url && options.matchContains ){ // track all matches var csub = []; // loop through all the data grids for matches for( var k in data ){ // don't search through the stMatchSets[""] (minChars: 0) cache // this prevents duplicates if( k.length > 0 ){ var c = data[k]; $.each(c, function(i, x) { // if we've got a match, add it to the array if (matchSubset(x.value, q)) { csub.push(x); } }); } } return csub; } else // if the exact item exists, use it if (data[q]){ return data[q]; } else if (options.matchSubset) { for (var i = q.length - 1; i >= options.minChars; i--) { var c = data[q.substr(0, i)]; if (c) { var csub = []; $.each(c, function(i, x) { if (matchSubset(x.value, q)) { csub[csub.length] = x; } }); return csub; } } } return null; } }; }; $.Autocompleter.Select = function (options, input, select, config) { var CLASSES = { ACTIVE: "ac_over" }; var listItems, active = -1, data, term = "", needsInit = true, element, list; // Create results function init() { if (!needsInit) return; element = $("
        ") .hide() .addClass(options.resultsClass) .css("position", "absolute") .appendTo(document.body); list = $("
          ").appendTo(element).mouseover( function(event) { if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); $(target(event)).addClass(CLASSES.ACTIVE); } }).click(function(event) { $(target(event)).addClass(CLASSES.ACTIVE); select(); // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus input.focus(); return false; }).mousedown(function() { config.mouseDownOnSelect = true; }).mouseup(function() { config.mouseDownOnSelect = false; }); if( options.width > 0 ) element.css("width", options.width); needsInit = false; } function target(event) { var element = event.target; while(element && element.tagName != "LI") element = element.parentNode; // more fun with IE, sometimes event.target is empty, just ignore it then if(!element) return []; return element; } function moveSelect(step) { listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE); movePosition(step); var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE); if(options.scroll) { var offset = 0; listItems.slice(0, active).each(function() { offset += this.offsetHeight; }); if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) { list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight()); } else if(offset < list.scrollTop()) { list.scrollTop(offset); } } }; function movePosition(step) { active += step; if (active < 0) { active = listItems.size() - 1; } else if (active >= listItems.size()) { active = 0; } } function limitNumberOfItems(available) { return options.max && options.max < available ? options.max : available; } function fillList() { list.empty(); var max = limitNumberOfItems(data.length); for (var i=0; i < max; i++) { if (!data[i]) continue; var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term); if ( formatted === false ) continue; var li = $("
        • ").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0]; $.data(li, "ac_data", data[i]); } listItems = list.find("li"); if ( options.selectFirst ) { listItems.slice(0, 1).addClass(CLASSES.ACTIVE); active = 0; } // apply bgiframe if available if ( $.fn.bgiframe ) list.bgiframe(); } return { display: function(d, q) { init(); data = d; term = q; fillList(); }, next: function() { moveSelect(1); }, prev: function() { moveSelect(-1); }, pageUp: function() { if (active != 0 && active - 8 < 0) { moveSelect( -active ); } else { moveSelect(-8); } }, pageDown: function() { if (active != listItems.size() - 1 && active + 8 > listItems.size()) { moveSelect( listItems.size() - 1 - active ); } else { moveSelect(8); } }, hide: function() { element && element.hide(); listItems && listItems.removeClass(CLASSES.ACTIVE); active = -1; }, visible : function() { return element && element.is(":visible"); }, current: function() { return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]); }, show: function() { var offset = $(input).offset(); element.css({ width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(), top: offset.top + input.offsetHeight, left: offset.left }).show(); if(options.scroll) { list.scrollTop(0); list.css({ maxHeight: options.scrollHeight, overflow: 'auto' }); if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { var listHeight = 0; listItems.each(function() { listHeight += this.offsetHeight; }); var scrollbarsVisible = listHeight > options.scrollHeight; list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight ); if (!scrollbarsVisible) { // IE doesn't recalculate width when scrollbar disappears listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) ); } } } }, selected: function() { var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE); return selected && selected.length && $.data(selected[0], "ac_data"); }, emptyList: function (){ list && list.empty(); }, unbind: function() { element && element.remove(); } }; }; $.fn.selection = function(start, end) { if (start !== undefined) { return this.each(function() { if( this.createTextRange ){ var selRange = this.createTextRange(); if (end === undefined || start == end) { selRange.move("character", start); selRange.select(); } else { selRange.collapse(true); selRange.moveStart("character", start); selRange.moveEnd("character", end); selRange.select(); } } else if( this.setSelectionRange ){ this.setSelectionRange(start, end); } else if( this.selectionStart ){ this.selectionStart = start; this.selectionEnd = end; } }); } var field = this[0]; if ( field.createTextRange ) { var range = document.selection.createRange(), orig = field.value, teststring = "<->", textLength = range.text.length; range.text = teststring; var caretAt = field.value.indexOf(teststring); field.value = orig; this.selection(caretAt, caretAt + textLength); return { start: caretAt, end: caretAt + textLength } } else if( field.selectionStart !== undefined ){ return { start: field.selectionStart, end: field.selectionEnd } } }; })(jQuery);jifty-1.10518+dfsg.orig/share/web/static/js/jquery.ajaxQueue.js0000644000175000017500000000556611447473536022116 0ustar fsfs/** * Ajax Queue Plugin * * Homepage: http://jquery.com/plugins/project/ajaxqueue * Documentation: http://docs.jquery.com/AjaxQueue */ /**
            */ /* * Queued Ajax requests. * A new Ajax request won't be started until the previous queued * request has finished. */ /* * Synced Ajax requests. * The Ajax request will happen as soon as you call this method, but * the callbacks (success/error/complete) won't fire until all previous * synced requests have been completed. */ (function($) { var ajax = $.ajax; var pendingRequests = {}; var synced = []; var syncedData = []; $.ajax = function(settings) { // create settings for compatibility with ajaxSetup settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings)); var port = settings.port; switch(settings.mode) { case "abort": if ( pendingRequests[port] ) { pendingRequests[port].abort(); } return pendingRequests[port] = ajax.apply(this, arguments); case "queue": var _old = settings.complete; settings.complete = function(){ if ( _old ) _old.apply( this, arguments ); jQuery([ajax]).dequeue("ajax" + port );; }; jQuery([ ajax ]).queue("ajax" + port, function(){ ajax( settings ); }); return; case "sync": var pos = synced.length; synced[ pos ] = { error: settings.error, success: settings.success, complete: settings.complete, done: false }; syncedData[ pos ] = { error: [], success: [], complete: [] }; settings.error = function(){ syncedData[ pos ].error = arguments; }; settings.success = function(){ syncedData[ pos ].success = arguments; }; settings.complete = function(){ syncedData[ pos ].complete = arguments; synced[ pos ].done = true; if ( pos == 0 || !synced[ pos-1 ] ) for ( var i = pos; i < synced.length && synced[i].done; i++ ) { if ( synced[i].error ) synced[i].error.apply( jQuery, syncedData[i].error ); if ( synced[i].success ) synced[i].success.apply( jQuery, syncedData[i].success ); if ( synced[i].complete ) synced[i].complete.apply( jQuery, syncedData[i].complete ); synced[i] = null; syncedData[i] = null; } }; } return ajax.apply(this, arguments); }; })(jQuery);jifty-1.10518+dfsg.orig/share/web/static/js/calendar.js0000644000175000017500000001107511447473536020411 0ustar fsfsif ( typeof Jifty == "undefined" ) Jifty = { }; Jifty.Calendar = { registerDateWidget: function(id) { jQuery(id).bind("focus", Jifty.Calendar.toggleCalendar) .bind("blur", Jifty.Calendar.doBlur); return true; }, dateRegex: /^(\d{4})\W(\d{2})\W(\d{2})/, Options: { OUT_OF_MONTH_SELECT: true }, toggleCalendar: function() { var calId = "cal_" + this.id; var wrapId = calId + "_wrap"; var wrap = document.getElementById(wrapId); if ( Jifty.Calendar.openCalendar == wrapId ) { Jifty.Calendar.hideOpenCalendar(); return; } Jifty.Calendar.hideOpenCalendar(); /* We need to delay Jifty's canonicalization until after we've selected a value via the calendar */ Jifty.Form.Element.disableValidation(this); wrap = document.createElement("div"); wrap.setAttribute( "id", wrapId ); wrap.setAttribute( "class", "select-free" ); wrap.style.position = "absolute"; wrap.style.left = Jifty.Utils.findRelativePosX( this ) + "px"; wrap.style.top = Jifty.Utils.findRelativePosY( this ) + this.offsetHeight + "px"; wrap.style.zIndex = 40; this.parentNode.insertBefore( wrap, this.nextSibling ); var cal; var start_weekday = jQuery(this).hasClass('calendar-starts-monday') ? 1 : 0; if (Jifty.Calendar.dateRegex.test(this.value) ) { var bits = this.value.match(Jifty.Calendar.dateRegex); cal = new YAHOO.widget.Calendar( calId, wrapId, { pagedate: bits[2]+"/"+bits[1], selected: bits[2]+"/"+bits[3]+"/"+bits[1], start_weekday: start_weekday } ); } else { cal = new YAHOO.widget.Calendar( calId, wrapId, { start_weekday: start_weekday } ); } cal.cfg.applyConfig( Jifty.Calendar.Options ); cal.cfg.fireQueue(); cal.selectEvent.subscribe( Jifty.Calendar.handleSelect, { input: this, calendar: cal }, true ); cal.changePageEvent.subscribe( function() { setTimeout( function() { Jifty.Calendar._blurredCalendar = null; }, 75 ) }, null, false ); cal.render(); Jifty.Calendar.openCalendar = wrapId; Jifty.Utils.scrollToShow( wrapId ); /*Jifty.Calendar.preventStutter = wrapId;*/ }, handleSelect: function(type, args, obj) { // args = [ [ [yyyy, mm, dd] ] ] var year = args[0][0][0], month = args[0][0][1], day = args[0][0][2]; if (month < 10) month = "0" + month; if (day < 10) day = "0" + day; jQuery(obj.input).val(year + "-" + month + "-" + day); // Trigger an onchange event for any listeners jQuery(obj.input).change(); Jifty.Calendar.hideOpenCalendar(); }, openCalendar: "", hideOpenCalendar: function() { if ( Jifty.Calendar.openCalendar && document.getElementById( Jifty.Calendar.openCalendar ) ) { /* Get the input's ID */ var inputId = Jifty.Calendar.openCalendar; inputId = inputId.replace(/^cal_/, ''); inputId = inputId.replace(/_wrap$/, ''); // XXX: jQuery(Jifty.Calendar.openCalendar).remove() doesn't work for some reason var cal = document.getElementById(Jifty.Calendar.openCalendar); cal.parentNode.removeChild(cal); var input = document.getElementById( inputId ); /* Reenable canonicalization, and do it */ Jifty.Form.Element.enableValidation(input); Jifty.Form.Element.validate(input); Jifty.Calendar.openCalendar = ""; } }, _doneBlurOnce: false, _blurredCalendar: null, doBlur: function(ev) { if ( Jifty.Calendar.openCalendar && !Jifty.Calendar._doneBlurOnce ) { Jifty.Calendar._doneBlurOnce = true; Jifty.Calendar._blurredCalendar = Jifty.Calendar.openCalendar; setTimeout( Jifty.Calendar.doBlur, 200 ); return; } else if ( Jifty.Calendar._doneBlurOnce && Jifty.Calendar._blurredCalendar == Jifty.Calendar.openCalendar ) { Jifty.Calendar.hideOpenCalendar(); } Jifty.Calendar._doneBlurOnce = false; Jifty.Calendar._blurredCalendar = null; } }; jifty-1.10518+dfsg.orig/share/web/static/js/jifty_smoothscroll.js0000644000175000017500000000224211447473536022571 0ustar fsfs if (typeof Jifty == "undefined") Jifty = { }; Jifty.SmoothScroll = { interval: '', steps: 20, scrollTo: function( y ) { if ( Jifty.SmoothScroll.interval ) clearInterval( Jifty.SmoothScroll.interval ); var stepsize = parseInt( ( y - Jifty.Utils.getScrollTop() ) / Jifty.SmoothScroll.steps ); Jifty.SmoothScroll.interval = setInterval('Jifty.SmoothScroll.scrollWindow('+stepsize+','+y+')',10); }, scrollWindow: function( amount, y ) { var curpos = Jifty.Utils.getScrollTop(); var isAbove = ( curpos < y ); window.scrollTo( 0, curpos + amount ); var newpos = Jifty.Utils.getScrollTop(); var newIsAbove = ( newpos < y ); if ( ( isAbove != newIsAbove ) || ( curpos == newpos ) ) { /* We've just scrolled past the destination, or we haven't moved from the last scroll (i.e., we're at the bottom of the page), so scroll exactly to the position */ window.scrollTo( 0, y ); clearInterval( Jifty.SmoothScroll.interval ); } } }; jifty-1.10518+dfsg.orig/share/web/static/js/rico.js0000644000175000017500000026175511447473536017610 0ustar fsfs/* * This is a slightly modified version of Rico which has improved * corner rounding methods that try to take care of preserving padding. * * Replacing it with a stock Rico probably isn't a good idea unless you * repatch it or don't plan on using any of the corner rounding. * * * WARNING: The patched version of Rico.Corner.round is *extremely* * slow on Mozilla/Firefox. Whenever possible, use the * -moz-border-radius CSS property in Mozilla browsers, and * conditionally only call it for any other browser, where its * performance is far more acceptable. * */ /** * * Copyright 2005 Sabre Airline Solutions * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions * and limitations under the License. **/ //-------------------- rico.js var Rico = { Version: '1.1.2.jifty.r4563', prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1]) } if((typeof Prototype=='undefined') || Rico.prototypeVersion < 1.3) throw("Rico requires the Prototype JavaScript framework >= 1.3"); Rico.ArrayExtensions = new Array(); if (Object.extend) { Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.extend; }else{ throw("Rico requires Object.extend from Prototype"); } if (Array.prototype.push) { Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push; } if (!Array.prototype.remove) { Array.prototype.remove = function(dx) { if( isNaN(dx) || dx > this.length ) return false; for( var i=0,n=0; i= this.accordionTabs.length) this.options.onLoadShowTab = 0; // set the initial visual state... for ( var i=0 ; i < this.accordionTabs.length ; i++ ) { if (i != this.options.onLoadShowTab){ this.accordionTabs[i].collapse(); this.accordionTabs[i].content.style.display = 'none'; } } this.lastExpandedTab = this.accordionTabs[this.options.onLoadShowTab]; if (this.options.panelHeight == 'auto'){ var tabToCheck = (this.options.onloadShowTab === 0)? 1 : 0; var titleBarSize = parseInt(RicoUtil.getElementsComputedStyle(this.accordionTabs[tabToCheck].titleBar, 'height')); if (isNaN(titleBarSize)) titleBarSize = this.accordionTabs[tabToCheck].titleBar.offsetHeight; var totalTitleBarSize = this.accordionTabs.length * titleBarSize; var parentHeight = parseInt(RicoUtil.getElementsComputedStyle(this.container.parentNode, 'height')); if (isNaN(parentHeight)) parentHeight = this.container.parentNode.offsetHeight; this.options.panelHeight = parentHeight - totalTitleBarSize-2; } this.lastExpandedTab.content.style.height = this.options.panelHeight + "px"; this.lastExpandedTab.showExpanded(); this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight; }, setOptions: function(options) { this.options = { expandedBg : '#63699c', hoverBg : '#63699c', collapsedBg : '#6b79a5', expandedTextColor : '#ffffff', expandedFontWeight : 'bold', hoverTextColor : '#ffffff', collapsedTextColor : '#ced7ef', collapsedFontWeight : 'normal', hoverTextColor : '#ffffff', borderColor : '#1f669b', panelHeight : 200, onHideTab : null, onShowTab : null, onLoadShowTab : 0 } Object.extend(this.options, options || {}); }, showTabByIndex: function( anIndex, animate ) { var doAnimate = arguments.length == 1 ? true : animate; this.showTab( this.accordionTabs[anIndex], doAnimate ); }, showTab: function( accordionTab, animate ) { if ( this.lastExpandedTab == accordionTab ) return; var doAnimate = arguments.length == 1 ? true : animate; if ( this.options.onHideTab ) this.options.onHideTab(this.lastExpandedTab); this.lastExpandedTab.showCollapsed(); var accordion = this; var lastExpandedTab = this.lastExpandedTab; this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px'; accordionTab.content.style.display = ''; accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight; if ( doAnimate ) { new Rico.Effect.AccordionSize( this.lastExpandedTab.content, accordionTab.content, 1, this.options.panelHeight, 100, 10, { complete: function() {accordion.showTabDone(lastExpandedTab)} } ); this.lastExpandedTab = accordionTab; } else { this.lastExpandedTab.content.style.height = "1px"; accordionTab.content.style.height = this.options.panelHeight + "px"; this.lastExpandedTab = accordionTab; this.showTabDone(lastExpandedTab); } }, showTabDone: function(collapsedTab) { collapsedTab.content.style.display = 'none'; this.lastExpandedTab.showExpanded(); if ( this.options.onShowTab ) this.options.onShowTab(this.lastExpandedTab); }, _attachBehaviors: function() { var panels = this._getDirectChildrenByTag(this.container, 'DIV'); for ( var i = 0 ; i < panels.length ; i++ ) { var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV'); if ( tabChildren.length != 2 ) continue; // unexpected var tabTitleBar = tabChildren[0]; var tabContentBox = tabChildren[1]; this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) ); } }, _getDirectChildrenByTag: function(e, tagName) { var kids = new Array(); var allKids = e.childNodes; for( var i = 0 ; i < allKids.length ; i++ ) if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName ) kids.push(allKids[i]); return kids; } }; Rico.Accordion.Tab = Class.create(); Rico.Accordion.Tab.prototype = { initialize: function(accordion, titleBar, content) { this.accordion = accordion; this.titleBar = titleBar; this.content = content; this._attachBehaviors(); }, collapse: function() { this.showCollapsed(); this.content.style.height = "1px"; }, showCollapsed: function() { this.expanded = false; this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg; this.titleBar.style.color = this.accordion.options.collapsedTextColor; this.titleBar.style.fontWeight = this.accordion.options.collapsedFontWeight; this.content.style.overflow = "hidden"; }, showExpanded: function() { this.expanded = true; this.titleBar.style.backgroundColor = this.accordion.options.expandedBg; this.titleBar.style.color = this.accordion.options.expandedTextColor; this.content.style.overflow = "auto"; }, titleBarClicked: function(e) { if ( this.accordion.lastExpandedTab == this ) return; this.accordion.showTab(this); }, hover: function(e) { this.titleBar.style.backgroundColor = this.accordion.options.hoverBg; this.titleBar.style.color = this.accordion.options.hoverTextColor; }, unhover: function(e) { if ( this.expanded ) { this.titleBar.style.backgroundColor = this.accordion.options.expandedBg; this.titleBar.style.color = this.accordion.options.expandedTextColor; } else { this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg; this.titleBar.style.color = this.accordion.options.collapsedTextColor; } }, _attachBehaviors: function() { this.content.style.border = "1px solid " + this.accordion.options.borderColor; this.content.style.borderTopWidth = "0px"; this.content.style.borderBottomWidth = "0px"; this.content.style.margin = "0px"; this.titleBar.onclick = this.titleBarClicked.bindAsEventListener(this); this.titleBar.onmouseover = this.hover.bindAsEventListener(this); this.titleBar.onmouseout = this.unhover.bindAsEventListener(this); } }; //-------------------- ricoAjaxEngine.js Rico.AjaxEngine = Class.create(); Rico.AjaxEngine.prototype = { initialize: function() { this.ajaxElements = new Array(); this.ajaxObjects = new Array(); this.requestURLS = new Array(); this.options = {}; }, registerAjaxElement: function( anId, anElement ) { if ( !anElement ) anElement = $(anId); this.ajaxElements[anId] = anElement; }, registerAjaxObject: function( anId, anObject ) { this.ajaxObjects[anId] = anObject; }, registerRequest: function (requestLogicalName, requestURL) { this.requestURLS[requestLogicalName] = requestURL; }, sendRequest: function(requestName, options) { // Allow for backwards Compatibility if ( arguments.length >= 2 ) if (typeof arguments[1] == 'string') options = {parameters: this._createQueryString(arguments, 1)}; this.sendRequestWithData(requestName, null, options); }, sendRequestWithData: function(requestName, xmlDocument, options) { var requestURL = this.requestURLS[requestName]; if ( requestURL == null ) return; // Allow for backwards Compatibility if ( arguments.length >= 3 ) if (typeof arguments[2] == 'string') options.parameters = this._createQueryString(arguments, 2); new Ajax.Request(requestURL, this._requestOptions(options,xmlDocument)); }, sendRequestAndUpdate: function(requestName,container,options) { // Allow for backwards Compatibility if ( arguments.length >= 3 ) if (typeof arguments[2] == 'string') options.parameters = this._createQueryString(arguments, 2); this.sendRequestWithDataAndUpdate(requestName, null, container, options); }, sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) { var requestURL = this.requestURLS[requestName]; if ( requestURL == null ) return; // Allow for backwards Compatibility if ( arguments.length >= 4 ) if (typeof arguments[3] == 'string') options.parameters = this._createQueryString(arguments, 3); var updaterOptions = this._requestOptions(options,xmlDocument); new Ajax.Updater(container, requestURL, updaterOptions); }, // Private -- not part of intended engine API -------------------------------------------------------------------- _requestOptions: function(options,xmlDoc) { var requestHeaders = ['X-Rico-Version', Rico.Version ]; var sendMethod = 'post'; if ( xmlDoc == null ) if (Rico.prototypeVersion < 1.4) requestHeaders.push( 'Content-type', 'text/xml' ); else sendMethod = 'get'; (!options) ? options = {} : ''; if (!options._RicoOptionsProcessed){ // Check and keep any user onComplete functions if (options.onComplete) options.onRicoComplete = options.onComplete; // Fix onComplete if (options.overrideOnComplete) options.onComplete = options.overrideOnComplete; else options.onComplete = this._onRequestComplete.bind(this); options._RicoOptionsProcessed = true; } // Set the default options and extend with any user options this.options = { requestHeaders: requestHeaders, parameters: options.parameters, postBody: xmlDoc, method: sendMethod, onComplete: options.onComplete }; // Set any user options: Object.extend(this.options, options); return this.options; }, _createQueryString: function( theArgs, offset ) { var queryString = "" for ( var i = offset ; i < theArgs.length ; i++ ) { if ( i != offset ) queryString += "&"; var anArg = theArgs[i]; if ( anArg.name != undefined && anArg.value != undefined ) { queryString += anArg.name + "=" + escape(anArg.value); } else { var ePos = anArg.indexOf('='); var argName = anArg.substring( 0, ePos ); var argValue = anArg.substring( ePos + 1 ); queryString += argName + "=" + escape(argValue); } } return queryString; }, _onRequestComplete : function(request) { if(!request) return; // User can set an onFailure option - which will be called by prototype if (request.status != 200) return; var response = request.responseXML.getElementsByTagName("ajax-response"); if (response == null || response.length != 1) return; this._processAjaxResponse( response[0].childNodes ); // Check if user has set a onComplete function var onRicoComplete = this.options.onRicoComplete; if (onRicoComplete != null) onRicoComplete(); }, _processAjaxResponse: function( xmlResponseElements ) { for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) { var responseElement = xmlResponseElements[i]; // only process nodes of type element..... if ( responseElement.nodeType != 1 ) continue; var responseType = responseElement.getAttribute("type"); var responseId = responseElement.getAttribute("id"); if ( responseType == "object" ) this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement ); else if ( responseType == "element" ) this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement ); else alert('unrecognized AjaxResponse type : ' + responseType ); } }, _processAjaxObjectUpdate: function( ajaxObject, responseElement ) { ajaxObject.ajaxUpdate( responseElement ); }, _processAjaxElementUpdate: function( ajaxElement, responseElement ) { ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement); } } var ajaxEngine = new Rico.AjaxEngine(); //-------------------- ricoColor.js Rico.Color = Class.create(); Rico.Color.prototype = { initialize: function(red, green, blue) { this.rgb = { r: red, g : green, b : blue }; }, setRed: function(r) { this.rgb.r = r; }, setGreen: function(g) { this.rgb.g = g; }, setBlue: function(b) { this.rgb.b = b; }, setHue: function(h) { // get an HSB model, and set the new hue... var hsb = this.asHSB(); hsb.h = h; // convert back to RGB... this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b); }, setSaturation: function(s) { // get an HSB model, and set the new hue... var hsb = this.asHSB(); hsb.s = s; // convert back to RGB and set values... this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b); }, setBrightness: function(b) { // get an HSB model, and set the new hue... var hsb = this.asHSB(); hsb.b = b; // convert back to RGB and set values... this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b ); }, darken: function(percent) { var hsb = this.asHSB(); this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0)); }, brighten: function(percent) { var hsb = this.asHSB(); this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1)); }, blend: function(other) { this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2); this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2); this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2); }, isBright: function() { var hsb = this.asHSB(); return this.asHSB().b > 0.5; }, isDark: function() { return ! this.isBright(); }, asRGB: function() { return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")"; }, asHex: function() { return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart(); }, asHSB: function() { return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b); }, toString: function() { return this.asHex(); } }; Rico.Color.createFromHex = function(hexCode) { if(hexCode.length==4) { var shortHexCode = hexCode; var hexCode = '#'; for(var i=1;i<4;i++) hexCode += (shortHexCode.charAt(i) + shortHexCode.charAt(i)); } if ( hexCode.indexOf('#') == 0 ) hexCode = hexCode.substring(1); var red = hexCode.substring(0,2); var green = hexCode.substring(2,4); var blue = hexCode.substring(4,6); return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) ); } /** * Factory method for creating a color from the background of * an HTML element. */ Rico.Color.createColorFromBackground = function(elem) { var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color"); if ( actualColor == "transparent" && elem.parentNode ) return Rico.Color.createColorFromBackground(elem.parentNode); if ( actualColor == null ) return new Rico.Color(255,255,255); if ( actualColor.indexOf("rgb(") == 0 ) { var colors = actualColor.substring(4, actualColor.length - 1 ); var colorArray = colors.split(","); return new Rico.Color( parseInt( colorArray[0] ), parseInt( colorArray[1] ), parseInt( colorArray[2] ) ); } else if ( actualColor.indexOf("#") == 0 ) { return Rico.Color.createFromHex(actualColor); } else return new Rico.Color(255,255,255); } Rico.Color.HSBtoRGB = function(hue, saturation, brightness) { var red = 0; var green = 0; var blue = 0; if (saturation == 0) { red = parseInt(brightness * 255.0 + 0.5); green = red; blue = red; } else { var h = (hue - Math.floor(hue)) * 6.0; var f = h - Math.floor(h); var p = brightness * (1.0 - saturation); var q = brightness * (1.0 - saturation * f); var t = brightness * (1.0 - (saturation * (1.0 - f))); switch (parseInt(h)) { case 0: red = (brightness * 255.0 + 0.5); green = (t * 255.0 + 0.5); blue = (p * 255.0 + 0.5); break; case 1: red = (q * 255.0 + 0.5); green = (brightness * 255.0 + 0.5); blue = (p * 255.0 + 0.5); break; case 2: red = (p * 255.0 + 0.5); green = (brightness * 255.0 + 0.5); blue = (t * 255.0 + 0.5); break; case 3: red = (p * 255.0 + 0.5); green = (q * 255.0 + 0.5); blue = (brightness * 255.0 + 0.5); break; case 4: red = (t * 255.0 + 0.5); green = (p * 255.0 + 0.5); blue = (brightness * 255.0 + 0.5); break; case 5: red = (brightness * 255.0 + 0.5); green = (p * 255.0 + 0.5); blue = (q * 255.0 + 0.5); break; } } return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) }; } Rico.Color.RGBtoHSB = function(r, g, b) { var hue; var saturation; var brightness; var cmax = (r > g) ? r : g; if (b > cmax) cmax = b; var cmin = (r < g) ? r : g; if (b < cmin) cmin = b; brightness = cmax / 255.0; if (cmax != 0) saturation = (cmax - cmin)/cmax; else saturation = 0; if (saturation == 0) hue = 0; else { var redc = (cmax - r)/(cmax - cmin); var greenc = (cmax - g)/(cmax - cmin); var bluec = (cmax - b)/(cmax - cmin); if (r == cmax) hue = bluec - greenc; else if (g == cmax) hue = 2.0 + redc - bluec; else hue = 4.0 + greenc - redc; hue = hue / 6.0; if (hue < 0) hue = hue + 1.0; } return { h : hue, s : saturation, b : brightness }; } //-------------------- ricoCorner.js Rico.Corner = { round: function(e, options) { var e = $(e); this._setOptions(options); var color = this.options.color; if ( this.options.color == "fromElement" ) color = this._background(e); var bgColor = this.options.bgColor; if ( this.options.bgColor == "fromParent" ) bgColor = this._background(e.offsetParent); this._roundCornersImpl(e, color, bgColor); }, _roundCornersImpl: function(e, color, bgColor) { if(this.options.border) this._renderBorder(e,bgColor); if(this._isTopRounded()) this._roundTopCorners(e,color,bgColor); if(this._isBottomRounded()) this._roundBottomCorners(e,color,bgColor); }, _renderBorder: function(el,bgColor) { var borderValue = "1px solid " + this._borderColor(bgColor); var borderL = "border-left: " + borderValue; var borderR = "border-right: " + borderValue; var style = "style='" + borderL + ";" + borderR + "'"; el.innerHTML = "
            " + el.innerHTML + "
            " }, _roundTopCorners: function(el, color, bgColor) { var corner = this._createCorner(el, bgColor); for(var i=0 ; i < this.options.numSlices ; i++ ) corner.appendChild(this._createCornerSlice(color,bgColor,i,"top")); el.style.paddingTop = 0; el.insertBefore(corner,el.firstChild); }, _roundBottomCorners: function(el, color, bgColor) { var corner = this._createCorner(el, bgColor); for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- ) corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom")); el.style.paddingBottom = 0; el.appendChild(corner); }, _createCorner: function(el, bgColor) { var corner = document.createElement("div"); corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor); var paddingLeft = "-" + RicoUtil.getElementsComputedStyle(el, "paddingLeft", "padding-left"); var paddingRight = "-" + RicoUtil.getElementsComputedStyle(el, "paddingRight", "padding-right"); corner.style.marginRight = paddingRight; corner.style.marginLeft = paddingLeft; return corner; }, _createCornerSlice: function(color,bgColor, n, position) { var slice = document.createElement("span"); var inStyle = slice.style; inStyle.backgroundColor = color; inStyle.display = "block"; inStyle.height = "1px"; inStyle.overflow = "hidden"; inStyle.fontSize = "1px"; var borderColor = this._borderColor(color,bgColor); if ( this.options.border && n == 0 ) { inStyle.borderTopStyle = "solid"; inStyle.borderTopWidth = "1px"; inStyle.borderLeftWidth = "0px"; inStyle.borderRightWidth = "0px"; inStyle.borderBottomWidth = "0px"; inStyle.height = "0px"; // assumes css compliant box model inStyle.borderColor = borderColor; } else if(borderColor) { inStyle.borderColor = borderColor; inStyle.borderStyle = "solid"; inStyle.borderWidth = "0px 1px"; } if ( !this.options.compact && (n == (this.options.numSlices-1)) ) inStyle.height = "2px"; this._setMargin(slice, n, position); this._setBorder(slice, n, position); return slice; }, _setOptions: function(options) { this.options = { corners : "all", color : "fromElement", bgColor : "fromParent", blend : true, border : false, compact : false } Object.extend(this.options, options || {}); this.options.numSlices = this.options.compact ? 2 : 4; if ( this._isTransparent() ) this.options.blend = false; }, _whichSideTop: function() { if ( this._hasString(this.options.corners, "all", "top") ) return ""; if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 ) return ""; if (this.options.corners.indexOf("tl") >= 0) return "left"; else if (this.options.corners.indexOf("tr") >= 0) return "right"; return ""; }, _whichSideBottom: function() { if ( this._hasString(this.options.corners, "all", "bottom") ) return ""; if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 ) return ""; if(this.options.corners.indexOf("bl") >=0) return "left"; else if(this.options.corners.indexOf("br")>=0) return "right"; return ""; }, _borderColor : function(color,bgColor) { if ( color == "transparent" ) return bgColor; else if ( this.options.border ) return this.options.border; else if ( this.options.blend ) return this._blend( bgColor, color ); else return ""; }, _setMargin: function(el, n, corners) { var marginSize = this._marginSize(n); var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom(); if ( whichSide == "left" ) { el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px"; } else if ( whichSide == "right" ) { el.style.marginRight = marginSize + "px"; el.style.marginLeft = "0px"; } else { el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px"; } }, _setBorder: function(el,n,corners) { var borderSize = this._borderSize(n); var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom(); if ( whichSide == "left" ) { el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px"; } else if ( whichSide == "right" ) { el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth = "0px"; } else { el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px"; } if (this.options.border != false) el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px"; }, _marginSize: function(n) { if ( this._isTransparent() ) return 0; var marginSizes = [ 5, 3, 2, 1 ]; var blendedMarginSizes = [ 3, 2, 1, 0 ]; var compactMarginSizes = [ 2, 1 ]; var smBlendedMarginSizes = [ 1, 0 ]; if ( this.options.compact && this.options.blend ) return smBlendedMarginSizes[n]; else if ( this.options.compact ) return compactMarginSizes[n]; else if ( this.options.blend ) return blendedMarginSizes[n]; else return marginSizes[n]; }, _borderSize: function(n) { var transparentBorderSizes = [ 5, 3, 2, 1 ]; var blendedBorderSizes = [ 2, 1, 1, 1 ]; var compactBorderSizes = [ 1, 0 ]; var actualBorderSizes = [ 0, 2, 0, 0 ]; if ( this.options.compact && (this.options.blend || this._isTransparent()) ) return 1; else if ( this.options.compact ) return compactBorderSizes[n]; else if ( this.options.blend ) return blendedBorderSizes[n]; else if ( this.options.border ) return actualBorderSizes[n]; else if ( this._isTransparent() ) return transparentBorderSizes[n]; return 0; }, _hasString: function(str) { for(var i=1 ; i= 0) return true; return false; }, _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; }, _background: function(el) { try { return Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } }, _isTransparent: function() { return this.options.color == "transparent"; }, _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); }, _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); }, _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; } } //-------------------- ricoDragAndDrop.js Rico.DragAndDrop = Class.create(); Rico.DragAndDrop.prototype = { initialize: function() { this.dropZones = new Array(); this.draggables = new Array(); this.currentDragObjects = new Array(); this.dragElement = null; this.lastSelectedDraggable = null; this.currentDragObjectVisible = false; this.interestedInMotionEvents = false; this._mouseDown = this._mouseDownHandler.bindAsEventListener(this); this._mouseMove = this._mouseMoveHandler.bindAsEventListener(this); this._mouseUp = this._mouseUpHandler.bindAsEventListener(this); }, registerDropZone: function(aDropZone) { this.dropZones[ this.dropZones.length ] = aDropZone; }, deregisterDropZone: function(aDropZone) { var newDropZones = new Array(); var j = 0; for ( var i = 0 ; i < this.dropZones.length ; i++ ) { if ( this.dropZones[i] != aDropZone ) newDropZones[j++] = this.dropZones[i]; } this.dropZones = newDropZones; }, clearDropZones: function() { this.dropZones = new Array(); }, registerDraggable: function( aDraggable ) { this.draggables[ this.draggables.length ] = aDraggable; this._addMouseDownHandler( aDraggable ); }, clearSelection: function() { for ( var i = 0 ; i < this.currentDragObjects.length ; i++ ) this.currentDragObjects[i].deselect(); this.currentDragObjects = new Array(); this.lastSelectedDraggable = null; }, hasSelection: function() { return this.currentDragObjects.length > 0; }, setStartDragFromElement: function( e, mouseDownElement ) { this.origPos = RicoUtil.toDocumentPosition(mouseDownElement); this.startx = e.screenX - this.origPos.x this.starty = e.screenY - this.origPos.y //this.startComponentX = e.layerX ? e.layerX : e.offsetX; //this.startComponentY = e.layerY ? e.layerY : e.offsetY; //this.adjustedForDraggableSize = false; this.interestedInMotionEvents = this.hasSelection(); this._terminateEvent(e); }, updateSelection: function( draggable, extendSelection ) { if ( ! extendSelection ) this.clearSelection(); if ( draggable.isSelected() ) { this.currentDragObjects.removeItem(draggable); draggable.deselect(); if ( draggable == this.lastSelectedDraggable ) this.lastSelectedDraggable = null; } else { this.currentDragObjects[ this.currentDragObjects.length ] = draggable; draggable.select(); this.lastSelectedDraggable = draggable; } }, _mouseDownHandler: function(e) { if ( arguments.length == 0 ) e = event; // if not button 1 ignore it... var nsEvent = e.which != undefined; if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1)) return; var eventTarget = e.target ? e.target : e.srcElement; var draggableObject = eventTarget.draggable; var candidate = eventTarget; while (draggableObject == null && candidate.parentNode) { candidate = candidate.parentNode; draggableObject = candidate.draggable; } if ( draggableObject == null ) return; this.updateSelection( draggableObject, e.ctrlKey ); // clear the drop zones postion cache... if ( this.hasSelection() ) for ( var i = 0 ; i < this.dropZones.length ; i++ ) this.dropZones[i].clearPositionCache(); this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() ); }, _mouseMoveHandler: function(e) { var nsEvent = e.which != undefined; if ( !this.interestedInMotionEvents ) { //this._terminateEvent(e); return; } if ( ! this.hasSelection() ) return; if ( ! this.currentDragObjectVisible ) this._startDrag(e); if ( !this.activatedDropZones ) this._activateRegisteredDropZones(); //if ( !this.adjustedForDraggableSize ) // this._adjustForDraggableSize(e); this._updateDraggableLocation(e); this._updateDropZonesHover(e); this._terminateEvent(e); }, _makeDraggableObjectVisible: function(e) { if ( !this.hasSelection() ) return; var dragElement; if ( this.currentDragObjects.length > 1 ) dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects); else dragElement = this.currentDragObjects[0].getSingleObjectDragGUI(); // go ahead and absolute position it... if ( RicoUtil.getElementsComputedStyle(dragElement, "position") != "absolute" ) dragElement.style.position = "absolute"; // need to parent him into the document... if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 ) document.body.appendChild(dragElement); this.dragElement = dragElement; this._updateDraggableLocation(e); this.currentDragObjectVisible = true; }, /** _adjustForDraggableSize: function(e) { var dragElementWidth = this.dragElement.offsetWidth; var dragElementHeight = this.dragElement.offsetHeight; if ( this.startComponentX > dragElementWidth ) this.startx -= this.startComponentX - dragElementWidth + 2; if ( e.offsetY ) { if ( this.startComponentY > dragElementHeight ) this.starty -= this.startComponentY - dragElementHeight + 2; } this.adjustedForDraggableSize = true; }, **/ _leftOffset: function(e) { return e.offsetX ? document.body.scrollLeft : 0 }, _topOffset: function(e) { return e.offsetY ? document.body.scrollTop:0 }, _updateDraggableLocation: function(e) { var dragObjectStyle = this.dragElement.style; dragObjectStyle.left = (e.screenX + this._leftOffset(e) - this.startx) + "px" dragObjectStyle.top = (e.screenY + this._topOffset(e) - this.starty) + "px"; }, _updateDropZonesHover: function(e) { var n = this.dropZones.length; for ( var i = 0 ; i < n ; i++ ) { if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) ) this.dropZones[i].hideHover(); } for ( var i = 0 ; i < n ; i++ ) { if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) { if ( this.dropZones[i].canAccept(this.currentDragObjects) ) this.dropZones[i].showHover(); } } }, _startDrag: function(e) { for ( var i = 0 ; i < this.currentDragObjects.length ; i++ ) this.currentDragObjects[i].startDrag(); this._makeDraggableObjectVisible(e); }, _mouseUpHandler: function(e) { if ( ! this.hasSelection() ) return; var nsEvent = e.which != undefined; if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1)) return; this.interestedInMotionEvents = false; if ( this.dragElement == null ) { this._terminateEvent(e); return; } if ( this._placeDraggableInDropZone(e) ) this._completeDropOperation(e); else { this._terminateEvent(e); new Rico.Effect.Position( this.dragElement, this.origPos.x, this.origPos.y, 200, 20, { complete : this._doCancelDragProcessing.bind(this) } ); } Event.stopObserving(document.body, "mousemove", this._mouseMove); Event.stopObserving(document.body, "mouseup", this._mouseUp); }, _retTrue: function () { return true; }, _completeDropOperation: function(e) { if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) { if ( this.dragElement.parentNode != null ) this.dragElement.parentNode.removeChild(this.dragElement); } this._deactivateRegisteredDropZones(); this._endDrag(); this.clearSelection(); this.dragElement = null; this.currentDragObjectVisible = false; this._terminateEvent(e); }, _doCancelDragProcessing: function() { this._cancelDrag(); if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() && this.dragElement) if ( this.dragElement.parentNode != null ) this.dragElement.parentNode.removeChild(this.dragElement); this._deactivateRegisteredDropZones(); this.dragElement = null; this.currentDragObjectVisible = false; }, _placeDraggableInDropZone: function(e) { var foundDropZone = false; var n = this.dropZones.length; for ( var i = 0 ; i < n ; i++ ) { if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) { if ( this.dropZones[i].canAccept(this.currentDragObjects) ) { this.dropZones[i].hideHover(); this.dropZones[i].accept(this.currentDragObjects); foundDropZone = true; break; } } } return foundDropZone; }, _cancelDrag: function() { for ( var i = 0 ; i < this.currentDragObjects.length ; i++ ) this.currentDragObjects[i].cancelDrag(); }, _endDrag: function() { for ( var i = 0 ; i < this.currentDragObjects.length ; i++ ) this.currentDragObjects[i].endDrag(); }, _mousePointInDropZone: function( e, dropZone ) { var absoluteRect = dropZone.getAbsoluteRect(); return e.clientX > absoluteRect.left + this._leftOffset(e) && e.clientX < absoluteRect.right + this._leftOffset(e) && e.clientY > absoluteRect.top + this._topOffset(e) && e.clientY < absoluteRect.bottom + this._topOffset(e); }, _addMouseDownHandler: function( aDraggable ) { htmlElement = aDraggable.getMouseDownHTMLElement(); if ( htmlElement != null ) { htmlElement.draggable = aDraggable; Event.observe(htmlElement , "mousedown", this._onmousedown.bindAsEventListener(this)); Event.observe(htmlElement, "mousedown", this._mouseDown); } }, _activateRegisteredDropZones: function() { var n = this.dropZones.length; for ( var i = 0 ; i < n ; i++ ) { var dropZone = this.dropZones[i]; if ( dropZone.canAccept(this.currentDragObjects) ) dropZone.activate(); } this.activatedDropZones = true; }, _deactivateRegisteredDropZones: function() { var n = this.dropZones.length; for ( var i = 0 ; i < n ; i++ ) this.dropZones[i].deactivate(); this.activatedDropZones = false; }, _onmousedown: function () { Event.observe(document.body, "mousemove", this._mouseMove); Event.observe(document.body, "mouseup", this._mouseUp); }, _terminateEvent: function(e) { if ( e.stopPropagation != undefined ) e.stopPropagation(); else if ( e.cancelBubble != undefined ) e.cancelBubble = true; if ( e.preventDefault != undefined ) e.preventDefault(); else e.returnValue = false; }, initializeEventHandlers: function() { if ( typeof document.implementation != "undefined" && document.implementation.hasFeature("HTML", "1.0") && document.implementation.hasFeature("Events", "2.0") && document.implementation.hasFeature("CSS", "2.0") ) { document.addEventListener("mouseup", this._mouseUpHandler.bindAsEventListener(this), false); document.addEventListener("mousemove", this._mouseMoveHandler.bindAsEventListener(this), false); } else if (document.attachEvent) { document.attachEvent( "onmouseup", this._mouseUpHandler.bindAsEventListener(this) ); document.attachEvent( "onmousemove", this._mouseMoveHandler.bindAsEventListener(this) ); } else { document.onmouseup = this._mouseUpHandler.bindAsEventListener(this); document.onmousemove = this._mouseMoveHandler.bindAsEventListener(this); } } } var dndMgr = new Rico.DragAndDrop(); dndMgr.initializeEventHandlers(); //-------------------- ricoDraggable.js Rico.Draggable = Class.create(); Rico.Draggable.prototype = { initialize: function( type, htmlElement ) { this.type = type; this.htmlElement = $(htmlElement); this.selected = false; }, /** * Returns the HTML element that should have a mouse down event * added to it in order to initiate a drag operation * **/ getMouseDownHTMLElement: function() { return this.htmlElement; }, select: function() { this.selected = true; if ( this.showingSelected ) return; var htmlElement = this.getMouseDownHTMLElement(); var color = Rico.Color.createColorFromBackground(htmlElement); color.isBright() ? color.darken(0.033) : color.brighten(0.033); this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color"); htmlElement.style.backgroundColor = color.asHex(); this.showingSelected = true; }, deselect: function() { this.selected = false; if ( !this.showingSelected ) return; var htmlElement = this.getMouseDownHTMLElement(); htmlElement.style.backgroundColor = this.saveBackground; this.showingSelected = false; }, isSelected: function() { return this.selected; }, startDrag: function() { }, cancelDrag: function() { }, endDrag: function() { }, getSingleObjectDragGUI: function() { return this.htmlElement; }, getMultiObjectDragGUI: function( draggables ) { return this.htmlElement; }, getDroppedGUI: function() { return this.htmlElement; }, toString: function() { return this.type + ":" + this.htmlElement + ":"; } } //-------------------- ricoDropzone.js Rico.Dropzone = Class.create(); Rico.Dropzone.prototype = { initialize: function( htmlElement ) { this.htmlElement = $(htmlElement); this.absoluteRect = null; }, getHTMLElement: function() { return this.htmlElement; }, clearPositionCache: function() { this.absoluteRect = null; }, getAbsoluteRect: function() { if ( this.absoluteRect == null ) { var htmlElement = this.getHTMLElement(); var pos = RicoUtil.toViewportPosition(htmlElement); this.absoluteRect = { top: pos.y, left: pos.x, bottom: pos.y + htmlElement.offsetHeight, right: pos.x + htmlElement.offsetWidth }; } return this.absoluteRect; }, activate: function() { var htmlElement = this.getHTMLElement(); if (htmlElement == null || this.showingActive) return; this.showingActive = true; this.saveBackgroundColor = htmlElement.style.backgroundColor; var fallbackColor = "#ffea84"; var currentColor = Rico.Color.createColorFromBackground(htmlElement); if ( currentColor == null ) htmlElement.style.backgroundColor = fallbackColor; else { currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2); htmlElement.style.backgroundColor = currentColor.asHex(); } }, deactivate: function() { var htmlElement = this.getHTMLElement(); if (htmlElement == null || !this.showingActive) return; htmlElement.style.backgroundColor = this.saveBackgroundColor; this.showingActive = false; this.saveBackgroundColor = null; }, showHover: function() { var htmlElement = this.getHTMLElement(); if ( htmlElement == null || this.showingHover ) return; this.saveBorderWidth = htmlElement.style.borderWidth; this.saveBorderStyle = htmlElement.style.borderStyle; this.saveBorderColor = htmlElement.style.borderColor; this.showingHover = true; htmlElement.style.borderWidth = "1px"; htmlElement.style.borderStyle = "solid"; //htmlElement.style.borderColor = "#ff9900"; htmlElement.style.borderColor = "#ffff00"; }, hideHover: function() { var htmlElement = this.getHTMLElement(); if ( htmlElement == null || !this.showingHover ) return; htmlElement.style.borderWidth = this.saveBorderWidth; htmlElement.style.borderStyle = this.saveBorderStyle; htmlElement.style.borderColor = this.saveBorderColor; this.showingHover = false; }, canAccept: function(draggableObjects) { return true; }, accept: function(draggableObjects) { var htmlElement = this.getHTMLElement(); if ( htmlElement == null ) return; n = draggableObjects.length; for ( var i = 0 ; i < n ; i++ ) { var theGUI = draggableObjects[i].getDroppedGUI(); if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" ) { theGUI.style.position = "static"; theGUI.style.top = ""; theGUI.style.top = ""; } htmlElement.appendChild(theGUI); } } } //-------------------- ricoEffects.js Rico.Effect = {}; Rico.Effect.SizeAndPosition = Class.create(); Rico.Effect.SizeAndPosition.prototype = { initialize: function(element, x, y, w, h, duration, steps, options) { this.element = $(element); this.x = x; this.y = y; this.w = w; this.h = h; this.duration = duration; this.steps = steps; this.options = arguments[7] || {}; this.sizeAndPosition(); }, sizeAndPosition: function() { if (this.isFinished()) { if(this.options.complete) this.options.complete(this); return; } if (this.timer) clearTimeout(this.timer); var stepDuration = Math.round(this.duration/this.steps) ; // Get original values: x,y = top left corner; w,h = width height var currentX = this.element.offsetLeft; var currentY = this.element.offsetTop; var currentW = this.element.offsetWidth; var currentH = this.element.offsetHeight; // If values not set, or zero, we do not modify them, and take original as final as well this.x = (this.x) ? this.x : currentX; this.y = (this.y) ? this.y : currentY; this.w = (this.w) ? this.w : currentW; this.h = (this.h) ? this.h : currentH; // how much do we need to modify our values for each step? var difX = this.steps > 0 ? (this.x - currentX)/this.steps : 0; var difY = this.steps > 0 ? (this.y - currentY)/this.steps : 0; var difW = this.steps > 0 ? (this.w - currentW)/this.steps : 0; var difH = this.steps > 0 ? (this.h - currentH)/this.steps : 0; this.moveBy(difX, difY); this.resizeBy(difW, difH); this.duration -= stepDuration; this.steps--; this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration); }, isFinished: function() { return this.steps <= 0; }, moveBy: function( difX, difY ) { var currentLeft = this.element.offsetLeft; var currentTop = this.element.offsetTop; var intDifX = parseInt(difX); var intDifY = parseInt(difY); var style = this.element.style; if ( intDifX != 0 ) style.left = (currentLeft + intDifX) + "px"; if ( intDifY != 0 ) style.top = (currentTop + intDifY) + "px"; }, resizeBy: function( difW, difH ) { var currentWidth = this.element.offsetWidth; var currentHeight = this.element.offsetHeight; var intDifW = parseInt(difW); var intDifH = parseInt(difH); var style = this.element.style; if ( intDifW != 0 ) style.width = (currentWidth + intDifW) + "px"; if ( intDifH != 0 ) style.height = (currentHeight + intDifH) + "px"; } } Rico.Effect.Size = Class.create(); Rico.Effect.Size.prototype = { initialize: function(element, w, h, duration, steps, options) { new Rico.Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options); } } Rico.Effect.Position = Class.create(); Rico.Effect.Position.prototype = { initialize: function(element, x, y, duration, steps, options) { new Rico.Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options); } } Rico.Effect.Round = Class.create(); Rico.Effect.Round.prototype = { initialize: function(tagName, className, options) { var elements = document.getElementsByTagAndClassName(tagName,className); for ( var i = 0 ; i < elements.length ; i++ ) Rico.Corner.round( elements[i], options ); } }; Rico.Effect.FadeTo = Class.create(); Rico.Effect.FadeTo.prototype = { initialize: function( element, opacity, duration, steps, options) { this.element = $(element); this.opacity = opacity; this.duration = duration; this.steps = steps; this.options = arguments[4] || {}; this.fadeTo(); }, fadeTo: function() { if (this.isFinished()) { if(this.options.complete) this.options.complete(this); return; } if (this.timer) clearTimeout(this.timer); var stepDuration = Math.round(this.duration/this.steps) ; var currentOpacity = this.getElementOpacity(); var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0; this.changeOpacityBy(delta); this.duration -= stepDuration; this.steps--; this.timer = setTimeout(this.fadeTo.bind(this), stepDuration); }, changeOpacityBy: function(v) { var currentOpacity = this.getElementOpacity(); var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1)); this.element.ricoOpacity = newOpacity; this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")"; this.element.style.opacity = newOpacity; /*//*/; }, isFinished: function() { return this.steps <= 0; }, getElementOpacity: function() { if ( this.element.ricoOpacity == undefined ) { var opacity = RicoUtil.getElementsComputedStyle(this.element, 'opacity'); this.element.ricoOpacity = opacity != undefined ? opacity : 1.0; } return parseFloat(this.element.ricoOpacity); } } Rico.Effect.AccordionSize = Class.create(); Rico.Effect.AccordionSize.prototype = { initialize: function(e1, e2, start, end, duration, steps, options) { this.e1 = $(e1); this.e2 = $(e2); this.start = start; this.end = end; this.duration = duration; this.steps = steps; this.options = arguments[6] || {}; this.accordionSize(); }, accordionSize: function() { if (this.isFinished()) { // just in case there are round errors or such... this.e1.style.height = this.start + "px"; this.e2.style.height = this.end + "px"; if(this.options.complete) this.options.complete(this); return; } if (this.timer) clearTimeout(this.timer); var stepDuration = Math.round(this.duration/this.steps) ; var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0; this.resizeBy(diff); this.duration -= stepDuration; this.steps--; this.timer = setTimeout(this.accordionSize.bind(this), stepDuration); }, isFinished: function() { return this.steps <= 0; }, resizeBy: function(diff) { var h1Height = this.e1.offsetHeight; var h2Height = this.e2.offsetHeight; var intDiff = parseInt(diff); if ( diff != 0 ) { this.e1.style.height = (h1Height - intDiff) + "px"; this.e2.style.height = (h2Height + intDiff) + "px"; } } }; //-------------------- ricoLiveGrid.js // Rico.LiveGridMetaData ----------------------------------------------------- Rico.LiveGridMetaData = Class.create(); Rico.LiveGridMetaData.prototype = { initialize: function( pageSize, totalRows, columnCount, options ) { this.pageSize = pageSize; this.totalRows = totalRows; this.setOptions(options); this.ArrowHeight = 16; this.columnCount = columnCount; }, setOptions: function(options) { this.options = { largeBufferSize : 7.0, // 7 pages nearLimitFactor : 0.2 // 20% of buffer }; Object.extend(this.options, options || {}); }, getPageSize: function() { return this.pageSize; }, getTotalRows: function() { return this.totalRows; }, setTotalRows: function(n) { this.totalRows = n; }, getLargeBufferSize: function() { return parseInt(this.options.largeBufferSize * this.pageSize); }, getLimitTolerance: function() { return parseInt(this.getLargeBufferSize() * this.options.nearLimitFactor); } }; // Rico.LiveGridScroller ----------------------------------------------------- Rico.LiveGridScroller = Class.create(); Rico.LiveGridScroller.prototype = { initialize: function(liveGrid, viewPort) { this.isIE = navigator.userAgent.toLowerCase().indexOf("msie") >= 0; this.liveGrid = liveGrid; this.metaData = liveGrid.metaData; this.createScrollBar(); this.scrollTimeout = null; this.lastScrollPos = 0; this.viewPort = viewPort; this.rows = new Array(); }, isUnPlugged: function() { return this.scrollerDiv.onscroll == null; }, plugin: function() { this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this); }, unplug: function() { this.scrollerDiv.onscroll = null; }, sizeIEHeaderHack: function() { if ( !this.isIE ) return; var headerTable = $(this.liveGrid.tableId + "_header"); if ( headerTable ) headerTable.rows[0].cells[0].style.width = (headerTable.rows[0].cells[0].offsetWidth + 1) + "px"; }, createScrollBar: function() { var visibleHeight = this.liveGrid.viewPort.visibleHeight(); // create the outer div... this.scrollerDiv = document.createElement("div"); var scrollerStyle = this.scrollerDiv.style; scrollerStyle.borderRight = this.liveGrid.options.scrollerBorderRight; scrollerStyle.position = "relative"; scrollerStyle.left = this.isIE ? "-6px" : "-3px"; scrollerStyle.width = "19px"; scrollerStyle.height = visibleHeight + "px"; scrollerStyle.overflow = "auto"; // create the inner div... this.heightDiv = document.createElement("div"); this.heightDiv.style.width = "1px"; this.heightDiv.style.height = parseInt(visibleHeight * this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px" ; this.scrollerDiv.appendChild(this.heightDiv); this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this); var table = this.liveGrid.table; table.parentNode.parentNode.insertBefore( this.scrollerDiv, table.parentNode.nextSibling ); var eventName = this.isIE ? "mousewheel" : "DOMMouseScroll"; Event.observe(table, eventName, function(evt) { if (evt.wheelDelta>=0 || evt.detail < 0) //wheel-up this.scrollerDiv.scrollTop -= (2*this.viewPort.rowHeight); else this.scrollerDiv.scrollTop += (2*this.viewPort.rowHeight); this.handleScroll(false); }.bindAsEventListener(this), false); }, updateSize: function() { var table = this.liveGrid.table; var visibleHeight = this.viewPort.visibleHeight(); this.heightDiv.style.height = parseInt(visibleHeight * this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px"; }, rowToPixel: function(rowOffset) { return (rowOffset / this.metaData.getTotalRows()) * this.heightDiv.offsetHeight }, moveScroll: function(rowOffset) { this.scrollerDiv.scrollTop = this.rowToPixel(rowOffset); if ( this.metaData.options.onscroll ) this.metaData.options.onscroll( this.liveGrid, rowOffset ); }, handleScroll: function() { if ( this.scrollTimeout ) clearTimeout( this.scrollTimeout ); var scrollDiff = this.lastScrollPos-this.scrollerDiv.scrollTop; if (scrollDiff != 0.00) { var r = this.scrollerDiv.scrollTop % this.viewPort.rowHeight; if (r != 0) { this.unplug(); if ( scrollDiff < 0 ) { this.scrollerDiv.scrollTop += (this.viewPort.rowHeight-r); } else { this.scrollerDiv.scrollTop -= r; } this.plugin(); } } var contentOffset = parseInt(this.scrollerDiv.scrollTop / this.viewPort.rowHeight); this.liveGrid.requestContentRefresh(contentOffset); this.viewPort.scrollTo(this.scrollerDiv.scrollTop); if ( this.metaData.options.onscroll ) this.metaData.options.onscroll( this.liveGrid, contentOffset ); this.scrollTimeout = setTimeout(this.scrollIdle.bind(this), 1200 ); this.lastScrollPos = this.scrollerDiv.scrollTop; }, scrollIdle: function() { if ( this.metaData.options.onscrollidle ) this.metaData.options.onscrollidle(); } }; // Rico.LiveGridBuffer ----------------------------------------------------- Rico.LiveGridBuffer = Class.create(); Rico.LiveGridBuffer.prototype = { initialize: function(metaData, viewPort) { this.startPos = 0; this.size = 0; this.metaData = metaData; this.rows = new Array(); this.updateInProgress = false; this.viewPort = viewPort; this.maxBufferSize = metaData.getLargeBufferSize() * 2; this.maxFetchSize = metaData.getLargeBufferSize(); this.lastOffset = 0; }, getBlankRow: function() { if (!this.blankRow ) { this.blankRow = new Array(); for ( var i=0; i < this.metaData.columnCount ; i++ ) this.blankRow[i] = " "; } return this.blankRow; }, loadRows: function(ajaxResponse) { var rowsElement = ajaxResponse.getElementsByTagName('rows')[0]; this.updateUI = rowsElement.getAttribute("update_ui") == "true" var newRows = new Array() var trs = rowsElement.getElementsByTagName("tr"); for ( var i=0 ; i < trs.length; i++ ) { var row = newRows[i] = new Array(); var cells = trs[i].getElementsByTagName("td"); for ( var j=0; j < cells.length ; j++ ) { var cell = cells[j]; var convertSpaces = cell.getAttribute("convert_spaces") == "true"; var cellContent = RicoUtil.getContentAsString(cell); row[j] = convertSpaces ? this.convertSpaces(cellContent) : cellContent; if (!row[j]) row[j] = ' '; } } return newRows; }, update: function(ajaxResponse, start) { var newRows = this.loadRows(ajaxResponse); if (this.rows.length == 0) { // initial load this.rows = newRows; this.size = this.rows.length; this.startPos = start; return; } if (start > this.startPos) { //appending if (this.startPos + this.rows.length < start) { this.rows = newRows; this.startPos = start;// } else { this.rows = this.rows.concat( newRows.slice(0, newRows.length)); if (this.rows.length > this.maxBufferSize) { var fullSize = this.rows.length; this.rows = this.rows.slice(this.rows.length - this.maxBufferSize, this.rows.length) this.startPos = this.startPos + (fullSize - this.rows.length); } } } else { //prepending if (start + newRows.length < this.startPos) { this.rows = newRows; } else { this.rows = newRows.slice(0, this.startPos).concat(this.rows); if (this.rows.length > this.maxBufferSize) this.rows = this.rows.slice(0, this.maxBufferSize) } this.startPos = start; } this.size = this.rows.length; }, clear: function() { this.rows = new Array(); this.startPos = 0; this.size = 0; }, isOverlapping: function(start, size) { return ((start < this.endPos()) && (this.startPos < start + size)) || (this.endPos() == 0) }, isInRange: function(position) { return (position >= this.startPos) && (position + this.metaData.getPageSize() <= this.endPos()); //&& this.size() != 0; }, isNearingTopLimit: function(position) { return position - this.startPos < this.metaData.getLimitTolerance(); }, endPos: function() { return this.startPos + this.rows.length; }, isNearingBottomLimit: function(position) { return this.endPos() - (position + this.metaData.getPageSize()) < this.metaData.getLimitTolerance(); }, isAtTop: function() { return this.startPos == 0; }, isAtBottom: function() { return this.endPos() == this.metaData.getTotalRows(); }, isNearingLimit: function(position) { return ( !this.isAtTop() && this.isNearingTopLimit(position)) || ( !this.isAtBottom() && this.isNearingBottomLimit(position) ) }, getFetchSize: function(offset) { var adjustedOffset = this.getFetchOffset(offset); var adjustedSize = 0; if (adjustedOffset >= this.startPos) { //apending var endFetchOffset = this.maxFetchSize + adjustedOffset; if (endFetchOffset > this.metaData.totalRows) endFetchOffset = this.metaData.totalRows; adjustedSize = endFetchOffset - adjustedOffset; if(adjustedOffset == 0 && adjustedSize < this.maxFetchSize){ adjustedSize = this.maxFetchSize; } } else {//prepending var adjustedSize = this.startPos - adjustedOffset; if (adjustedSize > this.maxFetchSize) adjustedSize = this.maxFetchSize; } return adjustedSize; }, getFetchOffset: function(offset) { var adjustedOffset = offset; if (offset > this.startPos) //apending adjustedOffset = (offset > this.endPos()) ? offset : this.endPos(); else { //prepending if (offset + this.maxFetchSize >= this.startPos) { var adjustedOffset = this.startPos - this.maxFetchSize; if (adjustedOffset < 0) adjustedOffset = 0; } } this.lastOffset = adjustedOffset; return adjustedOffset; }, getRows: function(start, count) { var begPos = start - this.startPos var endPos = begPos + count // er? need more data... if ( endPos > this.size ) endPos = this.size var results = new Array() var index = 0; for ( var i=begPos ; i < endPos; i++ ) { results[index++] = this.rows[i] } return results }, convertSpaces: function(s) { return s.split(" ").join(" "); } }; //Rico.GridViewPort -------------------------------------------------- Rico.GridViewPort = Class.create(); Rico.GridViewPort.prototype = { initialize: function(table, rowHeight, visibleRows, buffer, liveGrid) { this.lastDisplayedStartPos = 0; this.div = table.parentNode; this.table = table this.rowHeight = rowHeight; this.div.style.height = (this.rowHeight * visibleRows) + "px"; this.div.style.overflow = "hidden"; this.buffer = buffer; this.liveGrid = liveGrid; this.visibleRows = visibleRows + 1; this.lastPixelOffset = 0; this.startPos = 0; }, populateRow: function(htmlRow, row) { for (var j=0; j < row.length; j++) { htmlRow.cells[j].innerHTML = row[j] } }, bufferChanged: function() { this.refreshContents( parseInt(this.lastPixelOffset / this.rowHeight)); }, clearRows: function() { if (!this.isBlank) { this.liveGrid.table.className = this.liveGrid.options.loadingClass; for (var i=0; i < this.visibleRows; i++) this.populateRow(this.table.rows[i], this.buffer.getBlankRow()); this.isBlank = true; } }, clearContents: function() { this.clearRows(); this.scrollTo(0); this.startPos = 0; this.lastStartPos = -1; }, refreshContents: function(startPos) { if (startPos == this.lastRowPos && !this.isPartialBlank && !this.isBlank) { return; } if ((startPos + this.visibleRows < this.buffer.startPos) || (this.buffer.startPos + this.buffer.size < startPos) || (this.buffer.size == 0)) { this.clearRows(); return; } this.isBlank = false; var viewPrecedesBuffer = this.buffer.startPos > startPos var contentStartPos = viewPrecedesBuffer ? this.buffer.startPos: startPos; var contentEndPos = (this.buffer.startPos + this.buffer.size < startPos + this.visibleRows) ? this.buffer.startPos + this.buffer.size : startPos + this.visibleRows; var rowSize = contentEndPos - contentStartPos; var rows = this.buffer.getRows(contentStartPos, rowSize ); var blankSize = this.visibleRows - rowSize; var blankOffset = viewPrecedesBuffer ? 0: rowSize; var contentOffset = viewPrecedesBuffer ? blankSize: 0; for (var i=0; i < rows.length; i++) {//initialize what we have this.populateRow(this.table.rows[i + contentOffset], rows[i]); } for (var i=0; i < blankSize; i++) {// blank out the rest this.populateRow(this.table.rows[i + blankOffset], this.buffer.getBlankRow()); } this.isPartialBlank = blankSize > 0; this.lastRowPos = startPos; this.liveGrid.table.className = this.liveGrid.options.tableClass; // Check if user has set a onRefreshComplete function var onRefreshComplete = this.liveGrid.options.onRefreshComplete; if (onRefreshComplete != null) onRefreshComplete(); }, scrollTo: function(pixelOffset) { if (this.lastPixelOffset == pixelOffset) return; this.refreshContents(parseInt(pixelOffset / this.rowHeight)) this.div.scrollTop = pixelOffset % this.rowHeight this.lastPixelOffset = pixelOffset; }, visibleHeight: function() { return parseInt(RicoUtil.getElementsComputedStyle(this.div, 'height')); } }; Rico.LiveGridRequest = Class.create(); Rico.LiveGridRequest.prototype = { initialize: function( requestOffset, options ) { this.requestOffset = requestOffset; } }; // Rico.LiveGrid ----------------------------------------------------- Rico.LiveGrid = Class.create(); Rico.LiveGrid.prototype = { initialize: function( tableId, visibleRows, totalRows, url, options, ajaxOptions ) { this.options = { tableClass: $(tableId).className, loadingClass: $(tableId).className, scrollerBorderRight: '1px solid #ababab', bufferTimeout: 20000, sortAscendImg: 'images/sort_asc.gif', sortDescendImg: 'images/sort_desc.gif', sortImageWidth: 9, sortImageHeight: 5, ajaxSortURLParms: [], onRefreshComplete: null, requestParameters: null, inlineStyles: true }; Object.extend(this.options, options || {}); this.ajaxOptions = {parameters: null}; Object.extend(this.ajaxOptions, ajaxOptions || {}); this.tableId = tableId; this.table = $(tableId); this.addLiveGridHtml(); var columnCount = this.table.rows[0].cells.length; this.metaData = new Rico.LiveGridMetaData(visibleRows, totalRows, columnCount, options); this.buffer = new Rico.LiveGridBuffer(this.metaData); var rowCount = this.table.rows.length; this.viewPort = new Rico.GridViewPort(this.table, this.table.offsetHeight/rowCount, visibleRows, this.buffer, this); this.scroller = new Rico.LiveGridScroller(this,this.viewPort); this.options.sortHandler = this.sortHandler.bind(this); if ( $(tableId + '_header') ) this.sort = new Rico.LiveGridSort(tableId + '_header', this.options) this.processingRequest = null; this.unprocessedRequest = null; this.initAjax(url); if ( this.options.prefetchBuffer || this.options.prefetchOffset > 0) { var offset = 0; if (this.options.offset ) { offset = this.options.offset; this.scroller.moveScroll(offset); this.viewPort.scrollTo(this.scroller.rowToPixel(offset)); } if (this.options.sortCol) { this.sortCol = options.sortCol; this.sortDir = options.sortDir; } this.requestContentRefresh(offset); } }, addLiveGridHtml: function() { // Check to see if need to create a header table. if (this.table.getElementsByTagName("thead").length > 0){ // Create Table this.tableId+'_header' var tableHeader = this.table.cloneNode(true); tableHeader.setAttribute('id', this.tableId+'_header'); tableHeader.setAttribute('class', this.table.className+'_header'); // Clean up and insert for( var i = 0; i < tableHeader.tBodies.length; i++ ) tableHeader.removeChild(tableHeader.tBodies[i]); this.table.deleteTHead(); this.table.parentNode.insertBefore(tableHeader,this.table); } new Insertion.Before(this.table, "
            "); this.table.previousSibling.appendChild(this.table); new Insertion.Before(this.table,"
            "); this.table.previousSibling.appendChild(this.table); }, resetContents: function() { this.scroller.moveScroll(0); this.buffer.clear(); this.viewPort.clearContents(); }, sortHandler: function(column) { if(!column) return ; this.sortCol = column.name; this.sortDir = column.currentSort; this.resetContents(); this.requestContentRefresh(0) }, adjustRowSize: function() { }, setTotalRows: function( newTotalRows ) { this.resetContents(); this.metaData.setTotalRows(newTotalRows); this.scroller.updateSize(); }, initAjax: function(url) { ajaxEngine.registerRequest( this.tableId + '_request', url ); ajaxEngine.registerAjaxObject( this.tableId + '_updater', this ); }, invokeAjax: function() { }, handleTimedOut: function() { //server did not respond in 4 seconds... assume that there could have been //an error or something, and allow requests to be processed again... this.processingRequest = null; this.processQueuedRequest(); }, fetchBuffer: function(offset) { if ( this.buffer.isInRange(offset) && !this.buffer.isNearingLimit(offset)) { return; } if (this.processingRequest) { this.unprocessedRequest = new Rico.LiveGridRequest(offset); return; } var bufferStartPos = this.buffer.getFetchOffset(offset); this.processingRequest = new Rico.LiveGridRequest(offset); this.processingRequest.bufferOffset = bufferStartPos; var fetchSize = this.buffer.getFetchSize(offset); var partialLoaded = false; var queryString if (this.options.requestParameters) queryString = this._createQueryString(this.options.requestParameters, 0); queryString = (queryString == null) ? '' : queryString+'&'; queryString = queryString+'id='+this.tableId+'&page_size='+fetchSize+'&offset='+bufferStartPos; if (this.sortCol) queryString = queryString+'&sort_col='+escape(this.sortCol)+'&sort_dir='+this.sortDir; this.ajaxOptions.parameters = queryString; ajaxEngine.sendRequest( this.tableId + '_request', this.ajaxOptions ); this.timeoutHandler = setTimeout( this.handleTimedOut.bind(this), this.options.bufferTimeout); }, setRequestParams: function() { this.options.requestParameters = []; for ( var i=0 ; i < arguments.length ; i++ ) this.options.requestParameters[i] = arguments[i]; }, requestContentRefresh: function(contentOffset) { this.fetchBuffer(contentOffset); }, ajaxUpdate: function(ajaxResponse) { try { clearTimeout( this.timeoutHandler ); this.buffer.update(ajaxResponse,this.processingRequest.bufferOffset); this.viewPort.bufferChanged(); } catch(err) {} finally {this.processingRequest = null; } this.processQueuedRequest(); }, _createQueryString: function( theArgs, offset ) { var queryString = "" if (!theArgs) return queryString; for ( var i = offset ; i < theArgs.length ; i++ ) { if ( i != offset ) queryString += "&"; var anArg = theArgs[i]; if ( anArg.name != undefined && anArg.value != undefined ) { queryString += anArg.name + "=" + escape(anArg.value); } else { var ePos = anArg.indexOf('='); var argName = anArg.substring( 0, ePos ); var argValue = anArg.substring( ePos + 1 ); queryString += argName + "=" + escape(argValue); } } return queryString; }, processQueuedRequest: function() { if (this.unprocessedRequest != null) { this.requestContentRefresh(this.unprocessedRequest.requestOffset); this.unprocessedRequest = null } } }; //-------------------- ricoLiveGridSort.js Rico.LiveGridSort = Class.create(); Rico.LiveGridSort.prototype = { initialize: function(headerTableId, options) { this.headerTableId = headerTableId; this.headerTable = $(headerTableId); this.options = options; this.setOptions(); this.applySortBehavior(); if ( this.options.sortCol ) { this.setSortUI( this.options.sortCol, this.options.sortDir ); } }, setSortUI: function( columnName, sortDirection ) { var cols = this.options.columns; for ( var i = 0 ; i < cols.length ; i++ ) { if ( cols[i].name == columnName ) { this.setColumnSort(i, sortDirection); break; } } }, setOptions: function() { // preload the images... new Image().src = this.options.sortAscendImg; new Image().src = this.options.sortDescendImg; this.sort = this.options.sortHandler; if ( !this.options.columns ) this.options.columns = this.introspectForColumnInfo(); else { // allow client to pass { columns: [ ["a", true], ["b", false] ] } // and convert to an array of Rico.TableColumn objs... this.options.columns = this.convertToTableColumns(this.options.columns); } }, applySortBehavior: function() { var headerRow = this.headerTable.rows[0]; var headerCells = headerRow.cells; for ( var i = 0 ; i < headerCells.length ; i++ ) { this.addSortBehaviorToColumn( i, headerCells[i] ); } }, addSortBehaviorToColumn: function( n, cell ) { if ( this.options.columns[n].isSortable() ) { cell.id = this.headerTableId + '_' + n; cell.style.cursor = 'pointer'; cell.onclick = this.headerCellClicked.bindAsEventListener(this); cell.innerHTML = cell.innerHTML + '' + '   '; } }, // event handler.... headerCellClicked: function(evt) { var eventTarget = evt.target ? evt.target : evt.srcElement; var cellId = eventTarget.id; var columnNumber = parseInt(cellId.substring( cellId.lastIndexOf('_') + 1 )); var sortedColumnIndex = this.getSortedColumnIndex(); if ( sortedColumnIndex != -1 ) { if ( sortedColumnIndex != columnNumber ) { this.removeColumnSort(sortedColumnIndex); this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC); } else this.toggleColumnSort(sortedColumnIndex); } else this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC); if (this.options.sortHandler) { this.options.sortHandler(this.options.columns[columnNumber]); } }, removeColumnSort: function(n) { this.options.columns[n].setUnsorted(); this.setSortImage(n); }, setColumnSort: function(n, direction) { if(isNaN(n)) return ; this.options.columns[n].setSorted(direction); this.setSortImage(n); }, toggleColumnSort: function(n) { this.options.columns[n].toggleSort(); this.setSortImage(n); }, setSortImage: function(n) { var sortDirection = this.options.columns[n].getSortDirection(); var sortImageSpan = $( this.headerTableId + '_img_' + n ); if ( sortDirection == Rico.TableColumn.UNSORTED ) sortImageSpan.innerHTML = '  '; else if ( sortDirection == Rico.TableColumn.SORT_ASC ) sortImageSpan.innerHTML = '  '; else if ( sortDirection == Rico.TableColumn.SORT_DESC ) sortImageSpan.innerHTML = '  '; }, getSortedColumnIndex: function() { var cols = this.options.columns; for ( var i = 0 ; i < cols.length ; i++ ) { if ( cols[i].isSorted() ) return i; } return -1; }, introspectForColumnInfo: function() { var columns = new Array(); var headerRow = this.headerTable.rows[0]; var headerCells = headerRow.cells; for ( var i = 0 ; i < headerCells.length ; i++ ) columns.push( new Rico.TableColumn( this.deriveColumnNameFromCell(headerCells[i],i), true ) ); return columns; }, convertToTableColumns: function(cols) { var columns = new Array(); for ( var i = 0 ; i < cols.length ; i++ ) columns.push( new Rico.TableColumn( cols[i][0], cols[i][1] ) ); return columns; }, deriveColumnNameFromCell: function(cell,columnNumber) { var cellContent = cell.innerText != undefined ? cell.innerText : cell.textContent; return cellContent ? cellContent.toLowerCase().split(' ').join('_') : "col_" + columnNumber; } }; Rico.TableColumn = Class.create(); Rico.TableColumn.UNSORTED = 0; Rico.TableColumn.SORT_ASC = "ASC"; Rico.TableColumn.SORT_DESC = "DESC"; Rico.TableColumn.prototype = { initialize: function(name, sortable) { this.name = name; this.sortable = sortable; this.currentSort = Rico.TableColumn.UNSORTED; }, isSortable: function() { return this.sortable; }, isSorted: function() { return this.currentSort != Rico.TableColumn.UNSORTED; }, getSortDirection: function() { return this.currentSort; }, toggleSort: function() { if ( this.currentSort == Rico.TableColumn.UNSORTED || this.currentSort == Rico.TableColumn.SORT_DESC ) this.currentSort = Rico.TableColumn.SORT_ASC; else if ( this.currentSort == Rico.TableColumn.SORT_ASC ) this.currentSort = Rico.TableColumn.SORT_DESC; }, setUnsorted: function(direction) { this.setSorted(Rico.TableColumn.UNSORTED); }, setSorted: function(direction) { // direction must by one of Rico.TableColumn.UNSORTED, .SORT_ASC, or .SORT_DESC... this.currentSort = direction; } }; //-------------------- ricoUtil.js var RicoUtil = { getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) { if ( arguments.length == 2 ) mozillaEquivalentCSS = cssProperty; var el = $(htmlElement); if ( el.currentStyle ) return el.currentStyle[cssProperty]; else return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS); }, createXmlDocument : function() { if (document.implementation && document.implementation.createDocument) { var doc = document.implementation.createDocument("", "", null); if (doc.readyState == null) { doc.readyState = 1; doc.addEventListener("load", function () { doc.readyState = 4; if (typeof doc.onreadystatechange == "function") doc.onreadystatechange(); }, false); } return doc; } if (window.ActiveXObject) return Try.these( function() { return new ActiveXObject('MSXML2.DomDocument') }, function() { return new ActiveXObject('Microsoft.DomDocument')}, function() { return new ActiveXObject('MSXML.DomDocument') }, function() { return new ActiveXObject('MSXML3.DomDocument') } ) || false; return null; }, getContentAsString: function( parentNode ) { return parentNode.xml != undefined ? this._getContentAsStringIE(parentNode) : this._getContentAsStringMozilla(parentNode); }, _getContentAsStringIE: function(parentNode) { var contentStr = ""; for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) { var n = parentNode.childNodes[i]; if (n.nodeType == 4) { contentStr += n.nodeValue; } else { contentStr += n.xml; } } return contentStr; }, _getContentAsStringMozilla: function(parentNode) { var xmlSerializer = new XMLSerializer(); var contentStr = ""; for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) { var n = parentNode.childNodes[i]; if (n.nodeType == 4) { // CDATA node contentStr += n.nodeValue; } else { contentStr += xmlSerializer.serializeToString(n); } } return contentStr; }, toViewportPosition: function(element) { return this._toAbsolute(element,true); }, toDocumentPosition: function(element) { return this._toAbsolute(element,false); }, /** * Compute the elements position in terms of the window viewport * so that it can be compared to the position of the mouse (dnd) * This is additions of all the offsetTop,offsetLeft values up the * offsetParent hierarchy, ...taking into account any scrollTop, * scrollLeft values along the way... * * IE has a bug reporting a correct offsetLeft of elements within a * a relatively positioned parent!!! **/ _toAbsolute: function(element,accountForDocScroll) { if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 ) return this._toAbsoluteMozilla(element,accountForDocScroll); var x = 0; var y = 0; var parent = element; while ( parent ) { var borderXOffset = 0; var borderYOffset = 0; if ( parent != element ) { var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" )); var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" )); borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset; borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset; } x += parent.offsetLeft - parent.scrollLeft + borderXOffset; y += parent.offsetTop - parent.scrollTop + borderYOffset; parent = parent.offsetParent; } if ( accountForDocScroll ) { x -= this.docScrollLeft(); y -= this.docScrollTop(); } return { x:x, y:y }; }, /** * Mozilla did not report all of the parents up the hierarchy via the * offsetParent property that IE did. So for the calculation of the * offsets we use the offsetParent property, but for the calculation of * the scrollTop/scrollLeft adjustments we navigate up via the parentNode * property instead so as to get the scroll offsets... * **/ _toAbsoluteMozilla: function(element,accountForDocScroll) { var x = 0; var y = 0; var parent = element; while ( parent ) { x += parent.offsetLeft; y += parent.offsetTop; parent = parent.offsetParent; } parent = element; while ( parent && parent != document.body && parent != document.documentElement ) { if ( parent.scrollLeft ) x -= parent.scrollLeft; if ( parent.scrollTop ) y -= parent.scrollTop; parent = parent.parentNode; } if ( accountForDocScroll ) { x -= this.docScrollLeft(); y -= this.docScrollTop(); } return { x:x, y:y }; }, docScrollLeft: function() { if ( window.pageXOffset ) return window.pageXOffset; else if ( document.documentElement && document.documentElement.scrollLeft ) return document.documentElement.scrollLeft; else if ( document.body ) return document.body.scrollLeft; else return 0; }, docScrollTop: function() { if ( window.pageYOffset ) return window.pageYOffset; else if ( document.documentElement && document.documentElement.scrollTop ) return document.documentElement.scrollTop; else if ( document.body ) return document.body.scrollTop; else return 0; } }; jifty-1.10518+dfsg.orig/share/web/static/js/jquery_noconflict.js0000644000175000017500000000011711447473536022370 0ustar fsfs/** * noConflict.js - Tell jQuery not to clobber $() */ jQuery.noConflict(); jifty-1.10518+dfsg.orig/share/web/static/js/css_browser_selector.js0000644000175000017500000000174711447473536023100 0ustar fsfs/* * XXX TODO JS * This should be migrated to either Jifty's browser detection or jQuery's, but * changing the class values has the potential to break existing CSS. */ // CSS Browser Selector v0.4 // Documentation: http://rafael.adm.br/css_browser_selector // License: http://creativecommons.org/licenses/by/2.5/ // Author: Rafael Lima (http://rafael.adm.br) // Contributors: http://rafael.adm.br/css_browser_selector#contributors function css_browser_selector() { var ua = navigator.userAgent.toLowerCase(); var h = document.getElementsByTagName('html')[0]; if(ua.indexOf('msie') != -1 && !(ua.indexOf('opera') != -1) && (ua.indexOf('webtv') == -1) ) h.className='ie'; else if(ua.indexOf('gecko/') != -1) h.className='gecko'; else if(ua.indexOf('opera') != -1) h.className='opera'; else if(ua.indexOf('konqueror') != -1) h.className='konqueror'; else if(ua.indexOf('applewebkit/') != - 1) h.className='safari'; } css_browser_selector(); jifty-1.10518+dfsg.orig/share/web/static/js/halo.js0000644000175000017500000001024411447473536017560 0ustar fsfs/* XXX TODO JS: move into Jifty.Halos rather than global */ var halo_shown = null; var halos_drawn = null; var halo_top; var halo_left; var halo_width; function halo_toggle (id) { if (halo_shown && (id != halo_shown)) { halo_top = Jifty.$('halo-'+halo_shown+'-menu').style.top; halo_left = Jifty.$('halo-'+halo_shown+'-menu').style.left; halo_width = Jifty.$('halo-'+halo_shown+'-menu').style.width; jQuery('#halo-'+halo_shown+'-menu').hide(); } jQuery("#halo-"+id+"-menu").css({ top: halo_top, left: halo_left, width: halo_width }).toggle(); Drag.init( Jifty.$('halo-'+id+'-title'), Jifty.$('halo-'+id+'-menu') ); init_resize(Jifty.$('halo-'+id+'-resize'), Jifty.$('halo-'+id+'-menu') ); var e = jQuery('#halo-'+id).get(0); if (jQuery('#halo-'+id+'-menu').is(":visible")) { halo_shown = id; jQuery(e).css({ background: '#ffff80' }); } else { halo_top = Jifty.$('halo-'+halo_shown+'-menu').style.top; halo_left = Jifty.$('halo-'+halo_shown+'-menu').style.left; halo_width = Jifty.$('halo-'+halo_shown+'-menu').style.width; halo_shown = null; jQuery(e).css({ background: 'inherit' }); } return false; } function halo_over (id) { jQuery('#halo-'+id).css({ background: '#ffff80' }); } function halo_out (id) { if (! jQuery("#halo-"+id+"-menu").is(":visible")) { jQuery('#halo-'+id).css({ background: 'inherit' }); } } function init_resize (e, w) { e.xFrom = e.yFrom = 0; Drag.init(e, null, null, null, null, null, true, true ); e.onDrag = function(x, y) { resizeX( x, e, w ); }; } function resizeX (x, grip, window) { var width = parseInt( window.style.width ); var newWidth = Math.abs( width - ( x - grip.xFrom ) ) + 'px'; window.style.width = newWidth; grip.xFrom = x; } function draw_halos() { var halo_header_display = 'none'; var halo_border_width = '0'; var halo_margin = '0'; var halo_padding = '0'; halos_drawn = !halos_drawn; if (halos_drawn) { halo_header_display = 'block'; halo_border_width = '2px'; halo_margin = '3px'; halo_padding = '3px'; } jQuery("#render_info-draw_halos").text(halos_drawn ? "Hide halos" : "Draw halos"); jQuery(".halo-header").css({ display: halo_header_display }); jQuery(".halo").css({ 'border-width': halo_border_width, 'margin': halo_margin, 'padding': halo_padding }) } function render_info_tree() { jQuery("#render_info_tree").toggle(); } function halo_render(id, name) { halo_reset(id); jQuery('#halo-button-'+name+'-'+id).css("font-weight", "bold"); var e = jQuery('#halo-rendered-'+id).get(0); if (name == 'source') { e.halo_rendered = e.innerHTML; jQuery(e).html('
            ').find("div").text(e.halo_rendered); } else if (name == 'render') { /* ignore */ } else { e.style.display = 'none'; jQuery("#halo-info-"+id).show(); jQuery('#halo-info-'+name+'-'+id).show(); } } function halo_reset(id) { /* restore all buttons to nonbold */ for (var child = jQuery('#halo-rendermode-'+id).firstChild; child != null; child = child.nextSibling) { if (child.style) { child.style.fontWeight = 'normal'; } } /* hide all the info divs */ jQuery('#halo-info-'+id).hide(); for (var child = jQuery('#halo-info-'+id).firstChild; child != null; child = child.nextSibling) { if (child.style) { child.style.display = 'none'; } } /* restore the rendered div */ var e = jQuery('#halo-rendered-'+id).get(0); e.style.display = 'block'; if (e.halo_rendered) { e.innerHTML = e.halo_rendered; e.halo_rendered = null; } } function remove_link(id, name) { var link = jQuery('#halo-button-'+name+'-'+id).get(0); var newlink = document.createElement("span"); newlink.appendChild(link.childNodes[0]); link.parentNode.replaceChild(newlink, link); } jifty-1.10518+dfsg.orig/share/web/static/js/facebox.js0000644000175000017500000002234111447473536020245 0ustar fsfs/* This file has been changed for Jifty. Please see the commit log for its * changes before upgrading */ /* * Facebox (for jQuery) * version: 1.2 (05/05/2008) * @requires jQuery v1.2 or later * * Examples at http://famspam.com/facebox/ * * Licensed under the MIT: * http://www.opensource.org/licenses/mit-license.php * * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ] * * Usage: * * jQuery(document).ready(function() { * jQuery('a[rel*=facebox]').facebox() * }) * *
            Terms * Loads the #terms div in the box * * Terms * Loads the terms.html page in the box * * Terms * Loads the terms.png image in the box * * * You can also use it programmatically: * * jQuery.facebox('some html') * * The above will open a facebox with "some html" as the content. * * jQuery.facebox(function($) { * $.get('blah.html', function(data) { $.facebox(data) }) * }) * * The above will show a loading screen before the passed function is called, * allowing for a better ajaxy experience. * * The facebox function can also display an ajax page or image: * * jQuery.facebox({ ajax: 'remote.html' }) * jQuery.facebox({ image: 'dude.jpg' }) * * Want to close the facebox? Trigger the 'close.facebox' document event: * * jQuery(document).trigger('close.facebox') * * Facebox also has a bunch of other hooks: * * loading.facebox * beforeReveal.facebox * reveal.facebox (aliased as 'afterReveal.facebox') * init.facebox * * Simply bind a function to any of these hooks: * * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) * */ (function($) { $.facebox = function(data, klass) { $.facebox.loading() if (data.ajax) fillFaceboxFromAjax(data.ajax) else if (data.image) fillFaceboxFromImage(data.image) else if (data.div) fillFaceboxFromHref(data.div) else if ($.isFunction(data)) data.call($) else $.facebox.reveal(data, klass) } /* * Public, $.facebox methods */ $.extend($.facebox, { settings: { opacity : 0, overlay : true, loadingImage : '/static/images/facebox/loading.gif', closeImage : '/static/images/facebox/closelabel.gif', imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], faceboxHtml : '\ ' }, loading: function() { init() if ($('#facebox .loading').length == 1) return true showOverlay() $('#facebox .content').empty() $('#facebox .body').children().hide().end(). append('
            ') $('#facebox').css({ top: getPageScroll()[1] + (getPageHeight() / 10), left: 385.5 }).show() $(document).bind('keydown.facebox', function(e) { if (e.keyCode == 27) $.facebox.close() return true }) $(document).trigger('loading.facebox') }, reveal: function(data, klass) { $(document).trigger('beforeReveal.facebox') if (klass) $('#facebox .content').addClass(klass) $('#facebox .content').append(data) $('#facebox .loading').remove() $('#facebox .body').children().fadeIn('normal') $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2)) $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') }, close: function() { $(document).trigger('close.facebox') return false } }) /* * Public, $.fn methods */ $.fn.facebox = function(settings) { init(settings) function clickHandler() { $.facebox.loading(true) // support for rel="facebox.inline_popup" syntax, to add a class // also supports deprecated "facebox[.inline_popup]" syntax var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) if (klass) klass = klass[1] fillFaceboxFromHref(this.href, klass) return false } return this.click(clickHandler) } /* * Private methods */ // called one time to setup facebox on this page function init(settings) { if ($.facebox.settings.inited) return true else $.facebox.settings.inited = true $(document).trigger('init.facebox') makeCompatible() var imageTypes = $.facebox.settings.imageTypes.join('|') $.facebox.settings.imageTypesRegexp = new RegExp('\.' + imageTypes + '$', 'i') if (settings) $.extend($.facebox.settings, settings) $('body').append($.facebox.settings.faceboxHtml) var preload = [ new Image(), new Image() ] preload[0].src = $.facebox.settings.closeImage preload[1].src = $.facebox.settings.loadingImage $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() { preload.push(new Image()) preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1') }) $('#facebox .close').click($.facebox.close) $('#facebox .close_image').attr('src', $.facebox.settings.closeImage) } // getPageScroll() by quirksmode.com function getPageScroll() { var xScroll, yScroll; if (self.pageYOffset) { yScroll = self.pageYOffset; xScroll = self.pageXOffset; } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict yScroll = document.documentElement.scrollTop; xScroll = document.documentElement.scrollLeft; } else if (document.body) {// all other Explorers yScroll = document.body.scrollTop; xScroll = document.body.scrollLeft; } return new Array(xScroll,yScroll) } // Adapted from getPageSize() by quirksmode.com function getPageHeight() { var windowHeight if (self.innerHeight) { // all except Explorer windowHeight = self.innerHeight; } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode windowHeight = document.documentElement.clientHeight; } else if (document.body) { // other Explorers windowHeight = document.body.clientHeight; } return windowHeight } // Backwards compatibility function makeCompatible() { var $s = $.facebox.settings $s.loadingImage = $s.loading_image || $s.loadingImage $s.closeImage = $s.close_image || $s.closeImage $s.imageTypes = $s.image_types || $s.imageTypes $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml } // Figures out what you want to display and displays it // formats are: // div: #id // image: blah.extension // ajax: anything else function fillFaceboxFromHref(href, klass) { // div if (href.match(/#/)) { var url = window.location.href.split('#')[0] var target = href.replace(url,'') $.facebox.reveal($(target).clone().show(), klass) // image } else if (href.match($.facebox.settings.imageTypesRegexp)) { fillFaceboxFromImage(href, klass) // ajax } else { fillFaceboxFromAjax(href, klass) } } function fillFaceboxFromImage(href, klass) { var image = new Image() image.onload = function() { $.facebox.reveal('
            ', klass) } image.src = href } function fillFaceboxFromAjax(href, klass) { $.get(href, function(data) { $.facebox.reveal(data, klass) }) } function skipOverlay() { return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null } function showOverlay() { if (skipOverlay()) return if ($('facebox_overlay').length == 0) $("body").append('
            ') $('#facebox_overlay').hide().addClass("facebox_overlayBG") .css('opacity', $.facebox.settings.opacity) .click(function() { $(document).trigger('close.facebox') }) .fadeIn(200) return false } function hideOverlay() { if (skipOverlay()) return $('#facebox_overlay').fadeOut(200, function(){ $("#facebox_overlay").removeClass("facebox_overlayBG") $("#facebox_overlay").addClass("facebox_hide") $("#facebox_overlay").remove() }) return false } /* * Bindings */ $(document).bind('close.facebox', function() { $(document).unbind('keydown.facebox') $('#facebox').fadeOut(function() { $('#facebox .content').removeClass().addClass('content') hideOverlay() $('#facebox .loading').remove() }) }) })(jQuery); jifty-1.10518+dfsg.orig/share/web/static/js/jquery-1.4.1.js0000644000175000017500000047171011500012563020577 0ustar fsfs/*! * jQuery JavaScript Library v1.4.1 * http://jquery.com/ * * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Mon Jan 25 19:43:33 2010 -0500 */ (function( window, undefined ) { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // Use the correct document accordingly with window argument (sandbox) document = window.document, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // (both of which we optimize for) quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, // Is it a simple selector isSimple = /^.[^:#\[\.,]*$/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // Has the ready events already been bound? readyBound = false, // The functions to execute on DOM ready readyList = [], // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwnProperty = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, indexOf = Array.prototype.indexOf; jQuery.fn = jQuery.prototype = { init: function( selector, context ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? match = quickExpr.exec( selector ); // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { doc = (context ? context.ownerDocument || context : document); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = buildFragment( [ match[1] ], [ doc ] ); selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; } // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); if ( elem ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $("TAG") } else if ( !context && /^\w+$/.test( selector ) ) { this.selector = selector; this.context = document; selector = document.getElementsByTagName( selector ); // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return jQuery( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.isArray( selector ) ? this.setArray( selector ) : jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.4.1", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = jQuery( elems || null ); // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + (this.selector ? " " : "") + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Force the current matched set of elements to become // the specified array of elements (destroying the stack in the process) // You should use pushStack() in order to do this, but maintain the stack setArray: function( elems ) { // Resetting the length to 0, then using the native Array push // is a super-fast way to populate an object with array-like properties this.length = 0; push.apply( this, elems ); return this; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // If the DOM is already ready if ( jQuery.isReady ) { // Execute the function immediately fn.call( document, jQuery ); // Otherwise, remember the function for later } else if ( readyList ) { // Add the function to the wait list readyList.push( fn ); } return this; }, eq: function( i ) { return i === -1 ? this.slice( i ) : this.slice( i, +i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || jQuery(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { // copy reference to target object var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging object literal values or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src : jQuery.isArray(copy) ? [] : {}; // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { window.$ = _$; if ( deep ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // Handle when the DOM is ready ready: function() { // Make sure that the DOM is not already loaded if ( !jQuery.isReady ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 13 ); } // Remember that the DOM is ready jQuery.isReady = true; // If there are functions bound, to execute if ( readyList ) { // Execute all of them var fn, i = 0; while ( (fn = readyList[ i++ ]) ) { fn.call( document, jQuery ); } // Reset the list of functions readyList = null; } // Trigger any bound ready events if ( jQuery.fn.triggerHandler ) { jQuery( document ).triggerHandler( "ready" ); } } }, bindReady: function() { if ( readyBound ) { return; } readyBound = true; // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { return jQuery.ready(); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent("onreadystatechange", DOMContentLoaded); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return toString.call(obj) === "[object Function]"; }, isArray: function( obj ) { return toString.call(obj) === "[object Array]"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { return false; } // Not own constructor property must be Object if ( obj.constructor && !hasOwnProperty.call(obj, "constructor") && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwnProperty.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw msg; }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { // Try to use the native JSON parser first return window.JSON && window.JSON.parse ? window.JSON.parse( data ) : (new Function("return " + data))(); } else { jQuery.error( "Invalid JSON: " + data ); } }, noop: function() {}, // Evalulates a script in a global context globalEval: function( data ) { if ( data && rnotwhite.test(data) ) { // Inspired by code by Andrea Giammarchi // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html var head = document.getElementsByTagName("head")[0] || document.documentElement, script = document.createElement("script"); script.type = "text/javascript"; if ( jQuery.support.scriptEval ) { script.appendChild( document.createTextNode( data ) ); } else { script.text = data; } // Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709). head.insertBefore( script, head.firstChild ); head.removeChild( script ); } }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } } return object; }, trim: function( text ) { return (text || "").replace( rtrim, "" ); }, // results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // The extra typeof function check is to prevent crashes // in Safari 2 (See: #3039) if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array ) { if ( array.indexOf ) { return array.indexOf( elem ); } for ( var i = 0, length = array.length; i < length; i++ ) { if ( array[ i ] === elem ) { return i; } } return -1; }, merge: function( first, second ) { var i = first.length, j = 0; if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var ret = []; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { if ( !inv !== !callback( elems[ i ], i ) ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var ret = [], value; // Go through the array, translating each of the items to their // new value (or values). for ( var i = 0, length = elems.length; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, proxy: function( fn, proxy, thisObject ) { if ( arguments.length === 2 ) { if ( typeof proxy === "string" ) { thisObject = fn; fn = thisObject[ proxy ]; proxy = undefined; } else if ( proxy && !jQuery.isFunction( proxy ) ) { thisObject = proxy; proxy = undefined; } } if ( !proxy && fn ) { proxy = function() { return fn.apply( thisObject || this, arguments ); }; } // Set the guid of unique handler to the same of original handler, so it can be removed if ( fn ) { proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; } // So proxy can be declared as an argument return proxy; }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || /(msie) ([\w.]+)/.exec( ua ) || !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, browser: {} }); browserMatch = jQuery.uaMatch( userAgent ); if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version; } // Deprecated, use jQuery.browser.webkit instead if ( jQuery.browser.webkit ) { jQuery.browser.safari = true; } if ( indexOf ) { jQuery.inArray = function( elem, array ) { return indexOf.call( array, elem ); }; } // All jQuery objects should point back to these rootjQuery = jQuery(document); // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }; } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( jQuery.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch( error ) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready(); } function evalScript( i, elem ) { if ( elem.src ) { jQuery.ajax({ url: elem.src, async: false, dataType: "script" }); } else { jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); } if ( elem.parentNode ) { elem.parentNode.removeChild( elem ); } } // Mutifunctional method to get and set values to a collection // The value/s can be optionally by executed if its a function function access( elems, key, value, exec, fn, pass ) { var length = elems.length; // Setting many attributes if ( typeof key === "object" ) { for ( var k in key ) { access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attribute if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } // Getting an attribute return length ? fn( elems[0], key ) : null; } function now() { return (new Date).getTime(); } (function() { jQuery.support = {}; var root = document.documentElement, script = document.createElement("script"), div = document.createElement("div"), id = "script" + now(); div.style.display = "none"; div.innerHTML = "
            a"; var all = div.getElementsByTagName("*"), a = div.getElementsByTagName("a")[0]; // Can't get basic test support if ( !all || !all.length || !a ) { return; } jQuery.support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: div.firstChild.nodeType === 3, // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName("tbody").length, // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName("link").length, // Get the style information from getAttribute // (IE uses .cssText insted) style: /red/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: a.getAttribute("href") === "/a", // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 opacity: /^0.55$/.test( a.style.opacity ), // Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat, // Make sure that if no value is specified for a checkbox // that it defaults to "on". // (WebKit defaults to "" instead) checkOn: div.getElementsByTagName("input")[0].value === "on", // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected, // Will be defined later checkClone: false, scriptEval: false, noCloneEvent: true, boxModel: null }; script.type = "text/javascript"; try { script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); } catch(e) {} root.insertBefore( script, root.firstChild ); // Make sure that the execution of code works by injecting a script // tag with appendChild/createTextNode // (IE doesn't support this, fails, and uses .text instead) if ( window[ id ] ) { jQuery.support.scriptEval = true; delete window[ id ]; } root.removeChild( script ); if ( div.attachEvent && div.fireEvent ) { div.attachEvent("onclick", function click() { // Cloning a node shouldn't copy over any // bound event handlers (IE does this) jQuery.support.noCloneEvent = false; div.detachEvent("onclick", click); }); div.cloneNode(true).fireEvent("onclick"); } div = document.createElement("div"); div.innerHTML = ""; var fragment = document.createDocumentFragment(); fragment.appendChild( div.firstChild ); // WebKit doesn't clone checked state correctly in fragments jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; // Figure out if the W3C box model works as expected // document.body must exist before we can do this jQuery(function() { var div = document.createElement("div"); div.style.width = div.style.paddingLeft = "1px"; document.body.appendChild( div ); jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; document.body.removeChild( div ).style.display = 'none'; div = null; }); // Technique from Juriy Zaytsev // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ var eventSupported = function( eventName ) { var el = document.createElement("div"); eventName = "on" + eventName; var isSupported = (eventName in el); if ( !isSupported ) { el.setAttribute(eventName, "return;"); isSupported = typeof el[eventName] === "function"; } el = null; return isSupported; }; jQuery.support.submitBubbles = eventSupported("submit"); jQuery.support.changeBubbles = eventSupported("change"); // release memory in IE root = script = div = all = a = null; })(); jQuery.props = { "for": "htmlFor", "class": "className", readonly: "readOnly", maxlength: "maxLength", cellspacing: "cellSpacing", rowspan: "rowSpan", colspan: "colSpan", tabindex: "tabIndex", usemap: "useMap", frameborder: "frameBorder" }; var expando = "jQuery" + now(), uuid = 0, windowData = {}; var emptyObject = {}; jQuery.extend({ cache: {}, expando:expando, // The following elements throw uncatchable exceptions if you // attempt to add expando properties to them. noData: { "embed": true, "object": true, "applet": true }, data: function( elem, name, data ) { if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { return; } elem = elem == window ? windowData : elem; var id = elem[ expando ], cache = jQuery.cache, thisCache; // Handle the case where there's no name immediately if ( !name && !id ) { return null; } // Compute a unique ID for the element if ( !id ) { id = ++uuid; } // Avoid generating a new cache unless none exists and we // want to manipulate it. if ( typeof name === "object" ) { elem[ expando ] = id; thisCache = cache[ id ] = jQuery.extend(true, {}, name); } else if ( cache[ id ] ) { thisCache = cache[ id ]; } else if ( typeof data === "undefined" ) { thisCache = emptyObject; } else { thisCache = cache[ id ] = {}; } // Prevent overriding the named cache with undefined values if ( data !== undefined ) { elem[ expando ] = id; thisCache[ name ] = data; } return typeof name === "string" ? thisCache[ name ] : thisCache; }, removeData: function( elem, name ) { if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { return; } elem = elem == window ? windowData : elem; var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; // If we want to remove a specific section of the element's data if ( name ) { if ( thisCache ) { // Remove the section of cache data delete thisCache[ name ]; // If we've removed all the data, remove the element's cache if ( jQuery.isEmptyObject(thisCache) ) { jQuery.removeData( elem ); } } // Otherwise, we want to remove all of the element's data } else { // Clean up the element expando try { delete elem[ expando ]; } catch( e ) { // IE has trouble directly removing the expando // but it's ok with using removeAttribute if ( elem.removeAttribute ) { elem.removeAttribute( expando ); } } // Completely remove the data cache delete cache[ id ]; } } }); jQuery.fn.extend({ data: function( key, value ) { if ( typeof key === "undefined" && this.length ) { return jQuery.data( this[0] ); } else if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } var parts = key.split("."); parts[1] = parts[1] ? "." + parts[1] : ""; if ( value === undefined ) { var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); if ( data === undefined && this.length ) { data = jQuery.data( this[0], key ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } else { return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() { jQuery.data( this, key, value ); }); } }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); jQuery.extend({ queue: function( elem, type, data ) { if ( !elem ) { return; } type = (type || "fx") + "queue"; var q = jQuery.data( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( !data ) { return q || []; } if ( !q || jQuery.isArray(data) ) { q = jQuery.data( elem, type, jQuery.makeArray(data) ); } else { q.push( data ); } return q; }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(); // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift("inprogress"); } fn.call(elem, function() { jQuery.dequeue(elem, type); }); } } }); jQuery.fn.extend({ queue: function( type, data ) { if ( typeof type !== "string" ) { data = type; type = "fx"; } if ( data === undefined ) { return jQuery.queue( this[0], type ); } return this.each(function( i, elem ) { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; type = type || "fx"; return this.queue( type, function() { var elem = this; setTimeout(function() { jQuery.dequeue( elem, type ); }, time ); }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); } }); var rclass = /[\n\t]/g, rspace = /\s+/, rreturn = /\r/g, rspecialurl = /href|src|style/, rtype = /(button|input)/i, rfocusable = /(button|input|object|select|textarea)/i, rclickable = /^(a|area)$/i, rradiocheck = /radio|checkbox/; jQuery.fn.extend({ attr: function( name, value ) { return access( this, name, value, true, jQuery.attr ); }, removeAttr: function( name, fn ) { return this.each(function(){ jQuery.attr( this, name, "" ); if ( this.nodeType === 1 ) { this.removeAttribute( name ); } }); }, addClass: function( value ) { if ( jQuery.isFunction(value) ) { return this.each(function(i) { var self = jQuery(this); self.addClass( value.call(this, i, self.attr("class")) ); }); } if ( value && typeof value === "string" ) { var classNames = (value || "").split( rspace ); for ( var i = 0, l = this.length; i < l; i++ ) { var elem = this[i]; if ( elem.nodeType === 1 ) { if ( !elem.className ) { elem.className = value; } else { var className = " " + elem.className + " "; for ( var c = 0, cl = classNames.length; c < cl; c++ ) { if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { elem.className += " " + classNames[c]; } } } } } } return this; }, removeClass: function( value ) { if ( jQuery.isFunction(value) ) { return this.each(function(i) { var self = jQuery(this); self.removeClass( value.call(this, i, self.attr("class")) ); }); } if ( (value && typeof value === "string") || value === undefined ) { var classNames = (value || "").split(rspace); for ( var i = 0, l = this.length; i < l; i++ ) { var elem = this[i]; if ( elem.nodeType === 1 && elem.className ) { if ( value ) { var className = (" " + elem.className + " ").replace(rclass, " "); for ( var c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[c] + " ", " "); } elem.className = className.substring(1, className.length - 1); } else { elem.className = ""; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this); self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery(this), state = stateVal, classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space separated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery.data( this, "__className__", this.className ); } // toggle whole className this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " "; for ( var i = 0, l = this.length; i < l; i++ ) { if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { return true; } } return false; }, val: function( value ) { if ( value === undefined ) { var elem = this[0]; if ( elem ) { if ( jQuery.nodeName( elem, "option" ) ) { return (elem.attributes.value || {}).specified ? elem.value : elem.text; } // We need to handle select boxes special if ( jQuery.nodeName( elem, "select" ) ) { var index = elem.selectedIndex, values = [], options = elem.options, one = elem.type === "select-one"; // Nothing was selected if ( index < 0 ) { return null; } // Loop through all the selected options for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { var option = options[ i ]; if ( option.selected ) { // Get the specifc value for the option value = jQuery(option).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } return values; } // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { return elem.getAttribute("value") === null ? "on" : elem.value; } // Everything else, we just grab the value return (elem.value || "").replace(rreturn, ""); } return undefined; } var isFunction = jQuery.isFunction(value); return this.each(function(i) { var self = jQuery(this), val = value; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call(this, i, self.val()); } // Typecast each time if the value is a Function and the appended // value is therefore different each time. if ( typeof val === "number" ) { val += ""; } if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { this.checked = jQuery.inArray( self.val(), val ) >= 0; } else if ( jQuery.nodeName( this, "select" ) ) { var values = jQuery.makeArray(val); jQuery( "option", this ).each(function() { this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { this.selectedIndex = -1; } } else { this.value = val; } }); } }); jQuery.extend({ attrFn: { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true }, attr: function( elem, name, value, pass ) { // don't set attributes on text and comment nodes if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { return undefined; } if ( pass && name in jQuery.attrFn ) { return jQuery(elem)[name](value); } var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), // Whether we are setting (or getting) set = value !== undefined; // Try to normalize/fix the name name = notxml && jQuery.props[ name ] || name; // Only do all the following if this is a node (faster for style) if ( elem.nodeType === 1 ) { // These attributes require special treatment var special = rspecialurl.test( name ); // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( name === "selected" && !jQuery.support.optSelected ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } } // If applicable, access the attribute via the DOM 0 way if ( name in elem && notxml && !special ) { if ( set ) { // We can't allow the type property to be changed (since it causes problems in IE) if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } elem[ name ] = value; } // browsers index elements by id/name on forms, give priority to attributes. if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { return elem.getAttributeNode( name ).nodeValue; } // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ if ( name === "tabIndex" ) { var attributeNode = elem.getAttributeNode( "tabIndex" ); return attributeNode && attributeNode.specified ? attributeNode.value : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } return elem[ name ]; } if ( !jQuery.support.style && notxml && name === "style" ) { if ( set ) { elem.style.cssText = "" + value; } return elem.style.cssText; } if ( set ) { // convert the value to a string (all browsers do this but IE) see #1070 elem.setAttribute( name, "" + value ); } var attr = !jQuery.support.hrefNormalized && notxml && special ? // Some attributes require a special call on IE elem.getAttribute( name, 2 ) : elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined return attr === null ? undefined : attr; } // elem is actually elem.style ... set the style // Using attr for specific style information is now deprecated. Use style insead. return jQuery.style( elem, name, value ); } }); var fcleanup = function( nm ) { return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { return "\\" + ch; }); }; /* * A number of helper functions used for managing events. * Many of the ideas behind this code originated from * Dean Edwards' addEvent library. */ jQuery.event = { // Bind an event to an element // Original by Dean Edwards add: function( elem, types, handler, data ) { if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // For whatever reason, IE has trouble passing the window object // around, causing it to be cloned in the process if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) { elem = window; } // Make sure that the function being executed has a unique ID if ( !handler.guid ) { handler.guid = jQuery.guid++; } // if data is passed, bind to handler if ( data !== undefined ) { // Create temporary function pointer to original handler var fn = handler; // Create unique handler function, wrapped around original handler handler = jQuery.proxy( fn ); // Store data in unique handler handler.data = data; } // Init the element's event structure var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ), handle = jQuery.data( elem, "handle" ), eventHandle; if ( !handle ) { eventHandle = function() { // Handle the second event of a trigger and when // an event is called after a page has unloaded return typeof jQuery !== "undefined" && !jQuery.event.triggered ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; handle = jQuery.data( elem, "handle", eventHandle ); } // If no handle is found then we must be trying to bind to one of the // banned noData elements if ( !handle ) { return; } // Add elem as a property of the handle function // This is to prevent a memory leak with non-native // event in IE. handle.elem = elem; // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); types = types.split( /\s+/ ); var type, i = 0; while ( (type = types[ i++ ]) ) { // Namespaced event handlers var namespaces = type.split("."); type = namespaces.shift(); if ( i > 1 ) { handler = jQuery.proxy( handler ); if ( data !== undefined ) { handler.data = data; } } handler.type = namespaces.slice(0).sort().join("."); // Get the current list of functions bound to this event var handlers = events[ type ], special = this.special[ type ] || {}; // Init the event handler queue if ( !handlers ) { handlers = events[ type ] = {}; // Check for a special event handler // Only use addEventListener/attachEvent if the special // events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, handle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, handle ); } } } if ( special.add ) { var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers ); if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) { modifiedHandler.guid = modifiedHandler.guid || handler.guid; modifiedHandler.data = modifiedHandler.data || handler.data; modifiedHandler.type = modifiedHandler.type || handler.type; handler = modifiedHandler; } } // Add the function to the element's handler list handlers[ handler.guid ] = handler; // Keep track of which events have been used, for global triggering this.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, global: {}, // Detach an event or set of events from an element remove: function( elem, types, handler ) { // don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } var events = jQuery.data( elem, "events" ), ret, type, fn; if ( events ) { // Unbind all events for the element if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) { for ( type in events ) { this.remove( elem, type + (types || "") ); } } else { // types is actually an event object here if ( types.type ) { handler = types.handler; types = types.type; } // Handle multiple events separated by a space // jQuery(...).unbind("mouseover mouseout", fn); types = types.split(/\s+/); var i = 0; while ( (type = types[ i++ ]) ) { // Namespaced event handlers var namespaces = type.split("."); type = namespaces.shift(); var all = !namespaces.length, cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ), namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"), special = this.special[ type ] || {}; if ( events[ type ] ) { // remove the given handler for the given type if ( handler ) { fn = events[ type ][ handler.guid ]; delete events[ type ][ handler.guid ]; // remove all handlers for the given type } else { for ( var handle in events[ type ] ) { // Handle the removal of namespaced events if ( all || namespace.test( events[ type ][ handle ].type ) ) { delete events[ type ][ handle ]; } } } if ( special.remove ) { special.remove.call( elem, namespaces, fn); } // remove generic event handler if no more handlers exist for ( ret in events[ type ] ) { break; } if ( !ret ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, jQuery.data( elem, "handle" ), false ); } else if ( elem.detachEvent ) { elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) ); } } ret = null; delete events[ type ]; } } } } // Remove the expando if it's no longer used for ( ret in events ) { break; } if ( !ret ) { var handle = jQuery.data( elem, "handle" ); if ( handle ) { handle.elem = null; } jQuery.removeData( elem, "events" ); jQuery.removeData( elem, "handle" ); } } }, // bubbling is internal trigger: function( event, data, elem /*, bubbling */ ) { // Event object or event type var type = event.type || event, bubbling = arguments[3]; if ( !bubbling ) { event = typeof event === "object" ? // jQuery.Event object event[expando] ? event : // Object literal jQuery.extend( jQuery.Event(type), event ) : // Just the event type (string) jQuery.Event(type); if ( type.indexOf("!") >= 0 ) { event.type = type = type.slice(0, -1); event.exclusive = true; } // Handle a global trigger if ( !elem ) { // Don't bubble custom events when global (to avoid too much overhead) event.stopPropagation(); // Only trigger if we've ever bound an event for it if ( this.global[ type ] ) { jQuery.each( jQuery.cache, function() { if ( this.events && this.events[type] ) { jQuery.event.trigger( event, data, this.handle.elem ); } }); } } // Handle triggering a single element // don't do events on text and comment nodes if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { return undefined; } // Clean up in case it is reused event.result = undefined; event.target = elem; // Clone the incoming data, if any data = jQuery.makeArray( data ); data.unshift( event ); } event.currentTarget = elem; // Trigger the event, it is assumed that "handle" is a function var handle = jQuery.data( elem, "handle" ); if ( handle ) { handle.apply( elem, data ); } var parent = elem.parentNode || elem.ownerDocument; // Trigger an inline bound script try { if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { event.result = false; } } // prevent IE from throwing an error for some elements with some event types, see #3533 } catch (e) {} if ( !event.isPropagationStopped() && parent ) { jQuery.event.trigger( event, data, parent, true ); } else if ( !event.isDefaultPrevented() ) { var target = event.target, old, isClick = jQuery.nodeName(target, "a") && type === "click"; if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { try { if ( target[ type ] ) { // Make sure that we don't accidentally re-trigger the onFOO events old = target[ "on" + type ]; if ( old ) { target[ "on" + type ] = null; } this.triggered = true; target[ type ](); } // prevent IE from throwing an error for some elements with some event types, see #3533 } catch (e) {} if ( old ) { target[ "on" + type ] = old; } this.triggered = false; } } }, handle: function( event ) { // returned undefined or false var all, handlers; event = arguments[0] = jQuery.event.fix( event || window.event ); event.currentTarget = this; // Namespaced event handlers var namespaces = event.type.split("."); event.type = namespaces.shift(); // Cache this now, all = true means, any handler all = !namespaces.length && !event.exclusive; var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); handlers = ( jQuery.data(this, "events") || {} )[ event.type ]; for ( var j in handlers ) { var handler = handlers[ j ]; // Filter the functions by class if ( all || namespace.test(handler.type) ) { // Pass in a reference to the handler function itself // So that we can later remove it event.handler = handler; event.data = handler.data; var ret = handler.apply( this, arguments ); if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } if ( event.isImmediatePropagationStopped() ) { break; } } } return event.result; }, props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), fix: function( event ) { if ( event[ expando ] ) { return event; } // store a copy of the original event object // and "clone" to set read-only properties var originalEvent = event; event = jQuery.Event( originalEvent ); for ( var i = this.props.length, prop; i; ) { prop = this.props[ --i ]; event[ prop ] = originalEvent[ prop ]; } // Fix target property, if necessary if ( !event.target ) { event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either } // check if target is a textnode (safari) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // Add relatedTarget, if necessary if ( !event.relatedTarget && event.fromElement ) { event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; } // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && event.clientX != null ) { var doc = document.documentElement, body = document.body; event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); } // Add which for key events if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) { event.which = event.charCode || event.keyCode; } // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) if ( !event.metaKey && event.ctrlKey ) { event.metaKey = event.ctrlKey; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && event.button !== undefined ) { event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); } return event; }, // Deprecated, use jQuery.guid instead guid: 1E8, // Deprecated, use jQuery.proxy instead proxy: jQuery.proxy, special: { ready: { // Make sure the ready event is setup setup: jQuery.bindReady, teardown: jQuery.noop }, live: { add: function( proxy, data, namespaces, live ) { jQuery.extend( proxy, data || {} ); proxy.guid += data.selector + data.live; data.liveProxy = proxy; jQuery.event.add( this, data.live, liveHandler, data ); }, remove: function( namespaces ) { if ( namespaces.length ) { var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)"); jQuery.each( (jQuery.data(this, "events").live || {}), function() { if ( name.test(this.type) ) { remove++; } }); if ( remove < 1 ) { jQuery.event.remove( this, namespaces[0], liveHandler ); } } }, special: {} }, beforeunload: { setup: function( data, namespaces, fn ) { // We only want to do this special case on windows if ( this.setInterval ) { this.onbeforeunload = fn; } return false; }, teardown: function( namespaces, fn ) { if ( this.onbeforeunload === fn ) { this.onbeforeunload = null; } } } } }; jQuery.Event = function( src ) { // Allow instantiation without the 'new' keyword if ( !this.preventDefault ) { return new jQuery.Event( src ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Event type } else { this.type = src; } // timeStamp is buggy for some events on Firefox(#3843) // So we won't rely on the native value this.timeStamp = now(); // Mark it as fixed this[ expando ] = true; }; function returnFalse() { return false; } function returnTrue() { return true; } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); } // otherwise set the returnValue property of the original event to false (IE) e.returnValue = false; }, stopPropagation: function() { this.isPropagationStopped = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if stopPropagation exists run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // otherwise set the cancelBubble property of the original event to true (IE) e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); }, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse }; // Checks if an event happened on an element within another element // Used in jQuery.event.special.mouseenter and mouseleave handlers var withinElement = function( event ) { // Check if mouse(over|out) are still within the same parent element var parent = event.relatedTarget; // Traverse up the tree while ( parent && parent !== this ) { // Firefox sometimes assigns relatedTarget a XUL element // which we cannot access the parentNode property of try { parent = parent.parentNode; // assuming we've left the element since we most likely mousedover a xul element } catch(e) { break; } } if ( parent !== this ) { // set the correct event type event.type = event.data; // handle event if we actually just moused on to a non sub-element jQuery.event.handle.apply( this, arguments ); } }, // In case of event delegation, we only need to rename the event.type, // liveHandler will take care of the rest. delegate = function( event ) { event.type = event.data; jQuery.event.handle.apply( this, arguments ); }; // Create mouseenter and mouseleave events jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { setup: function( data ) { jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); }, teardown: function( data ) { jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); } }; }); // submit delegation if ( !jQuery.support.submitBubbles ) { jQuery.event.special.submit = { setup: function( data, namespaces, fn ) { if ( this.nodeName.toLowerCase() !== "form" ) { jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) { var elem = e.target, type = elem.type; if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { return trigger( "submit", this, arguments ); } }); jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) { var elem = e.target, type = elem.type; if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { return trigger( "submit", this, arguments ); } }); } else { return false; } }, remove: function( namespaces, fn ) { jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") ); jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") ); } }; } // change delegation, happens here so we have bind. if ( !jQuery.support.changeBubbles ) { var formElems = /textarea|input|select/i; function getVal( elem ) { var type = elem.type, val = elem.value; if ( type === "radio" || type === "checkbox" ) { val = elem.checked; } else if ( type === "select-multiple" ) { val = elem.selectedIndex > -1 ? jQuery.map( elem.options, function( elem ) { return elem.selected; }).join("-") : ""; } else if ( elem.nodeName.toLowerCase() === "select" ) { val = elem.selectedIndex; } return val; } function testChange( e ) { var elem = e.target, data, val; if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { return; } data = jQuery.data( elem, "_change_data" ); val = getVal(elem); // the current data will be also retrieved by beforeactivate if ( e.type !== "focusout" || elem.type !== "radio" ) { jQuery.data( elem, "_change_data", val ); } if ( data === undefined || val === data ) { return; } if ( data != null || val ) { e.type = "change"; return jQuery.event.trigger( e, arguments[1], elem ); } } jQuery.event.special.change = { filters: { focusout: testChange, click: function( e ) { var elem = e.target, type = elem.type; if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { return testChange.call( this, e ); } }, // Change has to be called before submit // Keydown will be called before keypress, which is used in submit-event delegation keydown: function( e ) { var elem = e.target, type = elem.type; if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || type === "select-multiple" ) { return testChange.call( this, e ); } }, // Beforeactivate happens also before the previous element is blurred // with this event you can't trigger a change event, but you can store // information/focus[in] is not needed anymore beforeactivate: function( e ) { var elem = e.target; if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) { jQuery.data( elem, "_change_data", getVal(elem) ); } } }, setup: function( data, namespaces, fn ) { for ( var type in changeFilters ) { jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] ); } return formElems.test( this.nodeName ); }, remove: function( namespaces, fn ) { for ( var type in changeFilters ) { jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] ); } return formElems.test( this.nodeName ); } }; var changeFilters = jQuery.event.special.change.filters; } function trigger( type, elem, args ) { args[0].type = type; return jQuery.event.handle.apply( elem, args ); } // Create "bubbling" focus and blur events if ( document.addEventListener ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { jQuery.event.special[ fix ] = { setup: function() { this.addEventListener( orig, handler, true ); }, teardown: function() { this.removeEventListener( orig, handler, true ); } }; function handler( e ) { e = jQuery.event.fix( e ); e.type = fix; return jQuery.event.handle.call( this, e ); } }); } jQuery.each(["bind", "one"], function( i, name ) { jQuery.fn[ name ] = function( type, data, fn ) { // Handle object literals if ( typeof type === "object" ) { for ( var key in type ) { this[ name ](key, data, type[key], fn); } return this; } if ( jQuery.isFunction( data ) ) { fn = data; data = undefined; } var handler = name === "one" ? jQuery.proxy( fn, function( event ) { jQuery( this ).unbind( event, handler ); return fn.apply( this, arguments ); }) : fn; return type === "unload" && name !== "one" ? this.one( type, data, fn ) : this.each(function() { jQuery.event.add( this, type, handler, data ); }); }; }); jQuery.fn.extend({ unbind: function( type, fn ) { // Handle object literals if ( typeof type === "object" && !type.preventDefault ) { for ( var key in type ) { this.unbind(key, type[key]); } return this; } return this.each(function() { jQuery.event.remove( this, type, fn ); }); }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { if ( this[0] ) { var event = jQuery.Event( type ); event.preventDefault(); event.stopPropagation(); jQuery.event.trigger( event, data, this[0] ); return event.result; } }, toggle: function( fn ) { // Save reference to arguments for access in closure var args = arguments, i = 1; // link all the functions, so any of them can unbind this click handler while ( i < args.length ) { jQuery.proxy( fn, args[ i++ ] ); } return this.click( jQuery.proxy( fn, function( event ) { // Figure out which function to execute var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; })); }, hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } }); jQuery.each(["live", "die"], function( i, name ) { jQuery.fn[ name ] = function( types, data, fn ) { var type, i = 0; if ( jQuery.isFunction( data ) ) { fn = data; data = undefined; } types = (types || "").split( /\s+/ ); while ( (type = types[ i++ ]) != null ) { type = type === "focus" ? "focusin" : // focus --> focusin type === "blur" ? "focusout" : // blur --> focusout type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support type; if ( name === "live" ) { // bind live handler jQuery( this.context ).bind( liveConvert( type, this.selector ), { data: data, selector: this.selector, live: type }, fn ); } else { // unbind live handler jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null ); } } return this; } }); function liveHandler( event ) { var stop, elems = [], selectors = [], args = arguments, related, match, fn, elem, j, i, l, data, live = jQuery.extend({}, jQuery.data( this, "events" ).live); // Make sure we avoid non-left-click bubbling in Firefox (#3861) if ( event.button && event.type === "click" ) { return; } for ( j in live ) { fn = live[j]; if ( fn.live === event.type || fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) { data = fn.data; if ( !(data.beforeFilter && data.beforeFilter[event.type] && !data.beforeFilter[event.type](event)) ) { selectors.push( fn.selector ); } } else { delete live[j]; } } match = jQuery( event.target ).closest( selectors, event.currentTarget ); for ( i = 0, l = match.length; i < l; i++ ) { for ( j in live ) { fn = live[j]; elem = match[i].elem; related = null; if ( match[i].selector === fn.selector ) { // Those two events require additional checking if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) { related = jQuery( event.relatedTarget ).closest( fn.selector )[0]; } if ( !related || related !== elem ) { elems.push({ elem: elem, fn: fn }); } } } } for ( i = 0, l = elems.length; i < l; i++ ) { match = elems[i]; event.currentTarget = match.elem; event.data = match.fn.data; if ( match.fn.apply( match.elem, args ) === false ) { stop = false; break; } } return stop; } function liveConvert( type, selector ) { return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); } jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( fn ) { return fn ? this.bind( name, fn ) : this.trigger( name ); }; if ( jQuery.attrFn ) { jQuery.attrFn[ name ] = true; } }); // Prevent memory leaks in IE // Window isn't included so as not to unbind existing unload events // More info: // - http://isaacschlueter.com/2006/10/msie-memory-leaks/ if ( window.attachEvent && !window.addEventListener ) { window.attachEvent("onunload", function() { for ( var id in jQuery.cache ) { if ( jQuery.cache[ id ].handle ) { // Try/Catch is to handle iframes being unloaded, see #4280 try { jQuery.event.remove( jQuery.cache[ id ].handle.elem ); } catch(e) {} } } }); } /*! * Sizzle CSS Selector Engine - v1.0 * Copyright 2009, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function(){ baseHasDuplicate = false; return 0; }); var Sizzle = function(selector, context, results, seed) { results = results || []; var origContext = context = context || document; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), soFar = selector; // Reset the position of the chunker regexp (start from head) while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { var ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { var ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray(set); } else { prune = false; } while ( parts.length ) { var cur = parts.pop(), pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( var i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( var i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function(results){ if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort(sortOrder); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[i-1] ) { results.splice(i--, 1); } } } } return results; }; Sizzle.matches = function(expr, set){ return Sizzle(expr, null, null, set); }; Sizzle.find = function(expr, context, isXML){ var set, match; if ( !expr ) { return []; } for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var type = Expr.order[i], match; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice(1,1); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace(/\\/g, ""); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = context.getElementsByTagName("*"); } return {set: set, expr: expr}; }; Sizzle.filter = function(expr, set, inplace, not){ var old = expr, result = [], curLoop = set, match, anyFound, isXMLFilter = set && set[0] && isXML(set[0]); while ( expr && set.length ) { for ( var type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { var filter = Expr.filter[ type ], found, item, left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( var i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); var pass = not ^ !!found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw "Syntax error, unrecognized expression: " + msg; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function(elem){ return elem.getAttribute("href"); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !/\W/.test(part), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function(checkSet, part){ var isPartStr = typeof part === "string"; if ( isPartStr && !/\W/.test(part) ) { part = part.toLowerCase(); for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !/\W/.test(part) ) { var nodeCheck = part = part.toLowerCase(); checkFn = dirNodeCheck; } checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); }, "~": function(checkSet, part, isXML){ var doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !/\W/.test(part) ) { var nodeCheck = part = part.toLowerCase(); checkFn = dirNodeCheck; } checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); } }, find: { ID: function(match, context, isXML){ if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? [m] : []; } }, NAME: function(match, context){ if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName(match[1]); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function(match, context){ return context.getElementsByTagName(match[1]); } }, preFilter: { CLASS: function(match, curLoop, inplace, result, not, isXML){ match = " " + match[1].replace(/\\/g, "") + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function(match){ return match[1].replace(/\\/g, ""); }, TAG: function(match, curLoop){ return match[1].toLowerCase(); }, CHILD: function(match){ if ( match[1] === "nth" ) { // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function(match, curLoop, inplace, result, not, isXML){ var name = match[1].replace(/\\/g, ""); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function(match, curLoop, inplace, result, not){ if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function(match){ match.unshift( true ); return match; } }, filters: { enabled: function(elem){ return elem.disabled === false && elem.type !== "hidden"; }, disabled: function(elem){ return elem.disabled === true; }, checked: function(elem){ return elem.checked === true; }, selected: function(elem){ // Accessing this property makes selected-by-default // options in Safari work properly elem.parentNode.selectedIndex; return elem.selected === true; }, parent: function(elem){ return !!elem.firstChild; }, empty: function(elem){ return !elem.firstChild; }, has: function(elem, i, match){ return !!Sizzle( match[3], elem ).length; }, header: function(elem){ return /h\d/i.test( elem.nodeName ); }, text: function(elem){ return "text" === elem.type; }, radio: function(elem){ return "radio" === elem.type; }, checkbox: function(elem){ return "checkbox" === elem.type; }, file: function(elem){ return "file" === elem.type; }, password: function(elem){ return "password" === elem.type; }, submit: function(elem){ return "submit" === elem.type; }, image: function(elem){ return "image" === elem.type; }, reset: function(elem){ return "reset" === elem.type; }, button: function(elem){ return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; }, input: function(elem){ return /input|select|textarea|button/i.test(elem.nodeName); } }, setFilters: { first: function(elem, i){ return i === 0; }, last: function(elem, i, match, array){ return i === array.length - 1; }, even: function(elem, i){ return i % 2 === 0; }, odd: function(elem, i){ return i % 2 === 1; }, lt: function(elem, i, match){ return i < match[3] - 0; }, gt: function(elem, i, match){ return i > match[3] - 0; }, nth: function(elem, i, match){ return match[3] - 0 === i; }, eq: function(elem, i, match){ return match[3] - 0 === i; } }, filter: { PSEUDO: function(elem, match, i, array){ var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var i = 0, l = not.length; i < l; i++ ) { if ( not[i] === elem ) { return false; } } return true; } else { Sizzle.error( "Syntax error, unrecognized expression: " + name ); } }, CHILD: function(elem, match){ var type = match[1], node = elem; switch (type) { case 'only': case 'first': while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; case 'last': while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case 'nth': var first = match[2], last = match[3]; if ( first === 1 && last === 0 ) { return true; } var doneName = match[0], parent = elem.parentNode; if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent.sizcache = doneName; } var diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function(elem, match){ return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function(elem, match){ return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, CLASS: function(elem, match){ return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function(elem, match){ var name = match[1], result = Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function(elem, match, i, array){ var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){ return "\\" + (num - 0 + 1); })); } var makeArray = function(array, results) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. try { Array.prototype.slice.call( document.documentElement.childNodes, 0 ); // Provide a fallback method if it does not work } catch(e){ makeArray = function(array, results) { var ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var i = 0, l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( var i = 0; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { if ( a == b ) { hasDuplicate = true; } return a.compareDocumentPosition ? -1 : 1; } var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; if ( ret === 0 ) { hasDuplicate = true; } return ret; }; } else if ( "sourceIndex" in document.documentElement ) { sortOrder = function( a, b ) { if ( !a.sourceIndex || !b.sourceIndex ) { if ( a == b ) { hasDuplicate = true; } return a.sourceIndex ? -1 : 1; } var ret = a.sourceIndex - b.sourceIndex; if ( ret === 0 ) { hasDuplicate = true; } return ret; }; } else if ( document.createRange ) { sortOrder = function( a, b ) { if ( !a.ownerDocument || !b.ownerDocument ) { if ( a == b ) { hasDuplicate = true; } return a.ownerDocument ? -1 : 1; } var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); aRange.setStart(a, 0); aRange.setEnd(a, 0); bRange.setStart(b, 0); bRange.setEnd(b, 0); var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); if ( ret === 0 ) { hasDuplicate = true; } return ret; }; } // Utility function for retreiving the text value of an array of DOM nodes function getText( elems ) { var ret = "", elem; for ( var i = 0; elems[i]; i++ ) { elem = elems[i]; // Get the text from text nodes and CDATA nodes if ( elem.nodeType === 3 || elem.nodeType === 4 ) { ret += elem.nodeValue; // Traverse everything else, except comment nodes } else if ( elem.nodeType !== 8 ) { ret += getText( elem.childNodes ); } } return ret; } // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date).getTime(); form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly var root = document.documentElement; root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function(match, context, isXML){ if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function(elem, match){ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); root = form = null; // release memory in IE })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function(match, context){ var results = context.getElementsByTagName(match[1]); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = ""; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function(elem){ return elem.getAttribute("href", 2); }; } div = null; // release memory in IE })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"); div.innerHTML = "

            "; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function(query, context, extra, seed){ context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && context.nodeType === 9 && !isXML(context) ) { try { return makeArray( context.querySelectorAll(query), extra ); } catch(e){} } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } div = null; // release memory in IE })(); } (function(){ var div = document.createElement("div"); div.innerHTML = "
            "; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function(match, context, isXML) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; div = null; // release memory in IE })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { elem = elem[dir]; var match = false; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem.sizcache = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { elem = elem[dir]; var match = false; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem.sizcache = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } var contains = document.compareDocumentPosition ? function(a, b){ return a.compareDocumentPosition(b) & 16; } : function(a, b){ return a !== b && (a.contains ? a.contains(b) : true); }; var isXML = function(elem){ // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function(selector, context){ var tmpSet = [], later = "", match, root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet ); } return Sizzle.filter( later, tmpSet ); }; // EXPOSE jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; jQuery.getText = getText; jQuery.isXMLDoc = isXML; jQuery.contains = contains; return; window.Sizzle = Sizzle; })(); var runtil = /Until$/, rparentsprev = /^(?:parents|prevUntil|prevAll)/, // Note: This RegExp should be improved, or likely pulled from Sizzle rmultiselector = /,/, slice = Array.prototype.slice; // Implement the identical functionality for filter and not var winnow = function( elements, qualifier, keep ) { if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { return !!qualifier.call( elem, i, elem ) === keep; }); } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem, i ) { return (elem === qualifier) === keep; }); } else if ( typeof qualifier === "string" ) { var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { qualifier = jQuery.filter( qualifier, filtered ); } } return jQuery.grep(elements, function( elem, i ) { return (jQuery.inArray( elem, qualifier ) >= 0) === keep; }); }; jQuery.fn.extend({ find: function( selector ) { var ret = this.pushStack( "", "find", selector ), length = 0; for ( var i = 0, l = this.length; i < l; i++ ) { length = ret.length; jQuery.find( selector, this[i], ret ); if ( i > 0 ) { // Make sure that the results are unique for ( var n = length; n < ret.length; n++ ) { for ( var r = 0; r < length; r++ ) { if ( ret[r] === ret[n] ) { ret.splice(n--, 1); break; } } } } } return ret; }, has: function( target ) { var targets = jQuery( target ); return this.filter(function() { for ( var i = 0, l = targets.length; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector, false), "not", selector); }, filter: function( selector ) { return this.pushStack( winnow(this, selector, true), "filter", selector ); }, is: function( selector ) { return !!selector && jQuery.filter( selector, this ).length > 0; }, closest: function( selectors, context ) { if ( jQuery.isArray( selectors ) ) { var ret = [], cur = this[0], match, matches = {}, selector; if ( cur && selectors.length ) { for ( var i = 0, l = selectors.length; i < l; i++ ) { selector = selectors[i]; if ( !matches[selector] ) { matches[selector] = jQuery.expr.match.POS.test( selector ) ? jQuery( selector, context || this.context ) : selector; } } while ( cur && cur.ownerDocument && cur !== context ) { for ( selector in matches ) { match = matches[selector]; if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { ret.push({ selector: selector, elem: cur }); delete matches[selector]; } } cur = cur.parentNode; } } return ret; } var pos = jQuery.expr.match.POS.test( selectors ) ? jQuery( selectors, context || this.context ) : null; return this.map(function( i, cur ) { while ( cur && cur.ownerDocument && cur !== context ) { if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) { return cur; } cur = cur.parentNode; } return null; }); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { if ( !elem || typeof elem === "string" ) { return jQuery.inArray( this[0], // If it receives a string, the selector is used // If it receives nothing, the siblings are used elem ? jQuery( elem ) : this.parent().children() ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context || this.context ) : jQuery.makeArray( selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? all : jQuery.unique( all ) ); }, andSelf: function() { return this.add( this.prevObject ); } }); // A painfully simple check to see if an element is disconnected // from a document (should be improved, where feasible). function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return jQuery.nth( elem, 2, "nextSibling" ); }, prev: function( elem ) { return jQuery.nth( elem, 2, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( elem.parentNode.firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray( elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); if ( !runtil.test( name ) ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } ret = this.length > 1 ? jQuery.unique( ret ) : ret; if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { ret = ret.reverse(); } return this.pushStack( ret, name, slice.call(arguments).join(",") ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } return jQuery.find.matches(expr, elems); }, dir: function( elem, dir, until ) { var matched = [], cur = elem[dir]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, nth: function( cur, result, dir, elem ) { result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) { if ( cur.nodeType === 1 && ++num === result ) { break; } } return cur; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, rtagName = /<([\w:]+)/, rtbody = /"; }, wrapMap = { option: [ 1, "" ], legend: [ 1, "
            ", "
            " ], thead: [ 1, "", "
            " ], tr: [ 2, "", "
            " ], td: [ 3, "", "
            " ], col: [ 2, "", "
            " ], area: [ 1, "", "" ], _default: [ 0, "", "" ] }; wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; // IE can't serialize and jifty-1.10518+dfsg.orig/share/web/static/js/cssQuery-jquery.js0000644000175000017500000000125411564753501021762 0ustar fsfsvar cssQuery = function() { var cssQuery = function(a, c) { return jQuery.makeArray( jQuery(a,c) ); } // All public interfaces are showing alert instead of doing the realthing. // Deep compatibiliy isn't going to be implemented. var msg = "This implementation of cssQuery is really a wrapper to jQuery. No compatibility is ensured. Please use jQuery instead."; var warned = 0; cssQuery.toString = function() { return "function() { [" + msg + "] }"; }; cssQuery.clearCache = cssQuery.addModule = cssQuery.valueOf = function() { if (warned) return; ++warned; alert(msg); }; return cssQuery; }(); jifty-1.10518+dfsg.orig/share/web/static/js/jquery.bgiframe.min.js0000644000175000017500000000257211447473536022516 0ustar fsfs/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net) * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * * $LastChangedDate: 2007-07-22 01:45:56 +0200 (Son, 22 Jul 2007) $ * $Rev: 2447 $ * * Version 2.1.1 */ (function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html=''); this.iefix = $(this.update.id+'_iefix'); } if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); }, fixIEOverlapping: function() { Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); this.iefix.style.zIndex = 1; this.update.style.zIndex = 2; Element.show(this.iefix); }, hide: function() { this.stopIndicator(); if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); if(this.iefix) Element.hide(this.iefix); }, startIndicator: function() { if(this.options.indicator) Element.show(this.options.indicator); }, stopIndicator: function() { if(this.options.indicator) Element.hide(this.options.indicator); }, onKeyPress: function(event) { if(this.active) switch(event.keyCode) { case Event.KEY_TAB: case Event.KEY_RETURN: this.selectEntry(); Event.stop(event); case Event.KEY_ESC: this.hide(); this.active = false; Event.stop(event); return; case Event.KEY_LEFT: case Event.KEY_RIGHT: return; case Event.KEY_UP: this.markPrevious(); this.render(); Event.stop(event); return; case Event.KEY_DOWN: this.markNext(); this.render(); Event.stop(event); return; } else if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; this.changed = true; this.hasFocus = true; if(this.observer) clearTimeout(this.observer); this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); }, activate: function() { this.changed = false; this.hasFocus = true; this.getUpdatedChoices(); }, onHover: function(event) { var element = Event.findElement(event, 'LI'); if(this.index != element.autocompleteIndex) { this.index = element.autocompleteIndex; this.render(); } Event.stop(event); }, onClick: function(event) { var element = Event.findElement(event, 'LI'); this.index = element.autocompleteIndex; this.selectEntry(); this.hide(); }, onBlur: function(event) { // needed to make click events working setTimeout(this.hide.bind(this), 250); this.hasFocus = false; this.active = false; }, render: function() { if(this.entryCount > 0) { for (var i = 0; i < this.entryCount; i++) this.index==i ? Element.addClassName(this.getEntry(i),"selected") : Element.removeClassName(this.getEntry(i),"selected"); if(this.hasFocus) { this.show(); this.active = true; } } else { this.active = false; this.hide(); } }, markPrevious: function() { if(this.index > 0) this.index-- else this.index = this.entryCount-1; this.getEntry(this.index).scrollIntoView(true); }, markNext: function() { if(this.index < this.entryCount-1) this.index++ else this.index = 0; this.getEntry(this.index).scrollIntoView(false); }, getEntry: function(index) { return this.update.firstChild.childNodes[index]; }, getCurrentEntry: function() { return this.getEntry(this.index); }, selectEntry: function() { this.active = false; this.updateElement(this.getCurrentEntry()); }, updateElement: function(selectedElement) { if (this.options.updateElement) { this.options.updateElement(selectedElement); return; } var value = ''; if (this.options.select) { var nodes = $(selectedElement).select('.' + this.options.select) || []; if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); } else value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); var bounds = this.getTokenBounds(); if (bounds[0] != -1) { var newValue = this.element.value.substr(0, bounds[0]); var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); if (whitespace) newValue += whitespace[0]; this.element.value = newValue + value + this.element.value.substr(bounds[1]); } else { this.element.value = value; } this.oldElementValue = this.element.value; this.element.focus(); if (this.options.afterUpdateElement) this.options.afterUpdateElement(this.element, selectedElement); }, updateChoices: function(choices) { if(!this.changed && this.hasFocus) { this.update.innerHTML = choices; Element.cleanWhitespace(this.update); Element.cleanWhitespace(this.update.down()); if(this.update.firstChild && this.update.down().childNodes) { this.entryCount = this.update.down().childNodes.length; for (var i = 0; i < this.entryCount; i++) { var entry = this.getEntry(i); entry.autocompleteIndex = i; this.addObservers(entry); } } else { this.entryCount = 0; } this.stopIndicator(); this.index = 0; if(this.entryCount==1 && this.options.autoSelect) { this.selectEntry(); this.hide(); } else { this.render(); } } }, addObservers: function(element) { Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); Event.observe(element, "click", this.onClick.bindAsEventListener(this)); }, onObserverEvent: function() { this.changed = false; this.tokenBounds = null; if(this.getToken().length>=this.options.minChars) { this.getUpdatedChoices(); } else { this.active = false; this.hide(); } this.oldElementValue = this.element.value; }, getToken: function() { var bounds = this.getTokenBounds(); return this.element.value.substring(bounds[0], bounds[1]).strip(); }, getTokenBounds: function() { if (null != this.tokenBounds) return this.tokenBounds; var value = this.element.value; if (value.strip().empty()) return [-1, 0]; var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); var offset = (diff == this.oldElementValue.length ? 1 : 0); var prevTokenPos = -1, nextTokenPos = value.length; var tp; for (var index = 0, l = this.options.tokens.length; index < l; ++index) { tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); if (tp > prevTokenPos) prevTokenPos = tp; tp = value.indexOf(this.options.tokens[index], diff + offset); if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; } return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); } }); Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { var boundary = Math.min(newS.length, oldS.length); for (var index = 0; index < boundary; ++index) if (newS[index] != oldS[index]) return index; return boundary; }; Ajax.Autocompleter = Class.create(Autocompleter.Base, { initialize: function(element, update, url, options) { this.baseInitialize(element, update, options); this.options.asynchronous = true; this.options.onComplete = this.onComplete.bind(this); this.options.defaultParams = this.options.parameters || null; this.url = url; }, getUpdatedChoices: function() { this.startIndicator(); var entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(this.getToken()); this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry; if(this.options.defaultParams) this.options.parameters += '&' + this.options.defaultParams; new Ajax.Request(this.url, this.options); }, onComplete: function(request) { this.updateChoices(request.responseText); } }); // The local array autocompleter. Used when you'd prefer to // inject an array of autocompletion options into the page, rather // than sending out Ajax queries, which can be quite slow sometimes. // // The constructor takes four parameters. The first two are, as usual, // the id of the monitored textbox, and id of the autocompletion menu. // The third is the array you want to autocomplete from, and the fourth // is the options block. // // Extra local autocompletion options: // - choices - How many autocompletion choices to offer // // - partialSearch - If false, the autocompleter will match entered // text only at the beginning of strings in the // autocomplete array. Defaults to true, which will // match text at the beginning of any *word* in the // strings in the autocomplete array. If you want to // search anywhere in the string, additionally set // the option fullSearch to true (default: off). // // - fullSsearch - Search anywhere in autocomplete array strings. // // - partialChars - How many characters to enter before triggering // a partial match (unlike minChars, which defines // how many characters are required to do any match // at all). Defaults to 2. // // - ignoreCase - Whether to ignore case when autocompleting. // Defaults to true. // // It's possible to pass in a custom function as the 'selector' // option, if you prefer to write your own autocompletion logic. // In that case, the other options above will not apply unless // you support them. Autocompleter.Local = Class.create(Autocompleter.Base, { initialize: function(element, update, array, options) { this.baseInitialize(element, update, options); this.options.array = array; }, getUpdatedChoices: function() { this.updateChoices(this.options.selector(this)); }, setOptions: function(options) { this.options = Object.extend({ choices: 10, partialSearch: true, partialChars: 2, ignoreCase: true, fullSearch: false, selector: function(instance) { var ret = []; // Beginning matches var partial = []; // Inside matches var entry = instance.getToken(); var count = 0; for (var i = 0; i < instance.options.array.length && ret.length < instance.options.choices ; i++) { var elem = instance.options.array[i]; var foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase()) : elem.indexOf(entry); while (foundPos != -1) { if (foundPos == 0 && elem.length != entry.length) { ret.push("
          • " + elem.substr(0, entry.length) + "" + elem.substr(entry.length) + "
          • "); break; } else if (entry.length >= instance.options.partialChars && instance.options.partialSearch && foundPos != -1) { if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { partial.push("
          • " + elem.substr(0, foundPos) + "" + elem.substr(foundPos, entry.length) + "" + elem.substr( foundPos + entry.length) + "
          • "); break; } } foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : elem.indexOf(entry, foundPos + 1); } } if (partial.length) ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) return "
              " + ret.join('') + "
            "; } }, options || { }); } }); // AJAX in-place editor and collection editor // Full rewrite by Christophe Porteneuve (April 2007). // Use this if you notice weird scrolling problems on some browsers, // the DOM might be a bit confused when this gets called so do this // waits 1 ms (with setTimeout) until it does the activation Field.scrollFreeActivate = function(field) { setTimeout(function() { Field.activate(field); }, 1); } Ajax.InPlaceEditor = Class.create({ initialize: function(element, url, options) { this.url = url; this.element = element = $(element); this.prepareOptions(); this._controls = { }; arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! Object.extend(this.options, options || { }); if (!this.options.formId && this.element.id) { this.options.formId = this.element.id + '-inplaceeditor'; if ($(this.options.formId)) this.options.formId = ''; } if (this.options.externalControl) this.options.externalControl = $(this.options.externalControl); if (!this.options.externalControl) this.options.externalControlOnly = false; this._originalBackground = this.element.getStyle('background-color') || 'transparent'; this.element.title = this.options.clickToEditText; this._boundCancelHandler = this.handleFormCancellation.bind(this); this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); this._boundFailureHandler = this.handleAJAXFailure.bind(this); this._boundSubmitHandler = this.handleFormSubmission.bind(this); this._boundWrapperHandler = this.wrapUp.bind(this); this.registerListeners(); }, checkForEscapeOrReturn: function(e) { if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; if (Event.KEY_ESC == e.keyCode) this.handleFormCancellation(e); else if (Event.KEY_RETURN == e.keyCode) this.handleFormSubmission(e); }, createControl: function(mode, handler, extraClasses) { var control = this.options[mode + 'Control']; var text = this.options[mode + 'Text']; if ('button' == control) { var btn = document.createElement('input'); btn.type = 'submit'; btn.value = text; btn.className = 'editor_' + mode + '_button'; if ('cancel' == mode) btn.onclick = this._boundCancelHandler; this._form.appendChild(btn); this._controls[mode] = btn; } else if ('link' == control) { var link = document.createElement('a'); link.href = '#'; link.appendChild(document.createTextNode(text)); link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; link.className = 'editor_' + mode + '_link'; if (extraClasses) link.className += ' ' + extraClasses; this._form.appendChild(link); this._controls[mode] = link; } }, createEditField: function() { var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); var fld; if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { fld = document.createElement('input'); fld.type = 'text'; var size = this.options.size || this.options.cols || 0; if (0 < size) fld.size = size; } else { fld = document.createElement('textarea'); fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); fld.cols = this.options.cols || 40; } fld.name = this.options.paramName; fld.value = text; // No HTML breaks conversion anymore fld.className = 'editor_field'; if (this.options.submitOnBlur) fld.onblur = this._boundSubmitHandler; this._controls.editor = fld; if (this.options.loadTextURL) this.loadExternalText(); this._form.appendChild(this._controls.editor); }, createForm: function() { var ipe = this; function addText(mode, condition) { var text = ipe.options['text' + mode + 'Controls']; if (!text || condition === false) return; ipe._form.appendChild(document.createTextNode(text)); }; this._form = $(document.createElement('form')); this._form.id = this.options.formId; this._form.addClassName(this.options.formClassName); this._form.onsubmit = this._boundSubmitHandler; this.createEditField(); if ('textarea' == this._controls.editor.tagName.toLowerCase()) this._form.appendChild(document.createElement('br')); if (this.options.onFormCustomization) this.options.onFormCustomization(this, this._form); addText('Before', this.options.okControl || this.options.cancelControl); this.createControl('ok', this._boundSubmitHandler); addText('Between', this.options.okControl && this.options.cancelControl); this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); addText('After', this.options.okControl || this.options.cancelControl); }, destroy: function() { if (this._oldInnerHTML) this.element.innerHTML = this._oldInnerHTML; this.leaveEditMode(); this.unregisterListeners(); }, enterEditMode: function(e) { if (this._saving || this._editing) return; this._editing = true; this.triggerCallback('onEnterEditMode'); if (this.options.externalControl) this.options.externalControl.hide(); this.element.hide(); this.createForm(); this.element.parentNode.insertBefore(this._form, this.element); if (!this.options.loadTextURL) this.postProcessEditField(); if (e) Event.stop(e); }, enterHover: function(e) { if (this.options.hoverClassName) this.element.addClassName(this.options.hoverClassName); if (this._saving) return; this.triggerCallback('onEnterHover'); }, getText: function() { return this.element.innerHTML; }, handleAJAXFailure: function(transport) { this.triggerCallback('onFailure', transport); if (this._oldInnerHTML) { this.element.innerHTML = this._oldInnerHTML; this._oldInnerHTML = null; } }, handleFormCancellation: function(e) { this.wrapUp(); if (e) Event.stop(e); }, handleFormSubmission: function(e) { var form = this._form; var value = $F(this._controls.editor); this.prepareSubmission(); var params = this.options.callback(form, value) || ''; if (Object.isString(params)) params = params.toQueryParams(); params.editorId = this.element.id; if (this.options.htmlResponse) { var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); Object.extend(options, { parameters: params, onComplete: this._boundWrapperHandler, onFailure: this._boundFailureHandler }); new Ajax.Updater({ success: this.element }, this.url, options); } else { var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: params, onComplete: this._boundWrapperHandler, onFailure: this._boundFailureHandler }); new Ajax.Request(this.url, options); } if (e) Event.stop(e); }, leaveEditMode: function() { this.element.removeClassName(this.options.savingClassName); this.removeForm(); this.leaveHover(); this.element.style.backgroundColor = this._originalBackground; this.element.show(); if (this.options.externalControl) this.options.externalControl.show(); this._saving = false; this._editing = false; this._oldInnerHTML = null; this.triggerCallback('onLeaveEditMode'); }, leaveHover: function(e) { if (this.options.hoverClassName) this.element.removeClassName(this.options.hoverClassName); if (this._saving) return; this.triggerCallback('onLeaveHover'); }, loadExternalText: function() { this._form.addClassName(this.options.loadingClassName); this._controls.editor.disabled = true; var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { this._form.removeClassName(this.options.loadingClassName); var text = transport.responseText; if (this.options.stripLoadedTextTags) text = text.stripTags(); this._controls.editor.value = text; this._controls.editor.disabled = false; this.postProcessEditField(); }.bind(this), onFailure: this._boundFailureHandler }); new Ajax.Request(this.options.loadTextURL, options); }, postProcessEditField: function() { var fpc = this.options.fieldPostCreation; if (fpc) $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); }, prepareOptions: function() { this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); [this._extraDefaultOptions].flatten().compact().each(function(defs) { Object.extend(this.options, defs); }.bind(this)); }, prepareSubmission: function() { this._saving = true; this.removeForm(); this.leaveHover(); this.showSaving(); }, registerListeners: function() { this._listeners = { }; var listener; $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { listener = this[pair.value].bind(this); this._listeners[pair.key] = listener; if (!this.options.externalControlOnly) this.element.observe(pair.key, listener); if (this.options.externalControl) this.options.externalControl.observe(pair.key, listener); }.bind(this)); }, removeForm: function() { if (!this._form) return; this._form.remove(); this._form = null; this._controls = { }; }, showSaving: function() { this._oldInnerHTML = this.element.innerHTML; this.element.innerHTML = this.options.savingText; this.element.addClassName(this.options.savingClassName); this.element.style.backgroundColor = this._originalBackground; this.element.show(); }, triggerCallback: function(cbName, arg) { if ('function' == typeof this.options[cbName]) { this.options[cbName](this, arg); } }, unregisterListeners: function() { $H(this._listeners).each(function(pair) { if (!this.options.externalControlOnly) this.element.stopObserving(pair.key, pair.value); if (this.options.externalControl) this.options.externalControl.stopObserving(pair.key, pair.value); }.bind(this)); }, wrapUp: function(transport) { this.leaveEditMode(); // Can't use triggerCallback due to backward compatibility: requires // binding + direct element this._boundComplete(transport, this.element); } }); Object.extend(Ajax.InPlaceEditor.prototype, { dispose: Ajax.InPlaceEditor.prototype.destroy }); Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { initialize: function($super, element, url, options) { this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; $super(element, url, options); }, createEditField: function() { var list = document.createElement('select'); list.name = this.options.paramName; list.size = 1; this._controls.editor = list; this._collection = this.options.collection || []; if (this.options.loadCollectionURL) this.loadCollection(); else this.checkForExternalText(); this._form.appendChild(this._controls.editor); }, loadCollection: function() { this._form.addClassName(this.options.loadingClassName); this.showLoadingText(this.options.loadingCollectionText); var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { var js = transport.responseText.strip(); if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check throw 'Server returned an invalid collection representation.'; this._collection = eval(js); this.checkForExternalText(); }.bind(this), onFailure: this.onFailure }); new Ajax.Request(this.options.loadCollectionURL, options); }, showLoadingText: function(text) { this._controls.editor.disabled = true; var tempOption = this._controls.editor.firstChild; if (!tempOption) { tempOption = document.createElement('option'); tempOption.value = ''; this._controls.editor.appendChild(tempOption); tempOption.selected = true; } tempOption.update((text || '').stripScripts().stripTags()); }, checkForExternalText: function() { this._text = this.getText(); if (this.options.loadTextURL) this.loadExternalText(); else this.buildOptionList(); }, loadExternalText: function() { this.showLoadingText(this.options.loadingText); var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { this._text = transport.responseText.strip(); this.buildOptionList(); }.bind(this), onFailure: this.onFailure }); new Ajax.Request(this.options.loadTextURL, options); }, buildOptionList: function() { this._form.removeClassName(this.options.loadingClassName); this._collection = this._collection.map(function(entry) { return 2 === entry.length ? entry : [entry, entry].flatten(); }); var marker = ('value' in this.options) ? this.options.value : this._text; var textFound = this._collection.any(function(entry) { return entry[0] == marker; }.bind(this)); this._controls.editor.update(''); var option; this._collection.each(function(entry, index) { option = document.createElement('option'); option.value = entry[0]; option.selected = textFound ? entry[0] == marker : 0 == index; option.appendChild(document.createTextNode(entry[1])); this._controls.editor.appendChild(option); }.bind(this)); this._controls.editor.disabled = false; Field.scrollFreeActivate(this._controls.editor); } }); //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** //**** This only exists for a while, in order to let **** //**** users adapt to the new API. Read up on the new **** //**** API and convert your code to it ASAP! **** Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { if (!options) return; function fallback(name, expr) { if (name in options || expr === undefined) return; options[name] = expr; }; fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : options.cancelLink == options.cancelButton == false ? false : undefined))); fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : options.okLink == options.okButton == false ? false : undefined))); fallback('highlightColor', options.highlightcolor); fallback('highlightEndColor', options.highlightendcolor); }; Object.extend(Ajax.InPlaceEditor, { DefaultOptions: { ajaxOptions: { }, autoRows: 3, // Use when multi-line w/ rows == 1 cancelControl: 'link', // 'link'|'button'|false cancelText: 'cancel', clickToEditText: 'Click to edit', externalControl: null, // id|elt externalControlOnly: false, fieldPostCreation: 'activate', // 'activate'|'focus'|false formClassName: 'inplaceeditor-form', formId: null, // id|elt highlightColor: '#ffff99', highlightEndColor: '#ffffff', hoverClassName: '', htmlResponse: true, loadingClassName: 'inplaceeditor-loading', loadingText: 'Loading...', okControl: 'button', // 'link'|'button'|false okText: 'ok', paramName: 'value', rows: 1, // If 1 and multi-line, uses autoRows savingClassName: 'inplaceeditor-saving', savingText: 'Saving...', size: 0, stripLoadedTextTags: false, submitOnBlur: false, textAfterControls: '', textBeforeControls: '', textBetweenControls: '' }, DefaultCallbacks: { callback: function(form) { return Form.serialize(form); }, onComplete: function(transport, element) { // For backward compatibility, this one is bound to the IPE, and passes // the element directly. It was too often customized, so we don't break it. new Effect.Highlight(element, { startcolor: this.options.highlightColor, keepBackgroundImage: true }); }, onEnterEditMode: null, onEnterHover: function(ipe) { ipe.element.style.backgroundColor = ipe.options.highlightColor; if (ipe._effect) ipe._effect.cancel(); }, onFailure: function(transport, ipe) { alert('Error communication with the server: ' + transport.responseText.stripTags()); }, onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. onLeaveEditMode: null, onLeaveHover: function(ipe) { ipe._effect = new Effect.Highlight(ipe.element, { startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, restorecolor: ipe._originalBackground, keepBackgroundImage: true }); } }, Listeners: { click: 'enterEditMode', keydown: 'checkForEscapeOrReturn', mouseover: 'enterHover', mouseout: 'leaveHover' } }); Ajax.InPlaceCollectionEditor.DefaultOptions = { loadingCollectionText: 'Loading options...' }; // Delayed observer, like Form.Element.Observer, // but waits for delay after last key input // Ideal for live-search fields Form.Element.DelayedObserver = Class.create({ initialize: function(element, delay, callback) { this.delay = delay || 0.5; this.element = $(element); this.callback = callback; this.timer = null; this.lastValue = $F(this.element); Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); }, delayedListener: function(event) { if(this.lastValue == $F(this.element)) return; if(this.timer) clearTimeout(this.timer); this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); this.lastValue = $F(this.element); }, onTimerEvent: function() { this.timer = null; this.callback(this.element, $F(this.element)); } }); ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculous/builder.jsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculo0000644000175000017500000001124211447473536031537 0ustar fsfs// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ var Builder = { NODEMAP: { AREA: 'map', CAPTION: 'table', COL: 'table', COLGROUP: 'table', LEGEND: 'fieldset', OPTGROUP: 'select', OPTION: 'select', PARAM: 'object', TBODY: 'table', TD: 'table', TFOOT: 'table', TH: 'table', THEAD: 'table', TR: 'table' }, // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, // due to a Firefox bug node: function(elementName) { elementName = elementName.toUpperCase(); // try innerHTML approach var parentTag = this.NODEMAP[elementName] || 'div'; var parentElement = document.createElement(parentTag); try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 parentElement.innerHTML = "<" + elementName + ">"; } catch(e) {} var element = parentElement.firstChild || null; // see if browser added wrapping tags if(element && (element.tagName.toUpperCase() != elementName)) element = element.getElementsByTagName(elementName)[0]; // fallback to createElement approach if(!element) element = document.createElement(elementName); // abort if nothing could be created if(!element) return; // attributes (or text) if(arguments[1]) if(this._isStringOrNumber(arguments[1]) || (arguments[1] instanceof Array) || arguments[1].tagName) { this._children(element, arguments[1]); } else { var attrs = this._attributes(arguments[1]); if(attrs.length) { try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 parentElement.innerHTML = "<" +elementName + " " + attrs + ">"; } catch(e) {} element = parentElement.firstChild || null; // workaround firefox 1.0.X bug if(!element) { element = document.createElement(elementName); for(attr in arguments[1]) element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; } if(element.tagName.toUpperCase() != elementName) element = parentElement.getElementsByTagName(elementName)[0]; } } // text, or array of children if(arguments[2]) this._children(element, arguments[2]); return element; }, _text: function(text) { return document.createTextNode(text); }, ATTR_MAP: { 'className': 'class', 'htmlFor': 'for' }, _attributes: function(attributes) { var attrs = []; for(attribute in attributes) attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); return attrs.join(" "); }, _children: function(element, children) { if(children.tagName) { element.appendChild(children); return; } if(typeof children=='object') { // array can hold nodes and text children.flatten().each( function(e) { if(typeof e=='object') element.appendChild(e) else if(Builder._isStringOrNumber(e)) element.appendChild(Builder._text(e)); }); } else if(Builder._isStringOrNumber(children)) element.appendChild(Builder._text(children)); }, _isStringOrNumber: function(param) { return(typeof param=='string' || typeof param=='number'); }, build: function(html) { var element = this.node('div'); $(element).update(html.strip()); return element.down(); }, dump: function(scope) { if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); tags.each( function(tag){ scope[tag] = function() { return Builder.node.apply(Builder, [tag].concat($A(arguments))); } }); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculous/dragdrop.jsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculo0000644000175000017500000007556511447473536031561 0ustar fsfs// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ if(Object.isUndefined(Effect)) throw("dragdrop.js requires including script.aculo.us' effects.js library"); var Droppables = { drops: [], remove: function(element) { this.drops = this.drops.reject(function(d) { return d.element==$(element) }); }, add: function(element) { element = $(element); var options = Object.extend({ greedy: true, hoverclass: null, tree: false }, arguments[1] || { }); // cache containers if(options.containment) { options._containers = []; var containment = options.containment; if(Object.isArray(containment)) { containment.each( function(c) { options._containers.push($(c)) }); } else { options._containers.push($(containment)); } } if(options.accept) options.accept = [options.accept].flatten(); Element.makePositioned(element); // fix IE options.element = element; this.drops.push(options); }, findDeepestChild: function(drops) { deepest = drops[0]; for (i = 1; i < drops.length; ++i) if (Element.isParent(drops[i].element, deepest.element)) deepest = drops[i]; return deepest; }, isContained: function(element, drop) { var containmentNode; if(drop.tree) { containmentNode = element.treeNode; } else { containmentNode = element.parentNode; } return drop._containers.detect(function(c) { return containmentNode == c }); }, isAffected: function(point, element, drop) { return ( (drop.element!=element) && ((!drop._containers) || this.isContained(element, drop)) && ((!drop.accept) || (Element.classNames(element).detect( function(v) { return drop.accept.include(v) } ) )) && Position.within(drop.element, point[0], point[1]) ); }, deactivate: function(drop) { if(drop.hoverclass) Element.removeClassName(drop.element, drop.hoverclass); this.last_active = null; }, activate: function(drop) { if(drop.hoverclass) Element.addClassName(drop.element, drop.hoverclass); this.last_active = drop; }, show: function(point, element) { if(!this.drops.length) return; var drop, affected = []; this.drops.each( function(drop) { if(Droppables.isAffected(point, element, drop)) affected.push(drop); }); if(affected.length>0) drop = Droppables.findDeepestChild(affected); if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); if (drop) { Position.within(drop.element, point[0], point[1]); if(drop.onHover) drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); if (drop != this.last_active) Droppables.activate(drop); } }, fire: function(event, element) { if(!this.last_active) return; Position.prepare(); if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) if (this.last_active.onDrop) { this.last_active.onDrop(element, this.last_active.element, event); return true; } }, reset: function() { if(this.last_active) this.deactivate(this.last_active); } } var Draggables = { drags: [], observers: [], register: function(draggable) { if(this.drags.length == 0) { this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.updateDrag.bindAsEventListener(this); this.eventKeypress = this.keyPress.bindAsEventListener(this); Event.observe(document, "mouseup", this.eventMouseUp); Event.observe(document, "mousemove", this.eventMouseMove); Event.observe(document, "keypress", this.eventKeypress); } this.drags.push(draggable); }, unregister: function(draggable) { this.drags = this.drags.reject(function(d) { return d==draggable }); if(this.drags.length == 0) { Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); Event.stopObserving(document, "keypress", this.eventKeypress); } }, activate: function(draggable) { if(draggable.options.delay) { this._timeout = setTimeout(function() { Draggables._timeout = null; window.focus(); Draggables.activeDraggable = draggable; }.bind(this), draggable.options.delay); } else { window.focus(); // allows keypress events if window isn't currently focused, fails for Safari this.activeDraggable = draggable; } }, deactivate: function() { this.activeDraggable = null; }, updateDrag: function(event) { if(!this.activeDraggable) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; // Mozilla-based browsers fire successive mousemove events with // the same coordinates, prevent needless redrawing (moz bug?) if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; this._lastPointer = pointer; this.activeDraggable.updateDrag(event, pointer); }, endDrag: function(event) { if(this._timeout) { clearTimeout(this._timeout); this._timeout = null; } if(!this.activeDraggable) return; this._lastPointer = null; this.activeDraggable.endDrag(event); this.activeDraggable = null; }, keyPress: function(event) { if(this.activeDraggable) this.activeDraggable.keyPress(event); }, addObserver: function(observer) { this.observers.push(observer); this._cacheObserverCallbacks(); }, removeObserver: function(element) { // element instead of observer fixes mem leaks this.observers = this.observers.reject( function(o) { return o.element==element }); this._cacheObserverCallbacks(); }, notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' if(this[eventName+'Count'] > 0) this.observers.each( function(o) { if(o[eventName]) o[eventName](eventName, draggable, event); }); if(draggable.options[eventName]) draggable.options[eventName](draggable, event); }, _cacheObserverCallbacks: function() { ['onStart','onEnd','onDrag'].each( function(eventName) { Draggables[eventName+'Count'] = Draggables.observers.select( function(o) { return o[eventName]; } ).length; }); } } /*--------------------------------------------------------------------------*/ var Draggable = Class.create({ initialize: function(element) { var defaults = { handle: false, reverteffect: function(element, top_offset, left_offset) { var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, queue: {scope:'_draggable', position:'end'} }); }, endeffect: function(element) { var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, queue: {scope:'_draggable', position:'end'}, afterFinish: function(){ Draggable._dragging[element] = false } }); }, zindex: 1000, revert: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } delay: 0 }; if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) Object.extend(defaults, { starteffect: function(element) { element._opacity = Element.getOpacity(element); Draggable._dragging[element] = true; new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); } }); var options = Object.extend(defaults, arguments[1] || { }); this.element = $(element); if(options.handle && Object.isString(options.handle)) this.handle = this.element.down('.'+options.handle, 0); if(!this.handle) this.handle = $(options.handle); if(!this.handle) this.handle = this.element; if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { options.scroll = $(options.scroll); this._isScrollChild = Element.childOf(this.element, options.scroll); } Element.makePositioned(this.element); // fix IE this.options = options; this.dragging = false; this.eventMouseDown = this.initDrag.bindAsEventListener(this); Event.observe(this.handle, "mousedown", this.eventMouseDown); Draggables.register(this); }, destroy: function() { Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); Draggables.unregister(this); }, currentDelta: function() { return([ parseInt(Element.getStyle(this.element,'left') || '0'), parseInt(Element.getStyle(this.element,'top') || '0')]); }, initDrag: function(event) { if(!Object.isUndefined(Draggable._dragging[this.element]) && Draggable._dragging[this.element]) return; if(Event.isLeftClick(event)) { // abort on form elements, fixes a Firefox issue var src = Event.element(event); if((tag_name = src.tagName.toUpperCase()) && ( tag_name=='INPUT' || tag_name=='SELECT' || tag_name=='OPTION' || tag_name=='BUTTON' || tag_name=='TEXTAREA')) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; var pos = Position.cumulativeOffset(this.element); this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); Draggables.activate(this); Event.stop(event); } }, startDrag: function(event) { this.dragging = true; if(!this.delta) this.delta = this.currentDelta(); if(this.options.zindex) { this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); this.element.style.zIndex = this.options.zindex; } if(this.options.ghosting) { this._clone = this.element.cloneNode(true); this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); if (!this.element._originallyAbsolute) Position.absolutize(this.element); this.element.parentNode.insertBefore(this._clone, this.element); } if(this.options.scroll) { if (this.options.scroll == window) { var where = this._getWindowScroll(this.options.scroll); this.originalScrollLeft = where.left; this.originalScrollTop = where.top; } else { this.originalScrollLeft = this.options.scroll.scrollLeft; this.originalScrollTop = this.options.scroll.scrollTop; } } Draggables.notify('onStart', this, event); if(this.options.starteffect) this.options.starteffect(this.element); }, updateDrag: function(event, pointer) { if(!this.dragging) this.startDrag(event); if(!this.options.quiet){ Position.prepare(); Droppables.show(pointer, this.element); } Draggables.notify('onDrag', this, event); this.draw(pointer); if(this.options.change) this.options.change(this); if(this.options.scroll) { this.stopScrolling(); var p; if (this.options.scroll == window) { with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } } else { p = Position.page(this.options.scroll); p[0] += this.options.scroll.scrollLeft + Position.deltaX; p[1] += this.options.scroll.scrollTop + Position.deltaY; p.push(p[0]+this.options.scroll.offsetWidth); p.push(p[1]+this.options.scroll.offsetHeight); } var speed = [0,0]; if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); this.startScrolling(speed); } // fix AppleWebKit rendering if(Prototype.Browser.WebKit) window.scrollBy(0,0); Event.stop(event); }, finishDrag: function(event, success) { this.dragging = false; if(this.options.quiet){ Position.prepare(); var pointer = [Event.pointerX(event), Event.pointerY(event)]; Droppables.show(pointer, this.element); } if(this.options.ghosting) { if (!this.element._originallyAbsolute) Position.relativize(this.element); delete this.element._originallyAbsolute; Element.remove(this._clone); this._clone = null; } var dropped = false; if(success) { dropped = Droppables.fire(event, this.element); if (!dropped) dropped = false; } if(dropped && this.options.onDropped) this.options.onDropped(this.element); Draggables.notify('onEnd', this, event); var revert = this.options.revert; if(revert && Object.isFunction(revert)) revert = revert(this.element); var d = this.currentDelta(); if(revert && this.options.reverteffect) { if (dropped == 0 || revert != 'failure') this.options.reverteffect(this.element, d[1]-this.delta[1], d[0]-this.delta[0]); } else { this.delta = d; } if(this.options.zindex) this.element.style.zIndex = this.originalZ; if(this.options.endeffect) this.options.endeffect(this.element); Draggables.deactivate(this); Droppables.reset(); }, keyPress: function(event) { if(event.keyCode!=Event.KEY_ESC) return; this.finishDrag(event, false); Event.stop(event); }, endDrag: function(event) { if(!this.dragging) return; this.stopScrolling(); this.finishDrag(event, true); Event.stop(event); }, draw: function(point) { var pos = Position.cumulativeOffset(this.element); if(this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; } var d = this.currentDelta(); pos[0] -= d[0]; pos[1] -= d[1]; if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; } var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i]) }.bind(this)); if(this.options.snap) { if(Object.isFunction(this.options.snap)) { p = this.options.snap(p[0],p[1],this); } else { if(Object.isArray(this.options.snap)) { p = p.map( function(v, i) { return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)) } else { p = p.map( function(v) { return (v/this.options.snap).round()*this.options.snap }.bind(this)) } }} var style = this.element.style; if((!this.options.constraint) || (this.options.constraint=='horizontal')) style.left = p[0] + "px"; if((!this.options.constraint) || (this.options.constraint=='vertical')) style.top = p[1] + "px"; if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering }, stopScrolling: function() { if(this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; Draggables._lastScrollPointer = null; } }, startScrolling: function(speed) { if(!(speed[0] || speed[1])) return; this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; this.lastScrolled = new Date(); this.scrollInterval = setInterval(this.scroll.bind(this), 10); }, scroll: function() { var current = new Date(); var delta = current - this.lastScrolled; this.lastScrolled = current; if(this.options.scroll == window) { with (this._getWindowScroll(this.options.scroll)) { if (this.scrollSpeed[0] || this.scrollSpeed[1]) { var d = delta / 1000; this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); } } } else { this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; } Position.prepare(); Droppables.show(Draggables._lastPointer, this.element); Draggables.notify('onDrag', this); if (this._isScrollChild) { Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; if (Draggables._lastScrollPointer[0] < 0) Draggables._lastScrollPointer[0] = 0; if (Draggables._lastScrollPointer[1] < 0) Draggables._lastScrollPointer[1] = 0; this.draw(Draggables._lastScrollPointer); } if(this.options.change) this.options.change(this); }, _getWindowScroll: function(w) { var T, L, W, H; with (w.document) { if (w.document.documentElement && documentElement.scrollTop) { T = documentElement.scrollTop; L = documentElement.scrollLeft; } else if (w.document.body) { T = body.scrollTop; L = body.scrollLeft; } if (w.innerWidth) { W = w.innerWidth; H = w.innerHeight; } else if (w.document.documentElement && documentElement.clientWidth) { W = documentElement.clientWidth; H = documentElement.clientHeight; } else { W = body.offsetWidth; H = body.offsetHeight } } return { top: T, left: L, width: W, height: H }; } }); Draggable._dragging = { }; /*--------------------------------------------------------------------------*/ var SortableObserver = Class.create({ initialize: function(element, observer) { this.element = $(element); this.observer = observer; this.lastValue = Sortable.serialize(this.element); }, onStart: function() { this.lastValue = Sortable.serialize(this.element); }, onEnd: function() { Sortable.unmark(); if(this.lastValue != Sortable.serialize(this.element)) this.observer(this.element) } }); var Sortable = { SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, sortables: { }, _findRootElement: function(element) { while (element.tagName.toUpperCase() != "BODY") { if(element.id && Sortable.sortables[element.id]) return element; element = element.parentNode; } }, options: function(element) { element = Sortable._findRootElement($(element)); if(!element) return; return Sortable.sortables[element.id]; }, destroy: function(element){ var s = Sortable.options(element); if(s) { Draggables.removeObserver(s.element); s.droppables.each(function(d){ Droppables.remove(d) }); s.draggables.invoke('destroy'); delete Sortable.sortables[s.element.id]; } }, create: function(element) { element = $(element); var options = Object.extend({ element: element, tag: 'li', // assumes li children, override with tag: 'tagname' dropOnEmpty: false, tree: false, treeTag: 'ul', overlap: 'vertical', // one of 'vertical', 'horizontal' constraint: 'vertical', // one of 'vertical', 'horizontal', false containment: element, // also takes array of elements (or id's); or false handle: false, // or a CSS class only: false, delay: 0, hoverclass: null, ghosting: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, format: this.SERIALIZE_RULE, // these take arrays of elements or ids and can be // used for better initialization performance elements: false, handles: false, onChange: Prototype.emptyFunction, onUpdate: Prototype.emptyFunction }, arguments[1] || { }); // clear any old sortable with same element this.destroy(element); // build options for the draggables var options_for_draggable = { revert: true, quiet: options.quiet, scroll: options.scroll, scrollSpeed: options.scrollSpeed, scrollSensitivity: options.scrollSensitivity, delay: options.delay, ghosting: options.ghosting, constraint: options.constraint, handle: options.handle }; if(options.starteffect) options_for_draggable.starteffect = options.starteffect; if(options.reverteffect) options_for_draggable.reverteffect = options.reverteffect; else if(options.ghosting) options_for_draggable.reverteffect = function(element) { element.style.top = 0; element.style.left = 0; }; if(options.endeffect) options_for_draggable.endeffect = options.endeffect; if(options.zindex) options_for_draggable.zindex = options.zindex; // build options for the droppables var options_for_droppable = { overlap: options.overlap, containment: options.containment, tree: options.tree, hoverclass: options.hoverclass, onHover: Sortable.onHover } var options_for_tree = { onHover: Sortable.onEmptyHover, overlap: options.overlap, containment: options.containment, hoverclass: options.hoverclass } // fix for gecko engine Element.cleanWhitespace(element); options.draggables = []; options.droppables = []; // drop on empty handling if(options.dropOnEmpty || options.tree) { Droppables.add(element, options_for_tree); options.droppables.push(element); } (options.elements || this.findElements(element, options) || []).each( function(e,i) { var handle = options.handles ? $(options.handles[i]) : (options.handle ? $(e).select('.' + options.handle)[0] : e); options.draggables.push( new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); Droppables.add(e, options_for_droppable); if(options.tree) e.treeNode = element; options.droppables.push(e); }); if(options.tree) { (Sortable.findTreeElements(element, options) || []).each( function(e) { Droppables.add(e, options_for_tree); e.treeNode = element; options.droppables.push(e); }); } // keep reference this.sortables[element.id] = options; // for onupdate Draggables.addObserver(new SortableObserver(element, options.onUpdate)); }, // return all suitable-for-sortable elements in a guaranteed order findElements: function(element, options) { return Element.findChildren( element, options.only, options.tree ? true : false, options.tag); }, findTreeElements: function(element, options) { return Element.findChildren( element, options.only, options.tree ? true : false, options.treeTag); }, onHover: function(element, dropon, overlap) { if(Element.isParent(dropon, element)) return; if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { return; } else if(overlap>0.5) { Sortable.mark(dropon, 'before'); if(dropon.previousSibling != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; // fix gecko rendering dropon.parentNode.insertBefore(element, dropon); if(dropon.parentNode!=oldParentNode) Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element); } } else { Sortable.mark(dropon, 'after'); var nextElement = dropon.nextSibling || null; if(nextElement != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; // fix gecko rendering dropon.parentNode.insertBefore(element, nextElement); if(dropon.parentNode!=oldParentNode) Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element); } } }, onEmptyHover: function(element, dropon, overlap) { var oldParentNode = element.parentNode; var droponOptions = Sortable.options(dropon); if(!Element.isParent(dropon, element)) { var index; var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); var child = null; if(children) { var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); for (index = 0; index < children.length; index += 1) { if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { offset -= Element.offsetSize (children[index], droponOptions.overlap); } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { child = index + 1 < children.length ? children[index + 1] : null; break; } else { child = children[index]; break; } } } dropon.insertBefore(element, child); Sortable.options(oldParentNode).onChange(element); droponOptions.onChange(element); } }, unmark: function() { if(Sortable._marker) Sortable._marker.hide(); }, mark: function(dropon, position) { // mark on ghosting only var sortable = Sortable.options(dropon.parentNode); if(sortable && !sortable.ghosting) return; if(!Sortable._marker) { Sortable._marker = ($('dropmarker') || Element.extend(document.createElement('DIV'))). hide().addClassName('dropmarker').setStyle({position:'absolute'}); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); } var offsets = Position.cumulativeOffset(dropon); Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); if(position=='after') if(sortable.overlap == 'horizontal') Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); else Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); Sortable._marker.show(); }, _tree: function(element, options, parent) { var children = Sortable.findElements(element, options) || []; for (var i = 0; i < children.length; ++i) { var match = children[i].id.match(options.format); if (!match) continue; var child = { id: encodeURIComponent(match ? match[1] : null), element: element, parent: parent, children: [], position: parent.children.length, container: $(children[i]).down(options.treeTag) } /* Get the element containing the children and recurse over it */ if (child.container) this._tree(child.container, options, child) parent.children.push (child); } return parent; }, tree: function(element) { element = $(element); var sortableOptions = this.options(element); var options = Object.extend({ tag: sortableOptions.tag, treeTag: sortableOptions.treeTag, only: sortableOptions.only, name: element.id, format: sortableOptions.format }, arguments[1] || { }); var root = { id: null, parent: null, children: [], container: element, position: 0 } return Sortable._tree(element, options, root); }, /* Construct a [i] index for a particular node */ _constructIndex: function(node) { var index = ''; do { if (node.id) index = '[' + node.position + ']' + index; } while ((node = node.parent) != null); return index; }, sequence: function(element) { element = $(element); var options = Object.extend(this.options(element), arguments[1] || { }); return $(this.findElements(element, options) || []).map( function(item) { return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; }); }, setSequence: function(element, new_sequence) { element = $(element); var options = Object.extend(this.options(element), arguments[2] || { }); var nodeMap = { }; this.findElements(element, options).each( function(n) { if (n.id.match(options.format)) nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; n.parentNode.removeChild(n); }); new_sequence.each(function(ident) { var n = nodeMap[ident]; if (n) { n[1].appendChild(n[0]); delete nodeMap[ident]; } }); }, serialize: function(element) { element = $(element); var options = Object.extend(Sortable.options(element), arguments[1] || { }); var name = encodeURIComponent( (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); if (options.tree) { return Sortable.tree(element, arguments[1]).children.map( function (item) { return [name + Sortable._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); }).flatten().join('&'); } else { return Sortable.sequence(element, arguments[1]).map( function(item) { return name + "[]=" + encodeURIComponent(item); }).join('&'); } } } // Returns true if child is contained within element Element.isParent = function(child, element) { if (!child.parentNode || child == element) return false; if (child.parentNode == element) return true; return Element.isParent(child.parentNode, element); } Element.findChildren = function(element, only, recursive, tagName) { if(!element.hasChildNodes()) return null; tagName = tagName.toUpperCase(); if(only) only = [only].flatten(); var elements = []; $A(element.childNodes).each( function(e) { if(e.tagName && e.tagName.toUpperCase()==tagName && (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) elements.push(e); if(recursive) { var grandchildren = Element.findChildren(e, only, recursive, tagName); if(grandchildren) elements.push(grandchildren); } }); return (elements.length>0 ? elements.flatten() : []); } Element.offsetSize = function (element, type) { return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculous/effects.jsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculo0000644000175000017500000011411211447473536031537 0ustar fsfs// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) // Martin Bialasinki // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ // converts rgb() and #xxx to #xxxxxx format, // returns self (or first argument) if not convertable String.prototype.parseColor = function() { var color = '#'; if (this.slice(0,4) == 'rgb(') { var cols = this.slice(4,this.length-1).split(','); var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); } else { if (this.slice(0,1) == '#') { if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); if (this.length==7) color = this.toLowerCase(); } } return (color.length==7 ? color : (arguments[0] || this)); }; /*--------------------------------------------------------------------------*/ Element.collectTextNodes = function(element) { return $A($(element).childNodes).collect( function(node) { return (node.nodeType==3 ? node.nodeValue : (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); }).flatten().join(''); }; Element.collectTextNodesIgnoreClass = function(element, className) { return $A($(element).childNodes).collect( function(node) { return (node.nodeType==3 ? node.nodeValue : ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? Element.collectTextNodesIgnoreClass(node, className) : '')); }).flatten().join(''); }; Element.setContentZoom = function(element, percent) { element = $(element); element.setStyle({fontSize: (percent/100) + 'em'}); if (Prototype.Browser.WebKit) window.scrollBy(0,0); return element; }; Element.getInlineOpacity = function(element){ return $(element).style.opacity || ''; }; Element.forceRerendering = function(element) { try { element = $(element); var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch(e) { } }; /*--------------------------------------------------------------------------*/ var Effect = { _elementDoesNotExistError: { name: 'ElementDoesNotExistError', message: 'The specified DOM element does not exist, but is required for this effect to operate' }, Transitions: { linear: Prototype.K, sinoidal: function(pos) { return (-Math.cos(pos*Math.PI)/2) + 0.5; }, reverse: function(pos) { return 1-pos; }, flicker: function(pos) { var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; return pos > 1 ? 1 : pos; }, wobble: function(pos) { return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; }, pulse: function(pos, pulses) { pulses = pulses || 5; return ( ((pos % (1/pulses)) * pulses).round() == 0 ? ((pos * pulses * 2) - (pos * pulses * 2).floor()) : 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) ); }, spring: function(pos) { return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); }, none: function(pos) { return 0; }, full: function(pos) { return 1; } }, DefaultOptions: { duration: 1.0, // seconds fps: 100, // 100= assume 66fps max. sync: false, // true for combining from: 0.0, to: 1.0, delay: 0.0, queue: 'parallel' }, tagifyText: function(element) { var tagifyStyle = 'position:relative'; if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { if (child.nodeType==3) { child.nodeValue.toArray().each( function(character) { element.insertBefore( new Element('span', {style: tagifyStyle}).update( character == ' ' ? String.fromCharCode(160) : character), child); }); Element.remove(child); } }); }, multiple: function(element, effect) { var elements; if (((typeof element == 'object') || Object.isFunction(element)) && (element.length)) elements = element; else elements = $(element).childNodes; var options = Object.extend({ speed: 0.1, delay: 0.0 }, arguments[2] || { }); var masterDelay = options.delay; $A(elements).each( function(element, index) { new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); }); }, PAIRS: { 'slide': ['SlideDown','SlideUp'], 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade'] }, toggle: function(element, effect) { element = $(element); effect = (effect || 'appear').toLowerCase(); var options = Object.extend({ queue: { position:'end', scope:(element.id || 'global'), limit: 1 } }, arguments[2] || { }); Effect[element.visible() ? Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); } }; Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; /* ------------- core effects ------------- */ Effect.ScopedQueue = Class.create(Enumerable, { initialize: function() { this.effects = []; this.interval = null; }, _each: function(iterator) { this.effects._each(iterator); }, add: function(effect) { var timestamp = new Date().getTime(); var position = Object.isString(effect.options.queue) ? effect.options.queue : effect.options.queue.position; switch(position) { case 'front': // move unstarted effects after this effect this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { e.startOn += effect.finishOn; e.finishOn += effect.finishOn; }); break; case 'with-last': timestamp = this.effects.pluck('startOn').max() || timestamp; break; case 'end': // start effect after last queued effect has finished timestamp = this.effects.pluck('finishOn').max() || timestamp; break; } effect.startOn += timestamp; effect.finishOn += timestamp; if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect); if (!this.interval) this.interval = setInterval(this.loop.bind(this), 15); }, remove: function(effect) { this.effects = this.effects.reject(function(e) { return e==effect }); if (this.effects.length == 0) { clearInterval(this.interval); this.interval = null; } }, loop: function() { var timePos = new Date().getTime(); for(var i=0, len=this.effects.length;i= this.startOn) { if (timePos >= this.finishOn) { this.render(1.0); this.cancel(); this.event('beforeFinish'); if (this.finish) this.finish(); this.event('afterFinish'); return; } var pos = (timePos - this.startOn) / this.totalTime, frame = (pos * this.totalFrames).round(); if (frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, cancel: function() { if (!this.options.sync) Effect.Queues.get(Object.isString(this.options.queue) ? 'global' : this.options.queue.scope).remove(this); this.state = 'finished'; }, event: function(eventName) { if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); if (this.options[eventName]) this.options[eventName](this); }, inspect: function() { var data = $H(); for(property in this) if (!Object.isFunction(this[property])) data.set(property, this[property]); return '#'; } }); Effect.Parallel = Class.create(Effect.Base, { initialize: function(effects) { this.effects = effects || []; this.start(arguments[1]); }, update: function(position) { this.effects.invoke('render', position); }, finish: function(position) { this.effects.each( function(effect) { effect.render(1.0); effect.cancel(); effect.event('beforeFinish'); if (effect.finish) effect.finish(position); effect.event('afterFinish'); }); } }); Effect.Tween = Class.create(Effect.Base, { initialize: function(object, from, to) { object = Object.isString(object) ? $(object) : object; var args = $A(arguments), method = args.last(), options = args.length == 5 ? args[3] : null; this.method = Object.isFunction(method) ? method.bind(object) : Object.isFunction(object[method]) ? object[method].bind(object) : function(value) { object[method] = value }; this.start(Object.extend({ from: from, to: to }, options || { })); }, update: function(position) { this.method(position); } }); Effect.Event = Class.create(Effect.Base, { initialize: function() { this.start(Object.extend({ duration: 0 }, arguments[0] || { })); }, update: Prototype.emptyFunction }); Effect.Opacity = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); // make this work on IE on elements without 'layout' if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, to: 1.0 }, arguments[1] || { }); this.start(options); }, update: function(position) { this.element.setOpacity(position); } }); Effect.Move = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ x: 0, y: 0, mode: 'relative' }, arguments[1] || { }); this.start(options); }, setup: function() { this.element.makePositioned(); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); if (this.options.mode == 'absolute') { this.options.x = this.options.x - this.originalLeft; this.options.y = this.options.y - this.originalTop; } }, update: function(position) { this.element.setStyle({ left: (this.options.x * position + this.originalLeft).round() + 'px', top: (this.options.y * position + this.originalTop).round() + 'px' }); } }); // for backwards compatibility Effect.MoveBy = function(element, toTop, toLeft) { return new Effect.Move(element, Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); }; Effect.Scale = Class.create(Effect.Base, { initialize: function(element, percent) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: 'box', // 'box' or 'contents' or { } with provided values scaleFrom: 100.0, scaleTo: percent }, arguments[2] || { }); this.start(options); }, setup: function() { this.restoreAfterFinish = this.options.restoreAfterFinish || false; this.elementPositioning = this.element.getStyle('position'); this.originalStyle = { }; ['top','left','width','height','fontSize'].each( function(k) { this.originalStyle[k] = this.element.style[k]; }.bind(this)); this.originalTop = this.element.offsetTop; this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; ['em','px','%','pt'].each( function(fontSizeType) { if (fontSize.indexOf(fontSizeType)>0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType; } }.bind(this)); this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; this.dims = null; if (this.options.scaleMode=='box') this.dims = [this.element.offsetHeight, this.element.offsetWidth]; if (/^content/.test(this.options.scaleMode)) this.dims = [this.element.scrollHeight, this.element.scrollWidth]; if (!this.dims) this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth]; }, update: function(position) { var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); if (this.options.scaleContent && this.fontSize) this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); }, finish: function(position) { if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); }, setDimensions: function(height, width) { var d = { }; if (this.options.scaleX) d.width = width.round() + 'px'; if (this.options.scaleY) d.height = height.round() + 'px'; if (this.options.scaleFromCenter) { var topd = (height - this.dims[0])/2; var leftd = (width - this.dims[1])/2; if (this.elementPositioning == 'absolute') { if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; } else { if (this.options.scaleY) d.top = -topd + 'px'; if (this.options.scaleX) d.left = -leftd + 'px'; } } this.element.setStyle(d); } }); Effect.Highlight = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); this.start(options); }, setup: function() { // Prevent executing on elements not in the layout flow if (this.element.getStyle('display')=='none') { this.cancel(); return; } // Disable background image during the effect this.oldStyle = { }; if (!this.options.keepBackgroundImage) { this.oldStyle.backgroundImage = this.element.getStyle('background-image'); this.element.setStyle({backgroundImage: 'none'}); } if (!this.options.endcolor) this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); if (!this.options.restorecolor) this.options.restorecolor = this.element.getStyle('background-color'); // init color calculations this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); }, update: function(position) { this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); }, finish: function() { this.element.setStyle(Object.extend(this.oldStyle, { backgroundColor: this.options.restorecolor })); } }); Effect.ScrollTo = function(element) { var options = arguments[1] || { }, scrollOffsets = document.viewport.getScrollOffsets(), elementOffsets = $(element).cumulativeOffset(), max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); if (options.offset) elementOffsets[1] += options.offset; return new Effect.Tween(null, scrollOffsets.top, elementOffsets[1] > max ? max : elementOffsets[1], options, function(p){ scrollTo(scrollOffsets.left, p.round()) } ); }; /* ------------- combination effects ------------- */ Effect.Fade = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); var options = Object.extend({ from: element.getOpacity() || 1.0, to: 0.0, afterFinishInternal: function(effect) { if (effect.options.to!=0) return; effect.element.hide().setStyle({opacity: oldOpacity}); } }, arguments[1] || { }); return new Effect.Opacity(element,options); }; Effect.Appear = function(element) { element = $(element); var options = Object.extend({ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), to: 1.0, // force Safari to render floated elements properly afterFinishInternal: function(effect) { effect.element.forceRerendering(); }, beforeSetup: function(effect) { effect.element.setOpacity(effect.options.from).show(); }}, arguments[1] || { }); return new Effect.Opacity(element,options); }; Effect.Puff = function(element) { element = $(element); var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position'), top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; return new Effect.Parallel( [ new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], Object.extend({ duration: 1.0, beforeSetupInternal: function(effect) { Position.absolutize(effect.effects[0].element) }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().setStyle(oldStyle); } }, arguments[1] || { }) ); }; Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, afterFinishInternal: function(effect) { effect.element.hide().undoClipping(); } }, arguments[1] || { }) ); }; Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makeClipping().setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { effect.element.undoClipping(); } }, arguments[1] || { })); }; Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, afterFinishInternal: function(effect) { new Effect.Scale(effect.element, 1, { duration: 0.3, scaleFromCenter: true, scaleX: false, scaleContent: false, restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); } }) } }, arguments[1] || { })); }; Effect.DropOut = function(element) { element = $(element); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left'), opacity: element.getInlineOpacity() }; return new Effect.Parallel( [ new Effect.Move(element, {x: 0, y: 100, sync: true }), new Effect.Opacity(element, { sync: true, to: 0.0 }) ], Object.extend( { duration: 0.5, beforeSetup: function(effect) { effect.effects[0].element.makePositioned(); }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); } }, arguments[1] || { })); }; Effect.Shake = function(element) { element = $(element); var options = Object.extend({ distance: 20, duration: 0.5 }, arguments[1] || {}); var distance = parseFloat(options.distance); var split = parseFloat(options.duration) / 10.0; var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { effect.element.undoPositioned().setStyle(oldStyle); }}) }}) }}) }}) }}) }}); }; Effect.SlideDown = function(element) { element = $(element).cleanWhitespace(); // SlideDown need to have the content of the element wrapped in a container element with fixed height! var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: window.opera ? 0 : 1, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().setStyle({height: '0px'}).show(); }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { effect.element.undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } }, arguments[1] || { }) ); }; Effect.SlideUp = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', scaleFrom: 100, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().show(); }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } }, arguments[1] || { }) ); }; // Bug in opera makes the TD containing this element expand for a instance after finish Effect.Squish = function(element) { return new Effect.Scale(element, window.opera ? 1 : 0, { restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makeClipping(); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping(); } }); }; Effect.Grow = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.full }, arguments[1] || { }); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var initialMoveX, initialMoveY; var moveX, moveY; switch (options.direction) { case 'top-left': initialMoveX = initialMoveY = moveX = moveY = 0; break; case 'top-right': initialMoveX = dims.width; initialMoveY = moveY = 0; moveX = -dims.width; break; case 'bottom-left': initialMoveX = moveX = 0; initialMoveY = dims.height; moveY = -dims.height; break; case 'bottom-right': initialMoveX = dims.width; initialMoveY = dims.height; moveX = -dims.width; moveY = -dims.height; break; case 'center': initialMoveX = dims.width / 2; initialMoveY = dims.height / 2; moveX = -dims.width / 2; moveY = -dims.height / 2; break; } return new Effect.Move(element, { x: initialMoveX, y: initialMoveY, duration: 0.01, beforeSetup: function(effect) { effect.element.hide().makeClipping().makePositioned(); }, afterFinishInternal: function(effect) { new Effect.Parallel( [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), new Effect.Scale(effect.element, 100, { scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) ], Object.extend({ beforeSetup: function(effect) { effect.effects[0].element.setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ) } }); }; Effect.Shrink = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.none }, arguments[1] || { }); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var moveX, moveY; switch (options.direction) { case 'top-left': moveX = moveY = 0; break; case 'top-right': moveX = dims.width; moveY = 0; break; case 'bottom-left': moveX = 0; moveY = dims.height; break; case 'bottom-right': moveX = dims.width; moveY = dims.height; break; case 'center': moveX = dims.width / 2; moveY = dims.height / 2; break; } return new Effect.Parallel( [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) ], Object.extend({ beforeStartInternal: function(effect) { effect.effects[0].element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ); }; Effect.Pulsate = function(element) { element = $(element); var options = arguments[1] || { }; var oldOpacity = element.getInlineOpacity(); var transition = options.transition || Effect.Transitions.sinoidal; var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; reverser.bind(transition); return new Effect.Opacity(element, Object.extend(Object.extend({ duration: 2.0, from: 0, afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } }, options), {transition: reverser})); }; Effect.Fold = function(element) { element = $(element); var oldStyle = { top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; element.makeClipping(); return new Effect.Scale(element, 5, Object.extend({ scaleContent: false, scaleX: false, afterFinishInternal: function(effect) { new Effect.Scale(element, 1, { scaleContent: false, scaleY: false, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().setStyle(oldStyle); } }); }}, arguments[1] || { })); }; Effect.Morph = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ style: { } }, arguments[1] || { }); if (!Object.isString(options.style)) this.style = $H(options.style); else { if (options.style.include(':')) this.style = options.style.parseStyle(); else { this.element.addClassName(options.style); this.style = $H(this.element.getStyles()); this.element.removeClassName(options.style); var css = this.element.getStyles(); this.style = this.style.reject(function(style) { return style.value == css[style.key]; }); options.afterFinishInternal = function(effect) { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { effect.element.style[transform.style] = ''; }); } } } this.start(options); }, setup: function(){ function parseColor(color){ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; color = color.parseColor(); return $R(0,2).map(function(i){ return parseInt( color.slice(i*2+1,i*2+3), 16 ) }); } this.transforms = this.style.map(function(pair){ var property = pair[0], value = pair[1], unit = null; if (value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color'; } else if (property == 'opacity') { value = parseFloat(value); if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); } else if (Element.CSS_LENGTH.test(value)) { var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); value = parseFloat(components[1]); unit = (components.length == 3) ? components[2] : null; } var originalValue = this.element.getStyle(property); return { style: property.camelize(), originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit=='color' ? parseColor(value) : value, unit: unit }; }.bind(this)).reject(function(transform){ return ( (transform.originalValue == transform.targetValue) || ( transform.unit != 'color' && (isNaN(transform.originalValue) || isNaN(transform.targetValue)) ) ) }); }, update: function(position) { var style = { }, transform, i = this.transforms.length; while(i--) style[(transform = this.transforms[i]).style] = transform.unit=='color' ? '#'+ (Math.round(transform.originalValue[0]+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + (Math.round(transform.originalValue[1]+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + (Math.round(transform.originalValue[2]+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : (transform.originalValue + (transform.targetValue - transform.originalValue) * position).toFixed(3) + (transform.unit === null ? '' : transform.unit); this.element.setStyle(style, true); } }); Effect.Transform = Class.create({ initialize: function(tracks){ this.tracks = []; this.options = arguments[1] || { }; this.addTracks(tracks); }, addTracks: function(tracks){ tracks.each(function(track){ track = $H(track); var data = track.values().first(); this.tracks.push($H({ ids: track.keys().first(), effect: Effect.Morph, options: { style: data } })); }.bind(this)); return this; }, play: function(){ return new Effect.Parallel( this.tracks.map(function(track){ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); var elements = [$(ids) || $$(ids)].flatten(); return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); }).flatten(), this.options ); } }); Element.CSS_PROPERTIES = $w( 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 'fontSize fontWeight height left letterSpacing lineHeight ' + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 'right textIndent top width wordSpacing zIndex'); Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.__parseStyleElement = document.createElement('div'); String.prototype.parseStyle = function(){ var style, styleRules = $H(); if (Prototype.Browser.WebKit) style = new Element('div',{style:this}).style; else { String.__parseStyleElement.innerHTML = '
            '; style = String.__parseStyleElement.childNodes[0].style; } Element.CSS_PROPERTIES.each(function(property){ if (style[property]) styleRules.set(property, style[property]); }); if (Prototype.Browser.IE && this.include('opacity')) styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); return styleRules; }; if (document.defaultView && document.defaultView.getComputedStyle) { Element.getStyles = function(element) { var css = document.defaultView.getComputedStyle($(element), null); return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { styles[property] = css[property]; return styles; }); }; } else { Element.getStyles = function(element) { element = $(element); var css = element.currentStyle, styles; styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { results[property] = css[property]; return results; }); if (!styles.opacity) styles.opacity = element.getOpacity(); return styles; }; }; Effect.Methods = { morph: function(element, style) { element = $(element); new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); return element; }, visualEffect: function(element, effect, options) { element = $(element) var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); new Effect[klass](element, options); return element; }, highlight: function(element, options) { element = $(element); new Effect.Highlight(element, options); return element; } }; $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ 'pulsate shake puff squish switchOff dropOut').each( function(effect) { Effect.Methods[effect] = function(element, options){ element = $(element); Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); return element; } } ); $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( function(f) { Effect.Methods[f] = Element[f]; } ); Element.addMethods(Effect.Methods); ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculous/unittest.jsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculo0000644000175000017500000004734511447473536031554 0ustar fsfs// script.aculo.us unittest.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) // (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ // experimental, Firefox-only Event.simulateMouse = function(element, eventName) { var options = Object.extend({ pointerX: 0, pointerY: 0, buttons: 0, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false }, arguments[2] || {}); var oEvent = document.createEvent("MouseEvents"); oEvent.initMouseEvent(eventName, true, true, document.defaultView, options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element)); if(this.mark) Element.remove(this.mark); this.mark = document.createElement('div'); this.mark.appendChild(document.createTextNode(" ")); document.body.appendChild(this.mark); this.mark.style.position = 'absolute'; this.mark.style.top = options.pointerY + "px"; this.mark.style.left = options.pointerX + "px"; this.mark.style.width = "5px"; this.mark.style.height = "5px;"; this.mark.style.borderTop = "1px solid red;" this.mark.style.borderLeft = "1px solid red;" if(this.step) alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options)); $(element).dispatchEvent(oEvent); }; // Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2. // You need to downgrade to 1.0.4 for now to get this working // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much Event.simulateKey = function(element, eventName) { var options = Object.extend({ ctrlKey: false, altKey: false, shiftKey: false, metaKey: false, keyCode: 0, charCode: 0 }, arguments[2] || {}); var oEvent = document.createEvent("KeyEvents"); oEvent.initKeyEvent(eventName, true, true, window, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.keyCode, options.charCode ); $(element).dispatchEvent(oEvent); }; Event.simulateKeys = function(element, command) { for(var i=0; i' + 'StatusTestMessage' + '' + ''; this.logsummary = $('logsummary') this.loglines = $('loglines'); }, _toHTML: function(txt) { return txt.escapeHTML().replace(/\n/g,"
            "); }, addLinksToResults: function(){ $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log td.title = "Run only this test" Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;}); }); $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log td.title = "Run all tests" Event.observe(td, 'click', function(){ window.location.search = "";}); }); } } Test.Unit.Runner = Class.create(); Test.Unit.Runner.prototype = { initialize: function(testcases) { this.options = Object.extend({ testLog: 'testlog' }, arguments[1] || {}); this.options.resultsURL = this.parseResultsURLQueryParameter(); this.options.tests = this.parseTestsQueryParameter(); if (this.options.testLog) { this.options.testLog = $(this.options.testLog) || null; } if(this.options.tests) { this.tests = []; for(var i = 0; i < this.options.tests.length; i++) { if(/^test/.test(this.options.tests[i])) { this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"])); } } } else { if (this.options.test) { this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])]; } else { this.tests = []; for(var testcase in testcases) { if(/^test/.test(testcase)) { this.tests.push( new Test.Unit.Testcase( this.options.context ? ' -> ' + this.options.titles[testcase] : testcase, testcases[testcase], testcases["setup"], testcases["teardown"] )); } } } } this.currentTest = 0; this.logger = new Test.Unit.Logger(this.options.testLog); setTimeout(this.runTests.bind(this), 1000); }, parseResultsURLQueryParameter: function() { return window.location.search.parseQuery()["resultsURL"]; }, parseTestsQueryParameter: function(){ if (window.location.search.parseQuery()["tests"]){ return window.location.search.parseQuery()["tests"].split(','); }; }, // Returns: // "ERROR" if there was an error, // "FAILURE" if there was a failure, or // "SUCCESS" if there was neither getResult: function() { var hasFailure = false; for(var i=0;i 0) { return "ERROR"; } if (this.tests[i].failures > 0) { hasFailure = true; } } if (hasFailure) { return "FAILURE"; } else { return "SUCCESS"; } }, postResults: function() { if (this.options.resultsURL) { new Ajax.Request(this.options.resultsURL, { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false }); } }, runTests: function() { var test = this.tests[this.currentTest]; if (!test) { // finished! this.postResults(); this.logger.summary(this.summary()); return; } if(!test.isWaiting) { this.logger.start(test.name); } test.run(); if(test.isWaiting) { this.logger.message("Waiting for " + test.timeToWait + "ms"); setTimeout(this.runTests.bind(this), test.timeToWait || 1000); } else { this.logger.finish(test.status(), test.summary()); this.currentTest++; // tail recursive, hopefully the browser will skip the stackframe this.runTests(); } }, summary: function() { var assertions = 0; var failures = 0; var errors = 0; var messages = []; for(var i=0;i 0) return 'failed'; if (this.errors > 0) return 'error'; return 'passed'; }, assert: function(expression) { var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"'; try { expression ? this.pass() : this.fail(message); } catch(e) { this.error(e); } }, assertEqual: function(expected, actual) { var message = arguments[2] || "assertEqual"; try { (expected == actual) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertInspect: function(expected, actual) { var message = arguments[2] || "assertInspect"; try { (expected == actual.inspect()) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertEnumEqual: function(expected, actual) { var message = arguments[2] || "assertEnumEqual"; try { $A(expected).length == $A(actual).length && expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ? this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + ', actual ' + Test.Unit.inspect(actual)); } catch(e) { this.error(e); } }, assertNotEqual: function(expected, actual) { var message = arguments[2] || "assertNotEqual"; try { (expected != actual) ? this.pass() : this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertIdentical: function(expected, actual) { var message = arguments[2] || "assertIdentical"; try { (expected === actual) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertNotIdentical: function(expected, actual) { var message = arguments[2] || "assertNotIdentical"; try { !(expected === actual) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertNull: function(obj) { var message = arguments[1] || 'assertNull' try { (obj==null) ? this.pass() : this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); } catch(e) { this.error(e); } }, assertMatch: function(expected, actual) { var message = arguments[2] || 'assertMatch'; var regex = new RegExp(expected); try { (regex.exec(actual)) ? this.pass() : this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertHidden: function(element) { var message = arguments[1] || 'assertHidden'; this.assertEqual("none", element.style.display, message); }, assertNotNull: function(object) { var message = arguments[1] || 'assertNotNull'; this.assert(object != null, message); }, assertType: function(expected, actual) { var message = arguments[2] || 'assertType'; try { (actual.constructor == expected) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + (actual.constructor) + '"'); } catch(e) { this.error(e); } }, assertNotOfType: function(expected, actual) { var message = arguments[2] || 'assertNotOfType'; try { (actual.constructor != expected) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + (actual.constructor) + '"'); } catch(e) { this.error(e); } }, assertInstanceOf: function(expected, actual) { var message = arguments[2] || 'assertInstanceOf'; try { (actual instanceof expected) ? this.pass() : this.fail(message + ": object was not an instance of the expected type"); } catch(e) { this.error(e); } }, assertNotInstanceOf: function(expected, actual) { var message = arguments[2] || 'assertNotInstanceOf'; try { !(actual instanceof expected) ? this.pass() : this.fail(message + ": object was an instance of the not expected type"); } catch(e) { this.error(e); } }, assertRespondsTo: function(method, obj) { var message = arguments[2] || 'assertRespondsTo'; try { (obj[method] && typeof obj[method] == 'function') ? this.pass() : this.fail(message + ": object doesn't respond to [" + method + "]"); } catch(e) { this.error(e); } }, assertReturnsTrue: function(method, obj) { var message = arguments[2] || 'assertReturnsTrue'; try { var m = obj[method]; if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)]; m() ? this.pass() : this.fail(message + ": method returned false"); } catch(e) { this.error(e); } }, assertReturnsFalse: function(method, obj) { var message = arguments[2] || 'assertReturnsFalse'; try { var m = obj[method]; if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)]; !m() ? this.pass() : this.fail(message + ": method returned true"); } catch(e) { this.error(e); } }, assertRaise: function(exceptionName, method) { var message = arguments[2] || 'assertRaise'; try { method(); this.fail(message + ": exception expected but none was raised"); } catch(e) { ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e); } }, assertElementsMatch: function() { var expressions = $A(arguments), elements = $A(expressions.shift()); if (elements.length != expressions.length) { this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions'); return false; } elements.zip(expressions).all(function(pair, index) { var element = $(pair.first()), expression = pair.last(); if (element.match(expression)) return true; this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect()); }.bind(this)) && this.pass(); }, assertElementMatches: function(element, expression) { this.assertElementsMatch([element], expression); }, benchmark: function(operation, iterations) { var startAt = new Date(); (iterations || 1).times(operation); var timeTaken = ((new Date())-startAt); this.info((arguments[2] || 'Operation') + ' finished ' + iterations + ' iterations in ' + (timeTaken/1000)+'s' ); return timeTaken; }, _isVisible: function(element) { element = $(element); if(!element.parentNode) return true; this.assertNotNull(element); if(element.style && Element.getStyle(element, 'display') == 'none') return false; return this._isVisible(element.parentNode); }, assertNotVisible: function(element) { this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1])); }, assertVisible: function(element) { this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1])); }, benchmark: function(operation, iterations) { var startAt = new Date(); (iterations || 1).times(operation); var timeTaken = ((new Date())-startAt); this.info((arguments[2] || 'Operation') + ' finished ' + iterations + ' iterations in ' + (timeTaken/1000)+'s' ); return timeTaken; } } Test.Unit.Testcase = Class.create(); Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), { initialize: function(name, test, setup, teardown) { Test.Unit.Assertions.prototype.initialize.bind(this)(); this.name = name; if(typeof test == 'string') { test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,'); test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)'); this.test = function() { eval('with(this){'+test+'}'); } } else { this.test = test || function() {}; } this.setup = setup || function() {}; this.teardown = teardown || function() {}; this.isWaiting = false; this.timeToWait = 1000; }, wait: function(time, nextPart) { this.isWaiting = true; this.test = nextPart; this.timeToWait = time; }, run: function() { try { try { if (!this.isWaiting) this.setup.bind(this)(); this.isWaiting = false; this.test.bind(this)(); } finally { if(!this.isWaiting) { this.teardown.bind(this)(); } } } catch(e) { this.error(e); } } }); // *EXPERIMENTAL* BDD-style testing to please non-technical folk // This draws many ideas from RSpec http://rspec.rubyforge.org/ Test.setupBDDExtensionMethods = function(){ var METHODMAP = { shouldEqual: 'assertEqual', shouldNotEqual: 'assertNotEqual', shouldEqualEnum: 'assertEnumEqual', shouldBeA: 'assertType', shouldNotBeA: 'assertNotOfType', shouldBeAn: 'assertType', shouldNotBeAn: 'assertNotOfType', shouldBeNull: 'assertNull', shouldNotBeNull: 'assertNotNull', shouldBe: 'assertReturnsTrue', shouldNotBe: 'assertReturnsFalse', shouldRespondTo: 'assertRespondsTo' }; var makeAssertion = function(assertion, args, object) { this[assertion].apply(this,(args || []).concat([object])); } Test.BDDMethods = {}; $H(METHODMAP).each(function(pair) { Test.BDDMethods[pair.key] = function() { var args = $A(arguments); var scope = args.shift(); makeAssertion.apply(scope, [pair.value, args, this]); }; }); [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each( function(p){ Object.extend(p, Test.BDDMethods) } ); } Test.context = function(name, spec, log){ Test.setupBDDExtensionMethods(); var compiledSpec = {}; var titles = {}; for(specName in spec) { switch(specName){ case "setup": case "teardown": compiledSpec[specName] = spec[specName]; break; default: var testName = 'test'+specName.gsub(/\s+/,'-').camelize(); var body = spec[specName].toString().split('\n').slice(1); if(/^\{/.test(body[0])) body = body.slice(1); body.pop(); body = body.map(function(statement){ return statement.strip() }); compiledSpec[testName] = body.join('\n'); titles[testName] = specName; } } new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name }); };././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculous/scriptaculous.jsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/Prototypism/web/static/js/prototypism/scriptaculo0000644000175000017500000000513611447473536031544 0ustar fsfs// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // For details, see the script.aculo.us web site: http://script.aculo.us/ var Scriptaculous = { Version: '1.8.1', require: function(libraryName) { // inserting via DOM fails in Safari 2.0, so brute force approach document.write('

            blank.html - Needed for Internet Explorer's hidden iframe

            jifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/SinglePage/web/static/js/singlepage/rsh/rsh.js0000644000175000017500000005706011447473536030374 0ustar fsfs/* Copyright (c) 2007 Brian Dillard and Brad Neuberg: Brian Dillard | Project Lead | bdillard@pathf.com | http://blogs.pathf.com/agileajax/ Brad Neuberg | Original Project Creator | http://codinginparadise.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Modified version. The path of blank.html has been changed to fit Jifty's directory structure and cache mechanism. */ /* dhtmlHistory: An object that provides history, history data, and bookmarking for DHTML and Ajax applications. dependencies: * the historyStorage object included in this file. */ window.dhtmlHistory = { /*Public: User-agent booleans*/ isIE: false, isOpera: false, isSafari: false, isKonquerer: false, isGecko: false, isSupported: false, /*Public: Create the DHTML history infrastructure*/ create: function(options) { /* options - object to store initialization parameters options.debugMode - boolean that causes hidden form fields to be shown for development purposes. options.toJSON - function to override default JSON stringifier options.fromJSON - function to override default JSON parser */ var that = this; /*set user-agent flags*/ var UA = navigator.userAgent.toLowerCase(); var platform = navigator.platform.toLowerCase(); var vendor = navigator.vendor || ""; if (vendor === "KDE") { this.isKonqueror = true; this.isSupported = false; } else if (typeof window.opera !== "undefined") { this.isOpera = true; this.isSupported = true; } else if (typeof document.all !== "undefined") { this.isIE = true; this.isSupported = true; } else if (vendor.indexOf("Apple Computer, Inc.") > -1) { this.isSafari = true; this.isSupported = (platform.indexOf("mac") > -1); } else if (UA.indexOf("gecko") != -1) { this.isGecko = true; this.isSupported = true; } /*Set up the historyStorage object; pass in init parameters*/ window.historyStorage.setup(options); /*Execute browser-specific setup methods*/ if (this.isSafari) { this.createSafari(); } else if (this.isOpera) { this.createOpera(); } /*Get our initial location*/ var initialHash = this.getCurrentLocation(); /*Save it as our current location*/ this.currentLocation = initialHash; /*Now that we have a hash, create IE-specific code*/ if (this.isIE) { this.createIE(initialHash); } /*Add an unload listener for the page; this is needed for FF 1.5+ because this browser caches all dynamic updates to the page, which can break some of our logic related to testing whether this is the first instance a page has loaded or whether it is being pulled from the cache*/ var unloadHandler = function() { that.firstLoad = null; }; this.addEventListener(window,'unload',unloadHandler); /*Determine if this is our first page load; for IE, we do this in this.iframeLoaded(), which is fired on pageload. We do it there because we have no historyStorage at this point, which only exists after the page is finished loading in IE*/ if (this.isIE) { /*The iframe will get loaded on page load, and we want to ignore this fact*/ this.ignoreLocationChange = true; } else { if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) { /*This is our first page load, so ignore the location change and add our special history entry*/ this.ignoreLocationChange = true; this.firstLoad = true; historyStorage.put(this.PAGELOADEDSTRING, true); } else { /*This isn't our first page load, so indicate that we want to pay attention to this location change*/ this.ignoreLocationChange = false; /*For browsers other than IE, fire a history change event; on IE, the event will be thrown automatically when its hidden iframe reloads on page load. Unfortunately, we don't have any listeners yet; indicate that we want to fire an event when a listener is added.*/ this.fireOnNewListener = true; } } /*Other browsers can use a location handler that checks at regular intervals as their primary mechanism; we use it for IE as well to handle an important edge case; see checkLocation() for details*/ var locationHandler = function() { that.checkLocation(); }; setInterval(locationHandler, 100); }, /*Public: Initialize our DHTML history. You must call this after the page is finished loading.*/ initialize: function() { /*IE needs to be explicitly initialized. IE doesn't autofill form data until the page is finished loading, so we have to wait*/ if (this.isIE) { /*If this is the first time this page has loaded*/ if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) { /*For IE, we do this in initialize(); for other browsers, we do it in create()*/ this.fireOnNewListener = false; this.firstLoad = true; historyStorage.put(this.PAGELOADEDSTRING, true); } /*Else if this is a fake onload event*/ else { this.fireOnNewListener = true; this.firstLoad = false; } } }, /*Public: Adds a history change listener. Note that only one listener is supported at this time.*/ addListener: function(listener) { this.listener = listener; /*If the page was just loaded and we should not ignore it, fire an event to our new listener now*/ if (this.fireOnNewListener) { this.fireHistoryEvent(this.currentLocation); this.fireOnNewListener = false; } }, /*Public: Generic utility function for attaching events*/ addEventListener: function(o,e,l) { if (o.addEventListener) { o.addEventListener(e,l,false); } else if (o.attachEvent) { o.attachEvent('on'+e,function() { l(window.event); }); } }, /*Public: Add a history point.*/ add: function(newLocation, historyData) { if (this.isSafari) { /*Remove any leading hash symbols on newLocation*/ newLocation = this.removeHash(newLocation); /*Store the history data into history storage*/ historyStorage.put(newLocation, historyData); /*Save this as our current location*/ this.currentLocation = newLocation; /*Change the browser location*/ window.location.hash = newLocation; /*Save this to the Safari form field*/ this.putSafariState(newLocation); } else { /*Most browsers require that we wait a certain amount of time before changing the location, such as 200 MS; rather than forcing external callers to use window.setTimeout to account for this, we internally handle it by putting requests in a queue.*/ var that = this; var addImpl = function() { /*Indicate that the current wait time is now less*/ if (that.currentWaitTime > 0) { that.currentWaitTime = that.currentWaitTime - that.waitTime; } /*Remove any leading hash symbols on newLocation*/ newLocation = that.removeHash(newLocation); /*IE has a strange bug; if the newLocation is the same as _any_ preexisting id in the document, then the history action gets recorded twice; throw a programmer exception if there is an element with this ID*/ if (document.getElementById(newLocation) && that.debugMode) { var e = "Exception: History locations can not have the same value as _any_ IDs that might be in the document," + " due to a bug in IE; please ask the developer to choose a history location that does not match any HTML" + " IDs in this document. The following ID is already taken and cannot be a location: " + newLocation; throw new Error(e); } /*Store the history data into history storage*/ historyStorage.put(newLocation, historyData); /*Indicate to the browser to ignore this upcomming location change since we're making it programmatically*/ that.ignoreLocationChange = true; /*Indicate to IE that this is an atomic location change block*/ that.ieAtomicLocationChange = true; /*Save this as our current location*/ that.currentLocation = newLocation; /*Change the browser location*/ window.location.hash = newLocation; /*Change the hidden iframe's location if on IE*/ if (that.isIE) { that.iframe.src = "/static/js/singlepage/rsh/blank.html?" + newLocation; } /*End of atomic location change block for IE*/ that.ieAtomicLocationChange = false; }; /*Now queue up this add request*/ window.setTimeout(addImpl, this.currentWaitTime); /*Indicate that the next request will have to wait for awhile*/ this.currentWaitTime = this.currentWaitTime + this.waitTime; } }, /*Public*/ isFirstLoad: function() { return this.firstLoad; }, /*Public*/ getVersion: function() { return "0.6"; }, /*Get browser's current hash location; for Safari, read value from a hidden form field*/ /*Public*/ getCurrentLocation: function() { var r = (this.isSafari ? this.getSafariState() : this.getCurrentHash() ); return r; }, /*Public: Manually parse the current url for a hash; tip of the hat to YUI*/ getCurrentHash: function() { var r = window.location.href; var i = r.indexOf("#"); return (i >= 0 ? r.substr(i+1) : "" ); }, /*- - - - - - - - - - - -*/ /*Private: Constant for our own internal history event called when the page is loaded*/ PAGELOADEDSTRING: "DhtmlHistory_pageLoaded", /*Private: Our history change listener.*/ listener: null, /*Private: MS to wait between add requests - will be reset for certain browsers*/ waitTime: 200, /*Private: MS before an add request can execute*/ currentWaitTime: 0, /*Private: Our current hash location, without the "#" symbol.*/ currentLocation: null, /*Private: Hidden iframe used to IE to detect history changes*/ iframe: null, /*Private: Flags and DOM references used only by Safari*/ safariHistoryStartPoint: null, safariStack: null, safariLength: null, /*Private: Flag used to keep checkLocation() from doing anything when it discovers location changes we've made ourselves programmatically with the add() method. Basically, add() sets this to true. When checkLocation() discovers it's true, it refrains from firing our listener, then resets the flag to false for next cycle. That way, our listener only gets fired on history change events triggered by the user via back/forward buttons and manual hash changes. This flag also helps us set up IE's special iframe-based method of handling history changes.*/ ignoreLocationChange: null, /*Private: A flag that indicates that we should fire a history change event when we are ready, i.e. after we are initialized and we have a history change listener. This is needed due to an edge case in browsers other than IE; if you leave a page entirely then return, we must fire this as a history change event. Unfortunately, we have lost all references to listeners from earlier, because JavaScript clears out.*/ fireOnNewListener: null, /*Private: A variable that indicates whether this is the first time this page has been loaded. If you go to a web page, leave it for another one, and then return, the page's onload listener fires again. We need a way to differentiate between the first page load and subsequent ones. This variable works hand in hand with the pageLoaded variable we store into historyStorage.*/ firstLoad: null, /*Private: A variable to handle an important edge case in IE. In IE, if a user manually types an address into their browser's location bar, we must intercept this by calling checkLocation() at regular intervals. However, if we are programmatically changing the location bar ourselves using the add() method, we need to ignore these changes in checkLocation(). Unfortunately, these changes take several lines of code to complete, so for the duration of those lines of code, we set this variable to true. That signals to checkLocation() to ignore the change-in-progress. Once we're done with our chunk of location-change code in add(), we set this back to false. We'll do the same thing when capturing user-entered address changes in checkLocation itself.*/ ieAtomicLocationChange: null, /*Private: Create IE-specific DOM nodes and overrides*/ createIE: function(initialHash) { /*write out a hidden iframe for IE and set the amount of time to wait between add() requests*/ this.waitTime = 400;/*IE needs longer between history updates*/ var styles = (historyStorage.debugMode ? 'width: 800px;height:80px;border:1px solid black;' : historyStorage.hideStyles ); var iframeID = "rshHistoryFrame"; var iframeHTML = ''; document.write(iframeHTML); this.iframe = document.getElementById(iframeID); }, /*Private: Create Opera-specific DOM nodes and overrides*/ createOpera: function() { this.waitTime = 400;/*Opera needs longer between history updates*/ var imgHTML = ''; document.write(imgHTML); }, /*Private: Create Safari-specific DOM nodes and overrides*/ createSafari: function() { var formID = "rshSafariForm"; var stackID = "rshSafariStack"; var lengthID = "rshSafariLength"; var formStyles = historyStorage.debugMode ? historyStorage.showStyles : historyStorage.hideStyles; var inputStyles = (historyStorage.debugMode ? 'width:800px;height:20px;border:1px solid black;margin:0;padding:0;' : historyStorage.hideStyles ); var safariHTML = '
            ' + '' + '' + '
            '; document.write(safariHTML); this.safariStack = document.getElementById(stackID); this.safariLength = document.getElementById(lengthID); if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) { this.safariHistoryStartPoint = history.length; this.safariLength.value = this.safariHistoryStartPoint; } else { this.safariHistoryStartPoint = this.safariLength.value; } }, /*Private: Safari method to read the history stack from a hidden form field*/ getSafariStack: function() { var r = this.safariStack.value; return historyStorage.fromJSON(r); }, /*Private: Safari method to read from the history stack*/ getSafariState: function() { var stack = this.getSafariStack(); var state = stack[history.length - this.safariHistoryStartPoint - 1]; return state; }, /*Private: Safari method to write the history stack to a hidden form field*/ putSafariState: function(newLocation) { var stack = this.getSafariStack(); stack[history.length - this.safariHistoryStartPoint] = newLocation; this.safariStack.value = historyStorage.toJSON(stack); }, /*Private: Notify the listener of new history changes.*/ fireHistoryEvent: function(newHash) { /*extract the value from our history storage for this hash*/ var historyData = historyStorage.get(newHash); /*call our listener*/ this.listener.call(null, newHash, historyData); }, /*Private: See if the browser has changed location. This is the primary history mechanism for Firefox. For IE, we use this to handle an important edge case: if a user manually types in a new hash value into their IE location bar and press enter, we want to to intercept this and notify any history listener.*/ checkLocation: function() { /*Ignore any location changes that we made ourselves for browsers other than IE*/ if (!this.isIE && this.ignoreLocationChange) { this.ignoreLocationChange = false; return; } /*If we are dealing with IE and we are in the middle of making a location change from an iframe, ignore it*/ if (!this.isIE && this.ieAtomicLocationChange) { return; } /*Get hash location*/ var hash = this.getCurrentLocation(); /*Do nothing if there's been no change*/ if (hash == this.currentLocation) { return; } /*In IE, users manually entering locations into the browser; we do this by comparing the browser's location against the iframe's location; if they differ, we are dealing with a manual event and need to place it inside our history, otherwise we can return*/ this.ieAtomicLocationChange = true; if (this.isIE && this.getIframeHash() != hash) { this.iframe.src = "/static/js/singlepage/rsh/blank.html?" + hash; } else if (this.isIE) { /*the iframe is unchanged*/ return; } /*Save this new location*/ this.currentLocation = hash; this.ieAtomicLocationChange = false; /*Notify listeners of the change*/ this.fireHistoryEvent(hash); }, /*Private: Get the current location of IE's hidden iframe.*/ getIframeHash: function() { var doc = this.iframe.contentWindow.document; var hash = String(doc.location.search); if (hash.length == 1 && hash.charAt(0) == "?") { hash = ""; } else if (hash.length >= 2 && hash.charAt(0) == "?") { hash = hash.substring(1); } return hash; }, /*Private: Remove any leading hash that might be on a location.*/ removeHash: function(hashValue) { var r; if (hashValue === null || hashValue === undefined) { r = null; } else if (hashValue === "") { r = ""; } else if (hashValue.length == 1 && hashValue.charAt(0) == "#") { r = ""; } else if (hashValue.length > 1 && hashValue.charAt(0) == "#") { r = hashValue.substring(1); } else { r = hashValue; } return r; }, /*Private: For IE, tell when the hidden iframe has finished loading.*/ iframeLoaded: function(newLocation) { /*ignore any location changes that we made ourselves*/ if (this.ignoreLocationChange) { this.ignoreLocationChange = false; return; } /*Get the new location*/ var hash = String(newLocation.search); if (hash.length == 1 && hash.charAt(0) == "?") { hash = ""; } else if (hash.length >= 2 && hash.charAt(0) == "?") { hash = hash.substring(1); } /*Keep the browser location bar in sync with the iframe hash*/ window.location.hash = hash; /*Notify listeners of the change*/ this.fireHistoryEvent(hash); } }; /* historyStorage: An object that uses a hidden form to store history state across page loads. The mechanism for doing so relies on the fact that browsers save the text in form data for the life of the browser session, which means the text is still there when the user navigates back to the page. This object can be used independently of the dhtmlHistory object for caching of Ajax session information. dependencies: * json2007.js (included in a separate file) or alternate JSON methods passed in through an options bundle. */ window.historyStorage = { /*Public: Set up our historyStorage object for use by dhtmlHistory or other objects*/ setup: function(options) { /* options - object to store initialization parameters - passed in from dhtmlHistory or directly into historyStorage options.debugMode - boolean that causes hidden form fields to be shown for development purposes. options.toJSON - function to override default JSON stringifier options.fromJSON - function to override default JSON parser */ /*process init parameters*/ if (typeof options !== "undefined") { if (options.debugMode) { this.debugMode = options.debugMode; } if (options.toJSON) { this.toJSON = options.toJSON; } if (options.fromJSON) { this.fromJSON = options.fromJSON; } } /*write a hidden form and textarea into the page; we'll stow our history stack here*/ var formID = "rshStorageForm"; var textareaID = "rshStorageField"; var formStyles = this.debugMode ? historyStorage.showStyles : historyStorage.hideStyles; var textareaStyles = (historyStorage.debugMode ? 'width: 800px;height:80px;border:1px solid black;' : historyStorage.hideStyles ); var textareaHTML = '
            ' + '' + '
            '; document.write(textareaHTML); this.storageField = document.getElementById(textareaID); if (typeof window.opera !== "undefined") { this.storageField.focus();/*Opera needs to focus this element before persisting values in it*/ } }, /*Public*/ put: function(key, value) { this.assertValidKey(key); /*if we already have a value for this, remove the value before adding the new one*/ if (this.hasKey(key)) { this.remove(key); } /*store this new key*/ this.storageHash[key] = value; /*save and serialize the hashtable into the form*/ this.saveHashTable(); }, /*Public*/ get: function(key) { this.assertValidKey(key); /*make sure the hash table has been loaded from the form*/ this.loadHashTable(); var value = this.storageHash[key]; if (value === undefined) { value = null; } return value; }, /*Public*/ remove: function(key) { this.assertValidKey(key); /*make sure the hash table has been loaded from the form*/ this.loadHashTable(); /*delete the value*/ delete this.storageHash[key]; /*serialize and save the hash table into the form*/ this.saveHashTable(); }, /*Public: Clears out all saved data.*/ reset: function() { this.storageField.value = ""; this.storageHash = {}; }, /*Public*/ hasKey: function(key) { this.assertValidKey(key); /*make sure the hash table has been loaded from the form*/ this.loadHashTable(); return (typeof this.storageHash[key] !== "undefined"); }, /*Public*/ isValidKey: function(key) { return (typeof key === "string"); }, /*Public - CSS strings utilized by both objects to hide or show behind-the-scenes DOM elements*/ showStyles: 'border:0;margin:0;padding:0;', hideStyles: 'left:-1000px;top:-1000px;width:1px;height:1px;border:0;position:absolute;', /*Public - debug mode flag*/ debugMode: false, /*- - - - - - - - - - - -*/ /*Private: Our hash of key name/values.*/ storageHash: {}, /*Private: If true, we have loaded our hash table out of the storage form.*/ hashLoaded: false, /*Private: DOM reference to our history field*/ storageField: null, /*Private: Assert that a key is valid; throw an exception if it not.*/ assertValidKey: function(key) { var isValid = this.isValidKey(key); if (!isValid && this.debugMode) { throw new Error("Please provide a valid key for window.historyStorage. Invalid key = " + key + "."); } }, /*Private: Load the hash table up from the form.*/ loadHashTable: function() { if (!this.hashLoaded) { var serializedHashTable = this.storageField.value; if (serializedHashTable !== "" && serializedHashTable !== null) { this.storageHash = this.fromJSON(serializedHashTable); this.hashLoaded = true; } } }, /*Private: Save the hash table into the form.*/ saveHashTable: function() { this.loadHashTable(); var serializedHashTable = this.toJSON(this.storageHash); this.storageField.value = serializedHashTable; }, /*Private: Bridges for our JSON implementations - both rely on 2007 JSON.org library - can be overridden by options bundle*/ toJSON: function(o) { return o.toJSONString(); }, fromJSON: function(s) { return s.parseJSON(); } }; jifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/0000755000175000017500000000000011625457665021662 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/0000755000175000017500000000000011565006011022411 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/0000755000175000017500000000000011565006011024407 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/0000755000175000017500000000000011565006011026032 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/0000755000175000017500000000000011565006014030331 5ustar fsfs././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/toc.htmljifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/toc.0000644000175000017500000000455111447473536031144 0ustar fsfs <% _($n || 'Jifty') %> - <%_('Jifty Developer Documentation Online')%> <%PERL> my @found; File::Find::find( { untaint => 1, wanted => sub { return unless /(\w+)\.(?:pm|pod)$/; my $name = $File::Find::name; $name =~ s/.*lib\b.//; $name =~ s!\.(?:pm|pod)!!i; $name =~ s!\W!::!g; push @found, $name; },follow => ($^O ne 'MSWin32') }, Jifty::Util->app_root ."/lib", ); File::Find::find( { untaint => 1, wanted => sub { return unless $File::Find::name =~ /^(?:.*?)(Jifty.*?\.(?:pm|pod))$/; my $name = $1; $name =~ s/.*lib\b.//; $name =~ s!\.(?:pm|pod)!!i; $name =~ s!\/!::!g; push @found, $name; },follow => ($^O ne 'MSWin32') }, Jifty::Util->jifty_root, ); my $indent = 0; my $prev = ''; foreach my $file (sort @found) { my ($parent, $name) = ($1, $2) if $file =~ /(?:(.*)::)?(\w+)$/; $parent = '' unless defined $parent; if ($file =~ /^$prev\::(.*)/) { my $foo = $1; while ($foo =~ s/(\w+):://) { $indent++; $m->print(('   ' x $indent)); $m->print("$1
            "); } $indent++; } elsif ($prev !~ /^$parent\::/) { $indent = 0 unless length $parent; while ($parent =~ s/(\w+)//) { next if $prev =~ s/\b$1:://; while ($prev =~ s/:://) { $indent--; } $m->print(('   ' x $indent)); $m->print("$1
            "); $indent++; } } elsif ($prev =~ /^$parent\::(.*::)/) { my $foo = $1; while ($foo =~ s/:://) { $indent--; } } $m->print( ( '   ' x $indent ) . '' . $name . '
            ' ."\n" ); $prev = $file; } <%ARGS> $n => '' $method => '' $Target => '&method=content' ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/index.htmljifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/inde0000644000175000017500000000137511447473536031221 0ustar fsfs <%_( $n || 'Jifty') %> - <%_('Online Documentation')%> " name="podcontent"> <a style="display: none" href="#toc"><%_('Table of Contents')%></a> <& content.html, Target => '' &> <h1><a id="toc"><%_('Table of Contents')%></a></h1> <& toc.html, Target => '' &> <%args> $n => undef ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/content.htmljifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/OnlineDocs/web/templates/__jifty/online_docs/cont0000644000175000017500000000335611447473536031246 0ustar fsfs <% _( $n || 'Jifty') %> - <%_('Jifty Pod Online')%> <%PERL> my $jifty_dirname = Jifty::Util->jifty_root."/"; my $app_dirname = Jifty::Util->app_root."/lib/"; $n =~ s/::/\//g; my $app_name = Jifty->app_class(); my @options = ( $app_dirname.$n.".pod", $app_dirname.$n.".pm", $jifty_dirname.$n.".pod", $jifty_dirname.$n.".pm"); my $total_body; foreach my $file (@options) { next unless -r "$file"; local $/; my $fh; open $fh, "$file" or next; $total_body = <$fh>; close $fh; } my $body; my $schema; use Pod::Simple::HTML; my $converter = Pod::Simple::HTML->new(); if($n !~ /^Jifty\//) { if ($total_body =~ /package (.*?)::Schema;(.*)package/ismx) { $schema = $2; } } $converter->output_string( \$body ); $converter->parse_string_document($total_body); $body =~ s{.*?]+>}{}s; $body =~ s{\s*\s*$}{}; $n =~ s{/}{::}g; $m->print("

            $n

            "); $m->print("

            "._('Schema')."

            $schema
            ") if ($schema); $body =~ s{]*)>}{}g; $body =~ s!\n\t
              !
                !; $body =~ s!
              !
            !; $body =~ s!

            !!; $body =~ s!
            print($body); <%ARGS> $Target => '&method=content' $n => 'Jifty' jifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/0000755000175000017500000000000011625457665021121 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/0000755000175000017500000000000011565006006021654 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/static/0000755000175000017500000000000011565006006023143 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/static/js/0000755000175000017500000000000011565006006023557 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/static/js/iefixes/0000755000175000017500000000000011565006014025212 5ustar fsfsjifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/static/js/iefixes/ie7-recalc.js0000644000175000017500000001170411447473536027506 0ustar fsfs // ========================================================================= // ie7-recalc.js // ========================================================================= (function() { /* --------------------------------------------------------------------- This allows refreshing of IE7 style rules. If you modify the DOM you can update IE7 by calling document.recalc(). This should be the LAST module included. --------------------------------------------------------------------- */ if (!IE7.loaded) return; // remove all IE7 classes from an element CLASSES = /\sie7_class\d+/g; IE7.CSS.extend({ // store for elements that have style properties calculated elements: {}, handlers: [], // clear IE7 classes and styles reset: function() { this.removeEventHandlers(); // reset IE7 classes here var elements = this.elements; for (var i in elements) elements[i].runtimeStyle.cssText = ""; this.elements = {}; // reset runtimeStyle here var elements = IE7.Rule.elements; for (var i in elements) { with (elements[i]) className = className.replace(CLASSES, ""); } IE7.Rule.elements = {}; }, reload: function() { this.rules = []; this.getInlineStyles(); this.screen.load(); if (this.print) this.print.load(); this.refresh(); this.trash(); }, addRecalc: function(propertyName, test, handler, replacement) { // call the ancestor method to add a wrapped recalc method this.base(propertyName, test, function(element) { // execute the original recalc method handler(element); // store a reference to this element so we can clear its style later IE7.CSS.elements[element.uniqueID] = element; }, replacement); }, recalc: function() { // clear IE7 styles and classes this.reset(); // execute the ancestor method to perform recalculations this.base(); }, addEventHandler: function(element, type, handler) { element.attachEvent(type, handler); // store the handler so it can be detached later this.handlers.push(arguments); }, removeEventHandlers: function() { var handler; while (handler = this.handlers.pop()) { handler[0].detachEvent(handler[1], handler[2]); } }, getInlineStyles: function() { // load inline styles var styleSheets = document.getElementsByTagName("style"), styleSheet; for (var i = styleSheets.length - 1; (styleSheet = styleSheets[i]); i--) { if (!styleSheet.disabled && !styleSheet.ie7) { var cssText = styleSheet.cssText || styleSheet.innerHTML; this.styles.push(cssText); styleSheet.cssText = cssText; } } }, trash: function() { // trash the old style sheets var styleSheets = document.styleSheets, styleSheet, i; for (i = 0; i < styleSheets.length; i++) { styleSheet = styleSheets[i]; if (!styleSheet.ie7 && !styleSheet.cssText) { styleSheet.cssText = styleSheet.cssText; } } this.base(); }, getText: function(styleSheet) { return styleSheet.cssText || this.base(styleSheet); } }); // remove event handlers (they eat memory) IE7.CSS.addEventHandler(window, "onunload", function() { IE7.CSS.removeEventHandlers(); }); // store all elements with an IE7 class assigned IE7.Rule.elements = {}; IE7.Rule.prototype.extend({ add: function(element) { // execute the ancestor "add" method this.base(element); // store a reference to this element so we can clear its classes later IE7.Rule.elements[element.uniqueID] = element; } }); // store created pseudo elements if (IE7.PseudoElement) { IE7.PseudoElement.hash = {}; IE7.PseudoElement.prototype.extend({ create: function(target) { var key = this.selector + ":" + target.uniqueID; if (!IE7.PseudoElement.hash[key]) { IE7.PseudoElement.hash[key] = true; this.base(target); } } }); } IE7.HTML.extend({ elements: {}, addRecalc: function(selector, handler) { // call the ancestor method to add a wrapped recalc method this.base(selector, function(element) { if (!this.elements[element.uniqueID]) { // execute the original recalc method handler(element); // store a reference to this element so that // it is not "fixed" again this.elements[element.uniqueID] = element; } }); } }); // allow refreshing of IE7 fixes document.recalc = function(reload) { if (IE7.CSS.screen) { if (reload) IE7.CSS.reload(); IE7.recalc(); } }; })(); jifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/static/js/iefixes/ie7-squish.js0000644000175000017500000000256711447473536027600 0ustar fsfs /* --------------------------------------------------------------------- Squish some IE bugs! Some of these bug fixes may have adverse effects so they are not included in the standard library. Add your own if you want. --------------------------------------------------------------------- */ // @NOTE: ie7Layout.boxSizing is the same as the "Holly Hack" if (IE7.loaded && IE7.appVersion < 7) { // "doubled margin" bug // http://www.positioniseverything.net/explorer/doubled-margin.html IE7.CSS.addFix(/(float\s*:\s*(left|right))/, "display:inline;$1"); // "peekaboo" bug // http://www.positioniseverything.net/explorer/peekaboo.html if (IE7.appVersion >= 6) IE7.CSS.addRecalc("float", "(left|right)", function(element) { IE7.Layout.boxSizing(element.parentElement); // assing "hasLayout" to parent element // "doubled margin" bug element.style.display = "inline"; }); // "unscrollable content" bug // http://www.positioniseverything.net/explorer/unscrollable.html IE7.CSS.addRecalc("position", "absolute|fixed", function(element) { if (element.offsetParent && element.offsetParent.currentStyle.position == "relative") IE7.Layout.boxSizing(element.offsetParent); // assing "hasLayout" }); } //# // get rid of Microsoft's pesky image toolbar //# document.write(''); jifty-1.10518+dfsg.orig/share/plugins/Jifty/Plugin/IEFixes/web/static/js/iefixes/IE8.js0000644000175000017500000026473511447473536026176 0ustar fsfs// timestamp: Sun, 03 Feb 2008 19:26:22 /* IE7/IE8.js - copyright 2004-2008, Dean Edwards http://dean.edwards.name/IE7/ http://www.opensource.org/licenses/mit-license.php */ /* W3C compliance for Microsoft Internet Explorer */ /* credits/thanks: Shaggy, Martijn Wargers, Jimmy Cerra, Mark D Anderson, Lars Dieckow, Erik Arvidsson, Gellért Gyuris, James Denny, Unknown W Brackets, Benjamin Westfarer, Rob Eberhardt, Bill Edney, Kevin Newman, James Crompton, Matthew Mastracci, Doug Wright, Richard York, Kenneth Kolano, MegaZone, Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Åhlfors, David Zulaica, Ken Kolano, Kevin Newman */ // ======================================================================= // TO DO // ======================================================================= // PNG - unclickable content // ======================================================================= // TEST/BUGGY // ======================================================================= // hr{margin:1em auto} (doesn't look right in IE5) (function() { IE7 = { toString: function(){return "IE7 version 2.0 (beta2)"} }; var appVersion = IE7.appVersion = navigator.appVersion.match(/MSIE (\d\.\d)/)[1]; if (/ie7_off/.test(top.location.search) || appVersion < 5) return; var Undefined = K(); var quirksMode = document.compatMode != "CSS1Compat"; var documentElement = document.documentElement, body, viewport; var ANON = "!"; var HEADER = ":link{ie7-link:link}:visited{ie7-link:visited}"; // ----------------------------------------------------------------------- // external // ----------------------------------------------------------------------- var RELATIVE = /^[\w\.]+[^:]*$/; function makePath(href, path) { if (RELATIVE.test(href)) href = (path || "") + href; return href; }; function getPath(href, path) { href = makePath(href, path); return href.slice(0, href.lastIndexOf("/") + 1); }; // get the path to this script var script = document.scripts[document.scripts.length - 1]; var path = getPath(script.src); // we'll use microsoft's http request object to load external files try { var httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { // ActiveX disabled } var fileCache = {}; function loadFile(href, path) { try { href = makePath(href, path); if (!fileCache[href]) { // easy to load a file huh? httpRequest.open("GET", href, false); httpRequest.send(); if (httpRequest.status == 0 || httpRequest.status == 200) { fileCache[href] = httpRequest.responseText; } } } catch (e) { // ignore errors } finally { return fileCache[href] || ""; }}; // ----------------------------------------------------------------------- // IE5.0 compatibility // ----------------------------------------------------------------------- if (appVersion < 5.5) { undefined = Undefined(); ANON = "HTML:!"; // for anonymous content // Fix String.replace (Safari1.x/IE5.0). var GLOBAL = /(g|gi)$/; var _String_replace = String.prototype.replace; String.prototype.replace = function(expression, replacement) { if (typeof replacement == "function") { // Safari doesn't like functions if (expression && expression.constructor == RegExp) { var regexp = expression; var global = regexp.global; if (global == null) global = GLOBAL.test(regexp); // we have to convert global RexpExps for exec() to work consistently if (global) regexp = new RegExp(regexp.source); // non-global } else { regexp = new RegExp(rescape(expression)); } var match, string = this, result = ""; while (string && (match = regexp.exec(string))) { result += string.slice(0, match.index) + replacement.apply(this, match); string = string.slice(match.index + match[0].length); if (!global) break; } return result + string; } return _String_replace.apply(this, arguments); }; Array.prototype.pop = function() { if (this.length) { var i = this[this.length - 1]; this.length--; return i; } return undefined; }; Array.prototype.push = function() { for (var i = 0; i < arguments.length; i++) { this[this.length] = arguments[i]; } return this.length; }; var ns = this; Function.prototype.apply = function(o, a) { if (o === undefined) o = ns; else if (o == null) o = window; else if (typeof o == "string") o = new String(o); else if (typeof o == "number") o = new Number(o); else if (typeof o == "boolean") o = new Boolean(o); if (arguments.length == 1) a = []; else if (a[0] && a[0].writeln) a[0] = a[0].documentElement.document || a[0]; var $ = "#ie7_apply", r; o[$] = this; switch (a.length) { // unroll for speed case 0: r = o[$](); break; case 1: r = o[$](a[0]); break; case 2: r = o[$](a[0],a[1]); break; case 3: r = o[$](a[0],a[1],a[2]); break; case 4: r = o[$](a[0],a[1],a[2],a[3]); break; case 5: r = o[$](a[0],a[1],a[2],a[3],a[4]); break; default: var b = [], i = a.length - 1; do b[i] = "a[" + i + "]"; while (i--); eval("r=o[$](" + b + ")"); } if (typeof o.valueOf == "function") { // not a COM object delete o[$]; } else { o[$] = undefined; if (r && r.writeln) r = r.documentElement.document || r; } return r; }; Function.prototype.call = function(o) { return this.apply(o, _slice.apply(arguments, [1])); }; // block elements are "inline" according to IE5.0 so we'll fix it HEADER += "address,blockquote,body,dd,div,dt,fieldset,form,"+ "frame,frameset,h1,h2,h3,h4,h5,h6,iframe,noframes,object,p,"+ "hr,applet,center,dir,menu,pre,dl,li,ol,ul{display:block}"; } // ----------------------------------------------------------------------- // OO support // ----------------------------------------------------------------------- // This is a cut-down version of base2 (http://code.google.com/p/base2/) var _slice = Array.prototype.slice; // private var _FORMAT = /%([1-9])/g; var _LTRIM = /^\s\s*/; var _RTRIM = /\s\s*$/; var _RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g; // safe regular expressions var _BASE = /\bbase\b/; var _HIDDEN = ["constructor", "toString"]; // only override these when prototyping var prototyping; function Base(){}; Base.extend = function(_instance, _static) { // Build the prototype. prototyping = true; var _prototype = new this; extend(_prototype, _instance); prototyping = false; // Create the wrapper for the constructor function. var _constructor = _prototype.constructor; function klass() { // Don't call the constructor function when prototyping. if (!prototyping) _constructor.apply(this, arguments); }; _prototype.constructor = klass; // Build the static interface. klass.extend = arguments.callee; extend(klass, _static); klass.prototype = _prototype; return klass; }; Base.prototype.extend = function(source) { return extend(this, source); }; // A collection of regular expressions and their associated replacement values. // A Base class for creating parsers. var _HASH = "#"; var _KEYS = "~"; var _RG_ESCAPE_CHARS = /\\./g; var _RG_ESCAPE_BRACKETS = /\(\?[:=!]|\[[^\]]+\]/g; var _RG_BRACKETS = /\(/g; var RegGrp = Base.extend({ constructor: function(values) { this[_KEYS] = []; this.merge(values); }, exec: function(string) { var items = this, keys = this[_KEYS]; return String(string).replace(new RegExp(this, this.ignoreCase ? "gi" : "g"), function() { var item, offset = 1, i = 0; // Loop through the RegGrp items. while ((item = items[_HASH + keys[i++]])) { var next = offset + item.length + 1; if (arguments[offset]) { // do we have a result? var replacement = item.replacement; switch (typeof replacement) { case "function": return replacement.apply(items, _slice.call(arguments, offset, next)); case "number": return arguments[offset + replacement]; default: return replacement; } } offset = next; } }); }, add: function(expression, replacement) { if (expression instanceof RegExp) { expression = expression.source; } if (!this[_HASH + expression]) this[_KEYS].push(String(expression)); this[_HASH + expression] = new RegGrp.Item(expression, replacement); }, merge: function(values) { for (var i in values) this.add(i, values[i]); }, toString: function() { // back references not supported in simple RegGrp return "(" + this[_KEYS].join(")|(") + ")"; } }, { IGNORE: "$0", Item: Base.extend({ constructor: function(expression, replacement) { expression = expression instanceof RegExp ? expression.source : String(expression); if (typeof replacement == "number") replacement = String(replacement); else if (replacement == null) replacement = ""; // does the pattern use sub-expressions? if (typeof replacement == "string" && /\$(\d+)/.test(replacement)) { // a simple lookup? (e.g. "$2") if (/^\$\d+$/.test(replacement)) { // store the index (used for fast retrieval of matched strings) replacement = parseInt(replacement.slice(1)); } else { // a complicated lookup (e.g. "Hello $2 $1") // build a function to do the lookup var Q = /'/.test(replacement.replace(/\\./g, "")) ? '"' : "'"; replacement = replacement.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\$(\d+)/g, Q + "+(arguments[$1]||" + Q+Q + ")+" + Q); replacement = new Function("return " + Q + replacement.replace(/(['"])\1\+(.*)\+\1\1$/, "$1") + Q); } } this.length = RegGrp.count(expression); this.replacement = replacement; this.toString = K(expression); } }), count: function(expression) { // Count the number of sub-expressions in a RegExp/RegGrp.Item. expression = String(expression).replace(_RG_ESCAPE_CHARS, "").replace(_RG_ESCAPE_BRACKETS, ""); return match(expression, _RG_BRACKETS).length; } }); // ========================================================================= // lang/extend.js // ========================================================================= function extend(object, source) { // or extend(object, key, value) if (object && source) { var proto = (typeof source == "function" ? Function : Object).prototype; // Add constructor, toString etc var i = _HIDDEN.length, key; if (prototyping) while (key = _HIDDEN[--i]) { var value = source[key]; if (value != proto[key]) { if (_BASE.test(value)) { _override(object, key, value) } else { object[key] = value; } } } // Copy each of the source object's properties to the target object. for (key in source) if (proto[key] === undefined) { var value = source[key]; // Check for method overriding. if (object[key] && typeof value == "function" && _BASE.test(value)) { _override(object, key, value); } else { object[key] = value; } } } return object; }; function _override(object, name, method) { // Override an existing method. var ancestor = object[name]; object[name] = function() { var previous = this.base; this.base = ancestor; var returnValue = method.apply(this, arguments); this.base = previous; return returnValue; }; }; function combine(keys, values) { // Combine two arrays to make a hash. if (!values) values = keys; var hash = {}; for (var i in keys) hash[i] = values[i]; return hash; }; function format(string) { // Replace %n with arguments[n]. // e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls"); // ==> "she sells sea shells" // Only %1 - %9 supported. var args = arguments; var _FORMAT = new RegExp("%([1-" + arguments.length + "])", "g"); return String(string).replace(_FORMAT, function(match, index) { return index < args.length ? args[index] : match; }); }; function match(string, expression) { // Same as String.match() except that this function will return an empty // array if there is no match. return String(string).match(expression) || []; }; function rescape(string) { // Make a string safe for creating a RegExp. return String(string).replace(_RESCAPE, "\\$1"); }; // http://blog.stevenlevithan.com/archives/faster-trim-javascript function trim(string) { return String(string).replace(_LTRIM, "").replace(_RTRIM, ""); }; function K(k) { return function() { return k; }; }; // ----------------------------------------------------------------------- // parsing // ----------------------------------------------------------------------- var Parser = RegGrp.extend({ignoreCase: true}); var ENCODED = /\x01(\d+)/g, QUOTES = /'/g, STRING = /^\x01/, UNICODE = /\\([\da-fA-F]{1,4})/g; var _strings = []; var encoder = new Parser({ // comments "": "", "\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/": "", // get rid "@(namespace|import)[^;\\n]+[;\\n]": "", // strings "'(\\\\.|[^'\\\\])*'": encodeString, '"(\\\\.|[^"\\\\])*"': encodeString, // white space "\\s+": " " }); function encode(cssText) { return encoder.exec(cssText); }; function decode(cssText) { return cssText.replace(ENCODED, function(match, index) { return _strings[index - 1]; }); }; function encodeString(string) { return "\x01" + _strings.push(string.replace(UNICODE, function(match, chr) { return eval("'\\u" + "0000".slice(chr.length) + chr + "'"); }).slice(1, -1).replace(QUOTES, "\\'")); }; function getString(value) { return STRING.test(value) ? _strings[value.slice(1) - 1] : value; }; // clone a "width" function to create a "height" function var rotater = new RegGrp({ Width: "Height", width: "height", Left: "Top", left: "top", Right: "Bottom", right: "bottom", onX: "onY" }); function rotate(fn) { return rotater.exec(fn); }; // ----------------------------------------------------------------------- // event handling // ----------------------------------------------------------------------- var eventHandlers = []; function addResize(handler) { addRecalc(handler); addEventHandler(window, "onresize", handler); }; // add an event handler (function) to an element function addEventHandler(element, type, handler) { element.attachEvent(type, handler); // store the handler so it can be detached later eventHandlers.push(arguments); }; // remove an event handler assigned to an element by IE7 function removeEventHandler(element, type, handler) { try { element.detachEvent(type, handler); } catch (ignore) { // write a letter of complaint to microsoft.. }}; // remove event handlers (they eat memory) addEventHandler(window, "onunload", function() { var handler; while (handler = eventHandlers.pop()) { removeEventHandler(handler[0], handler[1], handler[2]); } }); function register(handler, element, condition) { // -@DRE //var set = handler[element.uniqueID]; if (!handler.elements) handler.elements = {}; if (condition) handler.elements[element.uniqueID] = element; else delete handler.elements[element.uniqueID]; //return !set && condition; return condition; }; addEventHandler(window, "onbeforeprint", function() { if (!IE7.CSS.print) new StyleSheet("print"); IE7.CSS.print.recalc(); }); // ----------------------------------------------------------------------- // pixel conversion // ----------------------------------------------------------------------- // this is handy because it means that web developers can mix and match // measurement units in their style sheets. it is not uncommon to // express something like padding in "em" units whilst border thickness // is most often expressed in pixels. var PIXEL = /^\d+(px)?$/i; var PERCENT = /^\d+%$/; var getPixelValue = function(element, value) { if (PIXEL.test(value)) return parseInt(value); var style = element.style.left; var runtimeStyle = element.runtimeStyle.left; element.runtimeStyle.left = element.currentStyle.left; element.style.left = value || 0; value = element.style.pixelLeft; element.style.left = style; element.runtimeStyle.left = runtimeStyle; return value; }; // ----------------------------------------------------------------------- // generic // ----------------------------------------------------------------------- var $IE7 = "ie7-"; var Fix = Base.extend({ constructor: function() { this.fixes = []; this.recalcs = []; }, init: Undefined }); // a store for functions that will be called when refreshing IE7 var recalcs = []; function addRecalc(recalc) { recalcs.push(recalc); }; IE7.recalc = function() { IE7.HTML.recalc(); // re-apply style sheet rules (re-calculate ie7 classes) IE7.CSS.recalc(); // apply global fixes to the document for (var i = 0; i < recalcs.length; i++) recalcs[i](); }; function isFixed(element) { return element.currentStyle["ie7-position"] == "fixed"; }; // original style function getDefinedStyle(element, propertyName) { return element.currentStyle[$IE7 + propertyName] || element.currentStyle[propertyName]; }; function setOverrideStyle(element, propertyName, value) { if (element.currentStyle[$IE7 + propertyName] == null) { element.runtimeStyle[$IE7 + propertyName] = element.currentStyle[propertyName]; } element.runtimeStyle[propertyName] = value; }; // create a temporary element which is used to inherit styles // from the target element. the temporary element can be resized // to determine pixel widths/heights function createTempElement(tagName) { var element = document.createElement(tagName || "object"); element.style.cssText = "position:absolute;padding:0;display:block;border:none;clip:rect(0 0 0 0);left:-9999"; element.ie7_anon = true; return element; }; // ========================================================================= // ie7-cssQuery.js // ========================================================================= function cssQuery(selector, context, single) { if (!_cache[selector]) { reg = []; // store for RegExp objects var fn = ""; var selectors = cssParser.escape(selector).split(","); for (var i = 0; i < selectors.length; i++) { _wild = _index = _list = 0; // reset _duplicate = selectors.length > 1 ? 2 : 0; // reset var block = cssParser.exec(selectors[i]) || "if(0){"; if (_wild) { // IE's pesky comment nodes block += format("if(e%1.nodeName!='!'){", _index); } // check for duplicates before storing results var store = _duplicate > 1 ? _TEST : ""; block += format(store + _STORE, _index); // add closing braces block += Array(match(block, /\{/g).length + 1).join("}"); fn += block; } eval(format(_FN, reg) + cssParser.unescape(fn) + "return s?null:r}"); _cache[selector] = _selectorFunction; } return _cache[selector](context || document, single); }; var _MSIE5 = appVersion < 6; var _EVALUATED = /^(href|src)$/; var _ATTRIBUTES = { "class": "className", "for": "htmlFor" }; IE7._indexed = 1; IE7._byId = function(document, id) { var result = document.all[id] || null; // returns a single element or a collection if (!result || result.id == id) return result; // document.all has returned a collection of elements with name/id for (var i = 0; i < result.length; i++) { if (result[i].id == id) return result[i]; } return null; }; IE7._getAttribute = function(element, name) { if (name == "src" && element.pngSrc) return element.pngSrc; var attribute = _MSIE5 ? (element.attributes[name] || element.attributes[_ATTRIBUTES[name.toLowerCase()]]) : element.getAttributeNode(name); if (attribute && (attribute.specified || name == "value")) { if (_EVALUATED.test(name)) { return element.getAttribute(name, 2); } else if (name == "class") { return element.className.replace(/\sie7_\w+/g, ""); } else if (name == "style") { return element.style.cssText; } else { return attribute.nodeValue; } } return null; }; var names = "colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc"; // Convert the list of strings to a hash, mapping the lowercase name to the camelCase name. extend(_ATTRIBUTES, combine(names.toLowerCase().split(","), names.split(","))); IE7._getNextElementSibling = function(node) { // return the next element to the supplied element // nextSibling is not good enough as it might return a text or comment node while (node && (node = node.nextSibling) && (node.nodeType != 1 || node.nodeName == "!")) continue; return node; }; IE7._getPreviousElementSibling = function(node) { // return the previous element to the supplied element while (node && (node = node.previousSibling) && (node.nodeType != 1 || node.nodeName == "!")) continue; return node; }; // ========================================================================= // CSSParser // ========================================================================= var IMPLIED_ASTERISK = /([\s>+~,]|[^(]\+|^)([#.:\[])/g, IMPLIED_SPACE = /(^|,)([^\s>+~])/g, WHITESPACE = /\s*([\s>+~(),]|^|$)\s*/g, WILD_CARD = /\s\*\s/g;; var CSSParser = RegGrp.extend({ constructor: function(items) { this.base(items); this.sorter = new RegGrp; this.sorter.add(/:not\([^)]*\)/, RegGrp.IGNORE); this.sorter.add(/([ >](\*|[\w-]+))([^: >+~]*)(:\w+-child(\([^)]+\))?)([^: >+~]*)/, "$1$3$6$4"); }, ignoreCase: true, escape: function(selector) { return this.optimise(this.format(selector)); }, format: function(selector) { return selector .replace(WHITESPACE, "$1") .replace(IMPLIED_SPACE, "$1 $2") .replace(IMPLIED_ASTERISK, "$1*$2"); }, optimise: function(selector) { // optimise wild card descendant selectors return this.sorter.exec(selector.replace(WILD_CARD, ">* ")); }, unescape: function(selector) { return decode(selector); } }); // some constants var _OPERATORS = { "": "%1!=null", "=": "%1=='%2'", "~=": /(^| )%1( |$)/, "|=": /^%1(-|$)/, "^=": /^%1/, "$=": /%1$/, "*=": /%1/ }; var _PSEUDO_CLASSES = { "first-child": "!IE7._getPreviousElementSibling(e%1)", "link": "e%1.currentStyle['ie7-link']=='link'", "visited": "e%1.currentStyle['ie7-link']=='visited'" }; var _VAR = "var p%2=0,i%2,e%2,n%2=e%1."; var _ID = "e%1.sourceIndex"; var _TEST = "var g=" + _ID + ";if(!p[g]){p[g]=1;"; var _STORE = "r[r.length]=e%1;if(s)return e%1;"; var _FN = "var _selectorFunction=function(e0,s){IE7._indexed++;var r=[],p={},reg=[%1],d=document;"; var reg; // a store for RexExp objects var _index; var _wild; // need to flag certain _wild card selectors as MSIE includes comment nodes var _list; // are we processing a node _list? var _duplicate; // possible duplicates? var _cache = {}; // store parsed selectors // a hideous parser var cssParser = new CSSParser({ " (\\*|[\\w-]+)#([\\w-]+)": function(match, tagName, id) { // descendant selector followed by ID _wild = false; var replacement = "var e%2=IE7._byId(d,'%4');if(e%2&&"; if (tagName != "*") replacement += "e%2.nodeName=='%3'&&"; replacement += "(e%1==d||e%1.contains(e%2))){"; if (_list) replacement += format("i%1=n%1.length;", _list); return format(replacement, _index++, _index, tagName.toUpperCase(), id); }, " (\\*|[\\w-]+)": function(match, tagName) { // descendant selector _duplicate++; // this selector may produce duplicates _wild = tagName == "*"; var replacement = _VAR; // IE5.x does not support getElementsByTagName("*"); replacement += (_wild && _MSIE5) ? "all" : "getElementsByTagName('%3')"; replacement += ";for(i%2=0;(e%2=n%2[i%2]);i%2++){"; return format(replacement, _index++, _list = _index, tagName.toUpperCase()); }, ">(\\*|[\\w-]+)": function(match, tagName) { // child selector var children = _list; _wild = tagName == "*"; var replacement = _VAR; // use the children property for MSIE as it does not contain text nodes // (but the children collection still includes comments). // the document object does not have a children collection replacement += children ? "children": "childNodes"; if (!_wild && children) replacement += ".tags('%3')"; replacement += ";for(i%2=0;(e%2=n%2[i%2]);i%2++){"; if (_wild) { replacement += "if(e%2.nodeType==1){"; _wild = _MSIE5; } else { if (!children) replacement += "if(e%2.nodeName=='%3'){"; } return format(replacement, _index++, _list = _index, tagName.toUpperCase()); }, "\\+(\\*|[\\w-]+)": function(match, tagName) { // direct adjacent selector var replacement = ""; if (_wild) replacement += "if(e%1.nodeName!='!'){"; _wild = false; replacement += "e%1=IE7._getNextElementSibling(e%1);if(e%1"; if (tagName != "*") replacement += "&&e%1.nodeName=='%2'"; replacement += "){"; return format(replacement, _index, tagName.toUpperCase()); }, "~(\\*|[\\w-]+)": function(match, tagName) { // indirect adjacent selector var replacement = ""; if (_wild) replacement += "if(e%1.nodeName!='!'){"; _wild = false; _duplicate = 2; // this selector may produce duplicates replacement += "while(e%1=e%1.nextSibling){if(e%1.ie7_adjacent==IE7._indexed)break;if("; if (tagName == "*") { replacement += "e%1.nodeType==1"; if (_MSIE5) replacement += "&&e%1.nodeName!='!'"; } else replacement += "e%1.nodeName=='%2'"; replacement += "){e%1.ie7_adjacent=IE7._indexed;"; return format(replacement, _index, tagName.toUpperCase()); }, "#([\\w-]+)": function(match, id) { // ID selector _wild = false; var replacement = "if(e%1.id=='%2'){"; if (_list) replacement += format("i%1=n%1.length;", _list); return format(replacement, _index, id); }, "\\.([\\w-]+)": function(match, className) { // class selector _wild = false; // store RegExp objects - slightly faster on IE reg.push(new RegExp("(^|\\s)" + rescape(className) + "(\\s|$)")); return format("if(e%1.className&®[%2].test(e%1.className)){", _index, reg.length - 1); }, "\\[([\\w-]+)\\s*([^=]?=)?\\s*([^\\]]*)\\]": function(match, attr, operator, value) { // attribute selectors var alias = _ATTRIBUTES[attr] || attr; if (operator) { var getAttribute = "e%1.getAttribute('%2',2)"; if (!_EVALUATED.test(attr)) { getAttribute = "e%1.%3||" + getAttribute; } attr = format("(" + getAttribute + ")", _index, attr, alias); } else { attr = format("IE7._getAttribute(e%1,'%2')", _index, attr); } var replacement = _OPERATORS[operator || ""] || "0"; if (replacement && replacement.source) { reg.push(new RegExp(format(replacement.source, rescape(cssParser.unescape(value))))); replacement = "reg[%2].test(%1)"; value = reg.length - 1; } return "if(" + format(replacement, attr, value) + "){"; }, ":+([\\w-]+)(\\(([^)]+)\\))?": function(match, pseudoClass, $2, args) { // pseudo class selectors pseudoClass = _PSEUDO_CLASSES[pseudoClass]; return "if(" + (pseudoClass ? format(pseudoClass, _index, args || "") : "0") + "){"; } }); // ========================================================================= // ie7-css.js // ========================================================================= var HYPERLINK = /a(#[\w-]+)?(\.[\w-]+)?:(hover|active)/i; var BRACE1 = /\s*\{\s*/, BRACE2 = /\s*\}\s*/, COMMA = /\s*\,\s*/; var FIRST_LINE_LETTER = /(.*)(:first-(line|letter))/; //var UNKNOWN = /UNKNOWN|([:.])\w+\1/i; var styleSheets = document.styleSheets; IE7.CSS = new (Fix.extend({ // single instance parser: new Parser, screen: "", print: "", styles: [], rules: [], pseudoClasses: appVersion < 7 ? "first\\-child" : "", dynamicPseudoClasses: { toString: function() { var strings = []; for (var pseudoClass in this) strings.push(pseudoClass); return strings.join("|"); } }, init: function() { var NONE = "^\x01$"; var CLASS = "\\[class=?[^\\]]*\\]"; var pseudoClasses = []; if (this.pseudoClasses) pseudoClasses.push(this.pseudoClasses); var dynamicPseudoClasses = this.dynamicPseudoClasses.toString(); if (dynamicPseudoClasses) pseudoClasses.push(dynamicPseudoClasses); pseudoClasses = pseudoClasses.join("|"); var unknown = appVersion < 7 ? ["[>+~[(]|([:.])\\w+\\1"] : [CLASS]; if (pseudoClasses) unknown.push(":(" + pseudoClasses + ")"); this.UNKNOWN = new RegExp(unknown.join("|") || NONE, "i"); var complex = appVersion < 7 ? ["\\[[^\\]]+\\]|[^\\s(\\[]+\\s*[+~]"] : [CLASS]; var complexRule = complex.concat(); if (pseudoClasses) complexRule.push(":(" + pseudoClasses + ")"); Rule.COMPLEX = new RegExp(complexRule.join("|") || NONE, "ig"); if (this.pseudoClasses) complex.push(":(" + this.pseudoClasses + ")"); DynamicRule.COMPLEX = new RegExp(complex.join("|") || NONE, "i"); DynamicRule.MATCH = new RegExp(dynamicPseudoClasses ? "(.*):(" + dynamicPseudoClasses + ")(.*)" : NONE, "i"); this.createStyleSheet(); this.refresh(); }, addEventHandler: function() { addEventHandler.apply(null, arguments); }, addFix: function(expression, replacement) { this.parser.add(expression, replacement); }, addRecalc: function(propertyName, test, handler, replacement) { // recalcs occur whenever the document is refreshed using document.recalc() test = new RegExp("([{;\\s])" + propertyName + "\\s*:\\s*" + test + "[^;}]*"); var id = this.recalcs.length; if (replacement) replacement = propertyName + ":" + replacement; this.addFix(test, function(match, $1) { return (replacement ? $1 + replacement : match) + ";ie7-" + match.slice(1) + ";ie7_recalc" + id + ":1"; }); this.recalcs.push(arguments); return id; }, apply: function() { this.getInlineStyles(); new StyleSheet("screen"); this.trash(); }, createStyleSheet: function() { // create the IE7 style sheet this.styleSheet = document.createStyleSheet(); // flag it so we can ignore it during parsing this.styleSheet.ie7 = true; this.styleSheet.owningElement.ie7 = true; this.styleSheet.cssText = HEADER; }, getInlineStyles: function() { // load inline styles var styleSheets = document.getElementsByTagName("style"), styleSheet; for (var i = styleSheets.length - 1; (styleSheet = styleSheets[i]); i--) { if (!styleSheet.disabled && !styleSheet.ie7) { this.styles.push(styleSheet.innerHTML); } } }, getText: function(styleSheet, path) { // explorer will trash unknown selectors (it converts them to "UNKNOWN"). // so we must reload external style sheets (internal style sheets can have their text // extracted through the innerHTML property). // load the style sheet text from an external file try { var cssText = styleSheet.cssText; } catch (e) { cssText = ""; } if (httpRequest) cssText = loadFile(styleSheet.href, path) || cssText; return cssText; }, recalc: function() { this.screen.recalc(); // we're going to read through all style rules. // certain rules have had ie7 properties added to them. // e.g. p{top:0; ie7_recalc2:1; left:0} // this flags a property in the rule as needing a fix. // the selector text is then used to query the document. // we can then loop through the results of the query // and fix the elements. // we ignore the IE7 rules - so count them in the header var RECALCS = /ie7_recalc\d+/g; var start = HEADER.match(/[{,]/g).length; // only calculate screen fixes. print fixes don't show up anyway var stop = start + (this.screen.cssText.match(/\{/g)||"").length; var rules = this.styleSheet.rules, rule; var calcs, calc, elements, element, i, j, k, id; // loop through all rules for (i = start; i < stop; i++) { rule = rules[i]; var cssText = rule.style.cssText; // search for the "ie7_recalc" flag (there may be more than one) if (rule && (calcs = cssText.match(RECALCS))) { // use the selector text to query the document elements = cssQuery(rule.selectorText); // if there are matching elements then loop // through the recalc functions and apply them // to each element if (elements.length) for (j = 0; j < calcs.length; j++) { // get the matching flag (e.g. ie7_recalc3) id = calcs[j]; // extract the numeric id from the end of the flag // and use it to index the collection of recalc // functions calc = IE7.CSS.recalcs[id.slice(10)][2]; for (k = 0; (element = elements[k]); k++) { // apply the fix if (element.currentStyle[id]) calc(element, cssText); } } } } }, refresh: function() { this.styleSheet.cssText = HEADER + this.screen + this.print; }, trash: function() { // trash the old style sheets for (var i = 0; i < styleSheets.length; i++) { if (!styleSheets[i].ie7) { try { var cssText = styleSheets[i].cssText; } catch (e) { cssText = ""; } if (cssText) styleSheets[i].cssText = ""; } } } })); // ----------------------------------------------------------------------- // IE7 StyleSheet class // ----------------------------------------------------------------------- var StyleSheet = Base.extend({ constructor: function(media) { this.media = media; this.load(); IE7.CSS[media] = this; IE7.CSS.refresh(); }, createRule: function(selector, cssText) { if (IE7.CSS.UNKNOWN.test(selector)) { var match; if (PseudoElement && (match = selector.match(PseudoElement.MATCH))) { return new PseudoElement(match[1], match[2], cssText); } else if (match = selector.match(DynamicRule.MATCH)) { if (!HYPERLINK.test(match[0]) || DynamicRule.COMPLEX.test(match[0])) { return new DynamicRule(selector, match[1], match[2], match[3], cssText); } } else return new Rule(selector, cssText); } return selector + " {" + cssText + "}"; }, getText: function() { // store for style sheet text var _inlineStyles = [].concat(IE7.CSS.styles); // parse media decalarations var MEDIA = /@media\s+([^{]*)\{([^@]+\})\s*\}/gi; var ALL = /\ball\b|^$/i, SCREEN = /\bscreen\b/i, PRINT = /\bprint\b/i; function _parseMedia(cssText, media) { _filterMedia.value = media; return cssText.replace(MEDIA, _filterMedia); }; function _filterMedia(match, media, cssText) { media = _simpleMedia(media); switch (media) { case "screen": case "print": if (media != _filterMedia.value) return ""; case "all": return cssText; } return ""; }; function _simpleMedia(media) { if (ALL.test(media)) return "all"; else if (SCREEN.test(media)) return (PRINT.test(media)) ? "all" : "screen"; else if (PRINT.test(media)) return "print"; }; var self = this; function _getCSSText(styleSheet, path, media, level) { var cssText = ""; if (!level) { media = _simpleMedia(styleSheet.media); level = 0; } if (media == "all" || media == self.media) { // IE only allows importing style sheets three levels deep. // it will crash if you try to access a level below this if (level < 3) { // loop through imported style sheets for (var i = 0; i < styleSheet.imports.length; i++) { // call this function recursively to get all imported style sheets cssText += _getCSSText(styleSheet.imports[i], getPath(styleSheet.href, path), media, level + 1); } } // retrieve inline style or load an external style sheet cssText += encode(styleSheet.href ? _loadStyleSheet(styleSheet, path) : _inlineStyles.pop() || ""); cssText = _parseMedia(cssText, self.media); } return cssText; }; // store loaded cssText URLs var fileCache = {}; // load an external style sheet function _loadStyleSheet(styleSheet, path) { var url = makePath(styleSheet.href, path); // if the style sheet has already loaded then don't duplicate it if (fileCache[url]) return ""; // load from source fileCache[url] = (styleSheet.disabled) ? "" : _fixUrls(IE7.CSS.getText(styleSheet, path), getPath(styleSheet.href, path)); return fileCache[url]; }; // fix css paths // we're lumping all css text into one big style sheet so relative // paths have to be fixed. this is necessary anyway because of other // explorer bugs. var URL = /(url\s*\(\s*['"]?)([\w\.]+[^:\)]*['"]?\))/gi; function _fixUrls(cssText, pathname) { // hack & slash return cssText.replace(URL, "$1" + pathname.slice(0, pathname.lastIndexOf("/") + 1) + "$2"); }; // load all style sheets in the document for (var i = 0; i < styleSheets.length; i++) { if (!styleSheets[i].disabled && !styleSheets[i].ie7) { this.cssText += _getCSSText(styleSheets[i]); } } }, load: function() { this.cssText = ""; this.getText(); this.parse(); this.cssText = decode(this.cssText); fileCache = {}; }, parse: function() { this.cssText = IE7.CSS.parser.exec(this.cssText); // parse the style sheet var offset = IE7.CSS.rules.length; var rules = this.cssText.split(BRACE2), rule; var selectors, cssText, i, j; for (i = 0; i < rules.length; i++) { rule = rules[i].split(BRACE1); selectors = rule[0].split(COMMA); cssText = rule[1]; for (j = 0; j < selectors.length; j++) { selectors[j] = cssText ? this.createRule(selectors[j], cssText) : ""; } rules[i] = selectors.join("\n"); } this.cssText = rules.join("\n"); this.rules = IE7.CSS.rules.slice(offset); }, recalc: function() { var rule, i; for (i = 0; (rule = this.rules[i]); i++) rule.recalc(); }, toString: function() { return "@media " + this.media + "{" + this.cssText + "}"; } }); var PseudoElement; // ----------------------------------------------------------------------- // IE7 style rules // ----------------------------------------------------------------------- var Rule = IE7.Rule = Base.extend({ // properties constructor: function(selector, cssText) { this.id = IE7.CSS.rules.length; this.className = Rule.PREFIX + this.id; selector = selector.match(FIRST_LINE_LETTER) || selector || "*"; this.selector = selector[1] || selector; this.selectorText = this.parse(this.selector) + (selector[2] || ""); this.cssText = cssText; this.MATCH = new RegExp("\\s" + this.className + "(\\s|$)", "g"); IE7.CSS.rules.push(this); this.init(); }, init: Undefined, add: function(element) { // allocate this class element.className += " " + this.className; }, recalc: function() { // execute the underlying css query for this class var match = cssQuery(this.selector); // add the class name for all matching elements for (var i = 0; i < match.length; i++) this.add(match[i]); }, parse: function(selector) { // attempt to preserve specificity for "loose" parsing by // removing unknown tokens from a css selector but keep as // much as we can.. var simple = selector.replace(Rule.CHILD, " ").replace(Rule.COMPLEX, ""); if (appVersion < 7) simple = simple.replace(Rule.MULTI, ""); var tags = match(simple, Rule.TAGS).length - match(selector, Rule.TAGS).length; var classes = match(simple, Rule.CLASSES).length - match(selector, Rule.CLASSES).length + 1; while (classes > 0 && Rule.CLASS.test(simple)) { simple = simple.replace(Rule.CLASS, ""); classes--; } while (tags > 0 && Rule.TAG.test(simple)) { simple = simple.replace(Rule.TAG, "$1*"); tags--; } simple += "." + this.className; classes = Math.min(classes, 2); tags = Math.min(tags, 2); var score = -10 * classes - tags; if (score > 0) { simple = simple + "," + Rule.MAP[score] + " " + simple; } return simple; }, remove: function(element) { // deallocate this class element.className = element.className.replace(this.MATCH, "$1"); }, toString: function() { return format("%1 {%2}", this.selectorText, this.cssText); } }, { CHILD: />/g, CLASS: /\.[\w-]+/, CLASSES: /[.:\[]/g, MULTI: /(\.[\w-]+)+/g, PREFIX: "ie7_class", TAG: /^\w+|([\s>+~])\w+/, TAGS: /^\w|[\s>+~]\w/g, MAP: { 1: "html", 2: "html body", 10: ".ie7_html", 11: "html.ie7_html", 12: "html.ie7_html body", 20: ".ie7_html .ie7_body", 21: "html.ie7_html .ie7_body", 22: "html.ie7_html body.ie7_body" } }); // ----------------------------------------------------------------------- // IE7 dynamic style // ----------------------------------------------------------------------- // object properties: // attach: the element that an event handler will be attached to // target: the element that will have the IE7 class applied var DynamicRule = Rule.extend({ // properties constructor: function(selector, attach, dynamicPseudoClass, target, cssText) { // initialise object properties this.attach = attach || "*"; this.dynamicPseudoClass = IE7.CSS.dynamicPseudoClasses[dynamicPseudoClass]; this.target = target; this.base(selector, cssText); }, recalc: function() { // execute the underlying css query for this class var attaches = cssQuery(this.attach), attach; // process results for (var i = 0; attach = attaches[i]; i++) { // retrieve the event handler's target element(s) var target = this.target ? cssQuery(this.target, attach) : [attach]; // attach event handlers for dynamic pseudo-classes if (target.length) this.dynamicPseudoClass.apply(attach, target, this); } } }); // ----------------------------------------------------------------------- // IE7 dynamic pseudo-classes // ----------------------------------------------------------------------- var DynamicPseudoClass = Base.extend({ constructor: function(name, apply) { this.name = name; this.apply = apply; this.instances = {}; IE7.CSS.dynamicPseudoClasses[name] = this; }, register: function(instance) { // an "instance" is actually an Arguments object var _class = instance[2]; instance.id = _class.id + instance[0].uniqueID; if (!this.instances[instance.id]) { var target = instance[1], j; for (j = 0; j < target.length; j++) _class.add(target[j]); this.instances[instance.id] = instance; } }, unregister: function(instance) { if (this.instances[instance.id]) { var _class = instance[2]; var target = instance[1], j; for (j = 0; j < target.length; j++) _class.remove(target[j]); delete this.instances[instance.id]; } } }); // ----------------------------------------------------------------------- // dynamic pseudo-classes // ----------------------------------------------------------------------- if (appVersion < 7) { var Hover = new DynamicPseudoClass("hover", function(element) { var instance = arguments; IE7.CSS.addEventHandler(element, appVersion < 5.5 ? "onmouseover" : "onmouseenter", function() { Hover.register(instance); }); IE7.CSS.addEventHandler(element, appVersion < 5.5 ? "onmouseout" : "onmouseleave", function() { Hover.unregister(instance); }); }); // globally trap the mouseup event (thanks Martijn!) addEventHandler(document, "onmouseup", function() { var instances = Hover.instances; for (var i in instances) if (!instances[i][0].contains(event.srcElement)) Hover.unregister(instances[i]); }); } // ----------------------------------------------------------------------- // propertyName: inherit; // ----------------------------------------------------------------------- IE7.CSS.addRecalc("[\\w-]+", "inherit", function(element, cssText) { var inherited = cssText.match(/[\w-]+\s*:\s*inherit/g); for (var i = 0; i < inherited.length; i++) { var propertyName = inherited[i].replace(/ie7\-|\s*:\s*inherit/g, "").replace(/\-([a-z])/g, function(match, chr) { return chr.toUpperCase() }); element.runtimeStyle[propertyName] = element.parentElement.currentStyle[propertyName]; } }); // ========================================================================= // ie7-html.js // ========================================================================= // default font-sizes //HEADER += "h1{font-size:2em}h2{font-size:1.5em;}h3{font-size:1.17em;}h4{font-size:1em}h5{font-size:.83em}h6{font-size:.67em}"; IE7.HTML = new (Fix.extend({ // single instance fixed: {}, init: Undefined, addFix: function() { // fixes are a one-off, they are applied when the document is loaded this.fixes.push(arguments); }, apply: function() { for (var i = 0; i < this.fixes.length; i++) { var match = cssQuery(this.fixes[i][0]); var fix = this.fixes[i][1]; for (var j = 0; j < match.length; j++) fix(match[j]); } }, addRecalc: function() { // recalcs occur whenever the document is refreshed using document.recalc() this.recalcs.push(arguments); }, recalc: function() { // loop through the fixes for (var i = 0; i < this.recalcs.length; i++) { var match = cssQuery(this.recalcs[i][0]); var recalc = this.recalcs[i][1], element; var key = Math.pow(2, i); for (var j = 0; (element = match[j]); j++) { var uniqueID = element.uniqueID; if ((this.fixed[uniqueID] & key) == 0) { element = recalc(element) || element; this.fixed[uniqueID] |= key; } } } } })); if (appVersion < 7) { // provide support for the tag. // this is a proper fix, it preserves the DOM structure and // elements report the correct tagName & namespace prefix document.createElement("abbr"); // bind to the first child control IE7.HTML.addRecalc("label", function(label) { if (!label.htmlFor) { var firstChildControl = cssQuery("input,textarea", label, true); if (firstChildControl) { addEventHandler(label, "onclick", function() { firstChildControl.click(); }); } } }); } // ========================================================================= // ie7-layout.js // ========================================================================= var NUMERIC = "[.\\d]"; new function(_) { var layout = IE7.Layout = this; // big, ugly box-model hack + min/max stuff // #tantek > #erik > #dean { voice-family: hacker; } // ----------------------------------------------------------------------- // "layout" // ----------------------------------------------------------------------- HEADER += "*{boxSizing:content-box}"; // does an element have "layout" ? IE7.hasLayout = appVersion < 5.5 ? function(element) { // element.currentStyle.hasLayout doesn't work for IE5.0 return element.clientWidth; } : function(element) { return element.currentStyle.hasLayout; }; // give an element "layout" layout.boxSizing = function(element) { if (!IE7.hasLayout(element)) { //# element.runtimeStyle.fixedHeight = element.style.height = "0cm"; if (element.currentStyle.verticalAlign == "auto") element.runtimeStyle.verticalAlign = "top"; // when an element acquires "layout", margins no longer collapse correctly collapseMargins(element); } }; // ----------------------------------------------------------------------- // Margin Collapse // ----------------------------------------------------------------------- function collapseMargins(element) { if (element != viewport && element.currentStyle.position != "absolute") { collapseMargin(element, "marginTop"); collapseMargin(element, "marginBottom"); } }; function collapseMargin(element, type) { if (!element.runtimeStyle[type]) { var parentElement = element.parentElement; if (parentElement && IE7.hasLayout(parentElement) && !IE7[type == "marginTop" ? "_getPreviousElementSibling" : "_getNextElementSibling"](element)) return; var child = cssQuery(">*:" + (type == "marginTop" ? "first" : "last") + "-child", element, true); if (child && child.currentStyle.styleFloat == "none" && IE7.hasLayout(child)) { collapseMargin(child, type); margin = _getMargin(element, element.currentStyle[type]); childMargin = _getMargin(child, child.currentStyle[type]); if (margin < 0 || childMargin < 0) { element.runtimeStyle[type] = margin + childMargin; } else { element.runtimeStyle[type] = Math.max(childMargin, margin); } child.runtimeStyle[type] = "0px"; } } }; function _getMargin(element, value) { return value == "auto" ? 0 : getPixelValue(element, value); }; // ----------------------------------------------------------------------- // box-model // ----------------------------------------------------------------------- // constants var UNIT = /^[.\d][\w%]*$/, AUTO = /^(auto|0cm)$/; var applyWidth, applyHeight; IE7.Layout.borderBox = function(element){ applyWidth(element); applyHeight(element); }; var fixWidth = function(HEIGHT) { applyWidth = function(element) { if (!PERCENT.test(element.currentStyle.width)) fixWidth(element); collapseMargins(element); }; function fixWidth(element, value) { if (!element.runtimeStyle.fixedWidth) { if (!value) value = element.currentStyle.width; element.runtimeStyle.fixedWidth = (UNIT.test(value)) ? Math.max(0, getFixedWidth(element, value)) : value; setOverrideStyle(element, "width", element.runtimeStyle.fixedWidth); } }; function layoutWidth(element) { if (!isFixed(element)) { var layoutParent = element.offsetParent; while (layoutParent && !IE7.hasLayout(layoutParent)) layoutParent = layoutParent.offsetParent; } return (layoutParent || viewport).clientWidth; }; function getPixelWidth(element, value) { if (PERCENT.test(value)) return parseInt(parseFloat(value) / 100 * layoutWidth(element)); return getPixelValue(element, value); }; var getFixedWidth = function(element, value) { var borderBox = element.currentStyle["box-sizing"] == "border-box"; var adjustment = 0; if (quirksMode && !borderBox) adjustment += getBorderWidth(element) + getWidth(element, "padding"); else if (!quirksMode && borderBox) adjustment -= getBorderWidth(element) + getWidth(element, "padding"); return getPixelWidth(element, value) + adjustment; }; // easy way to get border thickness for elements with "layout" function getBorderWidth(element) { return element.offsetWidth - element.clientWidth; }; // have to do some pixel conversion to get padding/margin thickness :-( function getWidth(element, type) { return getPixelWidth(element, element.currentStyle[type + "Left"]) + getPixelWidth(element, element.currentStyle[type + "Right"]); }; // ----------------------------------------------------------------------- // min/max // ----------------------------------------------------------------------- HEADER += "*{minWidth:none;maxWidth:none;min-width:none;max-width:none}"; // handle min-width property layout.minWidth = function(element) { // IE6 supports min-height so we frig it here //#if (element.currentStyle.minHeight == "auto") element.runtimeStyle.minHeight = 0; if (element.currentStyle["min-width"] != null) { element.style.minWidth = element.currentStyle["min-width"]; } if (register(arguments.callee, element, element.currentStyle.minWidth != "none")) { layout.boxSizing(element); fixWidth(element); resizeWidth(element); } }; // clone the minWidth function to make a maxWidth function eval("IE7.Layout.maxWidth=" + String(layout.minWidth).replace(/min/g, "max")); // apply min/max restrictions function resizeWidth(element) { // check boundaries var rect = element.getBoundingClientRect(); var width = rect.right - rect.left; if (element.currentStyle.minWidth != "none" && width <= getFixedWidth(element, element.currentStyle.minWidth)) { element.runtimeStyle.width = element.currentStyle.minWidth; } else if (element.currentStyle.maxWidth != "none" && width >= getFixedWidth(element, element.currentStyle.maxWidth)) { element.runtimeStyle.width = element.currentStyle.maxWidth; } else { element.runtimeStyle.width = element.runtimeStyle.fixedWidth; // || "auto"; } }; // ----------------------------------------------------------------------- // right/bottom // ----------------------------------------------------------------------- function fixRight(element) { if (register(fixRight, element, /^(fixed|absolute)$/.test(element.currentStyle.position) && getDefinedStyle(element, "left") != "auto" && getDefinedStyle(element, "right") != "auto" && AUTO.test(getDefinedStyle(element, "width")))) { resizeRight(element); IE7.Layout.boxSizing(element); } }; IE7.Layout.fixRight = fixRight; function resizeRight(element) { var left = getPixelWidth(element, element.runtimeStyle._left || element.currentStyle.left); var width = layoutWidth(element) - getPixelWidth(element, element.currentStyle.right) - left - getWidth(element, "margin"); if (parseInt(element.runtimeStyle.width) == width) return; element.runtimeStyle.width = ""; if (isFixed(element) || HEIGHT || element.offsetWidth < width) { if (!quirksMode) width -= getBorderWidth(element) + getWidth(element, "padding"); if (width < 0) width = 0; element.runtimeStyle.fixedWidth = width; setOverrideStyle(element, "width", width); } }; // ----------------------------------------------------------------------- // window.onresize // ----------------------------------------------------------------------- // handle window resize var clientWidth = 0; addResize(function() { if (!viewport) return; var i, wider = (clientWidth < viewport.clientWidth); clientWidth = viewport.clientWidth; // resize elements with "min-width" set var elements = layout.minWidth.elements; for (i in elements) { var element = elements[i]; var fixedWidth = (parseInt(element.runtimeStyle.width) == getFixedWidth(element, element.currentStyle.minWidth)); if (wider && fixedWidth) element.runtimeStyle.width = ""; if (wider == fixedWidth) resizeWidth(element); } // resize elements with "max-width" set var elements = layout.maxWidth.elements; for (i in elements) { var element = elements[i]; var fixedWidth = (parseInt(element.runtimeStyle.width) == getFixedWidth(element, element.currentStyle.maxWidth)); if (!wider && fixedWidth) element.runtimeStyle.width = ""; if (wider != fixedWidth) resizeWidth(element); } // resize elements with "right" set for (i in fixRight.elements) resizeRight(fixRight.elements[i]); }); // ----------------------------------------------------------------------- // fix CSS // ----------------------------------------------------------------------- if (quirksMode) { IE7.CSS.addRecalc("width", NUMERIC, applyWidth); } if (appVersion < 7) { IE7.CSS.addRecalc("min-width", NUMERIC, layout.minWidth); IE7.CSS.addRecalc("max-width", NUMERIC, layout.maxWidth); IE7.CSS.addRecalc("right", NUMERIC, fixRight); } }; eval("var fixHeight=" + rotate(fixWidth)); // apply box-model + min/max fixes fixWidth(); fixHeight(true); }; // ========================================================================= // ie7-graphics.js // ========================================================================= // a small transparent image used as a placeholder var BLANK_GIF = makePath("blank.gif", path); var ALPHA_IMAGE_LOADER = "DXImageTransform.Microsoft.AlphaImageLoader"; var PNG_FILTER = "progid:" + ALPHA_IMAGE_LOADER + "(src='%1',sizingMethod='%2')"; // regular expression version of the above var PNG; var filtered = []; function fixImage(element) { if (PNG.test(element.src)) { // we have to preserve width and height var image = new Image(element.width, element.height); image.onload = function() { element.width = image.width; element.height = image.height; image = null; }; image.src = element.src; // store the original url (we'll put it back when it's printed) element.pngSrc = element.src; // add the AlphaImageLoader thingy addFilter(element); } }; if (appVersion >= 5.5 && appVersion < 7) { // ** IE7 VARIABLE // e.g. only apply the hack to files ending in ".png" // IE7_PNG_SUFFIX = ".png"; // replace background(-image): url(..) .. with background(-image): .. ;filter: ..; IE7.CSS.addFix(/background(-image)?\s*:\s*([^};]*)?url\(([^\)]+)\)([^;}]*)?/, function(match, $1, $2, url, $4) { url = getString(url); return PNG.test(url) ? "filter:" + format(PNG_FILTER, url, "crop") + ";zoom:1;background" + ($1||"") + ":" + ($2||"") + "none" + ($4||"") : match; }); // ----------------------------------------------------------------------- // fix PNG transparency (HTML images) // ----------------------------------------------------------------------- IE7.HTML.addRecalc("img,input", function(element) { if (element.tagName == "INPUT" && element.type != "image") return; fixImage(element); addEventHandler(element, "onpropertychange", function() { if (!printing && event.propertyName == "src" && element.src.indexOf(BLANK_GIF) == -1) fixImage(element); }); }); // assume that background images should not be printed // (if they are not transparent then they'll just obscure content) // but we'll put foreground images back... var printing = false; addEventHandler(window, "onbeforeprint", function() { printing = true; for (var i = 0; i < filtered.length; i++) removeFilter(filtered[i]); }); addEventHandler(window, "onafterprint", function() { for (var i = 0; i < filtered.length; i++) addFilter(filtered[i]); printing = false; }); } // apply a filter function addFilter(element, sizingMethod) { var filter = element.filters[ALPHA_IMAGE_LOADER]; if (filter) { filter.src = element.src; filter.enabled = true; } else { element.runtimeStyle.filter = format(PNG_FILTER, element.src, sizingMethod || "scale"); filtered.push(element); } // remove the real image element.src = BLANK_GIF; }; function removeFilter(element) { element.src = element.pngSrc; element.filters[ALPHA_IMAGE_LOADER].enabled = false; }; // ========================================================================= // ie7-fixed.js // ========================================================================= new function(_) { if (appVersion >= 7) return; // some things to consider for this hack. // the document body requires a fixed background. even if // it is just a blank image. // you have to use setExpression instead of onscroll, this // together with a fixed body background helps avoid the // annoying screen flicker of other solutions. IE7.CSS.addRecalc("position", "fixed", _positionFixed, "absolute"); IE7.CSS.addRecalc("background(-attachment)?", "[^};]*fixed", _backgroundFixed); // scrolling is relative to the documentElement (HTML tag) when in // standards mode, otherwise it's relative to the document body var $viewport = quirksMode ? "body" : "documentElement"; function _fixBackground() { // this is required by both position:fixed and background-attachment:fixed. // it is necessary for the document to also have a fixed background image. // we can fake this with a blank image if necessary if (body.currentStyle.backgroundAttachment != "fixed") { if (body.currentStyle.backgroundImage == "none") { body.runtimeStyle.backgroundRepeat = "no-repeat"; body.runtimeStyle.backgroundImage = "url(" + BLANK_GIF + ")"; // dummy } body.runtimeStyle.backgroundAttachment = "fixed"; } _fixBackground = Undefined; }; var _tmp = createTempElement("img"); function _isFixed(element) { return element ? isFixed(element) || _isFixed(element.parentElement) : false; }; function _setExpression(element, propertyName, expression) { setTimeout("document.all." + element.uniqueID + ".runtimeStyle.setExpression('" + propertyName + "','" + expression + "')", 0); }; // ----------------------------------------------------------------------- // backgroundAttachment: fixed // ----------------------------------------------------------------------- function _backgroundFixed(element) { if (register(_backgroundFixed, element, element.currentStyle.backgroundAttachment == "fixed" && !element.contains(body))) { _fixBackground(); bgLeft(element); bgTop(element); _backgroundPosition(element); } }; function _backgroundPosition(element) { _tmp.src = element.currentStyle.backgroundImage.slice(5, -2); var parentElement = element.canHaveChildren ? element : element.parentElement; parentElement.appendChild(_tmp); setOffsetLeft(element); setOffsetTop(element); parentElement.removeChild(_tmp); }; function bgLeft(element) { element.style.backgroundPositionX = element.currentStyle.backgroundPositionX; if (!_isFixed(element)) { _setExpression(element, "backgroundPositionX", "(parseInt(runtimeStyle.offsetLeft)+document." + $viewport + ".scrollLeft)||0"); } }; eval(rotate(bgLeft)); function setOffsetLeft(element) { var propertyName = _isFixed(element) ? "backgroundPositionX" : "offsetLeft"; element.runtimeStyle[propertyName] = getOffsetLeft(element, element.style.backgroundPositionX) - element.getBoundingClientRect().left - element.clientLeft + 2; }; eval(rotate(setOffsetLeft)); function getOffsetLeft(element, position) { switch (position) { case "left": case "top": return 0; case "right": case "bottom": return viewport.clientWidth - _tmp.offsetWidth; case "center": return (viewport.clientWidth - _tmp.offsetWidth) / 2; default: if (PERCENT.test(position)) { return parseInt((viewport.clientWidth - _tmp.offsetWidth) * parseFloat(position) / 100); } _tmp.style.left = position; return _tmp.offsetLeft; } }; eval(rotate(getOffsetLeft)); // ----------------------------------------------------------------------- // position: fixed // ----------------------------------------------------------------------- function _positionFixed(element) { if (register(_positionFixed, element, isFixed(element))) { setOverrideStyle(element, "position", "absolute"); setOverrideStyle(element, "left", element.currentStyle.left); setOverrideStyle(element, "top", element.currentStyle.top); _fixBackground(); IE7.Layout.fixRight(element); _foregroundPosition(element); } }; function _foregroundPosition(element, recalc) { positionTop(element, recalc); positionLeft(element, recalc, true); if (!element.runtimeStyle.autoLeft && element.currentStyle.marginLeft == "auto" && element.currentStyle.right != "auto") { var left = viewport.clientWidth - getPixelWidth(element, element.currentStyle.right) - getPixelWidth(element, element.runtimeStyle._left) - element.clientWidth; if (element.currentStyle.marginRight == "auto") left = parseInt(left / 2); if (_isFixed(element.offsetParent)) element.runtimeStyle.pixelLeft += left; else element.runtimeStyle.shiftLeft = left; } clipWidth(element); clipHeight(element); }; function clipWidth(element) { var fixWidth = element.runtimeStyle.fixWidth; element.runtimeStyle.borderRightWidth = ""; element.runtimeStyle.width = fixWidth ? getPixelWidth(element, fixWidth) : ""; if (element.currentStyle.width != "auto") { var rect = element.getBoundingClientRect(); var width = element.offsetWidth - viewport.clientWidth + rect.left - 2; if (width >= 0) { element.runtimeStyle.borderRightWidth = "0px"; width = Math.max(getPixelValue(element, element.currentStyle.width) - width, 0); setOverrideStyle(element, "width", width); return width; } } }; eval(rotate(clipWidth)); function positionLeft(element, recalc) { // if the element's width is in % units then it must be recalculated // with respect to the viewport if (!recalc && PERCENT.test(element.currentStyle.width)) { element.runtimeStyle.fixWidth = element.currentStyle.width; } if (element.runtimeStyle.fixWidth) { element.runtimeStyle.width = getPixelWidth(element, element.runtimeStyle.fixWidth); } //if (recalc) { // // if the element is fixed on the right then no need to recalculate // if (!element.runtimeStyle.autoLeft) return; //} else { element.runtimeStyle.shiftLeft = 0; element.runtimeStyle._left = element.currentStyle.left; // is the element fixed on the right? element.runtimeStyle.autoLeft = element.currentStyle.right != "auto" && element.currentStyle.left == "auto"; //} // reset the element's "left" value and get it's natural position element.runtimeStyle.left = ""; element.runtimeStyle.screenLeft = getScreenLeft(element); element.runtimeStyle.pixelLeft = element.runtimeStyle.screenLeft; // if the element is contained by another fixed element then there is no need to // continually recalculate it's left position if (!recalc && !_isFixed(element.offsetParent)) { // onsrcoll produces jerky movement, so we use an expression _setExpression(element, "pixelLeft", "runtimeStyle.screenLeft+runtimeStyle.shiftLeft+document." + $viewport + ".scrollLeft"); } }; // clone this function so we can do "top" eval(rotate(positionLeft)); // I've forgotten how this works... function getScreenLeft(element) { // thanks to kevin newman (captainn) var screenLeft = element.offsetLeft, nested = 1; if (element.runtimeStyle.autoLeft) { screenLeft = viewport.clientWidth - element.offsetWidth - getPixelWidth(element, element.currentStyle.right); } // accommodate margins if (element.currentStyle.marginLeft != "auto") { screenLeft -= getPixelWidth(element, element.currentStyle.marginLeft); } while (element = element.offsetParent) { if (element.currentStyle.position != "static") nested = -1; screenLeft += element.offsetLeft * nested; } return screenLeft; }; eval(rotate(getScreenLeft)); function getPixelWidth(element, value) { return PERCENT.test(value) ? parseInt(parseFloat(value) / 100 * viewport.clientWidth) : getPixelValue(element, value); }; eval(rotate(getPixelWidth)); // ----------------------------------------------------------------------- // capture window resize // ----------------------------------------------------------------------- function _resize() { // if the window has been resized then some positions need to be // recalculated (especially those aligned to "right" or "top" var elements = _backgroundFixed.elements; for (var i in elements) _backgroundPosition(elements[i]); elements = _positionFixed.elements; for (i in elements) { _foregroundPosition(elements[i], true); // do this twice to be sure - hackish, I know :-) _foregroundPosition(elements[i], true); } _timer = 0; }; // use a timer for some reason. // (sometimes this is a good way to prevent resize loops) var _timer; addResize(function() { if (!_timer) _timer = setTimeout(_resize, 0); }); }; // ========================================================================= // ie7-oveflow.js // ========================================================================= /* --------------------------------------------------------------------- This module alters the structure of the document. It may adversely affect other CSS rules. Be warned. --------------------------------------------------------------------- */ var WRAPPER_STYLE = { backgroundColor: "transparent", backgroundImage: "none", backgroundPositionX: null, backgroundPositionY: null, backgroundRepeat: null, borderTopWidth: 0, borderRightWidth: 0, borderBottomWidth: 0, borderLeftStyle: "none", borderTopStyle: "none", borderRightStyle: "none", borderBottomStyle: "none", borderLeftWidth: 0, height: null, marginTop: 0, marginBottom: 0, marginRight: 0, marginLeft: 0, width: "100%" }; IE7.CSS.addRecalc("overflow", "visible", function(element) { // don't do this again if (element.parentNode.ie7_wrapped) return; // if max-height is applied, makes sure it gets applied first if (IE7.Layout && element.currentStyle["max-height"] != "auto") { IE7.Layout.maxHeight(element); } if (element.currentStyle.marginLeft == "auto") element.style.marginLeft = 0; if (element.currentStyle.marginRight == "auto") element.style.marginRight = 0; var wrapper = document.createElement(ANON); wrapper.ie7_wrapped = element; for (var propertyName in WRAPPER_STYLE) { wrapper.style[propertyName] = element.currentStyle[propertyName]; if (WRAPPER_STYLE[propertyName] != null) { element.runtimeStyle[propertyName] = WRAPPER_STYLE[propertyName]; } } wrapper.style.display = "block"; wrapper.style.position = "relative"; element.runtimeStyle.position = "absolute"; element.parentNode.insertBefore(wrapper, element); wrapper.appendChild(element); }); // ========================================================================= // ie7-quirks.js // ========================================================================= function ie7Quirks() { var FONT_SIZES = "xx-small,x-small,small,medium,large,x-large,xx-large".split(","); for (var i = 0; i < FONT_SIZES.length; i++) { FONT_SIZES[FONT_SIZES[i]] = FONT_SIZES[i - 1] || "0.67em"; } IE7.CSS.addFix(/(font(-size)?\s*:\s*)([\w.-]+)/, function(match, label, size, value) { return label + (FONT_SIZES[value] || value); }); if (appVersion < 6) { var NEGATIVE = /^\-/, LENGTH = /(em|ex)$/i; var EM = /em$/i, EX = /ex$/i; getPixelValue = function(element, value) { if (PIXEL.test(value)) return parseInt(value)||0; var scale = NEGATIVE.test(value)? -1 : 1; if (LENGTH.test(value)) scale *= getFontScale(element); temp.style.width = (scale < 0) ? value.slice(1) : value; body.appendChild(temp); // retrieve pixel width value = scale * temp.offsetWidth; // remove the temporary element temp.removeNode(); return parseInt(value); }; var temp = createTempElement(); function getFontScale(element) { var scale = 1; temp.style.fontFamily = element.currentStyle.fontFamily; temp.style.lineHeight = element.currentStyle.lineHeight; //temp.style.fontSize = ""; while (element != body) { var fontSize = element.currentStyle["ie7-font-size"]; if (fontSize) { if (EM.test(fontSize)) scale *= parseFloat(fontSize); else if (PERCENT.test(fontSize)) scale *= (parseFloat(fontSize) / 100); else if (EX.test(fontSize)) scale *= (parseFloat(fontSize) / 2); else { temp.style.fontSize = fontSize; return 1; } } element = element.parentElement; } return scale; }; // cursor:pointer (IE5.x) IE7.CSS.addFix(/cursor\s*:\s*pointer/, "cursor:hand"); // display:list-item (IE5.x) IE7.CSS.addFix(/display\s*:\s*list-item/, "display:block"); } // ----------------------------------------------------------------------- // margin:auto // ----------------------------------------------------------------------- function fixMargin(element) { if (appVersion < 5.5) IE7.Layout.boxSizing(element.parentElement); var parent = element.parentElement; var margin = parent.offsetWidth - element.offsetWidth - getPaddingWidth(parent); var autoRight = (element.currentStyle["ie7-margin"] && element.currentStyle.marginRight == "auto") || element.currentStyle["ie7-margin-right"] == "auto"; switch (parent.currentStyle.textAlign) { case "right": margin = autoRight ? parseInt(margin / 2) : 0; element.runtimeStyle.marginRight = margin + "px"; break; case "center": if (autoRight) margin = 0; default: if (autoRight) margin /= 2; element.runtimeStyle.marginLeft = parseInt(margin) + "px"; } }; function getPaddingWidth(element) { return getPixelValue(element, element.currentStyle.paddingLeft) + getPixelValue(element, element.currentStyle.paddingRight); }; IE7.CSS.addRecalc("margin(-left|-right)?", "[^};]*auto", function(element) { if (register(fixMargin, element, element.parentElement && element.currentStyle.display == "block" && element.currentStyle.marginLeft == "auto" && element.currentStyle.position != "absolute")) { fixMargin(element); } }); addResize(function() { for (var i in fixMargin.elements) { var element = fixMargin.elements[i]; element.runtimeStyle.marginLeft = element.runtimeStyle.marginRight = ""; fixMargin(element); } }); }; // ========================================================================= // ie8-cssQuery.js // ========================================================================= IE7._isEmpty = function(element) { element = element.firstChild; while (element) { if (element.nodeType == 3 || (element.nodeType == 1 && element.nodeName != "!")) return false; element = element.nextSibling; } return true; }; IE7._isLang = function(element, code) { while (element && !element.getAttribute("lang")) element = element.parentNode; return element && new RegExp("^" + rescape(code), "i").test(element.getAttribute("lang")); }; function _nthChild(match, args, position, last) { // ugly but it works... last = /last/i.test(match) ? last + "+1-" : ""; if (!isNaN(args)) args = "0n+" + args; else if (args == "even") args = "2n"; else if (args == "odd") args = "2n+1"; args = args.split("n"); var a = args[0] ? (args[0] == "-") ? -1 : parseInt(args[0]) : 1; var b = parseInt(args[1]) || 0; var negate = a < 0; if (negate) { a = -a; if (a == 1) b++; } var query = format(a == 0 ? "%3%7" + (last + b) : "(%4%3-%2)%6%1%70%5%4%3>=%2", a, b, position, last, "&&", "%", "=="); if (negate) query = "!(" + query + ")"; return query; }; _PSEUDO_CLASSES = { "link": "e%1.currentStyle['ie7-link']=='link'", "visited": "e%1.currentStyle['ie7-link']=='visited'", "checked": "e%1.checked", "contains": "e%1.innerText.indexOf('%2')!=-1", "disabled": "e%1.isDisabled", "empty": "IE7._isEmpty(e%1)", "enabled": "e%1.disabled===false", "first-child": "!IE7._getPreviousElementSibling(e%1)", "lang": "IE7._isLang(e%1,'%2')", "last-child": "!IE7._getNextElementSibling(e%1)", "only-child": "!IE7._getPreviousElementSibling(e%1)&&!IE7._getNextElementSibling(e%1)", "target": "e%1.id==location.hash.slice(1)", "indeterminate": "e%1.indeterminate" }; // register a node and index its children IE7._register = function(element) { if (element.rows) { element.ie7_length = element.rows.length; element.ie7_lookup = "rowIndex"; } else if (element.cells) { element.ie7_length = element.cells.length; element.ie7_lookup = "cellIndex"; } else if (element.ie7_indexed != IE7._indexed) { var index = 0; var child = element.firstChild; while (child) { if (child.nodeType == 1 && child.nodeName != "!") { child.ie7_index = ++index; } child = child.nextSibling; } element.ie7_length = index; element.ie7_lookup = "ie7_index"; } element.ie7_indexed = IE7._indexed; return element; }; var keys = cssParser[_KEYS]; var pseudoClass = keys[keys.length - 1]; keys.length--; cssParser.merge({ ":not\\((\\*|[\\w-]+)?([^)]*)\\)": function(match, tagName, filters) { // :not pseudo class var replacement = (tagName && tagName != "*") ? format("if(e%1.nodeName=='%2'){", _index, tagName.toUpperCase()) : ""; replacement += cssParser.exec(filters); return "if(!" + replacement.slice(2, -1).replace(/\)\{if\(/g, "&&") + "){"; }, ":nth(-last)?-child\\(([^)]+)\\)": function(match, last, args) { // :nth-child pseudo classes _wild = false; last = format("e%1.parentNode.ie7_length", _index); var replacement = "if(p%1!==e%1.parentNode)p%1=IE7._register(e%1.parentNode);"; replacement += "var i=e%1[p%1.ie7_lookup];if(p%1.ie7_lookup!='ie7_index')i++;if("; return format(replacement, _index) + _nthChild(match, args, "i", last) + "){"; } }); keys.push(pseudoClass); // ========================================================================= // ie8-css.js // ========================================================================= var BRACKETS = "\\([^)]*\\)"; if (IE7.CSS.pseudoClasses) IE7.CSS.pseudoClasses += "|"; IE7.CSS.pseudoClasses += "before|after|last\\-child|only\\-child|empty|root|" + "not|nth\\-child|nth\\-last\\-child|contains|lang".split("|").join(BRACKETS + "|") + BRACKETS; // pseudo-elements can be declared with a double colon encoder.add(/::/, ":"); // ----------------------------------------------------------------------- // dynamic pseudo-classes // ----------------------------------------------------------------------- var Focus = new DynamicPseudoClass("focus", function(element) { var instance = arguments; IE7.CSS.addEventHandler(element, "onfocus", function() { Focus.unregister(instance); // in case it starts with focus Focus.register(instance); }); IE7.CSS.addEventHandler(element, "onblur", function() { Focus.unregister(instance); }); // check the active element for initial state if (element == document.activeElement) { Focus.register(instance) } }); var Active = new DynamicPseudoClass("active", function(element) { var instance = arguments; IE7.CSS.addEventHandler(element, "onmousedown", function() { Active.register(instance); }); }); // globally trap the mouseup event (thanks Martijn!) addEventHandler(document, "onmouseup", function() { var instances = Active.instances; for (var i in instances) Active.unregister(instances[i]); }); // :checked var Checked = new DynamicPseudoClass("checked", function(element) { if (typeof element.checked != "boolean") return; var instance = arguments; IE7.CSS.addEventHandler(element, "onpropertychange", function() { if (event.propertyName == "checked") { if (element.checked) Checked.register(instance); else Checked.unregister(instance); } }); // check current checked state if (element.checked) Checked.register(instance); }); // :enabled var Enabled = new DynamicPseudoClass("enabled", function(element) { if (typeof element.disabled != "boolean") return; var instance = arguments; IE7.CSS.addEventHandler(element, "onpropertychange", function() { if (event.propertyName == "disabled") { if (!element.isDisabled) Enabled.register(instance); else Enabled.unregister(instance); } }); // check current disabled state if (!element.isDisabled) Enabled.register(instance); }); // :disabled var Disabled = new DynamicPseudoClass("disabled", function(element) { if (typeof element.disabled != "boolean") return; var instance = arguments; IE7.CSS.addEventHandler(element, "onpropertychange", function() { if (event.propertyName == "disabled") { if (element.isDisabled) Disabled.register(instance); else Disabled.unregister(instance); } }); // check current disabled state if (element.isDisabled) Disabled.register(instance); }); // :indeterminate (Kevin Newman) var Indeterminate = new DynamicPseudoClass("indeterminate", function(element) { if (typeof element.indeterminate != "boolean") return; var instance = arguments; IE7.CSS.addEventHandler(element, "onpropertychange", function() { if (event.propertyName == "indeterminate") { if (element.indeterminate) Indeterminate.register(instance); else Indeterminate.unregister(instance); } }); IE7.CSS.addEventHandler(element, "onclick", function() { Indeterminate.unregister(instance); }); // clever Kev says no need to check this up front }); // :target var Target = new DynamicPseudoClass("target", function(element) { var instance = arguments; // if an element has a tabIndex then it can become "active". // The default is zero anyway but it works... if (!element.tabIndex) element.tabIndex = 0; // this doesn't detect the back button. I don't know how to do that :-( IE7.CSS.addEventHandler(document, "onpropertychange", function() { if (event.propertyName == "activeElement") { if (element.id && element.id == location.hash.slice(1)) Target.register(instance); else Target.unregister(instance); } }); // check the current location if (element.id && element.id == location.hash.slice(1)) Target.register(instance); }); // ----------------------------------------------------------------------- // IE7 pseudo elements // ----------------------------------------------------------------------- // constants var ATTR = /^attr/; var URL = /^url\s*\(\s*([^)]*)\)$/; var POSITION_MAP = { before0: "beforeBegin", before1: "afterBegin", after0: "afterEnd", after1: "beforeEnd" }; var PseudoElement = IE7.PseudoElement = Rule.extend({ constructor: function(selector, position, cssText) { // initialise object properties this.position = position; var content = cssText.match(PseudoElement.CONTENT), match, entity; if (content) { content = content[1]; match = content.split(/\s+/); for (var i = 0; (entity = match[i]); i++) { match[i] = ATTR.test(entity) ? {attr: entity.slice(5, -1)} : (entity.charAt(0) == "'") ? getString(entity) : decode(entity); } content = match; } this.content = content; // CSS text needs to be decoded immediately this.base(selector, decode(cssText)); }, init: function() { // execute the underlying css query for this class this.match = cssQuery(this.selector); for (var i = 0; i < this.match.length; i++) { var runtimeStyle = this.match[i].runtimeStyle; if (!runtimeStyle[this.position]) runtimeStyle[this.position] = {cssText:""}; runtimeStyle[this.position].cssText += ";" + this.cssText; if (this.content != null) runtimeStyle[this.position].content = this.content; } }, create: function(target) { var generated = target.runtimeStyle[this.position]; if (generated) { // copy the array of values var content = [].concat(generated.content || ""); for (var j = 0; j < content.length; j++) { if (typeof content[j] == "object") { content[j] = target.getAttribute(content[j].attr); } } content = content.join(""); var url = content.match(URL); var cssText = "overflow:hidden;" + generated.cssText.replace(/'/g, '"'); if (target.currentStyle.styleFloat != "none") { //cssText = cssText.replace(/display\s*:\s*block/, "display:inline-block"); } var position = POSITION_MAP[this.position + Number(target.canHaveChildren)]; var id = 'ie7_pseudo' + PseudoElement.count++; target.insertAdjacentHTML(position, format(PseudoElement.ANON, this.className, id, cssText, url ? "" : content)); if (url) { var pseudoElement = document.getElementById(id); pseudoElement.src = getString(url[1]); addFilter(pseudoElement, "crop"); } target.runtimeStyle[this.position] = null; } }, recalc: function() { if (this.content == null) return; for (var i = 0; i < this.match.length; i++) { this.create(this.match[i]); } }, toString: function() { return "." + this.className + "{display:inline}"; } }, { CONTENT: /content\s*:\s*([^;]*)(;|$)/, ANON: "%4", MATCH: /(.*):(before|after).*/, count: 0 }); // ========================================================================= // ie8-html.js // ========================================================================= var UNSUCCESSFUL = /^(submit|reset|button)$/; // ----------------------------------------------------------------------- // , which additionally defaults to calling the current continuation. Takes an additional argument, C, which can specify a default path to return to if there is no current continuation. =cut sub return { my $self = shift; my %args = (@_); # Fetch the current continuation or build a new one my $continuation = Jifty->web->request->continuation; if (not $continuation and $args{to}) { $continuation = Jifty::Continuation->new(request => Jifty::Request->new(path => $args{to})); } delete $args{to}; # Render a button that will call the continuation $self->button( call => $continuation, %args ); } =head1 NAMING METHODS These methods return the names of HTML form elements related to this action. =head2 register_name Returns the name of the "registration" query argument for this action in a web form. =cut sub register_name { my $self = shift; return 'J:A-' . (defined $self->order ? $self->order . "-" : "") .$self->moniker; } # prefixes a fieldname with a given prefix and follows it with the moniker sub _prefix_field { my $self = shift; my ($field_name, $prefix) = @_; return join("-", $prefix, $field_name, $self->moniker); } =head2 form_field_name ARGUMENT Turn one of this action's L into a fully qualified name; takes the name of the field as an argument. =cut sub form_field_name { my $self = shift; return $self->_prefix_field(shift, "J:A:F"); } =head2 fallback_form_field_name ARGUMENT Turn one of this action's L into a fully qualified "fallback" name; takes the name of the field as an argument. This is specifically to support checkboxes, which only show up in the query string if they are checked. Jifty creates a checkbox with the value of L as its name and a value of 1, and a hidden input with the value of L as its name and a value of 0; using this information, L can both determine if the checkbox was present at all in the form, as well as its true value. =cut sub fallback_form_field_name { my $self = shift; return $self->_prefix_field(shift, "J:A:F:F"); } =head2 error_div_id ARGUMENT Turn one of this action's L into the id for the div in which its errors live; takes name of the field as an argument. =cut sub error_div_id { my $self = shift; my $field_name = shift; return 'errors-' . $self->form_field_name($field_name); } =head2 warning_div_id ARGUMENT Turn one of this action's L into the id for the div in which its warnings live; takes name of the field as an argument. =cut sub warning_div_id { my $self = shift; my $field_name = shift; return 'warnings-' . $self->form_field_name($field_name); } =head2 canonicalization_note_div_id ARGUMENT Turn one of this action's L into the id for the div in which its canonicalization notes live; takes name of the field as an argument. =cut sub canonicalization_note_div_id { my $self = shift; my $field_name = shift; return 'canonicalization_note-' . $self->form_field_name($field_name); } =head1 VALIDATION METHODS =head2 argument_names Returns the list of argument names. This information is extracted from L. =cut sub argument_names { my $self = shift; my %arguments = %{ $self->arguments }; return ( sort { (($arguments{$a}->{'sort_order'} ||0 ) <=> ($arguments{$b}->{'sort_order'} || 0)) || (($arguments{$a}->{'name'} || '') cmp ($arguments{$b}->{'name'} ||'' )) || $a cmp $b } keys %arguments ); } =head2 _canonicalize_arguments Canonicalizes each of the L that this action knows about. This is done by calling L for each field described by L. =cut # XXX TODO: This is named with an underscore to prevent infinite # looping with arguments named "argument" or "arguments". We need a # better solution. sub _canonicalize_arguments { my $self = shift; # For each, canonicalize them all $self->_canonicalize_argument($_) for $self->argument_names; } =head2 _canonicalize_argument ARGUMENT Canonicalizes the value of an L. If the argument has an attribute named B, call the subroutine reference that attribute points points to. If it doesn't have a B attribute, but the action has a C> function, also invoke that function. If neither of those are true, by default canonicalize dates using _canonicalize_date Note that it is possible that a canonicalizer will be called multiple times on the same field -- canonicalizers should be careful to do nothing to already-canonicalized data. =cut # XXX TODO: This is named with an underscore to prevent infinite # looping with arguments named "argument" or "arguments". We need a # better solution. sub _canonicalize_argument { my $self = shift; my $field = shift; # Setup some variables my $field_info = $self->arguments->{$field}; my $value = $self->argument_value($field); my $default_method = 'canonicalize_' . $field; # XXX TODO: Do we really want to skip undef values? return unless defined $value; # Do we have a valid canonicalizer for this field? if ( $field_info->{canonicalizer} and defined &{ $field_info->{canonicalizer} } ) { # Run it, sucka $value = $field_info->{canonicalizer}->( $self, $value, $self->argument_values, $self->_extra_canonicalizer_args ); } # How about a method named canonicalize_$field? elsif ( $self->can($default_method) ) { # Run that, foo' $value = $self->$default_method( $value, $self->argument_values, $self->_extra_canonicalizer_args ); } # Or is it a date? elsif ( defined( $field_info->{render_as} ) && lc( $field_info->{render_as} ) eq 'date') { # Use the default date canonicalizer, Mr. T! $value = $self->_canonicalize_date( $value, $self->argument_values, $self->_extra_canonicalizer_args ); } $self->argument_value($field => $value); } =head2 _canonicalize_date DATE Parses and returns the date using L. =cut sub _canonicalize_date { my $self = shift; my $val = shift; return undef unless defined $val and $val =~ /\S/; return undef unless my $obj = Jifty::DateTime->new_from_string($val); return $obj->ymd; } =head2 _validate_arguments Validates the form fields. This is done by calling L for each field described by L =cut # XXX TODO: This is named with an underscore to prevent infinite # looping with arguments named "argument" or "arguments". We need a # better solution. sub _validate_arguments { my $self = shift; # Validate each argument $self->_validate_argument($_) for $self->argument_names; return $self->result->success; } =head2 _validate_argument ARGUMENT Validate your form fields. If the field C is mandatory, checks for a value. If the field has an attribute named B, call the subroutine reference validator points to. If the action doesn't have an explicit B attribute, but does have a C> function, invoke that function. =cut # XXX TODO: This is named with an underscore to prevent infinite # looping with arguments named "argument" or "arguments". We need a # better solution. sub _validate_argument { my $self = shift; my $field = shift; # Do nothing if we don't have a field name return unless $field; $self->log->debug(" validating argument $field"); # Do nothing if we don't know what that field is my $field_info = $self->arguments->{$field}; return unless $field_info; # Grab the current value my $value = $self->argument_value($field); # When it isn't even given, check if it's mandatory and whine about it if ( !defined $value || !length $value ) { if ( $field_info->{mandatory} and ($self->has_argument($field) or not defined $field_info->{default_value})) { return $self->validation_error( $field => _("You need to fill in the '%1' field", $field_info->{label} || $field) ); } } # If we have a set of allowed values, let's check that out. if ( $value && $field_info->{valid_values} ) { $self->_validate_valid_values($field => $value); # ... but still check through a validator function even if it's in the list return if $self->result->field_error($field); } # the validator method name is validate_$field my $default_validator = 'validate_' . $field; # Finally, fall back to running a validator sub if ( $field_info->{validator} and defined &{ $field_info->{validator} } ) { return $field_info->{validator}->( $self, $value, $self->argument_values, $self->_extra_validator_args ); } # Check to see if it's the validate_$field method instead and use that elsif ( $self->can($default_validator) ) { return $self->$default_validator( $value, $self->argument_values, $self->_extra_validator_args ); } # Check if we already have a failure for it, from some other field elsif ( $self->result->field_error($field) or $self->result->field_warning($field) ) { return 0; } # If none of the checks have failed so far, then it's ok else { return $self->validation_ok($field); } } =head2 _extra_validator_args Returns a list of extra arguments to pass to validators. By default, an empty hash reference, but subclasses can override it to pass, say, a better C. =cut sub _extra_validator_args { return {}; } =head2 _extra_canonicalizer_args Returns a list of extra arguments to pass to canonicalizers. By default, an empty hash reference, but subclasses can override it to pass, say, a better C. =cut sub _extra_canonicalizer_args { return {}; } =head2 _extra_autocompleter_args Returns a list of extra arguments to pass to autocompleters. By default, an empty hash reference, but subclasses can override it to pass, say, a better C. =cut sub _extra_autocompleter_args { return {}; } =head2 _autocomplete_argument ARGUMENT Get back a list of possible completions for C. The list should either be a list of scalar values or a list of hash references. Each hash reference must have a key named C. There can also additionally be a key named C