From jifty-commit at lists.jifty.org Sun Apr 1 08:41:41 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Sun Apr 1 08:42:30 2007 Subject: [Jifty-commit] r3078 - jifty/trunk/lib/Jifty Message-ID: <20070401124141.C65664D803F@diesel.bestpractical.com> Author: dpavlin Date: Sun Apr 1 08:41:39 2007 New Revision: 3078 Modified: jifty/trunk/lib/Jifty/JSON.pm Log: fix handling of multi-line data when encoded in JSON -- they should never wrap over multiple lines in generated output Modified: jifty/trunk/lib/Jifty/JSON.pm ============================================================================== --- jifty/trunk/lib/Jifty/JSON.pm (original) +++ jifty/trunk/lib/Jifty/JSON.pm Sun Apr 1 08:41:39 2007 @@ -73,7 +73,13 @@ local $JSON::Syck::SingleQuote = $args->{singlequote}; local $JSON::Syck::ImplicitUnicode = 1; - JSON::Syck::Dump($obj); + my $json = JSON::Syck::Dump($obj); + if (! $args->{singlequte}) { + $json =~ s/\n\n\n/\\n/gs; # fix syck bug + $json =~ s/\n/\\n/gs; # just to be safe + $json =~ s/\r/\\r/gs; + } + return $json; } # We should escape double-quotes somehow, so that we can guarantee @@ -101,7 +107,7 @@ local *JSON::Converter::_stringfy = sub { my $arg = shift; $arg =~ s/([\\\n'\r\t\f\b])/$esc{$1}/eg; - $arg =~ s/([\x00-\x07\x0b\x0e-\x1f])/'\\u00' . unpack('H2',$1)/eg; + $arg =~ s/([\x00-\x07\x0b\x0e-\x1f])/'\\u00' . unpack('H2',$1)/egs; return "'" . $arg ."'"; }; return JSON::objToJson($obj, $args); From jifty-commit at lists.jifty.org Sun Apr 1 14:32:16 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Sun Apr 1 14:32:21 2007 Subject: [Jifty-commit] r3079 - in jifty/trunk/plugins/DumpDispatcher/lib/Jifty/Plugin: . Message-ID: <20070401183216.2E55E4D803F@diesel.bestpractical.com> Author: dpavlin Date: Sun Apr 1 14:32:15 2007 New Revision: 3079 Removed: jifty/trunk/plugins/DumpDispatcher/lib/Jifty/Plugin/DumpDispatcher/ Modified: jifty/trunk/plugins/DumpDispatcher/lib/Jifty/Plugin/DumpDispatcher.pm Log: remove extra skeleton files, configuration example in pod Modified: jifty/trunk/plugins/DumpDispatcher/lib/Jifty/Plugin/DumpDispatcher.pm ============================================================================== --- jifty/trunk/plugins/DumpDispatcher/lib/Jifty/Plugin/DumpDispatcher.pm (original) +++ jifty/trunk/plugins/DumpDispatcher/lib/Jifty/Plugin/DumpDispatcher.pm Sun Apr 1 14:32:15 2007 @@ -4,12 +4,22 @@ package Jifty::Plugin::DumpDispatcher; use base qw/Jifty::Plugin/; -# Your plugin goes here. If takes any configuration or arguments, you -# probably want to override L. +=head1 NAME + +Jifty::Plugin::DumpDispatcher + +=head1 DESCRIPTION + +When activated in C with: + + Plugins: + - DumpDispatcher: {} + +it will dump all dispatcher rules in debug log. =head2 dump_rules -Dump all defined rules in debug log. It should be called by Jifty, after +Dump all defined rules in debug log. It is called by Jifty, after C<< Jifty->dispatcher->import_plugins >> on startup. =cut From jifty-commit at lists.jifty.org Mon Apr 2 01:22:09 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Mon Apr 2 01:22:16 2007 Subject: [Jifty-commit] r3080 - in jifty/trunk: . Message-ID: <20070402052209.A17D54D803F@diesel.bestpractical.com> Author: trs Date: Mon Apr 2 01:22:07 2007 New Revision: 3080 Modified: jifty/trunk/ (props changed) jifty/trunk/lib/Jifty/Manual/Cookbook.pod Log: r20560@zot: tom | 2007-04-02 01:21:31 -0400 * Make =head2 sections consistently titled * Add section on using models/actions outside of a Jifty app Modified: jifty/trunk/lib/Jifty/Manual/Cookbook.pod ============================================================================== --- jifty/trunk/lib/Jifty/Manual/Cookbook.pod (original) +++ jifty/trunk/lib/Jifty/Manual/Cookbook.pod Mon Apr 2 01:22:07 2007 @@ -125,7 +125,7 @@ zone appropriately. All dates are stored in UTC in the database, to ensure consistency. -=head2 How do I emulate 'created_on' field like Rails ? +=head2 Emulate 'created_on' field like Rails ? In Rails, if you have a field named 'created_on', it's automatically set to the creation time of the record. How can I emulate this @@ -154,7 +154,7 @@ $attr->{'created_on'} = DateTime->now; }; -=head2 How do I emulate 'updated_on' ? +=head2 Emulate 'updated_on' ? If a lot of column could change, you can override C<_set> method: @@ -254,7 +254,7 @@ pluralise or pluralises differently. -=head2 How do I perform ajax canonicalization on a given field ? +=head2 Perform ajax canonicalization on a given field ? Asking user to input something in a form is really common in a web app. For some certain form fields you want them to have a certain @@ -371,3 +371,20 @@ }; Otherwise, everything should work as expected. + +=head2 Reuse Jifty models and actions outside of a Jifty app + + use lib '/path/to/MyApp/lib'; + + use Jifty::Everything; + BEGIN { Jifty->new; } + + use MyApp::Model::Foo; + use MyApp::Action::FrobFoo; + +From there you can use the model and action to access your data and run your +actions like you normally would. + +If you've actually installed your app into C<@INC>, you can skip the +C line. + From jifty-commit at lists.jifty.org Tue Apr 3 02:25:59 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 02:26:15 2007 Subject: [Jifty-commit] r3081 - in jifty/trunk: . Message-ID: <20070403062559.592A14D80CE@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 02:25:58 2007 New Revision: 3081 Added: jifty/trunk/doc/talks/present-slides Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54413@dhcp207: jesse | 2007-04-03 15:25:32 +0900 * Next slides draft (and the tool to render them) Added: jifty/trunk/doc/talks/present-slides ============================================================================== --- (empty file) +++ jifty/trunk/doc/talks/present-slides Tue Apr 3 02:25:58 2007 @@ -0,0 +1,95 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; +use Term::ReadKey; +use Text::Autoformat; + +my $file = shift @ARGV; +my $handle; +open( $handle, "<$file" ) || die $!; + +my $datadata = join( '', <$handle> ); + +my @slides = split( /^----?\s*$/mi, $datadata ); +my $counter = 0; +my $slides_played = {}; + my $title; +while ( $counter <= $#slides ) { + my $mode = 'text'; + my ( $cols, $rows, undef, undef ) = GetTerminalSize(); + my $slide = $slides[$counter]; + my $console = Term::ANSIScreen->new; + $console->Cls; + $console->Cursor(1,1); + if ( $slide =~ s/^!\!\s*?(.*?)$//gm ) { + $title = $1; + } + if ($title) { + my $start = int ( ( $cols / 2 ) - ( length($title) / 2 ) ); + $console->Cursor($start,0); + chomp $title; + print "$title\n"; + } + + if ($slide =~ s/#\s*`(.*?)`//m) { + #my $cmd = $1; + #if(!$slides_played->{$counter} && ($slides_played->{$counter} = fork() )) { + #`$cmd>/dev/null 2>/dev/null`; + #} + } + if ( $slide =~ s/#\s*mode.*?perl.*?$//gms ) { + $mode = 'perl'; + } + if ( $mode eq 'text' and $slide ) { + $slide = autoformat $slide, { left => 1, right => ($cols), all => 1 }; + } + elsif ($mode eq 'perl') { + my $tidycols = $cols - 2; # squeeze for display + open my $out , ">/tmp/output.$$" || die $!; + print $out $slide || die $!; + close $out || die $!; + $slide = ` cat /tmp/output.$$ | source-highlight -s perl -f esc`; + #$slide = ` cat /tmp/output.$$ | perltidy -q -l $tidycols| source-highlight -s perl -f esc`; + } + + if ( $slide =~ /(\S+)\s*\n\s*(\S+)/m ) { + + print $slide; + } else { + chomp $slide; + $slide =~ s/(?:\n|\r)//g; + my $left = int ( ( $cols / 2 ) - ( length($slide) / 2 ) ); + if ($left < 0 ){ + $left = 0; + } + $console->Cursor( + $left, + int($rows/2)-1, + +); + print $slide."\n"; + } + + + $console->Cursor( 0, ( $rows - 1 ) ); + print "$counter/" . $#slides; + ReadMode 4; + my $key = ReadKey(0); + ReadMode 0; + if ( $key eq 'q' ) { + exit; + } + if ( $key =~ /^(?: |\n|n)/ ) { + $counter++; + } elsif ( $key eq 'r' ) { + next; + } else { + $counter--; + if ( $counter < 0 ) { + $counter = 0; + } + } +} + Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 02:25:58 2007 @@ -1,44 +1,88 @@ -* What are Domain Specific Languages - -* How did I get here? - - - Airplane, then Subway - - - All started at OSCON 2005 - - DHH demonstrated Rails migrations - - Looked very sexy - - Was very jealous - - "You can't do this in any other language" - - Never tell that to a Perl Hacker - - - Started sketching Jifty::DBI columns - - - Started with searchbuilder - - It was a big hash - - It was a big mess - - It was ugly - - - Spent about a month playing with syntaxes. - - +!!Jesse Vincent - Best Practical +Domain Specific Languages in Perl --- - +!!DSLs in Perl +DSLs are 'little languages' for specific programming tasks +--- +DSLs are easier to read +--- +DSLs are more expressive +--- +DSLs let you optimize your code for coding +--- +Mostly, I'm going to talk about "Englishy" DSLs +--- +Not all DSLs are Englishy +--- +- Excel Macros +- XML config files +- XSL-T +- GraphViz +--- +...but I've been on an Englishy DSL kick +--- +DSLs can be implemented in your 'host' language +--- +(These get called "internal" DSLs) +--- +DSLs can be implemented outside your 'host' langauge +--- +(External DSLs) +--- +Everything I'm going to talk about is Pure Perl (Internal) +--- +The Ruby community is big on DSLs +--- +You can make DSLs in Perl, too. +--- +(but it does take more work in Perl) +--- +!!How did I get here? +- Airplane +- Narita Express +- Subway +--- +- All started at OSCON 2005 +- DHH demonstrated Rails migrations +- Looked very sexy +- Was very jealous +- "You can't do this in any other language" +--- +Never say that to a Perl Hacker +--- +!!Jifty::DBI::Schema - The design process +- Started sketching Jifty::DBI columns +- Started with DBIx::SearchBuilder +- Columns were defined as a hash +- Hashes are ugly +--- +We spent about a month playing with syntax. +--- +Our first goal was "feels right" +--- +Our second goal was "we can implement this" +--- +I'm going to show you some of our design process +--- +(It's a mix of code and IRC) +--- +#mode perl $x = Jifty::DBI::SchemaBuilder->new; $x->define_blablalb $x->bla bla - - --- - +#mode perl our db_table 'addresses'; -our field name => { has_type 'varchar'; has_default 'frank' }; - -# (by the way, i'm pretty sure we don't get to do the sub-at-t-end thing -# either... I tried lots of hacky ways to get it working and failed.) - -# yeah, I think we're going to end up having a pseudo-sub that's really a hash behind the scenes +our field name => { + has_type 'varchar'; + has_default 'frank' +}; +--- + (by the way, i'm pretty sure we don't get to do the sub-at-the-end thing either... I tried lots of hacky ways to get it working and failed.) + yeah, I think we're going to end up having a pseudo-sub that's really a hash behind the scenes --- +#mode perl { my $s = Jifty::DBI::SG->import_functions; @@ -47,27 +91,33 @@ field bar; } # $s.DESTROY gets called and unimports db_table/field/... --- - +(This was astonishingly close to what we do today.) +--- +#mode perl my $schema = Jifty::DBI::RecordSchema->new; -$schema->for_class(__PACKAGE__); #just riffing +$schema->for_class(__PACKAGE__); -$schema->field name => { has_type 'varchar'; has_default 'Frank'} +$schema->field name => { + has_type 'varchar'; + has_default 'Frank' +} --- +#mode perl + BEGIN { @ISA = 'Jifty::DBI::Record' } use Jifty::DBI::Record; # but this sucks! use base qw/Jifty::DBI::Record/; -__PACKAGE__->schema_version (0.0001) # or some other method that -# does two thing evilly. +__PACKAGE__->schema_version (0.0001) +# (or some other method that does two thing evily). --- + we could tie @ISA -# we could tie @ISA - -# I'm kidding + ...I'm kidding --- - +#mode perl use base 'Jifty::DBI::Record'; Jifty::DBI::Record->___from_code(); @@ -75,59 +125,67 @@ field { called 'name'; # ? ---- - # but yeah, falls into the "works" category" - # and - has_type 'string' - # is definitely better than - type => 'string' - # in your book? ---- - # how would you do: - - refers_to_many RT::Tickets by 'owner'; +} +--- + is + + "has_type 'string'" + +definitely better than + + "type => 'string'" + +in your book? --- - - # hmm. i thought about this before. we can do like simon and - refers_to_many "RT::Tickets by owner"; - # but I don't really like that. parsing is lame. + how would you do: + + refers_to_many RT::Tickets by 'owner'; + + hmm. i thought about this before. we can do like simon and + + refers_to_many "RT::Tickets by owner"; + + but I don't really like that. parsing is lame. + + I'm *pretty* sure that we can't get the line you've written to compile. --- - # I'm *pretty* sure that we can't get the line you've written to compile. + I've got a bad perl5 idea for you. Robert claims it's impossible + + I'm trying to make the syntax "refers_to_many 'BTDT::Model::Tasks' by 'owner';" valid perl5 syntax. --- - # oh no, autrijus gave me the one line I needed. - - # don't forget that RT::Tickets is a class/package. - - # shit! it actually works!!! + well, that may be true but you don't want that. + + refers_to_many BTDT::Model::Tasks by 'owner' + + is more readable and easily implemented. + + sub by ($) { by => @_ } + + done! + + stop thinking classes as strings :) --- - - # the idea is that it just returns a key, val pair. so it doesn't matter. - - # well, right, but refers_to_many is being called in RT::Tickets - # instead of in the current package. but that's ok. ---- - 23:46 I've got a bad perl5 idea for you. Robert claims it's impossible -23:47 I'm trying to make the syntax "refers_to_many 'BTDT::Model::Tasks' by 'owner';" valid perl5 syntax. ---- -03:57 well, that may be true but you don't want that. -03:57 refers_to_many BTDT::Model::Tasks by 'owner' -03:57 is more readable and easily implemented. -03:58 sub by ($) { by => @_ } -03:58 done! -03:58 stop thinking classes as strings :) + shit! it actually works! --- - # so, now we're just still on the + +What we had left: - field foo => sub {}; issue - # let's see what the hash syntax looks like with my weird keys. - +the field foo => sub {}; issue --- +#mode perl + + # We wanted something that acted like this + # But without the ugly 'sub' keyword field email => sub { has_type 'varchar'; has_default 'Frank'; }; +--- +#mode perl +# We cculd do this, but it used a hash +# not a block field phone => { has_type 'varchar'; @@ -137,6 +195,10 @@ refers_to_a Sample::Employee; } --- +#mode perl + +# This is ugly and verbose + package Sample::Employee; use base qw/Jifty::DBI::Record/; @@ -147,61 +209,418 @@ __PACKAGE__->field dexterity => { has_type 'integer'}; -1; --- - - - Do we have notes from these? +!!In the end... +We ended up with Jifty::DBI columns +--- +#mode perl +use Jifty::DBI::Record schema { +column + auth_token => type is 'text', + render as 'Unrendered'; + +column score => type is 'int', + is immutable, + default is '0', + label is 'Score', + since is '0.0.7'; + +column time_zone => + label is 'Time zone', + since '0.0.12', + default is 'America/New_York', + valid are formatted_timezones(); +}; +--- +Implemented it twice +--- +!! +Take 1 +--- +!!Take 1: +Jifty::DBI::Schema +--- +Our first DSL in Perl +--- +We beat the parser into submission using: +- Clever function prototypes +- Injection of functions +--- +#mode perl +score => type is 'int', + is immutable, + default is '0', + render as 'text', + label is 'Score', + since is '0.0.7'; +--- +Prototype hacking +--- +#mode perl +sub is ($) { return shift }; +sub as ($) { return shift }; +sub since ($) { } +sub type ($) { } +sub render ($) {} +sub label ($) {} +sub default ($) {} +--- +#mode perl +score => type is 'int', + is immutable, + default is '0', + render as 'text', + label is 'Score', + since is '0.0.7'; - - Ended up with Jifty::DBI columns +# parses to: + type(is('int')), is('immutable'), default(is('0')), render(as('text')), label(is('Score')), since(is('0.0.7')); +--- +TODO: function injection +--- +!!Take 2: +Object::Declare +--- +#`mpg123 ~/katamari.mp3` +Katamari for Code +--- +#mode perl +use Jifty::DBI::Record schema { -* Object::Declare - - Sample usage - - Explanation of the sample usage's meaning - - Comparison with traditional code - - Why we like it - - Tricks we use to make it go - - Katamari Damacy Video - - Localized symbols - - copula - - - Explanation of how it works -* Template::Declare - - Sample usage - - Explanation of the sample usage's meaning - - Comparison with traditional code - - Why we like it - - perlish - - refactorable - - templates with class (inheritance) - - readable - - can balance parens - - if it doesn't have matched tags, it doesn't compile + column score => type is 'int', + is immutable, + render as 'text', + default is '0', + label is 'Score', + since is '0.0.7'; +}; - - Tricks we use to make it go - - - Our own method dispatch and inheritance tree - - $self hacking - - throwing insane things into the symbol table - - generating "tags" that take closures - - buffers - - Explanation of how it works +# parses as: + +'is'->type('int', + 'immutable'->is, + 'is'->default('0', + 'as'->render('text', + 'is'->label('Score', + 'is'->since('0.0.7'))))); +--- +What actually happens at compile time: + +- The 'schema' function in our baseclass takes a code block +- ...and returns a closure +- Jifty::DBI::Record::import takes over: +- it takes the closure +- it installs some methods... +- ...is::AUTOLOAD and UNIVERSAL::is and as::AUTOLOAD +- it runs the closure +- it removes its magic symbols + +--- +Template::Declare +--- +!!Template::Declare +Sample usage +--- +#mode perl +template '/pages/mypage.html' => sub { + html { + head {}; + body { + h1 {'Hey, this is text'}; + } + } +}; +--- +But! +Content! Templates! +Design! Code! +--- +OMGWTF!? THAT'S WRONG! +--- +The person who told you it's wrong was lying to you. +--- +We're perl hackers +--- +Why are we putting a minilanguage in our templates? +--- +This is not 1997 +--- +It's 2007. +--- +People use CSS for design now. +--- +Programmers still have to make templates +--- +Templates run like CODE +--- +Because they ARE code +--- +Let's use our PROGRAMMING tools to work with them. +--- +#mode perl +!!Refactoring + +template 'mypage.html' => page { + h1 { 'Two choices' }; + div { attr { class => 'item' }; + h2 { 'Item 1'}; + }; + div { attr { class => 'item' }; + h2 { 'Item 2'}; + }; +}; +--- +!!Refactoring +#mode perl + +template 'mypage.html' => page { + h1 { 'Two choices' }; + for ("Item 1", "Item 2") { item($_); } +}; + +sub item { + my $content = shift; + return + div { attr { class => 'item' }; + h2 {$content}; + }; + +} +--- +We can refactor templates! +--- +Have you ever tried to refactor HTML? +--- +Our HTML is magically valid. +(Syntax errors are...Syntax Errors) +--- +Inheritance +--- +Mixins +--- +Tricks we use +--- +!!Stashing our templates +#mode perl +template '/foo/index.html' => sub {... }; +--- +'sub template' takes a name and a coderef. +--- +But where do we put these? +--- +We need a global stash. +--- +It needs to be per package +(Don't want to mix things together) +--- +Basically, we need a symbol table. +--- +It's Perl. +--- +We have THE symbol table. +--- +But you can have characters in URLS you can't have in sub names. Oh no! +--- +Actually, Perl doesn't care. +--- +#mode perl + no strict 'refs'; + *{ $class . '::' . $subname } = $coderef;} +--- +That just works. +--- +Even if your subroutine is named './\\foo!!<>' +--- +But how do you call it? +--- +# perldoc UNIVERSAL + +CLASS->can( METHOD ) +"can" checks if the object or class has a method called "METHOD". +If it does then a reference to the sub is returned. +--- +!!Closures +Now, about that syntax. +--- +HTML tags take blocks +of content. +--- +Our tag methods take +blocks. (Of perl) +--- +#mode perl +sub h1 (&;$) { + my $code = shift; + + ... + + if (defined wantarray) { + return $closure_around_$code; + } else { + # Actually do our work and run $code + } +} +--- +!!Not everything is roses +(Here's where it all goes wrong) +--- +HTML Attributes +--- +# mode perl +# What we've got: + +div { + attr { id => 'my-div'}; + ... +}; + +# and + +with ( id => 'my-div'), div { +... +}; +--- +# mode perl +# What I think I'd like: +div ( id => 'my-div' ), { +... +} +--- +So, what's the big problem? +--- +Just change the prototype. +--- +In Perl, the (&) in a prototype +may ONLY come first. +--- +ORZ +--- +Not covering: + +- Our own method dispatch and inheritance tree +- $self hacking +- buffers -* Test::WWW::Declare - - Sample usage +--- +Test::WWW::Declare +--- +!!Test::WWW::Declare +Web test scripts are UGLY +--- +- Simple, declarative web testing +- Easy to read +- Easy to write +- Looks more like what users do +--- +#mode perl +my $server=Jifty::Test->make_server; +isa_ok($server, 'Jifty::Server'); +my $URL = $server->started_ok; +my $mech = Jifty::Test::WWW::Mechanize->new; +$mech->get_html_ok($URL); +like($mech->uri, qr{splash}, 'Redirected to splash page'); +--- +The insides are great +--- +The syntax ain't +--- +We built on Test::More and WWW::Mechanize +--- +#mode perl +session "check logins" => run { + flow "basic connectivity" => check { + get 'http://fsck.com'; + content should match qr{fsck.com}; + click href qr{book}; + content should match qr{RT Essentials}i; + }; +}; +--- +In early development +--- +- Sample usage - Explanation of the sample usage's meaning - Comparison with traditional code - Why we like it - - Tricks we use to make it go +--- +- Tricks we use to make it go +--- + +session "check logins" => run { + flow "basic connectivity" => check { + get 'http://fsck.com'; + content should match qr{fsck.com}; + click href qr{book}; + content should match qr{RT Essentials}i; + + + }; +}; + +--- +Why do we make this valid syntax? + content should match qr{RT Essentials}i; +--- +Readability +--- +Understandability +--- +It feels English-y. +--- + +content should match qr{RT Essentials}i; + + vs + +ok($req->content =~ /RT Essentials/i); + +--- + +How do we make this valid perl? + content should match qr{RT Essentials}i; +--- + - Prototypes - - eval - - custom test functions - - Explanation of how it works - +--- +sub match ($) { + return shift; +} +--- +sub should ($) { + my $item = shift; + return $item; +} +--- +sub content ($) { + my $regex = shift; + unless ( mech()->content =~ /$regex/ ) { + die "Content did not match $regex"; + } +} +--- + - eval, the (&) prototype and custom test functions +--- + check { + # do stuff that won't fail + }; +--- * Other interesting usages of DSLs in Perl + + +--- +Problems with DSLs +--- +Debugging can get harder +--- +Editors can get confused +--- +Hackers can get confused +--- + From jifty-commit at lists.jifty.org Tue Apr 3 02:51:00 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 02:51:02 2007 Subject: [Jifty-commit] r3082 - in wifty/trunk: lib/Wifty Message-ID: <20070403065100.A14EE4D815B@diesel.bestpractical.com> Author: clkao Date: Tue Apr 3 02:50:59 2007 New Revision: 3082 Added: wifty/trunk/lib/Wifty/View-not-ready-yet.pm - copied unchanged from r2306, /wifty/trunk/lib/Wifty/View.pm Removed: wifty/trunk/lib/Wifty/View.pm Modified: wifty/trunk/ (props changed) Log: merge from trs' local r20558@ubuntu: tom | 2007-04-02 06:51:03 +0900 Move Wifty::View so that it isn't automatically loaded. It's not ready for use yet (still contains much early TD syntax). From jifty-commit at lists.jifty.org Tue Apr 3 03:52:08 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 03:52:12 2007 Subject: [Jifty-commit] r3083 - in jifty/trunk: . Message-ID: <20070403075208.C48C54D8004@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 03:52:07 2007 New Revision: 3083 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54417@dhcp207: jesse | 2007-04-03 16:51:42 +0900 * ok. mostly ready Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Tue Apr 3 03:52:07 2007 @@ -5,21 +5,16 @@ use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; use Term::ReadKey; use Text::Autoformat; +our @SLIDES; -my $file = shift @ARGV; -my $handle; -open( $handle, "<$file" ) || die $!; - -my $datadata = join( '', <$handle> ); - -my @slides = split( /^----?\s*$/mi, $datadata ); +load_slides(); my $counter = 0; my $slides_played = {}; my $title; -while ( $counter <= $#slides ) { +while ( $counter <= $#SLIDES ) { my $mode = 'text'; my ( $cols, $rows, undef, undef ) = GetTerminalSize(); - my $slide = $slides[$counter]; + my $slide = $SLIDES[$counter]; my $console = Term::ANSIScreen->new; $console->Cls; $console->Cursor(1,1); @@ -34,10 +29,10 @@ } if ($slide =~ s/#\s*`(.*?)`//m) { - #my $cmd = $1; - #if(!$slides_played->{$counter} && ($slides_played->{$counter} = fork() )) { - #`$cmd>/dev/null 2>/dev/null`; - #} + my $cmd = $1; + if(!$slides_played->{$counter}) { + `$cmd>/dev/null 2>/dev/null &`; + $slides_played->{$counter}++} } if ( $slide =~ s/#\s*mode.*?perl.*?$//gms ) { $mode = 'perl'; @@ -55,7 +50,8 @@ } if ( $slide =~ /(\S+)\s*\n\s*(\S+)/m ) { - + my $lines = scalar split(/\n/,$slide); + $console->Cursor(0, int(($rows/2)-($lines/2))-1); print $slide; } else { chomp $slide; @@ -64,17 +60,13 @@ if ($left < 0 ){ $left = 0; } - $console->Cursor( - $left, - int($rows/2)-1, - -); + $console->Cursor( $left, int($rows/2)-1, ); print $slide."\n"; } $console->Cursor( 0, ( $rows - 1 ) ); - print "$counter/" . $#slides; + print "$counter/" . $#SLIDES; ReadMode 4; my $key = ReadKey(0); ReadMode 0; @@ -84,7 +76,9 @@ if ( $key =~ /^(?: |\n|n)/ ) { $counter++; } elsif ( $key eq 'r' ) { + load_slides(); next; + } else { $counter--; if ( $counter < 0 ) { @@ -93,3 +87,12 @@ } } +sub load_slides { +my $file = $ARGV[0]; +my $handle; +open( $handle, "<$file" ) || die $!; + +my $datadata = join( '', <$handle> ); + + @SLIDES = split( /^----?\s*$/mi, $datadata ); +} Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 03:52:07 2007 @@ -1,7 +1,7 @@ !!Jesse Vincent - Best Practical Domain Specific Languages in Perl --- -!!DSLs in Perl +!!A bit about DSLs DSLs are 'little languages' for specific programming tasks --- DSLs are easier to read @@ -249,6 +249,7 @@ - Injection of functions --- #mode perl +# The syntax we wanted score => type is 'int', is immutable, default is '0', @@ -256,7 +257,18 @@ label is 'Score', since is '0.0.7'; --- -Prototype hacking +#mode perl +How it parsed +'is'->type('int', + 'immutable'->is, + 'is'->default('0', + 'as'->render('text', + 'is'->label('Score', + 'is'->since('0.0.7'))))); +--- +How can we fix that? +--- +Prototype hacking! --- #mode perl sub is ($) { return shift }; @@ -276,11 +288,18 @@ label is 'Score', since is '0.0.7'; -# parses to: +# Now this parses like this: - type(is('int')), is('immutable'), default(is('0')), render(as('text')), label(is('Score')), since(is('0.0.7')); ---- -TODO: function injection + type(is('int')), + is('immutable'), + default(is('0')), + render(as('text')), + label(is('Score')), + since(is('0.0.7')); +--- +Downsides +- Limited flexibility +- Needs new functions for every attribute --- !!Take 2: Object::Declare @@ -317,6 +336,7 @@ - it installs some methods... - ...is::AUTOLOAD and UNIVERSAL::is and as::AUTOLOAD - it runs the closure +- it hands the result off to a method of your choice - it removes its magic symbols --- @@ -384,9 +404,9 @@ sub item { my $content = shift; - return - div { attr { class => 'item' }; - h2 {$content}; + div { + attr { class => 'item' }; + h2 {$content}; }; } @@ -398,12 +418,6 @@ Our HTML is magically valid. (Syntax errors are...Syntax Errors) --- -Inheritance ---- -Mixins ---- -Tricks we use ---- !!Stashing our templates #mode perl template '/foo/index.html' => sub {... }; @@ -446,11 +460,11 @@ !!Closures Now, about that syntax. --- -HTML tags take blocks -of content. +HTML tags take blocks of content. +--- +Our tag methods take blocks of perl. --- -Our tag methods take -blocks. (Of perl) +They return closures when you want them to --- #mode perl sub h1 (&;$) { @@ -465,6 +479,14 @@ } } --- +We install methods for all the HTML tags +--- +#mode perl +use CGI (); +install_tag($_) for ( @CGI::EXPORT_TAGS{ + qw/:html2 :html3 :html4 :netscape :form/} +); +--- !!Not everything is roses (Here's where it all goes wrong) --- @@ -500,24 +522,28 @@ --- ORZ --- -Not covering: - -- Our own method dispatch and inheritance tree -- $self hacking -- buffers - +Can anybody help me? --- +!! Test::WWW::Declare --- !!Test::WWW::Declare +In early development +--- +It might change +--- Web test scripts are UGLY --- +Test::WWW::Declare is PRETTY +--- - Simple, declarative web testing - Easy to read - Easy to write - Looks more like what users do --- #mode perl +# Test::WWW::Mechanize + my $server=Jifty::Test->make_server; isa_ok($server, 'Jifty::Server'); my $URL = $server->started_ok; @@ -532,70 +558,68 @@ We built on Test::More and WWW::Mechanize --- #mode perl -session "check logins" => run { - flow "basic connectivity" => check { - get 'http://fsck.com'; - content should match qr{fsck.com}; - click href qr{book}; - content should match qr{RT Essentials}i; - }; + +# Test::WWW::Declare + +session "search" => run { + flow "google searches work" => check { + get 'http://google.com/ncr'; + fill form 'f' => { q => 'Squeamish ossifrage' }; + click button 'Google Search'; + } }; --- -In early development +Regular tests keep running on failure --- -- Sample usage - - Explanation of the sample usage's meaning - - Comparison with traditional code - - Why we like it +Makes no sense when a failure means you lose context --- -- Tricks we use to make it go +Every 'check' block aborts on failure --- - +Abort means 'failing test' +--- +Every named 'session' gets its own cookie jar and WWW::Mechanize +--- +#mode perl session "check logins" => run { flow "basic connectivity" => check { get 'http://fsck.com'; content should match qr{fsck.com}; click href qr{book}; content should match qr{RT Essentials}i; - - }; }; - ---- -Why do we make this valid syntax? - content should match qr{RT Essentials}i; ---- -Readability --- -Understandability +What's the weird syntax? --- -It feels English-y. +# mode perl +content should match qr{RT Essentials}i; --- - +#mode perl content should match qr{RT Essentials}i; - vs +# vs ok($req->content =~ /RT Essentials/i); - --- +# mode perl +# How do we make this valid perl? -How do we make this valid perl? - content should match qr{RT Essentials}i; +content should match qr{RT Essentials}i; --- - - - Prototypes +Prototypes --- +#mode perl sub match ($) { return shift; } --- +#mode perl sub should ($) { my $item = shift; return $item; } --- +#mode perl sub content ($) { my $regex = shift; unless ( mech()->content =~ /$regex/ ) { @@ -603,24 +627,18 @@ } } --- - - eval, the (&) prototype and custom test functions +!!Conclusion +Creating DSLs is lots of fun --- - check { - # do stuff that won't fail - }; +Creating DSLs can be a lot of work --- - - -* Other interesting usages of DSLs in Perl - - +Creating DSLs helps you learn Perl internals --- -Problems with DSLs +Creating DSLs helps find bugs in Perl --- -Debugging can get harder +DSLs can make coding more fun --- -Editors can get confused +Challenge: CPAN some Japanese DSLs --- -Hackers can get confused +Thanks --- - From jifty-commit at lists.jifty.org Tue Apr 3 04:23:04 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 04:23:06 2007 Subject: [Jifty-commit] r3084 - in jifty/trunk: . Message-ID: <20070403082304.600F34D8004@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 04:23:03 2007 New Revision: 3084 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54420@dhcp207: jesse | 2007-04-03 17:22:40 +0900 * tidy Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Tue Apr 3 04:23:03 2007 @@ -38,7 +38,7 @@ $mode = 'perl'; } if ( $mode eq 'text' and $slide ) { - $slide = autoformat $slide, { left => 1, right => ($cols), all => 1 }; + $slide = autoformat $slide, { left => 1, right => ($cols-3), all => 1 }; } elsif ($mode eq 'perl') { my $tidycols = $cols - 2; # squeeze for display Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 04:23:03 2007 @@ -117,6 +117,10 @@ ...I'm kidding --- + we could tie the symbol table + + ...It just doesn't work +--- #mode perl use base 'Jifty::DBI::Record'; Jifty::DBI::Record->___from_code(); @@ -281,14 +285,7 @@ --- #mode perl -score => type is 'int', - is immutable, - default is '0', - render as 'text', - label is 'Score', - since is '0.0.7'; - -# Now this parses like this: +# Now it parses like this: type(is('int')), is('immutable'), @@ -317,7 +314,8 @@ label is 'Score', since is '0.0.7'; }; - +--- +# mode perl # parses as: 'is'->type('int', @@ -327,6 +325,12 @@ 'is'->label('Score', 'is'->since('0.0.7'))))); --- +Why fight the parser? +--- +Perl gives us all the rope we need +--- +UNIVERSAL:: and ::AUTOLOAD +--- What actually happens at compile time: - The 'schema' function in our baseclass takes a code block @@ -343,7 +347,7 @@ Template::Declare --- !!Template::Declare -Sample usage +What it looks like --- #mode perl template '/pages/mypage.html' => sub { @@ -369,7 +373,7 @@ --- This is not 1997 --- -It's 2007. +It's 2007 --- People use CSS for design now. --- From jifty-commit at lists.jifty.org Tue Apr 3 04:45:09 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 04:45:12 2007 Subject: [Jifty-commit] r3085 - in jifty/trunk: . Message-ID: <20070403084509.2B38F4D80CE@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 04:45:09 2007 New Revision: 3085 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54422@dhcp207: jesse | 2007-04-03 17:44:46 +0900 intro slides Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 04:45:09 2007 @@ -50,7 +50,11 @@ --- Never say that to a Perl Hacker --- +Jifty::DBI::Schema +--- !!Jifty::DBI::Schema - The design process +Delarative Syntax for an Object Relational Mapper +--- - Started sketching Jifty::DBI columns - Started with DBIx::SearchBuilder - Columns were defined as a hash @@ -347,6 +351,8 @@ Template::Declare --- !!Template::Declare +A pure Perl Templating Language +--- What it looks like --- #mode perl @@ -532,6 +538,9 @@ Test::WWW::Declare --- !!Test::WWW::Declare +--- +A language for testing web applications +--- In early development --- It might change From jifty-commit at lists.jifty.org Tue Apr 3 04:47:08 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 04:47:09 2007 Subject: [Jifty-commit] r3086 - jifty/trunk/lib/Jifty/Plugin/Authentication/Password Message-ID: <20070403084708.0D5BC4D80E6@diesel.bestpractical.com> Author: audreyt Date: Tue Apr 3 04:47:07 2007 New Revision: 3086 Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/View.pm Log: * dedebugbug. Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password/View.pm ============================================================================== --- jifty/trunk/lib/Jifty/Plugin/Authentication/Password/View.pm (original) +++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password/View.pm Tue Apr 3 04:47:07 2007 @@ -96,7 +96,6 @@ h2 { _('Send a link to reset your password') }; outs( _( "You lost your password. A link to reset it will be sent to the following email address:")); - outs($next); my $focused = 0; Jifty->web->form->start( call => $next ); render_param( $action => $_, focus => $focused++ ? 0 : 1 ) for ( $action->argument_names ); From jifty-commit at lists.jifty.org Tue Apr 3 05:11:01 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 05:11:05 2007 Subject: [Jifty-commit] r3087 - in jifty/trunk: lib/Jifty Message-ID: <20070403091101.E05BF4D80CE@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 05:10:58 2007 New Revision: 3087 Modified: jifty/trunk/ (props changed) jifty/trunk/lib/Jifty/Config.pm jifty/trunk/lib/Jifty/Record.pm Log: r54424@dhcp207: jesse | 2007-04-03 18:09:49 +0900 * added a "SkipAccessControl" framework directive Modified: jifty/trunk/lib/Jifty/Config.pm ============================================================================== --- jifty/trunk/lib/Jifty/Config.pm (original) +++ jifty/trunk/lib/Jifty/Config.pm Tue Apr 3 05:10:58 2007 @@ -239,6 +239,7 @@ framework => { AdminMode => 1, DevelMode => 1, + SkipAccessControl => 0, ApplicationClass => $app_class, TemplateClass => $app_class."::View", ApplicationName => $app_name, Modified: jifty/trunk/lib/Jifty/Record.pm ============================================================================== --- jifty/trunk/lib/Jifty/Record.pm (original) +++ jifty/trunk/lib/Jifty/Record.pm Tue Apr 3 05:10:58 2007 @@ -197,6 +197,11 @@ sub current_user_can { my $self = shift; my $right = shift; + + if (Jifty->config->framework('SkipAccessControl')) { + return 1; + } + if ( $self->current_user->is_bootstrap_user or $self->current_user->is_superuser ) From jifty-commit at lists.jifty.org Tue Apr 3 05:50:54 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 05:50:57 2007 Subject: [Jifty-commit] r3088 - in jifty/trunk/lib: . Jifty Message-ID: <20070403095054.324B94D80E5@diesel.bestpractical.com> Author: audreyt Date: Tue Apr 3 05:50:52 2007 New Revision: 3088 Modified: jifty/trunk/lib/Jifty.pm jifty/trunk/lib/Jifty/Plugin.pm jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm Log: * Jifty::Plugin - Authentication::Password now auto-loads LetMe and User. Modified: jifty/trunk/lib/Jifty.pm ============================================================================== --- jifty/trunk/lib/Jifty.pm (original) +++ jifty/trunk/lib/Jifty.pm Tue Apr 3 05:50:52 2007 @@ -164,12 +164,18 @@ # Set up plugins my @plugins; - for my $plugin (@{Jifty->config->framework('Plugins')}) { + my @plugins_to_load = @{Jifty->config->framework('Plugins')}; + for (my $i = 0; my $plugin = $plugins_to_load[$i]; $i++) { my $class = "Jifty::Plugin::".(keys %{$plugin})[0]; my %options = %{ $plugin->{(keys %{$plugin})[0]} }; Jifty::Util->require($class); Jifty::ClassLoader->new(base => $class)->require; - push @plugins, $class->new(%options); + my $plugin_obj = $class->new(%options); + push @plugins, $plugin_obj; + foreach my $name ($plugin_obj->prereq_plugins) { + next if grep { $_ eq $name } @plugins_to_load; + push @plugins_to_load, {$name => {}}; + } } Jifty->plugins(@plugins); Modified: jifty/trunk/lib/Jifty/Plugin.pm ============================================================================== --- jifty/trunk/lib/Jifty/Plugin.pm (original) +++ jifty/trunk/lib/Jifty/Plugin.pm Tue Apr 3 05:50:52 2007 @@ -174,4 +174,14 @@ return $class."::Dispatcher"; } +=head2 prereq_plugins + +Returns an array of plugin module names that this plugin depends on. + +=cut + +sub prereq_plugins { + return (); +} + 1; Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm ============================================================================== --- jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm (original) +++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm Tue Apr 3 05:50:52 2007 @@ -21,4 +21,8 @@ =cut +sub prereq_plugins { + return ('User', 'LetMe'); +} + 1; From jifty-commit at lists.jifty.org Tue Apr 3 06:13:18 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 06:13:54 2007 Subject: [Jifty-commit] r3089 - in jifty/trunk: lib/Jifty/Plugin/Authentication t/TestApp-Plugin-PasswordAuth/etc Message-ID: <20070403101318.F36BA4D8166@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 06:12:52 2007 New Revision: 3089 Modified: jifty/trunk/ (props changed) jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm jifty/trunk/t/TestApp-Plugin-PasswordAuth/etc/config.yml Log: r54430@dhcp207: jesse | 2007-04-03 19:11:02 +0900 * pod fixes * update tests to take advantage of audrey's new feature (plugin deps) Modified: jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm ============================================================================== --- jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm (original) +++ jifty/trunk/lib/Jifty/Plugin/Authentication/Password.pm Tue Apr 3 06:12:52 2007 @@ -21,6 +21,14 @@ =cut + +=head2 prereq_plugins + +This plugin depends on the C and C plugins. + +=cut + + sub prereq_plugins { return ('User', 'LetMe'); } Modified: jifty/trunk/t/TestApp-Plugin-PasswordAuth/etc/config.yml ============================================================================== --- jifty/trunk/t/TestApp-Plugin-PasswordAuth/etc/config.yml (original) +++ jifty/trunk/t/TestApp-Plugin-PasswordAuth/etc/config.yml Tue Apr 3 06:12:52 2007 @@ -22,7 +22,6 @@ - %log/mail.log% Plugins: - - User: {} - Authentication::Password: {} - REST: {} From jifty-commit at lists.jifty.org Tue Apr 3 21:31:59 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 21:32:30 2007 Subject: [Jifty-commit] r3090 - in jifty/trunk: . Message-ID: <20070404013159.5F6284D8004@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 21:31:57 2007 New Revision: 3090 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54432@pinglin-2: jesse | 2007-04-04 10:10:29 +0900 * More tweaking Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Tue Apr 3 21:31:57 2007 @@ -18,7 +18,7 @@ my $console = Term::ANSIScreen->new; $console->Cls; $console->Cursor(1,1); - if ( $slide =~ s/^!\!\s*?(.*?)$//gm ) { + if ( $slide =~ s/^#\s*title\s*?(.*?)$//gm ) { $title = $1; } if ($title) { @@ -38,7 +38,7 @@ $mode = 'perl'; } if ( $mode eq 'text' and $slide ) { - $slide = autoformat $slide, { left => 1, right => ($cols-3), all => 1 }; + $slide = autoformat $slide, { left => 1, right => ($cols-1), all => 1 }; } elsif ($mode eq 'perl') { my $tidycols = $cols - 2; # squeeze for display Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 21:31:57 2007 @@ -1,7 +1,7 @@ -!!Jesse Vincent - Best Practical +#title Jesse Vincent - Best Practical Domain Specific Languages in Perl --- -!!A bit about DSLs +#title A bit about DSLs DSLs are 'little languages' for specific programming tasks --- DSLs are easier to read @@ -14,10 +14,13 @@ --- Not all DSLs are Englishy --- -- Excel Macros -- XML config files -- XSL-T -- GraphViz +Excel Macros +--- +XML config files +--- +XSL-T +--- +GraphViz --- ...but I've been on an Englishy DSL kick --- @@ -33,32 +36,67 @@ --- The Ruby community is big on DSLs --- -You can make DSLs in Perl, too. +You can make DSLs in Perl, too --- (but it does take more work in Perl) --- -!!How did I get here? -- Airplane -- Narita Express -- Subway ---- -- All started at OSCON 2005 -- DHH demonstrated Rails migrations -- Looked very sexy -- Was very jealous -- "You can't do this in any other language" +#title How did I get here? +Airplane +--- +Narita Express +--- +Subway +--- +Ok, How'd I really get here? +--- +All started at OSCON 2005 +--- +DHH demonstrated Rails migrations +--- +Looked very sexy +--- +Was very jealous +--- +"You can't do this in any other language" --- Never say that to a Perl Hacker --- +#title agenda +We've made some DSLs +--- +One for declaring database schema +--- +(I thought Rails did more. But I never read the manual) +--- +(It does a lot more than Rails migrations) +--- +One for web templating +--- +(Yes, another web templating system) +--- +(Hopefully, this one will provide some closure) +--- +(You'll see) +--- +One for making web testing easier +--- +(It's VERY beta) +--- +(Perfect for Web 2.0) +--- +#title Jifty::DBI::Schema --- -!!Jifty::DBI::Schema - The design process +#title Jifty::DBI::Schema - The design process Delarative Syntax for an Object Relational Mapper --- -- Started sketching Jifty::DBI columns -- Started with DBIx::SearchBuilder -- Columns were defined as a hash -- Hashes are ugly +Started sketching Jifty::DBI columns +--- +Started with DBIx::SearchBuilder +--- +Columns were defined as a hash +--- +Hashes are ugly --- We spent about a month playing with syntax. --- @@ -218,7 +256,7 @@ __PACKAGE__->field dexterity => { has_type 'integer'}; --- -!!In the end... +#title In the end... We ended up with Jifty::DBI columns --- @@ -244,10 +282,10 @@ --- Implemented it twice --- -!! +#title Take 1 --- -!!Take 1: +#title Take 1: Jifty::DBI::Schema --- Our first DSL in Perl @@ -258,6 +296,7 @@ --- #mode perl # The syntax we wanted + score => type is 'int', is immutable, default is '0', @@ -266,7 +305,8 @@ since is '0.0.7'; --- #mode perl -How it parsed +# perl -MO=Deparse parses that as: + 'is'->type('int', 'immutable'->is, 'is'->default('0', @@ -289,7 +329,7 @@ --- #mode perl -# Now it parses like this: +# Now, perl -MO=Deparse parses that as: type(is('int')), is('immutable'), @@ -302,7 +342,7 @@ - Limited flexibility - Needs new functions for every attribute --- -!!Take 2: +#title Take 2: Object::Declare --- #`mpg123 ~/katamari.mp3` @@ -320,7 +360,7 @@ }; --- # mode perl -# parses as: +# perl -MO=Deparse parses that as: 'is'->type('int', 'immutable'->is, @@ -337,20 +377,33 @@ --- What actually happens at compile time: -- The 'schema' function in our baseclass takes a code block -- ...and returns a closure -- Jifty::DBI::Record::import takes over: -- it takes the closure -- it installs some methods... -- ...is::AUTOLOAD and UNIVERSAL::is and as::AUTOLOAD -- it runs the closure -- it hands the result off to a method of your choice -- it removes its magic symbols - --- +The 'schema' function in our baseclass takes a code block +--- +...and returns a closure +--- +Jifty::DBI::Record::import takes over: +--- +it takes the closure +--- +it installs some methods... +--- +...is::AUTOLOAD and UNIVERSAL::is and as::AUTOLOAD +--- +it runs the closure +--- +it hands the result off to a method of your choice +--- +it removes its magic symbols +--- +...and then your program gets control back +--- +That's Jifty::DBI::Schema. +--- +#title Template::Declare --- -!!Template::Declare +#title Template::Declare A pure Perl Templating Language --- What it looks like @@ -366,7 +419,9 @@ }; --- But! +--- Content! Templates! +--- Design! Code! --- OMGWTF!? THAT'S WRONG! @@ -375,7 +430,7 @@ --- We're perl hackers --- -Why are we putting a minilanguage in our templates? +Why are we writing our templates in another language? --- This is not 1997 --- @@ -389,10 +444,10 @@ --- Because they ARE code --- -Let's use our PROGRAMMING tools to work with them. +Let's use our CODING tools to work with them. --- #mode perl -!!Refactoring +#title Refactoring template 'mypage.html' => page { h1 { 'Two choices' }; @@ -404,7 +459,7 @@ }; }; --- -!!Refactoring +#title Refactoring #mode perl template 'mypage.html' => page { @@ -428,11 +483,11 @@ Our HTML is magically valid. (Syntax errors are...Syntax Errors) --- -!!Stashing our templates +#title Stashing our templates #mode perl template '/foo/index.html' => sub {... }; --- -'sub template' takes a name and a coderef. +'sub template' takes a name and a coderef --- But where do we put these? --- @@ -441,15 +496,15 @@ It needs to be per package (Don't want to mix things together) --- -Basically, we need a symbol table. +Basically, we need a symbol table --- -It's Perl. +It's Perl --- -We have THE symbol table. +We have THE symbol table --- -But you can have characters in URLS you can't have in sub names. Oh no! +But URLs can have characters that are illegal in sub names. :/ --- -Actually, Perl doesn't care. +Actually, Perl doesn't care --- #mode perl no strict 'refs'; @@ -457,7 +512,7 @@ --- That just works. --- -Even if your subroutine is named './\\foo!!<>' +Even if your sub is named './\\foo#title <>' --- But how do you call it? --- @@ -467,7 +522,7 @@ "can" checks if the object or class has a method called "METHOD". If it does then a reference to the sub is returned. --- -!!Closures +#title Closures Now, about that syntax. --- HTML tags take blocks of content. @@ -489,15 +544,19 @@ } } --- -We install methods for all the HTML tags +We install methods for ever HTML tag +--- +(Except 'tr'. Anybody know why?) --- #mode perl use CGI (); -install_tag($_) for ( @CGI::EXPORT_TAGS{ - qw/:html2 :html3 :html4 :netscape :form/} +install_tag($_) + for ( @CGI::EXPORT_TAGS{ + qw/:html2 :html3 :html4 + :netscape :form/} ); --- -!!Not everything is roses +#title Not everything is roses (Here's where it all goes wrong) --- HTML Attributes @@ -534,10 +593,12 @@ --- Can anybody help me? --- -!! +That's Template::Declare +--- +#title Test::WWW::Declare --- -!!Test::WWW::Declare +#title Test::WWW::Declare --- A language for testing web applications --- @@ -549,10 +610,13 @@ --- Test::WWW::Declare is PRETTY --- -- Simple, declarative web testing -- Easy to read -- Easy to write -- Looks more like what users do +Simple, declarative web testing +--- +Easy to read +--- +Easy to write +--- +Looks more like what users do --- #mode perl # Test::WWW::Mechanize @@ -562,7 +626,8 @@ my $URL = $server->started_ok; my $mech = Jifty::Test::WWW::Mechanize->new; $mech->get_html_ok($URL); -like($mech->uri, qr{splash}, 'Redirected to splash page'); +like($mech->uri, qr{splash}, + 'Redirected to splash page'); --- The insides are great --- @@ -577,7 +642,8 @@ session "search" => run { flow "google searches work" => check { get 'http://google.com/ncr'; - fill form 'f' => { q => 'Squeamish ossifrage' }; + fill form 'f' => { + q => 'Squeamish ossifrage' }; click button 'Google Search'; } }; @@ -590,7 +656,7 @@ --- Abort means 'failing test' --- -Every named 'session' gets its own cookie jar and WWW::Mechanize +Every 'session' has a cookie jar and WWW::Mechanize --- #mode perl session "check logins" => run { @@ -640,7 +706,9 @@ } } --- -!!Conclusion +That's Test::WWW::Declare +--- +#title Conclusion Creating DSLs is lots of fun --- Creating DSLs can be a lot of work From jifty-commit at lists.jifty.org Tue Apr 3 22:29:36 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 22:29:38 2007 Subject: [Jifty-commit] r3091 - in jifty/trunk: . Message-ID: <20070404022936.7DBBE4D8004@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 22:29:30 2007 New Revision: 3091 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54434@pinglin-2: jesse | 2007-04-04 11:08:47 +0900 * tweaky Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Tue Apr 3 22:29:30 2007 @@ -75,6 +75,10 @@ } if ( $key =~ /^(?: |\n|n)/ ) { $counter++; + } elsif ( $key eq 'e' ) { + system("vim", $ARGV[0]); + load_slides(); + next; } elsif ( $key eq 'r' ) { load_slides(); next; Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 22:29:30 2007 @@ -2,7 +2,7 @@ Domain Specific Languages in Perl --- #title A bit about DSLs -DSLs are 'little languages' for specific programming tasks +DSLs are little languages for specific programming tasks --- DSLs are easier to read --- @@ -61,7 +61,7 @@ --- Never say that to a Perl Hacker --- -#title agenda +#title Agenda We've made some DSLs --- One for declaring database schema @@ -261,17 +261,13 @@ We ended up with Jifty::DBI columns --- #mode perl - use Jifty::DBI::Record schema { -column - auth_token => type is 'text', +column auth_token => type is 'text', render as 'Unrendered'; column score => type is 'int', is immutable, - default is '0', - label is 'Score', - since is '0.0.7'; + label is 'Score'; column time_zone => label is 'Time zone', @@ -285,14 +281,21 @@ #title Take 1 --- -#title Take 1: +#title Take 1 Jifty::DBI::Schema --- +#title Take 1: Jifty::DBI::Schema Our first DSL in Perl --- -We beat the parser into submission using: -- Clever function prototypes -- Injection of functions +We beat the parser into submission with a few tricks +--- +Injection of functions +--- +We saw that a moment ago +--- +Clever function prototypes +--- +Let's have a look at that --- #mode perl # The syntax we wanted @@ -342,9 +345,10 @@ - Limited flexibility - Needs new functions for every attribute --- -#title Take 2: +#title Take 2 Object::Declare --- +#title Take 2: Object::Declare #`mpg123 ~/katamari.mp3` Katamari for Code --- @@ -398,6 +402,7 @@ --- ...and then your program gets control back --- +#title Jifty::DBI::Schema - end That's Jifty::DBI::Schema. --- #title @@ -593,6 +598,7 @@ --- Can anybody help me? --- +#title Template::Declare - end That's Template::Declare --- #title @@ -706,6 +712,7 @@ } } --- +#title Test::WWW::Declare - end That's Test::WWW::Declare --- #title Conclusion From jifty-commit at lists.jifty.org Tue Apr 3 22:30:15 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Tue Apr 3 22:30:17 2007 Subject: [Jifty-commit] r3092 - in jifty/trunk: . Message-ID: <20070404023015.234534D8004@diesel.bestpractical.com> Author: jesse Date: Tue Apr 3 22:30:07 2007 New Revision: 3092 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54435@pinglin-2: jesse | 2007-04-04 11:29:04 +0900 more slides Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Tue Apr 3 22:30:07 2007 @@ -38,9 +38,10 @@ $mode = 'perl'; } if ( $mode eq 'text' and $slide ) { - $slide = autoformat $slide, { left => 1, right => ($cols-1), all => 1 }; + $slide = autoformat $slide, { left => 2, right => ($cols-1), all => 1 }; } elsif ($mode eq 'perl') { + $slide =~ s/^/ /gsm; my $tidycols = $cols - 2; # squeeze for display open my $out , ">/tmp/output.$$" || die $!; print $out $slide || die $!; @@ -61,12 +62,12 @@ $left = 0; } $console->Cursor( $left, int($rows/2)-1, ); - print $slide."\n"; + print colored($slide." \n",'bold blue on white'); } $console->Cursor( 0, ( $rows - 1 ) ); - print "$counter/" . $#SLIDES; + print colored("$counter/" . $#SLIDES, "bold white"); ReadMode 4; my $key = ReadKey(0); ReadMode 0; Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Tue Apr 3 22:30:07 2007 @@ -53,9 +53,9 @@ --- DHH demonstrated Rails migrations --- -Looked very sexy +they looked very sexy --- -Was very jealous +I was very jealous --- "You can't do this in any other language" --- @@ -543,9 +543,9 @@ ... if (defined wantarray) { - return $closure_around_$code; + return sub { ...closure around $code...}; } else { - # Actually do our work and run $code + # Actually do our work, run $code and return the output } } --- From jifty-commit at lists.jifty.org Wed Apr 4 01:05:49 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Wed Apr 4 01:06:25 2007 Subject: [Jifty-commit] r3093 - in jifty/trunk: . Message-ID: <20070404050549.3A0EB4D80B0@diesel.bestpractical.com> Author: jesse Date: Wed Apr 4 01:05:43 2007 New Revision: 3093 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides jifty/trunk/doc/talks/yapc.asia.2007.txt Log: r54438@pinglin-2: jesse | 2007-04-04 14:04:04 +0900 * Slides system now has a presenter view Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Wed Apr 4 01:05:43 2007 @@ -11,10 +11,27 @@ my $counter = 0; my $slides_played = {}; my $title; + +open(my $next_slide, ">/tmp/next_slide"); +select($next_slide); +$| = 1; +select(STDOUT); while ( $counter <= $#SLIDES ) { my $mode = 'text'; my ( $cols, $rows, undef, undef ) = GetTerminalSize(); my $slide = $SLIDES[$counter]; + + print $next_slide Term::ANSIScreen::cls; + print $next_slide locate(1,1); + print $next_slide colored("Time: ".scalar localtime ."\n", 'blue'); + print $next_slide colored("Back 1\n", 'red'); + print $next_slide $SLIDES[$counter-1] ."\n\n"; + print $next_slide colored("This slide, $counter/".$#SLIDES."\n", 'blue'); + print $next_slide $SLIDES[$counter] ."\n\n"; + print $next_slide colored("Next slide\n", 'red'); + print $next_slide $SLIDES[$counter+1]; + print $next_slide "\n"; + my $console = Term::ANSIScreen->new; $console->Cls; $console->Cursor(1,1); Modified: jifty/trunk/doc/talks/yapc.asia.2007.txt ============================================================================== --- jifty/trunk/doc/talks/yapc.asia.2007.txt (original) +++ jifty/trunk/doc/talks/yapc.asia.2007.txt Wed Apr 4 01:05:43 2007 @@ -346,10 +346,10 @@ - Needs new functions for every attribute --- #title Take 2 +#`mpg123 ~/katamari.mp3` Object::Declare --- #title Take 2: Object::Declare -#`mpg123 ~/katamari.mp3` Katamari for Code --- #mode perl @@ -507,7 +507,7 @@ --- We have THE symbol table --- -But URLs can have characters that are illegal in sub names. :/ +But URLs have characters that are illegal in sub names. :/ --- Actually, Perl doesn't care --- @@ -605,7 +605,6 @@ Test::WWW::Declare --- #title Test::WWW::Declare ---- A language for testing web applications --- In early development From jifty-commit at lists.jifty.org Wed Apr 4 01:59:51 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Wed Apr 4 02:00:48 2007 Subject: [Jifty-commit] r3094 - in jifty/trunk: . Message-ID: <20070404055951.E502C4D80FB@diesel.bestpractical.com> Author: jesse Date: Wed Apr 4 01:59:46 2007 New Revision: 3094 Modified: jifty/trunk/ (props changed) jifty/trunk/doc/talks/present-slides Log: r54440@pinglin-2: jesse | 2007-04-04 14:56:43 +0900 * Autoopen the presenter tools Modified: jifty/trunk/doc/talks/present-slides ============================================================================== --- jifty/trunk/doc/talks/present-slides (original) +++ jifty/trunk/doc/talks/present-slides Wed Apr 4 01:59:46 2007 @@ -16,6 +16,9 @@ select($next_slide); $| = 1; select(STDOUT); + +my $cmd = q{ osascript -e ' tell application "Terminal"' -e ' do script "tail -f /tmp/next_slide"' -e 'end tell' }; +system($cmd); while ( $counter <= $#SLIDES ) { my $mode = 'text'; my ( $cols, $rows, undef, undef ) = GetTerminalSize(); @@ -23,7 +26,7 @@ print $next_slide Term::ANSIScreen::cls; print $next_slide locate(1,1); - print $next_slide colored("Time: ".scalar localtime ."\n", 'blue'); + print $next_slide colored("Time: ".scalar localtime() ."\n", 'blue'); print $next_slide colored("Back 1\n", 'red'); print $next_slide $SLIDES[$counter-1] ."\n\n"; print $next_slide colored("This slide, $counter/".$#SLIDES."\n", 'blue'); From jifty-commit at lists.jifty.org Wed Apr 4 02:04:02 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Wed Apr 4 02:04:07 2007 Subject: [Jifty-commit] r3095 - jifty/trunk/lib/Jifty/Web Message-ID: <20070404060402.D1D3C4D80FB@diesel.bestpractical.com> Author: hlb Date: Wed Apr 4 02:03:58 2007 New Revision: 3095 Modified: jifty/trunk/lib/Jifty/Web/Menu.pm Log: * fix "open" class in menu - active menu item doesn't imply current open item Modified: jifty/trunk/lib/Jifty/Web/Menu.pm ============================================================================== --- jifty/trunk/lib/Jifty/Web/Menu.pm (original) +++ jifty/trunk/lib/Jifty/Web/Menu.pm Wed Apr 4 02:03:58 2007 @@ -226,7 +226,7 @@ my @kids = $self->children; my $id = Jifty->web->serial; Jifty->web->out( qq{
  • } + . ( $self->active ? 'active' : 'closed' ) . qq{">} . qq{} ); Jifty->web->out( $self->as_link ); Jifty->web->out(qq{}); From jifty-commit at lists.jifty.org Wed Apr 4 14:18:25 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Wed Apr 4 14:18:29 2007 Subject: [Jifty-commit] r3096 - jifty/trunk/doc/talks Message-ID: <20070404181825.05AA44D8084@diesel.bestpractical.com> Author: audreyt Date: Wed Apr 4 14:18:24 2007 New Revision: 3096 Added: jifty/trunk/doc/talks/yapcasia2007-doxory.key.tbz2 (contents, props changed) Log: * Snapshot of doxory slides. Added: jifty/trunk/doc/talks/yapcasia2007-doxory.key.tbz2 ============================================================================== Binary file. No diff available. From jifty-commit at lists.jifty.org Wed Apr 4 19:53:34 2007 From: jifty-commit at lists.jifty.org (jifty-commit@lists.jifty.org) Date: Wed Apr 4 19:53:37 2007 Subject: [Jifty-commit] r3097 - in jifty/trunk: lib/Jifty lib/auto Message-ID: <20070404235334.D4AB14D8084@diesel.bestpractical.com> Author: alexmv Date: Wed Apr 4 19:53:33 2007 New Revision: 3097 Removed: jifty/trunk/lib/auto/ Modified: jifty/trunk/ (props changed) jifty/trunk/lib/Jifty/Action.pm Log: r18733@zoq-fot-pik: chmrr | 2007-04-04 19:53:06 -0400 * Typo fix in example in POD * Remove old, unused empty directory Modified: jifty/trunk/lib/Jifty/Action.pm ============================================================================== --- jifty/trunk/lib/Jifty/Action.pm (original) +++ jifty/trunk/lib/Jifty/Action.pm Wed Apr 4 19:53:33 2007 @@ -1185,7 +1185,7 @@ value => '%$value%', ); - return map { $_->name } @{ $foos->item_array_ref }; + return map { $_->name } @{ $foos->items_array_ref }; } In this example, the "foo" field is autocompleted from names matched from the C table. The match, in this case, matches any substring found in the database. I could have matched any item that starts with the string, ends with the string, matches other fields than the one returned, etc. It's up to you to decide. @@ -1195,7 +1195,7 @@ If you need a more complicated solution, you can return the autocompletion values as a list of hash references containing the keys C and (optionally) C
  • If MULTI_SELECT is false, selectCell will select the cell at the specified index for only the last displayed Calendar page.
  • +*
  • If MULTI_SELECT is true, selectCell will select the cell at the specified index, on each displayed Calendar page.
  • +* +* @method selectCell +* @param {Number} cellIndex The index of the cell to be selected. +* @return {Date[]} Array of JavaScript Date objects representing all individual dates that are currently selected. +*/ +YAHOO.widget.CalendarGroup.prototype.selectCell = function(cellIndex) { + for (var p=0;p=0;--p) { + var cal = this.pages[p]; + cal.previousMonth(); + } +}; + +/** +* Navigates to the next year in the currently selected month in the calendar widget. +* @method nextYear +*/ +YAHOO.widget.CalendarGroup.prototype.nextYear = function() { + for (var p=0;p 11)) { + var DM = YAHOO.widget.DateMath; + var newDate = DM.add(date, DM.MONTH, iMonth-date.getMonth()); + date.setTime(newDate.getTime()); + } else { + date.setMonth(iMonth); + } +}; + + +/** +* CSS class representing the container for the calendar +* @property YAHOO.widget.CalendarGroup.CSS_CONTAINER +* @static +* @final +* @type String +*/ +YAHOO.widget.CalendarGroup.CSS_CONTAINER = "yui-calcontainer"; + +/** +* CSS class representing the container for the calendar +* @property YAHOO.widget.CalendarGroup.CSS_MULTI_UP +* @static +* @final +* @type String +*/ +YAHOO.widget.CalendarGroup.CSS_MULTI_UP = "multi"; + +/** +* CSS class representing the title for the 2-up calendar +* @property YAHOO.widget.CalendarGroup.CSS_2UPTITLE +* @static +* @final +* @type String +*/ +YAHOO.widget.CalendarGroup.CSS_2UPTITLE = "title"; + +/** +* CSS class representing the close icon for the 2-up calendar +* @property YAHOO.widget.CalendarGroup.CSS_2UPCLOSE +* @static +* @final +* @deprecated Along with Calendar.IMG_ROOT and NAV_ARROW_LEFT, NAV_ARROW_RIGHT configuration properties. +* Calendar's Style.CSS_CLOSE property now represents the CSS class used to render the close icon +* @type String +*/ +YAHOO.widget.CalendarGroup.CSS_2UPCLOSE = "close-icon"; + +YAHOO.augment(YAHOO.widget.CalendarGroup, YAHOO.widget.Calendar, "buildDayLabel", + "buildMonthLabel", + "renderOutOfBoundsDate", + "renderRowHeader", + "renderRowFooter", + "renderCellDefault", + "styleCellDefault", + "renderCellStyleHighlight1", + "renderCellStyleHighlight2", + "renderCellStyleHighlight3", + "renderCellStyleHighlight4", + "renderCellStyleToday", + "renderCellStyleSelected", + "renderCellNotThisMonth", + "renderBodyCellRestricted", + "initStyles", + "configTitle", + "configClose", + "configIframe", + "hide", + "show", + "browser"); + +/** +* The set of default Config property keys and values for the CalendarGroup +* @property YAHOO.widget.CalendarGroup._DEFAULT_CONFIG +* @final +* @static +* @private +* @type Object +*/ +YAHOO.widget.CalendarGroup._DEFAULT_CONFIG = YAHOO.widget.Calendar._DEFAULT_CONFIG; +YAHOO.widget.CalendarGroup._DEFAULT_CONFIG.PAGES = {key:"pages", value:2}; + +/** +* Returns a string representation of the object. +* @method toString +* @return {String} A string representation of the CalendarGroup object. +*/ +YAHOO.widget.CalendarGroup.prototype.toString = function() { + return "CalendarGroup " + this.id; +}; + +YAHOO.widget.CalGrp = YAHOO.widget.CalendarGroup; + +/** +* @class YAHOO.widget.Calendar2up +* @extends YAHOO.widget.CalendarGroup +* @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default. +*/ +YAHOO.widget.Calendar2up = function(id, containerId, config) { + this.init(id, containerId, config); +}; + +YAHOO.extend(YAHOO.widget.Calendar2up, YAHOO.widget.CalendarGroup); + +/** +* @deprecated The old Calendar2up class is no longer necessary, since CalendarGroup renders in a 2up view by default. +*/ +YAHOO.widget.Cal2up = YAHOO.widget.Calendar2up; + +YAHOO.register("calendar", YAHOO.widget.Calendar, {version: "2.2.1", build: "193"}); Modified: jifty/trunk/share/web/static/js/yui/container.js ============================================================================== --- jifty/trunk/share/web/static/js/yui/container.js (original) +++ jifty/trunk/share/web/static/js/yui/container.js Thu Apr 12 03:32:44 2007 @@ -1,4614 +1,5398 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version 0.12.1 -*/ - -/** -* Config is a utility used within an Object to allow the implementer to maintain a list of local configuration properties and listen for changes to those properties dynamically using CustomEvent. The initial values are also maintained so that the configuration can be reset at any given point to its initial state. -* @namespace YAHOO.util -* @class Config -* @constructor -* @param {Object} owner The owner Object to which this Config Object belongs -*/ -YAHOO.util.Config = function(owner) { - if (owner) { - this.init(owner); - } -}; - -YAHOO.util.Config.prototype = { - - /** - * Object reference to the owner of this Config Object - * @property owner - * @type Object - */ - owner : null, - - /** - * Boolean flag that specifies whether a queue is currently being executed - * @property queueInProgress - * @type Boolean - */ - queueInProgress : false, - - - /** - * Validates that the value passed in is a Boolean. - * @method checkBoolean - * @param {Object} val The value to validate - * @return {Boolean} true, if the value is valid - */ - checkBoolean: function(val) { - if (typeof val == 'boolean') { - return true; - } else { - return false; - } - }, - - /** - * Validates that the value passed in is a number. - * @method checkNumber - * @param {Object} val The value to validate - * @return {Boolean} true, if the value is valid - */ - checkNumber: function(val) { - if (isNaN(val)) { - return false; - } else { - return true; - } - } -}; - - -/** -* Initializes the configuration Object and all of its local members. -* @method init -* @param {Object} owner The owner Object to which this Config Object belongs -*/ -YAHOO.util.Config.prototype.init = function(owner) { - - this.owner = owner; - - /** - * Object reference to the owner of this Config Object - * @event configChangedEvent - */ - this.configChangedEvent = new YAHOO.util.CustomEvent("configChanged"); - - this.queueInProgress = false; - - /* Private Members */ - - /** - * Maintains the local collection of configuration property objects and their specified values - * @property config - * @private - * @type Object - */ - var config = {}; - - /** - * Maintains the local collection of configuration property objects as they were initially applied. - * This object is used when resetting a property. - * @property initialConfig - * @private - * @type Object - */ - var initialConfig = {}; - - /** - * Maintains the local, normalized CustomEvent queue - * @property eventQueue - * @private - * @type Object - */ - var eventQueue = []; - - /** - * Fires a configuration property event using the specified value. - * @method fireEvent - * @private - * @param {String} key The configuration property's name - * @param {value} Object The value of the correct type for the property - */ - var fireEvent = function( key, value ) { - key = key.toLowerCase(); - - var property = config[key]; - - if (typeof property != 'undefined' && property.event) { - property.event.fire(value); - } - }; - /* End Private Members */ - - /** - * Adds a property to the Config Object's private config hash. - * @method addProperty - * @param {String} key The configuration property's name - * @param {Object} propertyObject The Object containing all of this property's arguments - */ - this.addProperty = function( key, propertyObject ) { - key = key.toLowerCase(); - - config[key] = propertyObject; - - propertyObject.event = new YAHOO.util.CustomEvent(key); - propertyObject.key = key; - - if (propertyObject.handler) { - propertyObject.event.subscribe(propertyObject.handler, this.owner, true); - } - - this.setProperty(key, propertyObject.value, true); - - if (! propertyObject.suppressEvent) { - this.queueProperty(key, propertyObject.value); - } - }; - - /** - * Returns a key-value configuration map of the values currently set in the Config Object. - * @method getConfig - * @return {Object} The current config, represented in a key-value map - */ - this.getConfig = function() { - var cfg = {}; - - for (var prop in config) { - var property = config[prop]; - if (typeof property != 'undefined' && property.event) { - cfg[prop] = property.value; - } - } - - return cfg; - }; - - /** - * Returns the value of specified property. - * @method getProperty - * @param {String} key The name of the property - * @return {Object} The value of the specified property - */ - this.getProperty = function(key) { - key = key.toLowerCase(); - - var property = config[key]; - if (typeof property != 'undefined' && property.event) { - return property.value; - } else { - return undefined; - } - }; - - /** - * Resets the specified property's value to its initial value. - * @method resetProperty - * @param {String} key The name of the property - * @return {Boolean} True is the property was reset, false if not - */ - this.resetProperty = function(key) { - key = key.toLowerCase(); - - var property = config[key]; - if (typeof property != 'undefined' && property.event) { - if (initialConfig[key] && initialConfig[key] != 'undefined') { - this.setProperty(key, initialConfig[key]); - } - return true; - } else { - return false; - } - }; - - /** - * Sets the value of a property. If the silent property is passed as true, the property's event will not be fired. - * @method setProperty - * @param {String} key The name of the property - * @param {String} value The value to set the property to - * @param {Boolean} silent Whether the value should be set silently, without firing the property event. - * @return {Boolean} True, if the set was successful, false if it failed. - */ - this.setProperty = function(key, value, silent) { - key = key.toLowerCase(); - - if (this.queueInProgress && ! silent) { - this.queueProperty(key,value); // Currently running through a queue... - return true; - } else { - var property = config[key]; - if (typeof property != 'undefined' && property.event) { - if (property.validator && ! property.validator(value)) { // validator - return false; - } else { - property.value = value; - if (! silent) { - fireEvent(key, value); - this.configChangedEvent.fire([key, value]); - } - return true; - } - } else { - return false; - } - } - }; - - /** - * Sets the value of a property and queues its event to execute. If the event is already scheduled to execute, it is - * moved from its current position to the end of the queue. - * @method queueProperty - * @param {String} key The name of the property - * @param {String} value The value to set the property to - * @return {Boolean} true, if the set was successful, false if it failed. - */ - this.queueProperty = function(key, value) { - key = key.toLowerCase(); - - var property = config[key]; - - if (typeof property != 'undefined' && property.event) { - if (typeof value != 'undefined' && property.validator && ! property.validator(value)) { // validator - return false; - } else { - - if (typeof value != 'undefined') { - property.value = value; - } else { - value = property.value; - } - - var foundDuplicate = false; - - for (var i=0;iOR -* @param {HTMLElement} el The element representing the Module -* @param {Object} userConfig The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details. -*/ -YAHOO.widget.Module = function(el, userConfig) { - if (el) { - this.init(el, userConfig); - } -}; - -/** -* Constant representing the prefix path to use for non-secure images -* @property YAHOO.widget.Module.IMG_ROOT -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.IMG_ROOT = "http://us.i1.yimg.com/us.yimg.com/i/"; - -/** -* Constant representing the prefix path to use for securely served images -* @property YAHOO.widget.Module.IMG_ROOT_SSL -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.IMG_ROOT_SSL = "https://a248.e.akamai.net/sec.yimg.com/i/"; - -/** -* Constant for the default CSS class name that represents a Module -* @property YAHOO.widget.Module.CSS_MODULE -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.CSS_MODULE = "module"; - -/** -* Constant representing the module header -* @property YAHOO.widget.Module.CSS_HEADER -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.CSS_HEADER = "hd"; - -/** -* Constant representing the module body -* @property YAHOO.widget.Module.CSS_BODY -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.CSS_BODY = "bd"; - -/** -* Constant representing the module footer -* @property YAHOO.widget.Module.CSS_FOOTER -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.CSS_FOOTER = "ft"; - -/** -* Constant representing the url for the "src" attribute of the iframe used to monitor changes to the browser's base font size -* @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL -* @static -* @final -* @type String -*/ -YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;"; - -/** -* Singleton CustomEvent fired when the font size is changed in the browser. -* Opera's "zoom" functionality currently does not support text size detection. -* @event YAHOO.widget.Module.textResizeEvent -*/ -YAHOO.widget.Module.textResizeEvent = new YAHOO.util.CustomEvent("textResize"); - -YAHOO.widget.Module.prototype = { - /** - * The class's constructor function - * @property contructor - * @type Function - */ - constructor : YAHOO.widget.Module, - - /** - * The main module element that contains the header, body, and footer - * @property element - * @type HTMLElement - */ - element : null, - - /** - * The header element, denoted with CSS class "hd" - * @property header - * @type HTMLElement - */ - header : null, - - /** - * The body element, denoted with CSS class "bd" - * @property body - * @type HTMLElement - */ - body : null, - - /** - * The footer element, denoted with CSS class "ft" - * @property footer - * @type HTMLElement - */ - footer : null, - - /** - * The id of the element - * @property id - * @type String - */ - id : null, - - /** - * The String representing the image root - * @property imageRoot - * @type String - */ - imageRoot : YAHOO.widget.Module.IMG_ROOT, - - /** - * Initializes the custom events for Module which are fired automatically at appropriate times by the Module class. - * @method initEvents - */ - initEvents : function() { - - /** - * CustomEvent fired prior to class initalization. - * @event beforeInitEvent - * @param {class} classRef class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module) - */ - this.beforeInitEvent = new YAHOO.util.CustomEvent("beforeInit"); - - /** - * CustomEvent fired after class initalization. - * @event initEvent - * @param {class} classRef class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module) - */ - this.initEvent = new YAHOO.util.CustomEvent("init"); - - /** - * CustomEvent fired when the Module is appended to the DOM - * @event appendEvent - */ - this.appendEvent = new YAHOO.util.CustomEvent("append"); - - /** - * CustomEvent fired before the Module is rendered - * @event beforeRenderEvent - */ - this.beforeRenderEvent = new YAHOO.util.CustomEvent("beforeRender"); - - /** - * CustomEvent fired after the Module is rendered - * @event renderEvent - */ - this.renderEvent = new YAHOO.util.CustomEvent("render"); - - /** - * CustomEvent fired when the header content of the Module is modified - * @event changeHeaderEvent - * @param {String/HTMLElement} content String/element representing the new header content - */ - this.changeHeaderEvent = new YAHOO.util.CustomEvent("changeHeader"); - - /** - * CustomEvent fired when the body content of the Module is modified - * @event changeBodyEvent - * @param {String/HTMLElement} content String/element representing the new body content - */ - this.changeBodyEvent = new YAHOO.util.CustomEvent("changeBody"); - - /** - * CustomEvent fired when the footer content of the Module is modified - * @event changeFooterEvent - * @param {String/HTMLElement} content String/element representing the new footer content - */ - this.changeFooterEvent = new YAHOO.util.CustomEvent("changeFooter"); - - /** - * CustomEvent fired when the content of the Module is modified - * @event changeContentEvent - */ - this.changeContentEvent = new YAHOO.util.CustomEvent("changeContent"); - - /** - * CustomEvent fired when the Module is destroyed - * @event destroyEvent - */ - this.destroyEvent = new YAHOO.util.CustomEvent("destroy"); - - /** - * CustomEvent fired before the Module is shown - * @event beforeShowEvent - */ - this.beforeShowEvent = new YAHOO.util.CustomEvent("beforeShow"); - - /** - * CustomEvent fired after the Module is shown - * @event showEvent - */ - this.showEvent = new YAHOO.util.CustomEvent("show"); - - /** - * CustomEvent fired before the Module is hidden - * @event beforeHideEvent - */ - this.beforeHideEvent = new YAHOO.util.CustomEvent("beforeHide"); - - /** - * CustomEvent fired after the Module is hidden - * @event hideEvent - */ - this.hideEvent = new YAHOO.util.CustomEvent("hide"); - }, - - /** - * String representing the current user-agent platform - * @property platform - * @type String - */ - platform : function() { - var ua = navigator.userAgent.toLowerCase(); - if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) { - return "windows"; - } else if (ua.indexOf("macintosh") != -1) { - return "mac"; - } else { - return false; - } - }(), - - /** - * String representing the current user-agent browser - * @property browser - * @type String - */ - browser : function() { - var ua = navigator.userAgent.toLowerCase(); - if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof) - return 'opera'; - } else if (ua.indexOf('msie 7')!=-1) { // IE7 - return 'ie7'; - } else if (ua.indexOf('msie') !=-1) { // IE - return 'ie'; - } else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko") - return 'safari'; - } else if (ua.indexOf('gecko') != -1) { // Gecko - return 'gecko'; - } else { - return false; - } - }(), - - /** - * Boolean representing whether or not the current browsing context is secure (https) - * @property isSecure - * @type Boolean - */ - isSecure : function() { - if (window.location.href.toLowerCase().indexOf("https") === 0) { - return true; - } else { - return false; - } - }(), - - /** - * Initializes the custom events for Module which are fired automatically at appropriate times by the Module class. - */ - initDefaultConfig : function() { - // Add properties // - - /** - * Specifies whether the Module is visible on the page. - * @config visible - * @type Boolean - * @default true - */ - this.cfg.addProperty("visible", { value:true, handler:this.configVisible, validator:this.cfg.checkBoolean } ); - - /** - * Object or array of objects representing the ContainerEffect classes that are active for animating the container. - * @config effect - * @type Object - * @default null - */ - this.cfg.addProperty("effect", { suppressEvent:true, supercedes:["visible"] } ); - - /** - * Specifies whether to create a special proxy iframe to monitor for user font resizing in the document - * @config monitorresize - * @type Boolean - * @default true - */ - this.cfg.addProperty("monitorresize", { value:true, handler:this.configMonitorResize } ); - }, - - /** - * The Module class's initialization method, which is executed for Module and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. - * @method init - * @param {String} el The element ID representing the Module OR - * @param {HTMLElement} el The element representing the Module - * @param {Object} userConfig The configuration Object literal containing the configuration that should be set for this module. See configuration documentation for more details. - */ - init : function(el, userConfig) { - - this.initEvents(); - - this.beforeInitEvent.fire(YAHOO.widget.Module); - - /** - * The Module's Config object used for monitoring configuration properties. - * @property cfg - * @type YAHOO.util.Config - */ - this.cfg = new YAHOO.util.Config(this); - - if (this.isSecure) { - this.imageRoot = YAHOO.widget.Module.IMG_ROOT_SSL; - } - - if (typeof el == "string") { - var elId = el; - - el = document.getElementById(el); - if (! el) { - el = document.createElement("DIV"); - el.id = elId; - } - } - - this.element = el; - - if (el.id) { - this.id = el.id; - } - - var childNodes = this.element.childNodes; - - if (childNodes) { - for (var i=0;iOR - * @param {HTMLElement} headerContent The HTMLElement to append to the header - */ - setHeader : function(headerContent) { - if (! this.header) { - this.header = document.createElement("DIV"); - this.header.className = YAHOO.widget.Module.CSS_HEADER; - } - - if (typeof headerContent == "string") { - this.header.innerHTML = headerContent; - } else { - this.header.innerHTML = ""; - this.header.appendChild(headerContent); - } - - this.changeHeaderEvent.fire(headerContent); - this.changeContentEvent.fire(); - }, - - /** - * Appends the passed element to the header. If no header is present, one will be automatically created. - * @method appendToHeader - * @param {HTMLElement} element The element to append to the header - */ - appendToHeader : function(element) { - if (! this.header) { - this.header = document.createElement("DIV"); - this.header.className = YAHOO.widget.Module.CSS_HEADER; - } - - this.header.appendChild(element); - this.changeHeaderEvent.fire(element); - this.changeContentEvent.fire(); - }, - - /** - * Sets the Module's body content to the HTML specified, or appends the passed element to the body. If no body is present, one will be automatically created. - * @method setBody - * @param {String} bodyContent The HTML used to set the body OR - * @param {HTMLElement} bodyContent The HTMLElement to append to the body - */ - setBody : function(bodyContent) { - if (! this.body) { - this.body = document.createElement("DIV"); - this.body.className = YAHOO.widget.Module.CSS_BODY; - } - - if (typeof bodyContent == "string") - { - this.body.innerHTML = bodyContent; - } else { - this.body.innerHTML = ""; - this.body.appendChild(bodyContent); - } - - this.changeBodyEvent.fire(bodyContent); - this.changeContentEvent.fire(); - }, - - /** - * Appends the passed element to the body. If no body is present, one will be automatically created. - * @method appendToBody - * @param {HTMLElement} element The element to append to the body - */ - appendToBody : function(element) { - if (! this.body) { - this.body = document.createElement("DIV"); - this.body.className = YAHOO.widget.Module.CSS_BODY; - } - - this.body.appendChild(element); - this.changeBodyEvent.fire(element); - this.changeContentEvent.fire(); - }, - - /** - * Sets the Module's footer content to the HTML specified, or appends the passed element to the footer. If no footer is present, one will be automatically created. - * @method setFooter - * @param {String} footerContent The HTML used to set the footer OR - * @param {HTMLElement} footerContent The HTMLElement to append to the footer - */ - setFooter : function(footerContent) { - if (! this.footer) { - this.footer = document.createElement("DIV"); - this.footer.className = YAHOO.widget.Module.CSS_FOOTER; - } - - if (typeof footerContent == "string") { - this.footer.innerHTML = footerContent; - } else { - this.footer.innerHTML = ""; - this.footer.appendChild(footerContent); - } - - this.changeFooterEvent.fire(footerContent); - this.changeContentEvent.fire(); - }, - - /** - * Appends the passed element to the footer. If no footer is present, one will be automatically created. - * @method appendToFooter - * @param {HTMLElement} element The element to append to the footer - */ - appendToFooter : function(element) { - if (! this.footer) { - this.footer = document.createElement("DIV"); - this.footer.className = YAHOO.widget.Module.CSS_FOOTER; - } - - this.footer.appendChild(element); - this.changeFooterEvent.fire(element); - this.changeContentEvent.fire(); - }, - - /** - * Renders the Module by inserting the elements that are not already in the main Module into their correct places. Optionally appends the Module to the specified node prior to the render's execution. NOTE: For Modules without existing markup, the appendToNode argument is REQUIRED. If this argument is ommitted and the current element is not present in the document, the function will return false, indicating that the render was a failure. - * @method render - * @param {String} appendToNode The element id to which the Module should be appended to prior to rendering OR - * @param {HTMLElement} appendToNode The element to which the Module should be appended to prior to rendering - * @param {HTMLElement} moduleElement OPTIONAL. The element that represents the actual Standard Module container. - * @return {Boolean} Success or failure of the render - */ - render : function(appendToNode, moduleElement) { - this.beforeRenderEvent.fire(); - - if (! moduleElement) { - moduleElement = this.element; - } - - var me = this; - var appendTo = function(element) { - if (typeof element == "string") { - element = document.getElementById(element); - } - - if (element) { - element.appendChild(me.element); - me.appendEvent.fire(); - } - }; - - if (appendToNode) { - appendTo(appendToNode); - } else { // No node was passed in. If the element is not pre-marked up, this fails - if (! YAHOO.util.Dom.inDocument(this.element)) { - return false; - } - } - - // Need to get everything into the DOM if it isn't already - - if (this.header && ! YAHOO.util.Dom.inDocument(this.header)) { - // There is a header, but it's not in the DOM yet... need to add it - var firstChild = moduleElement.firstChild; - if (firstChild) { // Insert before first child if exists - moduleElement.insertBefore(this.header, firstChild); - } else { // Append to empty body because there are no children - moduleElement.appendChild(this.header); - } - } - - if (this.body && ! YAHOO.util.Dom.inDocument(this.body)) { - // There is a body, but it's not in the DOM yet... need to add it - if (this.footer && YAHOO.util.Dom.isAncestor(this.moduleElement, this.footer)) { // Insert before footer if exists in DOM - moduleElement.insertBefore(this.body, this.footer); - } else { // Append to element because there is no footer - moduleElement.appendChild(this.body); - } - } - - if (this.footer && ! YAHOO.util.Dom.inDocument(this.footer)) { - // There is a footer, but it's not in the DOM yet... need to add it - moduleElement.appendChild(this.footer); - } - - this.renderEvent.fire(); - return true; - }, - - /** - * Removes the Module element from the DOM and sets all child elements to null. - * @method destroy - */ - destroy : function() { - var parent; - - if (this.element) { - YAHOO.util.Event.purgeElement(this.element, true); - parent = this.element.parentNode; - } - if (parent) { - parent.removeChild(this.element); - } - - this.element = null; - this.header = null; - this.body = null; - this.footer = null; - - for (var e in this) { - if (e instanceof YAHOO.util.CustomEvent) { - e.unsubscribeAll(); - } - } - - YAHOO.widget.Module.textResizeEvent.unsubscribe(this.onDomResize, this); - - this.destroyEvent.fire(); - }, - - /** - * Shows the Module element by setting the visible configuration property to true. Also fires two events: beforeShowEvent prior to the visibility change, and showEvent after. - * @method show - */ - show : function() { - this.cfg.setProperty("visible", true); - }, - - /** - * Hides the Module element by setting the visible configuration property to false. Also fires two events: beforeHideEvent prior to the visibility change, and hideEvent after. - * @method hide - */ - hide : function() { - this.cfg.setProperty("visible", false); - }, - - // BUILT-IN EVENT HANDLERS FOR MODULE // - - /** - * Default event handler for changing the visibility property of a Module. By default, this is achieved by switching the "display" style between "block" and "none". - * This method is responsible for firing showEvent and hideEvent. - * @param {String} type The CustomEvent type (usually the property name) - * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. - * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. - * @method configVisible - */ - configVisible : function(type, args, obj) { - var visible = args[0]; - if (visible) { - this.beforeShowEvent.fire(); - YAHOO.util.Dom.setStyle(this.element, "display", "block"); - this.showEvent.fire(); - } else { - this.beforeHideEvent.fire(); - YAHOO.util.Dom.setStyle(this.element, "display", "none"); - this.hideEvent.fire(); - } - }, - - /** - * Default event handler for the "monitorresize" configuration property - * @param {String} type The CustomEvent type (usually the property name) - * @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. - * @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. - * @method configMonitorResize - */ - configMonitorResize : function(type, args, obj) { - var monitor = args[0]; - if (monitor) { - this.initResizeMonitor(); - } else { - YAHOO.util.Event.removeListener(this.resizeMonitor, "resize", this.onDomResize); - this.resizeMonitor = null; - } - } -}; - -/** -* Returns a String representation of the Object. -* @method toString -* @return {String} The string representation of the Module -*/ -YAHOO.widget.Module.prototype.toString = function() { - return "Module " + this.id; -}; - -/** -* Overlay is a Module that is absolutely positioned above the page flow. It has convenience methods for positioning and sizing, as well as options for controlling zIndex and constraining the Overlay's position to the current visible viewport. Overlay also contains a dynamicly generated IFRAME which is placed beneath it for Internet Explorer 6 and 5.x so that it will be properly rendered above SELECT elements. -* @namespace YAHOO.widget -* @class Overlay -* @extends YAHOO.widget.Module -* @param {String} el The element ID representing the Overlay OR -* @param {HTMLElement} el The element representing the Overlay -* @param {Object} userConfig The configuration object literal containing 10/23/2006the configuration that should be set for this Overlay. See configuration documentation for more details. -* @constructor -*/ -YAHOO.widget.Overlay = function(el, userConfig) { - YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig); -}; - -YAHOO.extend(YAHOO.widget.Overlay, YAHOO.widget.Module); - -/** -* The URL that will be placed in the iframe -* @property YAHOO.widget.Overlay.IFRAME_SRC -* @static -* @final -* @type String -*/ -YAHOO.widget.Overlay.IFRAME_SRC = "javascript:false;"; - -/** -* Constant representing the top left corner of an element, used for configuring the context element alignment -* @property YAHOO.widget.Overlay.TOP_LEFT -* @static -* @final -* @type String -*/ -YAHOO.widget.Overlay.TOP_LEFT = "tl"; - -/** -* Constant representing the top right corner of an element, used for configuring the context element alignment -* @property YAHOO.widget.Overlay.TOP_RIGHT -* @static -* @final -* @type String -*/ -YAHOO.widget.Overlay.TOP_RIGHT = "tr"; - -/** -* Constant representing the top bottom left corner of an element, used for configuring the context element alignment -* @property YAHOO.widget.Overlay.BOTTOM_LEFT -* @static -* @final -* @type String -*/ -YAHOO.widget.Overlay.BOTTOM_LEFT = "bl"; - -/** -* Constant representing the bottom right corner of an element, used for configuring the context element alignment -* @property YAHOO.widget.Overlay.BOTTOM_RIGHT -* @static -* @final -* @type String -*/ -YAHOO.widget.Overlay.BOTTOM_RIGHT = "br"; - -/** -* Constant representing the default CSS class used for an Overlay -* @property YAHOO.widget.Overlay.CSS_OVERLAY -* @static -* @final -* @type String -*/ -YAHOO.widget.Overlay.CSS_OVERLAY = "overlay"; - -/** -* The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. -* @method init -* @param {String} el The element ID representing the Overlay OR -* @param {HTMLElement} el The element representing the Overlay -* @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details. -*/ -YAHOO.widget.Overlay.prototype.init = function(el, userConfig) { - YAHOO.widget.Overlay.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level - - this.beforeInitEvent.fire(YAHOO.widget.Overlay); - - YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Overlay.CSS_OVERLAY); - - if (userConfig) { - this.cfg.applyConfig(userConfig, true); - } - - if (this.platform == "mac" && this.browser == "gecko") { - if (! YAHOO.util.Config.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)) { - this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true); - } - if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)) { - this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true); - } - } - - this.initEvent.fire(YAHOO.widget.Overlay); -}; - -/** -* Initializes the custom events for Overlay which are fired automatically at appropriate times by the Overlay class. -* @method initEvents -*/ -YAHOO.widget.Overlay.prototype.initEvents = function() { - YAHOO.widget.Overlay.superclass.initEvents.call(this); - - /** - * CustomEvent fired before the Overlay is moved. - * @event beforeMoveEvent - * @param {Number} x x coordinate - * @param {Number} y y coordinate - */ - this.beforeMoveEvent = new YAHOO.util.CustomEvent("beforeMove", this); - - /** - * CustomEvent fired after the Overlay is moved. - * @event moveEvent - * @param {Number} x x coordinate - * @param {Number} y y coordinate - */ - this.moveEvent = new YAHOO.util.CustomEvent("move", this); -}; - -/** -* Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg). -* @method initDefaultConfig -*/ -YAHOO.widget.Overlay.prototype.initDefaultConfig = function() { - YAHOO.widget.Overlay.superclass.initDefaultConfig.call(this); - - // Add overlay config properties // - - /** - * The absolute x-coordinate position of the Overlay - * @config x - * @type Number - * @default null - */ - this.cfg.addProperty("x", { handler:this.configX, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } ); - - /** - * The absolute y-coordinate position of the Overlay - * @config y - * @type Number - * @default null - */ - this.cfg.addProperty("y", { handler:this.configY, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } ); - - /** - * An array with the absolute x and y positions of the Overlay - * @config xy - * @type Number[] - * @default null - */ - this.cfg.addProperty("xy",{ handler:this.configXY, suppressEvent:true, supercedes:["iframe"] } ); - - /** - * The array of context arguments for context-sensitive positioning. The format is: [id or element, element corner, context corner]. For example, setting this property to ["img1", "tl", "bl"] would align the Overlay's top left corner to the context element's bottom left corner. - * @config context - * @type Array - * @default null - */ - this.cfg.addProperty("context", { handler:this.configContext, suppressEvent:true, supercedes:["iframe"] } ); - - /** - * True if the Overlay should be anchored to the center of the viewport. - * @config fixedcenter - * @type Boolean - * @default false - */ - this.cfg.addProperty("fixedcenter", { value:false, handler:this.configFixedCenter, validator:this.cfg.checkBoolean, supercedes:["iframe","visible"] } ); - - /** - * CSS width of the Overlay. - * @config width - * @type String - * @default null - */ - this.cfg.addProperty("width", { handler:this.configWidth, suppressEvent:true, supercedes:["iframe"] } ); - - /** - * CSS height of the Overlay. - * @config height - * @type String - * @default null - */ - this.cfg.addProperty("height", { handler:this.configHeight, suppressEvent:true, supercedes:["iframe"] } ); - - /** - * CSS z-index of the Overlay. - * @config zIndex - * @type Number - * @default null - */ - this.cfg.addProperty("zIndex", { value:null, handler:this.configzIndex } ); - - /** - * True if the Overlay should be prevented from being positioned out of the viewport. - * @config constraintoviewport - * @type Boolean - * @default false - */ - this.cfg.addProperty("constraintoviewport", { value:false, handler:this.configConstrainToViewport, validator:this.cfg.checkBoolean, supercedes:["iframe","x","y","xy"] } ); - - /** - * True if the Overlay should have an IFRAME shim (for correcting the select z-index bug in IE6 and below). - * @config iframe - * @type Boolean - * @default true for IE6 and below, false for all others - */ - this.cfg.addProperty("iframe", { value:(this.browser == "ie" ? true : false), handler:this.configIframe, validator:this.cfg.checkBoolean, supercedes:["zIndex"] } ); -}; - -/** -* Moves the Overlay to the specified position. This function is identical to calling this.cfg.setProperty("xy", [x,y]); -* @method moveTo -* @param {Number} x The Overlay's new x position -* @param {Number} y The Overlay's new y position -*/ -YAHOO.widget.Overlay.prototype.moveTo = function(x, y) { - this.cfg.setProperty("xy",[x,y]); -}; - -/** -* Adds a special CSS class to the Overlay when Mac/Gecko is in use, to work around a Gecko bug where -* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435 -* @method hideMacGeckoScrollbars -*/ -YAHOO.widget.Overlay.prototype.hideMacGeckoScrollbars = function() { - YAHOO.util.Dom.removeClass(this.element, "show-scrollbars"); - YAHOO.util.Dom.addClass(this.element, "hide-scrollbars"); -}; - -/** -* Removes a special CSS class from the Overlay when Mac/Gecko is in use, to work around a Gecko bug where -* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435 -* @method showMacGeckoScrollbars -*/ -YAHOO.widget.Overlay.prototype.showMacGeckoScrollbars = function() { - YAHOO.util.Dom.removeClass(this.element, "hide-scrollbars"); - YAHOO.util.Dom.addClass(this.element, "show-scrollbars"); -}; - -// BEGIN BUILT-IN PROPERTY EVENT HANDLERS // - -/** -* The default event handler fired when the "visible" property is changed. This method is responsible for firing showEvent and hideEvent. -* @method configVisible -* @param {String} type The CustomEvent type (usually the property name) -* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. -* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. -*/ -YAHOO.widget.Overlay.prototype.configVisible = function(type, args, obj) { - var visible = args[0]; - - var currentVis = YAHOO.util.Dom.getStyle(this.element, "visibility"); - - if (currentVis == "inherit") { - var e = this.element.parentNode; - while (e.nodeType != 9 && e.nodeType != 11) { - currentVis = YAHOO.util.Dom.getStyle(e, "visibility"); - if (currentVis != "inherit") { break; } - e = e.parentNode; - } - if (currentVis == "inherit") { - currentVis = "visible"; - } - } - - var effect = this.cfg.getProperty("effect"); - - var effectInstances = []; - if (effect) { - if (effect instanceof Array) { - for (var i=0;i rightConstraint) { - x = rightConstraint; - } - - if (y < topConstraint) { - y = topConstraint; - } else if (y > bottomConstraint) { - y = bottomConstraint; - } - - this.cfg.setProperty("x", x, true); - this.cfg.setProperty("y", y, true); - this.cfg.setProperty("xy", [x,y], true); -}; - -/** -* Centers the container in the viewport. -* @method center -*/ -YAHOO.widget.Overlay.prototype.center = function() { - var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; - var scrollY = document.documentElement.scrollTop || document.body.scrollTop; - - var viewPortWidth = YAHOO.util.Dom.getClientWidth(); - var viewPortHeight = YAHOO.util.Dom.getClientHeight(); - - var elementWidth = this.element.offsetWidth; - var elementHeight = this.element.offsetHeight; - - var x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX; - var y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY; - - this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]); - - this.cfg.refireEvent("iframe"); -}; - -/** -* Synchronizes the Panel's "xy", "x", and "y" properties with the Panel's position in the DOM. This is primarily used to update position information during drag & drop. -* @method syncPosition -*/ -YAHOO.widget.Overlay.prototype.syncPosition = function() { - var pos = YAHOO.util.Dom.getXY(this.element); - this.cfg.setProperty("x", pos[0], true); - this.cfg.setProperty("y", pos[1], true); - this.cfg.setProperty("xy", pos, true); -}; - -/** -* Event handler fired when the resize monitor element is resized. -* @method onDomResize -* @param {DOMEvent} e The resize DOM event -* @param {Object} obj The scope object -*/ -YAHOO.widget.Overlay.prototype.onDomResize = function(e, obj) { - YAHOO.widget.Overlay.superclass.onDomResize.call(this, e, obj); - var me = this; - setTimeout(function() { - me.syncPosition(); - me.cfg.refireEvent("iframe"); - me.cfg.refireEvent("context"); - }, 0); -}; - -/** -* Removes the Overlay element from the DOM and sets all child elements to null. -* @method destroy -*/ -YAHOO.widget.Overlay.prototype.destroy = function() { - if (this.iframe) { - this.iframe.parentNode.removeChild(this.iframe); - } - - this.iframe = null; - - YAHOO.widget.Overlay.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this); - YAHOO.widget.Overlay.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this); - - YAHOO.widget.Overlay.superclass.destroy.call(this); -}; - -/** -* Returns a String representation of the object. -* @method toString -* @return {String} The string representation of the Overlay. -*/ -YAHOO.widget.Overlay.prototype.toString = function() { - return "Overlay " + this.id; -}; - -/** -* A singleton CustomEvent used for reacting to the DOM event for window scroll -* @event YAHOO.widget.Overlay.windowScrollEvent -*/ -YAHOO.widget.Overlay.windowScrollEvent = new YAHOO.util.CustomEvent("windowScroll"); - -/** -* A singleton CustomEvent used for reacting to the DOM event for window resize -* @event YAHOO.widget.Overlay.windowResizeEvent -*/ -YAHOO.widget.Overlay.windowResizeEvent = new YAHOO.util.CustomEvent("windowResize"); - -/** -* The DOM event handler used to fire the CustomEvent for window scroll -* @method YAHOO.widget.Overlay.windowScrollHandler -* @static -* @param {DOMEvent} e The DOM scroll event -*/ -YAHOO.widget.Overlay.windowScrollHandler = function(e) { - if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") { - if (! window.scrollEnd) { - window.scrollEnd = -1; - } - clearTimeout(window.scrollEnd); - window.scrollEnd = setTimeout(function() { YAHOO.widget.Overlay.windowScrollEvent.fire(); }, 1); - } else { - YAHOO.widget.Overlay.windowScrollEvent.fire(); - } -}; - -/** -* The DOM event handler used to fire the CustomEvent for window resize -* @method YAHOO.widget.Overlay.windowResizeHandler -* @static -* @param {DOMEvent} e The DOM resize event -*/ -YAHOO.widget.Overlay.windowResizeHandler = function(e) { - if (YAHOO.widget.Module.prototype.browser == "ie" || YAHOO.widget.Module.prototype.browser == "ie7") { - if (! window.resizeEnd) { - window.resizeEnd = -1; - } - clearTimeout(window.resizeEnd); - window.resizeEnd = setTimeout(function() { YAHOO.widget.Overlay.windowResizeEvent.fire(); }, 100); - } else { - YAHOO.widget.Overlay.windowResizeEvent.fire(); - } -}; - -/** -* A boolean that indicated whether the window resize and scroll events have already been subscribed to. -* @property YAHOO.widget.Overlay._initialized -* @private -* @type Boolean -*/ -YAHOO.widget.Overlay._initialized = null; - -if (YAHOO.widget.Overlay._initialized === null) { - YAHOO.util.Event.addListener(window, "scroll", YAHOO.widget.Overlay.windowScrollHandler); - YAHOO.util.Event.addListener(window, "resize", YAHOO.widget.Overlay.windowResizeHandler); - - YAHOO.widget.Overlay._initialized = true; -} - -/** -* OverlayManager is used for maintaining the focus status of multiple Overlays.* @namespace YAHOO.widget -* @namespace YAHOO.widget -* @class OverlayManager -* @constructor -* @param {Array} overlays Optional. A collection of Overlays to register with the manager. -* @param {Object} userConfig The object literal representing the user configuration of the OverlayManager -*/ -YAHOO.widget.OverlayManager = function(userConfig) { - this.init(userConfig); -}; - -/** -* The CSS class representing a focused Overlay -* @property YAHOO.widget.OverlayManager.CSS_FOCUSED -* @static -* @final -* @type String -*/ -YAHOO.widget.OverlayManager.CSS_FOCUSED = "focused"; - -YAHOO.widget.OverlayManager.prototype = { - /** - * The class's constructor function - * @property contructor - * @type Function - */ - constructor : YAHOO.widget.OverlayManager, - - /** - * The array of Overlays that are currently registered - * @property overlays - * @type YAHOO.widget.Overlay[] - */ - overlays : null, - - /** - * Initializes the default configuration of the OverlayManager - * @method initDefaultConfig - */ - initDefaultConfig : function() { - /** - * The collection of registered Overlays in use by the OverlayManager - * @config overlays - * @type YAHOO.widget.Overlay[] - * @default null - */ - this.cfg.addProperty("overlays", { suppressEvent:true } ); - - /** - * The default DOM event that should be used to focus an Overlay - * @config focusevent - * @type String - * @default "mousedown" - */ - this.cfg.addProperty("focusevent", { value:"mousedown" } ); - }, - - /** - * Initializes the OverlayManager - * @method init - * @param {YAHOO.widget.Overlay[]} overlays Optional. A collection of Overlays to register with the manager. - * @param {Object} userConfig The object literal representing the user configuration of the OverlayManager - */ - init : function(userConfig) { - /** - * The OverlayManager's Config object used for monitoring configuration properties. - * @property cfg - * @type YAHOO.util.Config - */ - this.cfg = new YAHOO.util.Config(this); - - this.initDefaultConfig(); - - if (userConfig) { - this.cfg.applyConfig(userConfig, true); - } - this.cfg.fireQueue(); - - /** - * The currently activated Overlay - * @property activeOverlay - * @private - * @type YAHOO.widget.Overlay - */ - var activeOverlay = null; - - /** - * Returns the currently focused Overlay - * @method getActive - * @return {YAHOO.widget.Overlay} The currently focused Overlay - */ - this.getActive = function() { - return activeOverlay; - }; - - /** - * Focuses the specified Overlay - * @method focus - * @param {YAHOO.widget.Overlay} overlay The Overlay to focus - * @param {String} overlay The id of the Overlay to focus - */ - this.focus = function(overlay) { - var o = this.find(overlay); - if (o) { - this.blurAll(); - activeOverlay = o; - YAHOO.util.Dom.addClass(activeOverlay.element, YAHOO.widget.OverlayManager.CSS_FOCUSED); - this.overlays.sort(this.compareZIndexDesc); - var topZIndex = YAHOO.util.Dom.getStyle(this.overlays[0].element, "zIndex"); - if (! isNaN(topZIndex) && this.overlays[0] != overlay) { - activeOverlay.cfg.setProperty("zIndex", (parseInt(topZIndex, 10) + 2)); - } - this.overlays.sort(this.compareZIndexDesc); - } - }; - - /** - * Removes the specified Overlay from the manager - * @method remove - * @param {YAHOO.widget.Overlay} overlay The Overlay to remove - * @param {String} overlay The id of the Overlay to remove - */ - this.remove = function(overlay) { - var o = this.find(overlay); - if (o) { - var originalZ = YAHOO.util.Dom.getStyle(o.element, "zIndex"); - o.cfg.setProperty("zIndex", -1000, true); - this.overlays.sort(this.compareZIndexDesc); - this.overlays = this.overlays.slice(0, this.overlays.length-1); - o.cfg.setProperty("zIndex", originalZ, true); - - o.cfg.setProperty("manager", null); - o.focusEvent = null; - o.blurEvent = null; - o.focus = null; - o.blur = null; - } - }; - - /** - * Removes focus from all registered Overlays in the manager - * @method blurAll - */ - this.blurAll = function() { - activeOverlay = null; - for (var o=0;o 0) { - return true; - } - } else { - return false; - } - }, - - /** - * Attempts to locate an Overlay by instance or ID. - * @method find - * @param {YAHOO.widget.Overlay} overlay An Overlay to locate within the manager - * @param {String} overlay An Overlay id to locate within the manager - * @return {YAHOO.widget.Overlay} The requested Overlay, if found, or null if it cannot be located. - */ - find : function(overlay) { - if (overlay instanceof YAHOO.widget.Overlay) { - for (var o=0;o zIndex2) { - return -1; - } else if (zIndex1 < zIndex2) { - return 1; - } else { - return 0; - } - }, - - /** - * Shows all Overlays in the manager. - * @method showAll - */ - showAll : function() { - for (var o=0;oOR -* @param {HTMLElement} el The element representing the Tooltip -* @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details. -*/ -YAHOO.widget.Tooltip = function(el, userConfig) { - YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig); -}; - -YAHOO.extend(YAHOO.widget.Tooltip, YAHOO.widget.Overlay); - -/** -* Constant representing the Tooltip CSS class -* @property YAHOO.widget.Tooltip.CSS_TOOLTIP -* @static -* @final -* @type String -*/ -YAHOO.widget.Tooltip.CSS_TOOLTIP = "tt"; - -/** -* The Tooltip initialization method. This method is automatically called by the constructor. A Tooltip is automatically rendered by the init method, and it also is set to be invisible by default, and constrained to viewport by default as well. -* @method init -* @param {String} el The element ID representing the Tooltip OR -* @param {HTMLElement} el The element representing the Tooltip -* @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Tooltip. See configuration documentation for more details. -*/ -YAHOO.widget.Tooltip.prototype.init = function(el, userConfig) { - if (document.readyState && document.readyState != "complete") { - var deferredInit = function() { - this.init(el, userConfig); - }; - YAHOO.util.Event.addListener(window, "load", deferredInit, this, true); - } else { - YAHOO.widget.Tooltip.superclass.init.call(this, el); - - this.beforeInitEvent.fire(YAHOO.widget.Tooltip); - - YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Tooltip.CSS_TOOLTIP); - - if (userConfig) { - this.cfg.applyConfig(userConfig, true); - } - - this.cfg.queueProperty("visible",false); - this.cfg.queueProperty("constraintoviewport",true); - - this.setBody(""); - this.render(this.cfg.getProperty("container")); - - this.initEvent.fire(YAHOO.widget.Tooltip); - } -}; - -/** -* Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg). -* @method initDefaultConfig -*/ -YAHOO.widget.Tooltip.prototype.initDefaultConfig = function() { - YAHOO.widget.Tooltip.superclass.initDefaultConfig.call(this); - - /** - * Specifies whether the Tooltip should be kept from overlapping its context element. - * @config preventoverlap - * @type Boolean - * @default true - */ - this.cfg.addProperty("preventoverlap", { value:true, validator:this.cfg.checkBoolean, supercedes:["x","y","xy"] } ); - - /** - * The number of milliseconds to wait before showing a Tooltip on mouseover. - * @config showdelay - * @type Number - * @default 200 - */ - this.cfg.addProperty("showdelay", { value:200, handler:this.configShowDelay, validator:this.cfg.checkNumber } ); - - /** - * The number of milliseconds to wait before automatically dismissing a Tooltip after the mouse has been resting on the context element. - * @config autodismissdelay - * @type Number - * @default 5000 - */ - this.cfg.addProperty("autodismissdelay", { value:5000, handler:this.configAutoDismissDelay, validator:this.cfg.checkNumber } ); - - /** - * The number of milliseconds to wait before hiding a Tooltip on mouseover. - * @config hidedelay - * @type Number - * @default 250 - */ - this.cfg.addProperty("hidedelay", { value:250, handler:this.configHideDelay, validator:this.cfg.checkNumber } ); - - /** - * Specifies the Tooltip's text. - * @config text - * @type String - * @default null - */ - this.cfg.addProperty("text", { handler:this.configText, suppressEvent:true } ); - - /** - * Specifies the container element that the Tooltip's markup should be rendered into. - * @config container - * @type HTMLElement/String - * @default document.body - */ - this.cfg.addProperty("container", { value:document.body, handler:this.configContainer } ); - - /** - * Specifies the element or elements that the Tooltip should be anchored to on mouseover. - * @config context - * @type HTMLElement[]/String[] - * @default null - */ - -}; - -// BEGIN BUILT-IN PROPERTY EVENT HANDLERS // - -/** -* The default event handler fired when the "text" property is changed. -* @method configText -* @param {String} type The CustomEvent type (usually the property name) -* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. -* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. -*/ -YAHOO.widget.Tooltip.prototype.configText = function(type, args, obj) { - var text = args[0]; - if (text) { - this.setBody(text); - } -}; - -/** -* The default event handler fired when the "container" property is changed. -* @method configContainer -* @param {String} type The CustomEvent type (usually the property name) -* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. -* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. -*/ -YAHOO.widget.Tooltip.prototype.configContainer = function(type, args, obj) { - var container = args[0]; - if (typeof container == 'string') { - this.cfg.setProperty("container", document.getElementById(container), true); - } -}; - -/** -* The default event handler fired when the "context" property is changed. -* @method configContext -* @param {String} type The CustomEvent type (usually the property name) -* @param {Object[]} args The CustomEvent arguments. For configuration handlers, args[0] will equal the newly applied value for the property. -* @param {Object} obj The scope object. For configuration handlers, this will usually equal the owner. -*/ -YAHOO.widget.Tooltip.prototype.configContext = function(type, args, obj) { - var context = args[0]; - if (context) { - - // Normalize parameter into an array - if (! (context instanceof Array)) { - if (typeof context == "string") { - this.cfg.setProperty("context", [document.getElementById(context)], true); - } else { // Assuming this is an element - this.cfg.setProperty("context", [context], true); - } - context = this.cfg.getProperty("context"); - } - - - // Remove any existing mouseover/mouseout listeners - if (this._context) { - for (var c=0;cOR -* @param {HTMLElement} el The element representing the Panel -* @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Panel. See configuration documentation for more details. -*/ -YAHOO.widget.Panel = function(el, userConfig) { - YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig); -}; - -YAHOO.extend(YAHOO.widget.Panel, YAHOO.widget.Overlay); - -/** -* Constant representing the default CSS class used for a Panel -* @property YAHOO.widget.Panel.CSS_PANEL -* @static -* @final -* @type String -*/ -YAHOO.widget.Panel.CSS_PANEL = "panel"; - -/** -* Constant representing the default CSS class used for a Panel's wrapping container -* @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER -* @static -* @final -* @type String -*/ -YAHOO.widget.Panel.CSS_PANEL_CONTAINER = "panel-container"; - -/** -* The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and sets up all DOM references for pre-existing markup, and creates required markup if it is not already present. -* @method init -* @param {String} el The element ID representing the Overlay OR -* @param {HTMLElement} el The element representing the Overlay -* @param {Object} userConfig The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details. -*/ -YAHOO.widget.Panel.prototype.init = function(el, userConfig) { - YAHOO.widget.Panel.superclass.init.call(this, el/*, userConfig*/); // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level - - this.beforeInitEvent.fire(YAHOO.widget.Panel); - - YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Panel.CSS_PANEL); - - this.buildWrapper(); - - if (userConfig) { - this.cfg.applyConfig(userConfig, true); - } - - this.beforeRenderEvent.subscribe(function() { - var draggable = this.cfg.getProperty("draggable"); - if (draggable) { - if (! this.header) { - this.setHeader(" "); - } - } - }, this, true); - - var me = this; - - var doBlur = function() { - this.blur(); - }; - - this.showMaskEvent.subscribe(function() { - var checkFocusable = function(el) { - if ((el.tagName == "A" || el.tagName == "BUTTON" || el.tagName == "SELECT" || el.tagName == "INPUT" || el.tagName == "TEXTAREA" || el.tagName == "FORM") && el.type != "hidden") { - if (! YAHOO.util.Dom.isAncestor(me.element, el)) { - YAHOO.util.Event.addListener(el, "focus", doBlur, el, true); - return true; - } - } else { - return false; - } - }; - - this.focusableElements = YAHOO.util.Dom.getElementsBy(checkFocusable); - }, this, true); - - this.hideMaskEvent.subscribe(function() { - for (var i=0;i